srdf_writer.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2012, 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 /* Author: Dave Coleman */
00036 
00037 #include <tinyxml.h>
00038 #include <ros/console.h>
00039 #include <moveit/setup_assistant/tools/srdf_writer.h>
00040 
00041 namespace moveit_setup_assistant
00042 {
00043 
00044 // ******************************************************************************************
00045 // Constructor
00046 // ******************************************************************************************
00047 SRDFWriter::SRDFWriter()
00048 {
00049   // Intialize the SRDF model
00050   srdf_model_.reset( new srdf::Model() );
00051 }
00052 
00053 // ******************************************************************************************
00054 // Destructor
00055 // ******************************************************************************************
00056 SRDFWriter::~SRDFWriter()
00057 {
00058 }
00059 
00060 // ******************************************************************************************
00061 // Load SRDF data from a pre-populated string
00062 // ******************************************************************************************
00063 bool SRDFWriter::initString( const urdf::ModelInterface &robot_model, const std::string &srdf_string )
00064 {
00065   // Parse string into srdf_model_ and Error check
00066   if( !srdf_model_->initString( robot_model, srdf_string ) )
00067   {
00068     return false; // error loading file. improper format?
00069   }
00070 
00071   // copy fields into this object
00072   initModel( robot_model, *srdf_model_ );
00073 
00074   return true;
00075 }
00076 
00077 // ******************************************************************************************
00078 // Load SRDF data from a pre-populated string
00079 // ******************************************************************************************
00080 void SRDFWriter::initModel( const urdf::ModelInterface &robot_model, const srdf::Model &srdf_model )
00081 {
00082   // copy to internal srdf_model_
00083   if (srdf_model_.get() != &srdf_model)
00084   {
00085     *srdf_model_ = srdf_model;
00086   }
00087 
00088   // Copy all read-only data from srdf model to this object
00089   disabled_collisions_ = srdf_model_->getDisabledCollisionPairs();
00090   link_sphere_approximations_ = srdf_model_->getLinkSphereApproximations();
00091   groups_ = srdf_model_->getGroups();
00092   virtual_joints_ = srdf_model_->getVirtualJoints();
00093   end_effectors_ = srdf_model_->getEndEffectors();
00094   group_states_ = srdf_model_->getGroupStates();
00095   passive_joints_ = srdf_model_->getPassiveJoints();
00096 
00097   // Copy the robot name b/c the root xml element requires this attribute
00098   robot_name_ = robot_model.getName();
00099 }
00100 
00101 // ******************************************************************************************
00102 // Update the SRDF Model class using a new SRDF string
00103 // ******************************************************************************************
00104 void SRDFWriter::updateSRDFModel( const urdf::ModelInterface &robot_model )
00105 {
00106   // Get an up to date SRDF String
00107   const std::string srdf_string = getSRDFString();
00108 
00109   // Error check
00110   if( !srdf_model_->initString( robot_model, srdf_string ) )
00111   {
00112     ROS_ERROR( "Unable to update the SRDF Model" );
00113     exit(1);
00114   }
00115 }
00116 
00117 // ******************************************************************************************
00118 // Save to file a generated SRDF document
00119 // ******************************************************************************************
00120 bool SRDFWriter::writeSRDF( const std::string &file_path )
00121 {
00122   // Generate the SRDF
00123   TiXmlDocument document = generateSRDF();
00124 
00125   // Save to file
00126   return document.SaveFile( file_path );
00127 }
00128 
00129 // ******************************************************************************************
00130 // Get a string of a generated SRDF document
00131 // ******************************************************************************************
00132 std::string SRDFWriter::getSRDFString()
00133 {
00134   // Generate the SRDF
00135   TiXmlDocument document = generateSRDF();
00136 
00137   // Setup printer
00138   TiXmlPrinter printer;
00139   printer.SetIndent( "    " );
00140   document.Accept( &printer );
00141 
00142   // Return string
00143   return printer.CStr();
00144 }
00145 
00146 // ******************************************************************************************
00147 // Generate SRDF XML of all contained data
00148 // ******************************************************************************************
00149 TiXmlDocument SRDFWriter::generateSRDF()
00150 {
00151   TiXmlDocument document;
00152   TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "", "" );
00153   document.LinkEndChild( decl );
00154 
00155   // Convenience comments
00156   TiXmlComment * comment = new TiXmlComment( "This does not replace URDF, and is not an extension of URDF.\n    This is a format for representing semantic information about the robot structure.\n    A URDF file must exist for this robot as well, where the joints and the links that are referenced are defined\n" );
00157   document.LinkEndChild( comment );
00158 
00159   // Root
00160   TiXmlElement* robot_root = new TiXmlElement("robot");
00161   robot_root->SetAttribute("name", robot_name_ ); // robot name
00162   document.LinkEndChild( robot_root );
00163 
00164   // Add Groups
00165   createGroupsXML( robot_root );
00166 
00167   // Add Group States
00168   createGroupStatesXML( robot_root );
00169 
00170   // Add End Effectors
00171   createEndEffectorsXML( robot_root );
00172 
00173   // Add Virtual Joints
00174   createVirtualJointsXML( robot_root );
00175 
00176   // Add Passive Joints
00177   createPassiveJointsXML( robot_root );
00178 
00179   // Add Link Sphere approximations
00180   createLinkSphereApproximationsXML( robot_root );
00181 
00182   // Add Disabled Collisions
00183   createDisabledCollisionsXML( robot_root );
00184 
00185   // Save
00186   return document;
00187 }
00188 
00189 // ******************************************************************************************
00190 // Generate XML for SRDF groups
00191 // ******************************************************************************************
00192 void SRDFWriter::createGroupsXML( TiXmlElement *root )
00193 {
00194   // Convenience comments
00195   if( groups_.size() ) // only show comments if there are corresponding elements
00196   {
00197     TiXmlComment *comment;
00198     comment = new TiXmlComment( "GROUPS: Representation of a set of joints and links. This can be useful for specifying DOF to plan for, defining arms, end effectors, etc" );
00199     root->LinkEndChild( comment );
00200     comment = new TiXmlComment( "LINKS: When a link is specified, the parent joint of that link (if it exists) is automatically included" );
00201     root->LinkEndChild( comment );
00202     comment = new TiXmlComment( "JOINTS: When a joint is specified, the child link of that joint (which will always exist) is automatically included" );
00203     root->LinkEndChild( comment );
00204     comment = new TiXmlComment( "CHAINS: When a chain is specified, all the links along the chain (including endpoints) are included in the group. Additionally, all the joints that are parents to included links are also included. This means that joints along the chain and the parent joint of the base link are included in the group");
00205     root->LinkEndChild( comment );
00206     comment = new TiXmlComment( "SUBGROUPS: Groups can also be formed by referencing to already defined group names" );
00207     root->LinkEndChild( comment );
00208   }
00209 
00210   // Loop through all of the top groups
00211   for( std::vector<srdf::Model::Group>::iterator group_it = groups_.begin();
00212        group_it != groups_.end();  ++group_it )
00213   {
00214 
00215     // Create group element
00216     TiXmlElement *group = new TiXmlElement("group");
00217     group->SetAttribute("name", group_it->name_ ); // group name
00218     root->LinkEndChild(group);
00219 
00220     // LINKS
00221     for( std::vector<std::string>::const_iterator link_it = group_it->links_.begin();
00222          link_it != group_it->links_.end(); ++link_it )
00223     {
00224       TiXmlElement *link = new TiXmlElement("link");
00225       link->SetAttribute("name", *link_it ); // link name
00226       group->LinkEndChild( link );
00227     }
00228 
00229     // JOINTS
00230     for( std::vector<std::string>::const_iterator joint_it = group_it->joints_.begin();
00231          joint_it != group_it->joints_.end(); ++joint_it )
00232     {
00233       TiXmlElement *joint = new TiXmlElement("joint");
00234       joint->SetAttribute("name", *joint_it ); // joint name
00235       group->LinkEndChild( joint );
00236     }
00237 
00238     // CHAINS
00239     for( std::vector<std::pair<std::string,std::string> >::const_iterator chain_it = group_it->chains_.begin();
00240          chain_it != group_it->chains_.end(); ++chain_it )
00241     {
00242       TiXmlElement *chain = new TiXmlElement("chain");
00243       chain->SetAttribute("base_link", chain_it->first );
00244       chain->SetAttribute("tip_link", chain_it->second );
00245       group->LinkEndChild( chain );
00246     }
00247 
00248     // SUBGROUPS
00249     for( std::vector<std::string>::const_iterator subgroup_it = group_it->subgroups_.begin();
00250          subgroup_it != group_it->subgroups_.end(); ++subgroup_it )
00251     {
00252       TiXmlElement *subgroup = new TiXmlElement("group");
00253       subgroup->SetAttribute("name", *subgroup_it ); // subgroup name
00254       group->LinkEndChild( subgroup );
00255     }
00256 
00257   }
00258 }
00259 
00260 // ******************************************************************************************
00261 // Generate XML for SRDF link collision spheres
00262 // ******************************************************************************************
00263 void SRDFWriter::createLinkSphereApproximationsXML( TiXmlElement *root )
00264 {
00265   if( link_sphere_approximations_.empty() ) // skip it if there are none
00266     return;
00267 
00268   // Convenience comments
00269   TiXmlComment *comment = new TiXmlComment();
00270   comment->SetValue( "COLLISION SPHERES: Purpose: Define a set of spheres that bounds a link." );
00271   root->LinkEndChild( comment );
00272 
00273 
00274   for ( std::vector<srdf::Model::LinkSpheres>::const_iterator link_sphere_it = link_sphere_approximations_.begin();
00275         link_sphere_it != link_sphere_approximations_.end() ; ++link_sphere_it)
00276   {
00277     if (link_sphere_it->spheres_.empty())  // skip if no spheres for this link
00278       continue;
00279 
00280     // Create new element for the link
00281     TiXmlElement *link = new TiXmlElement("link_sphere_approximation");
00282     link->SetAttribute("link", link_sphere_it->link_);
00283     root->LinkEndChild( link );
00284 
00285     // Add all spheres for the link
00286     for( std::vector<srdf::Model::Sphere>::const_iterator sphere_it = link_sphere_it->spheres_.begin();
00287          sphere_it != link_sphere_it->spheres_.end(); ++sphere_it )
00288     {
00289       TiXmlElement *sphere = new TiXmlElement("sphere");
00290       std::stringstream center;
00291       center.precision(20);
00292       center << sphere_it->center_x_ << " " << sphere_it->center_y_ << " " << sphere_it->center_z_;
00293       sphere->SetAttribute("center", center.str() );
00294       sphere->SetDoubleAttribute("radius", sphere_it->radius_ );
00295       link->LinkEndChild( sphere );
00296     }
00297   }
00298 }
00299 
00300 // ******************************************************************************************
00301 // Generate XML for SRDF disabled collisions of robot link pairs
00302 // ******************************************************************************************
00303 void SRDFWriter::createDisabledCollisionsXML( TiXmlElement *root )
00304 {
00305   // Convenience comments
00306   if( disabled_collisions_.size() ) // only show comments if there are corresponding elements
00307   {
00308     TiXmlComment *comment = new TiXmlComment();
00309     comment->SetValue( "DISABLE COLLISIONS: By default it is assumed that any link of the robot could potentially come into collision with any other link in the robot. This tag disables collision checking between a specified pair of links. " );
00310     root->LinkEndChild( comment );
00311   }
00312 
00313   for ( std::vector<srdf::Model::DisabledCollision>::const_iterator pair_it = disabled_collisions_.begin();
00314         pair_it != disabled_collisions_.end() ; ++pair_it)
00315   {
00316     // Create new element for each link pair
00317     TiXmlElement *link_pair = new TiXmlElement("disable_collisions");
00318     link_pair->SetAttribute("link1", pair_it->link1_ );
00319     link_pair->SetAttribute("link2", pair_it->link2_ );
00320     link_pair->SetAttribute("reason", pair_it->reason_ );
00321 
00322     root->LinkEndChild( link_pair );
00323   }
00324 }
00325 
00326 // ******************************************************************************************
00327 // Generate XML for SRDF group states
00328 // ******************************************************************************************
00329 void SRDFWriter::createGroupStatesXML( TiXmlElement *root )
00330 {
00331   // Convenience comments
00332   if( group_states_.size() ) // only show comments if there are corresponding elements
00333   {
00334     TiXmlComment *comment = new TiXmlComment();
00335     comment->SetValue( "GROUP STATES: Purpose: Define a named state for a particular group, in terms of joint values. This is useful to define states like 'folded arms'" );
00336     root->LinkEndChild( comment );
00337   }
00338 
00339   for ( std::vector<srdf::Model::GroupState>::const_iterator state_it = group_states_.begin();
00340         state_it != group_states_.end() ; ++state_it)
00341   {
00342     // Create new element for each group state
00343     TiXmlElement *state = new TiXmlElement("group_state");
00344     state->SetAttribute("name", state_it->name_ );
00345     state->SetAttribute("group", state_it->group_ );
00346     root->LinkEndChild( state );
00347 
00348     // Add all joints
00349     for( std::map<std::string, std::vector<double> >::const_iterator value_it = state_it->joint_values_.begin();
00350          value_it != state_it->joint_values_.end(); ++value_it )
00351     {
00352       TiXmlElement *joint = new TiXmlElement("joint");
00353       joint->SetAttribute("name", value_it->first ); // joint name
00354       joint->SetDoubleAttribute("value", value_it->second[0] ); // joint value
00355 
00356       // TODO: use the vector to support multi-DOF joints
00357       state->LinkEndChild( joint );
00358     }
00359   }
00360 }
00361 
00362 // ******************************************************************************************
00363 // Generate XML for SRDF end effectors
00364 // ******************************************************************************************
00365 void SRDFWriter::createEndEffectorsXML( TiXmlElement *root )
00366 {
00367   // Convenience comments
00368   if( end_effectors_.size() ) // only show comments if there are corresponding elements
00369   {
00370     TiXmlComment *comment = new TiXmlComment();
00371     comment->SetValue( "END EFFECTOR: Purpose: Represent information about an end effector." );
00372     root->LinkEndChild( comment );
00373   }
00374 
00375   for ( std::vector<srdf::Model::EndEffector>::const_iterator effector_it = end_effectors_.begin();
00376         effector_it != end_effectors_.end() ; ++effector_it)
00377   {
00378     // Create new element for each link pair
00379     TiXmlElement *effector = new TiXmlElement("end_effector");
00380     effector->SetAttribute("name", effector_it->name_ );
00381     effector->SetAttribute("parent_link", effector_it->parent_link_ );
00382     effector->SetAttribute("group", effector_it->component_group_ );
00383     if (!effector_it->parent_group_.empty())
00384       effector->SetAttribute("parent_group", effector_it->parent_group_ );
00385     root->LinkEndChild( effector );
00386   }
00387 }
00388 
00389 // ******************************************************************************************
00390 // Generate XML for SRDF virtual joints
00391 // ******************************************************************************************
00392 void SRDFWriter::createVirtualJointsXML( TiXmlElement *root )
00393 {
00394   // Convenience comments
00395   if( virtual_joints_.size() ) // only show comments if there are corresponding elements
00396   {
00397     TiXmlComment *comment = new TiXmlComment();
00398     comment->SetValue( "VIRTUAL JOINT: Purpose: this element defines a virtual joint between a robot link and an external frame of reference (considered fixed with respect to the robot)" );
00399     root->LinkEndChild( comment );
00400   }
00401 
00402   for ( std::vector<srdf::Model::VirtualJoint>::const_iterator virtual_it = virtual_joints_.begin();
00403         virtual_it != virtual_joints_.end() ; ++virtual_it)
00404   {
00405     // Create new element for each link pair
00406     TiXmlElement *virtual_joint = new TiXmlElement("virtual_joint");
00407     virtual_joint->SetAttribute("name", virtual_it->name_ );
00408     virtual_joint->SetAttribute("type", virtual_it->type_ );
00409     virtual_joint->SetAttribute("parent_frame", virtual_it->parent_frame_ );
00410     virtual_joint->SetAttribute("child_link", virtual_it->child_link_ );
00411 
00412     root->LinkEndChild( virtual_joint );
00413   }
00414 }
00415 
00416 void SRDFWriter::createPassiveJointsXML( TiXmlElement *root )
00417 {
00418   if ( passive_joints_.size() )
00419   {
00420     TiXmlComment *comment = new TiXmlComment();
00421     comment->SetValue( "PASSIVE JOINT: Purpose: this element is used to mark joints that are not actuated" );
00422     root->LinkEndChild( comment );
00423   }
00424   for ( std::vector<srdf::Model::PassiveJoint>::const_iterator p_it = passive_joints_.begin();
00425         p_it != passive_joints_.end() ; ++p_it)
00426   {
00427     // Create new element for each link pair
00428     TiXmlElement *p_joint = new TiXmlElement("passive_joint");
00429     p_joint->SetAttribute("name", p_it->name_ );
00430     root->LinkEndChild( p_joint );
00431   }
00432 }
00433 
00434 
00435 }


moveit_setup_assistant
Author(s): Dave Coleman
autogenerated on Mon Oct 6 2014 02:32:27