Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

segmentqueue.c File Reference

#include "segmentqueue.h"
#include <stdio.h>
#include <float.h>

Include dependency graph for segmentqueue.c:

Include dependency graph

Go to the source code of this file.

Defines

#define SQ_SAFETY_MARGIN   10
#define SQ_MAX_NUM_LINKED_SEGS   500
#define SQ_LOW_LINKING_PRIORITY   1
#define SQ_HIGH_LINKING_PRIORITY   2
#define SQ_LINKING_NEEDED   2
#define SQ_LINKING_NOT_NEEDED   1
#define diagnostics(fmt, args...)   fprintf(stderr, fmt, ## args )
#define diagnosticsOff(fmt, args...)

Functions

double sqGiveLength (EmcPose p1, EmcPose p2)
double sqGiveCornerVelocity (SEGMENT *s1, SEGMENT *s2, double amax,\double cycleTime)
double sqGiveMinAmaxTan (SEGMENT *s)
double sqGiveMaxInc (SEGMENTQUEUE *sq, SEGMENT *s)
int sqLinkCriterion (SEGMENTQUEUE *sq, SEGMENT *s, double feedOverride)
int sqPlanSegment (SEGMENTQUEUE *sq, SEGMENT *s)
int sqLinkSegments (SEGMENT *s1, SEGMENT *s2, int priority)
int sqForwardLinkSegment (SEGMENTQUEUE *sq, SEGMENT *s, double feedOverride)
int sqBackwardLinkSegment (SEGMENTQUEUE *sq, SEGMENT *s, double feedOverride)
int sqPreprocessSegment (SEGMENTQUEUE *sq, SEGMENT *newseg)
int sqInitQueue (SEGMENTQUEUE *sq, SEGMENT *first, int size)
int sqSetMaxAcc (SEGMENTQUEUE *sq, double amax)
int sqSetVmax (SEGMENTQUEUE *sq, double vmax)
int sqSetCycleTime (SEGMENTQUEUE *sq, double secs)
int sqSetMaxFeedOverride (SEGMENTQUEUE *sq, double mfo)
int sqSetPos (SEGMENTQUEUE *sq, EmcPose pos)
int sqClearQueue (SEGMENTQUEUE *sq)
int sqTrashQueue (SEGMENTQUEUE *sq)
int sqSetFeed (SEGMENTQUEUE *sq, double feed)
int sqAddLine (SEGMENTQUEUE *sq, EmcPose end, int ID)
int sqAddCircle (SEGMENTQUEUE *sq, EmcPose end, PmCartesian center,\PmCartesian normal, int turn, int ID)
int sqGetPosition (SEGMENTQUEUE *sq, EmcPose *p)
int sqRunCycle (SEGMENTQUEUE *sq)
int sqSetFeedOverride (SEGMENTQUEUE *sq, double fo)
int sqPause (SEGMENTQUEUE *sq)
int sqResume (SEGMENTQUEUE *sq)
int sqAbort (SEGMENTQUEUE *sq)
int sqStep (SEGMENTQUEUE *sq)
int sqIsStepping (SEGMENTQUEUE *sq)
int sqIsDone (SEGMENTQUEUE *sq)
int sqIsPaused (SEGMENTQUEUE *sq)
double sqGetVel (SEGMENTQUEUE *sq)
double sqGetMaxAcc (SEGMENTQUEUE *sq)
int sqGetDepth (SEGMENTQUEUE *sq)
int sqIsQueueFull (SEGMENTQUEUE *sq)
int sqGetID (SEGMENTQUEUE *sq)

Variables

EmcPose oldPos
EmcPose oldVel
EmcPose newVel
EmcPose newAcc
double oldDist


Define Documentation

#define SQ_HIGH_LINKING_PRIORITY   2
 

Definition at line 113 of file segmentqueue.c.

#define SQ_LINKING_NEEDED   2
 

Definition at line 115 of file segmentqueue.c.

#define SQ_LINKING_NOT_NEEDED   1
 

Definition at line 116 of file segmentqueue.c.

#define SQ_LOW_LINKING_PRIORITY   1
 

Definition at line 112 of file segmentqueue.c.

#define SQ_MAX_NUM_LINKED_SEGS   500
 

Definition at line 110 of file segmentqueue.c.

#define SQ_SAFETY_MARGIN   10
 

Definition at line 103 of file segmentqueue.c.

#define diagnostics fmt,
args...       fprintf(stderr, fmt, ## args )
 

Definition at line 124 of file segmentqueue.c.

#define diagnosticsOff fmt,
args...   
 

Definition at line 131 of file segmentqueue.c.

Referenced by sqAddLine(), sqPlanSegment(), sqResume(), and sqRunCycle().


Function Documentation

int sqAbort SEGMENTQUEUE   sq
 

Definition at line 2217 of file segmentqueue.c.

02218 {
02219   if (1 == sq->aborting)
02220     /* we are already aborting, so let's just ignore it */
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 }

int sqAddCircle SEGMENTQUEUE   sq,
EmcPose    end,
PmCartesian    center,
\PmCartesian    normal,
int    turn,
int    ID
 

Definition at line 1255 of file segmentqueue.c.

01257 {
01258   SEGMENT * newseg;
01259   PmCircle circle;
01260   EmcPose start;
01261   PmCartesian helix;
01262   double absHelix;
01263 
01264   /* used to calculate the maximum tangential acceleration */
01265   double rpow2,A,topIncPow2;
01266 
01267 /* check if segment queue has been initialized */
01268   if ( sq == 0 || sq->queue == 0 )
01269     {
01270       diagnostics("Error in sqAddCircle()\n");
01271       return -1;
01272     }
01273 
01274   /* check for full */
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       /* only set ID of last appended motion */
01291       sq->lastAppMotionID=ID;
01292       return 0;
01293     }
01294 
01295   /* Calculate the helix gradient in normal direction */
01296   pmCartScalDiv( circle.rHelix, circle.angle, &helix );
01297   pmCartMag( helix, &absHelix);
01298 
01299   /* let newseg point to the first empty place in the ring buffer... */
01300   newseg= sq->queue+sq->end;
01301   /* ...and update the ring buffer properties */
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   /* fill segment parameter fields */
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   /* calculate the maximum tangential acceleration for this circle */
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   /* set last Appended Motion ID */
01359   sq->lastAppMotionID=ID;
01360 
01361   return 0;
01362 }

int sqAddLine SEGMENTQUEUE   sq,
EmcPose    end,
int    ID
 

Definition at line 1168 of file segmentqueue.c.

01169 {
01170   double length, maxUVec;
01171   SEGMENT *newseg;
01172   EmcPose start;
01173 
01174 
01175   /* check if segment queue has been initialized */
01176   if ( sq == 0 || sq->queue == 0 )
01177     {
01178       diagnostics("Error in sqAddLine()\n");
01179       return -1;
01180     }
01181 
01182   /* check for full */
01183   if ( sq->numSegments == sq->size )
01184     {
01185       diagnostics("Panic!!!!, segmentqueue overflows!!!\n");
01186       return -1;
01187     }
01188 
01189   /* check if new motion has zero length */
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       /* only set ID of last appended motion */
01200       sq->lastAppMotionID=ID;
01201       return 0;
01202     }
01203 
01204   /* let newseg point to the first empty place in the ring buffer... */
01205   newseg= sq->queue+sq->end;
01206   /* ...and update the ring buffer properties */
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   /* fill segment parameter fields */
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   /* initialize line */
01234   pmLineInit( &newseg->line, newseg->start, newseg->end);
01235 
01236   /* set the maximum tangential acceleration for this line */
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   /* set last Appended Motion ID */
01250   sq->lastAppMotionID=ID;
01251 
01252   return 0;
01253 }

int sqBackwardLinkSegment SEGMENTQUEUE   sq,
SEGMENT   s,
double    feedOverride
 

Definition at line 772 of file segmentqueue.c.

Referenced by sqPreprocessSegment().

00773 {
00774   /* function that checks whether segment s needs to be linked to its
00775      predecessor(s) based upon the finalInc. It is possible that
00776      this requires linking of a set of preceding segments to make sure that
00777      the final increment can be reached. */
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       /* not critical, so we don't return -1, but it's not good....*/
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           /* we have browsed through the whole queue and can't
00806              get out of the loop.... */
00807           diagnostics("Can't get out of the loop in sqBackwardLinkSegment\n");
00808           return -1;
00809         }
00810 
00811       if (cursor->linkedToPrevSeg==1)
00812         /* it is already linked */
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         /* then we're done. This is always true as long as the set of
00823          segments that precede s is correctly processed, since the
00824          total length of the segments from cursor to the last segment
00825          before s is large enough to reach s's initial increment. This
00826          length is of course large enough too to reach s->finalInc
00827          because that is smaller than s->initInc (otherwise this
00828          function wouldn't have called). */
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; /* no further linking needed */
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 }

int sqClearQueue SEGMENTQUEUE   sq
 

Definition at line 1110 of file segmentqueue.c.

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;      /* the queue is empty, so by definition we're done */
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 }

int sqForwardLinkSegment SEGMENTQUEUE   sq,
SEGMENT   s,
double    feedOverride
 

Definition at line 665 of file segmentqueue.c.

Referenced by sqPreprocessSegment(), sqResume(), and sqSetFeedOverride().

00666 {
00667   /* function that checks whether segment s needs to be linked to its
00668      successor(s) based upon its initial increment. It is possible that
00669      this requires linking of a set of succeding segments to make sure that
00670      the final increment can be reached. */
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       /* not critical, so we don't return -1, but it's not good....*/
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           /* we have browsed through the whole queue and can't
00699              get out of the loop.... */
00700           diagnostics("Can't get out of the loop in sqForwardLinkSegment\n");
00701           return -1;
00702         }
00703       if (cursor->nextSegment == 0 )
00704         {
00705           /* then this is the last segment in the queue, which always has
00706              a final velocity of zero that can always be reached. Ergo: we're
00707              done */
00708           done = 1;
00709         }
00710       else if (cursor->nextSegment->linkedToPrevSeg==1)
00711         /* the next segment is already linked to cursor, so let's go on */
00712         {
00713           cursor=cursor->nextSegment;
00714           if (cursor == 0 )
00715             {
00716               /* this is VERY unlikely to happen, since we already checked
00717                  that a few lines before, but just in case...... */
00718               diagnostics("Panic: cursor = NULL in sqForwardLinkSegment\n");
00719               return -1;
00720             }
00721         }
00722       else if (s->initInc > cursor->finalInc )
00723         /* then we're done. This is always true as long as the set of
00724          segments that succeed s is correctly processed: if the
00725          succeeding segments are correctly processed, then
00726          cursor->finalInc can be reached from s->finalInc
00727          (= s->nextSegment->initInc) over the distance of the segments
00728          s->nextSegment to cursor. The final increment of s is larger
00729          than the initial increment (otherwise this function wouldn't
00730          have been called), so the distance of the segments s to cursor is
00731          of course large enough too to decelerate from s->initInc to
00732          cursor->finalInc */
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                   /* again, this is very unlikely to happen */
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             /* linkcrit==SQ_NO_LINKING_NEEDED */
00758             done=1; /* no further linking needed */
00759         }
00760       if ( cursor == sq->queue + sq->end )
00761         {
00762           /* sq->end points to the first free position in the ring buffer
00763              so there's no segment at that position. So if cursor points to
00764              that position, something is very wrong */
00765           diagnostics("End of queue reached, no further linking possible\n");
00766           done =1;
00767         }
00768     }
00769   return 0;
00770 }

int sqGetDepth SEGMENTQUEUE   sq
 

Definition at line 2347 of file segmentqueue.c.

02348 {
02349   if (sq==0)
02350     {
02351       diagnostics("Error in sqGetDepth\n");
02352       return -1;
02353     }
02354   return sq->numSegments;
02355 }

int sqGetID SEGMENTQUEUE   sq
 

Definition at line 2367 of file segmentqueue.c.

02368 {
02369   if (sq==0)
02370     {
02371       diagnostics("Error in sqGetID\n");
02372       return -1;
02373     }
02374   return sq->currentID;
02375 }

double sqGetMaxAcc SEGMENTQUEUE   sq
 

Definition at line 2337 of file segmentqueue.c.

02338 {
02339   if (sq==0)
02340     {
02341       diagnostics("Error in sqGetMaxAcc\n");
02342       return -1;
02343     }
02344   return sq->maxAcc;
02345 }

int sqGetPosition SEGMENTQUEUE   sq,
EmcPose   p
 

Definition at line 1364 of file segmentqueue.c.

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 };

double sqGetVel SEGMENTQUEUE   sq
 

Definition at line 2326 of file segmentqueue.c.

02327 {
02328   if (sq==0)
02329     {
02330       diagnostics("Error in sqGetVel\n");
02331       return -1;
02332     }
02333 
02334   return sq->currentVel;
02335 }

double sqGiveCornerVelocity SEGMENT   s1,
SEGMENT   s2,
double    amax,
\double    cycleTime
[static]
 

Definition at line 152 of file segmentqueue.c.

Referenced by sqPreprocessSegment().

00154 {
00155   /* s1 and s2 must have been initialized correctly and must have a nonzero
00156      lenght in order to get a valid corner */
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   /* check if s1 or s2 has a zero length or amax or cycleTime is zero */
00173   if ( s1->length == 0 || s2->length == 0 || amax==0 || cycleTime==0 )
00174     {
00175       /* of course this shouldn't happen */
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   /* calculate the difference between v1 and v2 */
00206   pmCartCartSub ( v2,v1, &diff );
00207 
00208   /* select the largest element in diff */
00209   maxdiff = max ( fabs(diff.x), fabs(diff.y) );
00210   maxdiff = max ( maxdiff , fabs(diff.z) );
00211 
00212   /* return cornerVelocity */
00213   if ( maxdiff <= 0 )
00214     return DBL_MAX;
00215   else
00216     return ( amax * cycleTime / maxdiff );
00217 
00218 };

double sqGiveLength EmcPose    p1,
EmcPose    p2
[static]
 

Definition at line 140 of file segmentqueue.c.

Referenced by sqAddLine(), sqRunCycle(), and sqSetFeedOverride().

00141 {
00142   PmCartesian disp;
00143   double mag;
00144 
00145   pmCartCartSub(p1.tran, p2.tran, &disp);
00146   pmCartMag(disp, &mag);
00147 
00148   return mag;
00149 };

double sqGiveMaxInc SEGMENTQUEUE   sq,
SEGMENT   s
[static]
 

Definition at line 250 of file segmentqueue.c.

Referenced by sqPlanSegment().

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           /* this segment was too short and therefore linked to the next
00296              one */
00297           cursor=cursor->nextSegment;
00298           l+=cursor->length;
00299         }
00300       else
00301         done=1;
00302     }
00303 
00304   return cursor->maxInc;
00305 }

double sqGiveMinAmaxTan SEGMENT   s [static]
 

Definition at line 220 of file segmentqueue.c.

Referenced by sqLinkCriterion(), sqPause(), sqPlanSegment(), and sqRunCycle().

00221 {
00222   /* give the minimum tangential acceleration for the chain of linked
00223      that starts with s. */
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 }

int sqInitQueue SEGMENTQUEUE   sq,
SEGMENT   first,
int    size
 

Definition at line 1003 of file segmentqueue.c.

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   /* FIXME: third argument (size) is ignored, since the queue size for
01014      the coordinated mode queue can not be set seperately from the
01015      free mode queues */
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;   /* this has to be set at start-up using
01028                                         sqSetMaxFeedOverride() */
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;      /* the queue is empty, so by definition we're done */
01036   sq->paused=0;
01037   sq->stepping=0;
01038   sq->feedAdjusting=0;
01039   sq->aborting=0;
01040 
01041 
01042   /* initializing debug variables */
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 };

int sqIsDone SEGMENTQUEUE   sq
 

Definition at line 2306 of file segmentqueue.c.

02307 {
02308   if (sq==0)
02309     {
02310       diagnostics("Error in sqIsStepping\n");
02311       return -1;
02312     }
02313   return sq->done;
02314 }

int sqIsPaused SEGMENTQUEUE   sq
 

Definition at line 2316 of file segmentqueue.c.

02317 {
02318   if (sq==0)
02319     {
02320       diagnostics("Error in sqIsPaused\n");
02321       return -1;
02322     }
02323   return sq->paused;
02324 }

int sqIsQueueFull SEGMENTQUEUE   sq
 

Definition at line 2357 of file segmentqueue.c.

02358 {
02359   if (sq==0)
02360     {
02361       diagnostics("Error in sqIsQueueFull\n");
02362       return -1;
02363     }
02364   return sq->full;
02365 }

int sqIsStepping SEGMENTQUEUE   sq
 

Definition at line 2296 of file segmentqueue.c.

02297 {
02298   if (sq==0)
02299     {
02300       diagnostics("Error in sqIsStepping\n");
02301       return -1;
02302     }
02303   return sq->stepping;
02304 }

int sqLinkCriterion SEGMENTQUEUE   sq,
SEGMENT   s,
double    feedOverride
 

Definition at line 306 of file segmentqueue.c.

Referenced by sqBackwardLinkSegment(), sqForwardLinkSegment(), and sqPlanSegment().

00307 {
00308   /* this function returns SQ_LINKING_NEEDED if the chain of segments starting
00309      with s is not long enough to accelerate or decelerate from the initial
00310      increment of the first segment in the chain to the final increment of the
00311      last segment in the chain
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   /* find the last segment of the chain */
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   /* find the minimum boundary for the acceleration in tangential
00344      direction */
00345   /* FIXME: this can be combined with the previous for statement that
00346      looks up the last segment of the chain */
00347   amaxTan = sqGiveMinAmaxTan(s);
00348 
00349   /* find the correct value for the initial increment: when s->plInitInc is
00350      non zero, this means that the segment has been processed before, and that
00351      value should be used */
00352   if ( 0 != s->plInitInc )
00353     initInc = s->plInitInc;
00354   else
00355     initInc = s->initInc;
00356 
00357   /* find the correct value of the final increment (with taking a feedoverride
00358      into account).*/
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 }

int sqLinkSegments SEGMENT   s1,
SEGMENT   s2,
int    priority
[static]
 

Definition at line 606 of file segmentqueue.c.

Referenced by sqBackwardLinkSegment(), sqForwardLinkSegment(), sqPreprocessSegment(), and sqRunCycle().

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   /* if s2 is not the segment that immediately follows s1, then linking
00621      can not be done */
00622 
00623   if ( s1->nextSegment != s2 )
00624     {
00625       diagnostics("Error 2 in sqLinkSegments()\n");
00626       return -1;
00627     }
00628 
00629   /* if s1 is active, linking should not be done */
00630   if (s1->active == 1)
00631     {
00632 /*        diagnostics("Error in sqLinkSegments()\n"); */
00633 /*        return -1; */
00634       return 0;
00635     }
00636 
00637   /* find the first element in the series of linked segments of which s1 is
00638      the last one */
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 /*    if (priority==SQ_HIGH_LINKING_PRIORITY) */
00658 /*      {   */
00659 /*        s2->amaxTan = s2->amaxTan * 0.50; */
00660 /*      } */
00661 
00662   return 0;
00663 }

int sqPause SEGMENTQUEUE   sq
 

Definition at line 1995 of file segmentqueue.c.

01996 {
01997   SEGMENT *as;          /* as = Active Segment */
01998   double startInc;      /* the incrediment at the time the pause command
01999                            was given */
02000   double startAcc;      /* the derivate of the inc at that time */
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     /* don't do anything, system is already paused */
02012     return 0;
02013 
02014   /* set paused flag */
02015   sq->paused=1;
02016 
02017   if ( sq->numSegments==0)
02018     {
02019       /* the queue is empty */
02020       sq->done = 1; /* propably redundant */
02021       return 0;
02022     }
02023 
02024   as=sq->queue+sq->start;
02025 
02026   if ( as->active==0 && as->initInc==0 )
02027     /* then this is the very first segment and we have not started yet.
02028        So let's set the done flag and return */
02029     {
02030       sq->done=1;
02031       return 0;
02032     }
02033 
02034   sq->feedAdjusting=0;  /* if we were adjusting the speed, ignore that too */
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; /* the planning will be done in this function */
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;          /* start allover, but skip the first initInc steps */
02050 
02051     }
02052   else if ( sq->n < as->m + 2 )
02053     {
02054       /* recalculate the last two dist values */
02055       npow1 = sq->n - 3;                /* sq->n-2-1 */
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;                /* sq->n-2-2 */
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;          /* start allover, but skip the first initInc steps */
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;          /* start allover, but skip the first initInc steps */
02084     }
02085   else
02086     {
02087       /* we are already decelerating, so it would be best to finish that
02088          first. After we're done with that, we can decelerate to zero */
02089 
02090       /* before messing the whole thing up, let's see if we are already
02091          decelerating to zero */
02092       if (as->plFinalInc==0)
02093         {
02094           /* Then we'll reach the end of the segment with a zero velocity.
02095              This means that we don't have to do anything but waiting at the
02096              end of the segment. This is basically the same thing that
02097              happens at the end of a step-motion. This is exactly what
02098              we will tell the system: that we're stepping, so that all of
02099              the extra things needed for a pause within a segment are skipped.
02100           */
02101           sq->paused=0;
02102           sq->stepping=1;
02103           return 0;
02104         }
02105       else
02106         {
02107 
02108           /* let's do a little trick: we copy the deceleration parameters
02109              of the current motion to the acceleration phase parameter
02110              fields in the current segment and calculate a new
02111              deceleration action from finalInc to 0. We'll decrease sq->n
02112              with a number such of steps, such that it will look like
02113              nothing has happened. sqRunCycle won't notice this, and will
02114              think it's (again) in phase 1. We know better.... */
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 ;        /* the cruising phase now becomes the
02125                               usual final step of a segment */
02126 
02127           /* find the finalInc */
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 }

int sqPlanSegment SEGMENTQUEUE   sq,
SEGMENT   s
[static]
 

Definition at line 385 of file segmentqueue.c.

Referenced by sqRunCycle().

00386 {
00387   /* variable declaration */
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   /* check is s is a valid pointer */
00404   if (s==0)
00405     {
00406       diagnostics("Error in sqPlanSegment()\n");
00407       return -1;
00408     }
00409 
00410 
00411   /* check if this segment is linked to its predecessor (which should never
00412      happen!) */
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   /* check if there are any segments linked to s, find the total length of the
00424      linked segments and find the finalInc of the last segment in the chain */
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   /* maxInc should never exceed the the system's maximum increment
00450      (maxV*cycleTime) */
00451   maxInc = min(maxInc, sq->maxV*sq->cycleTime);
00452 
00453   /* find the minimum value for the maximum tangential acceleration for this
00454      chain of segments beginning with s*/
00455   amaxTan = sqGiveMinAmaxTan(s);
00456   diagnosticsOff("AmaxTan in sqplansegment  = %d \n",(int)(ceil(amaxTan)));
00457   /* finalInc ( = initInc of nextSegment) should never be larger than
00458      the maxInc * feedOveride of this segment and the next segment */
00459 
00460   if ( cursor->finalInc!=0)     /* if true: this is not the last segment */
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   /* the first two steps and the last step are already defined */
00476   length = s->totLength - 2* s->plInitInc - s->plFinalInc;
00477 
00478 
00479   /* calculate minimal number of steps for the first phase (acc) */
00480   if (s->plInitInc == maxInc)
00481     s->m=0;
00482   else
00483     /* m should be always be two steps or more */
00484     s->m=max(2,ceil ( 3*fabs(maxInc-s->plInitInc)/(2*amaxTan*sq->ctPow2)));
00485 
00486   /* calulate minimal number of steps for the third phase (dec) */
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   /* calculate the minimal number of steps needed for the cruising phase */
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       /* true: there is no cruising phase */
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       /* recalculate m and q */
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   /* adjust maxInc a little */
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 /*    if ((s->m<=1) && (fabs(s->plInitInc - maxInc) > 0.3*amaxTan*sq->ctPow2)) */
00561 /*      { */
00562 /*        s->m=2; */
00563 /*        maxInc = (2*length - (s->m!=0) * (s->m-1) * s->initInc */
00564 /*              - (s->q!=0) * (s->q+1) * s->plFinalInc) \ */
00565 /*         / ( (s->m!=0) * (s->m+1) + 2 * s->p + (s->q!=0)*(s->q-1) ); */
00566 /*      } */
00567 /*    if ((s->q<=1) && (fabs(s->plFinalInc-maxInc)> 0.3 * amaxTan*sq->ctPow2))     */
00568 /*      { */
00569 /*        s->q=2; */
00570 /*        maxInc= (2*length - (s->m!=0)*(s->m-1)*s->plInitInc  */
00571 /*             - (s->q!=0) * (s->q+1) * s->plFinalInc) \ */
00572 /*         / ( (s->m!=0)*(s->m+1) + 2 * s->p + (s->q!=0)*(s->q-1) ); */
00573 /*      } */
00574   s->totNumPoints= s->m + s->p + s->q + 3;
00575   s->cruiseInc=maxInc;
00576 
00577   /* ok, we've found (sub)-optimal values for m, p and q. Let's go on
00578      with the actual planning */
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 };

int sqPreprocessSegment SEGMENTQUEUE   sq,
SEGMENT   newseg
 

Definition at line 864 of file segmentqueue.c.

Referenced by sqAddCircle(), and sqAddLine().

00865 {
00866 
00867   /* this is the stuff that's needs to be done for both linear and
00868      circular motions. Only sqAddLine and sqAddCircle should call this
00869      function.
00870   */
00871 
00872   double cornerInc;
00873 
00874   SEGMENT *prevseg;
00875   SEGMENT * cursor;
00876 
00877   /* check if segment queue has been initialized and if newseg is valid */
00878   if ( sq == 0 || sq->queue == 0 || newseg == 0 )
00879     {
00880       diagnostics("Error 1 in sqPreprocessSegment()\n");
00881       return -1;
00882     }
00883 
00884 
00885   /* if this is the first segment.... */
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   /* if not ... */
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         /* we can't change anything of the active segment */
00904         {
00905           newseg->initInc=prevseg->finalInc;
00906         }
00907       else
00908         {
00909 
00910           /* calculate the corner velocity for the corner between prevSegment
00911              and newseg */
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           /* if the maximum speeds of the new and the previous segment
00922           are the same and the corner speed is larger than this
00923           maximum speed, the segments can be linked */
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               /* the corner velocity shouldn't exceed the maximum
00941                  speeds of both segments */
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               /* is prevseg long enough to acc/dec from initInc to finalInc
00950                  (=cornerInc)? */
00951               cursor=prevseg;
00952               /* check if prevseg is linked to its predecessor and
00953                  if so, find the first segment in the linked
00954                  series of segments */
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                   /* check if prevseg needs to be linked to it's next
00971                      segment(s), which in this case only the newseg
00972                      can be. The feedoverride factor is set to the
00973                      maximum feedoverride to ensure correct linking
00974                      for every possible feed */
00975                   if ( -1 == sqForwardLinkSegment(sq,cursor,sq->maxFeedOverrideFactor) )
00976                     {
00977                       diagnostics("Error 4 in sqPreprocessSegment()\n");
00978                       return -1;
00979                     }
00980                 }
00981               else /* cursor->initInc > cornerInc */
00982                 /* check if the prevseg needs to be linked to its
00983                    predecessor(s). The feedoverride factor is set to
00984                    the maximum feedoverride to ensure correct linking
00985                    for every possible feed */
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 }

int sqResume SEGMENTQUEUE   sq
 

Definition at line 2150 of file segmentqueue.c.

02151 {
02152   SEGMENT *as;                  /* as = Active Segment */
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     /* we can't resume if the systems is not done yet with a step or pause
02164        action */
02165     {
02166       diagnosticsOff("Can't resume if not done with pause or step action\n");
02167       /* this is not a critical error, so we'll just ignore the command */
02168       return 0;
02169     }
02170 
02171   if ( sq->feedOverrideFactor == 0 )
02172     {
02173       /* we can't resume if the feed override factor is zero. To resume
02174          the user should set a new non-zero value for this factor first.
02175          This will immediately result in a resume action. */
02176       diagnostics("Can't resume if feed override is zero\n");
02177       /* not a critical error, so ignore it */
02178       return 0;
02179     }
02180 
02181   if ( sq->numSegments == 0)
02182     {
02183       /* there's not much to do */
02184       sq->paused = 0;
02185       return 0;
02186     }
02187 
02188   /* let's see if the length of the segment(chain) is large enough to
02189      accelerate from zero to finalInc */
02190   as=sq->queue+sq->start;
02191   cursor=as;
02192   /* first find the last segment in the chain */
02193   while ( cursor->nextSegment!=0 && cursor->nextSegment->linkedToPrevSeg==1)
02194     cursor=cursor->nextSegment;
02195 
02196   /* keep linking successive segments to as until the chain is long
02197      enough */
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 }

int sqRunCycle SEGMENTQUEUE   sq
 

Definition at line 1376 of file segmentqueue.c.

01377 {
01378   SEGMENT *as;             /* to use instead of sq->queue[sq->start],
01379                               stands for Active Segment */
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; /* to speed up cubic calculations */
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       /* do nothing */
01404       return 0;
01405     }
01406   /* if buffer is empty give last point (i.e. do nothing) */
01407   if ( sq->numSegments==0 )
01408     {
01409       /* set the 'done' flag ..... */
01410       sq->done=1;
01411 
01412       /* check if currentID is the same as the ID of the last appended motion.
01413          The only case in which this will not be true is when the last motion
01414          has a zero length */
01415       if (sq->currentID != sq->lastAppMotionID )
01416         sq->currentID=  sq->lastAppMotionID;
01417       return 0;
01418     }
01419   as=sq->queue+sq->start;   /* much shorter ..... */
01420   if (as == 0 )
01421     {
01422       diagnostics("Panic: as = NULL in sqRunCycle\n");
01423       return -1;
01424     }
01425 
01426   if (as->active==0)
01427     /* we're about to start with a new segment */
01428     {
01429       if (-1 == sqPlanSegment(sq, as))
01430         {
01431           diagnostics("Error in sqRunCycle\n");
01432           return -1;
01433         }
01434       /* mark the whole chain as active */
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       /* reset base, cursor, offset and cumlength and n */
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   /* else: planning has been done before and the parameters are correctly
01459      initialized, unless someone deliberately changed planningDone to 1.
01460      Let's trust our user and not check for that here. */
01461 
01462   /* depending of in what phase of the motion we are, determine the new
01463      distance */
01464   if ( sq->n==1 || sq->n==2 )
01465     {
01466       sq->dist += as->plInitInc;
01467     }
01468   else if ( sq->n <= as->m +2 )
01469     /* acceleration phase */
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     /* cruising phase */
01481     {
01482       sq->dist += as->cruiseInc;
01483     }
01484   else if ( sq->n <= as->m + as->p + as->q +2 )
01485     /* deceleration phase */
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     /* last step */
01498     {
01499       sq->dist+= as->plFinalInc;
01500     }
01501   else
01502     /* we have a problem, because this should never happen */
01503     {
01504       diagnostics("Error in sqRunCycle\n");
01505       return -1;
01506     }
01507 
01508   /* transform the dist scalar into a XYZ triplet */
01509   if (as->nextSegment !=0 && ( as->nextSegment->linkedToPrevSeg ==1 ||
01510                                sq->paused == 1))
01511     /* the active segment is the first segment of a chain */
01512     /* the sq->paused == 1 test is added to make sure that if a pause
01513        command is given just before the end of the segment, that the
01514        following segment is used to finish decelerating to zero */
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       /* set currentID */
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     /* the active segment has no other segments linked to it, which makes
01540        things much easier... */
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           /* remove all segments preceding the current segment */
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;         /* mark the first segment of the chain
01625                                    as not active */
01626 
01627           /* determine how many segments are linked to as */
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           /* find the minimum of the amax's of the segments in the chain */
01637           amaxTan=sqGiveMinAmaxTan(as);
01638 
01639           done=0;
01640           /* keep linking segments until the chain is long enough */
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         /* we are at the end of the segment, but shouldn't go on
01679            with the next one */
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           /* end of segment reached */
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;   /* we just removed some segments ... */
01704           if ( sq->numSegments < 0 )
01705             {
01706               diagnostics("Panic: sq->numSegments <0  in sqRunCycle\n");
01707               return -1;
01708             }
01709 
01710         }
01711     }
01712 
01713   /* for debugging */
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 }

int sqSetCycleTime SEGMENTQUEUE   sq,
double    secs
 

Definition at line 1073 of file segmentqueue.c.

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 };

int sqSetFeed SEGMENTQUEUE   sq,
double    feed
 

Definition at line 1153 of file segmentqueue.c.

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 }

int sqSetFeedOverride SEGMENTQUEUE   sq,
double    factor
 

Definition at line 1741 of file segmentqueue.c.

01742 {
01743 
01744   SEGMENT *as, *cursor;   /* as = Active Segment */
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   /* if fo is out of the valid range: clamp it */
01759   if ( fo < 0 )
01760     fo=0;
01761   else if ( fo > sq->maxFeedOverrideFactor )
01762     fo=sq->maxFeedOverrideFactor;
01763 
01764   if ( sq->feedOverrideFactor==fo )
01765     /* don't do anything, just return */
01766     return 0;
01767 
01768   if ( fo == 0 )
01769     {
01770       /* then this is actually a pause action */
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       /* the queue is empty */
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           /* If the previous feed override factor equals zero, then the
01797              pause action was actually done by setting the feed
01798              override to zero */
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           /* else: don't do anything else*/
01811           sq->feedOverrideFactor=fo;
01812           return 0;
01813         }
01814     }
01815 
01816   sq->feedOverrideFactor=fo;
01817   if ( as->active==0 )
01818     {
01819       /* the previous segment has just been finished. as still needs to
01820          be planned. So: don't do anything */
01821     }
01822 
01823   else if ( sq->n < as->m + 2 || sq->feedAdjusting==1 )
01824     {
01825       /* we are accelerating to (macInc * 'previous fo'). We need to adjust
01826          this phase in order get to the desired cruising feed */
01827 
01828       if ( sq->feedAdjusting!=1 && as->p==0 && as->maxInc*fo > as->cruiseInc )
01829         /* the the segment is too short to reach the current maxInc and it
01830            will be too short too to reach the new feed */
01831         return 0;
01832 
01833       if (sq->feedAdjusting==1)
01834         {
01835           /* copy the phase 3 params to the phase 1 params, since these will
01836              be used to find estimates for the current velocity and
01837              acceleration */
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       /* recalculate the last two dist values to find startInc and to use
01847          for making an estimation of startAcc */
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;            /* sq->n-2-1 */
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;            /* sq->n-2-2 */
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;          /* start all over, but skip the first initInc steps */
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       /* when the desired feed is reached, some things off this segment
01901          will have to be recalculated, which is done by runCycle. By setting
01902          this flag, runCycle will know that it needs to do this
01903       */
01904       sq->feedAdjusting=1;
01905 
01906     }
01907   else if ( sq->n < as->m + as->p + 2 )
01908     {
01909 
01910     /* change the active segment such that it looks like we are starting
01911        with a new segment */
01912 
01913       startInc=as->cruiseInc;
01914 
01915       /* delete all previous segments */
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;     /* mark the first segment of the chain
01963                            as not active */
01964 
01965       /* determine how many segments are linked to as */
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       /* keep linking successive segments to as until the chain is
01976          long enough */
01977       if ( -1 == sqForwardLinkSegment(sq,as,sq->feedOverrideFactor))
01978         {
01979           diagnostics("Error in sqSetFeedOverride\n");
01980           return -1;
01981         }
01982     }
01983   else
01984     {
01985       /* we are already decelerating, which is in most cases
01986          necessary.  Therefore, let's not interrupt this and finish
01987          the current segment first. The new segment will be planned
01988          with the new feedOverrideFactor.*/
01989     }
01990 
01991   return 0;
01992 }

int sqSetMaxAcc SEGMENTQUEUE   sq,
double    amax
 

Definition at line 1051 of file segmentqueue.c.

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 };

int sqSetMaxFeedOverride SEGMENTQUEUE   sq,
double    mfo
 

Definition at line 1086 of file segmentqueue.c.

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 }

int sqSetPos SEGMENTQUEUE   sq,
EmcPose    pos
 

Definition at line 1098 of file segmentqueue.c.

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 }

int sqSetVmax SEGMENTQUEUE   sq,
double    vmax
 

Definition at line 1062 of file segmentqueue.c.

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 };

int sqStep SEGMENTQUEUE   sq
 

Definition at line 2246 of file segmentqueue.c.

02247 {
02248   SEGMENT *as;                  /* as = Active Segment */
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     /* step should only be used when system is paused and waiting... */
02257     {
02258       diagnostics("Stepping can only be done when system is paused and waiting\n");
02259       /* not a critical error, let's ignore it */
02260       return 0;;
02261     }
02262 
02263   if ( sq->feedOverrideFactor == 0 )
02264     {
02265       /* we can't step if the feed override factor is zero. To step
02266          the user should set a new non-zero value for this factor first.
02267          This will immediately result in a resume action. */
02268       diagnostics("Can't resume if feed override is zero\n");
02269       /* not a critical error, so ignore it */
02270       return 0;
02271     }
02272 
02273 
02274   /* make finalInc of the current segment 0, set sq->stepping and resume.
02275      This means that after this is segment is done, it will
02276      wait for the next step or resume command */
02277 
02278   as=sq->queue+sq->start;
02279   as->finalInc=0;
02280 
02281   /* if the next segment is linked to the current one, unlink it */
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 }

int sqTrashQueue SEGMENTQUEUE   sq
 

Definition at line 1140 of file segmentqueue.c.

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 };


Variable Documentation

EmcPose newAcc [static]
 

Definition at line 134 of file segmentqueue.c.

EmcPose newVel [static]
 

Definition at line 134 of file segmentqueue.c.

double oldDist [static]
 

Definition at line 135 of file segmentqueue.c.

EmcPose oldPos [static]
 

Definition at line 134 of file segmentqueue.c.

EmcPose oldVel [static]
 

Definition at line 134 of file segmentqueue.c.


Generated on Sun Dec 2 15:28:25 2001 for EMC by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001