00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 # include "segmentqueue.h"
00088
00089 # ifdef rtlinux
00090 # include <linux/kernel.h>
00091 # else
00092 # include <stdio.h>
00093 # endif
00094
00095 #include <float.h>
00096
00097
00098
00099
00100
00101
00102
00103 #define SQ_SAFETY_MARGIN 10
00104
00105
00106
00107
00108
00109
00110 #define SQ_MAX_NUM_LINKED_SEGS 500
00111
00112 #define SQ_LOW_LINKING_PRIORITY 1
00113 #define SQ_HIGH_LINKING_PRIORITY 2
00114
00115 #define SQ_LINKING_NEEDED 2
00116 #define SQ_LINKING_NOT_NEEDED 1
00117
00118
00119 #if !defined(SQ_NO_DEBUG_PRINTING)
00120 # undef diagnostics
00121 # ifdef rtlinux
00122 # define diagnostics(fmt, args...) printk(KERN_CRIT fmt, ## args)
00123 # else
00124 # define diagnostics(fmt,args...) fprintf(stderr, fmt, ## args )
00125 # endif
00126 #else
00127 # define diagnostics(fmt, args...)
00128 #endif
00129
00130
00131 #define diagnosticsOff(fmt, args...)
00132
00133
00134 static EmcPose oldPos, oldVel, newVel, newAcc;
00135 static double oldDist;
00136
00137
00138
00139
00140 static double sqGiveLength(EmcPose p1, EmcPose p2)
00141 {
00142 PmCartesian disp;
00143 double mag;
00144
00145 pmCartCartSub(p1.tran, p2.tran, &disp);
00146 pmCartMag(disp, &mag);
00147
00148 return mag;
00149 };
00150
00151
00152 static double sqGiveCornerVelocity(SEGMENT *s1, SEGMENT *s2, double amax, \
00153 double cycleTime )
00154 {
00155
00156
00157
00158 PmCartesian v1;
00159 PmCartesian v2;
00160 PmCartesian me;
00161 PmCartesian diff;
00162 PmCartesian helix;
00163
00164 double maxdiff;
00165
00166 if ( s1 == 0 || s2 == 0 )
00167 {
00168 diagnostics("Error in sqGiveCornerVelocity()\n");
00169 return -1;
00170 }
00171
00172
00173 if ( s1->length == 0 || s2->length == 0 || amax==0 || cycleTime==0 )
00174 {
00175
00176 diagnostics("Error in sqGiveCornerVelocity()\n");
00177 return -1;
00178 }
00179
00180 if (s1->type == SQ_LINEAR)
00181 {
00182 v1=s1->line.uVec;
00183 }
00184 else
00185 {
00186 pmCartCartSub( s1->end.tran , s1->circle.center, &me );
00187 pmCartCartCross( s1->circle.normal, me, &v1 );
00188 pmCartScalDiv ( s1->circle.rHelix, s1->circle.angle, &helix);
00189 pmCartCartAdd ( v1, helix, &v1);
00190 pmCartNorm ( v1, &v1 );
00191
00192 }
00193
00194 if (s2->type == SQ_LINEAR)
00195 {
00196 v2=s2->line.uVec;
00197 }
00198 else
00199 {
00200 pmCartScalDiv ( s2->circle.rHelix, s2->circle.angle, &helix);
00201 pmCartCartAdd ( s2->circle.rPerp, helix, &v2);
00202 pmCartNorm ( v2, &v2 );
00203 }
00204
00205
00206 pmCartCartSub ( v2,v1, &diff );
00207
00208
00209 maxdiff = max ( fabs(diff.x), fabs(diff.y) );
00210 maxdiff = max ( maxdiff , fabs(diff.z) );
00211
00212
00213 if ( maxdiff <= 0 )
00214 return DBL_MAX;
00215 else
00216 return ( amax * cycleTime / maxdiff );
00217
00218 };
00219
00220 static double sqGiveMinAmaxTan(SEGMENT *s)
00221 {
00222
00223
00224 SEGMENT *cursor;
00225 double minAmax;
00226
00227 if (s == 0)
00228 {
00229 diagnostics("Error in sqGiveMinAmaxTan()\n");
00230 return -1;
00231 }
00232
00233 if ( s->numLinkedSegs == 0 )
00234 return s->amaxTan;
00235
00236 minAmax = s->amaxTan;
00237 cursor = s;
00238
00239 while (cursor->nextSegment!=0 && cursor->nextSegment->linkedToPrevSeg==1)
00240 {
00241 cursor = cursor->nextSegment;
00242 if (cursor->amaxTan < minAmax )
00243 {
00244 minAmax = cursor->amaxTan;
00245 }
00246 }
00247 return minAmax;
00248 }
00249
00250 static double sqGiveMaxInc(SEGMENTQUEUE *sq, SEGMENT *s)
00251
00252
00253 {
00254 int done=0;
00255 int minNumSteps;
00256 double startInc,finalInc;
00257 SEGMENT *cursor;
00258 double l;
00259 double maxAccTan;
00260
00261 if (sq == 0 || s == 0)
00262 {
00263 diagnostics("Error in sqGiveMaxInc()\n");
00264 return -1;
00265 }
00266
00267 if ( s->numLinkedSegs == 0 )
00268 return s->maxInc;
00269
00270 maxAccTan = sqGiveMinAmaxTan(s);
00271
00272 startInc=s->plInitInc;
00273 cursor=s;
00274 l=s->length;
00275 while (!done)
00276 {
00277 if ( cursor->nextSegment==0 )
00278 {
00279 return cursor->maxInc;
00280 }
00281 if ( cursor->nextSegment!=0 && cursor->nextSegment->maxInc < \
00282 cursor->maxInc)
00283 finalInc=min(cursor->finalInc,\
00284 cursor->nextSegment->maxInc*sq->feedOverrideFactor);
00285
00286 else
00287 finalInc=min(cursor->finalInc,\
00288 cursor->maxInc*sq->feedOverrideFactor);
00289 minNumSteps = ceil ( 3 *fabs(finalInc-startInc) / \
00290 ( 2 * maxAccTan * sq->ctPow2 ));
00291
00292 if ((minNumSteps+1)* (startInc+finalInc)/2 -startInc > \
00293 l - 5 * max(finalInc,startInc) )
00294 {
00295
00296
00297 cursor=cursor->nextSegment;
00298 l+=cursor->length;
00299 }
00300 else
00301 done=1;
00302 }
00303
00304 return cursor->maxInc;
00305 }
00306 int sqLinkCriterion(SEGMENTQUEUE *sq, SEGMENT *s, double feedOverride)
00307 {
00308
00309
00310
00311
00312
00313
00314 double amaxTan;
00315 double initInc, finalInc;
00316 int minNumSteps, i;
00317 SEGMENT *lastSeg;
00318
00319 if ( sq == 0 || s == 0 )
00320 {
00321 diagnostics("Error in sqLinkCriterion\n");
00322 return -1;
00323 }
00324
00325 if ( s->linkedToPrevSeg == 1 )
00326 {
00327 diagnostics("Segment s is linked to it's preceding segment in sqLinkCriterion\n");
00328 return -1;
00329 }
00330
00331
00332 lastSeg = s;
00333 for ( i=0 ; i<s->numLinkedSegs; i++)
00334 {
00335 lastSeg=lastSeg->nextSegment;
00336 if (lastSeg == 0 )
00337 {
00338 diagnostics("Panic: NULL pointer in sqLinkCriterion\n");
00339 return -1;
00340 }
00341 }
00342
00343
00344
00345
00346
00347 amaxTan = sqGiveMinAmaxTan(s);
00348
00349
00350
00351
00352 if ( 0 != s->plInitInc )
00353 initInc = s->plInitInc;
00354 else
00355 initInc = s->initInc;
00356
00357
00358
00359 if ( feedOverride >= 1.0)
00360 {
00361 finalInc=lastSeg->finalInc;
00362 }
00363 else
00364 {
00365 if ( lastSeg->nextSegment!=0 && lastSeg->nextSegment->maxInc < \
00366 lastSeg->maxInc)
00367 finalInc=min(lastSeg->finalInc,\
00368 lastSeg->nextSegment->maxInc*feedOverride);
00369 else
00370 finalInc=min(lastSeg->finalInc,\
00371 lastSeg->maxInc*feedOverride);
00372 }
00373 minNumSteps=ceil(3* fabs(initInc - finalInc ) / (2*amaxTan*sq->ctPow2));
00374 if ((minNumSteps+1)*(initInc + finalInc)/2 - initInc > \
00375 s->totLength - 2*initInc - finalInc - 5*max(initInc,finalInc) )
00376 {
00377 return SQ_LINKING_NEEDED;
00378 }
00379 else
00380 {
00381 return SQ_LINKING_NOT_NEEDED;
00382 }
00383 }
00384
00385 static int sqPlanSegment(SEGMENTQUEUE *sq, SEGMENT *s)
00386 {
00387
00388 double length;
00389 double maxInc;
00390 double amaxTan;
00391
00392 SEGMENT *cursor;
00393
00394 int validSolutionFound;
00395
00396 if (sq==0)
00397 {
00398 diagnostics("Error in sqPlanSegment()\n");
00399 return -1;
00400 }
00401
00402
00403
00404 if (s==0)
00405 {
00406 diagnostics("Error in sqPlanSegment()\n");
00407 return -1;
00408 }
00409
00410
00411
00412
00413 if ( s->linkedToPrevSeg == 1 )
00414 {
00415 diagnostics("Error in sqPlanSegment()\n");
00416 return -1;
00417 }
00418
00419
00420 length=s->length;
00421 cursor=s;
00422
00423
00424
00425 while (cursor->nextSegment!=0 && cursor->nextSegment->linkedToPrevSeg)
00426 {
00427 cursor = cursor->nextSegment;
00428 }
00429
00430 if ( SQ_LINKING_NEEDED == sqLinkCriterion(sq,s,1.0) )
00431 {
00432 diagnostics("Error in sqPlanSegment(), chain too short\n");
00433 if (s->initInc > cursor->finalInc )
00434 diagnostics("InitInc > finalInc \n");
00435 else
00436 diagnostics("InitInc < finalInc \n");
00437
00438 diagnostics("ID = %d\n", s->ID );
00439 diagnostics("Startpt: x=%d, y=%d, z=%d\n",(int)(1000.0*s->start.tran.x),(int)(1000.0*s->start.tran.y),(int)(1000.0*s->start.tran.z));
00440 }
00441
00442
00443 if (-1 == (maxInc=sqGiveMaxInc(sq,s)*sq->feedOverrideFactor))
00444 {
00445 diagnostics("Error in sqPlanSegment()\n");
00446 return -1;
00447 }
00448
00449
00450
00451 maxInc = min(maxInc, sq->maxV*sq->cycleTime);
00452
00453
00454
00455 amaxTan = sqGiveMinAmaxTan(s);
00456 diagnosticsOff("AmaxTan in sqplansegment = %d \n",(int)(ceil(amaxTan)));
00457
00458
00459
00460 if ( cursor->finalInc!=0)
00461 {
00462 if ( cursor->nextSegment->maxInc < cursor->maxInc)
00463 s->plFinalInc=min(cursor->finalInc,\
00464 cursor->nextSegment->maxInc*sq->feedOverrideFactor);
00465
00466 else
00467 s->plFinalInc=min(cursor->finalInc,maxInc);
00468
00469 cursor->nextSegment->plInitInc=s->plFinalInc;
00470 }
00471 else
00472 s->plFinalInc=0;
00473
00474
00475
00476 length = s->totLength - 2* s->plInitInc - s->plFinalInc;
00477
00478
00479
00480 if (s->plInitInc == maxInc)
00481 s->m=0;
00482 else
00483
00484 s->m=max(2,ceil ( 3*fabs(maxInc-s->plInitInc)/(2*amaxTan*sq->ctPow2)));
00485
00486
00487 if (s->plFinalInc == maxInc)
00488 s->q=0;
00489 else
00490 s->q=max(2,ceil(3*fabs(maxInc-s->plFinalInc)/(2*amaxTan*sq->ctPow2)));
00491
00492
00493 if (length - ((s->m+1)*(s->plInitInc+maxInc)/2 - s->plInitInc)*(s->m!=0) \
00494 - ((s->q+1)*(maxInc+s->plFinalInc)/2 - maxInc)*(s->q!=0) < 0 )
00495 {
00496
00497 s->p=3;
00498 validSolutionFound=0;
00499 if (s->ID==474) diagnostics("0: maxInc = %d, initInc = %d, finalInc = %d\n",(int)(100000.0*maxInc), (int)(100000.0*s->plInitInc),(int)(100000.0*s->plFinalInc));
00500 if ( maxInc > s->plInitInc && maxInc > s->plFinalInc )
00501 {
00502 maxInc = -s->p*amaxTan*sq->ctPow2/3 + sqrt ( 4*s->p*s->p*amaxTan*amaxTan*sq->ctPow2*sq->ctPow2 + 18*(s->plInitInc*s->plInitInc+s->plFinalInc*s->plFinalInc) + 12*amaxTan*sq->ctPow2*(s->plInitInc-s->plFinalInc+2*length))/6;
00503 diagnosticsOff("1: maxInc = %d\n",(int)(100000.0*maxInc));
00504 if ( maxInc > s->plInitInc && maxInc > s->plFinalInc )
00505 {
00506 validSolutionFound=1;
00507 }
00508 }
00509
00510 if ( (s->plInitInc >= maxInc && maxInc > s->plFinalInc) || !validSolutionFound )
00511 {
00512 maxInc = 3*((s->plFinalInc*s->plFinalInc - s->plInitInc*s->plInitInc) + 2*amaxTan*sq->ctPow2*(s->plInitInc-s->plFinalInc+2*length))/(4 * s->p * amaxTan * sq->ctPow2 );
00513 diagnosticsOff("2: maxInc = %d\n",(int)(100000.0*maxInc));
00514 if ( s->plInitInc >= maxInc && maxInc > s->plFinalInc )
00515 {
00516 validSolutionFound=1;
00517 }
00518 }
00519 if ( (s->plInitInc < maxInc && maxInc <= s->plFinalInc) || !validSolutionFound )
00520 {
00521 maxInc = ( 3*( s->plInitInc*s->plInitInc - s->plFinalInc*s->plFinalInc) + 2*amaxTan*sq->ctPow2*(s->plInitInc-s->plFinalInc+2*length))/(4 * s->p * amaxTan * sq->ctPow2 );
00522 diagnosticsOff("3: maxInc = %d\n",(int)(100000.0*maxInc));
00523 if ( s->plInitInc < maxInc && maxInc <= s->plFinalInc )
00524 {
00525 validSolutionFound=1;
00526 }
00527 }
00528 if ( ( maxInc <= s->plInitInc && maxInc <= s->plFinalInc) || !validSolutionFound )
00529 {
00530 maxInc = s->p*amaxTan*sq->ctPow2/3 + sqrt ( 4*s->p*s->p*amaxTan*amaxTan*sq->ctPow2*sq->ctPow2 + 18*(s->plInitInc*s->plInitInc+s->plFinalInc*s->plFinalInc) + 12*amaxTan*sq->ctPow2*(-s->plInitInc+s->plFinalInc-2*length))/6;
00531 diagnosticsOff("4: maxInc = %d\n",(int)(100000.0*maxInc));
00532 if ( maxInc <= s->plInitInc && maxInc <= s->plFinalInc )
00533 {
00534 validSolutionFound=1;
00535 }
00536 }
00537 if ( !validSolutionFound )
00538 {
00539 diagnostics("No solution found in sqPlanSegment\n");
00540 return -1;
00541 }
00542
00543
00544 s->m=ceil(3*fabs(maxInc-s->plInitInc)/(2*amaxTan*sq->ctPow2));
00545 s->q=ceil(3*fabs(maxInc-s->plFinalInc)/(2*amaxTan*sq->ctPow2));
00546 s->p=ceil((length-(s->m!=0)*((s->m+1)*(s->plInitInc+maxInc)/2-\
00547 s->plInitInc)-(s->q!=0)*((s->q+1)*(s->plFinalInc+maxInc)/2\
00548 -maxInc))/maxInc );
00549 }
00550 else
00551 s->p=ceil((length-(s->m!=0)*((s->m+1)*(s->plInitInc+maxInc)/2-\
00552 s->plInitInc)-(s->q!=0)*((s->q+1)*(s->plFinalInc+maxInc)/2\
00553 -maxInc))/maxInc );
00554
00555
00556 maxInc= (2*length-(s->m!=0)*(s->m-1)*s->plInitInc\
00557 -(s->q!=0)*(s->q+1)*s->plFinalInc) \
00558 / ( (s->m!=0)*(s->m+1) + 2 * s->p + (s->q!=0)*(s->q-1) );
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574 s->totNumPoints= s->m + s->p + s->q + 3;
00575 s->cruiseInc=maxInc;
00576
00577
00578
00579
00580 if (s->m!=0)
00581 {
00582 s->b1 = 3 * (maxInc-s->plInitInc ) / ( (s->m*s->m*sq->ctPow2) );
00583 s->a1 = -2 * s->b1 / ( 3 * s->m * sq->cycleTime) ;
00584 s->c1 = 0;
00585 s->d1 = s->plInitInc;
00586 }
00587
00588 else s->a1 = s->b1 = s->c1 = s->d1 = 0;
00589
00590 if (s->q!=0)
00591 {
00592 s->b3 = 3 * ( s->plFinalInc - maxInc ) / ( (s->q*s->q*sq->ctPow2) );
00593 s->a3 = -2 * s->b3 / ( 3 * s->q * sq->cycleTime) ;
00594 s->c3 = 0;
00595 s->d3 = maxInc;
00596 }
00597 else s->a3 = s->b3 = s->c3 = s->d3 = 0;
00598
00599 s->planningDone=1;
00600
00601 return 0;
00602 };
00603
00604
00605
00606 static int sqLinkSegments(SEGMENT *s1, SEGMENT *s2, int priority)
00607 {
00608 if (s1==0)
00609 {
00610 diagnostics("Error 1a in sqLinkSegments() \n");
00611 return -1;
00612 }
00613 if (s2==0)
00614 {
00615 diagnostics("Error 1b in sqLinkSegments() \n");
00616 return -1;
00617 }
00618
00619
00620
00621
00622
00623 if ( s1->nextSegment != s2 )
00624 {
00625 diagnostics("Error 2 in sqLinkSegments()\n");
00626 return -1;
00627 }
00628
00629
00630 if (s1->active == 1)
00631 {
00632
00633
00634 return 0;
00635 }
00636
00637
00638
00639 while (s1->linkedToPrevSeg)
00640 {
00641 if (s1==0)
00642 {
00643 diagnostics("Panic: NULL pointer in sqLinkSegments\n");
00644 return -1;
00645 }
00646 s1=s1->prevSegment;
00647 }
00648
00649 if ( s1->numLinkedSegs > SQ_MAX_NUM_LINKED_SEGS && priority==SQ_LOW_LINKING_PRIORITY)
00650 return 0;
00651
00652 s1->numLinkedSegs += s2->numLinkedSegs + 1;
00653 s1->totLength += s2->totLength;
00654 s2->linkedToPrevSeg = 1;
00655 s2->numLinkedSegs = 0;
00656
00657
00658
00659
00660
00661
00662 return 0;
00663 }
00664
00665 int sqForwardLinkSegment(SEGMENTQUEUE *sq, SEGMENT *s, double feedOverride)
00666 {
00667
00668
00669
00670
00671
00672 SEGMENT *cursor;
00673 int done, counter;
00674 int linkcrit;
00675
00676 if ( sq == 0 || s == 0 )
00677 {
00678 diagnostics("Error in sqForwardLinkSegment\n");
00679 return -1;
00680 }
00681
00682 if ( s->initInc > s->finalInc )
00683 {
00684 diagnostics("sqForwardlinkSegment called while initInc is larger than finalInc\n");
00685
00686 return 0;
00687 }
00688
00689 cursor=s;
00690 done=0;
00691 counter=0;
00692
00693 while (!done)
00694 {
00695 counter++;
00696 if ( counter > sq->size )
00697 {
00698
00699
00700 diagnostics("Can't get out of the loop in sqForwardLinkSegment\n");
00701 return -1;
00702 }
00703 if (cursor->nextSegment == 0 )
00704 {
00705
00706
00707
00708 done = 1;
00709 }
00710 else if (cursor->nextSegment->linkedToPrevSeg==1)
00711
00712 {
00713 cursor=cursor->nextSegment;
00714 if (cursor == 0 )
00715 {
00716
00717
00718 diagnostics("Panic: cursor = NULL in sqForwardLinkSegment\n");
00719 return -1;
00720 }
00721 }
00722 else if (s->initInc > cursor->finalInc )
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 done=1;
00734 else
00735 {
00736 if ( -1 == (linkcrit = sqLinkCriterion(sq,s,feedOverride)))
00737 {
00738 diagnostics("Error in sqForwardLinkSegment\n");
00739 return -1;
00740 }
00741 else if ( linkcrit == SQ_LINKING_NEEDED )
00742 {
00743 cursor=cursor->nextSegment;
00744 if (cursor == 0 )
00745 {
00746
00747 diagnostics("Panic: cursor = NULL in sqForwardLinkSegment\n");
00748 return -1;
00749 }
00750 if (-1 == sqLinkSegments(cursor->prevSegment,cursor,SQ_HIGH_LINKING_PRIORITY))
00751 {
00752 diagnostics("Error in sqForwardLinkSegment\n");
00753 return -1;
00754 }
00755 }
00756 else
00757
00758 done=1;
00759 }
00760 if ( cursor == sq->queue + sq->end )
00761 {
00762
00763
00764
00765 diagnostics("End of queue reached, no further linking possible\n");
00766 done =1;
00767 }
00768 }
00769 return 0;
00770 }
00771
00772 int sqBackwardLinkSegment(SEGMENTQUEUE *sq, SEGMENT *s, double feedOverride)
00773 {
00774
00775
00776
00777
00778
00779 SEGMENT *cursor;
00780 int done, counter;
00781 int linkcrit;
00782
00783 if ( sq == 0 || s == 0 )
00784 {
00785 diagnostics("Error in sqBackwardLinkSegment\n");
00786 return -1;
00787 }
00788
00789 if ( s->initInc < s->finalInc )
00790 {
00791 diagnostics("sqBackwardlinkSegment called while initInc is smaller than finalInc\n");
00792
00793 return 0;
00794 }
00795
00796 cursor=s;
00797 done=0;
00798 counter=0;
00799
00800 while (!done)
00801 {
00802 counter++;
00803 if ( counter > sq->size )
00804 {
00805
00806
00807 diagnostics("Can't get out of the loop in sqBackwardLinkSegment\n");
00808 return -1;
00809 }
00810
00811 if (cursor->linkedToPrevSeg==1)
00812
00813 {
00814 cursor=cursor->prevSegment;
00815 if (cursor == 0 )
00816 {
00817 diagnostics("Panic: cursor = NULL in sqBackwardLinkSegment\n");
00818 return -1;
00819 }
00820 }
00821 else if (cursor->initInc < s->finalInc )
00822
00823
00824
00825
00826
00827
00828
00829 done=1;
00830
00831 else
00832 {
00833 if ( -1 == (linkcrit = sqLinkCriterion(sq,cursor,feedOverride)))
00834 {
00835 diagnostics("Error in sqBackWardLinkSegment\n");
00836 return -1;
00837 }
00838 else if ( linkcrit == SQ_LINKING_NEEDED )
00839 {
00840 cursor=cursor->prevSegment;
00841 if (cursor == 0 )
00842 {
00843 diagnostics("Panic: cursor = NULL in sqBackwardLinkSegment\n");
00844 return -1;
00845 }
00846 if (-1 == sqLinkSegments(cursor,cursor->nextSegment,SQ_HIGH_LINKING_PRIORITY))
00847 {
00848 diagnostics("Error in sqBackwardLinkSegment\n");
00849 return -1;
00850 }
00851 }
00852 else
00853 done=1;
00854 }
00855 if ( cursor == sq->queue + sq->start )
00856 {
00857 diagnostics("Beginning of queue reached, no further linking possible\n");
00858 done =1;
00859 }
00860 }
00861 return 0;
00862 }
00863
00864 int sqPreprocessSegment(SEGMENTQUEUE *sq, SEGMENT *newseg)
00865 {
00866
00867
00868
00869
00870
00871
00872 double cornerInc;
00873
00874 SEGMENT *prevseg;
00875 SEGMENT * cursor;
00876
00877
00878 if ( sq == 0 || sq->queue == 0 || newseg == 0 )
00879 {
00880 diagnostics("Error 1 in sqPreprocessSegment()\n");
00881 return -1;
00882 }
00883
00884
00885
00886 if ( sq->numSegments == 1 )
00887 {
00888 newseg->initInc=0;
00889 newseg->start=sq->lastPoint;
00890 newseg->prevSegment=0;
00891 if (sq->paused != 1 && sq->stepping != 1 )
00892 sq->done=0;
00893 }
00894
00895 else
00896 {
00897 prevseg = sq->queue + ( ( sq->end+sq->size-2) % sq->size );
00898 newseg->start = prevseg->end;
00899 prevseg->nextSegment=newseg;
00900 newseg->prevSegment=prevseg;
00901
00902 if ( prevseg->active == 1 )
00903
00904 {
00905 newseg->initInc=prevseg->finalInc;
00906 }
00907 else
00908 {
00909
00910
00911
00912
00913 if ( -1 == (cornerInc = sqGiveCornerVelocity( prevseg, newseg ,\
00914 sq->maxAcc,sq->cycleTime) * sq->cycleTime ))
00915 {
00916 diagnostics("Error 2 in sqPreprocessSegment()\n");
00917 return -1;
00918 }
00919
00920
00921
00922
00923
00924
00925 if ( (prevseg->maxInc == newseg->maxInc ) && \
00926 (cornerInc > newseg->maxInc) )
00927 {
00928 if (-1 == sqLinkSegments(prevseg,newseg,SQ_LOW_LINKING_PRIORITY))
00929 {
00930 diagnostics("Error 3 in sqPreprocessSegment()\n");
00931 return -1;
00932 }
00933 cornerInc = prevseg->maxInc;
00934 newseg->initInc = cornerInc;
00935 prevseg->finalInc = cornerInc;
00936 }
00937
00938 else
00939 {
00940
00941
00942
00943 if ( (cornerInc>prevseg->maxInc) || (cornerInc>newseg->maxInc) )
00944 cornerInc = min( prevseg->maxInc, newseg->maxInc );
00945
00946 newseg->initInc = cornerInc;
00947 prevseg->finalInc = cornerInc;
00948
00949
00950
00951 cursor=prevseg;
00952
00953
00954
00955
00956 if (prevseg->linkedToPrevSeg == 1)
00957 {
00958 while (cursor->linkedToPrevSeg )
00959 {
00960 cursor=cursor->prevSegment;
00961 if (cursor == 0 )
00962 {
00963 diagnostics("Panic: cursor = NULL in sqPreprocessSegment\n");
00964 return -1;
00965 }
00966 }
00967 }
00968 if (cursor->initInc < cornerInc)
00969 {
00970
00971
00972
00973
00974
00975 if ( -1 == sqForwardLinkSegment(sq,cursor,sq->maxFeedOverrideFactor) )
00976 {
00977 diagnostics("Error 4 in sqPreprocessSegment()\n");
00978 return -1;
00979 }
00980 }
00981 else
00982
00983
00984
00985
00986 {
00987 if ( -1 == sqBackwardLinkSegment(sq,prevseg,sq->maxFeedOverrideFactor) )
00988 {
00989 diagnostics("Error 5 in sqPreprocessSegment()\n");
00990 return -1;
00991 }
00992 }
00993 }
00994 }
00995 }
00996
00997 return 0;
00998 }
00999
01000
01001
01002
01003 int sqInitQueue(SEGMENTQUEUE *sq, SEGMENT *first, int size)
01004 {
01005 if (size <= 0 || sq == 0 || first == 0 )
01006 {
01007 diagnostics("Error in sqInitQueue()\n");
01008 return -1;
01009 }
01010
01011 sq->queue = first;
01012
01013
01014
01015
01016 sq->size = 2000;
01017
01018 sq->start = sq->end = 0;
01019 sq->full = 0;
01020 sq->numSegments=0;
01021
01022 sq->initXYZ.tran.x=0;
01023 sq->initXYZ.tran.y=0;
01024 sq->initXYZ.tran.z=0;
01025 sq->lastPoint=sq->initXYZ;
01026 sq->n=0;
01027 sq->maxFeedOverrideFactor = 1.0;
01028
01029 sq->feedOverrideFactor=1.0;
01030 sq->cycleTime=0;
01031 sq->maxAcc=0;
01032 sq->maxV=0;
01033 sq->currentID=0;
01034
01035 sq->done=1;
01036 sq->paused=0;
01037 sq->stepping=0;
01038 sq->feedAdjusting=0;
01039 sq->aborting=0;
01040
01041
01042
01043 oldPos = sq->lastPoint;
01044 oldVel.tran.x=0;
01045 oldVel.tran.y=0;
01046 oldVel.tran.z=0;
01047 oldDist = 0;
01048 return 0;
01049 };
01050
01051 int sqSetMaxAcc(SEGMENTQUEUE *sq, double amax)
01052 {
01053 if (sq==0 || amax <=0 )
01054 {
01055 diagnostics("Error in SetMaxAcc!!!\n");
01056 return -1;
01057 }
01058 sq->maxAcc=amax/2;
01059 return 0;
01060 };
01061
01062 int sqSetVmax(SEGMENTQUEUE *sq, double vmax)
01063 {
01064 if (sq==0 || vmax <= 0 )
01065 {
01066 diagnostics("Error in SetVmax!!!\n");
01067 return -1;
01068 }
01069 sq->maxV=vmax;
01070 return 0;
01071 };
01072
01073 int sqSetCycleTime(SEGMENTQUEUE *sq, double secs)
01074 {
01075 if (sq==0 || secs==0 )
01076 {
01077 diagnostics("Cycletime is zero!!!\n");
01078 return -1;
01079 }
01080 sq->cycleTime=secs;
01081 sq->ctPow2=secs *secs;
01082 sq->ctPow3=sq->ctPow2 * secs;
01083 return 0;
01084 };
01085
01086 int sqSetMaxFeedOverride(SEGMENTQUEUE *sq, double mfo)
01087 {
01088 if (sq==0 || mfo<=0 )
01089 {
01090 diagnostics("Error in sqSetMaxFeedOverride()\n");
01091 return -1;
01092 }
01093 sq->maxFeedOverrideFactor = mfo;
01094 return 0;
01095 }
01096
01097
01098 int sqSetPos(SEGMENTQUEUE *sq, EmcPose pos)
01099 {
01100 if (sq==0)
01101 {
01102 diagnostics("Error in sqSetPos()\n");
01103 return -1;
01104 }
01105 sq->initXYZ=pos;
01106 sq->lastPoint=sq->initXYZ;
01107 return 0;
01108 }
01109
01110 int sqClearQueue(SEGMENTQUEUE *sq)
01111 {
01112 if (sq==0)
01113 {
01114 diagnostics("Error in sqClearQueue(): sq == 0 \n");
01115 return -1;
01116 }
01117 sq->numSegments=0;
01118 sq->start = sq->end = 0;
01119 sq->full = 0;
01120 sq->n=0;
01121 sq->feedOverrideFactor=1.0;
01122 sq->currentID=0;
01123
01124 sq->done=1;
01125 sq->paused=0;
01126 sq->stepping=0;
01127 sq->feedAdjusting=0;
01128 sq->aborting=0;
01129
01130 sq->currentVel=0;
01131 oldDist=0;
01132 oldPos = sq->lastPoint;
01133 oldVel.tran.x=0;
01134 oldVel.tran.y=0;
01135 oldVel.tran.z=0;
01136
01137 return 0;
01138 }
01139
01140 int sqTrashQueue(SEGMENTQUEUE *sq)
01141 {
01142 if ( sq == 0 || sq->queue == 0 )
01143 {
01144 diagnostics("Error in sqTrashQueue()\n");
01145 return -1;
01146 }
01147 sqClearQueue(sq);
01148 sq->queue=0;
01149 return 0;
01150 };
01151
01152
01153 int sqSetFeed(SEGMENTQUEUE *sq, double feed)
01154 {
01155 if (sq==0 || feed<=0)
01156 {
01157 diagnostics("Error in sqSetFeed()\n");
01158 return -1;
01159 }
01160
01161 if (feed > sq->maxV)
01162 sq->feed = sq->maxV;
01163 else
01164 sq->feed=feed;
01165 return 0;
01166 }
01167
01168 int sqAddLine(SEGMENTQUEUE *sq, EmcPose end, int ID)
01169 {
01170 double length, maxUVec;
01171 SEGMENT *newseg;
01172 EmcPose start;
01173
01174
01175
01176 if ( sq == 0 || sq->queue == 0 )
01177 {
01178 diagnostics("Error in sqAddLine()\n");
01179 return -1;
01180 }
01181
01182
01183 if ( sq->numSegments == sq->size )
01184 {
01185 diagnostics("Panic!!!!, segmentqueue overflows!!!\n");
01186 return -1;
01187 }
01188
01189
01190 if ( sq->numSegments==0 )
01191 start=sq->lastPoint;
01192 else
01193 start=sq->queue[(sq->end+sq->size-1)%sq->size].end;
01194
01195 length = sqGiveLength(start,end);
01196
01197 if (length==0)
01198 {
01199
01200 sq->lastAppMotionID=ID;
01201 return 0;
01202 }
01203
01204
01205 newseg= sq->queue+sq->end;
01206
01207 sq->end = (sq->end+1) % sq->size;
01208 sq->numSegments++;
01209 if ( sq->numSegments >= sq->size - SQ_SAFETY_MARGIN )
01210 {
01211 sq->full=1;
01212 }
01213
01214
01215 newseg->ID = ID;
01216 newseg->type = SQ_LINEAR;
01217 newseg->length = length;
01218 newseg->totLength = length;
01219 newseg->start = start;
01220 newseg->end = end;
01221 newseg->maxInc = sq->feed*sq->cycleTime;
01222 newseg->finalInc = 0;
01223 newseg->plInitInc = 0;
01224 newseg->plFinalInc = 0;
01225 newseg->cruiseInc = 0;
01226 newseg->planningDone = 0;
01227 newseg->active = 0;
01228 newseg->numLinkedSegs = 0;
01229 newseg->linkedToPrevSeg= 0;
01230 newseg->totNumPoints = 0;
01231 newseg->nextSegment = 0;
01232
01233
01234 pmLineInit( &newseg->line, newseg->start, newseg->end);
01235
01236
01237 maxUVec = max ( fabs(newseg->line.uVec.x) , fabs(newseg->line.uVec.y) );
01238 maxUVec = max ( fabs(newseg->line.uVec.z) , maxUVec );
01239 newseg->amaxTan = sq->maxAcc/maxUVec;
01240
01241 diagnosticsOff("Amax tan = %d\n",(int)newseg->amaxTan);
01242
01243 if (-1 == sqPreprocessSegment(sq, newseg))
01244 {
01245 diagnostics("Error in sqAddLine()\n");
01246 return -1;
01247 }
01248
01249
01250 sq->lastAppMotionID=ID;
01251
01252 return 0;
01253 }
01254
01255 int sqAddCircle(SEGMENTQUEUE *sq, EmcPose end, PmCartesian center, \
01256 PmCartesian normal, int turn, int ID)
01257 {
01258 SEGMENT * newseg;
01259 PmCircle circle;
01260 EmcPose start;
01261 PmCartesian helix;
01262 double absHelix;
01263
01264
01265 double rpow2,A,topIncPow2;
01266
01267
01268 if ( sq == 0 || sq->queue == 0 )
01269 {
01270 diagnostics("Error in sqAddCircle()\n");
01271 return -1;
01272 }
01273
01274
01275 if ( sq->numSegments == sq->size )
01276 {
01277 diagnostics("Panic!!!!, segmentqueue overflows!!!\n");
01278 return -1;
01279 }
01280
01281 if ( sq->numSegments==0 )
01282 start=sq->lastPoint;
01283 else
01284 start=sq->queue[(sq->end+sq->size-1)%sq->size].end;
01285
01286 pmCircleInit(&circle, start, end, center, normal, turn);
01287
01288 if (circle.angle==0)
01289 {
01290
01291 sq->lastAppMotionID=ID;
01292 return 0;
01293 }
01294
01295
01296 pmCartScalDiv( circle.rHelix, circle.angle, &helix );
01297 pmCartMag( helix, &absHelix);
01298
01299
01300 newseg= sq->queue+sq->end;
01301
01302 sq->end = (sq->end+1) % sq->size;
01303 sq->numSegments++;
01304 if ( sq->numSegments >= sq->size - SQ_SAFETY_MARGIN )
01305 {
01306 sq->full=1;
01307 }
01308
01309
01310 newseg->ID = ID;
01311 newseg->type = SQ_CIRCULAR;
01312 newseg->circle = circle;
01313
01314 newseg->helixRadius = sqrt(circle.radius*circle.radius\
01315 + absHelix*absHelix);
01316 newseg->length = circle.angle * newseg->helixRadius;
01317
01318 newseg->totLength = newseg->length;
01319 newseg->start = start;
01320 newseg->end = end;
01321 newseg->maxInc = min (sq->feed*sq->cycleTime, sqrt( sq->maxAcc * \
01322 circle.radius ) * sq->cycleTime );
01323 if ( absHelix != 0 )
01324 newseg->maxInc = min ( newseg->maxInc, sq->feed * sq->cycleTime / absHelix );
01325
01326 newseg->finalInc = 0;
01327 newseg->plInitInc = 0;
01328 newseg->plFinalInc = 0;
01329 newseg->cruiseInc = 0;
01330 newseg->planningDone = 0;
01331 newseg->active = 0;
01332 newseg->numLinkedSegs = 0;
01333 newseg->linkedToPrevSeg= 0;
01334 newseg->totNumPoints = 0;
01335 newseg->nextSegment = 0;
01336
01337
01338 rpow2 = circle.radius*circle.radius;
01339 topIncPow2 = newseg->maxInc * newseg->maxInc;
01340 A = max (sq->maxAcc*sq->maxAcc*sq->ctPow2*sq->ctPow2*rpow2 \
01341 - topIncPow2*topIncPow2 ,\
01342 3.0/4.0 * topIncPow2*topIncPow2 );
01343
01344 newseg->amaxTan = sqrt( A / ( rpow2 * (rpow2* + topIncPow2 )))/sq->ctPow2;
01345
01346 if ( absHelix != 0 )
01347 {
01348 newseg->amaxTan= min (newseg->amaxTan, \
01349 sq->maxAcc*newseg->helixRadius/absHelix );
01350 }
01351
01352 if (-1 == sqPreprocessSegment(sq, newseg))
01353 {
01354 diagnostics("Error in sqAddCircle()\n");
01355 return -1;
01356 }
01357
01358
01359 sq->lastAppMotionID=ID;
01360
01361 return 0;
01362 }
01363
01364 int sqGetPosition(SEGMENTQUEUE *sq, EmcPose *p)
01365 {
01366 if ( (sq == 0) || (p == 0) )
01367 {
01368 diagnostics("Error in sqGetPosition()\n");
01369 return -1;
01370 }
01371
01372 *p = sq->lastPoint;
01373 return 0;
01374 };
01375
01376 int sqRunCycle(SEGMENTQUEUE *sq)
01377 {
01378 SEGMENT *as;
01379
01380 int i;
01381 SEGMENT *cursor;
01382 double finalInc;
01383 int done;
01384 int minNumSteps;
01385 double angleToGo;
01386 double amaxTan;
01387 int turn;
01388 PmCartesian normal, center;
01389
01390 int npow1, npow2, npow3;
01391
01392 if (sq==0 )
01393 {
01394 diagnostics("Error in sqRunCycle(): Segmentqueue doesn't exist!\n");
01395 return -1;
01396 }
01397
01398 if ( sq->full == 1 && sq->numSegments < sq->size - SQ_SAFETY_MARGIN )
01399 diagnostics("sq->full == 1 although queue's not full!!!!\n");
01400
01401 if ( sq->done==1 )
01402 {
01403
01404 return 0;
01405 }
01406
01407 if ( sq->numSegments==0 )
01408 {
01409
01410 sq->done=1;
01411
01412
01413
01414
01415 if (sq->currentID != sq->lastAppMotionID )
01416 sq->currentID= sq->lastAppMotionID;
01417 return 0;
01418 }
01419 as=sq->queue+sq->start;
01420 if (as == 0 )
01421 {
01422 diagnostics("Panic: as = NULL in sqRunCycle\n");
01423 return -1;
01424 }
01425
01426 if (as->active==0)
01427
01428 {
01429 if (-1 == sqPlanSegment(sq, as))
01430 {
01431 diagnostics("Error in sqRunCycle\n");
01432 return -1;
01433 }
01434
01435 cursor=as;
01436 for (i=0;i<=as->numLinkedSegs;i++)
01437 {
01438 if (cursor == 0 )
01439 {
01440 diagnostics("Panic: cursor = NULL in sqRunCycle\n");
01441 return -1;
01442 }
01443 cursor->active=1;
01444 cursor=cursor->nextSegment;
01445 }
01446 oldDist=0;
01447 sq->dist=0;
01448
01449
01450 sq->base = as->start;
01451 sq->cursor=as;
01452 sq->offset=0;
01453 sq->cumLength=as->length;
01454 sq->n=1;
01455 sq->currentID=as->ID;
01456
01457 }
01458
01459
01460
01461
01462
01463
01464 if ( sq->n==1 || sq->n==2 )
01465 {
01466 sq->dist += as->plInitInc;
01467 }
01468 else if ( sq->n <= as->m +2 )
01469
01470 {
01471 npow1 = sq->n - 2;
01472 npow2 = npow1 * npow1;
01473 npow3 = npow2 * npow1;
01474 sq->dist += as->a1 * npow3 *sq->ctPow3 \
01475 + as->b1 * npow2 * sq->ctPow2 \
01476 + as->c1 * npow1 * sq->cycleTime \
01477 + as->d1;
01478 }
01479 else if ( sq->n <= as->m + as->p + 2 )
01480
01481 {
01482 sq->dist += as->cruiseInc;
01483 }
01484 else if ( sq->n <= as->m + as->p + as->q +2 )
01485
01486 {
01487 npow1 = sq->n - as->m - as->p - 2;
01488 npow2 = npow1 * npow1;
01489 npow3 = npow2 * npow1;
01490 sq->dist += as->a3 * npow3 *sq->ctPow3 \
01491 + as->b3 * npow2 * sq->ctPow2 \
01492 + as->c3 * npow1 * sq->cycleTime \
01493 + as->d3;
01494
01495 }
01496 else if ( sq->n == as->m + as->p + as->q + 3 )
01497
01498 {
01499 sq->dist+= as->plFinalInc;
01500 }
01501 else
01502
01503 {
01504 diagnostics("Error in sqRunCycle\n");
01505 return -1;
01506 }
01507
01508
01509 if (as->nextSegment !=0 && ( as->nextSegment->linkedToPrevSeg ==1 ||
01510 sq->paused == 1))
01511
01512
01513
01514
01515 {
01516 while ( (sq->dist > sq->cumLength)
01517 && ( sq->cursor->nextSegment!=0 )
01518 && ( (sq->cursor->nextSegment->linkedToPrevSeg==1 ) ||
01519 sq->paused==1 ) )
01520 {
01521 sq->offset = sq->cumLength;
01522 sq->base = sq->cursor->end;
01523 sq->cursor = sq->cursor->nextSegment;
01524 sq->cumLength += sq->cursor->length;
01525
01526 }
01527
01528 sq->currentID=sq->cursor->ID;
01529
01530 if ( sq->cursor->type == SQ_LINEAR )
01531 pmLinePoint( &sq->cursor->line, sq->dist - sq->offset, &sq->lastPoint);
01532 else
01533 pmCirclePoint( &sq->cursor->circle, \
01534 (sq->dist - sq->offset)/sq->cursor->helixRadius,\
01535 &sq->lastPoint );
01536 }
01537
01538 else
01539
01540
01541 {
01542 if ( sq->cursor->type == SQ_LINEAR )
01543 pmLinePoint(&as->line, sq->dist, &sq->lastPoint);
01544 else
01545 pmCirclePoint(&as->circle, sq->dist/as->helixRadius, &sq->lastPoint);
01546 }
01547
01548 sq->n++;
01549
01550 if (sq->n > as->totNumPoints )
01551 {
01552 if (sq->aborting == 1)
01553 {
01554 if (-1 == sqClearQueue(sq))
01555 {
01556 diagnostics("Error in sqRunCycle\n");
01557 return -1;
01558 }
01559 }
01560
01561 else if (sq->paused == 1 || sq->feedAdjusting == 1)
01562 {
01563
01564 if (sq->paused==1)
01565 {
01566 sq->done=1;
01567 finalInc=0;
01568 }
01569 else
01570 {
01571 sq->feedAdjusting=0;
01572 finalInc=as->plFinalInc;
01573 }
01574
01575
01576 cursor=as;
01577 while ( cursor!=sq->cursor )
01578 {
01579 cursor=cursor->nextSegment;
01580 if (cursor == 0 )
01581 {
01582 diagnostics("Panic: cursor = NULL in sqRunCycle\n");
01583 return -1;
01584 }
01585 sq->numSegments--;
01586 }
01587 if ( sq->numSegments < sq->size - SQ_SAFETY_MARGIN )
01588 sq->full = 0;
01589 if ( sq->numSegments < 0 )
01590 {
01591 diagnostics("Panic: sq->numSegments <0 in sqRunCycle\n");
01592 return -1;
01593 }
01594
01595 cursor->prevSegment=0;
01596 cursor->linkedToPrevSeg=0;
01597 sq->start= sq->cursor - sq->queue;
01598 as=cursor;
01599
01600 as->planningDone=0;
01601 as->plInitInc=finalInc;
01602 as->start=sq->lastPoint;
01603
01604 if ( as->type == SQ_LINEAR)
01605 {
01606 as->length=sqGiveLength(as->start,as->end);
01607 as->totLength=as->length;
01608 pmLineInit(&as->line,as->start,as->end);
01609 }
01610 else
01611 {
01612 angleToGo= as->circle.angle-\
01613 (sq->dist-sq->offset)/as->helixRadius;
01614 turn = floor(angleToGo / ( 2 * PM_PI ));
01615 normal = as->circle.normal;
01616 center = as->circle.center;
01617 pmCircleInit( &as->circle, as->start, as->end, \
01618 center, normal, turn);
01619 as->length=as->circle.angle* as->helixRadius;
01620 as->totLength= as->length;
01621 }
01622
01623
01624 as->active=0;
01625
01626
01627
01628 as->numLinkedSegs=0;
01629 while (cursor->nextSegment!=0 &&
01630 cursor->nextSegment->linkedToPrevSeg==1 )
01631 {
01632 cursor=cursor->nextSegment;
01633 as->numLinkedSegs++;
01634 as->totLength+=cursor->length;
01635 }
01636
01637 amaxTan=sqGiveMinAmaxTan(as);
01638
01639 done=0;
01640
01641 while (!done)
01642 {
01643 if ( cursor->nextSegment!=0 && cursor->nextSegment->maxInc < \
01644 cursor->maxInc)
01645 finalInc=min(cursor->finalInc,\
01646 cursor->nextSegment->maxInc*sq->feedOverrideFactor);
01647
01648 else
01649 finalInc=min(cursor->finalInc,\
01650 cursor->maxInc*sq->feedOverrideFactor);
01651
01652 amaxTan= min(amaxTan, cursor->amaxTan);
01653 minNumSteps = ceil ( 3 * fabs(finalInc-as->plInitInc) / \
01654 ( 2 * amaxTan * sq->ctPow2 ));
01655 if ((minNumSteps+1)* (as->plInitInc+finalInc)/2-as->plInitInc >\
01656 as->totLength - 5 * max(as->plInitInc,finalInc ))
01657
01658 {
01659 if (-1 ==sqLinkSegments(cursor,cursor->nextSegment,SQ_HIGH_LINKING_PRIORITY))
01660 {
01661 diagnostics("Error in sqRunCycle\n");
01662 return -1;
01663 }
01664 cursor=cursor->nextSegment;
01665 if (cursor == 0 )
01666 {
01667 diagnostics("Panic: cursor = NULL in sqRunCycle\n");
01668 return -1;
01669 }
01670
01671 }
01672 else
01673 done=1;
01674 }
01675
01676 }
01677 else if ( sq->stepping == 1)
01678
01679
01680 {
01681 sq->numSegments--;
01682 sq->start = (sq->start + 1 ) % sq->size;
01683 if ( sq->numSegments < sq->size - SQ_SAFETY_MARGIN )
01684 sq->full = 0;
01685 if ( sq->numSegments < 0 )
01686 {
01687 diagnostics("Panic: sq->numSegments < 0 in sqRunCycle\n");
01688 return -1;
01689 }
01690
01691 as= sq->queue+sq->start;
01692 as->plInitInc=0;
01693 as->active=0;
01694 sq->done=1;
01695 }
01696
01697 else
01698 {
01699
01700 sq->numSegments -= 1 + as->numLinkedSegs;
01701 sq->start = ( sq->start + as->numLinkedSegs + 1 ) % sq->size;
01702 if ( sq->numSegments < sq->size - SQ_SAFETY_MARGIN )
01703 sq->full = 0;
01704 if ( sq->numSegments < 0 )
01705 {
01706 diagnostics("Panic: sq->numSegments <0 in sqRunCycle\n");
01707 return -1;
01708 }
01709
01710 }
01711 }
01712
01713
01714
01715 oldVel=newVel;
01716 newVel.tran.x= sq->lastPoint.tran.x - oldPos.tran.x;
01717 newVel.tran.y= sq->lastPoint.tran.y - oldPos.tran.y;
01718 newVel.tran.z= sq->lastPoint.tran.z - oldPos.tran.z;
01719
01720 oldPos=sq->lastPoint;
01721
01722 newAcc.tran.x= newVel.tran.x - oldVel.tran.x;
01723 newAcc.tran.y= newVel.tran.y - oldVel.tran.y;
01724 newAcc.tran.z= newVel.tran.z - oldVel.tran.z;
01725
01726 if (fabs(newAcc.tran.x) > sq->maxAcc*sq->ctPow2 || \
01727 fabs(newAcc.tran.y) > sq->maxAcc*sq->ctPow2 || \
01728 fabs(newAcc.tran.z) > sq->maxAcc*sq->ctPow2 )
01729 {
01730 diagnosticsOff("MaxAcc limited violated on motion %d\n",sq->currentID);
01731 diagnosticsOff("ddx=%d ddy=%d ddz=%d\n",(int)(newAcc.tran.x*1000000.0),(int)(newAcc.tran.y*1000000.0),(int)(newAcc.tran.z*1000000.0 ));
01732 }
01733
01734 sq->currentVel = sq->dist - oldDist;
01735 oldDist = sq->dist;
01736
01737 return 0;
01738 }
01739
01740
01741 int sqSetFeedOverride(SEGMENTQUEUE *sq, double fo)
01742 {
01743
01744 SEGMENT *as, *cursor;
01745 double startInc,finalInc,startAcc=0;
01746 double prevInc;
01747 int npow1,npow2,npow3;
01748 double angleToGo;
01749 int turn;
01750 PmCartesian normal, center;
01751
01752 if ( sq==0 || sq->queue==0 )
01753 {
01754 diagnostics("Error in sqSetFeedOverride\n");
01755 return -1;
01756 }
01757
01758
01759 if ( fo < 0 )
01760 fo=0;
01761 else if ( fo > sq->maxFeedOverrideFactor )
01762 fo=sq->maxFeedOverrideFactor;
01763
01764 if ( sq->feedOverrideFactor==fo )
01765
01766 return 0;
01767
01768 if ( fo == 0 )
01769 {
01770
01771 if ( -1 == sqPause(sq) )
01772 {
01773 diagnostics("Error in sqSetFeedOverride\n");
01774 return -1;
01775 }
01776 else
01777 {
01778 sq->feedOverrideFactor=0;
01779 return 0;
01780 }
01781 }
01782
01783 if ( sq->numSegments==0 )
01784 {
01785
01786 sq->feedOverrideFactor=fo;
01787 return 0;
01788 }
01789
01790 as=sq->queue+sq->start;
01791
01792 if ( sq->paused==1 )
01793 {
01794 if ( sq->feedOverrideFactor == 0 )
01795 {
01796
01797
01798
01799 sq->feedOverrideFactor=fo;
01800 if ( -1 == sqResume(sq) )
01801 {
01802 diagnostics("Error in sqSetFeedOverride\n");
01803 return -1;
01804 }
01805 else
01806 return 0;
01807 }
01808 else
01809 {
01810
01811 sq->feedOverrideFactor=fo;
01812 return 0;
01813 }
01814 }
01815
01816 sq->feedOverrideFactor=fo;
01817 if ( as->active==0 )
01818 {
01819
01820
01821 }
01822
01823 else if ( sq->n < as->m + 2 || sq->feedAdjusting==1 )
01824 {
01825
01826
01827
01828 if ( sq->feedAdjusting!=1 && as->p==0 && as->maxInc*fo > as->cruiseInc )
01829
01830
01831 return 0;
01832
01833 if (sq->feedAdjusting==1)
01834 {
01835
01836
01837
01838 as->a1=as->a3;
01839 as->b1=as->b3;
01840 as->c1=as->c3;
01841 as->d1=as->d3;
01842 }
01843
01844 finalInc=as->maxInc*fo;
01845
01846
01847
01848 if (sq->n==1 || sq->n==2 || sq->n==3)
01849 {
01850 startInc=as->plInitInc;
01851 startAcc=0;
01852 }
01853 else if ( sq->n==3)
01854 {
01855 npow1 = 1;
01856 npow2 = 1;
01857 npow3 = 1;
01858 startInc = as->a1 * npow3 *sq->ctPow3 \
01859 + as->b1 * npow2 * sq->ctPow2 \
01860 + as->c1 * npow1 * sq->cycleTime \
01861 + as->d1;
01862 startAcc = (startInc - as->plInitInc );
01863 }
01864 else
01865 {
01866 npow1 = sq->n - 3;
01867 npow2 = npow1 * npow1;
01868 npow3 = npow2 * npow1;
01869 startInc = as->a1 * npow3 *sq->ctPow3 \
01870 + as->b1 * npow2 * sq->ctPow2 \
01871 + as->c1 * npow1 * sq->cycleTime \
01872 + as->d1;
01873 npow1 = sq->n - 4;
01874 npow2 = npow1 * npow1;
01875 npow3 = npow2 * npow1;
01876 prevInc = (as->a1 * npow3 *sq->ctPow3 \
01877 + as->b1 * npow2 * sq->ctPow2 \
01878 + as->c1 * npow1 * sq->cycleTime \
01879 + as->d1);
01880 startAcc = startInc - prevInc;
01881 }
01882 as->q= ceil ( 1.7393877* fabs(startInc-finalInc) / \
01883 ( sq->maxAcc * sq->ctPow2 ) +
01884 0.5967755904 * fabs(startInc-finalInc) / \
01885 ( sq->maxAcc * sq->maxAcc * sq->ctPow2 * sq->ctPow2) *\
01886 startAcc-(sq->maxAcc * sq->ctPow2)/2);
01887 as->m=0;
01888 as->p=0;
01889 as->totNumPoints = as->q + 1;
01890 sq->n=3;
01891
01892 as->b3 = - ( 3 * (startInc-finalInc) + 2 * as->q* startAcc ) \
01893 / ( as->q * as->q * sq->ctPow2 ) ;
01894 as->a3 = ( 2 * (startInc-finalInc) + as->q* startAcc ) \
01895 / ( as->q * as->q * as->q * sq->ctPow3 ) ;
01896 as->c3 = startAcc/sq->cycleTime;
01897 as->d3 = startInc;
01898
01899 as->plFinalInc=finalInc;
01900
01901
01902
01903
01904 sq->feedAdjusting=1;
01905
01906 }
01907 else if ( sq->n < as->m + as->p + 2 )
01908 {
01909
01910
01911
01912
01913 startInc=as->cruiseInc;
01914
01915
01916 cursor=as;
01917 while ( cursor!=sq->cursor )
01918 {
01919 cursor=cursor->nextSegment;
01920 if (cursor == 0 )
01921 {
01922 diagnostics("Panic 1: cursor = NULL in sqSetFeedOverride\n");
01923 return -1;
01924 }
01925 sq->numSegments--;
01926 }
01927 if ( sq->numSegments < sq->size - SQ_SAFETY_MARGIN )
01928 sq->full = 0;
01929 if ( sq->numSegments < 0 )
01930 {
01931 diagnostics("Panic: sq->numSegments <0 in sqSetFeedOverride\n");
01932 return -1;
01933 }
01934
01935
01936 cursor->prevSegment=0;
01937 cursor->linkedToPrevSeg=0;
01938 sq->start= sq->cursor - sq->queue;
01939 as=cursor;
01940
01941 as->planningDone=0;
01942 as->plInitInc=startInc;
01943 as->start=sq->lastPoint;
01944 if ( as->type == SQ_LINEAR)
01945 {
01946 as->length=sqGiveLength(as->start,as->end);
01947 as->totLength=as->length;
01948 pmLineInit(&as->line,as->start,as->end);
01949 }
01950 else
01951 {
01952 angleToGo= as->circle.angle-(sq->dist-sq->offset)/as->helixRadius;
01953 turn = floor(angleToGo / ( 2 * PM_PI ));
01954 normal = as->circle.normal;
01955 center = as->circle.center;
01956 pmCircleInit( &as->circle, as->start, as->end, center, normal, turn);
01957 as->length=as->circle.angle* as->helixRadius;
01958 as->totLength= as->length;
01959 }
01960
01961
01962 as->active=0;
01963
01964
01965
01966 as->numLinkedSegs=0;
01967 while (cursor->nextSegment!=0 &&
01968 cursor->nextSegment->linkedToPrevSeg==1 )
01969 {
01970 cursor=cursor->nextSegment;
01971 as->numLinkedSegs++;
01972 as->totLength+=cursor->length;
01973 }
01974
01975
01976
01977 if ( -1 == sqForwardLinkSegment(sq,as,sq->feedOverrideFactor))
01978 {
01979 diagnostics("Error in sqSetFeedOverride\n");
01980 return -1;
01981 }
01982 }
01983 else
01984 {
01985
01986
01987
01988
01989 }
01990
01991 return 0;
01992 }
01993
01994
01995 int sqPause(SEGMENTQUEUE *sq)
01996 {
01997 SEGMENT *as;
01998 double startInc;
01999
02000 double startAcc;
02001 int npow1,npow2,npow3;
02002 double amaxTan;
02003
02004 if (sq==0 || sq->queue==0 )
02005 {
02006 diagnostics("Error in sqPause\n");
02007 return -1;
02008 }
02009
02010 if (sq->paused == 1)
02011
02012 return 0;
02013
02014
02015 sq->paused=1;
02016
02017 if ( sq->numSegments==0)
02018 {
02019
02020 sq->done = 1;
02021 return 0;
02022 }
02023
02024 as=sq->queue+sq->start;
02025
02026 if ( as->active==0 && as->initInc==0 )
02027
02028
02029 {
02030 sq->done=1;
02031 return 0;
02032 }
02033
02034 sq->feedAdjusting=0;
02035
02036 amaxTan= sqGiveMinAmaxTan(as);
02037
02038 if ( as->active==0 || sq->n<=3)
02039 {
02040 startInc = as->plInitInc;
02041 startAcc = 0;
02042 as->active=1;
02043 as->planningDone=1;
02044
02045 as->q= ceil ( 3 * startInc / ( 2 * amaxTan * sq->ctPow2 ) );
02046 as->m=0;
02047 as->p=0;
02048 as->totNumPoints = as->q + 3;
02049 sq->n=3;
02050
02051 }
02052 else if ( sq->n < as->m + 2 )
02053 {
02054
02055 npow1 = sq->n - 3;
02056 npow2 = npow1 * npow1;
02057 npow3 = npow2 * npow1;
02058 startInc = as->a1 * npow3 *sq->ctPow3 \
02059 + as->b1 * npow2 * sq->ctPow2 \
02060 + as->c1 * npow1 * sq->cycleTime \
02061 + as->d1;
02062 npow1 = sq->n - 4;
02063 npow2 = npow1 * npow1;
02064 npow3 = npow2 * npow1;
02065 startAcc = startInc - (as->a1 * npow3 *sq->ctPow3 \
02066 + as->b1 * npow2 * sq->ctPow2 \
02067 + as->c1 * npow1 * sq->cycleTime \
02068 + as->d1);
02069 as->q= ceil ( 2.12* startInc / ( amaxTan * sq->ctPow2 ) );
02070 as->m=0;
02071 as->p=0;
02072 as->totNumPoints = as->q + 3;
02073 sq->n=3;
02074 }
02075 else if ( sq->n < as->m + as->p + 2 )
02076 {
02077 startInc = as->cruiseInc;
02078 startAcc = 0;
02079 as->q= ceil ( 3 * startInc / ( 2 * amaxTan * sq->ctPow2 ) );
02080 as->m=0;
02081 as->p=0;
02082 as->totNumPoints = as->q + 3;
02083 sq->n=3;
02084 }
02085 else
02086 {
02087
02088
02089
02090
02091
02092 if (as->plFinalInc==0)
02093 {
02094
02095
02096
02097
02098
02099
02100
02101 sq->paused=0;
02102 sq->stepping=1;
02103 return 0;
02104 }
02105 else
02106 {
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116 as->a1=as->a3;
02117 as->b1=as->b3;
02118 as->c1=as->c3;
02119 as->d1=as->d3;
02120
02121 sq->n -= as->m + as->p;
02122
02123 as->m =as->q;
02124 as->p=1 ;
02125
02126
02127
02128 startInc = as->plFinalInc;
02129 startAcc = 0;
02130 as->cruiseInc = startInc;
02131
02132 as->q= ceil ( 3 * startInc / ( 2 * amaxTan * sq->ctPow2 ) );
02133 as->totNumPoints = as->m + as->q + as->p + 2;
02134
02135 }
02136 }
02137 as->b3 = - ( 3 * startInc + 2 * as->q* startAcc ) \
02138 / ( as->q * as->q * sq->ctPow2 ) ;
02139 as->a3 = ( 2 * startInc + as->q* startAcc ) \
02140 / ( as->q * as->q * as->q * sq->ctPow3 ) ;
02141 as->c3 = startAcc/sq->cycleTime;
02142 as->d3 = startInc;
02143
02144 as->plFinalInc=0;
02145
02146 return 0;
02147 }
02148
02149
02150 int sqResume(SEGMENTQUEUE *sq)
02151 {
02152 SEGMENT *as;
02153 SEGMENT *cursor;
02154
02155 if (sq==0 || sq->queue==0 )
02156 {
02157 diagnostics("Error in sqResume\n");
02158 return -1;
02159 }
02160
02161 if ( sq->done!=1)
02162
02163
02164
02165 {
02166 diagnosticsOff("Can't resume if not done with pause or step action\n");
02167
02168 return 0;
02169 }
02170
02171 if ( sq->feedOverrideFactor == 0 )
02172 {
02173
02174
02175
02176 diagnostics("Can't resume if feed override is zero\n");
02177
02178 return 0;
02179 }
02180
02181 if ( sq->numSegments == 0)
02182 {
02183
02184 sq->paused = 0;
02185 return 0;
02186 }
02187
02188
02189
02190 as=sq->queue+sq->start;
02191 cursor=as;
02192
02193 while ( cursor->nextSegment!=0 && cursor->nextSegment->linkedToPrevSeg==1)
02194 cursor=cursor->nextSegment;
02195
02196
02197
02198
02199 if ( -1 == sqForwardLinkSegment(sq, as, sq->feedOverrideFactor ))
02200 {
02201 diagnostics("Error in sqResume \n ");
02202 return -1;
02203 }
02204
02205 if (sq->paused == 1 && sq->stepping == 1 )
02206 sq->stepping=1;
02207 else
02208 sq->stepping=0;
02209
02210 sq->paused=0;
02211 sq->done=0;
02212
02213 return 0;
02214 }
02215
02216
02217 int sqAbort(SEGMENTQUEUE *sq)
02218 {
02219 if (1 == sq->aborting)
02220
02221 return 0;
02222
02223 if (sq==0)
02224 {
02225 diagnostics("Error in sqAbort\n");
02226 return -1;
02227 }
02228
02229 if ( sq->paused == 1 || sq->done == 1 )
02230 {
02231 if (-1 == sqClearQueue(sq))
02232 {
02233 diagnostics("Error in sqAbort\n");
02234 return -1;
02235 }
02236 }
02237 else
02238 {
02239 sq->aborting=1;
02240 sqPause(sq);
02241 }
02242 return 0;
02243 }
02244
02245
02246 int sqStep(SEGMENTQUEUE *sq)
02247 {
02248 SEGMENT *as;
02249 if (sq==0)
02250 {
02251 diagnostics("Error in sqStep\n");
02252 return -1;
02253 }
02254
02255 if (sq->done!=1 || sq->numSegments==0 )
02256
02257 {
02258 diagnostics("Stepping can only be done when system is paused and waiting\n");
02259
02260 return 0;;
02261 }
02262
02263 if ( sq->feedOverrideFactor == 0 )
02264 {
02265
02266
02267
02268 diagnostics("Can't resume if feed override is zero\n");
02269
02270 return 0;
02271 }
02272
02273
02274
02275
02276
02277
02278 as=sq->queue+sq->start;
02279 as->finalInc=0;
02280
02281
02282 if (as->nextSegment!=0 && as->nextSegment->linkedToPrevSeg==1)
02283 {
02284 as->nextSegment->linkedToPrevSeg=0;
02285 as->nextSegment->numLinkedSegs=as->numLinkedSegs-1;
02286 as->nextSegment->totLength=as->totLength - as->length;
02287 as->numLinkedSegs=0;
02288 as->totLength=as->length;
02289 }
02290 sq->done=0;
02291 sq->stepping=1;
02292 sq->paused=0;
02293 return 0;
02294 }
02295
02296 int sqIsStepping(SEGMENTQUEUE *sq)
02297 {
02298 if (sq==0)
02299 {
02300 diagnostics("Error in sqIsStepping\n");
02301 return -1;
02302 }
02303 return sq->stepping;
02304 }
02305
02306 int sqIsDone(SEGMENTQUEUE *sq)
02307 {
02308 if (sq==0)
02309 {
02310 diagnostics("Error in sqIsStepping\n");
02311 return -1;
02312 }
02313 return sq->done;
02314 }
02315
02316 int sqIsPaused(SEGMENTQUEUE *sq)
02317 {
02318 if (sq==0)
02319 {
02320 diagnostics("Error in sqIsPaused\n");
02321 return -1;
02322 }
02323 return sq->paused;
02324 }
02325
02326 double sqGetVel(SEGMENTQUEUE *sq)
02327 {
02328 if (sq==0)
02329 {
02330 diagnostics("Error in sqGetVel\n");
02331 return -1;
02332 }
02333
02334 return sq->currentVel;
02335 }
02336
02337 double sqGetMaxAcc(SEGMENTQUEUE *sq)
02338 {
02339 if (sq==0)
02340 {
02341 diagnostics("Error in sqGetMaxAcc\n");
02342 return -1;
02343 }
02344 return sq->maxAcc;
02345 }
02346
02347 int sqGetDepth(SEGMENTQUEUE *sq)
02348 {
02349 if (sq==0)
02350 {
02351 diagnostics("Error in sqGetDepth\n");
02352 return -1;
02353 }
02354 return sq->numSegments;
02355 }
02356
02357 int sqIsQueueFull(SEGMENTQUEUE *sq)
02358 {
02359 if (sq==0)
02360 {
02361 diagnostics("Error in sqIsQueueFull\n");
02362 return -1;
02363 }
02364 return sq->full;
02365 }
02366
02367 int sqGetID(SEGMENTQUEUE *sq)
02368 {
02369 if (sq==0)
02370 {
02371 diagnostics("Error in sqGetID\n");
02372 return -1;
02373 }
02374 return sq->currentID;
02375 }
02376
02377
02378
02379 # ifdef trash
02380
02381
02382
02383 {
02384 cursor=prevseg;
02385 done=0;
02386 counter=0;
02387 while (!done)
02388 {
02389 counter++;
02390 if ( counter > sq->size )
02391 {
02392
02393
02394 diagnostics("Can't get out of the loop\n");
02395 return -1;
02396 }
02397
02398 if (cursor->initInc < cornerInc )
02399
02400
02401
02402 done=1;
02403 else if (cursor->linkedToPrevSeg==1)
02404
02405 {
02406 cursor=cursor->prevSegment;
02407 if (cursor == 0 )
02408 {
02409 diagnostics("Panic: cursor = NULL in sqPreprocessSegment\n");
02410 return -1;
02411 }
02412 }
02413 else
02414 {
02415 amaxTan = sqGiveMinAmaxTan(cursor);
02416 minNumSteps=ceil(3*( cursor->initInc-cornerInc ) / \
02417 (2*amaxTan*sq->ctPow2));
02418 if ((minNumSteps+1)*(cursor->initInc+cornerInc)/2 \
02419 - cursor->initInc > \
02420 cursor->length-5*max(cursor->initInc,cornerInc) )
02421 {
02422
02423
02424 cursor=cursor->prevSegment;
02425 if (cursor == 0 )
02426 {
02427 diagnostics("Panic: cursor = NULL in sqPreprocessSegment\n");
02428 return -1;
02429 }
02430 if (-1 == sqLinkSegments(cursor,cursor->nextSegment,SQ_HIGH_LINKING_PRIORITY))
02431 {
02432 diagnostics("Error 5 in sqPreprocessSegment()\n");
02433 return -1;
02434 }
02435
02436 }
02437 else
02438 done=1;
02439 }
02440 if ( cursor == sq->queue + sq->start )
02441 {
02442 diagnostics("Beginning of queue reached, no further linking possible\n");
02443 done =1;
02444 }
02445 }
02446
02447
02448
02449
02450 amaxTan = sqGiveMinAmaxTan(cursor);
02451 minNumSteps = ceil ( 3 * (cornerInc-cursor->initInc ) / \
02452 ( 2 * amaxTan * sq->ctPow2 ));
02453 if ((minNumSteps+1)*(cursor->initInc+cornerInc)/2 - \
02454 cursor->initInc >
02455 cursor->totLength - 5*max( cursor->initInc,cornerInc ) )
02456
02457 if ( -1 == sqLinkSegments(prevseg,newseg,SQ_HIGH_LINKING_PRIORITY))
02458 {
02459 diagnostics("Error 4 in sqPreprocessSegment()\n");
02460 return -1;
02461 }
02462
02463
02464 amaxTan = sqGiveMinAmaxTan(as);
02465 while (!done)
02466 {
02467 if ( cursor->nextSegment!=0 && cursor->nextSegment->maxInc < \
02468 cursor->maxInc)
02469 finalInc=min(cursor->finalInc,\
02470 cursor->nextSegment->maxInc*sq->feedOverrideFactor);
02471
02472 else
02473 finalInc=min(cursor->finalInc,\
02474 cursor->maxInc*sq->feedOverrideFactor);
02475 amaxTan = min ( amaxTan, cursor->amaxTan);
02476 minNumSteps = ceil ( 3 *fabs(finalInc-startInc) / \
02477 ( 2 * amaxTan * sq->ctPow2 ));
02478 if ((minNumSteps+1)* (startInc+finalInc)/2 > \
02479 as->totLength - 1 * finalInc )
02480
02481 {
02482 if (-1 ==sqLinkSegments(cursor,cursor->nextSegment,SQ_HIGH_LINKING_PRIORITY))
02483 {
02484 diagnostics("Error in sqSetFeedOverride\n");
02485 return -1;
02486 }
02487 cursor=cursor->nextSegment;
02488 if (cursor == 0 )
02489 {
02490 diagnostics("Panic 2: cursor = NULL in sqSetFeedOverride\n");
02491 return -1;
02492 }
02493
02494 }
02495 else
02496 done=1;
02497 }
02498
02499
02500 amaxTan = sqGiveMinAmaxTan(as);
02501
02502
02503 while (!done)
02504 {
02505 if ( cursor->nextSegment!=0 && cursor->nextSegment->maxInc < \
02506 cursor->maxInc)
02507 finalInc=min(cursor->finalInc,\
02508 cursor->nextSegment->maxInc*sq->feedOverrideFactor);
02509
02510 else
02511 finalInc=min(cursor->finalInc,\
02512 cursor->maxInc*sq->feedOverrideFactor);
02513
02514 amaxTan = min ( amaxTan, cursor->amaxTan);
02515 minNumSteps = ceil ( 3 * finalInc / \
02516 ( 2 * amaxTan * sq->ctPow2 ));
02517 if ((minNumSteps+1)* finalInc/2 > \
02518 as->totLength - 2 * finalInc )
02519
02520 {
02521 if (-1 == sqLinkSegments(cursor,cursor->nextSegment,SQ_HIGH_LINKING_PRIORITY))
02522 {
02523 diagnostics("Error in sqResume \n");
02524 return -1;
02525 }
02526 cursor=cursor->nextSegment;
02527 if (cursor == 0 )
02528 {
02529 diagnostics("Panic: cursor = NULL in sqResume\n");
02530 return -1;
02531 }
02532
02533 }
02534 else
02535 done=1;
02536 }
02537
02538
02539 #endif