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 #ifndef NO_STDIO_SUPPORT
00050 #ifndef UNDER_CE
00051 #include <stdio.h>
00052 #endif
00053 #include "rcs_prnt.hh"
00054 #endif
00055
00056
00057
00058
00059 #include <math.h>
00060 #include "posemath.h"
00061 #include "emcpos.h"
00062 #include "tc.h"
00063
00064 #if !defined(rtlinux) && !defined(rtai)
00065 #include "rcsvers.hh"
00066 #endif
00067
00068
00069 #ifndef __GNUC__
00070 #ifndef __attribute__
00071 #define __attribute__(x)
00072 #endif
00073 #endif
00074
00075 static char __attribute__((unused)) ident[] = "$Id: tc.c,v 1.9 2001/08/17 22:05:41 proctor Exp $";
00076
00077
00078
00079 static unsigned char doutbyte = 0;
00080 extern void extMotDout(unsigned char byte);
00081
00082 #define TC_VEL_EPSILON 0.0001
00083 #define TC_SCALE_EPSILON 0.0001
00084
00085 int tcInit(TC_STRUCT *tc)
00086 {
00087 PmPose zero;
00088
00089 if (0 == tc)
00090 {
00091 return -1;
00092 }
00093
00094 tc->cycleTime = 0.0;
00095 tc->targetPos = 0.0;
00096 tc->vMax = 0.0;
00097 tc->vScale = 1.0;
00098 tc->aMax = 0.0;
00099 tc->preVMax = 0.0;
00100 tc->preAMax = 0.0;
00101 tc->vLimit = 0.0;
00102 tc->toGo = 0.0;
00103 tc->currentPos = 0.0;
00104 tc->currentVel = 0.0;
00105 tc->currentAccel = 0.0;
00106 tc->tcFlag = TC_IS_UNSET;
00107 tc->type = TC_LINEAR;
00108 tc->id = 0;
00109 tc->termCond = TC_TERM_COND_BLEND;
00110
00111 tc->tmag=0.0;
00112 tc->abc_mag=0.0;
00113 tc->tvMax=0.0;
00114 tc->taMax=0.0;
00115 tc->abc_vMax=0.0;
00116 tc->abc_aMax=0.0;
00117 tc->unitCart.x = tc->unitCart.y = tc->unitCart.z = 0.0;
00118 zero.tran.x = zero.tran.y = zero.tran.z = 0.0;
00119 zero.rot.s=1.0;
00120 zero.rot.x = zero.rot.y = zero.rot.z = 0.0;
00121
00122 pmLineInit(&tc->line, zero, zero);
00123 pmLineInit(&tc->line_abc, zero, zero);
00124
00125
00126 tc->douts = 0;
00127 tc->doutstarts = 0;
00128 tc->doutends = 0;
00129
00130 return 0;
00131 }
00132
00133 int tcSetCycleTime(TC_STRUCT *tc, double secs)
00134 {
00135 if (secs <= 0.0 ||
00136 0 == tc)
00137 {
00138 return -1;
00139 }
00140
00141 tc->cycleTime = secs;
00142
00143 return 0;
00144 }
00145
00146 int tcSetLine(TC_STRUCT *tc, PmLine line, PmLine line_abc)
00147 {
00148 double tmag,abc_mag;
00149
00150 if (0 == tc)
00151 {
00152 return -1;
00153 }
00154
00155 tc->line = line;
00156 tc->line_abc = line_abc;
00157
00158
00159
00160 pmCartCartDisp(line.end.tran, line.start.tran, &tmag);
00161 pmCartCartDisp(line_abc.end.tran, line_abc.start.tran, &abc_mag);
00162
00163 tc->abc_mag = abc_mag;
00164 tc->tmag = tmag;
00165
00166 if(tc->abc_aMax <= 0.0 && tc->taMax > 0.0)
00167 {
00168 tc->abc_aMax = tc->taMax;
00169 }
00170
00171 if(tc->abc_vMax <= 0.0 && tc->tvMax > 0.0)
00172 {
00173 tc->abc_vMax = tc->tvMax;
00174 }
00175
00176 if(tc->tmag < 1e-6)
00177 {
00178 tc->aMax = tc->abc_aMax;
00179 tc->vMax = tc->abc_vMax;
00180 tc->targetPos = abc_mag;
00181 }
00182 else
00183 {
00184 if(0)
00185 #if 0
00186 if(tc->abc_mag > 1e-6)
00187 #endif
00188 {
00189 if(tc->abc_aMax * tmag/abc_mag < tc->taMax)
00190 {
00191 tc->aMax = tc->abc_aMax *tmag/abc_mag;
00192 }
00193 else
00194 {
00195 tc->aMax = tc->taMax;
00196 }
00197 if(tc->abc_vMax * tmag/abc_mag < tc->tvMax)
00198 {
00199 tc->vMax = tc->abc_vMax * tmag /abc_mag;
00200 }
00201 else
00202 {
00203 tc->vMax = tc->tvMax;
00204 }
00205 }
00206 else
00207 {
00208 tc->aMax = tc->taMax;
00209 tc->vMax = tc->tvMax;
00210 }
00211 tc->targetPos = tmag;
00212 }
00213
00214 tc->currentPos = 0.0;
00215 tc->type = TC_LINEAR;
00216 return 0;
00217 }
00218
00219 int tcSetCircle(TC_STRUCT *tc, PmCircle circle, PmLine line_abc)
00220 {
00221 if (0 == tc)
00222 {
00223 return -1;
00224 }
00225
00226 tc->circle = circle;
00227 tc->line_abc = line_abc;
00228
00229
00230 tc->tmag = tc->targetPos = circle.angle * circle.radius;
00231
00232 tc->currentPos = 0.0;
00233 tc->type = TC_CIRCULAR;
00234
00235 tc->aMax = tc->taMax;
00236 tc->vMax = tc->tvMax;
00237
00238 pmCartCartDisp(line_abc.end.tran, line_abc.start.tran, &tc->abc_mag);
00239
00240 return 0;
00241 }
00242
00243 int tcSetTVmax(TC_STRUCT *tc, double _vMax)
00244 {
00245 if (_vMax < 0.0 ||
00246 0 == tc)
00247 {
00248 return -1;
00249 }
00250
00251 tc->tvMax = _vMax;
00252
00253 return 0;
00254 }
00255
00256 int tcSetRVmax(TC_STRUCT *tc, double _Rvmax)
00257 {
00258 if (_Rvmax < 0.0 ||
00259 0 == tc)
00260 {
00261 return -1;
00262 }
00263
00264 tc->abc_vMax = _Rvmax;
00265
00266 return 0;
00267 }
00268
00269 int tcSetRAmax(TC_STRUCT *tc, double _WDotMax)
00270 {
00271 if (_WDotMax < 0.0 ||
00272 0 == tc)
00273 {
00274 return -1;
00275 }
00276
00277 tc->abc_aMax = _WDotMax;
00278
00279 return 0;
00280 }
00281
00282 int tcSetVscale(TC_STRUCT *tc, double _vScale)
00283 {
00284 if (_vScale < 0.0 ||
00285 0 == tc)
00286 {
00287 return -1;
00288 }
00289
00290 tc->vScale = _vScale;
00291
00292 return 0;
00293 }
00294
00295 int tcSetTAmax(TC_STRUCT *tc, double _aMax)
00296 {
00297 if (_aMax <= 0.0 ||
00298 0 == tc)
00299 {
00300 return -1;
00301 }
00302
00303 tc->taMax = _aMax;
00304
00305 return 0;
00306 }
00307
00308 int tcSetPremax(TC_STRUCT *tc, double vMax, double aMax)
00309 {
00310 if (0 == tc)
00311 {
00312 return -1;
00313 }
00314
00315 tc->preVMax = vMax;
00316 tc->preAMax = aMax;
00317
00318 return 0;
00319 }
00320
00321 int tcSetVlimit(TC_STRUCT *tc, double vLimit)
00322 {
00323 if (0 == tc)
00324 {
00325 return -1;
00326 }
00327
00328 tc->vLimit = vLimit;
00329
00330 return 0;
00331 }
00332
00333 int tcSetId(TC_STRUCT *tc, int _id)
00334 {
00335 if (0 == tc)
00336 {
00337 return -1;
00338 }
00339
00340 tc->id = _id;
00341
00342 return 0;
00343 }
00344
00345 int tcGetId(TC_STRUCT *tc)
00346 {
00347 if (0 == tc)
00348 {
00349 return -1;
00350 }
00351
00352 return tc->id;
00353 }
00354
00355 int tcSetTermCond(TC_STRUCT *tc, int cond)
00356 {
00357 if (0 == tc)
00358 {
00359 return -1;
00360 }
00361
00362 if (cond != TC_TERM_COND_STOP &&
00363 cond != TC_TERM_COND_BLEND)
00364 {
00365 return -1;
00366 }
00367
00368 tc->termCond = cond;
00369
00370 return 0;
00371 }
00372
00373 int tcGetTermCond(TC_STRUCT *tc)
00374 {
00375 if (0 == tc)
00376 {
00377 return -1;
00378 }
00379
00380 return tc->termCond;
00381 }
00382
00383 int tcRunCycle(TC_STRUCT *tc)
00384 {
00385 double newPos;
00386 double newVel;
00387 double newAccel;
00388 double discr;
00389 int isScaleDecel;
00390 int oldTcFlag;
00391
00392 if (0 == tc) {
00393 return -1;
00394 }
00395
00396
00397
00398 oldTcFlag = tc->tcFlag;
00399
00400 if (tc->tcFlag == TC_IS_DONE) {
00401 tc->currentVel = 0.0;
00402 tc->currentAccel = 0.0;
00403 return 0;
00404 }
00405
00406 tc->toGo = tc->targetPos - tc->currentPos;
00407
00408 if (tc->aMax <= 0.0 || tc->vMax <= 0.0 || tc->cycleTime <= 0.0) {
00409 return -1;
00410 }
00411
00412
00413 discr = 0.5 * tc->cycleTime * tc->currentVel - tc->toGo;
00414 if (discr > 0.0) {
00415 newVel = 0.0;
00416 }
00417 else {
00418 discr = 0.25 * tc->cycleTime * tc->cycleTime - 2.0 / tc->aMax * discr;
00419 newVel = - 0.5 * tc->aMax * tc->cycleTime + tc->aMax * sqrt(discr);
00420 }
00421
00422 if (tc->tcFlag == TC_IS_UNSET) {
00423
00424 if (tc->douts) {
00425 doutbyte |= (tc->douts & tc->doutstarts);
00426 doutbyte &= (~tc->douts | tc->doutstarts);
00427 extMotDout(doutbyte);
00428 }
00429 }
00430
00431 if (newVel <= 0.0) {
00432 newVel = 0.0;
00433 newAccel = 0;
00434 newPos = tc->targetPos;
00435 tc->tcFlag = TC_IS_DONE;
00436
00437 if (tc->douts) {
00438 doutbyte |= (tc->douts & tc->doutends);
00439 doutbyte &= (~tc->douts | tc->doutends);
00440 extMotDout(doutbyte);
00441 }
00442 }
00443 else {
00444
00445
00446
00447
00448
00449
00450 isScaleDecel = 0;
00451 if (newVel > (tc->vMax - tc->preVMax) * tc->vScale) {
00452 newVel = (tc->vMax - tc->preVMax) * tc->vScale;
00453 isScaleDecel = 1;
00454 }
00455
00456
00457 if (newVel > tc->vLimit) {
00458 newVel = tc->vLimit;
00459 }
00460
00461 if (tc->type == TC_CIRCULAR) {
00462 if (newVel > pmSqrt(tc->aMax*tc->circle.radius)) {
00463 newVel = pmSqrt(tc->aMax*tc->circle.radius);
00464 }
00465 }
00466
00467
00468 newAccel = (newVel - tc->currentVel) / tc->cycleTime;
00469
00470
00471
00472
00473 if (newAccel > 0.0) {
00474 if (newAccel > tc->aMax - tc->preAMax) {
00475 newAccel = tc->aMax - tc->preAMax;
00476
00477
00478
00479 if (newAccel < 0.0) {
00480 newAccel = 0.0;
00481 }
00482 newVel = tc->currentVel + newAccel * tc->cycleTime;
00483 }
00484 }
00485 else {
00486 if (newAccel < -tc->aMax) {
00487 newAccel = -tc->aMax;
00488 newVel = tc->currentVel + newAccel * tc->cycleTime;
00489 }
00490 }
00491
00492 #ifdef A_CHANGE_MAX
00493 if (newAccel > A_CHANGE_MAX*tc->cycleTime+tc->currentAccel) {
00494 newAccel = A_CHANGE_MAX*tc->cycleTime + tc->currentAccel;
00495 newVel = tc->currentVel + newAccel * tc->cycleTime;
00496 }
00497 else if(newAccel < -A_CHANGE_MAX*tc->cycleTime+tc->currentAccel) {
00498 newAccel = -A_CHANGE_MAX*tc->cycleTime + tc->currentAccel;
00499 newVel = tc->currentVel + newAccel * tc->cycleTime;
00500 }
00501 #endif
00502
00503 tc->toGo = (newVel + tc->currentVel) * 0.5 * tc->cycleTime;
00504 newPos = tc->currentPos + tc->toGo;
00505
00506 if (newAccel < 0.0) {
00507 if (isScaleDecel && oldTcFlag != TC_IS_DECEL) {
00508
00509
00510
00511 tc->tcFlag = TC_IS_ACCEL;
00512 }
00513 else {
00514 tc->tcFlag = TC_IS_DECEL;
00515 }
00516 }
00517 else if (newAccel > 0.0) {
00518 tc->tcFlag = TC_IS_ACCEL;
00519 }
00520 else if (newVel < TC_VEL_EPSILON &&
00521 tc->vScale < TC_SCALE_EPSILON) {
00522 tc->tcFlag = TC_IS_PAUSED;
00523 }
00524 else {
00525 tc->tcFlag = TC_IS_CONST;
00526 }
00527 }
00528
00529 tc->currentPos = newPos;
00530 tc->currentVel = newVel;
00531 tc->currentAccel = newAccel;
00532
00533 return 0;
00534 }
00535
00536 EmcPose tcGetPos(TC_STRUCT *tc)
00537 {
00538 EmcPose v;
00539 PmPose v1;
00540 PmPose v2;
00541
00542 if (0 == tc)
00543 {
00544 v1.tran.x = v1.tran.y = v1.tran.z = 0.0;
00545 v1.rot.s = 1.0;
00546 v1.rot.x = v1.rot.y = v1.rot.z = 0.0;
00547 return v;
00548 }
00549
00550
00551 if (tc->type == TC_LINEAR)
00552 {
00553 pmLinePoint(&tc->line, tc->currentPos, &v1);
00554 }
00555 else if (tc->type == TC_CIRCULAR)
00556 {
00557 pmCirclePoint(&tc->circle, tc->currentPos / tc->circle.radius, &v1);
00558 }
00559 else
00560 {
00561 v1.tran.x = v1.tran.y = v1.tran.z = 0.0;
00562 v1.rot.s = 1.0;
00563 v1.rot.x = v1.rot.y = v1.rot.z = 0.0;
00564 }
00565 v.tran = v1.tran;
00566 if(tc->abc_mag > 1e-6)
00567 {
00568 if(tc->tmag > 1e-6 )
00569 {
00570 pmLinePoint(&tc->line_abc,(tc->currentPos *tc->abc_mag /tc->tmag),&v2);
00571 v.a = v2.tran.x;
00572 v.b = v2.tran.y;
00573 v.c = v2.tran.z;
00574 }
00575 else
00576 {
00577 pmLinePoint(&tc->line_abc,tc->currentPos,&v2);
00578 v.a = v2.tran.x;
00579 v.b = v2.tran.y;
00580 v.c = v2.tran.z;
00581 }
00582 }
00583 else
00584 {
00585 v.a = v.b = v.c = 0.0;
00586 }
00587
00588 return v;
00589 }
00590
00591 EmcPose tcGetGoalPos(TC_STRUCT *tc)
00592 {
00593 PmPose v;
00594 EmcPose ev;
00595
00596 if (0 == tc)
00597 {
00598 ev.tran.x = ev.tran.y = ev.tran.z = 0.0;
00599 ev.a = ev.b = ev.c = 0.0;
00600 return ev;
00601 }
00602
00603 if (tc->type == TC_LINEAR)
00604 {
00605 v = tc->line.end;
00606 }
00607 else if (tc->type == TC_CIRCULAR)
00608 {
00609
00610
00611
00612
00613
00614
00615 pmCirclePoint(&tc->circle, tc->circle.angle, &v);
00616 }
00617 else
00618 {
00619 v.tran.x = v.tran.y = v.tran.z = 0.0;
00620 v.rot.s = 1.0;
00621 v.rot.x = v.rot.y = v.rot.z = 0.0;
00622 }
00623
00624 ev.tran = v.tran;
00625 ev.a = tc->line_abc.end.tran.x;
00626 ev.b = tc->line_abc.end.tran.y;
00627 ev.c = tc->line_abc.end.tran.z;
00628 return ev;
00629 }
00630
00631 double tcGetVel(TC_STRUCT *tc)
00632 {
00633 if (0 == tc)
00634 {
00635 return 0.0;
00636 }
00637
00638 return tc->currentVel;
00639 }
00640
00641 double tcGetAccel(TC_STRUCT *tc)
00642 {
00643 if (0 == tc)
00644 {
00645 return 0.0;
00646 }
00647
00648 return tc->currentAccel;
00649 }
00650
00651 int tcGetTcFlag(TC_STRUCT *tc)
00652 {
00653 if (0 == tc)
00654 {
00655 return TC_IS_UNSET;
00656 }
00657
00658 return tc->tcFlag;
00659 }
00660
00661 int tcIsDone(TC_STRUCT *tc)
00662 {
00663 if (0 == tc)
00664 {
00665 return 0;
00666 }
00667
00668 return (tc->tcFlag == TC_IS_DONE);
00669 }
00670
00671 int tcIsAccel(TC_STRUCT *tc)
00672 {
00673 if (0 == tc)
00674 {
00675 return 0;
00676 }
00677
00678 return (tc->tcFlag == TC_IS_ACCEL);
00679 }
00680
00681 int tcIsConst(TC_STRUCT *tc)
00682 {
00683 if (0 == tc)
00684 {
00685 return 0;
00686 }
00687
00688 return (tc->tcFlag == TC_IS_CONST);
00689 }
00690
00691 int tcIsDecel(TC_STRUCT *tc)
00692 {
00693 if (0 == tc)
00694 {
00695 return 0;
00696 }
00697
00698 return (tc->tcFlag == TC_IS_DECEL);
00699 }
00700
00701 int tcIsPaused(TC_STRUCT *tc)
00702 {
00703 if (0 == tc)
00704 {
00705 return 0;
00706 }
00707
00708 return (tc->tcFlag == TC_IS_PAUSED);
00709 }
00710
00711 void tcPrint(TC_STRUCT *tc)
00712 {
00713 #ifndef NO_STDIO_SUPPORT
00714 if (0 == tc)
00715 {
00716 rcs_print("(null)\n");
00717 return;
00718 }
00719
00720 rcs_print("cycleTime: %f\n", tc->cycleTime);
00721 rcs_print("targetPos: %f\n", tc->targetPos);
00722 rcs_print("vMax: %f\n", tc->vMax);
00723 rcs_print("vLimit: %f\n", tc->vLimit);
00724 rcs_print("vScale %f\n", tc->vScale);
00725 rcs_print("aMax: %f\n", tc->aMax);
00726 rcs_print("toGo: %f\n", tc->toGo);
00727 rcs_print("currentPos: %f\n", tc->currentPos);
00728 rcs_print("currentVel: %f\n", tc->currentVel);
00729 rcs_print("currentAccel: %f\n", tc->currentAccel);
00730 rcs_print("tcFlag: %s\n", tc->tcFlag == TC_IS_UNSET ? "UNSET" :
00731 tc->tcFlag == TC_IS_DONE ? "DONE" :
00732 tc->tcFlag == TC_IS_ACCEL ? "ACCEL" :
00733 tc->tcFlag == TC_IS_CONST ? "CONST" :
00734 tc->tcFlag == TC_IS_DECEL ? "DECEL" :
00735 tc->tcFlag == TC_IS_PAUSED ? "PAUSED" : "?");
00736 rcs_print("type: %s\n", tc->type == TC_LINEAR ? "LINEAR" :
00737 tc->type == TC_CIRCULAR ? "CIRCULAR" : "?");
00738 rcs_print("id: %d\n", tc->id);
00739 #endif
00740 }
00741
00742
00743
00744 int tcqCreate(TC_QUEUE_STRUCT *tcq, int _size, TC_STRUCT *tcSpace)
00745 {
00746 if (_size <= 0 ||
00747 0 == tcq)
00748 {
00749 return -1;
00750 }
00751 else
00752 {
00753 tcq->queue = tcSpace;
00754 tcq->size = _size;
00755 tcq->_len = 0;
00756 tcq->start = tcq->end = 0;
00757 tcq->allFull = 0;
00758
00759 if (0 == tcq->queue)
00760 {
00761 return -1;
00762 }
00763 return 0;
00764 }
00765 }
00766
00767 int tcqDelete(TC_QUEUE_STRUCT *tcq)
00768 {
00769 if (0 != tcq &&
00770 0 != tcq->queue)
00771 {
00772
00773 tcq->queue = 0;
00774 }
00775
00776 return 0;
00777 }
00778
00779 int tcqInit(TC_QUEUE_STRUCT *tcq)
00780 {
00781 if (0 == tcq)
00782 {
00783 return -1;
00784 }
00785
00786 tcq->_len = 0;
00787 tcq->start = tcq->end = 0;
00788 tcq->allFull = 0;
00789
00790 return 0;
00791 }
00792
00793
00794 int tcqPut(TC_QUEUE_STRUCT *tcq, TC_STRUCT tc)
00795 {
00796
00797 if (0 == tcq ||
00798 0 == tcq->queue)
00799 {
00800 return -1;
00801 }
00802
00803
00804 if (tcq->allFull)
00805 {
00806 return -1;
00807 }
00808
00809
00810 tcq->queue[tcq->end] = tc;
00811 tcq->_len++;
00812
00813
00814 tcq->end = (tcq->end + 1) % tcq->size;
00815
00816
00817 if (tcq->end == tcq->start)
00818 {
00819 tcq->allFull = 1;
00820 }
00821
00822 return 0;
00823 }
00824
00825
00826 TC_STRUCT tcqGet(TC_QUEUE_STRUCT *tcq, int *status)
00827 {
00828 TC_STRUCT tc;
00829
00830 if ((0 == tcq) ||
00831 (0 == tcq->queue) ||
00832 ((tcq->start == tcq->end) && ! tcq->allFull))
00833 {
00834 if (0 != status)
00835 {
00836 *status = -1;
00837 }
00838 tc.cycleTime=0;
00839 tc.targetPos=0;
00840 tc.vMax=0;
00841 tc.vScale=0;
00842 tc.aMax=0;
00843 tc.preVMax=0;
00844 tc.preAMax=0;
00845 tc.vLimit=0;
00846 tc.toGo=0;
00847 tc.currentPos=0;
00848 tc.currentVel=0;
00849 tc.currentAccel=0;
00850 tc.tcFlag=0;
00851 tc.type=0;
00852 tc.id=0;
00853 tc.termCond=0;
00854 return tc;
00855 }
00856
00857
00858 if (0 != status)
00859 {
00860 *status = 0;
00861 }
00862 tc = tcq->queue[tcq->start];
00863
00864
00865 tcq->start = (tcq->start + 1) % tcq->size;
00866 tcq->allFull = 0;
00867 tcq->_len--;
00868
00869 return tc;
00870 }
00871
00872
00873 int tcqRemove(TC_QUEUE_STRUCT *tcq, int n)
00874 {
00875 if (n <= 0)
00876 {
00877 return 0;
00878 }
00879
00880 if ((0 == tcq) ||
00881 (0 == tcq->queue) ||
00882 ((tcq->start == tcq->end) && ! tcq->allFull) ||
00883 (n > tcq->_len))
00884 {
00885 return -1;
00886 }
00887
00888
00889 tcq->start = (tcq->start + n) % tcq->size;
00890 tcq->allFull = 0;
00891 tcq->_len -= n;
00892
00893 return 0;
00894 }
00895
00896
00897 int tcqLen(TC_QUEUE_STRUCT *tcq)
00898 {
00899 if (0 == tcq)
00900 {
00901 return -1;
00902 }
00903
00904 return tcq->_len;
00905 }
00906
00907
00908 TC_STRUCT * tcqItem(TC_QUEUE_STRUCT *tcq, int n, int *status)
00909 {
00910 if ((0 == tcq) ||
00911 (0 == tcq->queue) ||
00912 (n < 0) ||
00913 (n >= tcq->_len))
00914 {
00915 if (0 != status)
00916 {
00917 *status = -1;
00918 }
00919 return (TC_STRUCT *) 0;
00920 }
00921
00922 if (0 != status)
00923 {
00924 *status = 0;
00925 }
00926 return &(tcq->queue[(tcq->start + n) % tcq->size]);
00927 }
00928
00929
00930 TC_STRUCT * tcqLast(TC_QUEUE_STRUCT *tcq, int *status)
00931 {
00932 if (0 == tcq)
00933 {
00934 return (TC_STRUCT *) 0;
00935 }
00936
00937 return tcqItem(tcq, tcq->_len - 1, status);
00938 }
00939
00940
00941 #define TC_QUEUE_MARGIN 10
00942 int tcqFull(TC_QUEUE_STRUCT *tcq)
00943 {
00944 if (0 == tcq)
00945 {
00946 return 1;
00947 }
00948
00949
00950
00951
00952
00953 if (tcq->size <= TC_QUEUE_MARGIN)
00954 {
00955
00956 return tcq->allFull;
00957 }
00958
00959 if (tcq->_len >= tcq->size - TC_QUEUE_MARGIN)
00960 {
00961
00962 return 1;
00963 }
00964
00965
00966 return 0;
00967 }
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 double tcRunPreCycle(const TC_STRUCT *tc)
00980 {
00981 TC_STRUCT preTc;
00982 double ratio;
00983
00984 if (0 == tc)
00985 {
00986 return -1;
00987 }
00988
00989 if (tc->targetPos <= 0.0)
00990 {
00991
00992 ratio = 1.0;
00993 }
00994 else
00995 {
00996 preTc = *tc;
00997 tcRunCycle(&preTc);
00998 ratio = preTc.currentPos / preTc.targetPos;
00999 }
01000
01001 if (preTc.tcFlag == TC_IS_DONE)
01002 {
01003
01004 return 1.0;
01005 }
01006
01007 return ratio;
01008 }
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022 int tcForceCycle(TC_STRUCT *tc, double ratio)
01023 {
01024 double newPos;
01025 double newToGo;
01026 double newVel;
01027 double newAccel;
01028 int newTcFlag;
01029
01030 if (0 == tc)
01031 {
01032 return -1;
01033 }
01034
01035 newPos = ratio * tc->targetPos;
01036 newToGo = newPos - tc->currentPos;
01037
01038 if (ratio >= 1.0)
01039 {
01040 newVel = 0.0;
01041 newAccel = 0.0;
01042 newTcFlag = TC_IS_DONE;
01043 }
01044 else
01045 {
01046 newVel = (newPos - tc->currentPos) / tc->cycleTime;
01047 newAccel = (newVel - tc->currentVel) / tc->cycleTime;
01048 if (newAccel > 0.0)
01049 {
01050 newTcFlag = TC_IS_ACCEL;
01051 }
01052 else if (newAccel < 0.0)
01053 {
01054 newTcFlag = TC_IS_DECEL;
01055 }
01056 else
01057 {
01058 newTcFlag = TC_IS_CONST;
01059 }
01060 }
01061
01062 tc->currentPos = newPos;
01063 tc->toGo = newToGo;
01064 tc->currentVel = newVel;
01065 tc->currentAccel = newAccel;
01066 tc->tcFlag = newTcFlag;
01067
01068 return 0;
01069 }
01070
01071
01072 PmCartesian tcGetUnitCart(TC_STRUCT *tc)
01073 {
01074 PmPose currentPose;
01075 PmCartesian radialCart;
01076 static const PmCartesian fake= {1.0,0.0,0.0};
01077
01078 if(tc->type == TC_LINEAR)
01079 {
01080 pmCartCartSub(tc->line.end.tran,tc->line.start.tran,&tc->unitCart);
01081 #ifdef USE_PM_CART_NORM
01082 pmCartNorm(tc->unitCart,&tc->unitCart);
01083 #else
01084 pmCartUnit(tc->unitCart,&tc->unitCart);
01085 #endif
01086 return(tc->unitCart);
01087 }
01088 else if(tc->type == TC_CIRCULAR)
01089 {
01090 pmCirclePoint(&tc->circle,tc->currentPos,¤tPose);
01091 pmCartCartSub(currentPose.tran, tc->circle.center, &radialCart);
01092 pmCartCartCross(tc->circle.normal, radialCart,&tc->unitCart);
01093 #ifdef USE_PM_CART_NORM
01094 pmCartNorm(tc->unitCart,&tc->unitCart);
01095 #else
01096 pmCartUnit(tc->unitCart,&tc->unitCart);
01097 #endif
01098 return(tc->unitCart);
01099 }
01100
01101 return fake;
01102 }
01103
01104 int tcSetDout(TC_STRUCT *tc, unsigned char douts, unsigned char starts, unsigned char ends)
01105 {
01106 if (0 == tc) {
01107 return -1;
01108 }
01109
01110 tc->douts = douts;
01111 tc->doutstarts = starts;
01112 tc->doutends = ends;
01113
01114 return 0;
01115 }
01116
01117