00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #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
00046
00047 SRDFWriter::SRDFWriter()
00048 {
00049
00050 srdf_model_.reset( new srdf::Model() );
00051 }
00052
00053
00054
00055
00056 SRDFWriter::~SRDFWriter()
00057 {
00058 }
00059
00060
00061
00062
00063 bool SRDFWriter::initString( const urdf::ModelInterface &robot_model, const std::string &srdf_string )
00064 {
00065
00066 if( !srdf_model_->initString( robot_model, srdf_string ) )
00067 {
00068 return false;
00069 }
00070
00071
00072 initModel( robot_model, *srdf_model_ );
00073
00074 return true;
00075 }
00076
00077
00078
00079
00080 void SRDFWriter::initModel( const urdf::ModelInterface &robot_model, const srdf::Model &srdf_model )
00081 {
00082
00083 if (srdf_model_.get() != &srdf_model)
00084 {
00085 *srdf_model_ = srdf_model;
00086 }
00087
00088
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
00098 robot_name_ = robot_model.getName();
00099 }
00100
00101
00102
00103
00104 void SRDFWriter::updateSRDFModel( const urdf::ModelInterface &robot_model )
00105 {
00106
00107 const std::string srdf_string = getSRDFString();
00108
00109
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
00119
00120 bool SRDFWriter::writeSRDF( const std::string &file_path )
00121 {
00122
00123 TiXmlDocument document = generateSRDF();
00124
00125
00126 return document.SaveFile( file_path );
00127 }
00128
00129
00130
00131
00132 std::string SRDFWriter::getSRDFString()
00133 {
00134
00135 TiXmlDocument document = generateSRDF();
00136
00137
00138 TiXmlPrinter printer;
00139 printer.SetIndent( " " );
00140 document.Accept( &printer );
00141
00142
00143 return printer.CStr();
00144 }
00145
00146
00147
00148
00149 TiXmlDocument SRDFWriter::generateSRDF()
00150 {
00151 TiXmlDocument document;
00152 TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "", "" );
00153 document.LinkEndChild( decl );
00154
00155
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
00160 TiXmlElement* robot_root = new TiXmlElement("robot");
00161 robot_root->SetAttribute("name", robot_name_ );
00162 document.LinkEndChild( robot_root );
00163
00164
00165 createGroupsXML( robot_root );
00166
00167
00168 createGroupStatesXML( robot_root );
00169
00170
00171 createEndEffectorsXML( robot_root );
00172
00173
00174 createVirtualJointsXML( robot_root );
00175
00176
00177 createPassiveJointsXML( robot_root );
00178
00179
00180 createLinkSphereApproximationsXML( robot_root );
00181
00182
00183 createDisabledCollisionsXML( robot_root );
00184
00185
00186 return document;
00187 }
00188
00189
00190
00191
00192 void SRDFWriter::createGroupsXML( TiXmlElement *root )
00193 {
00194
00195 if( groups_.size() )
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
00211 for( std::vector<srdf::Model::Group>::iterator group_it = groups_.begin();
00212 group_it != groups_.end(); ++group_it )
00213 {
00214
00215
00216 TiXmlElement *group = new TiXmlElement("group");
00217 group->SetAttribute("name", group_it->name_ );
00218 root->LinkEndChild(group);
00219
00220
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 );
00226 group->LinkEndChild( link );
00227 }
00228
00229
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 );
00235 group->LinkEndChild( joint );
00236 }
00237
00238
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
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 );
00254 group->LinkEndChild( subgroup );
00255 }
00256
00257 }
00258 }
00259
00260
00261
00262
00263 void SRDFWriter::createLinkSphereApproximationsXML( TiXmlElement *root )
00264 {
00265 if( link_sphere_approximations_.empty() )
00266 return;
00267
00268
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())
00278 continue;
00279
00280
00281 TiXmlElement *link = new TiXmlElement("link_sphere_approximation");
00282 link->SetAttribute("link", link_sphere_it->link_);
00283 root->LinkEndChild( link );
00284
00285
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
00302
00303 void SRDFWriter::createDisabledCollisionsXML( TiXmlElement *root )
00304 {
00305
00306 if( disabled_collisions_.size() )
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
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
00328
00329 void SRDFWriter::createGroupStatesXML( TiXmlElement *root )
00330 {
00331
00332 if( group_states_.size() )
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
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
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 );
00354 joint->SetDoubleAttribute("value", value_it->second[0] );
00355
00356
00357 state->LinkEndChild( joint );
00358 }
00359 }
00360 }
00361
00362
00363
00364
00365 void SRDFWriter::createEndEffectorsXML( TiXmlElement *root )
00366 {
00367
00368 if( end_effectors_.size() )
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
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
00391
00392 void SRDFWriter::createVirtualJointsXML( TiXmlElement *root )
00393 {
00394
00395 if( virtual_joints_.size() )
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
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
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 }