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