urdf2gazebo.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 * 
00004 *  Copyright (c) 2008, Willow Garage, Inc.
00005 *  All rights reserved.
00006 * 
00007 *  Redistribution and use in source and binary forms, with or without
00008 *  modification, are permitted provided that the following conditions
00009 *  are met:
00010 * 
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of the Willow Garage nor the names of its
00018 *     contributors may be used to endorse or promote products derived
00019 *     from this software without specific prior written permission.
00020 * 
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
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   // set gazebo media paths by adding all packages that exports "gazebo_media_path" for gazebo
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     // search for path, add if not there already
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 /* do some checks
00114 
00115     if (vals.empty())
00116     {
00117       poseStr += "0 0 0";
00118     }
00119     else
00120     {
00121       if (vals.size() != 3)
00122       {
00123         gzerr << "Vector contains [" << static_cast<int>(vals.size())
00124               << "] elements instead of 3 elements\n";
00125         return false;
00126       }
00127       // convert vals to radian
00128       std::ostringstream rpy_stream;
00129       rpy_stream << GZ_DTOR(vals[0]) << " "
00130                  << GZ_DTOR(vals[1]) << " "
00131                  << GZ_DTOR(vals[2]);
00132       if (rpy_stream.str().empty())
00133       {
00134         gzerr << "rpy_stream is empty, something is wrong\n";
00135         return false;
00136       }
00137       poseStr += rpy_stream.str();
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     // group does not exist, create one and add to map
00150     viss.reset(new std::vector<boost::shared_ptr<urdf::Visual > >);
00151     // new group name, create vector, add vector to map and add Visual to the vector
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   // group exists, add Visual to the vector in the map
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     // group does not exist, create one and add to map
00172     viss.reset(new std::vector<boost::shared_ptr<urdf::Collision > >);
00173     // new group name, create vector, add vector to map and add Collision to the vector
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   // group exists, add Collision to the vector in the map
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); // remove if one already exists
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     // Notes:
00239     // mat.getRPY is broken, get back quaternion, use urdf::Rotation to get from quaternion to rpy
00240     //q.getRPY(crot[0],crot[1],crot[2]);
00241     //mat.getEulerYPR(crot[2],crot[1],crot[0]); // equivalent to below // bug with gimbal lock
00242     //mat.getRPY(crot[0],crot[1],crot[2]); // bug with gimbal lock
00243     
00244     /* set geometry transform */
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()) // FIXME: comment out check for now, as ros and system tinyxml does not match.  elem->FirstChild()->Type() == TiXmlNode::TINYXML_TEXT
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   // Get all Gazebo extension elements, put everything in this->gazebo_extensions_ map, containing a key string (link/joint name) and values
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       // copy extensions for robot (outside of link/joint)
00277       ref_str.clear();
00278     }
00279     else
00280     {
00281       ROS_DEBUG("parsing gazebo extension for %s",ref);
00282       // copy extensions for link/joint
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     // create and insert a new GazeboExtension into the map
00294     GazeboExtension* gazebo = new GazeboExtension();
00295 
00296 
00297     // begin parsing xml node
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       // go through all elements of the extension, extract what we know, and save the rest in blobs
00305 
00306       // material
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         // default of setting static flag is false
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         // default of turnGravityOff is false
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         // default of genTexCoord is false
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         // default of selfCollide is false
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           // save all unknown stuff in a vector of blobs
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     // insert into my map
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           // insert mu1, mu2, kp, kd for geom
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           // max contact interpenetration correction velocity
00489           if ((*ge)->is_maxVel)
00490               addKeyValue(elem, "maxVel", values2str(1, &(*ge)->maxVel) );
00491           // contact interpenetration margin tolerance
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           // insert material block
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           // insert turnGravityOff
00533           if ((*ge)->turnGravityOff)
00534               addKeyValue(elem, "turnGravityOff", "true");
00535           else
00536               addKeyValue(elem, "turnGravityOff", "false");
00537 
00538           // damping factor
00539           if ((*ge)->is_dampingFactor)
00540               addKeyValue(elem, "dampingFactor", values2str(1, &(*ge)->dampingFactor) );
00541           // selfCollide tag
00542           if ((*ge)->selfCollide)
00543               addKeyValue(elem, "selfCollide", "true");
00544           else
00545               addKeyValue(elem, "selfCollide", "false");
00546           // insert blobs into body
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           // insert stopKp, stopKd, fudgeFactor
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           // insert provideFeedback
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()) // no reference
00591       {
00592         for (std::vector<GazeboExtension*>::iterator ge = gazebo_it->second.begin(); ge != gazebo_it->second.end(); ge++)
00593         {
00594           // insert static flag
00595           if ((*ge)->setStaticFlag)
00596               addKeyValue(elem, "static", "true");
00597           else
00598               addKeyValue(elem, "static", "false");
00599           // insert blobs into robot
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   // if child is attached to self by fixed link first go up the tree, check it's children recursively
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   // reduce this link's stuff up the tree to parent but skip first joint if it's the world
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     // lump gazebo extensions to parent, (give them new reference link names)
00759     reduceGazeboExtensionToParent(link);
00760 
00761     ROS_DEBUG("TREE:   mass lumping from [%s] to [%s]",link->name.c_str(),link->getParent()->name.c_str());
00762     /* now lump all contents of this link to parent */
00763     if (link->inertial)
00764     {
00765       // get parent mass (in parent link frame)
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       // set link mass (in link frame)
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       // un-rotate link mass into parent link frame
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       // un-translate link mass into parent link frame
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       // now link_mass is in the parent frame, add link_mass to parent_mass
00797       dMassAdd(&parent_mass,&link_mass); // now parent_mass contains link_mass in parent frame
00798       printMass(link->getParent()->name,parent_mass);
00799       // update parent mass
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     // lump visual to parent
00814     // lump all visual to parent, assign group name "lump::"+group name+"::'+link name
00815     // lump but keep the link name in(/as) the group name, so we can correlate visuals to visuals somehow.
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       // if it's a "default" mesh, it should be added under "lump:"+link name
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           // transform visual origin from link frame to parent link frame before adding to parent
00827           (*visual_it)->origin = transformToParentFrame((*visual_it)->origin, link->parent_joint->parent_to_joint_origin_transform);
00828           // add the modified visual to parent
00829           this->addVisual(link->getParent(),lump_group_name,*visual_it);
00830         }
00831       }
00832       else if (visuals_it->first.find(std::string("lump::")) == 0) // starts with "lump::"
00833       {
00834         // if it's a previously lumped mesh, relump under same group_name
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           // transform visual origin from link frame to parent link frame before adding to parent
00840           (*visual_it)->origin = transformToParentFrame((*visual_it)->origin, link->parent_joint->parent_to_joint_origin_transform);
00841           // add the modified visual to parent
00842           this->addVisual(link->getParent(),lump_group_name,*visual_it);
00843         }
00844       }
00845     }
00846 
00847     // lump collision parent
00848     // lump all collision to parent, assign group name "lump::"+group name+"::'+link name
00849     // lump but keep the link name in(/as) the group name, so we can correlate visuals to collisions somehow.
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       // if it's a "default" mesh, it should be added under "lump:"+link name
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           // transform collision origin from link frame to parent link frame before adding to parent
00861           (*collision_it)->origin = transformToParentFrame((*collision_it)->origin, link->parent_joint->parent_to_joint_origin_transform);
00862           // add the modified collision to parent
00863           this->addCollision(link->getParent(),lump_group_name,*collision_it);
00864         }
00865       }
00866       else if (collisions_it->first.find(std::string("lump::")) == 0) // starts with "lump::"
00867       {
00868         // if it's a previously lumped mesh, relump under same group_name
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           // transform collision origin from link frame to parent link frame before adding to parent
00874           (*collision_it)->origin = transformToParentFrame((*collision_it)->origin, link->parent_joint->parent_to_joint_origin_transform);
00875           // add the modified collision to parent
00876           this->addCollision(link->getParent(),lump_group_name,*collision_it);
00877         }
00878       }
00879     }
00880     printCollisionGroups(link->getParent());
00881 
00882     // STRATEGY: later when extracting visuals and collision pairs to construct <geom> for gazebo, given that geom(coillision) wraps visual,
00883     //           loop through lumped collisions, for each collision,
00884     //             call createGeom() using visual_groups.find(lump group name) to find potential visuals to create the <geom> tag for the body.
00885     //           This way, <geom> is created only if collision exists in first place, and if matching visual exists it is used, other a sphere default
00886     //             is created
00887 
00888 
00889     ROS_DEBUG("BEGIN JOINT LUMPING");
00890     // set child link's parent_joint's parent link to a parent link up stream that does not have a fixed parent_joint
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         // go down the tree until we hit a parent joint that is not fixed
00895         boost::shared_ptr<urdf::Link> new_parent_link = link;
00896         gazebo::math::Pose joint_anchor_transform; // set to identity first
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         // now set the link->child_links[i]->parent_joint's parent link to the new_parent_link
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         // and set the link->child_links[i]->parent_joint's parent_to_joint_orogin_transform as the aggregated
00909         //   anchor transform?
00910       }
00911     }
00912   }
00913 
00914   // continue down the tree for non-fixed joints
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     //for (std::vector<boost::shared_ptr<urdf::Collision> >::iterator collision_it = cols_it->second->begin(); collision_it != cols_it->second->end(); collision_it++)
00929     //  ROS_DEBUG("     origins for debugging: [%s]",...cols_it->first.c_str());
00930   }
00931 }
00932 
00934 urdf::Pose  URDF2Gazebo::transformToParentFrame(urdf::Pose transform_in_link_frame, urdf::Pose parent_to_link_transform)
00935 {
00936     // transform to gazebo::math::Pose then call transformToParentFrame
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     // transform to gazebo::math::Pose then call transformToParentFrame
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     // in the new revision, gazebo::math::Pose has some transform operator overrides
00952     //   rotate link pose to parent_link frame
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     //   translate link to parent_link frame
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     // in the new revision, gazebo::math::Pose has some transform operator overrides
00965     //   rotate link pose to parent_link frame
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     //   translate link to parent_link frame
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   // this is a very complicated module that updates the plugins based on fixed joint reduction
00983   // really wish this could be a lot cleaner
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   // update extension map with references to link_name
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     // update reduction transform (for rays, cameras for now).  FIXME: contact frames too?
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       // FIXME: if the sensor block has sensor:ray or sensor:camera or sensor:stereo_camera, look for/replace/insert reduction transform into xml block
01002       updateGazeboExtensionBlobsReductionTransform((*ge));
01003       // replace all instances of the link_name string in blobs with new_link_name
01004       updateGazeboExtensionFrameReplace(*ge, link, new_link_name);
01005     }
01006 
01007     // find existing extension with the new link reference
01008     std::map<std::string,std::vector<GazeboExtension*> >::iterator new_ext = this->gazebo_extensions_.find(new_link_name);
01009     // create new_extension if none exists
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     // pop extensions from link's vector and push them into the new link's vector
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   // for extensions with empty reference, search and replace link name patterns within the plugin with new link name
01028   //   and assign the proper reduction transform for the link name pattern
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       // update reduction transform (for contacts, rays, cameras for now).
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   // HACK: need to do this more generally, but we also need to replace all instances of link name with new link name
01047   //       e.g. contact sensor refers to <geom>base_link_geom</geom> and it needs to be reparented to <geom>base_footprint_geom</geom>
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         // parse it and add/replace the reduction transform
01061         // find first instance of xyz and rpy, replace with reduction transform
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           // FIXME: chagning contact sensor's contact geom should trigger a update in sensor offset as well.
01077           // FIXME: but first we need to implement offsets in contact sensors
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         // parse it and add/replace the reduction transform
01086         // find first instance of xyz and rpy, replace with reduction transform
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             // overwrite <xyzOffset> and <rpyOffset> if they exist
01121             if ((*blob_it)->ValueStr() == "controller:gazebo_ros_p3d" || (*blob_it)->ValueStr() == "controller:gazebo_ros_imu")
01122             {
01123               // parse it and add/replace the reduction transform
01124               // find first instance of xyzOffset and rpyOffset, replace with reduction transform
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               // read user specified xyzOffset and rpyOffset, fill in the current reduction transform
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                 // remove xyzOffset and rpyOffset
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                 // remove xyzOffset and rpyOffset
01148                 (*blob_it)->RemoveChild(rpy_key);
01149               }
01150 
01151               // pass through the parent transform from fixed joint reduction
01152               ge->reduction_transform = inverseTransformToParentFrame(ge->reduction_transform, link->parent_joint->parent_to_joint_origin_transform);
01153 
01154               // create new offset xml blocks
01155               xyz_key = new TiXmlElement("xyzOffset");
01156               rpy_key = new TiXmlElement("rpyOffset");
01157 
01158               // create new offset xml blocks
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); // convert to Euler angles for Gazebo XML
01166               rpy_stream << reduction_rpy.x*180./M_PI << " " << reduction_rpy.y*180./M_PI << " " << reduction_rpy.z*180./M_PI; // convert to degrees for Gazebo (though ROS is in Radians)
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         // updates link reference for <projector> inside of controller:gazebo_ros_projector
01181         TiXmlNode* projectorName = (*blob_it)->FirstChild("projector");
01182         {
01183           // change body name, in this case, projector element is "link name"/"projector name"
01184           // and we only want to replace link name
01185           if (projectorName)
01186           {
01187             std::string projector_name =  getGazeboValue(projectorName->ToElement());
01188             // extract projector link name and projector name
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               // do the replacement
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         // parse it and add/replace the reduction transform
01250         // find first instance of xyz and rpy, replace with reduction transform
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     // overwrite <xyz> and <rpy> if they exist
01310     if ((*blob_it)->ValueStr() == "sensor:ray" || (*blob_it)->ValueStr() == "sensor:camera")
01311     {
01312       // parse it and add/replace the reduction transform
01313       // find first instance of xyz and rpy, replace with reduction transform
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       // FIXME:  we should read xyz, rpy and aggregate it to reduction_transform instead of just throwing the info away.
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); // convert to Euler angles for Gazebo XML
01340       rpy_stream << reduction_rpy.x*180./M_PI << " " << reduction_rpy.y*180./M_PI << " " << reduction_rpy.z*180./M_PI; // convert to degrees for Gazebo (though ROS is in Radians)
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     // overwrite <pose> (xyz/rpy) if it exists
01353     if ((*blob_it)->ValueStr() == "projector")
01354     {
01355       // parse it and add/replace the reduction transform
01356       // find first instance of xyz and rpy, replace with reduction transform
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       /* should read <pose>...</pose> and agregate reduction_transform */
01366       TiXmlNode* pose_key = (*blob_it)->FirstChild("pose");
01367       // read pose and save it
01368 
01369       // remove the tag for now
01370       if (pose_key) (*blob_it)->RemoveChild(pose_key);
01371 
01372       // convert reduction_transform to values
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); // convert to Euler angles for Gazebo XML
01377       // output updated pose to text
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; // convert to degrees for Gazebo (though ROS is in Radians)
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     // must have an <inertial> block and cannot have zero mass.  allow det(I) == zero, such as in the case of point mass geoms.
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     /* create <body:...> block for non fixed joint attached bodies */
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     // recurse into children
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 &currentTransform, bool enforce_limits, bool reduce_fixed_joints)
01493 {
01494     int linkGeomSize;
01495     double linkSize[3];
01496 
01497     /* create new body */
01498     TiXmlElement *elem     = new TiXmlElement("body:empty"); // FIXME:  does it matter what the collision type of the body is?
01499 
01500     /* set body name */
01501     elem->SetAttribute("name", link->name);
01502 
01503     /* set mass properties */
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     /* compute global transform */
01524     gazebo::math::Pose localTransform;
01525     // this is the transform from parent link to current link
01526     // this transform does not exist for the root link
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     // create origin tag for this element
01538     addTransform(elem, currentTransform);
01539 
01540     // make additional geoms using the lumped stuff
01541     // FIXME:  what's the pairing strategy between visuals and collisions?
01542     //      when only visuals exists?
01543     //      when only collisions exists?
01544     //         originally, there's one visual and one collision per link, which maps nicely to <body><geom><visual> heirarchy
01545     //         now we have multiple visuals and collisions...  how do we map?
01546     // loop through all default visuals and lump visuals
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); // add collision information
01561         
01562         /* make a <geom:...> block */
01563         createGeom(elem, link, collision_type, collision, visual, linkGeomSize, linkSize, link->name);
01564       }
01565       else if (collisions_it->first.find(std::string("lump::")) == 0) // starts with "lump::"
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); // add collision information
01576         
01577         std::string original_reference = collisions_it->first.substr(6);
01578         /* make a <geom:...> block */
01579         createGeom(elem, link, collision_type, collision, visual, linkGeomSize, linkSize, original_reference);
01580       }
01581     }
01582 
01583     /* copy gazebo extensions data */
01584     insertGazeboExtensionBody(elem,link->name);
01585     
01586     /* add body to document */
01587     root->LinkEndChild(elem);
01588 
01589     /* make a <joint:...> block */
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 &currentTransform, bool enforce_limits,bool reduce_fixed_joints)
01596 {
01597     /* compute the joint tag */
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     // skip if joint type is fixed and we are not faking it with a hinge, skip/return
01624     //   with the exception of root link being world, because there's no lumping there
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             // Joint Anchor is deprecated
01655             // urdf::Transform currentAnchorTransform( currentTransform ); 
01656             // currentAnchorTransform.setOrigin( urdf::Vector3(0, 0, 0) ); 
01657             // urdf::Vector3 jointAnchor = currentAnchorTransform * urdf::Vector3( link->parent_joint->anchor.x,
01658             //                                                             link->parent_joint->anchor.y,
01659             //                                                             link->parent_joint->anchor.z ); 
01660             // double tmpAnchor[3] =  { jointAnchor.x(), jointAnchor.y(), jointAnchor.z() };
01661             // addKeyValue(joint, "anchorOffset", values2str(3, tmpAnchor));
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                     // enforce ode bounds, this will need to be fixed
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         /* copy gazebo extensions data */
01686         insertGazeboExtensionJoint(joint,link->parent_joint->name);
01687 
01688         /* add joint to document */
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     /* begin create geometry node, skip if no collision specified */
01697     if (collision_type != "empty")
01698     {
01699         TiXmlElement *geom     = new TiXmlElement("geom:" + collision_type);
01700         /* set its name */
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         /* set transform */
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             /* set mesh size or scale */
01717             addKeyValue(geom, "scale", vector32str(mesh->scale));
01718 
01719             /* set mesh file */
01720             /* expand to get absolute mesh filename */
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             // give some warning if file does not exist.
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             // add mesh filename
01749             addKeyValue(geom, "mesh", fullname);
01750             
01751         }
01752         else
01753         {
01754             /* set geometry size */
01755             addKeyValue(geom, "size", values2str(linkGeomSize, linkSize));
01756         }
01757         
01758         /* set additional data from extensions */
01759         insertGazeboExtensionGeom(geom,original_reference);
01760 
01761         // FIXME: unfortunately, visual is not created if collision is missing!!!
01762         createVisual(geom, link, collision_type, collision, visual,original_reference);
01763 
01764         /* add geometry to body */
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     /* begin create gazebo visual node */
01772     TiXmlElement *gazebo_visual = new TiXmlElement("visual");
01773 
01774     /* compute the visualisation transfrom */
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     /* set geometry size */                
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         /* set mesh size or scale */
01805         /*
01806         if (visual->geometry->isSet["size"])
01807             addKeyValue(gazebo_visual, "size", values2str(3, mesh->size));        
01808         else
01809             addKeyValue(gazebo_visual, "scale", values2str(3, mesh->scale));        
01810         */
01811         addKeyValue(gazebo_visual, "scale", vector32str(mesh->scale));
01812 
01813         /* set mesh file */
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); // reuse collision type if mesh does not specify filename
01818         }
01819         else
01820         {
01821             /* set mesh file */
01822             /* expand to get absolute mesh filename */
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             // add mesh filename
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     /* set additional data from extensions */
01859     insertGazeboExtensionVisual(gazebo_visual,original_reference);
01860 
01861     /* end create visual node */
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     // copy model to a string
01893     std::ostringstream stream_in;
01894     stream_in << urdf_in;
01895 
01896     /* Create a RobotModel from string */
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     // add xml declaration if needed
01908     if (xml_declaration)
01909     {
01910       TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "", "");
01911       gazebo_xml_out.LinkEndChild(decl);  // uncomment if returning old gazebo_xml
01912     }
01913 #endif
01914     
01915     /* create root element and define needed namespaces */
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     // set model name to urdf robot name if not specified
01929     if (model_name.empty())
01930       robot->SetAttribute("name", robot_model.getName());
01931     else
01932       robot->SetAttribute("name", model_name);
01933     
01934     /* set the transform for the whole model to identity */
01935     addKeyValue(robot, "xyz", vector32str(initial_xyz));
01936     addKeyValue(robot, "rpy", vector32str(initial_rpy));
01937     gazebo::math::Pose transform;
01938     
01939     /* parse gazebo extension */
01940     parseGazeboExtension( urdf_in );
01941 
01942     /* start conversion */
01943 
01944     boost::shared_ptr<const urdf::Link> root_link = robot_model.getRoot();
01945     /* if link connects to parent via fixed joint, lump down and remove link */
01946     // set reduce_fixed_joints to true will use hinge joints replacements, otherwise, we reduce it down to its parent link recursively
01947     bool reduce_fixed_joints = true;
01948     if (reduce_fixed_joints)
01949       reduceFixedJoints(robot, (boost::const_pointer_cast< urdf::Link >(root_link))); // uncomment to test reduction
01950 
01951     if (root_link->name == "world")
01952     {
01953       /* convert all children link */
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       /* convert, starting from root link */
01960       convertLink(robot, root_link, transform, enforce_limits, reduce_fixed_joints);
01961     }
01962     
01963     /* find all data item types */
01964     insertGazeboExtensionRobot(robot);
01965     
01966     if (!robot_namespace.empty())
01967     {
01968       // traverse all of the: controller::*, add robotNamespace if does not exist already
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);  // uncomment if returning old gazebo_xml
01978 #endif
01979 
01980 
01981 #ifdef TO_SDF
01982     //
01983     // step 2 of the two step conversion from URDF --> XML --> SDF
01984     // now convert the old gazebo xml into sdf
01985     //
01986     sdf::SDFPtr robot_sdf(new sdf::SDF());
01987     if (!sdf::init(robot_sdf))  // FIXME: this step requires that GAZEBO_RESOURCE_PATH be set to where *.sdf are located
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     // write out sdf as a string, then read string into TiXmlDocument gazebo_xml_out
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 


gazebo
Author(s): Nate Koenig, Andrew Howard, with contributions from many others. See web page for a full credits llist.
autogenerated on Sun Jan 5 2014 11:34:52