00001 /***************************************************************************/ 00008 #include "robodyn_controllers/RobotURDF.h" 00009 00010 /***************************************************************************/ 00020 RobotURDF::RobotURDF(const std::string& filename, const std::string& rootLink) : Robot() 00021 { 00022 parseFile(filename, rootLink); 00023 } 00024 00025 /***************************************************************************/ 00030 RobotURDF::~RobotURDF() 00031 { 00032 // linkMap.clear(); 00033 // jointMap.clear(); 00034 } 00035 00036 /***************************************************************************/ 00049 void RobotURDF::parseFile(const std::string& filename, const std::string& rootLink) 00050 { 00051 TiXmlDocument file(filename.c_str()); 00052 00053 if (!file.LoadFile()) 00054 { 00055 std::stringstream err; 00056 err << "RobotURDF::parseFile could not load file " << filename; 00057 NasaCommonLogging::Logger::log("gov.nasa.controllers.RobotURDF", log4cpp::Priority::ERROR, err.str()); 00058 throw std::runtime_error(err.str()); 00059 return; 00060 } 00061 00062 TiXmlHandle doc(&file); 00063 TiXmlElement* robotElement; 00064 TiXmlElement* curElement; 00065 00066 robotElement = doc.FirstChildElement("robot").Element(); 00067 00068 if (robotElement == NULL) 00069 { 00070 std::stringstream err; 00071 err << "RobotURDF::parseFile provided file does not contain a robot definition, file " << filename; 00072 NasaCommonLogging::Logger::log("gov.nasa.controllers.RobotURDF", log4cpp::Priority::ERROR, err.str()); 00073 throw std::runtime_error(err.str()); 00074 return; 00075 } 00076 00077 // PVDEBUG("RobotURDF::parseFile loading configuration for robot %s\n", robotElement->Attribute("name")); 00078 00079 // load the links 00080 // curElement = robotElement->FirstChildElement("link"); 00081 // while (curElement != NULL) 00082 // { 00083 // parseLink(curElement); 00084 // curElement = curElement->NextSiblingElement("link"); 00085 // } 00086 00087 // load the joints 00088 curElement = robotElement->FirstChildElement("joint"); 00089 00090 while (curElement != NULL) 00091 { 00092 parseJoint(curElement); 00093 curElement = curElement->NextSiblingElement("joint"); 00094 } 00095 00096 if (!kdl_parser::treeFromFile(filename, robotTree)) 00097 { 00098 std::stringstream err; 00099 err << "RobotURDF::parseFile provided file does not contain a robot definition, file " << filename; 00100 NasaCommonLogging::Logger::log("gov.nasa.controllers.RobotURDF", log4cpp::Priority::ERROR, err.str()); 00101 throw std::runtime_error(err.str()); 00102 } 00103 00104 // PVDEBUG("RobotURDF::parseFile file loaded\n"); 00105 // 00106 // // build the tree 00107 // 00108 // JointMap joints; 00109 // getChildJoints(rootLink, &joints); 00110 // 00111 // PVDEBUG("RobotURDF::parseFile building KDL Tree\n"); 00112 // JointMap::iterator ittr; 00113 // for(ittr = joints.begin(); ittr != joints.end(); ittr++) 00114 // { 00115 // KDL::Chain chain; 00116 // buildTree(chain, ittr->first, "root", 00117 // ittr->first, ittr->second); 00118 // } 00119 // PVDEBUG("RobotURDF::parseFile KDL Tree complete\n"); 00120 } 00121 00122 /***************************************************************************/ 00161 //void RobotURDF::buildTree(KDL::Chain& chain, const std::string chainName, 00162 // const std::string chainHook, const std::string jointName, 00163 // const Joint& baseJoint) 00164 //{ 00165 // if (linkMap.find(baseJoint.child) == linkMap.end()) 00166 // { 00167 // PDEBUG("RobotURDF::buildTree missing child link (%s) of joint %s, assuming NULL link\n", 00168 // baseJoint.child.c_str(), jointName.c_str()); 00169 // 00170 // KDL::Segment halfSeg(KDL::Segment("NullLink", KDL::Joint(jointName, baseJoint.type), 00171 // KDL::Frame(KDL::Rotation::RPY(0.0, 0.0, 0.0), KDL::Vector(0.0, 0.0, 0.0)), 00172 // KDL::RigidBodyInertia() )); 00173 // 00174 // chain.addSegment(halfSeg); 00175 // 00176 // PVDEBUG("RobotURDF::buildTree -------- addChain: %s [null]\n", chainName.c_str()); 00177 // addChain(chainName, chain, chainHook); 00178 // } 00179 // else 00180 // { 00181 // KDL::RigidBodyInertia childLink = linkMap.find(baseJoint.child)->second; 00182 // 00183 // JointMap joints; 00184 // getChildJoints(baseJoint.child, &joints); 00185 // 00186 // if (joints.size() == 0) 00187 // { 00188 // KDL::Segment lastSeg(KDL::Segment(baseJoint.child, KDL::Joint(jointName, baseJoint.type), 00189 // KDL::Frame(KDL::Rotation::RPY(0.0, 0.0, 0.0), KDL::Vector(0.0, 0.0, 0.0)), childLink)); 00190 // 00191 // chain.addSegment(lastSeg); 00192 // 00193 // PVDEBUG("RobotURDF::buildTree -------- addChain: %s [end]\n", chainName.c_str()); 00194 // addChain(chainName, chain, chainHook); 00195 // } 00196 // else if (joints.size() == 1) 00197 // { 00198 // KDL::Segment midSeg(KDL::Segment(baseJoint.child, KDL::Joint(jointName, baseJoint.type), 00199 // joints.begin()->second.frame, childLink)); 00200 // 00201 // chain.addSegment(midSeg); 00202 // 00203 // buildTree(chain, chainName, chainHook, 00204 // joints.begin()->first, joints.begin()->second); 00205 // } 00206 // else 00207 // { 00208 // KDL::Segment tailSeg(baseJoint.child, KDL::Joint(jointName, baseJoint.type), 00209 // KDL::Frame(KDL::Rotation::RPY(0.0, 0.0, 0.0), KDL::Vector(0.0, 0.0, 0.0)), childLink); 00210 // PVDEBUG("RobotURDF::buildTree -------- addChain: %s [split]\n", chainName.c_str()); 00211 // chain.addSegment(tailSeg); 00212 // 00213 // addChain(chainName, chain, chainHook); 00214 // JointMap::iterator ittr; 00215 // for(ittr = joints.begin(); ittr != joints.end(); ittr++) 00216 // { 00217 // KDL::Chain schain; 00218 // buildTree(schain, ittr->second.child, chain.segments[chain.getNrOfSegments() -1].getName(), 00219 // ittr->first, ittr->second); 00220 // } 00221 // } 00222 // } 00223 //} 00224 00225 /***************************************************************************/ 00235 //void RobotURDF::getChildJoints(std::string parentName, JointMap *jnts) 00236 //{ 00237 // jnts->clear(); 00238 // 00239 // JointMap::iterator ittr; 00240 // for (ittr = jointMap.begin(); ittr != jointMap.end(); ittr++) 00241 // { 00242 // if (ittr->second.parent.compare(parentName) == 0) 00243 // { 00244 // jnts->insert(std::pair<std::string, Joint>(ittr->first, ittr->second)); 00245 // } 00246 // } 00247 //} 00248 00249 /***************************************************************************/ 00257 //void RobotURDF::parseLink(TiXmlElement *element) 00258 //{ 00259 // PVDEBUG("RobotURDF::parseLink %s\n", element->Attribute("name") ); 00260 // 00261 // double mass = 0.0; 00262 // double ixx, ixy, ixz, iyy, iyz, izz = 0.0; 00263 // 00264 // TiXmlElement *inertial = element->FirstChildElement("inertial"); 00265 // 00266 // if (inertial == NULL) 00267 // { 00268 // PDEBUG("RobotURDF::parseLink URDF format incomplete, link %s does not contain an inertial child, using default inertial", 00269 // element->Attribute("name")); 00270 // } 00271 // else 00272 // { 00273 // TiXmlElement *child = inertial->FirstChildElement("mass"); 00274 // if (child == NULL) 00275 // { 00276 // PDEBUG("RobotURDF::parseLink URDF format incomplete, link %s does not contain a mass element, using default mass", 00277 // element->Attribute("name")); 00278 // } 00279 // else 00280 // { 00281 // child->QueryDoubleAttribute("value", &mass); 00282 // } 00283 // 00284 // child = inertial->FirstChildElement("inertia"); 00285 // if (child == NULL) 00286 // { 00287 // PDEBUG("RobotURDF::parseLink URDF format incomplete, link %s does not contain an inertia element, using default inertia", 00288 // element->Attribute("name")); 00289 // } 00290 // else 00291 // { 00292 // child->QueryDoubleAttribute("ixx", &ixx); 00293 // child->QueryDoubleAttribute("ixy", &ixy); 00294 // child->QueryDoubleAttribute("ixz", &ixz); 00295 // child->QueryDoubleAttribute("iyy", &iyy); 00296 // child->QueryDoubleAttribute("iyz", &iyz); 00297 // child->QueryDoubleAttribute("izz", &izz); 00298 // } 00299 // 00300 // child = inertial->FirstChildElement("origin"); 00301 // if (child != NULL) 00302 // { 00303 // // Currently, the origin element is not used by us, so print a warning 00304 // // if someone is using it. Code could be added to support this, but I 00305 // // don't know how to turn the optional xyz and optional rpy elements 00306 // // of the origin into a single KDL::Vector. 00307 // PDEBUG("RobotURDF::parseLink URDF format unsupported, link %s contains an unsupported origin element that will be ignored\n", 00308 // element->Attribute("name")); 00309 // PDEBUG(" rpy=%s\n", child->Attribute("rpy")); 00310 // PDEBUG(" xyz=%s\n", child->Attribute("xyz")); 00311 // } 00312 // } 00313 // 00314 // linkMap[element->Attribute("name")] = KDL::RigidBodyInertia(mass, KDL::Vector(0,0,0), 00315 // KDL::RotationalInertia(ixx, ixy, ixz, iyy, iyz, izz)); 00316 //} 00317 00318 /***************************************************************************/ 00326 void RobotURDF::parseJoint(TiXmlElement* element) 00327 { 00328 // PVDEBUG("RobotURDF::parseJoint %s\n", element->Attribute("name") ); 00329 00330 // Joint joint; 00331 TiXmlElement* elmnt; 00332 00333 // Get the joint axis, if not specified, z will be used 00334 // int axis_x, axis_y, axis_z = 0; 00335 // elmnt = element->FirstChildElement("axis"); 00336 // if (elmnt != NULL) 00337 // { 00338 // const char *aval = elmnt->Attribute("xyz"); 00339 // if (aval != NULL) 00340 // { 00341 // std::stringstream a; 00342 // a << aval; 00343 // a >> axis_x; 00344 // a >> axis_y; 00345 // a >> axis_z; 00346 // } 00347 // } 00348 00349 // get the joint type 00350 const char* jtype = element->Attribute("type"); 00351 // if (strcmp(jtype, "revolute" ) == 0) 00352 // { 00353 // if (axis_x != 0) joint.type = KDL::Joint::RotX; 00354 // else if (axis_y != 0) joint.type = KDL::Joint::RotY; 00355 // else joint.type = KDL::Joint::RotZ; 00356 // } 00357 // else if (strcmp(jtype, "prismatic" ) == 0) 00358 // { 00359 // if (axis_x != 0) joint.type = KDL::Joint::TransX; 00360 // else if (axis_y != 0) joint.type = KDL::Joint::TransY; 00361 // else joint.type = KDL::Joint::TransZ; 00362 // } 00363 // else if (strcmp(jtype, "fixed" ) == 0) 00364 // { 00365 // joint.type = KDL::Joint::None; 00366 // } 00367 // else 00368 // { 00369 // // KDL::Joint::TransAxis and KDL::Joint::RotAxis throw exceptions in KDL::Joint so don't 00370 // // bother with them, just throw an exception now. So URDF continuous and planar have no 00371 // // useful mapping. 00372 // THROW_RUNTIME("RobotURDF::parseJoint found a joint type %s, that does not translate to known KDL joint", 00373 // jtype); 00374 // } 00375 // 00376 // get the links that this joint connects 00377 // elmnt = element->FirstChildElement("parent"); 00378 // if (elmnt == NULL) 00379 // { 00380 // THROW_RUNTIME("RobotURDF::parseJoint URDF format error, joint %s does not contain a parent element", 00381 // element->Attribute("name")); 00382 // } 00383 // joint.parent = std::string(elmnt->Attribute("link")); 00384 // 00385 // elmnt = element->FirstChildElement("child"); 00386 // if (elmnt == NULL) 00387 // { 00388 // THROW_RUNTIME("RobotURDF::parseJoint URDF format error, joint %s does not contain a child element", 00389 // element->Attribute("name")); 00390 // } 00391 // joint.child = std::string(elmnt->Attribute("link")); 00392 00393 // double roll, pitch, yaw, x, y, z = 0.0; 00394 // elmnt = element->FirstChildElement("origin"); 00395 // if (elmnt == NULL) 00396 // { 00397 // PDEBUG("RobotURDF::parseJoint URDF format incomplete, joint %s does not contain an origin element, using default origin", 00398 // element->Attribute("name")); 00399 // } 00400 // else 00401 // { 00402 // 00403 // const char *vval = elmnt->Attribute("xyz"); 00404 // if (vval != NULL) 00405 // { 00406 // std::stringstream a; 00407 // a << vval; 00408 // a >> x; 00409 // a >> y; 00410 // a >> z; 00411 // } 00412 // 00413 // const char *rval = elmnt->Attribute("rpy"); 00414 // if (rval != NULL) 00415 // { 00416 // std::stringstream a; 00417 // a << rval; 00418 // a >> roll; 00419 // a >> pitch; 00420 // a >> yaw; 00421 // } 00422 // 00423 // const char *rotm = elmnt->Attribute("rotm"); 00424 // if (rotm != NULL) 00425 // { 00426 // double xx, xy, xz, yx, yy, yz, zx, zy, zz = 0.0; 00427 // std::stringstream a; 00428 // a << rotm; 00429 // a >> xx; 00430 // a >> xy; 00431 // a >> xz; 00432 // a >> yx; 00433 // a >> yy; 00434 // a >> yz; 00435 // a >> zx; 00436 // a >> zy; 00437 // a >> zz; 00438 // 00439 // KDL::Rotation r(xx, xy, xz, yx, yy, yz, zx, zy, zz); 00440 // 00441 // double mr, mp, my; 00442 // r.GetRPY(mr, mp, my); 00443 // 00444 // printf(" %s rotm -> rpy=\"%10.6f %10.6f %10.6f\"\n", element->Attribute("name"), mr, mp, my); 00445 // } 00446 // } 00447 // joint.frame = KDL::Frame(KDL::Rotation::RPY(roll, pitch, yaw), KDL::Vector(x, y, z)); 00448 00449 if ((strcmp(jtype, "revolute" ) == 0) || (strcmp(jtype, "prismatic" ) == 0)) 00450 { 00451 JointTraits* data = addJoint(element->Attribute("name")); 00452 00453 elmnt = element->FirstChildElement("limit"); 00454 00455 if (elmnt == NULL) 00456 { 00457 // PDEBUG("RobotURDF::parseJoint URDF format incomplete, joint %s does not contain a limit element, using default limits", 00458 // element->Attribute("name")); 00459 } 00460 else 00461 { 00462 elmnt->QueryDoubleAttribute("lower", &data->minPosition); 00463 elmnt->QueryDoubleAttribute("upper", &data->maxPosition); 00464 elmnt->QueryDoubleAttribute("velocity", &data->maxVelocity); 00465 elmnt->QueryDoubleAttribute("effort", &data->maxTorque); 00466 } 00467 00468 elmnt = element->FirstChildElement("traits"); 00469 00470 if (elmnt == NULL) 00471 { 00472 data->springConstant = 10.0; 00473 data->type = "SuperDriver"; 00474 } 00475 else 00476 { 00477 elmnt->QueryDoubleAttribute("spring_k", &data->springConstant); 00478 00479 if (elmnt->Attribute("type")) 00480 { 00481 data->type = std::string(elmnt->Attribute("type")); 00482 } 00483 00484 if (data->type == "") 00485 { 00486 data->type = "SuperDriver"; 00487 } 00488 } 00489 } 00490 00491 // ad the joint to the map 00492 // jointMap[element->Attribute("name")] = joint; 00493 } 00494