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 #include <rtt/Property.hpp>
00043 #include <rtt/PropertyBag.hpp>
00044 #include <rtt/base/PropertyIntrospection.hpp>
00045 #include <rtt/Logger.hpp>
00046 #include <sstream>
00047
00048 #include "motionproperties.hpp"
00049
00050
00051 namespace RTT
00052 {
00053 using namespace std;
00054
00055
00056 template class Property<KDL::Frame>;
00057 template class Property<KDL::Wrench>;
00058 template class Property<KDL::Twist>;
00059 template class Property<KDL::Rotation>;
00060 template class Property<KDL::Vector>;
00061
00072 class VectorDecomposer
00073 {
00074 PropertyBag resultBag;
00075 Property<double> X;
00076 Property<double> Y;
00077 Property<double> Z;
00078
00079 public:
00080
00081 VectorDecomposer( const Vector& v);
00082
00083 PropertyBag& result() { return resultBag; }
00084 };
00085
00090 class VectorComposer
00091 {
00092 const PropertyBag& bag;
00093 public:
00094 VectorComposer(const PropertyBag& _bag )
00095 : bag(_bag)
00096 {}
00097
00098 bool getResult( Vector& res);
00099 };
00100
00101 VectorDecomposer::VectorDecomposer( const Vector& v )
00102 : resultBag("KDL.Vector"),
00103 X("X","X Value", v[0]),
00104 Y("Y","Y Value", v[1]),
00105 Z("Z","Z Value", v[2])
00106 {
00107 resultBag.add(X.clone());
00108 resultBag.add(Y.clone());
00109 resultBag.add(Z.clone());
00110 }
00111
00112 bool VectorComposer::getResult(Vector& res)
00113 {
00114 if ( bag.getType() == "MotCon::Vector" || bag.getType() == "KDL.Vector" )
00115 {
00116 Property<double>* px = dynamic_cast<Property<double>*>( bag.find("X") );
00117 Property<double>* py = dynamic_cast<Property<double>*>( bag.find("Y") );
00118 Property<double>* pz = dynamic_cast<Property<double>*>( bag.find("Z") );
00119
00120 if ( px != 0 && py != 0 && pz != 0)
00121 {
00122 res = Vector( px->get(),py->get(),pz->get() );
00123 return true;
00124 } else {
00125 std::string element = !px ? "X" : !py ? "Y" : "Z";
00126 Logger::log() << Logger::Error << "Aborting composition of Property< KDL.Vector > "
00127 << ": Missing element '" <<element<<"'." <<Logger::endl;
00128 return false;
00129 }
00130 } else {
00131 Logger::log() << Logger::Error << "Aborting composition of Property< KDL.Vector > "
00132 << ": Expected type 'KDL.Vector', got type '"<< bag.getType() <<"'."
00133 <<Logger::endl;
00134 }
00135 return false;
00136 }
00137
00138
00149 class RotationDecomposer
00150 {
00151 PropertyBag resultBag;
00152 Property<double> X_x;
00153 Property<double> X_y;
00154 Property<double> X_z;
00155 Property<double> Y_x;
00156 Property<double> Y_y;
00157 Property<double> Y_z;
00158 Property<double> Z_x;
00159 Property<double> Z_y;
00160 Property<double> Z_z;
00161 public:
00162
00163 RotationDecomposer( const Rotation& r );
00164
00165 PropertyBag& result() { return resultBag; }
00166 };
00167
00172 class RotationComposer
00173 {
00174 const PropertyBag& bag;
00175 public:
00176 RotationComposer(const PropertyBag& _bag )
00177 : bag(_bag)
00178 {}
00179
00180 bool getResult( Rotation& res );
00181 };
00182
00183 RotationDecomposer::RotationDecomposer( const Rotation& r)
00184 : resultBag("KDL.Rotation"),
00185 X_x("X_x","", r(0,0) ),
00186 X_y("X_y","", r(1,0) ),
00187 X_z("X_z","", r(2,0) ),
00188 Y_x("Y_x","", r(0,1) ),
00189 Y_y("Y_y","", r(1,1) ),
00190 Y_z("Y_z","", r(2,1) ),
00191 Z_x("Z_x","", r(0,2) ),
00192 Z_y("Z_y","", r(1,2) ),
00193 Z_z("Z_z","", r(2,2) )
00194 {
00195 resultBag.add(X_x.clone());
00196 resultBag.add(X_y.clone());
00197 resultBag.add(X_z.clone());
00198 resultBag.add(Y_x.clone());
00199 resultBag.add(Y_y.clone());
00200 resultBag.add(Y_z.clone());
00201 resultBag.add(Z_x.clone());
00202 resultBag.add(Z_y.clone());
00203 resultBag.add(Z_z.clone());
00204 }
00205
00206 bool RotationComposer::getResult(Rotation& res)
00207 {
00208 if ( bag.getType() == "MotCon::Rotation" || bag.getType() == "KDL.Rotation" )
00209 {
00210
00211 Property<double>* X_x = dynamic_cast<Property<double>*>( bag.find("X_x") );
00212 Property<double>* X_y = dynamic_cast<Property<double>*>( bag.find("X_y") );
00213 Property<double>* X_z = dynamic_cast<Property<double>*>( bag.find("X_z") );
00214 Property<double>* Y_x = dynamic_cast<Property<double>*>( bag.find("Y_x") );
00215 Property<double>* Y_y = dynamic_cast<Property<double>*>( bag.find("Y_y") );
00216 Property<double>* Y_z = dynamic_cast<Property<double>*>( bag.find("Y_z") );
00217 Property<double>* Z_x = dynamic_cast<Property<double>*>( bag.find("Z_x") );
00218 Property<double>* Z_y = dynamic_cast<Property<double>*>( bag.find("Z_y") );
00219 Property<double>* Z_z = dynamic_cast<Property<double>*>( bag.find("Z_z") );
00220
00221 if ( X_x != 0 && X_y != 0 && X_z != 0 &&
00222 Y_x != 0 && Y_y != 0 && Y_z != 0 &&
00223 Z_x != 0 && Z_y != 0 && Z_z != 0 )
00224 {
00225 res = Rotation(
00226 X_x->get(), Y_x->get(),Z_x->get(),
00227 X_y->get(),Y_y->get(),Z_y->get(),
00228 X_z->get(),Y_z->get(),Z_z->get()
00229 );
00230 return true;
00231 }
00232 }
00233 return false;
00234 }
00235
00240 class EulerZYXDecomposer
00241 {
00242 PropertyBag resultBag;
00243 Property<double> _a;
00244 Property<double> _b;
00245 Property<double> _g;
00246
00247 public:
00248
00249 EulerZYXDecomposer( const Rotation& r);
00250
00251 PropertyBag& result() { return resultBag; }
00252 };
00253
00258 class EulerZYXComposer
00259 {
00260 const PropertyBag& bag;
00261 public:
00262 EulerZYXComposer(const PropertyBag& _bag )
00263 : bag(_bag)
00264 {}
00265
00266 bool getResult( Rotation& res );
00267 };
00268
00269 EulerZYXDecomposer::EulerZYXDecomposer( const Rotation& r)
00270 : resultBag("KDL.Rotation"),
00271 _a("alpha","First Rotate around the Z axis with alpha in radians" ),
00272 _b("beta","Then Rotate around the new Y axis with beta in radians" ),
00273 _g("gamma","Then Rotation around the new X axis with gamma in radians" )
00274 {
00275 r.GetEulerZYX(_a.set(), _b.set(), _g.set());
00276 resultBag.add(_a.clone());
00277 resultBag.add(_b.clone());
00278 resultBag.add(_g.clone());
00279 }
00280
00281 bool EulerZYXComposer::getResult(Rotation& res )
00282 {
00283 if ( bag.getType() == "KDL.Rotation" || bag.getType() == "MotCon::Rotation" )
00284 {
00285
00286
00287 Property<double>* _a = dynamic_cast<Property<double>*>( bag.find("alpha") );
00288 if ( !_a)
00289 _a = dynamic_cast<Property<double>*>( bag.find("Z") );
00290 Property<double>* _b = dynamic_cast<Property<double>*>( bag.find("beta") );
00291 if ( !_b)
00292 _b = dynamic_cast<Property<double>*>( bag.find("Y") );
00293 Property<double>* _g = dynamic_cast<Property<double>*>( bag.find("gamma") );
00294 if ( !_g)
00295 _g = dynamic_cast<Property<double>*>( bag.find("X") );
00296
00297
00298 if ( _a != 0 && _b != 0 && _g != 0 )
00299 {
00300 res = Rotation::EulerZYX(_a->get(), _b->get(), _g->get() );
00301 return true;
00302 } else {
00303 std::string element = !_a ? "alpha" : !_b ? "beta" : "gamma";
00304 Logger::log() << Logger::Error << "Aborting composition of (KDL.EulerZYX) Property< KDL.Rotation > "
00305 << ": Missing element '" <<element<<"'." <<Logger::endl;
00306 return false;
00307 }
00308 }
00309 return false;
00310 }
00311
00316 class RPYDecomposer
00317 {
00318 PropertyBag resultBag;
00319 Property<double> _r;
00320 Property<double> _p;
00321 Property<double> _y;
00322
00323 public:
00324
00325 RPYDecomposer( const Rotation& r);
00326
00327 PropertyBag& result() { return resultBag; }
00328 };
00329
00334 class RPYComposer
00335 {
00336 const PropertyBag& bag;
00337 public:
00338 RPYComposer(const PropertyBag& _bag )
00339 : bag(_bag)
00340 {}
00341
00342 bool getResult( Rotation& res);
00343 };
00344 RPYDecomposer::RPYDecomposer( const Rotation& r)
00345 : resultBag("KDL.Rotation" ),
00346 _r("R","First rotate around X with R(oll) in radians" ),
00347 _p("P","Next rotate around old Y with P(itch) in radians" ),
00348 _y("Y","Next rotate around old Z with Y(aw) in radians" )
00349 {
00350 r.GetRPY(_r.set(), _p.set(), _y.set());
00351 resultBag.add(_r.clone());
00352 resultBag.add(_p.clone());
00353 resultBag.add(_y.clone());
00354 }
00355
00356 bool RPYComposer::getResult(Rotation& res)
00357 {
00358 if ( bag.getType() == "KDL.Rotation" || bag.getType() == "MotCon::Rotation" )
00359 {
00360 Property<double>* _r = dynamic_cast<Property<double>*>( bag.find("R") );
00361 Property<double>* _p = dynamic_cast<Property<double>*>( bag.find("P") );
00362 Property<double>* _y = dynamic_cast<Property<double>*>( bag.find("Y") );
00363
00364
00365 if ( _r != 0 && _p != 0 && _y != 0 )
00366 {
00367 res = Rotation::RPY(_r->get(), _p->get(), _y->get() );
00368 return true;
00369 } else {
00370 std::string element = !_r ? "R" : !_p ? "P" : "Y";
00371 Logger::log() << Logger::Error << "Aborting composition of (KDL.RPY) Property< KDL.Rotation > "
00372 << ": Missing element '" <<element<<"'." <<Logger::endl;
00373 return false;
00374 }
00375 }
00376 return false;
00377 }
00378
00379
00380 void decomposeProperty(const Vector &v, PropertyBag& targetbag)
00381 {
00382
00383 VectorDecomposer vco(v);
00384 targetbag = vco.result();
00385 }
00386
00387 bool composeProperty(const PropertyBag& bag, Vector &v)
00388 {
00389 VectorComposer vas( bag );
00390 return vas.getResult(v);
00391 }
00392
00393 void decomposeProperty(const Rotation &b, PropertyBag& targetbag)
00394 {
00395
00396 #ifdef ROTATION_PROPERTIES_EULER
00397 EulerZYXDecomposer rot(b);
00398 #else
00399 # ifdef ROTATION_PROPERTIES_RPY
00400 RPYDecomposer rot(b);
00401 # else
00402 RotationDecomposer rot(b);
00403 # endif
00404 #endif
00405 targetbag = rot.result();
00406 }
00407
00408 bool composeProperty(const PropertyBag& bag, Rotation &r)
00409 {
00410
00411 RPYComposer rpyc(bag);
00412 EulerZYXComposer eulc(bag);
00413 RotationComposer rotc(bag);
00414
00415 if ( rpyc.getResult( r ) || eulc.getResult( r ) || rotc.getResult( r ) )
00416 return true;
00417 else {
00418 Logger::log() << Logger::Error << "Aborting composition of Property< KDL.Rotation > "
00419 << ": Expected type 'KDL.Rotation', got type '"<< bag.getType() <<"'."
00420 <<Logger::endl;
00421 }
00422 return false;
00423 }
00424
00425 void decomposeProperty(const Twist &t, PropertyBag& targetbag)
00426 {
00427 targetbag.setType("KDL.Twist");
00428
00429 VectorDecomposer vel( t.vel );
00430 VectorDecomposer rot( t.rot );
00431
00432 targetbag.add( new Property<PropertyBag>("vel","Translational Velocity", vel.result() ) );
00433 targetbag.add( new Property<PropertyBag>("rot","Rotational Velocity",rot.result() ));
00434 }
00435
00436 bool composeProperty(const PropertyBag& bag, Twist &t)
00437 {
00438 if ( bag.getType() == "KDL.Twist" || bag.getType() == "MotCon::Twist" )
00439 {
00440
00441
00442 Property<PropertyBag>* subbag = bag.getPropertyType<PropertyBag>("vel");
00443 if (! subbag ) {
00444 Logger::log() << Logger::Error << "Aborting composition of Property< KDL.Twist > "
00445 << ": Trans_Vel not found."
00446 <<Logger::endl;
00447 return false;
00448 }
00449 VectorComposer vas_vel( subbag->value() );
00450
00451 subbag = bag.getPropertyType<PropertyBag>("rot");
00452 if (! subbag ) {
00453 Logger::log() << Logger::Error << "Aborting composition of Property< KDL.Twist > "
00454 << ": Rot_Vel not found."
00455 <<Logger::endl;
00456 return false;
00457 }
00458 VectorComposer vas_rot( subbag->value() );
00459
00460 return vas_vel.getResult( t.vel ) && vas_rot.getResult( t.rot );
00461 } else {
00462 Logger::log() << Logger::Error << "Aborting composition of Property< KDL.Twist > "
00463 << ": Expected type 'KDL.Twist', got type '"<< bag.getType() <<"'."
00464 <<Logger::endl;
00465 }
00466 return false;
00467 }
00468
00469 void decomposeProperty(const Wrench &b, PropertyBag& targetbag)
00470 {
00471
00472 targetbag.setType("KDL.Wrench");
00473
00474 VectorDecomposer force( b.force );
00475 VectorDecomposer torque( b.torque );
00476
00477 targetbag.add( new Property<PropertyBag>("force", "Axial Force", force.result() ) );
00478 targetbag.add( new Property<PropertyBag>("torque", "Axial Torque", torque.result() ) );
00479 }
00480
00481 bool composeProperty(const PropertyBag& bag,Wrench &w)
00482 {
00483 if ( bag.getType() == "KDL.Wrench" || bag.getType() == "Motcon::Wrench")
00484 {
00485
00486
00487 Property<PropertyBag>* subbag = bag.getPropertyType<PropertyBag>("force");
00488 if (! subbag ) {
00489 Logger::log() << Logger::Error << "Aborting composition of Property< KDL.Wrench > "
00490 << ": Force not found."
00491 <<Logger::endl;
00492 return false;
00493 }
00494 VectorComposer vas_force( subbag->value() );
00495
00496 subbag = bag.getPropertyType<PropertyBag>("torque");
00497 if (! subbag ) {
00498 Logger::log() << Logger::Error << "Aborting composition of Property< KDL.Wrench > "
00499 << ": Torque not found."
00500 <<Logger::endl;
00501 return false;
00502 }
00503 VectorComposer vas_torque( subbag->value() );
00504
00505 return vas_force.getResult( w.force ) && vas_torque.getResult( w.torque );
00506 } else {
00507 Logger::log() << Logger::Error << "Aborting composition of Property< KDL.Wrench > "
00508 << ": Expected type 'KDL.Wrench', got type '"<< bag.getType() <<"'."
00509 <<Logger::endl;
00510 return false;
00511 }
00512 return false;
00513 }
00514
00515 void decomposeProperty(const KDL::Frame &f, PropertyBag& targetbag )
00516 {
00517
00518 targetbag.setType("KDL.Frame");
00519
00520 VectorDecomposer vel( f.p );
00521 #ifdef ROTATION_PROPERTIES_EULER
00522 EulerZYXDecomposer rot( f.M );
00523 #else
00524 # ifdef ROTATION_PROPERTIES_RPY
00525 RPYDecomposer rot( f.M );
00526 # else
00527 RotationDecomposer rot( f.M );
00528 # endif
00529 #endif
00530
00531 targetbag.add( new Property<PropertyBag>("p","", vel.result() ) );
00532 targetbag.add( new Property<PropertyBag>("M","", rot.result() ) );
00533 }
00534
00535 bool composeProperty(const PropertyBag& f_bag, KDL::Frame &f)
00536 {
00537 if ( f_bag.getType() == "KDL.Frame" || f_bag.getType() == "MotCon::Frame" )
00538 {
00539
00540 Property<PropertyBag>* subbag = f_bag.getPropertyType<PropertyBag>("p");
00541 if (! subbag ) {
00542 Logger::log() << Logger::Error << "Aborting composition of Property< KDL.Frame > "
00543 << ": Position not found."
00544 <<Logger::endl;
00545 return false;
00546 }
00547 VectorComposer vas_pos( subbag->value() );
00548
00549 subbag = f_bag.getPropertyType<PropertyBag>("M");
00550 if (! subbag ) {
00551 Logger::log() << Logger::Error << "Aborting composition of Property< KDL.Frame > "
00552 << ": Rotation not found."
00553 <<Logger::endl;
00554 return false;
00555 }
00556 RPYComposer vas_rpy( subbag->value() );
00557 EulerZYXComposer vas_eul( subbag->value() );
00558 RotationComposer vas_rot( subbag->value() );
00559 bool result = vas_pos.getResult( f.p );
00560 if (!result )
00561 {
00562 Logger::log() << Logger::Error << "Aborting composition of Property< KDL.Frame > "
00563 << ": element 'Position' has wrong format." <<Logger::endl;
00564 return false;
00565 }
00566 result = vas_rpy.getResult( f.M) ||
00567 vas_eul.getResult( f.M ) ||
00568 vas_rot.getResult( f.M );
00569 if (!result )
00570 {
00571 Logger::log()
00572 << Logger::Error << "Aborting composition of Property< KDL.Frame > "
00573 << ": Could not compose 'Rotation' type 'KDL.Rotation','KDL.EulerZYX' or 'KDL.RPY', got type '"
00574 << subbag->get().getType() <<"'."<<Logger::endl;
00575 return false;
00576 }
00577
00578 return true;
00579 } else {
00580 Logger::log() << Logger::Error << "Aborting composition of Property< KDL.Frame > "
00581 << ": Expected type 'KDL.Frame', got type '"<< f_bag.getType() <<"'."
00582 <<Logger::endl;
00583 return false;
00584 }
00585 return false;
00586 }
00587
00588 }