00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <cstdio>
00036 #include <cstdlib>
00037
00038 #include <vector>
00039 #include <string>
00040 #include <sstream>
00041
00042 #include <gazebo/gazebo.h>
00043 #include <gazebo/GazeboError.hh>
00044 #include <gazebo/World.hh>
00045 #include <gazebo/Model.hh>
00046
00047 #include "ros/ros.h"
00048 #include <boost/program_options.hpp>
00049
00050 #include <gazebo_tools/urdf2gazebo.h>
00051
00052 void usage(const char *progname)
00053 {
00054 printf("\nUsage: %s [param_name] [options]\n", progname);
00055 printf(" Example: %s --help\n",progname);
00056 printf(" Example: %s robot_description -x 10\n",progname);
00057 printf(" Example: %s -i my_urdf_file.urdf -o gazebo_model.xml -x 10\n",progname);
00058 printf(" Example: %s -e pr2_model\n",progname);
00059 }
00060
00061 void remove_model(std::string remove_model_name)
00062 {
00063
00064
00065 libgazebo::Client *client = new libgazebo::Client();
00066 libgazebo::FactoryIface *factoryIface = new libgazebo::FactoryIface();
00067
00068 int serverId = 0;
00069
00071 bool connected_to_server = false;
00072 while (!connected_to_server)
00073 {
00074 try
00075 {
00076 client->ConnectWait(serverId, GZ_CLIENT_ID_USER_FIRST);
00077 connected_to_server = true;
00078 }
00079 catch (gazebo::GazeboError e)
00080 {
00081 ROS_ERROR("Gazebo error: Unable to connect\n %s\n",e.GetErrorStr().c_str());
00082 usleep(1000000);
00083 connected_to_server = false;
00084 }
00085 }
00086
00088 try
00089 {
00090 factoryIface->Open(client, "default");
00091 }
00092 catch (gazebo::GazeboError e)
00093 {
00094 ROS_ERROR("Gazebo error: Unable to connect to the factory interface\n%s\n",e.GetErrorStr().c_str());
00095 exit(2);
00096 }
00097
00099 bool writing_iface = true;
00100 while (writing_iface)
00101 {
00102 factoryIface->Lock(1);
00103 if (strcmp((char*)factoryIface->data->deleteEntity,"")==0)
00104 {
00105 ROS_INFO("Deleting Robot Model Name:%s in Gazebo\n",remove_model_name.c_str());
00106
00107 strcpy((char*)factoryIface->data->deleteEntity, remove_model_name.c_str());
00108 writing_iface = false;
00109 }
00110 factoryIface->Unlock();
00111 }
00112 }
00113
00114 void spawn_model(TiXmlDocument gazebo_model_xml)
00115 {
00116
00117 libgazebo::Client *client = new libgazebo::Client();
00118 libgazebo::FactoryIface *factoryIface = new libgazebo::FactoryIface();
00119
00120 int serverId = 0;
00121
00122 bool connected_to_server = false;
00124 while (!connected_to_server)
00125 {
00126 try
00127 {
00128 ROS_DEBUG("spawn_gazebo_model waiting for gazebo factory, usually launched by 'roslaunch `rospack find gazebo`/launch/empty_world.launch'");
00129 client->ConnectWait(serverId, GZ_CLIENT_ID_USER_FIRST);
00130 connected_to_server = true;
00131 }
00132 catch (gazebo::GazeboError e)
00133 {
00134 ROS_ERROR("Gazebo error: Unable to connect\n %s\n",e.GetErrorStr().c_str());
00135 usleep(1000000);
00136 connected_to_server = false;
00137 }
00138 }
00139
00140
00141 try
00142 {
00143 factoryIface->Open(client, "default");
00144 }
00145 catch (gazebo::GazeboError e)
00146 {
00147 ROS_ERROR("Gazebo error: Unable to connect to the factory interface\n%s\n",e.GetErrorStr().c_str());
00148 exit(2);
00149 }
00150
00151 std::ostringstream stream;
00152 stream << gazebo_model_xml;
00153 std::string gazebo_model_xml_string = stream.str();
00154 ROS_DEBUG("Gazebo Model XML\n\n%s\n\n ",gazebo_model_xml_string.c_str());
00155
00156 bool writing_iface = true;
00157 while (writing_iface)
00158 {
00159 factoryIface->Lock(1);
00160 if (strcmp((char*)factoryIface->data->newModel,"")==0)
00161 {
00162
00163 strcpy((char*)factoryIface->data->newModel, gazebo_model_xml_string.c_str());
00164 writing_iface = false;
00165 }
00166 factoryIface->Unlock();
00167 }
00168 }
00169 namespace po = boost::program_options;
00170
00171 int main(int argc, char **argv)
00172 {
00173 ros::init(argc,argv,"spawn_gazebo_model",ros::init_options::AnonymousName);
00174
00175 ROS_WARN("spawn_gazebo_model will be deprecated in the next release, please use the new gazebo_model interface instead:\n\nrosrun gazebo_tools gazebo_model -h");
00176
00177
00178 if (argc < 2)
00179 {
00180 usage(argv[0]);
00181 exit(1);
00182 }
00183
00184 double initial_x = 0;
00185 double initial_y = 0;
00186 double initial_z = 0;
00187 double initial_rx = 0;
00188 double initial_ry = 0;
00189 double initial_rz = 0;
00190
00191
00192 po::options_description v_desc("Allowed options");
00193 v_desc.add_options()
00194 ("help,h" , "produce this help message")
00195 ("model-name,m" , po::value<std::string>() , "overwrite name of the gazebo model in simulation. If not specified, the model name defaults to the name in urdf.")
00196 ("namespace,n" , po::value<std::string>() , "ROS namespace of the model spawned in simulation. If not specified, the namespace of this node is used.")
00197 ("file-in,i" , po::value<std::string>() , "read input model from file, not from the parameter server. Do not specify param_name if an input filename is provided.")
00198 ("file-out,o" , po::value<std::string>() , "write converted gazebo model xml to a file instead, model is not spawned in simulation.")
00199 ("skip-joint-limits,l" , "do not enforce joint limits during urdf-->gazebo conversion.")
00200 ("init-x,x" , po::value<double>() , "set initial x position of model.")
00201 ("init-y,y" , po::value<double>() , "set initial y position of model.")
00202 ("init-z,z" , po::value<double>() , "set initial z position of model.")
00203 ("yaw,w" , po::value<double>() , "set initial yaw (rz) of model. application orders are r-p-y.")
00204 ("pitch,p" , po::value<double>() , "set initial pitch (ry) of model. application orders are r-p-y.")
00205 ("roll,r" , po::value<double>() , "set initial roll (rx) of model. application orders are r-p-y.")
00206 ("remove,e" , po::value<std::string>() , "remove existing model in simulation (to be implemented)");
00207
00208 po::options_description h_desc("Hidden options");
00209 h_desc.add_options()
00210 ("param-name" , po::value< std::vector<std::string> >(), "ROS param name containing URDF as a string.");
00211
00212 po::options_description desc("Allowed options");
00213 desc.add(v_desc).add(h_desc);
00214
00215 po::positional_options_description p_desc;
00216 p_desc.add("param-name", -1);
00217
00218 po::variables_map vm;
00219
00220 po::store(po::command_line_parser(argc, argv).options(desc).positional(p_desc).run(), vm);
00221 po::notify(vm);
00222
00223 if (vm.count("help"))
00224 {
00225 usage(argv[0]);
00226 std::cout << v_desc << std::endl;
00227 exit(1);
00228 }
00229
00230
00231
00232 bool enforce_limits = true;
00233 if (vm.count("skip-joint-limits"))
00234 enforce_limits = false;
00235
00236
00237
00238 bool do_conversion = true;
00239
00240 std::string file_in;
00241 if (vm.count("file-in"))
00242 file_in = vm["file-in"].as<std::string>();
00243 else
00244 file_in.clear();
00245
00246 std::string file_out;
00247 if (vm.count("file-out"))
00248 {
00249 file_out = vm["file-out"].as<std::string>();
00250 }
00251
00252 std::string robot_namespace;
00253 if (vm.count("namespace"))
00254 {
00255 robot_namespace = vm["namespace"].as<std::string>();
00256 }
00257 else
00258 {
00259 robot_namespace = ros::this_node::getNamespace();
00260 ROS_DEBUG("NOTE: %s is called under namespace %s, this namespace is passed to gazebo so all Gazebo plugins (e.g.ros_time, gazebo_mechanism_control,etc.) will start up under this namespace. User can overwrite by passing in argument -namespace, for example: %s /prf/robot_description -n /prf",argv[0],argv[0],robot_namespace.c_str());
00261 }
00262 ROS_DEBUG("namespace: %s",robot_namespace.c_str());
00263
00264
00265 if (vm.count("init-x"))
00266 {
00267 initial_x = vm["init-x"].as<double>();
00268 ROS_DEBUG("x: %f",initial_x);
00269 }
00270 if (vm.count("init-y"))
00271 {
00272 initial_y = vm["init-y"].as<double>();
00273 ROS_DEBUG("y: %f",initial_y);
00274 }
00275 if (vm.count("init-z"))
00276 {
00277 initial_z = vm["init-z"].as<double>();
00278 ROS_DEBUG("z: %f",initial_z);
00279 }
00280 if (vm.count("roll"))
00281 {
00282 initial_rx = vm["roll"].as<double>();
00283 ROS_DEBUG("roll: %f",initial_rx);
00284 }
00285 if (vm.count("pitch"))
00286 {
00287 initial_ry = vm["pitch"].as<double>();
00288 ROS_DEBUG("pitch: %f",initial_ry);
00289 }
00290 if (vm.count("yaw"))
00291 {
00292 initial_rz = vm["yaw"].as<double>();
00293 ROS_DEBUG("yaw: %f",initial_rz);
00294 }
00295
00296 std::string remove_model_name;
00297 if (vm.count("remove"))
00298 {
00299 remove_model_name = vm["remove"].as<std::string>();
00300 ROS_DEBUG("remove: %s",remove_model_name.c_str());
00301 }
00302 else
00303 remove_model_name.clear();
00304
00305 std::string model_name;
00306 if (vm.count("model-name"))
00307 model_name = vm["model-name"].as<std::string>();
00308
00309 std::string param_name;
00310 if (vm.count("param-name"))
00311 {
00312 if (!file_in.empty())
00313 {
00314 ROS_ERROR("Both param-name and input file name are specified. Only one input source is allowed.\n");
00315 exit(2);
00316 }
00317
00318 std::vector<std::string> str_vec = vm["param-name"].as<std::vector<std::string> >();
00319 if (str_vec.size() > 1)
00320 {
00321 ROS_WARN("multiple urdf is deprecated!");
00322 param_name = str_vec[0];
00323 if (str_vec.size() >= 4)
00324 {
00325 initial_x = atof(str_vec[1].c_str());
00326 initial_y = atof(str_vec[2].c_str());
00327 initial_z = atof(str_vec[3].c_str());
00328 }
00329 if (str_vec.size() >= 7)
00330 {
00331 initial_rx = atof(str_vec[4].c_str());
00332 initial_ry = atof(str_vec[5].c_str());
00333 initial_rz = atof(str_vec[6].c_str());
00334 }
00335 if (str_vec.size() >= 8)
00336 model_name = str_vec[7];
00337 }
00338 else
00339 {
00340 ROS_DEBUG("parameter names are: ");
00341 for (std::vector<std::string>::iterator str = str_vec.begin(); str != str_vec.end(); str++)
00342 {
00343 ROS_DEBUG(" %s",str->c_str());
00344 param_name = *str;
00345 }
00346 }
00347 }
00348
00349
00350 std::replace(model_name.begin(),model_name.end(),'/','_');
00351 ROS_DEBUG("model name will be: %s",model_name.c_str());
00352
00353
00354 urdf::Vector3 initial_xyz(initial_x,initial_y,initial_z);
00355 urdf::Vector3 initial_rpy(initial_rx,initial_ry,initial_rz);
00356
00357 if (!remove_model_name.empty())
00358 {
00359
00360 remove_model(remove_model_name);
00361 }
00362 else
00363 {
00364
00365 std::string xml_string;
00366 if (file_in.empty())
00367 {
00368
00369 ros::NodeHandle rosnode("~");
00370 std::string full_param_name;
00371 rosnode.searchParam(param_name,full_param_name);
00372 rosnode.getParam(full_param_name.c_str(),xml_string);
00373 ROS_DEBUG("%s content\n%s\n", full_param_name.c_str(), xml_string.c_str());
00374 if (xml_string.c_str()==NULL)
00375 {
00376 ROS_ERROR("Unable to load robot model from param server robot_description\n");
00377 exit(2);
00378 }
00379 }
00380 else
00381 {
00382
00383 TiXmlDocument xml_in(file_in);
00384 xml_in.LoadFile();
00385
00386 std::ostringstream stream;
00387 stream << xml_in;
00388 xml_string = stream.str();
00389 }
00390
00391
00392 TiXmlDocument xml_doc;
00393 xml_doc.Parse(xml_string.c_str());
00394
00395
00396 TiXmlDocument gazebo_model_xml;
00397
00398
00399 if (xml_doc.FirstChild("robot"))
00400 do_conversion = true;
00401 else if (xml_doc.FirstChild("model:physical"))
00402 do_conversion = false;
00403 else
00404 {
00405 ROS_ERROR("Unable to determine input xml type: input urdf xml must begin with <robot>, input gazebo model xml must begin with <model:physical>\n");
00406 exit(2);
00407 }
00408
00409
00410 if (do_conversion)
00411 {
00412
00413 urdf2gazebo::URDF2Gazebo u2g;
00414 u2g.convert(xml_doc, gazebo_model_xml, enforce_limits, initial_xyz, initial_rpy, model_name, robot_namespace);
00415 }
00416 else
00417 {
00421 std::string open_bracket("<?");
00422 std::string close_bracket("?>");
00423 int pos1 = xml_string.find(open_bracket,0);
00424 int pos2 = xml_string.find(close_bracket,0);
00425 xml_string.replace(pos1,pos2-pos1+2,std::string(""));
00426
00427
00428 gazebo_model_xml.Parse(xml_string.c_str());
00429
00430
00431
00432
00433 TiXmlElement* model;
00434 model = gazebo_model_xml.FirstChildElement("model:physical");
00435 if (model)
00436 {
00437
00438
00439 TiXmlElement* xyz_key = model->FirstChildElement("xyz");
00440 if (xyz_key)
00441 model->RemoveChild(xyz_key);
00442 TiXmlElement* rpy_key = model->FirstChildElement("rpy");
00443 if (rpy_key)
00444 model->RemoveChild(rpy_key);
00445
00446 xyz_key = new TiXmlElement("xyz");
00447 rpy_key = new TiXmlElement("rpy");
00448
00449 std::ostringstream xyz_stream, rpy_stream;
00450 xyz_stream << initial_x << " " << initial_y << " " << initial_z;
00451 rpy_stream << initial_rx << " " << initial_ry << " " << initial_rz;
00452
00453 TiXmlText* xyz_txt = new TiXmlText(xyz_stream.str());
00454 TiXmlText* rpy_txt = new TiXmlText(rpy_stream.str());
00455
00456 xyz_key->LinkEndChild(xyz_txt);
00457 rpy_key->LinkEndChild(rpy_txt);
00458
00459 model->LinkEndChild(xyz_key);
00460 model->LinkEndChild(rpy_key);
00461
00462
00463
00464 if (!model_name.empty())
00465 {
00466
00467 model->RemoveAttribute("name");
00468 model->SetAttribute("name",model_name);
00469 }
00470 else
00471 {
00472
00473 model_name = model->Attribute("name");
00474 }
00475
00476 }
00477
00478 }
00479
00480 if (file_out.empty())
00481 {
00482
00483 spawn_model(gazebo_model_xml);
00484 }
00485 else
00486 {
00487
00488 if (!gazebo_model_xml.SaveFile(file_out))
00489 {
00490 printf("Unable to save gazebo model in %s\n", file_out.c_str());
00491 exit(3);
00492 }
00493
00494 }
00495 }
00496
00497 return 0;
00498 }
00499