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

genhexkins.c

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------
00002   genhexkins.c
00003   Written by R. Brian Register
00004   1999
00005   -----------------------------------------------------------------------------
00006   These are the forward and inverse kinematic functions for a class of
00007   machines referred to as "Stewart Platforms".
00008 
00009   The functions are general enough to be configured for any platform
00010   configuration.  In the functions "kinematicsForward" and
00011   "kinematicsInverse" are arrays "a[i]" and "b[i]".  The values stored
00012   in these arrays correspond to the positions of the ends of the i'th
00013   strut. The value stored in a[i] is the position of the end of the i'th
00014   strut attatched to the platform, in platform coordinates. The value
00015   stored in b[i] is the position of the end of the i'th strut attached
00016   to the base, in base (world) coordinates.
00017 
00018   To have these functions solve the kinematics of a particular
00019   platform configuration, adjust the values stored in arrays "a[i]" and
00020   "b[i]".  The values stored in these arrays are defined in the header
00021   file genhex.h.  The kinematicsInverse function solves the inverse
00022   kinematics using a closed form algorithm.  The inverse kinematics
00023   problem is given the pose of the platform and returns the strut
00024   lengths. For this problem there is only one solution that is always
00025   returned correctly.
00026 
00027   The kinematicsForward function solves the forward kinematics using
00028   an iterative algorithm.  Due to the iterative nature of this algorithm
00029   the kinematicsForward function requires an initial value to begin the
00030   iterative routine and then converges to the "nearest" solution. The
00031   forward kinematics problem is given the strut lengths and returns the
00032   pose of the platform.  For this problem there arein multiple
00033   solutions.  The kinematicsForward function will return only one of
00034   these solutions which will be the solution nearest to the initial
00035   value given.  It is possible that there are no solutions "near" the
00036   given initial value and the iteration will not converge and no
00037   solution will be returned.  Assuming there is a solution "near" the
00038   initial value, the function will always return one correct solution
00039   out of the multiple possible solutions.
00040   -----------------------------------------------------------------------------*/
00041 
00042 /*
00043   Modification history:
00044 
00045   23-Aug-2001 FMP pulled out jacobianInverse(), jacobianForward(); added
00046   genhexSet,GetParams()
00047   15-May-2001  FMP added more to main debug; changed kinematicsType() to
00048   return KINEMATICS_BOTH
00049   16-Nov-2000 WPS change pmCartNorm to pmCartUnit
00050   6-Mar-2000  FMP added MAIN debug section
00051   22-Sep-1999 WPS removed unneccessary include directives not supported by CE
00052   */
00053 
00054 #include <math.h>
00055 #include "posemath.h"
00056 #include "genhexkins.h"
00057 #include "emcmot.h"             /* these decls, KINEMATICS_FORWARD_FLAGS */
00058 
00059 /******************************* MatInvert() ***************************/
00060 
00061 /*-----------------------------------------------------------------------------
00062  This is a function that inverts a 6x6 matrix.
00063 -----------------------------------------------------------------------------*/
00064 
00065 static int MatInvert(double J[][NUM_STRUTS], double InvJ[][NUM_STRUTS])
00066 {
00067   double JAug[NUM_STRUTS][12], m, temp;
00068   int j, k, n;
00069 
00070   /* This function determines the inverse of a 6x6 matrix using
00071      Gauss-Jordan elimination */
00072 
00073   /* Augment the Identity matrix to the Jacobian matrix */
00074 
00075   for (j=0; j<=5; ++j){
00076     for (k=0; k<=5; ++k){     /* Assign J matrix to first 6 columns of AugJ */
00077       JAug[j][k] = J[j][k];
00078     }
00079     for(k=6; k<=11; ++k){    /* Assign I matrix to last six columns of AugJ */
00080       if (k-6 == j){
00081         JAug[j][k]=1;
00082       }
00083       else{
00084         JAug[j][k]=0;
00085       }
00086     }
00087   }
00088 
00089   /* Perform Gauss elimination */
00090   for (k=0; k<=4; ++k){               /* Pivot        */
00091     if ((JAug[k][k]< 0.01) && (JAug[k][k] > -0.01)){
00092       for (j=k+1;j<=5; ++j){
00093         if ((JAug[j][k]>0.01) || (JAug[j][k]<-0.01)){
00094           for (n=0; n<=11;++n){
00095             temp = JAug[k][n];
00096             JAug[k][n] = JAug[j][n];
00097             JAug[j][n] = temp;
00098           }
00099           break;
00100         }
00101       }
00102     }
00103     for (j=k+1; j<=5; ++j){            /* Pivot */
00104       m = -JAug[j][k] / JAug[k][k];
00105       for (n=0; n<=11; ++n){
00106         JAug[j][n]=JAug[j][n] + m*JAug[k][n];   /* (Row j) + m * (Row k) */
00107         if ((JAug[j][n] < 0.000001) && (JAug[j][n] > -0.000001)){
00108           JAug[j][n] = 0;
00109         }
00110       }
00111     }
00112   }
00113 
00114   /* Normalization of Diagonal Terms */
00115   for (j=0; j<=5; ++j){
00116     m=1/JAug[j][j];
00117     for(k=0; k<=11; ++k){
00118       JAug[j][k] = m * JAug[j][k];
00119     }
00120   }
00121 
00122   /* Perform Gauss Jordan Steps */
00123   for (k=5; k>=0; --k){
00124     for(j=k-1; j>=0; --j){
00125       m = -JAug[j][k]/JAug[k][k];
00126       for (n=0; n<=11; ++n){
00127         JAug[j][n] = JAug[j][n] + m * JAug[k][n];
00128       }
00129     }
00130   }
00131 
00132   /* Assign last 6 columns of JAug to InvJ */
00133   for (j=0; j<=5; ++j){
00134     for (k=0; k<=5; ++k){
00135       InvJ[j][k] = JAug[j][k+6];
00136 
00137     }
00138   }
00139 
00140   return 0;                     /* FIXME-- check divisors for 0 above */
00141 }
00142 
00143 /******************************** MatMult() *********************************/
00144 
00145 /*---------------------------------------------------------------------------
00146   This function simply multiplies a 6x6 matrix by a 1x6 vector
00147   ---------------------------------------------------------------------------*/
00148 
00149 static void MatMult(double J[][6], const double x[], double Ans[])
00150 {
00151   int j, k;
00152   for (j=0; j<=5; ++j){
00153     Ans[j] = 0;
00154     for (k=0; k<=5; ++k){
00155       Ans[j] = J[j][k]*x[k]+Ans[j];
00156     }
00157   }
00158 }
00159 
00160 /* define position of base strut ends in base (world) coordinate system */
00161 static PmCartesian b[6] = {{BASE_0_X, BASE_0_Y, BASE_0_Z},
00162                            {BASE_1_X, BASE_1_Y, BASE_1_Z},
00163                            {BASE_2_X, BASE_2_Y, BASE_2_Z},
00164                            {BASE_3_X, BASE_3_Y, BASE_3_Z},
00165                            {BASE_4_X, BASE_4_Y, BASE_4_Z},
00166                            {BASE_5_X, BASE_5_Y, BASE_5_Z}};
00167 
00168 static PmCartesian a[6] = {{PLATFORM_0_X, PLATFORM_0_Y, PLATFORM_0_Z},
00169                            {PLATFORM_1_X, PLATFORM_1_Y, PLATFORM_1_Z},
00170                            {PLATFORM_2_X, PLATFORM_2_Y, PLATFORM_2_Z},
00171                            {PLATFORM_3_X, PLATFORM_3_Y, PLATFORM_3_Z},
00172                            {PLATFORM_4_X, PLATFORM_4_Y, PLATFORM_4_Z},
00173                            {PLATFORM_5_X, PLATFORM_5_Y, PLATFORM_5_Z}};
00174 
00175 int genhexSetParams(const PmCartesian base[], const PmCartesian platform[])
00176 {
00177   int t;
00178 
00179   for (t = 0; t < 6; t++) {
00180     b[t] = base[t];
00181     a[t] = platform[t];
00182   }
00183 
00184   return 0;
00185 }
00186 
00187 int genhexGetParams(PmCartesian base[], PmCartesian platform[])
00188 {
00189   int t;
00190 
00191   for (t = 0; t < 6; t++) {
00192     base[t] = b[t];
00193     platform[t] = b[t];
00194   }
00195 
00196   return 0;
00197 }
00198 
00199 /**************************** jacobianInverse() ***************************/
00200 
00201 static int JInvMat(const EmcPose * pos,
00202                    double InverseJacobian[][NUM_STRUTS])
00203 {
00204   int i;
00205   PmRpy rpy;
00206   PmRotationMatrix RMatrix;
00207   PmCartesian aw, RMatrix_a;
00208   PmCartesian InvKinStrutVect,InvKinStrutVectUnit;
00209   PmCartesian RMatrix_a_cross_Strut;
00210 
00211   /* assign a, b, c to roll, pitch, yaw angles and convert to rot matrix */
00212   rpy.r = pos->a * PM_PI / 180.0;
00213   rpy.p = pos->b * PM_PI / 180.0;
00214   rpy.y = pos->c * PM_PI / 180.0;
00215   pmRpyMatConvert(rpy, &RMatrix);
00216 
00217   /* Enter for loop to build Inverse Jacobian */
00218   for (i = 0; i < NUM_STRUTS; i++) {
00219     /* run part of inverse kins to get strut vectors */
00220     pmMatCartMult(RMatrix, a[i], &RMatrix_a);
00221     pmCartCartAdd(pos->tran, RMatrix_a, &aw);
00222     pmCartCartSub(aw, b[i], &InvKinStrutVect);
00223 
00224     /* Determine RMatrix_a_cross_strut */
00225     if (0 != pmCartUnit(InvKinStrutVect, &InvKinStrutVectUnit)) {
00226       return -1;
00227     }
00228     pmCartCartCross(RMatrix_a, InvKinStrutVectUnit, &RMatrix_a_cross_Strut);
00229 
00230     /* Build Inverse Jacobian Matrix */
00231     InverseJacobian[i][0] = InvKinStrutVectUnit.x;
00232     InverseJacobian[i][1] = InvKinStrutVectUnit.y;
00233     InverseJacobian[i][2] = InvKinStrutVectUnit.z;
00234     InverseJacobian[i][3] = RMatrix_a_cross_Strut.x;
00235     InverseJacobian[i][4] = RMatrix_a_cross_Strut.y;
00236     InverseJacobian[i][5] = RMatrix_a_cross_Strut.z;
00237   }
00238 
00239   return 0;
00240 }
00241 
00242 int jacobianInverse(const EmcPose * pos,
00243                     const EmcPose * vel,
00244                     const double * joints,
00245                     double * jointvels)
00246 {
00247   double InverseJacobian[NUM_STRUTS][NUM_STRUTS];
00248   double velmatrix[6];
00249 
00250   if (0 != JInvMat(pos, InverseJacobian)) {
00251     return -1;
00252   }
00253 
00254   /* Multiply Jinv[] by vel[] to get jointvels */
00255   velmatrix[0] = vel->tran.x;   /* dx/dt */
00256   velmatrix[1] = vel->tran.y;   /* dy/dt */
00257   velmatrix[2] = vel->tran.z;   /* dz/dt */
00258   velmatrix[3] = vel->a;        /* droll/dt */
00259   velmatrix[4] = vel->b;        /* dpitch/dt */
00260   velmatrix[5] = vel->c;        /* dyaw/dt */
00261   MatMult(InverseJacobian, velmatrix, jointvels);
00262 
00263   return 0;
00264 }
00265 
00266 /**************************** jacobianForward() ***************************/
00267 
00268 /* FIXME-- could use a better implementation than computing the
00269    inverse and then inverting it */
00270 int jacobianForward(const double * joints,
00271                     const double * jointvels,
00272                     const EmcPose * pos,
00273                     EmcPose * vel)
00274 {
00275   double InverseJacobian[NUM_STRUTS][NUM_STRUTS];
00276   double Jacobian[NUM_STRUTS][NUM_STRUTS];
00277   double velmatrix[6];
00278 
00279   if (0 != JInvMat(pos, InverseJacobian)) {
00280     return -1;
00281   }
00282   if (0 != MatInvert(InverseJacobian, Jacobian)) {
00283     return -1;
00284   }
00285 
00286   /* Multiply J[] by jointvels to get vels */
00287   MatMult(Jacobian, jointvels, velmatrix);
00288   vel->tran.x = velmatrix[0];
00289   vel->tran.y = velmatrix[1];
00290   vel->tran.z = velmatrix[2];
00291   vel->a = velmatrix[3];
00292   vel->b = velmatrix[4];
00293   vel->c = velmatrix[5];
00294 
00295   return 0;
00296 }
00297 
00298 /**************************** kinematicsForward() ***************************/
00299 
00300 /* the inverse kinematics take world coordinates and determine joint values,
00301    given the inverse kinematics flags to resolve any ambiguities. The forward
00302    flags are set to indicate their value appropriate to the world coordinates
00303    passed in. */
00304 int kinematicsForward(const double * joints,
00305                       EmcPose * pos,
00306                       const KINEMATICS_FORWARD_FLAGS * fflags,
00307                       KINEMATICS_INVERSE_FLAGS * iflags)
00308 {
00309   PmCartesian aw;
00310   PmCartesian InvKinStrutVect,InvKinStrutVectUnit;
00311   PmCartesian q_trans, RMatrix_a, RMatrix_a_cross_Strut;
00312 
00313   double Jacobian[NUM_STRUTS][NUM_STRUTS];
00314   double InverseJacobian[NUM_STRUTS][NUM_STRUTS];
00315   double InvKinStrutLength, StrutLengthDiff[NUM_STRUTS];
00316   double delta[NUM_STRUTS];
00317   double conv_err = 1.0;
00318 
00319   PmRotationMatrix RMatrix;
00320   PmRpy q_RPY;
00321 
00322   int iterate = 1;
00323   int i;
00324   int iteration = 0;
00325   int retval = 0;
00326 
00327 #define HIGH_CONV_CRITERION   (1e-12)
00328 #define MEDIUM_CONV_CRITERION (1e-5)
00329 #define LOW_CONV_CRITERION    (1e-3)
00330 #define MEDIUM_CONV_ITERATIONS  50
00331 #define LOW_CONV_ITERATIONS    100
00332 #define FAIL_CONV_ITERATIONS   150
00333 #define LARGE_CONV_ERROR 10000
00334   double conv_criterion = HIGH_CONV_CRITERION;
00335 
00336   /* abort on obvious problems, like joints <= 0 */
00337   /* FIXME-- should check against triangle inequality, so that joints
00338      are never too short to span shared base and platform sides */
00339   if (joints[0] <= 0.0 ||
00340       joints[1] <= 0.0 ||
00341       joints[2] <= 0.0 ||
00342       joints[3] <= 0.0 ||
00343       joints[4] <= 0.0 ||
00344       joints[5] <= 0.0) {
00345     return -1;
00346   }
00347 
00348   /* assign a,b,c to roll, pitch, yaw angles */
00349   q_RPY.r = pos->a * PM_PI / 180.0;
00350   q_RPY.p = pos->b * PM_PI / 180.0;
00351   q_RPY.y = pos->c * PM_PI / 180.0;
00352 
00353   /* Assign translation values in pos to q_trans */
00354   q_trans.x = pos->tran.x;
00355   q_trans.y = pos->tran.y;
00356   q_trans.z = pos->tran.z;
00357 
00358   /* Enter Newton-Raphson iterative method   */
00359   while (iterate) {
00360     /* check for large error and return error flag if no convergence */
00361     if ((conv_err > +LARGE_CONV_ERROR) || 
00362         (conv_err < -LARGE_CONV_ERROR)) {
00363       /* we can't converge */
00364       return -2;
00365     };
00366 
00367     iteration++;
00368 
00369 #if 0
00370     /* if forward kinematics are having a difficult time converging
00371        ease the restrictions on the convergence criterion */
00372     if (iteration == MEDIUM_CONV_ITERATIONS) {
00373       conv_criterion = MEDIUM_CONV_CRITERION;
00374       retval = -3;              /* this means if we eventually converge,
00375                                  the result is sloppy */
00376     }
00377 
00378     if (iteration == LOW_CONV_ITERATIONS) {
00379       conv_criterion = LOW_CONV_CRITERION;
00380       retval = -4;              /* this means if we eventually converge,
00381                                  the result is even sloppier */
00382     }
00383 #endif
00384 
00385     /* check iteration to see if the kinematics can reach the
00386        convergence criterion and return error flag if it can't */
00387     if (iteration > FAIL_CONV_ITERATIONS) {
00388       /* we can't converge */
00389       return -5;
00390     }
00391 
00392     /* Convert q_RPY to Rotation Matrix */
00393     pmRpyMatConvert(q_RPY, &RMatrix);
00394 
00395     /* compute StrutLengthDiff[] by running inverse kins on Cartesian
00396      estimate to get joint estimate, subtract joints to get joint deltas,
00397      and compute inv J while we're at it */
00398     for (i = 0; i < NUM_STRUTS; i++) {
00399       pmMatCartMult(RMatrix, a[i], &RMatrix_a);
00400       pmCartCartAdd(q_trans, RMatrix_a, &aw);
00401       pmCartCartSub(aw,b[i], &InvKinStrutVect);
00402       if (0 != pmCartUnit(InvKinStrutVect, &InvKinStrutVectUnit)) {
00403         return -1;
00404       }
00405       pmCartMag(InvKinStrutVect, &InvKinStrutLength);
00406       StrutLengthDiff[i] = InvKinStrutLength - joints[i];
00407 
00408       /* Determine RMatrix_a_cross_strut */
00409       pmCartCartCross(RMatrix_a, InvKinStrutVectUnit, &RMatrix_a_cross_Strut);
00410 
00411       /* Build Inverse Jacobian Matrix */
00412       InverseJacobian[i][0] = InvKinStrutVectUnit.x;
00413       InverseJacobian[i][1] = InvKinStrutVectUnit.y;
00414       InverseJacobian[i][2] = InvKinStrutVectUnit.z;
00415       InverseJacobian[i][3] = RMatrix_a_cross_Strut.x;
00416       InverseJacobian[i][4] = RMatrix_a_cross_Strut.y;
00417       InverseJacobian[i][5] = RMatrix_a_cross_Strut.z;
00418     }
00419 
00420     /* invert Inverse Jacobian */
00421     MatInvert(InverseJacobian, Jacobian);
00422 
00423     /* multiply Jacobian by LegLengthDiff */
00424     MatMult(Jacobian, StrutLengthDiff, delta);
00425 
00426     /* subtract delta from last iterations pos values */
00427     q_trans.x -= delta[0];
00428     q_trans.y -= delta[1];
00429     q_trans.z -= delta[2];
00430     q_RPY.r   -= delta[3];
00431     q_RPY.p   -= delta[4];
00432     q_RPY.y   -= delta[5];
00433 
00434     /* determine value of conv_error (used to determine if no convergence) */
00435     conv_err = 0.0;
00436     for (i = 0; i < NUM_STRUTS; i++) {
00437       conv_err += fabs(StrutLengthDiff[i]);
00438     }
00439 
00440     /* enter loop to determine if a strut needs another iteration */
00441     iterate = 0;                        /*assume iteration is done */
00442     for (i = 0; i < NUM_STRUTS; i++) {
00443       if (fabs(StrutLengthDiff[i]) > conv_criterion) {
00444         iterate = 1;
00445       }
00446     }
00447   } /* exit Newton-Raphson Iterative loop */
00448 
00449   /* assign r,p,w to a,b,c */
00450   pos->a = q_RPY.r * 180.0 / PM_PI;  
00451   pos->b = q_RPY.p * 180.0 / PM_PI;  
00452   pos->c = q_RPY.y * 180.0 / PM_PI;
00453   
00454   /* assign q_trans to pos */
00455   pos->tran.x = q_trans.x;
00456   pos->tran.y = q_trans.y;
00457   pos->tran.z = q_trans.z;
00458 
00459   return retval;
00460 }
00461 
00462 /************************ kinematicsInverse() ********************************/
00463 
00464 int kinematicsInverse(const EmcPose * pos,
00465                       double * joints,
00466                       const KINEMATICS_INVERSE_FLAGS * iflags,
00467                       KINEMATICS_FORWARD_FLAGS * fflags)
00468 {
00469   PmCartesian aw, temp;
00470   PmRotationMatrix RMatrix;
00471   PmRpy rpy;
00472   int i;
00473 
00474   /* define Rotation Matrix */
00475   rpy.r = pos->a * PM_PI / 180.0;
00476   rpy.p = pos->b * PM_PI / 180.0;
00477   rpy.y = pos->c * PM_PI / 180.0;
00478   pmRpyMatConvert(rpy, &RMatrix);
00479 
00480   /* enter for loop to calculate joints (strut lengths) */
00481   for (i = 0; i < NUM_STRUTS; i++) {
00482     /* convert location of platform strut end from platform
00483        to world coordinates */
00484     pmMatCartMult(RMatrix, a[i], &temp);
00485     pmCartCartAdd(pos->tran, temp, &aw);
00486 
00487     /* define strut lengths */
00488     pmCartCartSub(aw, b[i], &temp);
00489     pmCartMag(temp, &joints[i]);
00490   }
00491 
00492   return 0;
00493 }
00494 
00495 /*
00496   kinematicsHome() is implemented by taking the desired world coordinates,
00497   which are passed as an arg, and running the inverse kinematics to get
00498   the resulting joints. The flags are set to zero.
00499 */
00500 int kinematicsHome(EmcPose * world,
00501                    double * joint,
00502                    KINEMATICS_FORWARD_FLAGS * fflags,
00503                    KINEMATICS_INVERSE_FLAGS * iflags)
00504 {
00505   *fflags = 0;
00506   *iflags = 0;
00507 
00508   return kinematicsInverse(world, joint, iflags, fflags);
00509 }
00510 
00511 KINEMATICS_TYPE kinematicsType()
00512 {
00513 #if 1
00514   return KINEMATICS_BOTH;
00515 #else
00516   return KINEMATICS_INVERSE_ONLY;
00517 #endif
00518 }
00519 
00520 #ifdef MAIN
00521 
00522 #include <stdio.h>
00523 /* FIXME-- this works for Unix only */
00524 #include <sys/time.h>           /* struct timeval */
00525 #include <unistd.h>             /* gettimeofday() */
00526 
00527 static double timestamp()
00528 {
00529   struct timeval tp;
00530 
00531   if (0 != gettimeofday(&tp, NULL)) {
00532     return 0.0;
00533   }
00534   return ((double) tp.tv_sec) + ((double) tp.tv_usec) / 1000000.0;
00535 }
00536 
00537 int main(int argc, char *argv[])
00538 {
00539 #define BUFFERLEN 256
00540   char buffer[BUFFERLEN];
00541   int inverse = 1;
00542   int jacobian = 0;
00543   EmcPose pos = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
00544   EmcPose vel = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
00545   double joints[6] = {0.0};
00546   double jointvels[6] = {0.0};
00547   KINEMATICS_INVERSE_FLAGS iflags = 0;
00548   KINEMATICS_FORWARD_FLAGS fflags = 0;
00549   int t;
00550   int retval;
00551 #define ITERATIONS 100000
00552   double start, end;
00553 
00554   /* syntax is a.out {i|f # # # # # #} */
00555   if (argc == 8) {
00556     if (argv[1][0] == 'f') {
00557       /* joints passed, so do interations on forward kins for timing */
00558       for (t = 0; t < 6; t++) {
00559         if (1 != sscanf(argv[t + 2], "%lf", &joints[t])) {
00560           fprintf(stderr, "bad value: %s\n", argv[t + 2]);
00561           return 1;
00562         }
00563       }
00564       inverse = 0;
00565     }
00566     else if (argv[1][0] == 'i') {
00567       /* world coords passed, so do iterations on inverse kins for timing */
00568       if (1 != sscanf(argv[2], "%lf", &pos.tran.x)) {
00569         fprintf(stderr, "bad value: %s\n", argv[2]);
00570         return 1;
00571       }
00572       if (1 != sscanf(argv[3], "%lf", &pos.tran.y)) {
00573         fprintf(stderr, "bad value: %s\n", argv[3]);
00574         return 1;
00575       }
00576       if (1 != sscanf(argv[4], "%lf", &pos.tran.z)) {
00577         fprintf(stderr, "bad value: %s\n", argv[4]);
00578         return 1;
00579       }
00580       if (1 != sscanf(argv[5], "%lf", &pos.a)) {
00581         fprintf(stderr, "bad value: %s\n", argv[5]);
00582         return 1;
00583       }
00584       if (1 != sscanf(argv[6], "%lf", &pos.b)) {
00585         fprintf(stderr, "bad value: %s\n", argv[6]);
00586         return 1;
00587       }
00588       if (1 != sscanf(argv[7], "%lf", &pos.c)) {
00589         fprintf(stderr, "bad value: %s\n", argv[7]);
00590         return 1;
00591       }
00592       inverse = 1;
00593     }
00594     else {
00595       fprintf(stderr, "syntax: %s {i|f # # # # # #}\n", argv[0]);
00596       return 1;
00597     }
00598 
00599     /* need an initial estimate for the forward kins, so ask for it */
00600     if (inverse == 0) {
00601       do {
00602         printf("initial estimate for Cartesian position, xyzrpw: ");
00603         fflush(stdout);
00604         if (NULL == fgets(buffer, BUFFERLEN, stdin)) {
00605           return 0;
00606         }
00607       } while (6 != sscanf(buffer, "%lf %lf %lf %lf %lf %lf",
00608                            &pos.tran.x,
00609                            &pos.tran.y,
00610                            &pos.tran.z,
00611                            &pos.a,
00612                            &pos.b,
00613                            &pos.c));
00614     }
00615 
00616     start = timestamp();
00617     for (t = 0; t < ITERATIONS; t++) {
00618       if (inverse) {
00619         retval = kinematicsInverse(&pos, joints, &iflags, &fflags);
00620         if (0 != retval) {
00621           printf("inv kins error %d\n", retval);
00622           break;
00623         }
00624       }
00625       else {
00626         retval = kinematicsForward(joints, &pos, &fflags, &iflags);
00627         if (0 != retval) {
00628           printf("fwd kins error %d\n", retval);
00629           break;
00630         }
00631       }
00632     }
00633     end = timestamp();
00634 
00635     printf("calculation time: %f secs\n",
00636            (end - start) / ((double) ITERATIONS));
00637     return 0;
00638   } /* end of if args for timestamping */
00639 
00640   /* else we're interactive */
00641   while (! feof(stdin)) {
00642     if (inverse) {
00643       if (jacobian) {
00644         printf("jinv> ");
00645       }
00646       else {
00647         printf("inv> ");
00648       }
00649     }
00650     else {
00651       if (jacobian) {
00652         printf("jfwd> ");
00653       }
00654       else {
00655         printf("fwd> ");
00656       }
00657     }
00658     fflush(stdout);
00659 
00660     if (NULL == fgets(buffer, BUFFERLEN, stdin)) {
00661       break;
00662     }
00663 
00664     if (buffer[0] == 'i') {
00665       inverse = 1;
00666       continue;
00667     }
00668     else if (buffer[0] == 'f') {
00669       inverse = 0;
00670       continue;
00671     }
00672     else if (buffer[0] == 'j') {
00673       jacobian = ! jacobian;
00674       continue;
00675     }
00676     else if (buffer[0] == 'q') {
00677       break;
00678     }
00679 
00680     if (inverse) {
00681       if (jacobian) {
00682         if (12 != sscanf(buffer, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
00683                         &pos.tran.x,
00684                         &pos.tran.y,
00685                         &pos.tran.z,
00686                         &pos.a,
00687                         &pos.b,
00688                         &pos.c,
00689                         &vel.tran.x,
00690                         &vel.tran.y,
00691                         &vel.tran.z,
00692                         &vel.a,
00693                         &vel.b,
00694                         &vel.c)) {
00695           printf("?\n");
00696         }
00697         else {
00698           retval = jacobianInverse(&pos, &vel, joints, jointvels);
00699           printf("%f %f %f %f %f %f\n",
00700                  jointvels[0],
00701                  jointvels[1],
00702                  jointvels[2],
00703                  jointvels[3],
00704                  jointvels[4],
00705                  jointvels[5]);
00706           if (0 != retval) {
00707             printf("inv Jacobian error %d\n", retval);
00708           }
00709           else {
00710             retval = jacobianForward(joints, jointvels, &pos, &vel);
00711             printf("%f %f %f %f %f %f\n",
00712                    vel.tran.x,
00713                    vel.tran.y,
00714                    vel.tran.z,
00715                    vel.a,
00716                    vel.b,
00717                    vel.c);
00718             if (0 != retval) {
00719               printf("fwd kins error %d\n", retval);
00720             }
00721           }
00722         }
00723       }
00724       else {
00725         if (6 != sscanf(buffer, "%lf %lf %lf %lf %lf %lf",
00726                         &pos.tran.x,
00727                         &pos.tran.y,
00728                         &pos.tran.z,
00729                         &pos.a,
00730                         &pos.b,
00731                         &pos.c)) {
00732           printf("?\n");
00733         }
00734         else {
00735           retval = kinematicsInverse(&pos, joints, &iflags, &fflags);
00736           printf("%f %f %f %f %f %f\n",
00737                  joints[0],
00738                  joints[1],
00739                  joints[2],
00740                  joints[3],
00741                  joints[4],
00742                  joints[5]);
00743           if (0 != retval) {
00744             printf("inv kins error %d\n", retval);
00745           }
00746           else {
00747             retval = kinematicsForward(joints, &pos, &fflags, &iflags);
00748             printf("%f %f %f %f %f %f\n",
00749                    pos.tran.x,
00750                    pos.tran.y,
00751                    pos.tran.z,
00752                    pos.a,
00753                    pos.b,
00754                    pos.c);
00755             if (0 != retval) {
00756               printf("fwd kins error %d\n", retval);
00757             }
00758           }
00759         }
00760       }
00761     }
00762     else {
00763       if (jacobian) {
00764         if (12 != sscanf(buffer, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
00765                         &joints[0],
00766                         &joints[1],
00767                         &joints[2],
00768                         &joints[3],
00769                         &joints[4],
00770                         &joints[5],
00771                         &jointvels[0],
00772                         &jointvels[1],
00773                         &jointvels[2],
00774                         &jointvels[3],
00775                         &jointvels[4],
00776                         &jointvels[5])) {
00777           printf("?\n");
00778         }
00779         else {
00780           retval = jacobianForward(joints, jointvels, &pos, &vel);
00781           printf("%f %f %f %f %f %f\n",
00782                  vel.tran.x,
00783                  vel.tran.y,
00784                  vel.tran.z,
00785                  vel.a,
00786                  vel.b,
00787                  vel.c);
00788           if (0 != retval) {
00789             printf("fwd kins error %d\n", retval);
00790           }
00791           else {
00792             retval = jacobianInverse(&pos, &vel, joints, jointvels);
00793             printf("%f %f %f %f %f %f\n",
00794                    jointvels[0],
00795                    jointvels[1],
00796                    jointvels[2],
00797                    jointvels[3],
00798                    jointvels[4],
00799                    jointvels[5]);
00800             if (0 != retval) {
00801               printf("inv kins error %d\n", retval);
00802             }
00803           }
00804         }
00805       }
00806       else {
00807         if (6 != sscanf(buffer, "%lf %lf %lf %lf %lf %lf",
00808                         &joints[0],
00809                         &joints[1],
00810                         &joints[2],
00811                         &joints[3],
00812                         &joints[4],
00813                         &joints[5])) {
00814           printf("?\n");
00815         }
00816         else {
00817           retval = kinematicsForward(joints, &pos, &fflags, &iflags);
00818           printf("%f %f %f %f %f %f\n",
00819                  pos.tran.x,
00820                  pos.tran.y,
00821                  pos.tran.z,
00822                  pos.a,
00823                  pos.b,
00824                  pos.c);
00825           if (0 != retval) {
00826             printf("fwd kins error %d\n", retval);
00827           }
00828           else {
00829             retval = kinematicsInverse(&pos, joints, &iflags, &fflags);
00830             printf("%f %f %f %f %f %f\n",
00831                    joints[0],
00832                    joints[1],
00833                    joints[2],
00834                    joints[3],
00835                    joints[4],
00836                    joints[5]);
00837             if (0 != retval) {
00838               printf("inv kins error %d\n", retval);
00839             }
00840           }
00841         }
00842       }
00843     }
00844   }
00845 
00846   return 0;
00847 
00848 #undef ITERATIONS
00849 #undef BUFFERLEN
00850 }
00851 
00852 #endif /* MAIN */
00853 

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