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 #include <robot/JFKengine>
00026 #include <base/base>
00027
00028 #include <base/Time>
00029
00030 using robot::JFKengine;
00031 using robot::KinematicChain;
00032
00033 using base::Math;
00034 using base::Time;
00035 using base::Vector;
00036 using base::Vector3;
00037 using base::Matrix;
00038 using base::Expression;
00039 using base::ExpressionMatrix;
00040
00041
00042 JFKengine::JFKengine()
00043 : forwardKinematicsCached(false), A(0), T(0),
00044 JCached(false), J(1,1)
00045 {
00046 }
00047
00048
00049 ExpressionMatrix JFKengine::getForwardKinematics(const KinematicChain& chain) const
00050 {
00051 const Int n = chain.size();
00052
00053 const Real trigEpsilon = 1.0e-5;
00054
00055 if (n < 1) {
00056 ExpressionMatrix I(4,4);
00057 I(0,0)=I(1,1)=I(2,2)=I(3,3)=1;
00058 return I;
00059 }
00060
00061 if ( A.size() != n ) {
00062
00063 A.resize(n);
00064 T.resize(n);
00065 chain_AT.resize(n);
00066 }
00067
00068 Expression zero = 0;
00069 Expression one = 1;
00070
00071
00072 Int dof = 0;
00073 for ( Int l = 0; l < n; l++ ) {
00074 const KinematicChain::Link& link( chain[l] );
00075
00076
00077
00078
00079 if (forwardKinematicsCached) {
00080 if ( chain_AT[l] != link )
00081 forwardKinematicsCached = false;
00082 }
00083
00084
00085 if (!forwardKinematicsCached) {
00086
00087 A[l].resize(4,4); T[l].resize(4,4);
00088 chain_AT.setLink(l, link);
00089
00090
00091 Expression theta, d;
00092 if (link.isDHType()) {
00093
00094
00095 if (link.type() == KinematicChain::Link::Revolute) {
00096 if (link.isActive())
00097 theta = Expression::p[dof];
00098 else
00099 theta = link.getTheta();
00100 d = link.getD();
00101 }
00102 else {
00103 theta = link.getTheta();
00104 if (link.isActive())
00105 d = Expression::p[dof];
00106 else
00107 d = link.getD();
00108 }
00109
00110 Real sinAlpha = Math::zeroIfNeighbour( Math::sin(link.getAlpha()), trigEpsilon );
00111 Real cosAlpha = Math::zeroIfNeighbour( Math::cos(link.getAlpha()), trigEpsilon );
00112 Expression sinTheta = sin(theta);
00113 Expression cosTheta = cos(theta);
00114
00115
00116 A[l](0,0)=cosTheta; A[l](0,1)=-sinTheta*cosAlpha; A[l](0,2)=sinTheta*sinAlpha; A[l](0,3)=link.getA()*cosTheta;
00117 A[l](1,0)=sinTheta; A[l](1,1)=cosTheta*cosAlpha; A[l](1,2)=-cosTheta*sinAlpha; A[l](1,3)=link.getA()*sinTheta;
00118 A[l](2,0)=zero; A[l](2,1)=sinAlpha; A[l](2,2)=cosAlpha; A[l](2,3)=d;
00119 A[l](3,0)=zero; A[l](3,1)=zero; A[l](3,2)=zero; A[l](3,3)=one;
00120
00121 }
00122 else {
00123
00124 if (link.type() == KinematicChain::Link::Translating) {
00125
00126 Expression t = Expression::p[dof];
00127 Assert(link.getDirection().length() > 0);
00128 Vector3 dir( link.getDirection() ); dir.normalize();
00129
00130
00131 A[l](0,0)=one; A[l](0,1)=zero; A[l](0,2)=zero; A[l](0,3)=dir.x*t;
00132 A[l](1,0)=zero; A[l](1,1)=one; A[l](1,2)=zero; A[l](1,3)=dir.y*t;
00133 A[l](2,0)=zero; A[l](2,1)=zero; A[l](2,2)=one; A[l](2,3)=dir.z*t;
00134 A[l](3,0)=zero; A[l](3,1)=zero; A[l](3,2)=zero; A[l](3,3)=one;
00135
00136 }
00137 else if (link.type() == KinematicChain::Link::FixedTransform) {
00138
00139
00140 A[l] = base::toExpressionMatrix(base::fromMatrix4(link.getTransform()));
00141
00142
00143 }
00144 else
00145 throw std::runtime_error(Exception("unsupported joint type in chain - can't calculate forward kinematic transform"));
00146
00147 }
00148
00149 simplify( A[l] );
00150
00151 if ( l < 1 )
00152 T[l] = A[l];
00153 else {
00154 T[l] = T[l-1] * A[l];
00155 simplify( T[l] );
00156 }
00157
00158
00159
00160 }
00161
00162 dof += link.dof();
00163
00164
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 forwardKinematicsCached = true;
00180
00181
00182 return T[n-1];
00183 }
00184
00185
00186
00187 ExpressionMatrix JFKengine::getJacobian(const KinematicChain& chain, bool includeOrientation) const
00188 {
00189 const Int n = chain.size();
00190 const Int chain_dof = chain.dof();
00191
00192 if (chain.dof() < 1) {
00193 ExpressionMatrix Z(includeOrientation?6:3,0);
00194 return Z;
00195 }
00196
00197
00198
00199
00200 if ( chain_J.dof() != chain_dof ) {
00201 JCached = false;
00202 }
00203 else {
00204 if (chain_J.hashCode() != chain.hashCode())
00205 JCached = false;
00206 else {
00207 if (includeOrientation) {
00208 if (J.size1() != 6)
00209 JCached = false;
00210 }
00211 else {
00212
00213 ExpressionMatrix cachedJ(J);
00214 J.resize(3,cachedJ.size2());
00215
00216 for(Int r=0; r<3; r++)
00217 for(Int c=0; c<J.size2(); c++)
00218 J(r,c) = cachedJ(r,c);
00219 }
00220 }
00221 }
00222
00223
00224 if (!JCached) {
00225 #ifdef DEBUG
00226 base::Time start( Time::now() );
00227 #endif
00228
00229 chain_J = chain;
00230 J.resize(includeOrientation?6:3, chain_dof);
00231
00232 getForwardKinematics( chain );
00233
00234 Expression zero = 0;
00235 Expression one = 1;
00236
00237 for (Int dof=0, l=0; l < n; l++) {
00238 const KinematicChain::Link& link( chain[l] );
00239
00240 if (link.dof() > 0) {
00241
00242
00243 for (Int iVar=0; iVar < 3; iVar++) {
00244
00245 J(iVar,dof) = T[n-1](iVar,3).differentiate( Expression::p[dof] );
00246 J(iVar,dof).simplify();
00247
00248 }
00249
00250 if (includeOrientation) {
00251
00252 const KinematicChain::Link::LinkType linkType( (chain[l]).type() );
00253 switch (linkType) {
00254 case KinematicChain::Link::Revolute:
00255 if (dof < 1) {
00256 J(3,0) = J(4,0) = zero;
00257 J(5,0) = one;
00258 }
00259 else {
00260 J(3,dof) = T[l-1](0,2);
00261 J(4,dof) = T[l-1](1,2);
00262 J(5,dof) = T[l-1](2,2);
00263 }
00264 break;
00265
00266 case KinematicChain::Link::Prismatic:
00267 case KinematicChain::Link::Translating:
00268 for (Int i=3; i< 6; i++) {
00269 J(i,dof) = zero;
00270 }
00271 break;
00272 default:
00273 throw std::runtime_error(Exception("unsupported joint type in chain - can't compute Jacobian"));
00274 }
00275 }
00276
00277 }
00278
00279 dof += link.dof();
00280
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 JCached = true;
00294
00295 #ifdef DEBUG
00296 Debugln( JFKE, "Symbolic Jacobian computation for " << chain.size()
00297 << " link manipulator took " << (Time::now()-start).seconds() << "s");
00298 #endif
00299 }
00300 return J;
00301 }
00302
00303
00304
00305 Matrix JFKengine::getForwardKinematics(const KinematicChain& chain, const Vector& q) const
00306 {
00307 ExpressionMatrix F( getForwardKinematics(chain) );
00308 return evaluate(F,q);
00309 }
00310
00311
00312 Matrix JFKengine::getJacobian(const KinematicChain& chain, const Vector& q, bool includeOrientation) const
00313 {
00314 ExpressionMatrix J( getJacobian(chain, includeOrientation) );
00315 return evaluate(J,q);
00316 }
00317
00318
00319
00320
00321 array<Vector> JFKengine::getJointOrigins(const KinematicChain& chain, const Vector& q ) const
00322 {
00323 if ( chain.dof() < 1 )
00324 return array<Vector>(0);
00325
00326 Assert(q.size() == chain.dof() );
00327
00328
00329
00330 const Int chain_dof = chain.dof();
00331
00332 array<Vector> locs(chain_dof);
00333 getForwardKinematics(chain);
00334
00335 for (Int v=0; v < chain_dof; v++ ) {
00336 locs[v].resize(3);
00337 Int li = chain.linkIndexOfVariable(v);
00338 for ( Int iDimension=0; iDimension < 3; iDimension++ ) {
00339 locs[v][iDimension] = T[li](iDimension,3).evaluate( q );
00340 }
00341 }
00342
00343 return locs;
00344 }
00345
00346
00347 array<Vector> JFKengine::getLinkOrigins(const KinematicChain& chain, const Vector& q ) const
00348 {
00349 if ( chain.size() < 1 )
00350 return array<Vector>(0);
00351
00352 Assert(q.size() == chain.dof() );
00353
00354 const Int chain_size = chain.size();
00355
00356 array<Vector> locs(chain_size);
00357 getForwardKinematics(chain);
00358
00359 for (Int li=0; li < chain_size; li++ ) {
00360 locs[li].resize(3);
00361 for ( Int iDimension=0; iDimension < 3; iDimension++ ) {
00362 locs[li][iDimension] = T[li](iDimension,3).evaluate( q );
00363 }
00364 }
00365
00366
00367
00368
00369
00370
00371 return locs;
00372 }