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
00030 #include "puma560.h"
00031
00032 const int Puma560::NUM_SOLUTIONS=8;
00033
00035
00039 struct Puma560Solution{
00040 double angle[6];
00041 double angle12;
00042 bool valid;
00043 };
00044
00045
00046 #define JOINT_DIST_EPSILON .05
00047 int
00048 Puma560::findClosestSol(Puma560Solution *candidates, Puma560Solution *current)
00049 {
00050 unsigned char bits[Puma560::NUM_SOLUTIONS]=
00051 {0x1,0x2,0x4,0x08,0x10,0x20,0x40,0x80};
00052 unsigned char masks[Puma560::NUM_SOLUTIONS]=
00053 {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
00054
00055 unsigned char possible = 0xFF;
00056 unsigned char best;
00057 double shortest_distance,distance;
00058 bool one_solution;
00059
00060 int i,j;
00061
00062
00063 for(i=0; i < Puma560::NUM_SOLUTIONS; i++)
00064 if(candidates[i].valid != true) possible &= masks[i];
00065
00066
00067 if(possible == 0)
00068 return(Puma560::NUM_SOLUTIONS);
00069
00070
00071
00072
00073 for(j=0; j < numDOF; j++) {
00074 shortest_distance = 6*M_PI;
00075 best = 0;
00076 for(i=0; i < Puma560::NUM_SOLUTIONS; i++) {
00077 if(possible & bits[i]) {
00078 distance = fabs(candidates[i].angle[j] - current->angle[j]);
00079 if(fabs(distance - shortest_distance) < JOINT_DIST_EPSILON) {
00080 best |= bits[i];
00081 one_solution = false;
00082 }
00083 else if(distance < shortest_distance) {
00084 shortest_distance = distance;
00085 best = bits[i];
00086 one_solution = true;
00087 }
00088 }
00089 }
00090 possible = best;
00091 if(one_solution == true) break;
00092 }
00093
00094
00095 for(i=0; i < Puma560::NUM_SOLUTIONS; i++)
00096 if(possible & bits[i]) return(i);
00097
00098
00099
00100
00101
00102 return(Puma560::NUM_SOLUTIONS);
00103 }
00104
00105 int
00106 Puma560::invKinematics(const transf& endTranLocal,double* dofVals,int)
00107 {
00108 transf endTran = endTranLocal * base->getTran().inverse();
00109 int i;
00110 const double a2=431.8,a3=20.3;
00111 const double d3=149.0,d4=431.8;
00112 mat3 rot;
00113 endTran.rotation().ToRotationMatrix(rot);
00114
00115 double r21 = rot.element(1,0);
00116 double r22 = rot.element(1,1);
00117 double r23 = rot.element(1,2);
00118
00119 double r31 = rot.element(2,0);
00120 double r32 = rot.element(2,1);
00121 double r33 = rot.element(2,2);
00122
00123 double px = endTran.translation()[0];
00124 double py = endTran.translation()[1];
00125 double pz = endTran.translation()[2];
00126
00127 double r = sqrt(px*px + py*py);
00128 double r1;
00129
00130 double num,den,Psi,V114,V113,V323,V313,V112,V132,V312,V332,V412,V432;
00131 Puma560Solution sol[Puma560::NUM_SOLUTIONS];
00132
00133 for(i=0; i < Puma560::NUM_SOLUTIONS; i++) {
00134 sol[i].valid = true;
00135
00136
00137 if (i > 3)
00138 sol[i].angle[0] = atan2(py,px) + asin(d3/r);
00139 else
00140 sol[i].angle[0] = atan2(py,px) + M_PI - asin(d3/r);
00141
00142
00143 V114 = px*cos(sol[i].angle[0]) + py*sin(sol[i].angle[0]);
00144 r1=sqrt(V114*V114 + pz*pz);
00145 Psi = acos((a2*a2 - d4*d4 - a3*a3 + V114*V114 + pz*pz)/(2.0*a2*r1));
00146 if (i%4 == 0 || i%4 == 1)
00147 sol[i].angle[1] = atan2(pz,V114) - Psi;
00148 else
00149 sol[i].angle[1] = atan2(pz,V114) + Psi;
00150
00151
00152 num = cos(sol[i].angle[1])*V114 + sin(sol[i].angle[1])*pz - a2;
00153 den = cos(sol[i].angle[1])*pz - sin(sol[i].angle[1])*V114;
00154 sol[i].angle[2] = atan2(a3,d4) - atan2(num,den);
00155
00156
00157 V113 = cos(sol[i].angle[0])*r31 + sin(sol[i].angle[0])*r32;
00158 V323 = cos(sol[i].angle[0])*r32 - sin(sol[i].angle[0])*r31;
00159 V313 = cos(sol[i].angle[1] + sol[i].angle[2])*V113 +
00160 sin(sol[i].angle[1] + sol[i].angle[2])*r33;
00161 if (i % 2)
00162 sol[i].angle[3] = atan2(V323,V313);
00163 else
00164 sol[i].angle[3] = atan2(-V323,-V313);
00165
00166
00167 num = -cos(sol[i].angle[3])*V313 - V323*sin(sol[i].angle[3]);
00168 den = -V113*sin(sol[i].angle[1] + sol[i].angle[2]) +
00169 r33*cos(sol[i].angle[1] + sol[i].angle[2]);
00170 sol[i].angle[4] = atan2(num,den);
00171
00172
00173 V112 = cos(sol[i].angle[0])*r21 + sin(sol[i].angle[0])*r22;
00174 V132 = sin(sol[i].angle[0])*r21 - cos(sol[i].angle[0])*r22;
00175 V312 = V112*cos(sol[i].angle[1]+sol[i].angle[2]) +
00176 r23*sin(sol[i].angle[1]+sol[i].angle[2]);
00177 V332 = -V112*sin(sol[i].angle[1]+sol[i].angle[2]) +
00178 r23*cos(sol[i].angle[1]+sol[i].angle[2]);
00179 V412 = V312*cos(sol[i].angle[3]) - V132*sin(sol[i].angle[3]);
00180 V432 = V312*sin(sol[i].angle[3]) + V132*cos(sol[i].angle[3]);
00181 num = -V412*cos(sol[i].angle[4]) - V332*sin(sol[i].angle[4]);
00182 den = -V432;
00183 sol[i].angle[5] = atan2(num,den);
00184 }
00185
00186
00187 int j;
00188
00189
00190 for(j=0; j < Puma560::NUM_SOLUTIONS; j++) {
00191 for(i=0;i<numDOF;i++) {
00192 if(sol[j].angle[i] < dofVec[i]->getMin() && sol[j].angle[i] +(2*M_PI)>
00193 dofVec[i]->getMax()) {
00194 sol[j].valid = false;
00195 break;
00196 }
00197 else if (sol[j].angle[i] < dofVec[i]->getMin())
00198 sol[j].angle[i] += 2*M_PI;
00199 if(sol[j].angle[i] > dofVec[i]->getMax() && sol[j].angle[i] -(2*M_PI)<
00200 dofVec[i]->getMin()) {
00201 sol[j].valid = FALSE;
00202 break;
00203 }
00204 else if (sol[j].angle[i] > dofVec[i]->getMax())
00205 sol[j].angle[i] -= 2*M_PI;
00206 }
00207 }
00208
00209 #ifdef PUMADBG
00210 for(j=0; j < Puma560::NUM_SOLUTIONS; j++)
00211 {
00212 fprintf(stderr,"solution %d = ", j);
00213
00214 for(i=0;i<numDOF;i++)
00215 fprintf(stderr,"%f ",sol[j].angle[i]);
00216 fprintf(stderr,"\n");
00217
00218 }
00219 #endif
00220
00221 Puma560Solution current;
00222 for(i=0;i<numDOF;i++)
00223 current.angle[i] = dofVec[i]->getVal();
00224
00225 int chosen = findClosestSol(sol, ¤t);
00226
00227 if(chosen == Puma560::NUM_SOLUTIONS) return FAILURE;
00228
00229 #ifdef PUMADBG
00230 fprintf(stderr,"chosen = %d\n",chosen);
00231 #endif
00232
00233 for (i=0;i<numDOF;i++)
00234 dofVals[i] = sol[chosen].angle[i];
00235
00236
00237 return SUCCESS;
00238 }