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 #include <gazebo/urdf2gazebo.h>
00036 #include "ros/ros.h"
00037 #include "ros/package.h"
00038 #include <fstream>
00039 #include <sstream>
00040
00041 #undef TO_SDF
00042 #ifdef TO_SDF
00043 #include "common/SystemPaths.hh"
00044 #include "sdf/interface/parser.hh"
00045 #include "sdf/interface/parser_deprecated.hh"
00046 #endif
00047
00048 using namespace urdf2gazebo;
00049
00050 URDF2Gazebo::URDF2Gazebo()
00051 {
00052 #ifdef TO_SDF
00053
00054 std::list<std::string> paths = gazebo::common::SystemPaths::Instance()->GetGazeboPaths();
00055 std::vector<std::string> gazebo_media_paths;
00056 ros::package::getPlugins("gazebo","gazebo_media_path",gazebo_media_paths);
00057 for (std::vector<std::string>::iterator iter=gazebo_media_paths.begin(); iter != gazebo_media_paths.end(); iter++)
00058 {
00059 ROS_DEBUG("med path %s",iter->c_str());
00060
00061
00062
00063 bool found = false;
00064 for (std::list<std::string>::const_iterator p_iter = paths.begin();
00065 p_iter != paths.end(); ++p_iter)
00066 {
00067 if ((*p_iter) == (*iter))
00068 {
00069 found = true;
00070 break;
00071 }
00072 }
00073 if (!found)
00074 gazebo::common::SystemPaths::Instance()->AddGazeboPaths(iter->c_str());
00075 }
00076 #endif
00077 }
00078
00079 URDF2Gazebo::~URDF2Gazebo()
00080 {
00081 }
00082
00083
00084 urdf::Vector3 URDF2Gazebo::parseVector3(TiXmlNode* key, double scale)
00085 {
00086 if (key != NULL)
00087 {
00088 std::string str = key->Value();
00089 std::vector<std::string> pieces;
00090 std::vector<double> vals;
00091
00092 boost::split(pieces, str, boost::is_any_of(" "));
00093 for (unsigned int i = 0; i < pieces.size(); ++i)
00094 {
00095 if (pieces[i] != "")
00096 {
00097 try
00098 {
00099 vals.push_back(scale * boost::lexical_cast<double>(pieces[i].c_str()));
00100 }
00101 catch(boost::bad_lexical_cast &e)
00102 {
00103 ROS_ERROR("xml key [%s][%d] value [%s] is not a valid double from a 3-tuple\n",str.c_str(),i,pieces[i].c_str());
00104 return urdf::Vector3(0,0,0);
00105 }
00106 }
00107 }
00108 return urdf::Vector3(vals[0],vals[1],vals[3]);
00109 }
00110 else
00111 return urdf::Vector3(0,0,0);
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 }
00143
00144 void URDF2Gazebo::addVisual(boost::shared_ptr<urdf::Link> link, std::string group_name, boost::shared_ptr<urdf::Visual> visual)
00145 {
00146 boost::shared_ptr<std::vector<boost::shared_ptr<urdf::Visual > > > viss = link->getVisuals(group_name);
00147 if (!viss)
00148 {
00149
00150 viss.reset(new std::vector<boost::shared_ptr<urdf::Visual > >);
00151
00152 link->visual_groups.insert(make_pair(group_name,viss));
00153 ROS_DEBUG("successfully added a new visual group name '%s'",group_name.c_str());
00154 }
00155
00156
00157 std::vector<boost::shared_ptr<urdf::Visual > >::iterator vis_it = find(viss->begin(),viss->end(),visual);
00158 if (vis_it != viss->end())
00159 ROS_WARN("attempted to add a visual that already exists under group name '%s', skipping.",group_name.c_str());
00160 else
00161 viss->push_back(visual);
00162 ROS_DEBUG("successfully added a new visual under group name '%s'",group_name.c_str());
00163
00164 }
00165
00166 void URDF2Gazebo::addCollision(boost::shared_ptr<urdf::Link> link, std::string group_name, boost::shared_ptr<urdf::Collision> collision)
00167 {
00168 boost::shared_ptr<std::vector<boost::shared_ptr<urdf::Collision > > > viss = link->getCollisions(group_name);
00169 if (!viss)
00170 {
00171
00172 viss.reset(new std::vector<boost::shared_ptr<urdf::Collision > >);
00173
00174 link->collision_groups.insert(make_pair(group_name,viss));
00175 ROS_DEBUG("successfully added a new collision group name '%s'",group_name.c_str());
00176 }
00177
00178
00179 std::vector<boost::shared_ptr<urdf::Collision > >::iterator vis_it = find(viss->begin(),viss->end(),collision);
00180 if (vis_it != viss->end())
00181 ROS_WARN("attempted to add a collision that already exists under group name '%s', skipping.",group_name.c_str());
00182 else
00183 viss->push_back(collision);
00184 ROS_DEBUG("successfully added a new collision under group name '%s'",group_name.c_str());
00185
00186 }
00187
00188
00189
00190 std::string URDF2Gazebo::vector32str(const urdf::Vector3 vector, double (*conv)(double) = NULL)
00191 {
00192 std::stringstream ss;
00193 ss << (conv ? conv(vector.x) : vector.x);
00194 ss << " ";
00195 ss << (conv ? conv(vector.y) : vector.y);
00196 ss << " ";
00197 ss << (conv ? conv(vector.z) : vector.z);
00198 return ss.str();
00199 }
00200
00201 std::string URDF2Gazebo::values2str(unsigned int count, const double *values, double (*conv)(double) = NULL)
00202 {
00203 std::stringstream ss;
00204 for (unsigned int i = 0 ; i < count ; i++)
00205 {
00206 if (i > 0)
00207 ss << " ";
00208 ss << (conv ? conv(values[i]) : values[i]);
00209 }
00210 return ss.str();
00211 }
00212
00213 void URDF2Gazebo::addKeyValue(TiXmlElement *elem, const std::string& key, const std::string &value)
00214 {
00215 TiXmlElement* child_elem = elem->FirstChildElement(key);
00216 if (child_elem)
00217 {
00218 std::string old_value = getGazeboValue(child_elem);
00219 if (old_value != value)
00220 ROS_WARN("multiple inconsistent <%s> exists due to fixed joint reduction, overwriting previous value [%s] with [%s].",key.c_str(),old_value.c_str(),value.c_str());
00221 else
00222 ROS_DEBUG("multiple <%s> exists due to fixed joint reduction, overwriting previous value.",key.c_str());
00223 elem->RemoveChild(child_elem);
00224 }
00225
00226 TiXmlElement *ekey = new TiXmlElement(key);
00227 TiXmlText *text_ekey = new TiXmlText(value);
00228 ekey->LinkEndChild(text_ekey);
00229 elem->LinkEndChild(ekey);
00230 }
00231
00232 void URDF2Gazebo::addTransform(TiXmlElement *elem, const::gazebo::math::Pose& transform)
00233 {
00234 double cpos[3] = { transform.pos.x, transform.pos.y, transform.pos.z };
00235 gazebo::math::Vector3 e = transform.rot.GetAsEuler();
00236 double crot[3] = { e.x, e.y, e.z };
00237
00238
00239
00240
00241
00242
00243
00244
00245 addKeyValue(elem, "xyz", values2str(3, cpos));
00246 addKeyValue(elem, "rpy", values2str(3, crot, rad2deg));
00247 }
00248
00249 std::string URDF2Gazebo::getGazeboValue(TiXmlElement* elem)
00250 {
00251 std::string value_str;
00252 if (elem->Attribute("value"))
00253 {
00254 value_str = elem->Attribute("value");
00255 }
00256 else if(elem->FirstChild())
00257 {
00258 value_str = elem->FirstChild()->ValueStr();
00259 }
00260 return value_str;
00261 }
00262
00263 void URDF2Gazebo::parseGazeboExtension(TiXmlDocument &urdf_in)
00264 {
00265 ROS_DEBUG("parsing gazebo extension");
00266 TiXmlElement* robot_xml = urdf_in.FirstChildElement("robot");
00267
00268
00269 for (TiXmlElement* gazebo_xml = robot_xml->FirstChildElement("gazebo"); gazebo_xml; gazebo_xml = gazebo_xml->NextSiblingElement("gazebo"))
00270 {
00271 const char* ref = gazebo_xml->Attribute("reference");
00272 std::string ref_str;
00273 if (!ref)
00274 {
00275 ROS_DEBUG("parsing gazebo extension for robot, reference is not specified");
00276
00277 ref_str.clear();
00278 }
00279 else
00280 {
00281 ROS_DEBUG("parsing gazebo extension for %s",ref);
00282
00283 ref_str = std::string(ref);
00284 }
00285
00286 if (this->gazebo_extensions_.find(ref_str) == this->gazebo_extensions_.end())
00287 {
00288 std::vector<GazeboExtension*> extensions;
00289 ROS_DEBUG("extension map for reference [%s] does not exist yet, creating new extension map",ref);
00290 this->gazebo_extensions_.insert(std::make_pair( ref_str, extensions ) );
00291 }
00292
00293
00294 GazeboExtension* gazebo = new GazeboExtension();
00295
00296
00297
00298 for (TiXmlElement *child_elem = gazebo_xml->FirstChildElement(); child_elem; child_elem = child_elem->NextSiblingElement())
00299 {
00300 ROS_DEBUG("child element : %s ", child_elem->ValueStr().c_str());
00301
00302 gazebo->original_reference = ref_str;
00303
00304
00305
00306
00307 if (child_elem->ValueStr() == "material")
00308 {
00309 gazebo->material = getGazeboValue(child_elem);
00310 ROS_DEBUG(" material %s",gazebo->material.c_str());
00311 }
00312 else if (child_elem->ValueStr() == "static")
00313 {
00314 std::string value_str = getGazeboValue(child_elem);
00315
00316
00317 if (value_str == "true" || value_str == "True" || value_str == "TRUE" || value_str == "yes" || value_str == "1")
00318 gazebo->setStaticFlag = true;
00319 else
00320 gazebo->setStaticFlag = false;
00321
00322 ROS_DEBUG(" setStaticFlag %d",gazebo->setStaticFlag);
00323
00324 }
00325 else if (child_elem->ValueStr() == "turnGravityOff")
00326 {
00327 std::string value_str = getGazeboValue(child_elem);
00328
00329
00330 if (value_str == "true" || value_str == "True" || value_str == "TRUE" || value_str == "yes" || value_str == "1")
00331 gazebo->turnGravityOff = true;
00332 else
00333 gazebo->turnGravityOff = false;
00334
00335 ROS_DEBUG(" turnGravityOff %d",gazebo->turnGravityOff);
00336
00337 }
00338 else if (child_elem->ValueStr() == "dampingFactor")
00339 {
00340 gazebo->is_dampingFactor = true;
00341 gazebo->dampingFactor = atof(getGazeboValue(child_elem).c_str());
00342 ROS_DEBUG(" dampingFactor %f",gazebo->dampingFactor);
00343 }
00344 else if (child_elem->ValueStr() == "maxVel")
00345 {
00346 gazebo->is_maxVel = true;
00347 gazebo->maxVel = atof(getGazeboValue(child_elem).c_str());
00348 ROS_DEBUG(" maxVel %f",gazebo->maxVel);
00349 }
00350 else if (child_elem->ValueStr() == "minDepth")
00351 {
00352 gazebo->is_minDepth = true;
00353 gazebo->minDepth = atof(getGazeboValue(child_elem).c_str());
00354 ROS_DEBUG(" minDepth %f",gazebo->minDepth);
00355 }
00356 else if (child_elem->ValueStr() == "mu1")
00357 {
00358 gazebo->is_mu1 = true;
00359 gazebo->mu1 = atof(getGazeboValue(child_elem).c_str());
00360 ROS_DEBUG(" mu1 %f",gazebo->mu1);
00361 }
00362 else if (child_elem->ValueStr() == "mu2")
00363 {
00364 gazebo->is_mu2 = true;
00365 gazebo->mu2 = atof(getGazeboValue(child_elem).c_str());
00366 ROS_DEBUG(" mu2 %f",gazebo->mu2);
00367 }
00368 else if (child_elem->ValueStr() == "fdir1")
00369 {
00370 gazebo->fdir1 = getGazeboValue(child_elem);
00371 ROS_DEBUG(" fdir1 %s",gazebo->fdir1.c_str());
00372 }
00373 else if (child_elem->ValueStr() == "kp")
00374 {
00375 gazebo->is_kp = true;
00376 gazebo->kp = atof(getGazeboValue(child_elem).c_str());
00377 ROS_DEBUG(" kp %f",gazebo->kp);
00378 }
00379 else if (child_elem->ValueStr() == "kd")
00380 {
00381 gazebo->is_kd = true;
00382 gazebo->kd = atof(getGazeboValue(child_elem).c_str());
00383 ROS_DEBUG(" kd %f",gazebo->kd);
00384 }
00385 else if (child_elem->ValueStr() == "genTexCoord")
00386 {
00387 std::string value_str = getGazeboValue(child_elem);
00388
00389
00390 if (value_str == "true" || value_str == "True" || value_str == "TRUE" || value_str == "yes" || value_str == "1")
00391 gazebo->genTexCoord = true;
00392 else
00393 gazebo->genTexCoord = false;
00394
00395 ROS_DEBUG(" genTexCoord %d",gazebo->genTexCoord);
00396
00397 }
00398 else if (child_elem->ValueStr() == "selfCollide")
00399 {
00400 std::string value_str = getGazeboValue(child_elem);
00401
00402
00403 if (value_str == "true" || value_str == "True" || value_str == "TRUE" || value_str == "yes" || value_str == "1")
00404 gazebo->selfCollide = true;
00405 else
00406 gazebo->selfCollide = false;
00407
00408 ROS_DEBUG(" selfCollide %d",gazebo->selfCollide);
00409
00410 }
00411 else if (child_elem->ValueStr() == "laserRetro")
00412 {
00413 gazebo->is_laserRetro = true;
00414 gazebo->laserRetro = atof(getGazeboValue(child_elem).c_str());
00415 ROS_DEBUG(" laserRetro %f",gazebo->laserRetro);
00416 }
00417 else if (child_elem->ValueStr() == "stopKp")
00418 {
00419 gazebo->is_stopKp = true;
00420 gazebo->stopKp = atof(getGazeboValue(child_elem).c_str());
00421 ROS_DEBUG(" stopKp %f",gazebo->stopKp);
00422 }
00423 else if (child_elem->ValueStr() == "stopKd")
00424 {
00425 gazebo->is_stopKd = true;
00426 gazebo->stopKd = atof(getGazeboValue(child_elem).c_str());
00427 ROS_DEBUG(" stopKd %f",gazebo->stopKd);
00428 }
00429 else if (child_elem->ValueStr() == "initial_joint_position")
00430 {
00431 gazebo->is_initial_joint_position = true;
00432 gazebo->initial_joint_position = atof(getGazeboValue(child_elem).c_str());
00433 ROS_DEBUG(" initial_joint_position %f",gazebo->initial_joint_position);
00434 }
00435 else if (child_elem->ValueStr() == "fudgeFactor")
00436 {
00437 gazebo->is_fudgeFactor = true;
00438 gazebo->fudgeFactor = atof(getGazeboValue(child_elem).c_str());
00439 ROS_DEBUG(" fudgeFactor %f",gazebo->fudgeFactor);
00440 }
00441 else if (child_elem->ValueStr() == "provideFeedback")
00442 {
00443 std::string value_str = getGazeboValue(child_elem);
00444
00445 if (value_str == "true" || value_str == "True" || value_str == "TRUE" || value_str == "yes" || value_str == "1")
00446 gazebo->provideFeedback = true;
00447 else
00448 gazebo->provideFeedback = false;
00449
00450 ROS_DEBUG(" provideFeedback %d",(int)gazebo->provideFeedback);
00451 }
00452 else
00453 {
00454 std::ostringstream stream;
00455 stream << *child_elem;
00456
00457 TiXmlElement *blob = new TiXmlElement(*child_elem);
00458 gazebo->blobs.push_back(blob);
00459 ROS_DEBUG(" blobs %s",stream.str().c_str());
00460 }
00461 }
00462
00463
00464 (this->gazebo_extensions_.find(ref_str))->second.push_back(gazebo);
00465 }
00466 }
00467
00468 void URDF2Gazebo::insertGazeboExtensionGeom(TiXmlElement *elem,std::string link_name)
00469 {
00470 for (std::map<std::string,std::vector<GazeboExtension*> >::iterator gazebo_it = this->gazebo_extensions_.begin();
00471 gazebo_it != this->gazebo_extensions_.end(); gazebo_it++)
00472 {
00473 for (std::vector<GazeboExtension*>::iterator ge = gazebo_it->second.begin(); ge != gazebo_it->second.end(); ge++)
00474 {
00475 if ((*ge)->original_reference == link_name)
00476 {
00477
00478 if ((*ge)->is_mu1)
00479 addKeyValue(elem, "mu1", values2str(1, &(*ge)->mu1) );
00480 if ((*ge)->is_mu2)
00481 addKeyValue(elem, "mu2", values2str(1, &(*ge)->mu2) );
00482 if (!(*ge)->fdir1.empty())
00483 addKeyValue(elem, "fdir1", (*ge)->fdir1);
00484 if ((*ge)->is_kp)
00485 addKeyValue(elem, "kp", values2str(1, &(*ge)->kp) );
00486 if ((*ge)->is_kd)
00487 addKeyValue(elem, "kd", values2str(1, &(*ge)->kd) );
00488
00489 if ((*ge)->is_maxVel)
00490 addKeyValue(elem, "maxVel", values2str(1, &(*ge)->maxVel) );
00491
00492 if ((*ge)->is_minDepth)
00493 addKeyValue(elem, "minDepth", values2str(1, &(*ge)->minDepth) );
00494 if ((*ge)->genTexCoord)
00495 addKeyValue(elem, "genTexCoord", "true");
00496 else
00497 addKeyValue(elem, "genTexCoord", "false");
00498 if ((*ge)->is_laserRetro)
00499 addKeyValue(elem, "laserRetro", values2str(1, &(*ge)->laserRetro) );
00500 }
00501 }
00502 }
00503 }
00504
00505 void URDF2Gazebo::insertGazeboExtensionVisual(TiXmlElement *elem,std::string link_name)
00506 {
00507 for (std::map<std::string,std::vector<GazeboExtension*> >::iterator gazebo_it = this->gazebo_extensions_.begin();
00508 gazebo_it != this->gazebo_extensions_.end(); gazebo_it++)
00509 {
00510 for (std::vector<GazeboExtension*>::iterator ge = gazebo_it->second.begin(); ge != gazebo_it->second.end(); ge++)
00511 {
00512 if ((*ge)->original_reference == link_name)
00513 {
00514
00515 if (!(*ge)->material.empty())
00516 addKeyValue(elem, "material", (*ge)->material);
00517 }
00518 }
00519 }
00520 }
00521
00522 void URDF2Gazebo::insertGazeboExtensionBody(TiXmlElement *elem,std::string link_name)
00523 {
00524 for (std::map<std::string,std::vector<GazeboExtension*> >::iterator gazebo_it = this->gazebo_extensions_.begin();
00525 gazebo_it != this->gazebo_extensions_.end(); gazebo_it++)
00526 {
00527 if (gazebo_it->first == link_name)
00528 {
00529 ROS_DEBUG("body: reference %s link name %s",gazebo_it->first.c_str(),link_name.c_str());
00530 for (std::vector<GazeboExtension*>::iterator ge = gazebo_it->second.begin(); ge != gazebo_it->second.end(); ge++)
00531 {
00532
00533 if ((*ge)->turnGravityOff)
00534 addKeyValue(elem, "turnGravityOff", "true");
00535 else
00536 addKeyValue(elem, "turnGravityOff", "false");
00537
00538
00539 if ((*ge)->is_dampingFactor)
00540 addKeyValue(elem, "dampingFactor", values2str(1, &(*ge)->dampingFactor) );
00541
00542 if ((*ge)->selfCollide)
00543 addKeyValue(elem, "selfCollide", "true");
00544 else
00545 addKeyValue(elem, "selfCollide", "false");
00546
00547 for (std::vector<TiXmlElement*>::iterator blob_it = (*ge)->blobs.begin();
00548 blob_it != (*ge)->blobs.end(); blob_it++)
00549 {
00550 elem->LinkEndChild((*blob_it)->Clone());
00551 }
00552 }
00553 }
00554 }
00555 }
00556 void URDF2Gazebo::insertGazeboExtensionJoint(TiXmlElement *elem,std::string joint_name)
00557 {
00558 for (std::map<std::string,std::vector<GazeboExtension*> >::iterator gazebo_it = this->gazebo_extensions_.begin();
00559 gazebo_it != this->gazebo_extensions_.end(); gazebo_it++)
00560 {
00561 if (gazebo_it->first == joint_name)
00562 {
00563 for (std::vector<GazeboExtension*>::iterator ge = gazebo_it->second.begin(); ge != gazebo_it->second.end(); ge++)
00564 {
00565 ROS_DEBUG("geom: reference %s joint name %s, stopKp %f",gazebo_it->first.c_str(),joint_name.c_str(),(*ge)->stopKp);
00566
00567 if ((*ge)->is_stopKp)
00568 addKeyValue(elem, "stopKp", values2str(1, &(*ge)->stopKp) );
00569 if ((*ge)->is_stopKd)
00570 addKeyValue(elem, "stopKd", values2str(1, &(*ge)->stopKd) );
00571 if ((*ge)->is_initial_joint_position)
00572 addKeyValue(elem, "initial_joint_position", values2str(1, &(*ge)->initial_joint_position) );
00573 if ((*ge)->is_fudgeFactor)
00574 addKeyValue(elem, "fudgeFactor", values2str(1, &(*ge)->fudgeFactor) );
00575
00576
00577 if ((*ge)->provideFeedback)
00578 addKeyValue(elem, "provideFeedback", "true");
00579 else
00580 addKeyValue(elem, "provideFeedback", "false");
00581 }
00582 }
00583 }
00584 }
00585 void URDF2Gazebo::insertGazeboExtensionRobot(TiXmlElement *elem)
00586 {
00587 for (std::map<std::string,std::vector<GazeboExtension*> >::iterator gazebo_it = this->gazebo_extensions_.begin();
00588 gazebo_it != this->gazebo_extensions_.end(); gazebo_it++)
00589 {
00590 if (gazebo_it->first.empty())
00591 {
00592 for (std::vector<GazeboExtension*>::iterator ge = gazebo_it->second.begin(); ge != gazebo_it->second.end(); ge++)
00593 {
00594
00595 if ((*ge)->setStaticFlag)
00596 addKeyValue(elem, "static", "true");
00597 else
00598 addKeyValue(elem, "static", "false");
00599
00600 for (std::vector<TiXmlElement*>::iterator blob_it = (*ge)->blobs.begin();
00601 blob_it != (*ge)->blobs.end(); blob_it++)
00602 {
00603 std::ostringstream stream_in;
00604 stream_in << *(*blob_it);
00605 ROS_DEBUG("robot: reference empty, blobs for robot\n%s",stream_in.str().c_str());
00606 elem->LinkEndChild((*blob_it)->Clone());
00607 }
00608 }
00609 }
00610 }
00611 }
00612
00613 std::string URDF2Gazebo::getGeometrySize(boost::shared_ptr<urdf::Geometry> geometry, int *sizeCount, double *sizeVals)
00614 {
00615 std::string type("empty");
00616
00617 switch (geometry->type)
00618 {
00619 case urdf::Geometry::BOX:
00620 type = "box";
00621 *sizeCount = 3;
00622 {
00623 boost::shared_ptr<const urdf::Box> box;
00624 box = boost::dynamic_pointer_cast< const urdf::Box >(geometry);
00625 sizeVals[0] = box->dim.x;
00626 sizeVals[1] = box->dim.y;
00627 sizeVals[2] = box->dim.z;
00628 }
00629 break;
00630 case urdf::Geometry::CYLINDER:
00631 type = "cylinder";
00632 *sizeCount = 2;
00633 {
00634 boost::shared_ptr<const urdf::Cylinder> cylinder;
00635 cylinder = boost::dynamic_pointer_cast<const urdf::Cylinder >(geometry);
00636 sizeVals[0] = cylinder->radius;
00637 sizeVals[1] = cylinder->length;
00638 }
00639 break;
00640 case urdf::Geometry::SPHERE:
00641 type = "sphere";
00642 *sizeCount = 1;
00643 {
00644 boost::shared_ptr<const urdf::Sphere> sphere;
00645 sphere = boost::dynamic_pointer_cast<const urdf::Sphere >(geometry);
00646 sizeVals[0] = sphere->radius;
00647 }
00648 break;
00649 case urdf::Geometry::MESH:
00650 type = "trimesh";
00651 *sizeCount = 3;
00652 {
00653 boost::shared_ptr<const urdf::Mesh> mesh;
00654 mesh = boost::dynamic_pointer_cast<const urdf::Mesh >(geometry);
00655 sizeVals[0] = mesh->scale.x;
00656 sizeVals[1] = mesh->scale.y;
00657 sizeVals[2] = mesh->scale.z;
00658 }
00659 break;
00660 default:
00661 *sizeCount = 0;
00662 printf("Unknown body type: %d in geometry\n", geometry->type);
00663 break;
00664 }
00665
00666 return type;
00667 }
00668
00669 std::string URDF2Gazebo::getGeometryBoundingBox(boost::shared_ptr<urdf::Geometry> geometry, double *sizeVals)
00670 {
00671 std::string type;
00672
00673 switch (geometry->type)
00674 {
00675 case urdf::Geometry::BOX:
00676 type = "box";
00677 {
00678 boost::shared_ptr<const urdf::Box> box;
00679 box = boost::dynamic_pointer_cast<const urdf::Box >(geometry);
00680 sizeVals[0] = box->dim.x;
00681 sizeVals[1] = box->dim.y;
00682 sizeVals[2] = box->dim.z;
00683 }
00684 break;
00685 case urdf::Geometry::CYLINDER:
00686 type = "cylinder";
00687 {
00688 boost::shared_ptr<const urdf::Cylinder> cylinder;
00689 cylinder = boost::dynamic_pointer_cast<const urdf::Cylinder >(geometry);
00690 sizeVals[0] = cylinder->radius * 2;
00691 sizeVals[1] = cylinder->radius * 2;
00692 sizeVals[2] = cylinder->length;
00693 }
00694 break;
00695 case urdf::Geometry::SPHERE:
00696 type = "sphere";
00697 {
00698 boost::shared_ptr<const urdf::Sphere> sphere;
00699 sphere = boost::dynamic_pointer_cast<const urdf::Sphere >(geometry);
00700 sizeVals[0] = sizeVals[1] = sizeVals[2] = sphere->radius * 2;
00701 }
00702 break;
00703 case urdf::Geometry::MESH:
00704 type = "trimesh";
00705 {
00706 boost::shared_ptr<const urdf::Mesh> mesh;
00707 mesh = boost::dynamic_pointer_cast<const urdf::Mesh >(geometry);
00708 sizeVals[0] = mesh->scale.x;
00709 sizeVals[1] = mesh->scale.y;
00710 sizeVals[2] = mesh->scale.z;
00711 }
00712 break;
00713 default:
00714 sizeVals[0] = sizeVals[1] = sizeVals[2] = 0;
00715 printf("Unknown body type: %d in geometry\n", geometry->type);
00716 break;
00717 }
00718
00719 return type;
00720 }
00721
00722 void URDF2Gazebo::printMass(std::string link_name, dMass mass)
00723 {
00724 ROS_DEBUG("LINK NAME: [%s] from dMass",link_name.c_str());
00725 ROS_DEBUG(" MASS: [%f]",mass.mass);
00726 ROS_DEBUG(" CG: [%f %f %f]",mass.c[0],mass.c[1],mass.c[2]);
00727 ROS_DEBUG(" I: [%f %f %f]",mass.I[0],mass.I[1],mass.I[2]);
00728 ROS_DEBUG(" [%f %f %f]",mass.I[4],mass.I[5],mass.I[6]);
00729 ROS_DEBUG(" [%f %f %f]",mass.I[8],mass.I[9],mass.I[10]);
00730 }
00731
00732 void URDF2Gazebo::printMass(boost::shared_ptr<urdf::Link> link)
00733 {
00734 ROS_DEBUG("LINK NAME: [%s] from urdf::Link",link->name.c_str());
00735 ROS_DEBUG(" MASS: [%f]",link->inertial->mass);
00736 ROS_DEBUG(" CG: [%f %f %f]",link->inertial->origin.position.x,link->inertial->origin.position.y,link->inertial->origin.position.z);
00737 ROS_DEBUG(" I: [%f %f %f]",link->inertial->ixx,link->inertial->ixy,link->inertial->ixz);
00738 ROS_DEBUG(" [%f %f %f]",link->inertial->ixy,link->inertial->iyy,link->inertial->iyz);
00739 ROS_DEBUG(" [%f %f %f]",link->inertial->ixz,link->inertial->iyz,link->inertial->izz);
00740 }
00741
00742
00743 void URDF2Gazebo::reduceFixedJoints(TiXmlElement *root, boost::shared_ptr<urdf::Link> link)
00744 {
00745
00746 ROS_DEBUG("TREE: at [%s]",link->name.c_str());
00747
00748
00749 for (unsigned int i = 0 ; i < link->child_links.size() ; ++i)
00750 if (link->child_links[i]->parent_joint->type == urdf::Joint::FIXED)
00751 reduceFixedJoints(root, link->child_links[i]);
00752
00753
00754 if (link->getParent() && link->getParent()->name != "world" && link->parent_joint && link->parent_joint->type == urdf::Joint::FIXED)
00755 {
00756 ROS_DEBUG("TREE: extension lumping from [%s] to [%s]",link->name.c_str(),link->getParent()->name.c_str());
00757
00758
00759 reduceGazeboExtensionToParent(link);
00760
00761 ROS_DEBUG("TREE: mass lumping from [%s] to [%s]",link->name.c_str(),link->getParent()->name.c_str());
00762
00763 if (link->inertial)
00764 {
00765
00766 dMass parent_mass;
00767 if (!link->getParent()->inertial)
00768 link->getParent()->inertial.reset(new urdf::Inertial);
00769 dMassSetParameters(&parent_mass, link->getParent()->inertial->mass,
00770 link->getParent()->inertial->origin.position.x, link->getParent()->inertial->origin.position.y, link->getParent()->inertial->origin.position.z,
00771 link->getParent()->inertial->ixx, link->getParent()->inertial->iyy, link->getParent()->inertial->izz,
00772 link->getParent()->inertial->ixy, link->getParent()->inertial->ixz, link->getParent()->inertial->iyz);
00773 printMass(link->getParent()->name,parent_mass);
00774 printMass(link->getParent());
00775
00776 dMass link_mass;
00777 dMassSetParameters(&link_mass, link->inertial->mass,
00778 link->inertial->origin.position.x, link->inertial->origin.position.y, link->inertial->origin.position.z,
00779 link->inertial->ixx, link->inertial->iyy, link->inertial->izz,
00780 link->inertial->ixy, link->inertial->ixz, link->inertial->iyz);
00781 printMass(link->name,link_mass);
00782 printMass(link);
00783
00784 dMatrix3 R;
00785 double phi, theta, psi;
00786 link->parent_joint->parent_to_joint_origin_transform.rotation.getRPY(phi,theta,psi);
00787 ROS_DEBUG("debug: %f %f %f",phi,theta,psi);
00788 dRFromEulerAngles(R, phi, theta, psi);
00789 dMassRotate(&link_mass, R);
00790 printMass(link->name,link_mass);
00791
00792 dMassTranslate(&link_mass, link->parent_joint->parent_to_joint_origin_transform.position.x
00793 , link->parent_joint->parent_to_joint_origin_transform.position.y
00794 , link->parent_joint->parent_to_joint_origin_transform.position.z);
00795 printMass(link->name,link_mass);
00796
00797 dMassAdd(&parent_mass,&link_mass);
00798 printMass(link->getParent()->name,parent_mass);
00799
00800 link->getParent()->inertial->mass = parent_mass.mass;
00801 link->getParent()->inertial->ixx = parent_mass.I[0+4*0];
00802 link->getParent()->inertial->iyy = parent_mass.I[1+4*1];
00803 link->getParent()->inertial->izz = parent_mass.I[2+4*2];
00804 link->getParent()->inertial->ixy = parent_mass.I[0+4*1];
00805 link->getParent()->inertial->ixz = parent_mass.I[0+4*2];
00806 link->getParent()->inertial->iyz = parent_mass.I[1+4*2];
00807 link->getParent()->inertial->origin.position.x = parent_mass.c[0];
00808 link->getParent()->inertial->origin.position.y = parent_mass.c[1];
00809 link->getParent()->inertial->origin.position.z = parent_mass.c[2];
00810 printMass(link->getParent());
00811 }
00812
00813
00814
00815
00816 for (std::map<std::string, boost::shared_ptr<std::vector<boost::shared_ptr<urdf::Visual> > > >::iterator visuals_it = link->visual_groups.begin();
00817 visuals_it != link->visual_groups.end(); visuals_it++)
00818 {
00819
00820 if (visuals_it->first == "default")
00821 {
00822 std::string lump_group_name = std::string("lump::")+link->name;
00823 ROS_DEBUG("adding modified lump group name [%s] to link [%s]",lump_group_name.c_str(),link->getParent()->name.c_str());
00824 for (std::vector<boost::shared_ptr<urdf::Visual> >::iterator visual_it = visuals_it->second->begin(); visual_it != visuals_it->second->end(); visual_it++)
00825 {
00826
00827 (*visual_it)->origin = transformToParentFrame((*visual_it)->origin, link->parent_joint->parent_to_joint_origin_transform);
00828
00829 this->addVisual(link->getParent(),lump_group_name,*visual_it);
00830 }
00831 }
00832 else if (visuals_it->first.find(std::string("lump::")) == 0)
00833 {
00834
00835 std::string lump_group_name = visuals_it->first;
00836 ROS_DEBUG("re-lumping group name [%s] to link [%s]",lump_group_name.c_str(),link->getParent()->name.c_str());
00837 for (std::vector<boost::shared_ptr<urdf::Visual> >::iterator visual_it = visuals_it->second->begin(); visual_it != visuals_it->second->end(); visual_it++)
00838 {
00839
00840 (*visual_it)->origin = transformToParentFrame((*visual_it)->origin, link->parent_joint->parent_to_joint_origin_transform);
00841
00842 this->addVisual(link->getParent(),lump_group_name,*visual_it);
00843 }
00844 }
00845 }
00846
00847
00848
00849
00850 for (std::map<std::string, boost::shared_ptr<std::vector<boost::shared_ptr<urdf::Collision> > > >::iterator collisions_it = link->collision_groups.begin();
00851 collisions_it != link->collision_groups.end(); collisions_it++)
00852 {
00853
00854 if (collisions_it->first == "default")
00855 {
00856 std::string lump_group_name = std::string("lump::")+link->name;
00857 ROS_DEBUG("adding modified lump group name [%s] to link [%s]",lump_group_name.c_str(),link->getParent()->name.c_str());
00858 for (std::vector<boost::shared_ptr<urdf::Collision> >::iterator collision_it = collisions_it->second->begin(); collision_it != collisions_it->second->end(); collision_it++)
00859 {
00860
00861 (*collision_it)->origin = transformToParentFrame((*collision_it)->origin, link->parent_joint->parent_to_joint_origin_transform);
00862
00863 this->addCollision(link->getParent(),lump_group_name,*collision_it);
00864 }
00865 }
00866 else if (collisions_it->first.find(std::string("lump::")) == 0)
00867 {
00868
00869 std::string lump_group_name = collisions_it->first;
00870 ROS_DEBUG("re-lumping group name [%s] to link [%s]",lump_group_name.c_str(),link->getParent()->name.c_str());
00871 for (std::vector<boost::shared_ptr<urdf::Collision> >::iterator collision_it = collisions_it->second->begin(); collision_it != collisions_it->second->end(); collision_it++)
00872 {
00873
00874 (*collision_it)->origin = transformToParentFrame((*collision_it)->origin, link->parent_joint->parent_to_joint_origin_transform);
00875
00876 this->addCollision(link->getParent(),lump_group_name,*collision_it);
00877 }
00878 }
00879 }
00880 printCollisionGroups(link->getParent());
00881
00882
00883
00884
00885
00886
00887
00888
00889 ROS_DEBUG("BEGIN JOINT LUMPING");
00890
00891 for (unsigned int i = 0 ; i < link->child_links.size() ; ++i) {
00892 boost::shared_ptr<urdf::Joint> parent_joint = link->child_links[i]->parent_joint;
00893 if (parent_joint->type != urdf::Joint::FIXED) {
00894
00895 boost::shared_ptr<urdf::Link> new_parent_link = link;
00896 gazebo::math::Pose joint_anchor_transform;
00897 while(new_parent_link->parent_joint && new_parent_link->getParent()->name != "world" && new_parent_link->parent_joint->type == urdf::Joint::FIXED) {
00898 ROS_DEBUG(" ...JOINT: searching: at [%s] checking if parent [%s] is attachable",new_parent_link->name.c_str(),new_parent_link->getParent()->name.c_str());
00899 joint_anchor_transform = joint_anchor_transform*joint_anchor_transform;
00900 parent_joint->parent_to_joint_origin_transform = transformToParentFrame(parent_joint->parent_to_joint_origin_transform,
00901 new_parent_link->parent_joint->parent_to_joint_origin_transform);
00902 new_parent_link = new_parent_link->getParent();
00903 }
00904
00905 link->child_links[i]->setParent(new_parent_link);
00906 parent_joint->parent_link_name = new_parent_link->name;
00907 ROS_DEBUG(" JOINT: reparenting for link %s joint %s from %s to %s",link->child_links[i]->name.c_str(),link->child_links[i]->parent_joint->name.c_str(),link->name.c_str(),new_parent_link->name.c_str());
00908
00909
00910 }
00911 }
00912 }
00913
00914
00915 for (unsigned int i = 0 ; i < link->child_links.size() ; ++i)
00916 if (link->child_links[i]->parent_joint->type != urdf::Joint::FIXED)
00917 reduceFixedJoints(root, link->child_links[i]);
00918 }
00919
00920
00921 void URDF2Gazebo::printCollisionGroups(boost::shared_ptr<urdf::Link> link)
00922 {
00923 ROS_DEBUG("COLLISION LUMPING: link: [%s] contains [%d] collisions",link->name.c_str(),(int)link->collision_groups.size());
00924 for (std::map<std::string, boost::shared_ptr<std::vector<boost::shared_ptr<urdf::Collision> > > >::iterator cols_it = link->collision_groups.begin();
00925 cols_it != link->collision_groups.end(); cols_it++)
00926 {
00927 ROS_DEBUG(" collision_groups: [%s] has [%d] Collision objects",cols_it->first.c_str(),(int)cols_it->second->size());
00928
00929
00930 }
00931 }
00932
00934 urdf::Pose URDF2Gazebo::transformToParentFrame(urdf::Pose transform_in_link_frame, urdf::Pose parent_to_link_transform)
00935 {
00936
00937 gazebo::math::Pose p1 = URDF2Gazebo::copyPose(transform_in_link_frame);
00938 gazebo::math::Pose p2 = URDF2Gazebo::copyPose(parent_to_link_transform);
00939 return URDF2Gazebo::copyPose(transformToParentFrame(p1,p2));
00940 }
00941 gazebo::math::Pose URDF2Gazebo::transformToParentFrame(gazebo::math::Pose transform_in_link_frame, urdf::Pose parent_to_link_transform)
00942 {
00943
00944 gazebo::math::Pose p2 = URDF2Gazebo::copyPose(parent_to_link_transform);
00945 return transformToParentFrame(transform_in_link_frame,p2);
00946 }
00947
00948 gazebo::math::Pose URDF2Gazebo::transformToParentFrame(gazebo::math::Pose transform_in_link_frame, gazebo::math::Pose parent_to_link_transform)
00949 {
00950 gazebo::math::Pose transform_in_parent_link_frame;
00951
00952
00953 transform_in_parent_link_frame.pos = parent_to_link_transform.rot * transform_in_link_frame.pos;
00954 transform_in_parent_link_frame.rot = parent_to_link_transform.rot * transform_in_link_frame.rot;
00955
00956 transform_in_parent_link_frame.pos = parent_to_link_transform.pos + transform_in_parent_link_frame.pos;
00957
00958 return transform_in_parent_link_frame;
00959 }
00960
00961 gazebo::math::Pose URDF2Gazebo::inverseTransformToParentFrame(gazebo::math::Pose transform_in_link_frame, urdf::Pose parent_to_link_transform)
00962 {
00963 gazebo::math::Pose transform_in_parent_link_frame;
00964
00965
00966 urdf::Rotation ri = parent_to_link_transform.rotation.GetInverse();
00967 gazebo::math::Quaternion q1(ri.w, ri.x, ri.y, ri.z);
00968 transform_in_parent_link_frame.pos = q1 * transform_in_link_frame.pos;
00969 urdf::Rotation r2 = parent_to_link_transform.rotation.GetInverse();
00970 gazebo::math::Quaternion q3(r2.w, r2.x, r2.y, r2.z);
00971 transform_in_parent_link_frame.rot = q3 * transform_in_link_frame.rot;
00972
00973 transform_in_parent_link_frame.pos.x = transform_in_parent_link_frame.pos.x - parent_to_link_transform.position.x;
00974 transform_in_parent_link_frame.pos.y = transform_in_parent_link_frame.pos.y - parent_to_link_transform.position.y;
00975 transform_in_parent_link_frame.pos.z = transform_in_parent_link_frame.pos.z - parent_to_link_transform.position.z;
00976
00977 return transform_in_parent_link_frame;
00978 }
00979
00980 void URDF2Gazebo::reduceGazeboExtensionToParent(boost::shared_ptr<urdf::Link> link)
00981 {
00982
00983
00984
00985 std::string link_name = link->name;
00986 std::string new_link_name = link->getParent()->name;
00987
00988 ROS_DEBUG(" EXTENSION: Reference lumping from [%s] to [%s]",link_name.c_str(), new_link_name.c_str());
00989
00990
00991 listGazeboExtensions();
00992
00993 std::map<std::string,std::vector<GazeboExtension*> >::iterator ext = this->gazebo_extensions_.find(link_name);
00994 if (ext != this->gazebo_extensions_.end())
00995 {
00996
00997
00998 for (std::vector<GazeboExtension*>::iterator ge = ext->second.begin(); ge != ext->second.end(); ge++)
00999 {
01000 (*ge)->reduction_transform = transformToParentFrame((*ge)->reduction_transform, link->parent_joint->parent_to_joint_origin_transform);
01001
01002 updateGazeboExtensionBlobsReductionTransform((*ge));
01003
01004 updateGazeboExtensionFrameReplace(*ge, link, new_link_name);
01005 }
01006
01007
01008 std::map<std::string,std::vector<GazeboExtension*> >::iterator new_ext = this->gazebo_extensions_.find(new_link_name);
01009
01010 if (new_ext == this->gazebo_extensions_.end())
01011 {
01012 std::vector<GazeboExtension*> extensions;
01013 this->gazebo_extensions_.insert(std::make_pair( new_link_name, extensions ) );
01014 new_ext = this->gazebo_extensions_.find(new_link_name);
01015 }
01016
01017
01018 for (std::vector<GazeboExtension*>::iterator ge = ext->second.begin(); ge != ext->second.end(); ge++)
01019 {
01020 new_ext->second.push_back(*ge);
01021 }
01022 ext->second.clear();
01023 }
01024
01025 listGazeboExtensions();
01026
01027
01028
01029 for (std::map<std::string,std::vector<GazeboExtension*> >::iterator gazebo_it = this->gazebo_extensions_.begin();
01030 gazebo_it != this->gazebo_extensions_.end(); gazebo_it++)
01031 if (gazebo_it->first.empty())
01032 {
01033
01034 for (std::vector<GazeboExtension*>::iterator ge = gazebo_it->second.begin(); ge != gazebo_it->second.end(); ge++)
01035 updateGazeboExtensionFrameReplace(*ge, link, new_link_name);
01036 }
01037
01038 listGazeboExtensions();
01039 }
01040
01041 void URDF2Gazebo::updateGazeboExtensionFrameReplace(GazeboExtension* ge, boost::shared_ptr<urdf::Link> link, std::string new_link_name)
01042 {
01043 std::vector<TiXmlElement*> blobs = ge->blobs;
01044
01045 std::string link_name = link->name;
01046
01047
01048 ROS_DEBUG(" STRING REPLACE: instances of link name [%s] with new link name [%s]",link_name.c_str(),new_link_name.c_str());
01049 for (std::vector<TiXmlElement*>::iterator blob_it = blobs.begin(); blob_it != blobs.end(); blob_it++)
01050 {
01051
01052
01053 std::ostringstream stream_in;
01054 stream_in << *(*blob_it);
01055 std::string blob = stream_in.str();
01056 ROS_DEBUG(" INITIAL STRING [%s-->%s]: %s",link_name.c_str(),new_link_name.c_str(),blob.c_str());
01057
01058 if ((*blob_it)->ValueStr() == "sensor:contact")
01059 {
01060
01061
01062 TiXmlNode* geomName = (*blob_it)->FirstChild("geom");
01063 if (geomName)
01064 {
01065 ROS_DEBUG(" <geom>%s</geom> : %s --> %s",getGazeboValue(geomName->ToElement()).c_str(),link_name.c_str(),new_link_name.c_str());
01066 if (getGazeboValue(geomName->ToElement()) == link_name + std::string("_geom"))
01067 {
01068 (*blob_it)->RemoveChild(geomName);
01069 TiXmlElement* geom_name_key = new TiXmlElement("geom");
01070 std::ostringstream geom_name_stream;
01071 geom_name_stream << new_link_name << "_geom_" << link_name;
01072 TiXmlText* geom_name_txt = new TiXmlText(geom_name_stream.str());
01073 geom_name_key->LinkEndChild(geom_name_txt);
01074 (*blob_it)->LinkEndChild(geom_name_key);
01075 }
01076
01077
01078 }
01079 }
01080
01081 if ((*blob_it)->ValueStr() == "controller:gazebo_ros_p3d" ||
01082 (*blob_it)->ValueStr() == "controller:gazebo_ros_imu" ||
01083 (*blob_it)->ValueStr() == "controller:gazebo_ros_projector")
01084 {
01085
01086
01087 TiXmlNode* bodyName = (*blob_it)->FirstChild("bodyName");
01088 if (bodyName)
01089 {
01090 if (getGazeboValue(bodyName->ToElement()) == link_name)
01091 {
01092 ROS_DEBUG(" <bodyName>%s</bodyName> : %s --> %s",getGazeboValue(bodyName->ToElement()).c_str(),link_name.c_str(),new_link_name.c_str());
01093 (*blob_it)->RemoveChild(bodyName);
01094 TiXmlElement* body_name_key = new TiXmlElement("bodyName");
01095 std::ostringstream body_name_stream;
01096 body_name_stream << new_link_name;
01097 TiXmlText* body_name_txt = new TiXmlText(body_name_stream.str());
01098 body_name_key->LinkEndChild(body_name_txt);
01099 (*blob_it)->LinkEndChild(body_name_key);
01100 ROS_DEBUG("Re-parenting extension [%s] from [%s] to [%s] is broken, needs the transform to be complete",(*blob_it)->ValueStr().c_str(),link_name.c_str(),new_link_name.c_str());
01101 }
01102 }
01103
01104 TiXmlNode* frameName = (*blob_it)->FirstChild("frameName");
01105 if (frameName)
01106 {
01107 if (getGazeboValue(frameName->ToElement()) == link_name)
01108 {
01109 ROS_DEBUG(" <frameName>%s</frameName> : %s --> %s",getGazeboValue(frameName->ToElement()).c_str(),link_name.c_str(),new_link_name.c_str());
01110 (*blob_it)->RemoveChild(frameName);
01111 TiXmlElement* body_name_key = new TiXmlElement("frameName");
01112 std::ostringstream body_name_stream;
01113 body_name_stream << new_link_name;
01114 TiXmlText* body_name_txt = new TiXmlText(body_name_stream.str());
01115 body_name_key->LinkEndChild(body_name_txt);
01116 (*blob_it)->LinkEndChild(body_name_key);
01117 ROS_DEBUG("Re-parenting extension [%s] from [%s] to [%s] is broken, needs the transform to be complete",(*blob_it)->ValueStr().c_str(),link_name.c_str(),new_link_name.c_str());
01118
01119
01120
01121 if ((*blob_it)->ValueStr() == "controller:gazebo_ros_p3d" || (*blob_it)->ValueStr() == "controller:gazebo_ros_imu")
01122 {
01123
01124
01125 ROS_DEBUG("testing reduction transform for [%s] for frameName",(*blob_it)->ValueStr().c_str());
01126 for (TiXmlNode* el_it = (*blob_it)->FirstChild(); el_it; el_it = el_it->NextSibling())
01127 {
01128 std::ostringstream stream_debug;
01129 stream_debug << *el_it;
01130 ROS_DEBUG(" %s",stream_debug.str().c_str());
01131 }
01132
01133
01134 TiXmlNode* xyz_key = (*blob_it)->FirstChild("xyzOffset");
01135 if (xyz_key)
01136 {
01137 urdf::Vector3 v1 = parseVector3(xyz_key);
01138 ge->reduction_transform.pos = gazebo::math::Vector3(v1.x, v1.y, v1.z);
01139
01140 (*blob_it)->RemoveChild(xyz_key);
01141 }
01142 TiXmlNode* rpy_key = (*blob_it)->FirstChild("rpyOffset");
01143 if (rpy_key)
01144 {
01145 urdf::Vector3 rpy = parseVector3(rpy_key, M_PI/180.0);
01146 ge->reduction_transform.rot = gazebo::math::Quaternion::EulerToQuaternion(rpy.x, rpy.y, rpy.z);
01147
01148 (*blob_it)->RemoveChild(rpy_key);
01149 }
01150
01151
01152 ge->reduction_transform = inverseTransformToParentFrame(ge->reduction_transform, link->parent_joint->parent_to_joint_origin_transform);
01153
01154
01155 xyz_key = new TiXmlElement("xyzOffset");
01156 rpy_key = new TiXmlElement("rpyOffset");
01157
01158
01159 urdf::Vector3 reduction_xyz(ge->reduction_transform.pos.x,ge->reduction_transform.pos.y,ge->reduction_transform.pos.z);
01160 urdf::Rotation reduction_q(ge->reduction_transform.rot.x,ge->reduction_transform.rot.y,ge->reduction_transform.rot.z,ge->reduction_transform.rot.w);
01161
01162 std::ostringstream xyz_stream, rpy_stream;
01163 xyz_stream << reduction_xyz.x << " " << reduction_xyz.y << " " << reduction_xyz.z;
01164 urdf::Vector3 reduction_rpy;
01165 reduction_q.getRPY(reduction_rpy.x,reduction_rpy.y,reduction_rpy.z);
01166 rpy_stream << reduction_rpy.x*180./M_PI << " " << reduction_rpy.y*180./M_PI << " " << reduction_rpy.z*180./M_PI;
01167
01168 TiXmlText* xyz_txt = new TiXmlText(xyz_stream.str());
01169 TiXmlText* rpy_txt = new TiXmlText(rpy_stream.str());
01170
01171 xyz_key->LinkEndChild(xyz_txt);
01172 rpy_key->LinkEndChild(rpy_txt);
01173
01174 (*blob_it)->LinkEndChild(xyz_key);
01175 (*blob_it)->LinkEndChild(rpy_key);
01176 }
01177 }
01178 }
01179
01180
01181 TiXmlNode* projectorName = (*blob_it)->FirstChild("projector");
01182 {
01183
01184
01185 if (projectorName)
01186 {
01187 std::string projector_name = getGazeboValue(projectorName->ToElement());
01188
01189 size_t pos = projector_name.find("/");
01190 if (pos == std::string::npos)
01191 ROS_ERROR("no slash in projector tag, should be link_name/projector_name");
01192 std::string projector_link_name = projector_name.substr(0, pos);
01193
01194 if (projector_link_name == link_name)
01195 {
01196
01197 projector_name = new_link_name+"/"+projector_name.substr(pos+1, projector_name.size());
01198
01199 ROS_DEBUG(" <projector>%s</projector> : %s --> %s",projector_link_name.c_str(),link_name.c_str(),new_link_name.c_str());
01200 (*blob_it)->RemoveChild(projectorName);
01201 TiXmlElement* body_name_key = new TiXmlElement("projector");
01202 std::ostringstream body_name_stream;
01203 body_name_stream << projector_name;
01204 TiXmlText* body_name_txt = new TiXmlText(body_name_stream.str());
01205 body_name_key->LinkEndChild(body_name_txt);
01206 (*blob_it)->LinkEndChild(body_name_key);
01207 ROS_DEBUG("Re-parenting extension [%s] from [%s] to [%s] is broken, needs the transform to be complete",(*blob_it)->ValueStr().c_str(),link_name.c_str(),new_link_name.c_str());
01208 }
01209 }
01210 }
01211 }
01212 if ((*blob_it)->ValueStr() == "gripper")
01213 {
01214 TiXmlNode* gripper_link = (*blob_it)->FirstChild("gripper_link");
01215 if (gripper_link)
01216 {
01217 if (getGazeboValue(gripper_link->ToElement()) == link_name)
01218 {
01219 ROS_DEBUG(" <gripper_link>%s</gripper_link> : %s --> %s",getGazeboValue(gripper_link->ToElement()).c_str(),link_name.c_str(),new_link_name.c_str());
01220 (*blob_it)->RemoveChild(gripper_link);
01221 TiXmlElement* body_name_key = new TiXmlElement("gripper_link");
01222 std::ostringstream body_name_stream;
01223 body_name_stream << new_link_name;
01224 TiXmlText* body_name_txt = new TiXmlText(body_name_stream.str());
01225 body_name_key->LinkEndChild(body_name_txt);
01226 (*blob_it)->LinkEndChild(body_name_key);
01227 ROS_DEBUG("Re-parenting extension [%s] from [%s] to [%s] is broken, needs the transform to be complete",(*blob_it)->ValueStr().c_str(),link_name.c_str(),new_link_name.c_str());
01228 }
01229 }
01230 TiXmlNode* palm_link = (*blob_it)->FirstChild("palm_link");
01231 if (palm_link)
01232 {
01233 if (getGazeboValue(palm_link->ToElement()) == link_name)
01234 {
01235 ROS_DEBUG(" <palm_link>%s</palm_link> : %s --> %s",getGazeboValue(palm_link->ToElement()).c_str(),link_name.c_str(),new_link_name.c_str());
01236 (*blob_it)->RemoveChild(palm_link);
01237 TiXmlElement* body_name_key = new TiXmlElement("palm_link");
01238 std::ostringstream body_name_stream;
01239 body_name_stream << new_link_name;
01240 TiXmlText* body_name_txt = new TiXmlText(body_name_stream.str());
01241 body_name_key->LinkEndChild(body_name_txt);
01242 (*blob_it)->LinkEndChild(body_name_key);
01243 ROS_DEBUG("Re-parenting extension [%s] from [%s] to [%s] is broken, needs the transform to be complete",(*blob_it)->ValueStr().c_str(),link_name.c_str(),new_link_name.c_str());
01244 }
01245 }
01246 }
01247 if ((*blob_it)->ValueStr() == "joint:hinge")
01248 {
01249
01250
01251 TiXmlNode* body1 = (*blob_it)->FirstChild("body1");
01252 if (body1)
01253 {
01254 if (getGazeboValue(body1->ToElement()) == link_name)
01255 {
01256 ROS_DEBUG(" <body1>%s</body1> : %s --> %s",getGazeboValue(body1->ToElement()).c_str(),link_name.c_str(),new_link_name.c_str());
01257 (*blob_it)->RemoveChild(body1);
01258 TiXmlElement* body1_name_key = new TiXmlElement("body1");
01259 std::ostringstream body1_name_stream;
01260 body1_name_stream << new_link_name;
01261 TiXmlText* body1_name_txt = new TiXmlText(body1_name_stream.str());
01262 body1_name_key->LinkEndChild(body1_name_txt);
01263 (*blob_it)->LinkEndChild(body1_name_key);
01264 }
01265 }
01266 TiXmlNode* body2 = (*blob_it)->FirstChild("body2");
01267 if (body2)
01268 {
01269 if (getGazeboValue(body2->ToElement()) == link_name)
01270 {
01271 ROS_DEBUG(" <body2>%s</body2> : %s --> %s",getGazeboValue(body2->ToElement()).c_str(),link_name.c_str(),new_link_name.c_str());
01272 (*blob_it)->RemoveChild(body2);
01273 TiXmlElement* body2_name_key = new TiXmlElement("body2");
01274 std::ostringstream body2_name_stream;
01275 body2_name_stream << new_link_name;
01276 TiXmlText* body2_name_txt = new TiXmlText(body2_name_stream.str());
01277 body2_name_key->LinkEndChild(body2_name_txt);
01278 (*blob_it)->LinkEndChild(body2_name_key);
01279 }
01280 }
01281 TiXmlNode* anchor = (*blob_it)->FirstChild("anchor");
01282 if (anchor)
01283 {
01284 if (getGazeboValue(anchor->ToElement()) == link_name)
01285 {
01286 ROS_DEBUG(" <anchor>%s</anchor> : %s --> %s",getGazeboValue(anchor->ToElement()).c_str(),link_name.c_str(),new_link_name.c_str());
01287 (*blob_it)->RemoveChild(anchor);
01288 TiXmlElement* anchor_name_key = new TiXmlElement("anchor");
01289 std::ostringstream anchor_name_stream;
01290 anchor_name_stream << new_link_name;
01291 TiXmlText* anchor_name_txt = new TiXmlText(anchor_name_stream.str());
01292 anchor_name_key->LinkEndChild(anchor_name_txt);
01293 (*blob_it)->LinkEndChild(anchor_name_key);
01294 }
01295 }
01296 }
01297
01298
01299 std::ostringstream stream_out;
01300 stream_out << *(*blob_it);
01301 ROS_DEBUG(" STRING REPLACED: %s",stream_out.str().c_str());
01302 }
01303 }
01304
01305 void URDF2Gazebo::updateGazeboExtensionBlobsReductionTransform(GazeboExtension* ge)
01306 {
01307 for (std::vector<TiXmlElement*>::iterator blob_it = ge->blobs.begin(); blob_it != ge->blobs.end(); blob_it++)
01308 {
01309
01310 if ((*blob_it)->ValueStr() == "sensor:ray" || (*blob_it)->ValueStr() == "sensor:camera")
01311 {
01312
01313
01314 ROS_DEBUG("testing reduction transform for [%s]",(*blob_it)->ValueStr().c_str());
01315 for (TiXmlNode* el_it = (*blob_it)->FirstChild(); el_it; el_it = el_it->NextSibling())
01316 {
01317 std::ostringstream stream_in;
01318 stream_in << *el_it;
01319 ROS_DEBUG(" %s",stream_in.str().c_str());
01320 }
01321
01322 TiXmlNode* xyz_key = (*blob_it)->FirstChild("xyz");
01323 if (xyz_key)
01324 (*blob_it)->RemoveChild(xyz_key);
01325 TiXmlNode* rpy_key = (*blob_it)->FirstChild("rpy");
01326 if (rpy_key)
01327 (*blob_it)->RemoveChild(rpy_key);
01328
01329 xyz_key = new TiXmlElement("xyz");
01330 rpy_key = new TiXmlElement("rpy");
01331
01332
01333 urdf::Vector3 reduction_xyz(ge->reduction_transform.pos.x,ge->reduction_transform.pos.y,ge->reduction_transform.pos.z);
01334 urdf::Rotation reduction_q(ge->reduction_transform.rot.x,ge->reduction_transform.rot.y,ge->reduction_transform.rot.z,ge->reduction_transform.rot.w);
01335
01336 std::ostringstream xyz_stream, rpy_stream;
01337 xyz_stream << reduction_xyz.x << " " << reduction_xyz.y << " " << reduction_xyz.z;
01338 urdf::Vector3 reduction_rpy;
01339 reduction_q.getRPY(reduction_rpy.x,reduction_rpy.y,reduction_rpy.z);
01340 rpy_stream << reduction_rpy.x*180./M_PI << " " << reduction_rpy.y*180./M_PI << " " << reduction_rpy.z*180./M_PI;
01341
01342 TiXmlText* xyz_txt = new TiXmlText(xyz_stream.str());
01343 TiXmlText* rpy_txt = new TiXmlText(rpy_stream.str());
01344
01345 xyz_key->LinkEndChild(xyz_txt);
01346 rpy_key->LinkEndChild(rpy_txt);
01347
01348 (*blob_it)->LinkEndChild(xyz_key);
01349 (*blob_it)->LinkEndChild(rpy_key);
01350 }
01351
01352
01353 if ((*blob_it)->ValueStr() == "projector")
01354 {
01355
01356
01357 ROS_DEBUG("testing reduction transform for [%s]",(*blob_it)->ValueStr().c_str());
01358 for (TiXmlNode* el_it = (*blob_it)->FirstChild(); el_it; el_it = el_it->NextSibling())
01359 {
01360 std::ostringstream stream_in;
01361 stream_in << *el_it;
01362 ROS_DEBUG(" %s",stream_in.str().c_str());
01363 }
01364
01365
01366 TiXmlNode* pose_key = (*blob_it)->FirstChild("pose");
01367
01368
01369
01370 if (pose_key) (*blob_it)->RemoveChild(pose_key);
01371
01372
01373 urdf::Vector3 reduction_xyz(ge->reduction_transform.pos.x,ge->reduction_transform.pos.y,ge->reduction_transform.pos.z);
01374 urdf::Rotation reduction_q(ge->reduction_transform.rot.x,ge->reduction_transform.rot.y,ge->reduction_transform.rot.z,ge->reduction_transform.rot.w);
01375 urdf::Vector3 reduction_rpy;
01376 reduction_q.getRPY(reduction_rpy.x,reduction_rpy.y,reduction_rpy.z);
01377
01378 std::ostringstream pose_stream;
01379 pose_stream << reduction_xyz.x << " " << reduction_xyz.y << " " << reduction_xyz.z << " "
01380 << reduction_rpy.x << " " << reduction_rpy.y << " " << reduction_rpy.z;
01381 TiXmlText* pose_txt = new TiXmlText(pose_stream.str());
01382
01383 pose_key = new TiXmlElement("pose");
01384 pose_key->LinkEndChild(pose_txt);
01385
01386 (*blob_it)->LinkEndChild(pose_key);
01387 }
01388 }
01389 }
01390
01391
01392 void URDF2Gazebo::listGazeboExtensions()
01393 {
01394 ROS_DEBUG("====================================================================");
01395 for (std::map<std::string,std::vector<GazeboExtension*> >::iterator gazebo_it = this->gazebo_extensions_.begin(); gazebo_it != this->gazebo_extensions_.end(); gazebo_it++)
01396 {
01397 int ext_count = 0;
01398 for (std::vector<GazeboExtension*>::iterator ge = gazebo_it->second.begin(); ge != gazebo_it->second.end(); ge++)
01399 {
01400 if ((*ge)->blobs.size() > 0)
01401 {
01402 ROS_DEBUG(" PRINTING [%d] BLOBS for extension [%d] referencing [%s]",(int)(*ge)->blobs.size(),ext_count++,gazebo_it->first.c_str());
01403 for (std::vector<TiXmlElement*>::iterator blob_it = (*ge)->blobs.begin(); blob_it != (*ge)->blobs.end(); blob_it++)
01404 {
01405 std::ostringstream stream_in;
01406 stream_in << *(*blob_it);
01407 ROS_DEBUG(" BLOB: %s",stream_in.str().c_str());
01408 }
01409 }
01410 }
01411 }
01412 ROS_DEBUG("====================================================================");
01413 }
01414
01415 void URDF2Gazebo::listGazeboExtensions(std::string reference)
01416 {
01417 ROS_DEBUG("--------------------------------------------------------------------");
01418 for (std::map<std::string,std::vector<GazeboExtension*> >::iterator gazebo_it = this->gazebo_extensions_.begin(); gazebo_it != this->gazebo_extensions_.end(); gazebo_it++)
01419 {
01420 if (gazebo_it->first == reference)
01421 {
01422 ROS_DEBUG(" PRINTING [%d] EXTENSIONS referencing [%s]",(int)gazebo_it->second.size(),reference.c_str());
01423 for (std::vector<GazeboExtension*>::iterator ge = gazebo_it->second.begin(); ge != gazebo_it->second.end(); ge++)
01424 {
01425 for (std::vector<TiXmlElement*>::iterator blob_it = (*ge)->blobs.begin(); blob_it != (*ge)->blobs.end(); blob_it++)
01426 {
01427 std::ostringstream stream_in;
01428 stream_in << *(*blob_it);
01429 ROS_DEBUG(" BLOB: %s",stream_in.str().c_str());
01430 }
01431 }
01432 }
01433 }
01434 ROS_DEBUG("--------------------------------------------------------------------");
01435 }
01436
01437 void URDF2Gazebo::convertLink(TiXmlElement *root, boost::shared_ptr<const urdf::Link> link, const gazebo::math::Pose &transform, bool enforce_limits,bool reduce_fixed_joints)
01438 {
01439 gazebo::math::Pose currentTransform = transform;
01440
01441
01442 if (link->name != "world" && ((!link->inertial) || gazebo::math::equal(link->inertial->mass, 0.0)))
01443 {
01444 if(!link->child_links.empty())
01445 ROS_WARN("urdf2gazebo: link(%s) has no inertia, %d children link ignored.", link->name.c_str(),(int)link->child_links.size());
01446
01447 if(!link->child_joints.empty())
01448 ROS_WARN("urdf2gazebo: link(%s) has no inertia, %d children joint ignored.", link->name.c_str(),(int)link->child_joints.size());
01449
01450 if(link->parent_joint)
01451 ROS_WARN("urdf2gazebo: link(%s) has no inertia, parent joint(%s) is ignored.",link->name.c_str(), link->parent_joint->name.c_str());
01452
01453 ROS_WARN("urdf2gazebo: link(%s) has no inertia, not modeled in gazebo.", link->name.c_str());
01454 return;
01455 }
01456
01457
01458 if ((link->getParent() && link->getParent()->name == "world") ||
01459 !reduce_fixed_joints || (!link->parent_joint || link->parent_joint->type != urdf::Joint::FIXED))
01460 createBody(root, link, currentTransform, enforce_limits, reduce_fixed_joints);
01461
01462
01463 for (unsigned int i = 0 ; i < link->child_links.size() ; ++i)
01464 convertLink(root, link->child_links[i], currentTransform, enforce_limits, reduce_fixed_joints);
01465 }
01466
01467 gazebo::math::Pose URDF2Gazebo::copyPose(urdf::Pose pose)
01468 {
01469 gazebo::math::Pose p;
01470 p.pos.x = pose.position.x;
01471 p.pos.y = pose.position.y;
01472 p.pos.z = pose.position.z;
01473 p.rot.x = pose.rotation.x;
01474 p.rot.y = pose.rotation.y;
01475 p.rot.z = pose.rotation.z;
01476 p.rot.w = pose.rotation.w;
01477 return p;
01478 }
01479 urdf::Pose URDF2Gazebo::copyPose(gazebo::math::Pose pose)
01480 {
01481 urdf::Pose p;
01482 p.position.x = pose.pos.x;
01483 p.position.y = pose.pos.y;
01484 p.position.z = pose.pos.z;
01485 p.rotation.x = pose.rot.x;
01486 p.rotation.y = pose.rot.y;
01487 p.rotation.z = pose.rot.z;
01488 p.rotation.w = pose.rot.w;
01489 return p;
01490 }
01491
01492 void URDF2Gazebo::createBody(TiXmlElement *root, boost::shared_ptr<const urdf::Link> link, gazebo::math::Pose ¤tTransform, bool enforce_limits, bool reduce_fixed_joints)
01493 {
01494 int linkGeomSize;
01495 double linkSize[3];
01496
01497
01498 TiXmlElement *elem = new TiXmlElement("body:empty");
01499
01500
01501 elem->SetAttribute("name", link->name);
01502
01503
01504 addKeyValue(elem, "massMatrix", "true");
01505 addKeyValue(elem, "mass", values2str(1, &link->inertial->mass));
01506
01507 addKeyValue(elem, "ixx", values2str(1, &link->inertial->ixx));
01508 addKeyValue(elem, "ixy", values2str(1, &link->inertial->ixy));
01509 addKeyValue(elem, "ixz", values2str(1, &link->inertial->ixz));
01510 addKeyValue(elem, "iyy", values2str(1, &link->inertial->iyy));
01511 addKeyValue(elem, "iyz", values2str(1, &link->inertial->iyz));
01512 addKeyValue(elem, "izz", values2str(1, &link->inertial->izz));
01513
01514 addKeyValue(elem, "cx", values2str(1, &link->inertial->origin.position.x));
01515 addKeyValue(elem, "cy", values2str(1, &link->inertial->origin.position.y));
01516 addKeyValue(elem, "cz", values2str(1, &link->inertial->origin.position.z));
01517
01518 double roll,pitch,yaw;
01519 link->inertial->origin.rotation.getRPY(roll,pitch,yaw);
01520 if (!gazebo::math::equal(roll, 0.0) || !gazebo::math::equal(pitch, 0.0) || !gazebo::math::equal(yaw, 0.0))
01521 ROS_ERROR("rotation of inertial frame is not supported\n");
01522
01523
01524 gazebo::math::Pose localTransform;
01525
01526
01527 if (link->parent_joint)
01528 {
01529 ROS_DEBUG("%s has a parent joint",link->name.c_str());
01530 localTransform = URDF2Gazebo::copyPose(link->parent_joint->parent_to_joint_origin_transform);
01531 currentTransform = localTransform * currentTransform;
01532 }
01533 else
01534 ROS_DEBUG("%s has no parent joint",link->name.c_str());
01535
01536
01537
01538 addTransform(elem, currentTransform);
01539
01540
01541
01542
01543
01544
01545
01546
01547 for (std::map<std::string, boost::shared_ptr<std::vector<boost::shared_ptr<urdf::Collision> > > >::const_iterator collisions_it = link->collision_groups.begin();
01548 collisions_it != link->collision_groups.end(); collisions_it++)
01549 {
01550 if (collisions_it->first == "default")
01551 {
01552 ROS_DEBUG("creating default geom for link [%s]",link->name.c_str());
01553 boost::shared_ptr<urdf::Collision> collision = *(collisions_it->second->begin());
01554 boost::shared_ptr<urdf::Visual> visual = *(link->visual_groups.find(collisions_it->first)->second->begin());
01555
01556 std::string collision_type = "empty";
01557 if (!collision || !collision->geometry)
01558 ROS_DEBUG("urdf2gazebo: link(%s) does not have a collision or geometry tag. No <geometry> will be assigned.", link->name.c_str());
01559 else
01560 collision_type = getGeometrySize(collision->geometry, &linkGeomSize, linkSize);
01561
01562
01563 createGeom(elem, link, collision_type, collision, visual, linkGeomSize, linkSize, link->name);
01564 }
01565 else if (collisions_it->first.find(std::string("lump::")) == 0)
01566 {
01567 ROS_DEBUG("creating lump geom [%s] for link [%s]",collisions_it->first.c_str(),link->name.c_str());
01568 boost::shared_ptr<urdf::Collision> collision = *(collisions_it->second->begin());
01569 boost::shared_ptr<urdf::Visual> visual = *(link->visual_groups.find(collisions_it->first)->second->begin());
01570
01571 std::string collision_type = "empty";
01572 if (!collision || !collision->geometry)
01573 ROS_DEBUG("urdf2gazebo: link(%s) does not have a collision or geometry tag. No <geometry> will be assigned.", link->name.c_str());
01574 else
01575 collision_type = getGeometrySize(collision->geometry, &linkGeomSize, linkSize);
01576
01577 std::string original_reference = collisions_it->first.substr(6);
01578
01579 createGeom(elem, link, collision_type, collision, visual, linkGeomSize, linkSize, original_reference);
01580 }
01581 }
01582
01583
01584 insertGazeboExtensionBody(elem,link->name);
01585
01586
01587 root->LinkEndChild(elem);
01588
01589
01590 createJoint(root, link, currentTransform, enforce_limits, reduce_fixed_joints);
01591
01592 }
01593
01594
01595 void URDF2Gazebo::createJoint(TiXmlElement *root, boost::shared_ptr<const urdf::Link> link, gazebo::math::Pose ¤tTransform, bool enforce_limits,bool reduce_fixed_joints)
01596 {
01597
01598 std::string jtype;
01599 jtype.clear();
01600 if (link->parent_joint != NULL)
01601 {
01602 switch (link->parent_joint->type)
01603 {
01604 case urdf::Joint::CONTINUOUS:
01605 case urdf::Joint::REVOLUTE:
01606 jtype = "hinge";
01607 break;
01608 case urdf::Joint::PRISMATIC:
01609 jtype = "slider";
01610 break;
01611 case urdf::Joint::FLOATING:
01612 case urdf::Joint::PLANAR:
01613 break;
01614 case urdf::Joint::FIXED:
01615 jtype = "fixed";
01616 break;
01617 default:
01618 printf("Unknown joint type: %d in link '%s'\n", link->parent_joint->type, link->name.c_str());
01619 break;
01620 }
01621 }
01622
01623
01624
01625 if (link->getParent() && link->getParent()->name != "world" && jtype == "fixed" && reduce_fixed_joints) return;
01626
01627 if (!jtype.empty())
01628 {
01629 TiXmlElement *joint;
01630 if (jtype == "fixed") joint = new TiXmlElement("joint:hinge");
01631 else joint = new TiXmlElement("joint:" + jtype);
01632 joint->SetAttribute("name", link->parent_joint->name);
01633 addKeyValue(joint, "body1", link->name);
01634 addKeyValue(joint, "body2", link->getParent()->name);
01635 addKeyValue(joint, "anchor", link->name);
01636
01637 if (jtype == "fixed")
01638 {
01639 addKeyValue(joint, "lowStop", "0");
01640 addKeyValue(joint, "highStop", "0");
01641 addKeyValue(joint, "axis", "0 0 1");
01642 addKeyValue(joint, "damping", "0");
01643 }
01644 else
01645 {
01646 gazebo::math::Vector3 rotatedJointAxis = currentTransform.rot.RotateVector(gazebo::math::Vector3(link->parent_joint->axis.x,
01647 link->parent_joint->axis.y,
01648 link->parent_joint->axis.z ));
01649 double rotatedJointAxisArray[3] = { rotatedJointAxis.x, rotatedJointAxis.y, rotatedJointAxis.z };
01650 addKeyValue(joint, "axis", values2str(3, rotatedJointAxisArray));
01651 if (link->parent_joint->dynamics)
01652 addKeyValue(joint, "damping", values2str(1, &link->parent_joint->dynamics->damping ));
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663 if (enforce_limits && link->parent_joint->limits)
01664 {
01665 if (jtype == "slider")
01666 {
01667 addKeyValue(joint, "lowStop", values2str(1, &link->parent_joint->limits->lower ));
01668 addKeyValue(joint, "highStop", values2str(1, &link->parent_joint->limits->upper ));
01669 }
01670 else if (link->parent_joint->type != urdf::Joint::CONTINUOUS)
01671 {
01672 double *lowstop = &link->parent_joint->limits->lower;
01673 double *highstop = &link->parent_joint->limits->upper;
01674
01675 if (*lowstop > *highstop)
01676 {
01677 ROS_WARN("urdf2gazebo: hinge joint limits: lowStop > highStop, setting lowStop to highStop.");
01678 *lowstop = *highstop;
01679 }
01680 addKeyValue(joint, "lowStop", values2str(1, &link->parent_joint->limits->lower, rad2deg));
01681 addKeyValue(joint, "highStop", values2str(1, &link->parent_joint->limits->upper, rad2deg));
01682 }
01683 }
01684 }
01685
01686 insertGazeboExtensionJoint(joint,link->parent_joint->name);
01687
01688
01689 root->LinkEndChild(joint);
01690 }
01691 }
01692
01693
01694 void URDF2Gazebo::createGeom(TiXmlElement* elem, boost::shared_ptr<const urdf::Link> link,std::string collision_type, boost::shared_ptr<urdf::Collision> collision, boost::shared_ptr<urdf::Visual> visual, int linkGeomSize, double* linkSize, std::string original_reference)
01695 {
01696
01697 if (collision_type != "empty")
01698 {
01699 TiXmlElement *geom = new TiXmlElement("geom:" + collision_type);
01700
01701 if (original_reference == link->name)
01702 geom->SetAttribute("name", link->name + std::string("_geom"));
01703 else
01704 geom->SetAttribute("name", link->name + std::string("_geom_")+original_reference);
01705
01706
01707 addKeyValue(geom, "xyz", vector32str(collision->origin.position));
01708 double rpy[3];
01709 collision->origin.rotation.getRPY(rpy[0],rpy[1],rpy[2]);
01710 addKeyValue(geom, "rpy", values2str(3, rpy, rad2deg));
01711
01712 if (collision->geometry->type == urdf::Geometry::MESH)
01713 {
01714 boost::shared_ptr<const urdf::Mesh> mesh;
01715 mesh = boost::dynamic_pointer_cast<const urdf::Mesh >(collision->geometry);
01716
01717 addKeyValue(geom, "scale", vector32str(mesh->scale));
01718
01719
01720
01721 std::string fullname = mesh->filename;
01722 if (fullname.find("package://") == 0)
01723 {
01724 fullname.erase(0, strlen("package://"));
01725 size_t pos = fullname.find("/");
01726 if (pos == std::string::npos)
01727 {
01728 ROS_FATAL("Could not parse package:// format for [%s]",mesh->filename.c_str());
01729 }
01730
01731 std::string package = fullname.substr(0, pos);
01732 fullname.erase(0, pos);
01733 std::string package_path = ros::package::getPath(package);
01734
01735 if (package_path.empty())
01736 {
01737 ROS_FATAL("%s Package[%s] does not exist",mesh->filename.c_str(),package.c_str());
01738 }
01739
01740 fullname = package_path + fullname;
01741 }
01742
01743
01744 std::ifstream fin; fin.open(fullname.c_str(), std::ios::in); fin.close();
01745 if (fin.fail())
01746 ROS_ERROR("filename referred by mesh [%s] does not appear to exist.",mesh->filename.c_str());
01747
01748
01749 addKeyValue(geom, "mesh", fullname);
01750
01751 }
01752 else
01753 {
01754
01755 addKeyValue(geom, "size", values2str(linkGeomSize, linkSize));
01756 }
01757
01758
01759 insertGazeboExtensionGeom(geom,original_reference);
01760
01761
01762 createVisual(geom, link, collision_type, collision, visual,original_reference);
01763
01764
01765 elem->LinkEndChild(geom);
01766 }
01767 }
01768
01769 void URDF2Gazebo::createVisual(TiXmlElement *geom, boost::shared_ptr<const urdf::Link> link, std::string collision_type, boost::shared_ptr<urdf::Collision> collision, boost::shared_ptr<urdf::Visual> visual,std::string original_reference)
01770 {
01771
01772 TiXmlElement *gazebo_visual = new TiXmlElement("visual");
01773
01774
01775 gazebo::math::Pose coll = URDF2Gazebo::copyPose(collision->origin);
01776
01777 gazebo::math::Pose vis;
01778 if(!visual)
01779 {
01780 ROS_WARN("urdf2gazebo: link(%s) does not have a visual tag, using zero transform.", link->name.c_str());
01781 vis = gazebo::math::Pose();
01782 }
01783 else
01784 vis = URDF2Gazebo::copyPose(visual->origin);
01785
01786 coll = coll.GetInverse()*vis;
01787
01788 addTransform(gazebo_visual, coll);
01789
01790
01791
01792 if (!visual || !visual->geometry)
01793 {
01794 ROS_WARN("urdf2gazebo: link(%s) does not have a visual->geometry tag, using default SPHERE with 1mm radius.", link->name.c_str());
01795 double visualSize[3];
01796 visualSize[0]=visualSize[1]=visualSize[2]=0.002;
01797 addKeyValue(gazebo_visual, "scale", values2str(3, visualSize));
01798 addKeyValue(gazebo_visual, "mesh", "unit_sphere");
01799 }
01800 else if (visual->geometry->type == urdf::Geometry::MESH)
01801 {
01802 boost::shared_ptr<const urdf::Mesh> mesh;
01803 mesh = boost::dynamic_pointer_cast<const urdf::Mesh >(visual->geometry);
01804
01805
01806
01807
01808
01809
01810
01811 addKeyValue(gazebo_visual, "scale", vector32str(mesh->scale));
01812
01813
01814 if (mesh->filename.empty())
01815 {
01816 ROS_ERROR("urdf2gazebo: mesh geometry (%s) was specified but no filename given? using collision type.",link->name.c_str());
01817 addKeyValue(gazebo_visual, "mesh", "unit_" + collision_type);
01818 }
01819 else
01820 {
01821
01822
01823 std::string fullname = mesh->filename;
01824 if (fullname.find("package://") == 0)
01825 {
01826 fullname.erase(0, strlen("package://"));
01827 size_t pos = fullname.find("/");
01828 if (pos == std::string::npos)
01829 {
01830 ROS_FATAL("Could not parse package:// format for [%s]",mesh->filename.c_str());
01831 }
01832
01833 std::string package = fullname.substr(0, pos);
01834 fullname.erase(0, pos);
01835 std::string package_path = ros::package::getPath(package);
01836
01837 if (package_path.empty())
01838 {
01839 ROS_FATAL("%s Package[%s] does not exist",mesh->filename.c_str(),package.c_str());
01840 }
01841
01842 fullname = package_path + fullname;
01843 }
01844
01845
01846 addKeyValue(gazebo_visual, "mesh", fullname);
01847 }
01848
01849 }
01850 else
01851 {
01852 double visualSize[3];
01853 std::string visual_geom_type = getGeometryBoundingBox(visual->geometry, visualSize);
01854 addKeyValue(gazebo_visual, "scale", values2str(3, visualSize));
01855 addKeyValue(gazebo_visual, "mesh", "unit_" + visual_geom_type);
01856 }
01857
01858
01859 insertGazeboExtensionVisual(gazebo_visual,original_reference);
01860
01861
01862 geom->LinkEndChild(gazebo_visual);
01863 }
01864
01865 void URDF2Gazebo::walkChildAddNamespace(TiXmlNode* robot_xml,std::string robot_namespace)
01866 {
01867 TiXmlNode* child = 0;
01868 child = robot_xml->IterateChildren(child);
01869 while (child != NULL)
01870 {
01871 ROS_DEBUG("recursively walking gazebo extension for %s --> %d",child->ValueStr().c_str(),(int)child->ValueStr().find(std::string("controller")));
01872 if (child->ValueStr().find(std::string("controller")) == 0 && child->ValueStr().find(std::string("controller")) != std::string::npos)
01873 {
01874 if (child->FirstChildElement("robotNamespace") == NULL)
01875 {
01876 ROS_DEBUG(" adding robotNamespace for %s",child->ValueStr().c_str());
01877 addKeyValue(child->ToElement(), "robotNamespace", robot_namespace);
01878 }
01879 else
01880 {
01881 ROS_DEBUG(" robotNamespace already exists for %s",child->ValueStr().c_str());
01882 }
01883 }
01884 this->walkChildAddNamespace(child,robot_namespace);
01885 child = robot_xml->IterateChildren(child);
01886 }
01887 }
01888
01889 bool URDF2Gazebo::convert(TiXmlDocument &urdf_in, TiXmlDocument &gazebo_xml_out, bool enforce_limits, urdf::Vector3 initial_xyz, urdf::Vector3 initial_rpy,std::string model_name , std::string robot_namespace, bool xml_declaration)
01890 {
01891
01892
01893 std::ostringstream stream_in;
01894 stream_in << urdf_in;
01895
01896
01897 urdf::Model robot_model;
01898
01899 if (!robot_model.initString(stream_in.str().c_str()))
01900 {
01901 ROS_ERROR("Unable to load robot model from param server robot_description\n");
01902 return false;
01903 }
01904
01905
01906 #ifndef TO_SDF
01907
01908 if (xml_declaration)
01909 {
01910 TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "", "");
01911 gazebo_xml_out.LinkEndChild(decl);
01912 }
01913 #endif
01914
01915
01916 TiXmlElement *robot = new TiXmlElement("model:physical");
01917 robot->SetAttribute("xmlns:gazebo", "http://playerstage.sourceforge.net/gazebo/xmlschema/#gz");
01918 robot->SetAttribute("xmlns:model", "http://playerstage.sourceforge.net/gazebo/xmlschema/#model");
01919 robot->SetAttribute("xmlns:sensor", "http://playerstage.sourceforge.net/gazebo/xmlschema/#sensor");
01920 robot->SetAttribute("xmlns:body", "http://playerstage.sourceforge.net/gazebo/xmlschema/#body");
01921 robot->SetAttribute("xmlns:geom", "http://playerstage.sourceforge.net/gazebo/xmlschema/#geom");
01922 robot->SetAttribute("xmlns:joint", "http://playerstage.sourceforge.net/gazebo/xmlschema/#joint");
01923 robot->SetAttribute("xmlns:controller", "http://playerstage.sourceforge.net/gazebo/xmlschema/#controller");
01924 robot->SetAttribute("xmlns:interface", "http://playerstage.sourceforge.net/gazebo/xmlschema/#interface");
01925 robot->SetAttribute("xmlns:rendering", "http://playerstage.sourceforge.net/gazebo/xmlschema/#rendering");
01926 robot->SetAttribute("xmlns:physics", "http://playerstage.sourceforge.net/gazebo/xmlschema/#physics");
01927
01928
01929 if (model_name.empty())
01930 robot->SetAttribute("name", robot_model.getName());
01931 else
01932 robot->SetAttribute("name", model_name);
01933
01934
01935 addKeyValue(robot, "xyz", vector32str(initial_xyz));
01936 addKeyValue(robot, "rpy", vector32str(initial_rpy));
01937 gazebo::math::Pose transform;
01938
01939
01940 parseGazeboExtension( urdf_in );
01941
01942
01943
01944 boost::shared_ptr<const urdf::Link> root_link = robot_model.getRoot();
01945
01946
01947 bool reduce_fixed_joints = true;
01948 if (reduce_fixed_joints)
01949 reduceFixedJoints(robot, (boost::const_pointer_cast< urdf::Link >(root_link)));
01950
01951 if (root_link->name == "world")
01952 {
01953
01954 for (std::vector<boost::shared_ptr<urdf::Link> >::const_iterator child = root_link->child_links.begin(); child != root_link->child_links.end(); child++)
01955 convertLink(robot, (*child), transform, enforce_limits, reduce_fixed_joints);
01956 }
01957 else
01958 {
01959
01960 convertLink(robot, root_link, transform, enforce_limits, reduce_fixed_joints);
01961 }
01962
01963
01964 insertGazeboExtensionRobot(robot);
01965
01966 if (!robot_namespace.empty())
01967 {
01968
01969 ROS_DEBUG("walking gazebo extension for %s",robot->ValueStr().c_str());
01970 this->walkChildAddNamespace(robot,robot_namespace);
01971 }
01972
01973 std::ostringstream stream_robot;
01974 stream_robot << *(robot);
01975 ROS_DEBUG("\n--------------entire robot------------------\n%s\n--------------------\n",stream_robot.str().c_str());
01976 #ifndef TO_SDF
01977 gazebo_xml_out.LinkEndChild(robot);
01978 #endif
01979
01980
01981 #ifdef TO_SDF
01982
01983
01984
01985
01986 sdf::SDFPtr robot_sdf(new sdf::SDF());
01987 if (!sdf::init(robot_sdf))
01988 {
01989 std::cerr << "ERROR: SDF parsing the xml failed" << std::endl;
01990 return -1;
01991 }
01992 deprecated_sdf::initModelString(stream_robot.str(), robot_sdf);
01993
01994 std::string sdf_string = robot_sdf->ToString();
01995 ROS_DEBUG("--------------sdf---------------\n%s\n--------------------\n",sdf_string.c_str());
01996 gazebo_xml_out.Parse(sdf_string.c_str());
01997 #endif
01998
01999 return true;
02000 }
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010