00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <gazebo/common/Events.hh>
00024 #include <gazebo/gazebo_config.h>
00025 #include <gazebo_ros/gazebo_ros_api_plugin.h>
00026
00027 namespace gazebo
00028 {
00029
00030 GazeboRosApiPlugin::GazeboRosApiPlugin() :
00031 physics_reconfigure_initialized_(false),
00032 world_created_(false),
00033 stop_(false),
00034 plugin_loaded_(false),
00035 pub_link_states_connection_count_(0),
00036 pub_model_states_connection_count_(0)
00037 {
00038 robot_namespace_.clear();
00039 }
00040
00041 GazeboRosApiPlugin::~GazeboRosApiPlugin()
00042 {
00043 ROS_DEBUG_STREAM_NAMED("api_plugin","GazeboRosApiPlugin Deconstructor start");
00044
00045
00046 gazebo::event::Events::DisconnectSigInt(sigint_event_);
00047 ROS_DEBUG_STREAM_NAMED("api_plugin","After sigint_event unload");
00048
00049
00050 if(!plugin_loaded_)
00051 {
00052 ROS_DEBUG_STREAM_NAMED("api_plugin","Deconstructor skipped because never loaded");
00053 return;
00054 }
00055
00056
00057 gazebo::event::Events::DisconnectWorldCreated(load_gazebo_ros_api_plugin_event_);
00058 gazebo::event::Events::DisconnectWorldUpdateBegin(wrench_update_event_);
00059 gazebo::event::Events::DisconnectWorldUpdateBegin(force_update_event_);
00060 gazebo::event::Events::DisconnectWorldUpdateBegin(time_update_event_);
00061 ROS_DEBUG_STREAM_NAMED("api_plugin","Slots disconnected");
00062
00063 if (pub_link_states_connection_count_ > 0)
00064 gazebo::event::Events::DisconnectWorldUpdateBegin(pub_link_states_event_);
00065 if (pub_model_states_connection_count_ > 0)
00066 gazebo::event::Events::DisconnectWorldUpdateBegin(pub_model_states_event_);
00067 ROS_DEBUG_STREAM_NAMED("api_plugin","Disconnected World Updates");
00068
00069
00070 async_ros_spin_->stop();
00071 ROS_DEBUG_STREAM_NAMED("api_plugin","Async ROS Spin Stopped");
00072
00073
00074 nh_->shutdown();
00075 ROS_DEBUG_STREAM_NAMED("api_plugin","Node Handle Shutdown");
00076
00077
00078 gazebo_callback_queue_thread_->join();
00079 ROS_DEBUG_STREAM_NAMED("api_plugin","Callback Queue Joined");
00080
00081
00082 physics_reconfigure_thread_->join();
00083 ROS_DEBUG_STREAM_NAMED("api_plugin","Physics reconfigure joined");
00084
00085
00086 lock_.lock();
00087 for (std::vector<GazeboRosApiPlugin::ForceJointJob*>::iterator iter=force_joint_jobs_.begin();iter!=force_joint_jobs_.end();)
00088 {
00089 delete (*iter);
00090 iter = force_joint_jobs_.erase(iter);
00091 }
00092 force_joint_jobs_.clear();
00093 ROS_DEBUG_STREAM_NAMED("api_plugin","ForceJointJobs deleted");
00094 for (std::vector<GazeboRosApiPlugin::WrenchBodyJob*>::iterator iter=wrench_body_jobs_.begin();iter!=wrench_body_jobs_.end();)
00095 {
00096 delete (*iter);
00097 iter = wrench_body_jobs_.erase(iter);
00098 }
00099 wrench_body_jobs_.clear();
00100 lock_.unlock();
00101 ROS_DEBUG_STREAM_NAMED("api_plugin","WrenchBodyJobs deleted");
00102
00103 ROS_DEBUG_STREAM_NAMED("api_plugin","Unloaded");
00104 }
00105
00106 void GazeboRosApiPlugin::shutdownSignal()
00107 {
00108 ROS_DEBUG_STREAM_NAMED("api_plugin","shutdownSignal() recieved");
00109 stop_ = true;
00110 }
00111
00112 void GazeboRosApiPlugin::Load(int argc, char** argv)
00113 {
00114 ROS_DEBUG_STREAM_NAMED("api_plugin","Load");
00115
00116
00117 sigint_event_ = gazebo::event::Events::ConnectSigInt(boost::bind(&GazeboRosApiPlugin::shutdownSignal,this));
00118
00119
00120 if (!ros::isInitialized())
00121 ros::init(argc,argv,"gazebo",ros::init_options::NoSigintHandler);
00122 else
00123 ROS_ERROR("Something other than this gazebo_ros_api plugin started ros::init(...), command line arguments may not be parsed properly.");
00124
00125
00126 while(!ros::master::check())
00127 {
00128 ROS_WARN_STREAM_NAMED("api_plugin","No ROS master - start roscore to continue...");
00129
00130 usleep(500*1000);
00131
00132 if(stop_)
00133 {
00134 ROS_WARN_STREAM_NAMED("api_plugin","Canceled loading Gazebo ROS API plugin by sigint event");
00135 return;
00136 }
00137 }
00138
00139 nh_.reset(new ros::NodeHandle("~"));
00140
00141
00142 async_ros_spin_.reset(new ros::AsyncSpinner(0));
00143 async_ros_spin_->start();
00144
00146 gazebo_callback_queue_thread_.reset(new boost::thread( &GazeboRosApiPlugin::gazeboQueueThread, this) );
00147
00149 physics_reconfigure_thread_.reset(new boost::thread(boost::bind(&GazeboRosApiPlugin::physicsReconfigureThread, this)));
00150
00151
00152 load_gazebo_ros_api_plugin_event_ = gazebo::event::Events::ConnectWorldCreated(boost::bind(&GazeboRosApiPlugin::loadGazeboRosApiPlugin,this,_1));
00153
00154 plugin_loaded_ = true;
00155 ROS_INFO("Finished loading Gazebo ROS API Plugin.");
00156 }
00157
00158 void GazeboRosApiPlugin::loadGazeboRosApiPlugin(std::string world_name)
00159 {
00160
00161 lock_.lock();
00162 if (world_created_)
00163 {
00164 lock_.unlock();
00165 return;
00166 }
00167
00168
00169 world_created_ = true;
00170 lock_.unlock();
00171
00172 world_ = gazebo::physics::get_world(world_name);
00173 if (!world_)
00174 {
00175
00176
00177 ROS_FATAL("cannot load gazebo ros api server plugin, physics::get_world() fails to return world");
00178 return;
00179 }
00180
00181 gazebonode_ = gazebo::transport::NodePtr(new gazebo::transport::Node());
00182 gazebonode_->Init(world_name);
00183
00184 factory_pub_ = gazebonode_->Advertise<gazebo::msgs::Factory>("~/factory");
00185 request_pub_ = gazebonode_->Advertise<gazebo::msgs::Request>("~/request");
00186 response_sub_ = gazebonode_->Subscribe("~/response",&GazeboRosApiPlugin::onResponse, this);
00187
00188
00189 pub_link_states_connection_count_ = 0;
00190 pub_model_states_connection_count_ = 0;
00191
00193 advertiseServices();
00194
00195
00196 wrench_update_event_ = gazebo::event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboRosApiPlugin::wrenchBodySchedulerSlot,this));
00197 force_update_event_ = gazebo::event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboRosApiPlugin::forceJointSchedulerSlot,this));
00198 time_update_event_ = gazebo::event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboRosApiPlugin::publishSimTime,this));
00199 }
00200
00201 void GazeboRosApiPlugin::onResponse(ConstResponsePtr &response)
00202 {
00203
00204 }
00205
00206 void GazeboRosApiPlugin::gazeboQueueThread()
00207 {
00208 static const double timeout = 0.001;
00209 while (nh_->ok())
00210 {
00211 gazebo_queue_.callAvailable(ros::WallDuration(timeout));
00212 }
00213 }
00214
00215 void GazeboRosApiPlugin::advertiseServices()
00216 {
00217
00218 pub_clock_ = nh_->advertise<rosgraph_msgs::Clock>("/clock",10);
00219
00220
00221 std::string spawn_gazebo_model_service_name("spawn_gazebo_model");
00222 ros::AdvertiseServiceOptions spawn_gazebo_model_aso =
00223 ros::AdvertiseServiceOptions::create<gazebo_msgs::SpawnModel>(
00224 spawn_gazebo_model_service_name,
00225 boost::bind(&GazeboRosApiPlugin::spawnGazeboModel,this,_1,_2),
00226 ros::VoidPtr(), &gazebo_queue_);
00227 spawn_gazebo_model_service_ = nh_->advertiseService(spawn_gazebo_model_aso);
00228
00229
00230 std::string spawn_sdf_model_service_name("spawn_sdf_model");
00231 ros::AdvertiseServiceOptions spawn_sdf_model_aso =
00232 ros::AdvertiseServiceOptions::create<gazebo_msgs::SpawnModel>(
00233 spawn_sdf_model_service_name,
00234 boost::bind(&GazeboRosApiPlugin::spawnSDFModel,this,_1,_2),
00235 ros::VoidPtr(), &gazebo_queue_);
00236 spawn_sdf_model_service_ = nh_->advertiseService(spawn_sdf_model_aso);
00237
00238
00239 std::string spawn_urdf_model_service_name("spawn_urdf_model");
00240 ros::AdvertiseServiceOptions spawn_urdf_model_aso =
00241 ros::AdvertiseServiceOptions::create<gazebo_msgs::SpawnModel>(
00242 spawn_urdf_model_service_name,
00243 boost::bind(&GazeboRosApiPlugin::spawnURDFModel,this,_1,_2),
00244 ros::VoidPtr(), &gazebo_queue_);
00245 spawn_urdf_model_service_ = nh_->advertiseService(spawn_urdf_model_aso);
00246
00247
00248 std::string delete_model_service_name("delete_model");
00249 ros::AdvertiseServiceOptions delete_aso =
00250 ros::AdvertiseServiceOptions::create<gazebo_msgs::DeleteModel>(
00251 delete_model_service_name,
00252 boost::bind(&GazeboRosApiPlugin::deleteModel,this,_1,_2),
00253 ros::VoidPtr(), &gazebo_queue_);
00254 delete_model_service_ = nh_->advertiseService(delete_aso);
00255
00256
00257 std::string get_model_properties_service_name("get_model_properties");
00258 ros::AdvertiseServiceOptions get_model_properties_aso =
00259 ros::AdvertiseServiceOptions::create<gazebo_msgs::GetModelProperties>(
00260 get_model_properties_service_name,
00261 boost::bind(&GazeboRosApiPlugin::getModelProperties,this,_1,_2),
00262 ros::VoidPtr(), &gazebo_queue_);
00263 get_model_properties_service_ = nh_->advertiseService(get_model_properties_aso);
00264
00265
00266 std::string get_model_state_service_name("get_model_state");
00267 ros::AdvertiseServiceOptions get_model_state_aso =
00268 ros::AdvertiseServiceOptions::create<gazebo_msgs::GetModelState>(
00269 get_model_state_service_name,
00270 boost::bind(&GazeboRosApiPlugin::getModelState,this,_1,_2),
00271 ros::VoidPtr(), &gazebo_queue_);
00272 get_model_state_service_ = nh_->advertiseService(get_model_state_aso);
00273
00274
00275 std::string get_world_properties_service_name("get_world_properties");
00276 ros::AdvertiseServiceOptions get_world_properties_aso =
00277 ros::AdvertiseServiceOptions::create<gazebo_msgs::GetWorldProperties>(
00278 get_world_properties_service_name,
00279 boost::bind(&GazeboRosApiPlugin::getWorldProperties,this,_1,_2),
00280 ros::VoidPtr(), &gazebo_queue_);
00281 get_world_properties_service_ = nh_->advertiseService(get_world_properties_aso);
00282
00283
00284 std::string get_joint_properties_service_name("get_joint_properties");
00285 ros::AdvertiseServiceOptions get_joint_properties_aso =
00286 ros::AdvertiseServiceOptions::create<gazebo_msgs::GetJointProperties>(
00287 get_joint_properties_service_name,
00288 boost::bind(&GazeboRosApiPlugin::getJointProperties,this,_1,_2),
00289 ros::VoidPtr(), &gazebo_queue_);
00290 get_joint_properties_service_ = nh_->advertiseService(get_joint_properties_aso);
00291
00292
00293 std::string get_link_properties_service_name("get_link_properties");
00294 ros::AdvertiseServiceOptions get_link_properties_aso =
00295 ros::AdvertiseServiceOptions::create<gazebo_msgs::GetLinkProperties>(
00296 get_link_properties_service_name,
00297 boost::bind(&GazeboRosApiPlugin::getLinkProperties,this,_1,_2),
00298 ros::VoidPtr(), &gazebo_queue_);
00299 get_link_properties_service_ = nh_->advertiseService(get_link_properties_aso);
00300
00301
00302 std::string get_link_state_service_name("get_link_state");
00303 ros::AdvertiseServiceOptions get_link_state_aso =
00304 ros::AdvertiseServiceOptions::create<gazebo_msgs::GetLinkState>(
00305 get_link_state_service_name,
00306 boost::bind(&GazeboRosApiPlugin::getLinkState,this,_1,_2),
00307 ros::VoidPtr(), &gazebo_queue_);
00308 get_link_state_service_ = nh_->advertiseService(get_link_state_aso);
00309
00310
00311 std::string get_physics_properties_service_name("get_physics_properties");
00312 ros::AdvertiseServiceOptions get_physics_properties_aso =
00313 ros::AdvertiseServiceOptions::create<gazebo_msgs::GetPhysicsProperties>(
00314 get_physics_properties_service_name,
00315 boost::bind(&GazeboRosApiPlugin::getPhysicsProperties,this,_1,_2),
00316 ros::VoidPtr(), &gazebo_queue_);
00317 get_physics_properties_service_ = nh_->advertiseService(get_physics_properties_aso);
00318
00319
00320 ros::AdvertiseOptions pub_link_states_ao =
00321 ros::AdvertiseOptions::create<gazebo_msgs::LinkStates>(
00322 "link_states",10,
00323 boost::bind(&GazeboRosApiPlugin::onLinkStatesConnect,this),
00324 boost::bind(&GazeboRosApiPlugin::onLinkStatesDisconnect,this),
00325 ros::VoidPtr(), &gazebo_queue_);
00326 pub_link_states_ = nh_->advertise(pub_link_states_ao);
00327
00328
00329 ros::AdvertiseOptions pub_model_states_ao =
00330 ros::AdvertiseOptions::create<gazebo_msgs::ModelStates>(
00331 "model_states",10,
00332 boost::bind(&GazeboRosApiPlugin::onModelStatesConnect,this),
00333 boost::bind(&GazeboRosApiPlugin::onModelStatesDisconnect,this),
00334 ros::VoidPtr(), &gazebo_queue_);
00335 pub_model_states_ = nh_->advertise(pub_model_states_ao);
00336
00337
00338 std::string set_link_properties_service_name("set_link_properties");
00339 ros::AdvertiseServiceOptions set_link_properties_aso =
00340 ros::AdvertiseServiceOptions::create<gazebo_msgs::SetLinkProperties>(
00341 set_link_properties_service_name,
00342 boost::bind(&GazeboRosApiPlugin::setLinkProperties,this,_1,_2),
00343 ros::VoidPtr(), &gazebo_queue_);
00344 set_link_properties_service_ = nh_->advertiseService(set_link_properties_aso);
00345
00346
00347 std::string set_physics_properties_service_name("set_physics_properties");
00348 ros::AdvertiseServiceOptions set_physics_properties_aso =
00349 ros::AdvertiseServiceOptions::create<gazebo_msgs::SetPhysicsProperties>(
00350 set_physics_properties_service_name,
00351 boost::bind(&GazeboRosApiPlugin::setPhysicsProperties,this,_1,_2),
00352 ros::VoidPtr(), &gazebo_queue_);
00353 set_physics_properties_service_ = nh_->advertiseService(set_physics_properties_aso);
00354
00355
00356 std::string set_model_state_service_name("set_model_state");
00357 ros::AdvertiseServiceOptions set_model_state_aso =
00358 ros::AdvertiseServiceOptions::create<gazebo_msgs::SetModelState>(
00359 set_model_state_service_name,
00360 boost::bind(&GazeboRosApiPlugin::setModelState,this,_1,_2),
00361 ros::VoidPtr(), &gazebo_queue_);
00362 set_model_state_service_ = nh_->advertiseService(set_model_state_aso);
00363
00364
00365 std::string set_model_configuration_service_name("set_model_configuration");
00366 ros::AdvertiseServiceOptions set_model_configuration_aso =
00367 ros::AdvertiseServiceOptions::create<gazebo_msgs::SetModelConfiguration>(
00368 set_model_configuration_service_name,
00369 boost::bind(&GazeboRosApiPlugin::setModelConfiguration,this,_1,_2),
00370 ros::VoidPtr(), &gazebo_queue_);
00371 set_model_configuration_service_ = nh_->advertiseService(set_model_configuration_aso);
00372
00373
00374 std::string set_joint_properties_service_name("set_joint_properties");
00375 ros::AdvertiseServiceOptions set_joint_properties_aso =
00376 ros::AdvertiseServiceOptions::create<gazebo_msgs::SetJointProperties>(
00377 set_joint_properties_service_name,
00378 boost::bind(&GazeboRosApiPlugin::setJointProperties,this,_1,_2),
00379 ros::VoidPtr(), &gazebo_queue_);
00380 set_joint_properties_service_ = nh_->advertiseService(set_joint_properties_aso);
00381
00382
00383 std::string set_link_state_service_name("set_link_state");
00384 ros::AdvertiseServiceOptions set_link_state_aso =
00385 ros::AdvertiseServiceOptions::create<gazebo_msgs::SetLinkState>(
00386 set_link_state_service_name,
00387 boost::bind(&GazeboRosApiPlugin::setLinkState,this,_1,_2),
00388 ros::VoidPtr(), &gazebo_queue_);
00389 set_link_state_service_ = nh_->advertiseService(set_link_state_aso);
00390
00391
00392
00393 ros::SubscribeOptions link_state_so =
00394 ros::SubscribeOptions::create<gazebo_msgs::LinkState>(
00395 "set_link_state",10,
00396 boost::bind( &GazeboRosApiPlugin::updateLinkState,this,_1),
00397 ros::VoidPtr(), &gazebo_queue_);
00398 set_link_state_topic_ = nh_->subscribe(link_state_so);
00399
00400
00401 ros::SubscribeOptions model_state_so =
00402 ros::SubscribeOptions::create<gazebo_msgs::ModelState>(
00403 "set_model_state",10,
00404 boost::bind( &GazeboRosApiPlugin::updateModelState,this,_1),
00405 ros::VoidPtr(), &gazebo_queue_);
00406 set_model_state_topic_ = nh_->subscribe(model_state_so);
00407
00408
00409 std::string pause_physics_service_name("pause_physics");
00410 ros::AdvertiseServiceOptions pause_physics_aso =
00411 ros::AdvertiseServiceOptions::create<std_srvs::Empty>(
00412 pause_physics_service_name,
00413 boost::bind(&GazeboRosApiPlugin::pausePhysics,this,_1,_2),
00414 ros::VoidPtr(), &gazebo_queue_);
00415 pause_physics_service_ = nh_->advertiseService(pause_physics_aso);
00416
00417
00418 std::string unpause_physics_service_name("unpause_physics");
00419 ros::AdvertiseServiceOptions unpause_physics_aso =
00420 ros::AdvertiseServiceOptions::create<std_srvs::Empty>(
00421 unpause_physics_service_name,
00422 boost::bind(&GazeboRosApiPlugin::unpausePhysics,this,_1,_2),
00423 ros::VoidPtr(), &gazebo_queue_);
00424 unpause_physics_service_ = nh_->advertiseService(unpause_physics_aso);
00425
00426
00427 std::string apply_body_wrench_service_name("apply_body_wrench");
00428 ros::AdvertiseServiceOptions apply_body_wrench_aso =
00429 ros::AdvertiseServiceOptions::create<gazebo_msgs::ApplyBodyWrench>(
00430 apply_body_wrench_service_name,
00431 boost::bind(&GazeboRosApiPlugin::applyBodyWrench,this,_1,_2),
00432 ros::VoidPtr(), &gazebo_queue_);
00433 apply_body_wrench_service_ = nh_->advertiseService(apply_body_wrench_aso);
00434
00435
00436 std::string apply_joint_effort_service_name("apply_joint_effort");
00437 ros::AdvertiseServiceOptions apply_joint_effort_aso =
00438 ros::AdvertiseServiceOptions::create<gazebo_msgs::ApplyJointEffort>(
00439 apply_joint_effort_service_name,
00440 boost::bind(&GazeboRosApiPlugin::applyJointEffort,this,_1,_2),
00441 ros::VoidPtr(), &gazebo_queue_);
00442 apply_joint_effort_service_ = nh_->advertiseService(apply_joint_effort_aso);
00443
00444
00445 std::string clear_joint_forces_service_name("clear_joint_forces");
00446 ros::AdvertiseServiceOptions clear_joint_forces_aso =
00447 ros::AdvertiseServiceOptions::create<gazebo_msgs::JointRequest>(
00448 clear_joint_forces_service_name,
00449 boost::bind(&GazeboRosApiPlugin::clearJointForces,this,_1,_2),
00450 ros::VoidPtr(), &gazebo_queue_);
00451 clear_joint_forces_service_ = nh_->advertiseService(clear_joint_forces_aso);
00452
00453
00454 std::string clear_body_wrenches_service_name("clear_body_wrenches");
00455 ros::AdvertiseServiceOptions clear_body_wrenches_aso =
00456 ros::AdvertiseServiceOptions::create<gazebo_msgs::BodyRequest>(
00457 clear_body_wrenches_service_name,
00458 boost::bind(&GazeboRosApiPlugin::clearBodyWrenches,this,_1,_2),
00459 ros::VoidPtr(), &gazebo_queue_);
00460 clear_body_wrenches_service_ = nh_->advertiseService(clear_body_wrenches_aso);
00461
00462
00463 std::string reset_simulation_service_name("reset_simulation");
00464 ros::AdvertiseServiceOptions reset_simulation_aso =
00465 ros::AdvertiseServiceOptions::create<std_srvs::Empty>(
00466 reset_simulation_service_name,
00467 boost::bind(&GazeboRosApiPlugin::resetSimulation,this,_1,_2),
00468 ros::VoidPtr(), &gazebo_queue_);
00469 reset_simulation_service_ = nh_->advertiseService(reset_simulation_aso);
00470
00471
00472 std::string reset_world_service_name("reset_world");
00473 ros::AdvertiseServiceOptions reset_world_aso =
00474 ros::AdvertiseServiceOptions::create<std_srvs::Empty>(
00475 reset_world_service_name,
00476 boost::bind(&GazeboRosApiPlugin::resetWorld,this,_1,_2),
00477 ros::VoidPtr(), &gazebo_queue_);
00478 reset_world_service_ = nh_->advertiseService(reset_world_aso);
00479
00480
00481
00482 nh_->setParam("/use_sim_time", true);
00483
00484
00485
00486 }
00487
00488 void GazeboRosApiPlugin::onLinkStatesConnect()
00489 {
00490 pub_link_states_connection_count_++;
00491 if (pub_link_states_connection_count_ == 1)
00492 pub_link_states_event_ = gazebo::event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboRosApiPlugin::publishLinkStates,this));
00493 }
00494
00495 void GazeboRosApiPlugin::onModelStatesConnect()
00496 {
00497 pub_model_states_connection_count_++;
00498 if (pub_model_states_connection_count_ == 1)
00499 pub_model_states_event_ = gazebo::event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboRosApiPlugin::publishModelStates,this));
00500 }
00501
00502 void GazeboRosApiPlugin::onLinkStatesDisconnect()
00503 {
00504 pub_link_states_connection_count_--;
00505 if (pub_link_states_connection_count_ <= 0)
00506 {
00507 gazebo::event::Events::DisconnectWorldUpdateBegin(pub_link_states_event_);
00508 if (pub_link_states_connection_count_ < 0)
00509 ROS_ERROR("one too mandy disconnect from pub_link_states_ in gazebo_ros.cpp? something weird");
00510 }
00511 }
00512
00513 void GazeboRosApiPlugin::onModelStatesDisconnect()
00514 {
00515 pub_model_states_connection_count_--;
00516 if (pub_model_states_connection_count_ <= 0)
00517 {
00518 gazebo::event::Events::DisconnectWorldUpdateBegin(pub_model_states_event_);
00519 if (pub_model_states_connection_count_ < 0)
00520 ROS_ERROR("one too mandy disconnect from pub_model_states_ in gazebo_ros.cpp? something weird");
00521 }
00522 }
00523
00524 bool GazeboRosApiPlugin::spawnURDFModel(gazebo_msgs::SpawnModel::Request &req,
00525 gazebo_msgs::SpawnModel::Response &res)
00526 {
00527
00528 robot_namespace_ = req.robot_namespace;
00529
00530
00531 std::string model_xml = req.model_xml;
00532
00533 if (!isURDF(model_xml))
00534 {
00535 ROS_ERROR("SpawnModel: Failure - model format is not URDF.");
00536 res.success = false;
00537 res.status_message = "SpawnModel: Failure - model format is not URDF.";
00538 return false;
00539 }
00540
00544 {
00545 std::string open_bracket("<?");
00546 std::string close_bracket("?>");
00547 size_t pos1 = model_xml.find(open_bracket,0);
00548 size_t pos2 = model_xml.find(close_bracket,0);
00549 if (pos1 != std::string::npos && pos2 != std::string::npos)
00550 model_xml.replace(pos1,pos2-pos1+2,std::string(""));
00551 }
00552
00553
00554 {
00555 std::string package_prefix("package://");
00556 size_t pos1 = model_xml.find(package_prefix,0);
00557 while (pos1 != std::string::npos)
00558 {
00559 size_t pos2 = model_xml.find("/", pos1+10);
00560
00561 if (pos2 == std::string::npos || pos1 >= pos2)
00562 {
00563 ROS_ERROR("malformed package name?");
00564 break;
00565 }
00566
00567 std::string package_name = model_xml.substr(pos1+10,pos2-pos1-10);
00568
00569 std::string package_path = ros::package::getPath(package_name);
00570 if (package_path.empty())
00571 {
00572 ROS_FATAL("Package[%s] does not have a path",package_name.c_str());
00573 res.success = false;
00574 res.status_message = std::string("urdf reference package name does not exist: ")+package_name;
00575 return false;
00576 }
00577 ROS_DEBUG_ONCE("Package name [%s] has path [%s]", package_name.c_str(), package_path.c_str());
00578
00579 model_xml.replace(pos1,(pos2-pos1),package_path);
00580 pos1 = model_xml.find(package_prefix, pos1);
00581 }
00582 }
00583
00584
00585 req.model_xml = model_xml;
00586
00587
00588 return spawnSDFModel(req,res);
00589 }
00590
00591
00592 bool GazeboRosApiPlugin::spawnGazeboModel(gazebo_msgs::SpawnModel::Request &req,
00593 gazebo_msgs::SpawnModel::Response &res)
00594 {
00595 ROS_WARN_STREAM_NAMED("api_plugin","/gazebo/spawn_gazebo_model is deprecated, use /gazebo/spawn_sdf_model instead");
00596 spawnSDFModel(req, res);
00597 }
00598
00599 bool GazeboRosApiPlugin::spawnSDFModel(gazebo_msgs::SpawnModel::Request &req,
00600 gazebo_msgs::SpawnModel::Response &res)
00601 {
00602
00603 std::string model_name = req.model_name;
00604
00605
00606 robot_namespace_ = req.robot_namespace;
00607
00608
00609 gazebo::math::Vector3 initial_xyz(req.initial_pose.position.x,req.initial_pose.position.y,req.initial_pose.position.z);
00610
00611 gazebo::math::Quaternion initial_q(req.initial_pose.orientation.w,req.initial_pose.orientation.x,req.initial_pose.orientation.y,req.initial_pose.orientation.z);
00612
00613
00614 gazebo::physics::LinkPtr frame = boost::dynamic_pointer_cast<gazebo::physics::Link>(world_->GetEntity(req.reference_frame));
00615 if (frame)
00616 {
00617
00618 gazebo::math::Pose frame_pose = frame->GetWorldPose();
00619 initial_xyz = frame_pose.rot.RotateVector(initial_xyz);
00620 initial_xyz += frame_pose.pos;
00621 initial_q *= frame_pose.rot;
00622 }
00623
00625 else if (req.reference_frame == "" || req.reference_frame == "world" || req.reference_frame == "map" || req.reference_frame == "/map")
00626 {
00627 ROS_DEBUG("SpawnModel: reference_frame is empty/world/map, using inertial frame");
00628 }
00629 else
00630 {
00631 res.success = false;
00632 res.status_message = "SpawnModel: reference reference_frame not found, did you forget to scope the link by model name?";
00633 return true;
00634 }
00635
00636
00637 std::string model_xml = req.model_xml;
00638
00639
00640
00641
00642 stripXmlDeclaration(model_xml);
00643
00644
00645 TiXmlDocument gazebo_model_xml;
00646 gazebo_model_xml.Parse(model_xml.c_str());
00647
00648
00649 if (isSDF(model_xml))
00650 {
00651 updateSDFAttributes(gazebo_model_xml, model_name, initial_xyz, initial_q);
00652
00653
00654
00655 if (!this->robot_namespace_.empty())
00656 {
00657
00658 TiXmlNode* model_tixml = gazebo_model_xml.FirstChild("sdf");
00659 model_tixml = (!model_tixml) ?
00660 gazebo_model_xml.FirstChild("gazebo") : model_tixml;
00661 if (model_tixml)
00662 {
00663 walkChildAddRobotNamespace(model_tixml);
00664 }
00665 else
00666 {
00667 ROS_WARN("Unable to add robot namespace to xml");
00668 }
00669 }
00670 }
00671 else if (isURDF(model_xml))
00672 {
00673 updateURDFModelPose(gazebo_model_xml, initial_xyz, initial_q);
00674 updateURDFName(gazebo_model_xml, model_name);
00675
00676
00677
00678 if (!this->robot_namespace_.empty())
00679 {
00680
00681 TiXmlNode* model_tixml = gazebo_model_xml.FirstChild("robot");
00682 if (model_tixml)
00683 {
00684 walkChildAddRobotNamespace(model_tixml);
00685 }
00686 else
00687 {
00688 ROS_WARN("Unable to add robot namespace to xml");
00689 }
00690 }
00691 }
00692 else
00693 {
00694 ROS_ERROR("GazeboRosApiPlugin SpawnModel Failure: input xml format not recognized");
00695 res.success = false;
00696 res.status_message = std::string("GazeboRosApiPlugin SpawnModel Failure: input model_xml not SDF or URDF, or cannot be converted to Gazebo compatible format.");
00697 return true;
00698 }
00699
00700
00701 return spawnAndConform(gazebo_model_xml, model_name, res);
00702 }
00703
00704 bool GazeboRosApiPlugin::deleteModel(gazebo_msgs::DeleteModel::Request &req,
00705 gazebo_msgs::DeleteModel::Response &res)
00706 {
00707
00708 gazebo::physics::ModelPtr model = world_->GetModel(req.model_name);
00709 if (!model)
00710 {
00711 ROS_ERROR("DeleteModel: model [%s] does not exist",req.model_name.c_str());
00712 res.success = false;
00713 res.status_message = "DeleteModel: model does not exist";
00714 return true;
00715 }
00716
00717
00718 for (unsigned int i = 0 ; i < model->GetChildCount(); i ++)
00719 {
00720 gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(model->GetChild(i));
00721 if (body)
00722 {
00723
00724 clearBodyWrenches(body->GetScopedName());
00725 }
00726 }
00727
00728
00729 gazebo::physics::Joint_V joints = model->GetJoints();
00730 for (unsigned int i=0;i< joints.size(); i++)
00731 {
00732
00733 clearJointForces(joints[i]->GetName());
00734 }
00735
00736
00737 gazebo::msgs::Request *msg = gazebo::msgs::CreateRequest("entity_delete",req.model_name);
00738 request_pub_->Publish(*msg,true);
00739
00740 ros::Duration model_spawn_timeout(60.0);
00741 ros::Time timeout = ros::Time::now() + model_spawn_timeout;
00742
00743 while (true)
00744 {
00745 if (ros::Time::now() > timeout)
00746 {
00747 res.success = false;
00748 res.status_message = std::string("DeleteModel: Model pushed to delete queue, but delete service timed out waiting for model to disappear from simulation");
00749 return true;
00750 }
00751 {
00752
00753 if (!world_->GetModel(req.model_name)) break;
00754 }
00755 ROS_DEBUG("Waiting for model deletion (%s)",req.model_name.c_str());
00756 usleep(1000);
00757 }
00758
00759
00760 res.success = true;
00761 res.status_message = std::string("DeleteModel: successfully deleted model");
00762 return true;
00763 }
00764
00765 bool GazeboRosApiPlugin::getModelState(gazebo_msgs::GetModelState::Request &req,
00766 gazebo_msgs::GetModelState::Response &res)
00767 {
00768 gazebo::physics::ModelPtr model = world_->GetModel(req.model_name);
00769 gazebo::physics::LinkPtr frame = boost::dynamic_pointer_cast<gazebo::physics::Link>(world_->GetEntity(req.relative_entity_name));
00770 if (!model)
00771 {
00772 ROS_ERROR("GetModelState: model [%s] does not exist",req.model_name.c_str());
00773 res.success = false;
00774 res.status_message = "GetModelState: model does not exist";
00775 return true;
00776 }
00777 else
00778 {
00779
00780 gazebo::math::Pose model_pose = model->GetWorldPose();
00781 gazebo::math::Vector3 model_pos = model_pose.pos;
00782 gazebo::math::Quaternion model_rot = model_pose.rot;
00783
00784
00785 gazebo::math::Vector3 model_linear_vel = model->GetWorldLinearVel();
00786 gazebo::math::Vector3 model_angular_vel = model->GetWorldAngularVel();
00787
00788
00789 if (frame)
00790 {
00791
00792 gazebo::math::Pose frame_pose = frame->GetWorldPose();
00793 model_pos = model_pos - frame_pose.pos;
00794 model_pos = frame_pose.rot.RotateVectorReverse(model_pos);
00795 model_rot *= frame_pose.rot.GetInverse();
00796
00797
00798 gazebo::math::Vector3 frame_vpos = frame->GetWorldLinearVel();
00799 gazebo::math::Vector3 frame_veul = frame->GetWorldAngularVel();
00800 model_linear_vel = frame_pose.rot.RotateVector(model_linear_vel - frame_vpos);
00801 model_angular_vel = frame_pose.rot.RotateVector(model_angular_vel - frame_veul);
00802 }
00804 else if (req.relative_entity_name == "" || req.relative_entity_name == "world" || req.relative_entity_name == "map" || req.relative_entity_name == "/map")
00805 {
00806 ROS_DEBUG("GetModelState: relative_entity_name is empty/world/map, using inertial frame");
00807 }
00808 else
00809 {
00810 res.success = false;
00811 res.status_message = "GetModelState: reference relative_entity_name not found, did you forget to scope the body by model name?";
00812 return true;
00813 }
00814
00815
00816 res.pose.position.x = model_pos.x;
00817 res.pose.position.y = model_pos.y;
00818 res.pose.position.z = model_pos.z;
00819 res.pose.orientation.w = model_rot.w;
00820 res.pose.orientation.x = model_rot.x;
00821 res.pose.orientation.y = model_rot.y;
00822 res.pose.orientation.z = model_rot.z;
00823
00824 res.twist.linear.x = model_linear_vel.x;
00825 res.twist.linear.y = model_linear_vel.y;
00826 res.twist.linear.z = model_linear_vel.z;
00827 res.twist.angular.x = model_angular_vel.x;
00828 res.twist.angular.y = model_angular_vel.y;
00829 res.twist.angular.z = model_angular_vel.z;
00830
00831 res.success = true;
00832 res.status_message = "GetModelState: got properties";
00833 return true;
00834 }
00835 return true;
00836 }
00837
00838 bool GazeboRosApiPlugin::getModelProperties(gazebo_msgs::GetModelProperties::Request &req,
00839 gazebo_msgs::GetModelProperties::Response &res)
00840 {
00841 gazebo::physics::ModelPtr model = world_->GetModel(req.model_name);
00842 if (!model)
00843 {
00844 ROS_ERROR("GetModelProperties: model [%s] does not exist",req.model_name.c_str());
00845 res.success = false;
00846 res.status_message = "GetModelProperties: model does not exist";
00847 return true;
00848 }
00849 else
00850 {
00851
00852 gazebo::physics::ModelPtr parent_model = boost::dynamic_pointer_cast<gazebo::physics::Model>(model->GetParent());
00853 if (parent_model) res.parent_model_name = parent_model->GetName();
00854
00855
00856 res.body_names.clear();
00857 res.geom_names.clear();
00858 for (unsigned int i = 0 ; i < model->GetChildCount(); i ++)
00859 {
00860 gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(model->GetChild(i));
00861 if (body)
00862 {
00863 res.body_names.push_back(body->GetName());
00864
00865 for (unsigned int j = 0; j < body->GetChildCount() ; j++)
00866 {
00867 gazebo::physics::CollisionPtr geom = boost::dynamic_pointer_cast<gazebo::physics::Collision>(body->GetChild(j));
00868 if (geom)
00869 res.geom_names.push_back(geom->GetName());
00870 }
00871 }
00872 }
00873
00874
00875 res.joint_names.clear();
00876
00877 gazebo::physics::Joint_V joints = model->GetJoints();
00878 for (unsigned int i=0;i< joints.size(); i++)
00879 res.joint_names.push_back( joints[i]->GetName() );
00880
00881
00882 res.child_model_names.clear();
00883 for (unsigned int j = 0; j < model->GetChildCount(); j++)
00884 {
00885 gazebo::physics::ModelPtr child_model = boost::dynamic_pointer_cast<gazebo::physics::Model>(model->GetChild(j));
00886 if (child_model)
00887 res.child_model_names.push_back(child_model->GetName() );
00888 }
00889
00890
00891 res.is_static = model->IsStatic();
00892
00893 res.success = true;
00894 res.status_message = "GetModelProperties: got properties";
00895 return true;
00896 }
00897 return true;
00898 }
00899
00900 bool GazeboRosApiPlugin::getWorldProperties(gazebo_msgs::GetWorldProperties::Request &req,
00901 gazebo_msgs::GetWorldProperties::Response &res)
00902 {
00903 res.sim_time = world_->GetSimTime().Double();
00904 res.model_names.clear();
00905 for (unsigned int i = 0; i < world_->GetModelCount(); i ++)
00906 res.model_names.push_back(world_->GetModel(i)->GetName());
00907 gzerr << "disablign rendering has not been implemented, rendering is always enabled\n";
00908 res.rendering_enabled = true;
00909 res.success = true;
00910 res.status_message = "GetWorldProperties: got properties";
00911 return true;
00912 }
00913
00914 bool GazeboRosApiPlugin::getJointProperties(gazebo_msgs::GetJointProperties::Request &req,
00915 gazebo_msgs::GetJointProperties::Response &res)
00916 {
00917 gazebo::physics::JointPtr joint;
00918 for (unsigned int i = 0; i < world_->GetModelCount(); i ++)
00919 {
00920 joint = world_->GetModel(i)->GetJoint(req.joint_name);
00921 if (joint) break;
00922 }
00923
00924 if (!joint)
00925 {
00926 res.success = false;
00927 res.status_message = "GetJointProperties: joint not found";
00928 return true;
00929 }
00930 else
00931 {
00933 res.type = res.REVOLUTE;
00934
00935 res.damping.clear();
00936
00937
00938 res.position.clear();
00939 res.position.push_back(joint->GetAngle(0).Radian());
00940
00941 res.rate.clear();
00942 res.rate.push_back(joint->GetVelocity(0));
00943
00944 res.success = true;
00945 res.status_message = "GetJointProperties: got properties";
00946 return true;
00947 }
00948 }
00949
00950 bool GazeboRosApiPlugin::getLinkProperties(gazebo_msgs::GetLinkProperties::Request &req,
00951 gazebo_msgs::GetLinkProperties::Response &res)
00952 {
00953 gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(world_->GetEntity(req.link_name));
00954 if (!body)
00955 {
00956 res.success = false;
00957 res.status_message = "GetLinkProperties: link not found, did you forget to scope the link by model name?";
00958 return true;
00959 }
00960 else
00961 {
00963 res.gravity_mode = body->GetGravityMode();
00964
00965 res.mass = body->GetInertial()->GetMass();
00966
00967 gazebo::physics::InertialPtr inertia = body->GetInertial();
00968 res.ixx = inertia->GetIXX();
00969 res.iyy = inertia->GetIYY();
00970 res.izz = inertia->GetIZZ();
00971 res.ixy = inertia->GetIXY();
00972 res.ixz = inertia->GetIXZ();
00973 res.iyz = inertia->GetIYZ();
00974
00975 gazebo::math::Vector3 com = body->GetInertial()->GetCoG();
00976 res.com.position.x = com.x;
00977 res.com.position.y = com.y;
00978 res.com.position.z = com.z;
00979 res.com.orientation.x = 0;
00980 res.com.orientation.y = 0;
00981 res.com.orientation.z = 0;
00982 res.com.orientation.w = 1;
00983
00984 res.success = true;
00985 res.status_message = "GetLinkProperties: got properties";
00986 return true;
00987 }
00988 }
00989
00990 bool GazeboRosApiPlugin::getLinkState(gazebo_msgs::GetLinkState::Request &req,
00991 gazebo_msgs::GetLinkState::Response &res)
00992 {
00993 gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(world_->GetEntity(req.link_name));
00994 gazebo::physics::LinkPtr frame = boost::dynamic_pointer_cast<gazebo::physics::Link>(world_->GetEntity(req.reference_frame));
00995
00996 if (!body)
00997 {
00998 res.success = false;
00999 res.status_message = "GetLinkState: link not found, did you forget to scope the link by model name?";
01000 return true;
01001 }
01002
01003
01004 gazebo::math::Pose body_pose = body->GetWorldPose();
01005
01006 gazebo::math::Vector3 body_vpos = body->GetWorldLinearVel();
01007 gazebo::math::Vector3 body_veul = body->GetWorldAngularVel();
01008
01009 if (frame)
01010 {
01011
01012 gazebo::math::Pose frame_pose = frame->GetWorldPose();
01013 body_pose.pos = body_pose.pos - frame_pose.pos;
01014 body_pose.pos = frame_pose.rot.RotateVectorReverse(body_pose.pos);
01015 body_pose.rot *= frame_pose.rot.GetInverse();
01016
01017
01018 gazebo::math::Vector3 frame_vpos = frame->GetWorldLinearVel();
01019 gazebo::math::Vector3 frame_veul = frame->GetWorldAngularVel();
01020 body_vpos = frame_pose.rot.RotateVector(body_vpos - frame_vpos);
01021 body_veul = frame_pose.rot.RotateVector(body_veul - frame_veul);
01022 }
01024 else if (req.reference_frame == "" || req.reference_frame == "world" || req.reference_frame == "map" || req.reference_frame == "/map")
01025 {
01026 ROS_DEBUG("GetLinkState: reference_frame is empty/world/map, using inertial frame");
01027 }
01028 else
01029 {
01030 res.success = false;
01031 res.status_message = "GetLinkState: reference reference_frame not found, did you forget to scope the link by model name?";
01032 return true;
01033 }
01034
01035 res.link_state.link_name = req.link_name;
01036 res.link_state.pose.position.x = body_pose.pos.x;
01037 res.link_state.pose.position.y = body_pose.pos.y;
01038 res.link_state.pose.position.z = body_pose.pos.z;
01039 res.link_state.pose.orientation.x = body_pose.rot.x;
01040 res.link_state.pose.orientation.y = body_pose.rot.y;
01041 res.link_state.pose.orientation.z = body_pose.rot.z;
01042 res.link_state.pose.orientation.w = body_pose.rot.w;
01043 res.link_state.twist.linear.x = body_vpos.x;
01044 res.link_state.twist.linear.y = body_vpos.y;
01045 res.link_state.twist.linear.z = body_vpos.z;
01046 res.link_state.twist.angular.x = body_veul.x;
01047 res.link_state.twist.angular.y = body_veul.y;
01048 res.link_state.twist.angular.z = body_veul.z;
01049 res.link_state.reference_frame = req.reference_frame;
01050
01051 res.success = true;
01052 res.status_message = "GetLinkState: got state";
01053 return true;
01054 }
01055
01056 bool GazeboRosApiPlugin::setLinkProperties(gazebo_msgs::SetLinkProperties::Request &req,
01057 gazebo_msgs::SetLinkProperties::Response &res)
01058 {
01059 gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(world_->GetEntity(req.link_name));
01060 if (!body)
01061 {
01062 res.success = false;
01063 res.status_message = "SetLinkProperties: link not found, did you forget to scope the link by model name?";
01064 return true;
01065 }
01066 else
01067 {
01068 gazebo::physics::InertialPtr mass = body->GetInertial();
01069
01070
01071 mass->SetCoG(gazebo::math::Vector3(req.com.position.x,req.com.position.y,req.com.position.z));
01072 mass->SetInertiaMatrix(req.ixx,req.iyy,req.izz,req.ixy,req.ixz,req.iyz);
01073 mass->SetMass(req.mass);
01074 body->SetGravityMode(req.gravity_mode);
01075
01076 res.success = true;
01077 res.status_message = "SetLinkProperties: properties set";
01078 return true;
01079 }
01080 }
01081
01082 bool GazeboRosApiPlugin::setPhysicsProperties(gazebo_msgs::SetPhysicsProperties::Request &req,
01083 gazebo_msgs::SetPhysicsProperties::Response &res)
01084 {
01085
01086 bool is_paused = world_->IsPaused();
01087 world_->SetPaused(true);
01088
01089
01090 gazebo::physics::PhysicsEnginePtr pe = (world_->GetPhysicsEngine());
01091 pe->SetMaxStepSize(req.time_step);
01092 pe->SetRealTimeUpdateRate(req.max_update_rate);
01093 pe->SetGravity(gazebo::math::Vector3(req.gravity.x,req.gravity.y,req.gravity.z));
01094
01095 if (world_->GetPhysicsEngine()->GetType() == "ode")
01096 {
01097
01098 pe->SetAutoDisableFlag(req.ode_config.auto_disable_bodies);
01099 #if GAZEBO_MAJOR_VERSION >= 3
01100 pe->SetParam("precon_iters", req.ode_config.sor_pgs_precon_iters);
01101 pe->SetParam("iters", req.ode_config.sor_pgs_iters);
01102 pe->SetParam("sor", req.ode_config.sor_pgs_w);
01103 pe->SetParam("cfm", req.ode_config.cfm);
01104 pe->SetParam("erp", req.ode_config.erp);
01105 pe->SetParam("contact_surface_layer",
01106 req.ode_config.contact_surface_layer);
01107 pe->SetParam("contact_max_correcting_vel",
01108 req.ode_config.contact_max_correcting_vel);
01109 pe->SetParam("max_contacts", req.ode_config.max_contacts);
01110 #else
01111 pe->SetSORPGSPreconIters(req.ode_config.sor_pgs_precon_iters);
01112 pe->SetSORPGSIters(req.ode_config.sor_pgs_iters);
01113 pe->SetSORPGSW(req.ode_config.sor_pgs_w);
01114 pe->SetWorldCFM(req.ode_config.cfm);
01115 pe->SetWorldERP(req.ode_config.erp);
01116 pe->SetContactSurfaceLayer(req.ode_config.contact_surface_layer);
01117 pe->SetContactMaxCorrectingVel(req.ode_config.contact_max_correcting_vel);
01118 pe->SetMaxContacts(req.ode_config.max_contacts);
01119 #endif
01120
01121 world_->SetPaused(is_paused);
01122
01123 res.success = true;
01124 res.status_message = "physics engine updated";
01125 }
01126 else
01127 {
01129 ROS_ERROR("ROS set_physics_properties service call does not yet support physics engine [%s].", world_->GetPhysicsEngine()->GetType().c_str());
01130 res.success = false;
01131 res.status_message = "Physics engine [" + world_->GetPhysicsEngine()->GetType() + "]: set_physics_properties not supported.";
01132 }
01133 return res.success;
01134 }
01135
01136 bool GazeboRosApiPlugin::getPhysicsProperties(gazebo_msgs::GetPhysicsProperties::Request &req,
01137 gazebo_msgs::GetPhysicsProperties::Response &res)
01138 {
01139
01140 res.time_step = world_->GetPhysicsEngine()->GetMaxStepSize();
01141 res.pause = world_->IsPaused();
01142 res.max_update_rate = world_->GetPhysicsEngine()->GetRealTimeUpdateRate();
01143 gazebo::math::Vector3 gravity = world_->GetPhysicsEngine()->GetGravity();
01144 res.gravity.x = gravity.x;
01145 res.gravity.y = gravity.y;
01146 res.gravity.z = gravity.z;
01147
01148
01149 if (world_->GetPhysicsEngine()->GetType() == "ode")
01150 {
01151 res.ode_config.auto_disable_bodies =
01152 world_->GetPhysicsEngine()->GetAutoDisableFlag();
01153 #if GAZEBO_MAJOR_VERSION >= 3
01154 res.ode_config.sor_pgs_precon_iters = boost::any_cast<int>(
01155 world_->GetPhysicsEngine()->GetParam("precon_iters"));
01156 res.ode_config.sor_pgs_iters = boost::any_cast<int>(
01157 world_->GetPhysicsEngine()->GetParam("iters"));
01158 res.ode_config.sor_pgs_w = boost::any_cast<double>(
01159 world_->GetPhysicsEngine()->GetParam("sor"));
01160 res.ode_config.contact_surface_layer = boost::any_cast<double>(
01161 world_->GetPhysicsEngine()->GetParam("contact_surface_layer"));
01162 res.ode_config.contact_max_correcting_vel = boost::any_cast<double>(
01163 world_->GetPhysicsEngine()->GetParam("contact_max_correcting_vel"));
01164 res.ode_config.cfm = boost::any_cast<double>(
01165 world_->GetPhysicsEngine()->GetParam("cfm"));
01166 res.ode_config.erp = boost::any_cast<double>(
01167 world_->GetPhysicsEngine()->GetParam("erp"));
01168 res.ode_config.max_contacts = boost::any_cast<int>(
01169 world_->GetPhysicsEngine()->GetParam("max_contacts"));
01170 #else
01171 res.ode_config.sor_pgs_precon_iters = world_->GetPhysicsEngine()->GetSORPGSPreconIters();
01172 res.ode_config.sor_pgs_iters = world_->GetPhysicsEngine()->GetSORPGSIters();
01173 res.ode_config.sor_pgs_w = world_->GetPhysicsEngine()->GetSORPGSW();
01174 res.ode_config.contact_surface_layer = world_->GetPhysicsEngine()->GetContactSurfaceLayer();
01175 res.ode_config.contact_max_correcting_vel = world_->GetPhysicsEngine()->GetContactMaxCorrectingVel();
01176 res.ode_config.cfm = world_->GetPhysicsEngine()->GetWorldCFM();
01177 res.ode_config.erp = world_->GetPhysicsEngine()->GetWorldERP();
01178 res.ode_config.max_contacts = world_->GetPhysicsEngine()->GetMaxContacts();
01179 #endif
01180
01181 res.success = true;
01182 res.status_message = "GetPhysicsProperties: got properties";
01183 }
01184 else
01185 {
01187 ROS_ERROR("ROS get_physics_properties service call does not yet support physics engine [%s].", world_->GetPhysicsEngine()->GetType().c_str());
01188 res.success = false;
01189 res.status_message = "Physics engine [" + world_->GetPhysicsEngine()->GetType() + "]: get_physics_properties not supported.";
01190 }
01191 return res.success;
01192 }
01193
01194 bool GazeboRosApiPlugin::setJointProperties(gazebo_msgs::SetJointProperties::Request &req,
01195 gazebo_msgs::SetJointProperties::Response &res)
01196 {
01198 gazebo::physics::JointPtr joint;
01199 for (unsigned int i = 0; i < world_->GetModelCount(); i ++)
01200 {
01201 joint = world_->GetModel(i)->GetJoint(req.joint_name);
01202 if (joint) break;
01203 }
01204
01205 if (!joint)
01206 {
01207 res.success = false;
01208 res.status_message = "SetJointProperties: joint not found";
01209 return true;
01210 }
01211 else
01212 {
01213 for(unsigned int i=0;i< req.ode_joint_config.damping.size();i++)
01214 joint->SetDamping(i,req.ode_joint_config.damping[i]);
01215 #if GAZEBO_MAJOR_VERSION >= 4
01216 for(unsigned int i=0;i< req.ode_joint_config.hiStop.size();i++)
01217 joint->SetParam("hi_stop",i,req.ode_joint_config.hiStop[i]);
01218 for(unsigned int i=0;i< req.ode_joint_config.loStop.size();i++)
01219 joint->SetParam("lo_stop",i,req.ode_joint_config.loStop[i]);
01220 for(unsigned int i=0;i< req.ode_joint_config.erp.size();i++)
01221 joint->SetParam("erp",i,req.ode_joint_config.erp[i]);
01222 for(unsigned int i=0;i< req.ode_joint_config.cfm.size();i++)
01223 joint->SetParam("cfm",i,req.ode_joint_config.cfm[i]);
01224 for(unsigned int i=0;i< req.ode_joint_config.stop_erp.size();i++)
01225 joint->SetParam("stop_erp",i,req.ode_joint_config.stop_erp[i]);
01226 for(unsigned int i=0;i< req.ode_joint_config.stop_cfm.size();i++)
01227 joint->SetParam("stop_cfm",i,req.ode_joint_config.stop_cfm[i]);
01228 for(unsigned int i=0;i< req.ode_joint_config.fudge_factor.size();i++)
01229 joint->SetParam("fudge_factor",i,req.ode_joint_config.fudge_factor[i]);
01230 for(unsigned int i=0;i< req.ode_joint_config.fmax.size();i++)
01231 joint->SetParam("fmax",i,req.ode_joint_config.fmax[i]);
01232 for(unsigned int i=0;i< req.ode_joint_config.vel.size();i++)
01233 joint->SetParam("vel",i,req.ode_joint_config.vel[i]);
01234 #else
01235 for(unsigned int i=0;i< req.ode_joint_config.hiStop.size();i++)
01236 joint->SetAttribute("hi_stop",i,req.ode_joint_config.hiStop[i]);
01237 for(unsigned int i=0;i< req.ode_joint_config.loStop.size();i++)
01238 joint->SetAttribute("lo_stop",i,req.ode_joint_config.loStop[i]);
01239 for(unsigned int i=0;i< req.ode_joint_config.erp.size();i++)
01240 joint->SetAttribute("erp",i,req.ode_joint_config.erp[i]);
01241 for(unsigned int i=0;i< req.ode_joint_config.cfm.size();i++)
01242 joint->SetAttribute("cfm",i,req.ode_joint_config.cfm[i]);
01243 for(unsigned int i=0;i< req.ode_joint_config.stop_erp.size();i++)
01244 joint->SetAttribute("stop_erp",i,req.ode_joint_config.stop_erp[i]);
01245 for(unsigned int i=0;i< req.ode_joint_config.stop_cfm.size();i++)
01246 joint->SetAttribute("stop_cfm",i,req.ode_joint_config.stop_cfm[i]);
01247 for(unsigned int i=0;i< req.ode_joint_config.fudge_factor.size();i++)
01248 joint->SetAttribute("fudge_factor",i,req.ode_joint_config.fudge_factor[i]);
01249 for(unsigned int i=0;i< req.ode_joint_config.fmax.size();i++)
01250 joint->SetAttribute("fmax",i,req.ode_joint_config.fmax[i]);
01251 for(unsigned int i=0;i< req.ode_joint_config.vel.size();i++)
01252 joint->SetAttribute("vel",i,req.ode_joint_config.vel[i]);
01253 #endif
01254
01255 res.success = true;
01256 res.status_message = "SetJointProperties: properties set";
01257 return true;
01258 }
01259 }
01260
01261 bool GazeboRosApiPlugin::setModelState(gazebo_msgs::SetModelState::Request &req,
01262 gazebo_msgs::SetModelState::Response &res)
01263 {
01264 gazebo::math::Vector3 target_pos(req.model_state.pose.position.x,req.model_state.pose.position.y,req.model_state.pose.position.z);
01265 gazebo::math::Quaternion target_rot(req.model_state.pose.orientation.w,req.model_state.pose.orientation.x,req.model_state.pose.orientation.y,req.model_state.pose.orientation.z);
01266 target_rot.Normalize();
01267 gazebo::math::Pose target_pose(target_pos,target_rot);
01268 gazebo::math::Vector3 target_pos_dot(req.model_state.twist.linear.x,req.model_state.twist.linear.y,req.model_state.twist.linear.z);
01269 gazebo::math::Vector3 target_rot_dot(req.model_state.twist.angular.x,req.model_state.twist.angular.y,req.model_state.twist.angular.z);
01270
01271 gazebo::physics::ModelPtr model = world_->GetModel(req.model_state.model_name);
01272 if (!model)
01273 {
01274 ROS_ERROR("Updating ModelState: model [%s] does not exist",req.model_state.model_name.c_str());
01275 res.success = false;
01276 res.status_message = "SetModelState: model does not exist";
01277 return true;
01278 }
01279 else
01280 {
01281 gazebo::physics::LinkPtr relative_entity = boost::dynamic_pointer_cast<gazebo::physics::Link>(world_->GetEntity(req.model_state.reference_frame));
01282 if (relative_entity)
01283 {
01284 gazebo::math::Pose frame_pose = relative_entity->GetWorldPose();
01285 gazebo::math::Vector3 frame_pos = frame_pose.pos;
01286 gazebo::math::Quaternion frame_rot = frame_pose.rot;
01287
01288
01289
01290 target_pose.pos = model->GetWorldPose().pos + frame_rot.RotateVector(target_pos);
01291 target_pose.rot = frame_rot * target_pose.rot;
01292
01293
01294
01295 target_pos_dot = frame_rot.RotateVector(target_pos_dot);
01296 target_rot_dot = frame_rot.RotateVector(target_rot_dot);
01297 }
01299 else if (req.model_state.reference_frame == "" || req.model_state.reference_frame == "world" || req.model_state.reference_frame == "map" || req.model_state.reference_frame == "/map" )
01300 {
01301 ROS_DEBUG("Updating ModelState: reference frame is empty/world/map, usig inertial frame");
01302 }
01303 else
01304 {
01305 ROS_ERROR("Updating ModelState: for model[%s], specified reference frame entity [%s] does not exist",
01306 req.model_state.model_name.c_str(),req.model_state.reference_frame.c_str());
01307 res.success = false;
01308 res.status_message = "SetModelState: specified reference frame entity does not exist";
01309 return true;
01310 }
01311
01312
01313 bool is_paused = world_->IsPaused();
01314 world_->SetPaused(true);
01315 model->SetWorldPose(target_pose);
01316 world_->SetPaused(is_paused);
01317
01318
01319
01320
01321 model->SetLinearVel(target_pos_dot);
01322 model->SetAngularVel(target_rot_dot);
01323
01324 res.success = true;
01325 res.status_message = "SetModelState: set model state done";
01326 return true;
01327 }
01328 }
01329
01330 void GazeboRosApiPlugin::updateModelState(const gazebo_msgs::ModelState::ConstPtr& model_state)
01331 {
01332 gazebo_msgs::SetModelState::Response res;
01333 gazebo_msgs::SetModelState::Request req;
01334 req.model_state = *model_state;
01335 setModelState(req,res);
01336 }
01337
01338 bool GazeboRosApiPlugin::applyJointEffort(gazebo_msgs::ApplyJointEffort::Request &req,
01339 gazebo_msgs::ApplyJointEffort::Response &res)
01340 {
01341 gazebo::physics::JointPtr joint;
01342 for (unsigned int i = 0; i < world_->GetModelCount(); i ++)
01343 {
01344 joint = world_->GetModel(i)->GetJoint(req.joint_name);
01345 if (joint)
01346 {
01347 GazeboRosApiPlugin::ForceJointJob* fjj = new GazeboRosApiPlugin::ForceJointJob;
01348 fjj->joint = joint;
01349 fjj->force = req.effort;
01350 fjj->start_time = req.start_time;
01351 if (fjj->start_time < ros::Time(world_->GetSimTime().Double()))
01352 fjj->start_time = ros::Time(world_->GetSimTime().Double());
01353 fjj->duration = req.duration;
01354 lock_.lock();
01355 force_joint_jobs_.push_back(fjj);
01356 lock_.unlock();
01357
01358 res.success = true;
01359 res.status_message = "ApplyJointEffort: effort set";
01360 return true;
01361 }
01362 }
01363
01364 res.success = false;
01365 res.status_message = "ApplyJointEffort: joint not found";
01366 return true;
01367 }
01368
01369 bool GazeboRosApiPlugin::resetSimulation(std_srvs::Empty::Request &req,std_srvs::Empty::Response &res)
01370 {
01371 world_->Reset();
01372 return true;
01373 }
01374
01375 bool GazeboRosApiPlugin::resetWorld(std_srvs::Empty::Request &req,std_srvs::Empty::Response &res)
01376 {
01377 world_->ResetEntities(gazebo::physics::Base::MODEL);
01378 return true;
01379 }
01380
01381 bool GazeboRosApiPlugin::pausePhysics(std_srvs::Empty::Request &req,std_srvs::Empty::Response &res)
01382 {
01383 world_->SetPaused(true);
01384 return true;
01385 }
01386
01387 bool GazeboRosApiPlugin::unpausePhysics(std_srvs::Empty::Request &req,std_srvs::Empty::Response &res)
01388 {
01389 world_->SetPaused(false);
01390 return true;
01391 }
01392
01393 bool GazeboRosApiPlugin::clearJointForces(gazebo_msgs::JointRequest::Request &req,
01394 gazebo_msgs::JointRequest::Response &res)
01395 {
01396 return clearJointForces(req.joint_name);
01397 }
01398 bool GazeboRosApiPlugin::clearJointForces(std::string joint_name)
01399 {
01400 bool search = true;
01401 lock_.lock();
01402 while(search)
01403 {
01404 search = false;
01405 for (std::vector<GazeboRosApiPlugin::ForceJointJob*>::iterator iter=force_joint_jobs_.begin();iter!=force_joint_jobs_.end();++iter)
01406 {
01407 if ((*iter)->joint->GetName() == joint_name)
01408 {
01409
01410 search = true;
01411 delete (*iter);
01412 force_joint_jobs_.erase(iter);
01413 break;
01414 }
01415 }
01416 }
01417 lock_.unlock();
01418 return true;
01419 }
01420
01421 bool GazeboRosApiPlugin::clearBodyWrenches(gazebo_msgs::BodyRequest::Request &req,
01422 gazebo_msgs::BodyRequest::Response &res)
01423 {
01424 return clearBodyWrenches(req.body_name);
01425 }
01426 bool GazeboRosApiPlugin::clearBodyWrenches(std::string body_name)
01427 {
01428 bool search = true;
01429 lock_.lock();
01430 while(search)
01431 {
01432 search = false;
01433 for (std::vector<GazeboRosApiPlugin::WrenchBodyJob*>::iterator iter=wrench_body_jobs_.begin();iter!=wrench_body_jobs_.end();++iter)
01434 {
01435
01436 if ((*iter)->body->GetScopedName() == body_name)
01437 {
01438
01439 search = true;
01440 delete (*iter);
01441 wrench_body_jobs_.erase(iter);
01442 break;
01443 }
01444 }
01445 }
01446 lock_.unlock();
01447 return true;
01448 }
01449
01450 bool GazeboRosApiPlugin::setModelConfiguration(gazebo_msgs::SetModelConfiguration::Request &req,
01451 gazebo_msgs::SetModelConfiguration::Response &res)
01452 {
01453 std::string gazebo_model_name = req.model_name;
01454
01455
01456 gazebo::physics::ModelPtr gazebo_model = world_->GetModel(req.model_name);
01457 if (!gazebo_model)
01458 {
01459 ROS_ERROR("SetModelConfiguration: model [%s] does not exist",gazebo_model_name.c_str());
01460 res.success = false;
01461 res.status_message = "SetModelConfiguration: model does not exist";
01462 return true;
01463 }
01464
01465 if (req.joint_names.size() == req.joint_positions.size())
01466 {
01467 std::map<std::string, double> joint_position_map;
01468 for (unsigned int i = 0; i < req.joint_names.size(); i++)
01469 {
01470 joint_position_map[req.joint_names[i]] = req.joint_positions[i];
01471 }
01472
01473
01474 bool is_paused = world_->IsPaused();
01475 if (!is_paused) world_->SetPaused(true);
01476
01477 gazebo_model->SetJointPositions(joint_position_map);
01478
01479
01480 world_->SetPaused(is_paused);
01481
01482 res.success = true;
01483 res.status_message = "SetModelConfiguration: success";
01484 return true;
01485 }
01486 else
01487 {
01488 res.success = false;
01489 res.status_message = "SetModelConfiguration: joint name and position list have different lengths";
01490 return true;
01491 }
01492 }
01493
01494 bool GazeboRosApiPlugin::setLinkState(gazebo_msgs::SetLinkState::Request &req,
01495 gazebo_msgs::SetLinkState::Response &res)
01496 {
01497 gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(world_->GetEntity(req.link_state.link_name));
01498 gazebo::physics::LinkPtr frame = boost::dynamic_pointer_cast<gazebo::physics::Link>(world_->GetEntity(req.link_state.reference_frame));
01499 if (!body)
01500 {
01501 ROS_ERROR("Updating LinkState: link [%s] does not exist",req.link_state.link_name.c_str());
01502 res.success = false;
01503 res.status_message = "SetLinkState: link does not exist";
01504 return true;
01505 }
01506
01508
01509
01510 gazebo::math::Vector3 target_pos(req.link_state.pose.position.x,req.link_state.pose.position.y,req.link_state.pose.position.z);
01511 gazebo::math::Quaternion target_rot(req.link_state.pose.orientation.w,req.link_state.pose.orientation.x,req.link_state.pose.orientation.y,req.link_state.pose.orientation.z);
01512 gazebo::math::Pose target_pose(target_pos,target_rot);
01513 gazebo::math::Vector3 target_linear_vel(req.link_state.twist.linear.x,req.link_state.twist.linear.y,req.link_state.twist.linear.z);
01514 gazebo::math::Vector3 target_angular_vel(req.link_state.twist.angular.x,req.link_state.twist.angular.y,req.link_state.twist.angular.z);
01515
01516 if (frame)
01517 {
01518 gazebo::math::Pose frame_pose = frame->GetWorldPose();
01519 gazebo::math::Vector3 frame_pos = frame_pose.pos;
01520 gazebo::math::Quaternion frame_rot = frame_pose.rot;
01521
01522
01523
01524 target_pose.pos = frame_pos + frame_rot.RotateVector(target_pos);
01525 target_pose.rot = frame_rot * target_pose.rot;
01526
01527 gazebo::math::Vector3 frame_linear_vel = frame->GetWorldLinearVel();
01528 gazebo::math::Vector3 frame_angular_vel = frame->GetWorldAngularVel();
01529 target_linear_vel -= frame_linear_vel;
01530 target_angular_vel -= frame_angular_vel;
01531 }
01532 else if (req.link_state.reference_frame == "" || req.link_state.reference_frame == "world" || req.link_state.reference_frame == "map" || req.link_state.reference_frame == "/map")
01533 {
01534 ROS_INFO("Updating LinkState: reference_frame is empty/world/map, using inertial frame");
01535 }
01536 else
01537 {
01538 ROS_ERROR("Updating LinkState: reference_frame is not a valid link name");
01539 res.success = false;
01540 res.status_message = "SetLinkState: failed";
01541 return true;
01542 }
01543
01544
01545
01546
01547 bool is_paused = world_->IsPaused();
01548 if (!is_paused) world_->SetPaused(true);
01549 body->SetWorldPose(target_pose);
01550 world_->SetPaused(is_paused);
01551
01552
01553 body->SetLinearVel(target_linear_vel);
01554 body->SetAngularVel(target_angular_vel);
01555
01556 res.success = true;
01557 res.status_message = "SetLinkState: success";
01558 return true;
01559 }
01560
01561 void GazeboRosApiPlugin::updateLinkState(const gazebo_msgs::LinkState::ConstPtr& link_state)
01562 {
01563 gazebo_msgs::SetLinkState::Request req;
01564 gazebo_msgs::SetLinkState::Response res;
01565 req.link_state = *link_state;
01566 setLinkState(req,res);
01567 }
01568
01569 void GazeboRosApiPlugin::transformWrench( gazebo::math::Vector3 &target_force, gazebo::math::Vector3 &target_torque,
01570 gazebo::math::Vector3 reference_force, gazebo::math::Vector3 reference_torque,
01571 gazebo::math::Pose target_to_reference )
01572 {
01573
01574 target_force = target_to_reference.rot.RotateVector(reference_force);
01575
01576 target_torque = target_to_reference.rot.RotateVector(reference_torque);
01577
01578
01579 target_torque = target_torque + target_to_reference.pos.Cross(target_force);
01580 }
01581
01582 bool GazeboRosApiPlugin::applyBodyWrench(gazebo_msgs::ApplyBodyWrench::Request &req,
01583 gazebo_msgs::ApplyBodyWrench::Response &res)
01584 {
01585 gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(world_->GetEntity(req.body_name));
01586 gazebo::physics::LinkPtr frame = boost::dynamic_pointer_cast<gazebo::physics::Link>(world_->GetEntity(req.reference_frame));
01587 if (!body)
01588 {
01589 ROS_ERROR("ApplyBodyWrench: body [%s] does not exist",req.body_name.c_str());
01590 res.success = false;
01591 res.status_message = "ApplyBodyWrench: body does not exist";
01592 return true;
01593 }
01594
01595
01596 gazebo::math::Vector3 reference_force(req.wrench.force.x,req.wrench.force.y,req.wrench.force.z);
01597 gazebo::math::Vector3 reference_torque(req.wrench.torque.x,req.wrench.torque.y,req.wrench.torque.z);
01598 gazebo::math::Vector3 reference_point(req.reference_point.x,req.reference_point.y,req.reference_point.z);
01599
01600 gazebo::math::Vector3 target_force;
01601 gazebo::math::Vector3 target_torque;
01602
01605 reference_torque = reference_torque + reference_point.Cross(reference_force);
01606
01608 if (frame)
01609 {
01610
01611
01612
01613
01614
01615
01616 gazebo::math::Pose target_to_reference = frame->GetWorldPose() - body->GetWorldPose();
01617 ROS_DEBUG("reference frame for applied wrench: [%f %f %f, %f %f %f]-[%f %f %f, %f %f %f]=[%f %f %f, %f %f %f]",
01618 body->GetWorldPose().pos.x,
01619 body->GetWorldPose().pos.y,
01620 body->GetWorldPose().pos.z,
01621 body->GetWorldPose().rot.GetAsEuler().x,
01622 body->GetWorldPose().rot.GetAsEuler().y,
01623 body->GetWorldPose().rot.GetAsEuler().z,
01624 frame->GetWorldPose().pos.x,
01625 frame->GetWorldPose().pos.y,
01626 frame->GetWorldPose().pos.z,
01627 frame->GetWorldPose().rot.GetAsEuler().x,
01628 frame->GetWorldPose().rot.GetAsEuler().y,
01629 frame->GetWorldPose().rot.GetAsEuler().z,
01630 target_to_reference.pos.x,
01631 target_to_reference.pos.y,
01632 target_to_reference.pos.z,
01633 target_to_reference.rot.GetAsEuler().x,
01634 target_to_reference.rot.GetAsEuler().y,
01635 target_to_reference.rot.GetAsEuler().z
01636 );
01637 transformWrench(target_force, target_torque, reference_force, reference_torque, target_to_reference);
01638 ROS_ERROR("wrench defined as [%s]:[%f %f %f, %f %f %f] --> applied as [%s]:[%f %f %f, %f %f %f]",
01639 frame->GetName().c_str(),
01640 reference_force.x,
01641 reference_force.y,
01642 reference_force.z,
01643 reference_torque.x,
01644 reference_torque.y,
01645 reference_torque.z,
01646 body->GetName().c_str(),
01647 target_force.x,
01648 target_force.y,
01649 target_force.z,
01650 target_torque.x,
01651 target_torque.y,
01652 target_torque.z
01653 );
01654
01655 }
01656 else if (req.reference_frame == "" || req.reference_frame == "world" || req.reference_frame == "map" || req.reference_frame == "/map")
01657 {
01658 ROS_INFO("ApplyBodyWrench: reference_frame is empty/world/map, using inertial frame, transferring from body relative to inertial frame");
01659
01660 gazebo::math::Pose target_to_reference = body->GetWorldPose();
01661 target_force = reference_force;
01662 target_torque = reference_torque;
01663
01664 }
01665 else
01666 {
01667 ROS_ERROR("ApplyBodyWrench: reference_frame is not a valid link name");
01668 res.success = false;
01669 res.status_message = "ApplyBodyWrench: reference_frame not found";
01670 return true;
01671 }
01672
01673
01674
01675
01676
01677 GazeboRosApiPlugin::WrenchBodyJob* wej = new GazeboRosApiPlugin::WrenchBodyJob;
01678 wej->body = body;
01679 wej->force = target_force;
01680 wej->torque = target_torque;
01681 wej->start_time = req.start_time;
01682 if (wej->start_time < ros::Time(world_->GetSimTime().Double()))
01683 wej->start_time = ros::Time(world_->GetSimTime().Double());
01684 wej->duration = req.duration;
01685 lock_.lock();
01686 wrench_body_jobs_.push_back(wej);
01687 lock_.unlock();
01688
01689 res.success = true;
01690 res.status_message = "";
01691 return true;
01692 }
01693
01694 bool GazeboRosApiPlugin::isURDF(std::string model_xml)
01695 {
01696 TiXmlDocument doc_in;
01697 doc_in.Parse(model_xml.c_str());
01698 if (doc_in.FirstChild("robot"))
01699 return true;
01700 else
01701 return false;
01702 }
01703
01704 bool GazeboRosApiPlugin::isSDF(std::string model_xml)
01705 {
01706
01707 TiXmlDocument doc_in;
01708 doc_in.Parse(model_xml.c_str());
01709 if (doc_in.FirstChild("gazebo") ||
01710 doc_in.FirstChild("sdf"))
01711 return true;
01712 else
01713 return false;
01714 }
01715
01716 void GazeboRosApiPlugin::wrenchBodySchedulerSlot()
01717 {
01718
01719
01720 lock_.lock();
01721 for (std::vector<GazeboRosApiPlugin::WrenchBodyJob*>::iterator iter=wrench_body_jobs_.begin();iter!=wrench_body_jobs_.end();)
01722 {
01723
01724 if (ros::Time(world_->GetSimTime().Double()) >= (*iter)->start_time)
01725 if (ros::Time(world_->GetSimTime().Double()) <= (*iter)->start_time+(*iter)->duration ||
01726 (*iter)->duration.toSec() < 0.0)
01727 {
01728 if ((*iter)->body)
01729 {
01730 (*iter)->body->SetForce((*iter)->force);
01731 (*iter)->body->SetTorque((*iter)->torque);
01732 }
01733 else
01734 (*iter)->duration.fromSec(0.0);
01735 }
01736
01737 if (ros::Time(world_->GetSimTime().Double()) > (*iter)->start_time+(*iter)->duration &&
01738 (*iter)->duration.toSec() >= 0.0)
01739 {
01740
01741 delete (*iter);
01742 iter = wrench_body_jobs_.erase(iter);
01743 }
01744 else
01745 ++iter;
01746 }
01747 lock_.unlock();
01748 }
01749
01750 void GazeboRosApiPlugin::forceJointSchedulerSlot()
01751 {
01752
01753
01754 lock_.lock();
01755 for (std::vector<GazeboRosApiPlugin::ForceJointJob*>::iterator iter=force_joint_jobs_.begin();iter!=force_joint_jobs_.end();)
01756 {
01757
01758 if (ros::Time(world_->GetSimTime().Double()) >= (*iter)->start_time)
01759 if (ros::Time(world_->GetSimTime().Double()) <= (*iter)->start_time+(*iter)->duration ||
01760 (*iter)->duration.toSec() < 0.0)
01761 {
01762 if ((*iter)->joint)
01763 (*iter)->joint->SetForce(0,(*iter)->force);
01764 else
01765 (*iter)->duration.fromSec(0.0);
01766 }
01767
01768 if (ros::Time(world_->GetSimTime().Double()) > (*iter)->start_time+(*iter)->duration &&
01769 (*iter)->duration.toSec() >= 0.0)
01770 {
01771
01772 iter = force_joint_jobs_.erase(iter);
01773 }
01774 else
01775 ++iter;
01776 }
01777 lock_.unlock();
01778 }
01779
01780 void GazeboRosApiPlugin::publishSimTime(const boost::shared_ptr<gazebo::msgs::WorldStatistics const> &msg)
01781 {
01782 ROS_ERROR("CLOCK2");
01783 gazebo::common::Time currentTime = gazebo::msgs::Convert( msg->sim_time() );
01784 rosgraph_msgs::Clock ros_time_;
01785 ros_time_.clock.fromSec(currentTime.Double());
01786
01787 pub_clock_.publish(ros_time_);
01788 }
01789 void GazeboRosApiPlugin::publishSimTime()
01790 {
01791 gazebo::common::Time currentTime = world_->GetSimTime();
01792 rosgraph_msgs::Clock ros_time_;
01793 ros_time_.clock.fromSec(currentTime.Double());
01794
01795 pub_clock_.publish(ros_time_);
01796 }
01797
01798 void GazeboRosApiPlugin::publishLinkStates()
01799 {
01800 gazebo_msgs::LinkStates link_states;
01801
01802
01803 for (unsigned int i = 0; i < world_->GetModelCount(); i ++)
01804 {
01805 gazebo::physics::ModelPtr model = world_->GetModel(i);
01806
01807 for (unsigned int j = 0 ; j < model->GetChildCount(); j ++)
01808 {
01809 gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(model->GetChild(j));
01810
01811 if (body)
01812 {
01813 link_states.name.push_back(body->GetScopedName());
01814 geometry_msgs::Pose pose;
01815 gazebo::math::Pose body_pose = body->GetWorldPose();
01816 gazebo::math::Vector3 pos = body_pose.pos;
01817 gazebo::math::Quaternion rot = body_pose.rot;
01818 pose.position.x = pos.x;
01819 pose.position.y = pos.y;
01820 pose.position.z = pos.z;
01821 pose.orientation.w = rot.w;
01822 pose.orientation.x = rot.x;
01823 pose.orientation.y = rot.y;
01824 pose.orientation.z = rot.z;
01825 link_states.pose.push_back(pose);
01826 gazebo::math::Vector3 linear_vel = body->GetWorldLinearVel();
01827 gazebo::math::Vector3 angular_vel = body->GetWorldAngularVel();
01828 geometry_msgs::Twist twist;
01829 twist.linear.x = linear_vel.x;
01830 twist.linear.y = linear_vel.y;
01831 twist.linear.z = linear_vel.z;
01832 twist.angular.x = angular_vel.x;
01833 twist.angular.y = angular_vel.y;
01834 twist.angular.z = angular_vel.z;
01835 link_states.twist.push_back(twist);
01836 }
01837 }
01838 }
01839
01840 pub_link_states_.publish(link_states);
01841 }
01842
01843 void GazeboRosApiPlugin::publishModelStates()
01844 {
01845 gazebo_msgs::ModelStates model_states;
01846
01847
01848 for (unsigned int i = 0; i < world_->GetModelCount(); i ++)
01849 {
01850 gazebo::physics::ModelPtr model = world_->GetModel(i);
01851 model_states.name.push_back(model->GetName());
01852 geometry_msgs::Pose pose;
01853 gazebo::math::Pose model_pose = model->GetWorldPose();
01854 gazebo::math::Vector3 pos = model_pose.pos;
01855 gazebo::math::Quaternion rot = model_pose.rot;
01856 pose.position.x = pos.x;
01857 pose.position.y = pos.y;
01858 pose.position.z = pos.z;
01859 pose.orientation.w = rot.w;
01860 pose.orientation.x = rot.x;
01861 pose.orientation.y = rot.y;
01862 pose.orientation.z = rot.z;
01863 model_states.pose.push_back(pose);
01864 gazebo::math::Vector3 linear_vel = model->GetWorldLinearVel();
01865 gazebo::math::Vector3 angular_vel = model->GetWorldAngularVel();
01866 geometry_msgs::Twist twist;
01867 twist.linear.x = linear_vel.x;
01868 twist.linear.y = linear_vel.y;
01869 twist.linear.z = linear_vel.z;
01870 twist.angular.x = angular_vel.x;
01871 twist.angular.y = angular_vel.y;
01872 twist.angular.z = angular_vel.z;
01873 model_states.twist.push_back(twist);
01874 }
01875 pub_model_states_.publish(model_states);
01876 }
01877
01878 void GazeboRosApiPlugin::physicsReconfigureCallback(gazebo_ros::PhysicsConfig &config, uint32_t level)
01879 {
01880 if (!physics_reconfigure_initialized_)
01881 {
01882 gazebo_msgs::GetPhysicsProperties srv;
01883 physics_reconfigure_get_client_.call(srv);
01884
01885 config.time_step = srv.response.time_step;
01886 config.max_update_rate = srv.response.max_update_rate;
01887 config.gravity_x = srv.response.gravity.x;
01888 config.gravity_y = srv.response.gravity.y;
01889 config.gravity_z = srv.response.gravity.z;
01890 config.auto_disable_bodies = srv.response.ode_config.auto_disable_bodies;
01891 config.sor_pgs_precon_iters = srv.response.ode_config.sor_pgs_precon_iters;
01892 config.sor_pgs_iters = srv.response.ode_config.sor_pgs_iters;
01893 config.sor_pgs_rms_error_tol = srv.response.ode_config.sor_pgs_rms_error_tol;
01894 config.sor_pgs_w = srv.response.ode_config.sor_pgs_w;
01895 config.contact_surface_layer = srv.response.ode_config.contact_surface_layer;
01896 config.contact_max_correcting_vel = srv.response.ode_config.contact_max_correcting_vel;
01897 config.cfm = srv.response.ode_config.cfm;
01898 config.erp = srv.response.ode_config.erp;
01899 config.max_contacts = srv.response.ode_config.max_contacts;
01900 physics_reconfigure_initialized_ = true;
01901 }
01902 else
01903 {
01904 bool changed = false;
01905 gazebo_msgs::GetPhysicsProperties srv;
01906 physics_reconfigure_get_client_.call(srv);
01907
01908
01909 if (config.time_step != srv.response.time_step) changed = true;
01910 if (config.max_update_rate != srv.response.max_update_rate) changed = true;
01911 if (config.gravity_x != srv.response.gravity.x) changed = true;
01912 if (config.gravity_y != srv.response.gravity.y) changed = true;
01913 if (config.gravity_z != srv.response.gravity.z) changed = true;
01914 if (config.auto_disable_bodies != srv.response.ode_config.auto_disable_bodies) changed = true;
01915 if ((uint32_t)config.sor_pgs_precon_iters != srv.response.ode_config.sor_pgs_precon_iters) changed = true;
01916 if ((uint32_t)config.sor_pgs_iters != srv.response.ode_config.sor_pgs_iters) changed = true;
01917 if (config.sor_pgs_rms_error_tol != srv.response.ode_config.sor_pgs_rms_error_tol) changed = true;
01918 if (config.sor_pgs_w != srv.response.ode_config.sor_pgs_w) changed = true;
01919 if (config.contact_surface_layer != srv.response.ode_config.contact_surface_layer) changed = true;
01920 if (config.contact_max_correcting_vel != srv.response.ode_config.contact_max_correcting_vel) changed = true;
01921 if (config.cfm != srv.response.ode_config.cfm) changed = true;
01922 if (config.erp != srv.response.ode_config.erp) changed = true;
01923 if ((uint32_t)config.max_contacts != srv.response.ode_config.max_contacts) changed = true;
01924
01925 if (changed)
01926 {
01927
01928 gazebo_msgs::SetPhysicsProperties srv;
01929 srv.request.time_step = config.time_step ;
01930 srv.request.max_update_rate = config.max_update_rate ;
01931 srv.request.gravity.x = config.gravity_x ;
01932 srv.request.gravity.y = config.gravity_y ;
01933 srv.request.gravity.z = config.gravity_z ;
01934 srv.request.ode_config.auto_disable_bodies = config.auto_disable_bodies ;
01935 srv.request.ode_config.sor_pgs_precon_iters = config.sor_pgs_precon_iters ;
01936 srv.request.ode_config.sor_pgs_iters = config.sor_pgs_iters ;
01937 srv.request.ode_config.sor_pgs_rms_error_tol = config.sor_pgs_rms_error_tol ;
01938 srv.request.ode_config.sor_pgs_w = config.sor_pgs_w ;
01939 srv.request.ode_config.contact_surface_layer = config.contact_surface_layer ;
01940 srv.request.ode_config.contact_max_correcting_vel = config.contact_max_correcting_vel ;
01941 srv.request.ode_config.cfm = config.cfm ;
01942 srv.request.ode_config.erp = config.erp ;
01943 srv.request.ode_config.max_contacts = config.max_contacts ;
01944 physics_reconfigure_set_client_.call(srv);
01945 ROS_INFO("physics dynamics reconfigure update complete");
01946 }
01947 ROS_INFO("physics dynamics reconfigure complete");
01948 }
01949 }
01950
01951 void GazeboRosApiPlugin::physicsReconfigureThread()
01952 {
01953 physics_reconfigure_set_client_ = nh_->serviceClient<gazebo_msgs::SetPhysicsProperties>("/gazebo/set_physics_properties");
01954 physics_reconfigure_get_client_ = nh_->serviceClient<gazebo_msgs::GetPhysicsProperties>("/gazebo/get_physics_properties");
01955
01956
01957 physics_reconfigure_set_client_.waitForExistence();
01958 physics_reconfigure_get_client_.waitForExistence();
01959
01960 physics_reconfigure_srv_.reset(new dynamic_reconfigure::Server<gazebo_ros::PhysicsConfig>());
01961
01962 physics_reconfigure_callback_ = boost::bind(&GazeboRosApiPlugin::physicsReconfigureCallback, this, _1, _2);
01963 physics_reconfigure_srv_->setCallback(physics_reconfigure_callback_);
01964
01965 ROS_INFO("Physics dynamic reconfigure ready.");
01966 }
01967
01968 void GazeboRosApiPlugin::stripXmlDeclaration(std::string &model_xml)
01969 {
01970
01974 std::string open_bracket("<?");
01975 std::string close_bracket("?>");
01976 size_t pos1 = model_xml.find(open_bracket,0);
01977 size_t pos2 = model_xml.find(close_bracket,0);
01978 if (pos1 != std::string::npos && pos2 != std::string::npos)
01979 model_xml.replace(pos1,pos2-pos1+2,std::string(""));
01980 }
01981
01982 void GazeboRosApiPlugin::updateSDFAttributes(TiXmlDocument &gazebo_model_xml, std::string model_name,
01983 gazebo::math::Vector3 initial_xyz, gazebo::math::Quaternion initial_q)
01984 {
01985
01986
01987
01988 TiXmlElement* pose_element;
01989
01990
01991 TiXmlElement* gazebo_tixml = gazebo_model_xml.FirstChildElement("sdf");
01992 if (!gazebo_tixml)
01993 {
01994 ROS_WARN("Could not find <sdf> element in sdf, so name and initial position cannot be applied");
01995 return;
01996 }
01997
01998
01999 TiXmlElement* model_tixml = gazebo_tixml->FirstChildElement("model");
02000 if (model_tixml)
02001 {
02002
02003 if (model_tixml->Attribute("name") != NULL)
02004 {
02005
02006 model_tixml->RemoveAttribute("name");
02007 }
02008
02009 model_tixml->SetAttribute("name",model_name);
02010 }
02011 else
02012 {
02013
02014 TiXmlElement* world_tixml = gazebo_tixml->FirstChildElement("world");
02015 if (!world_tixml)
02016 {
02017 ROS_WARN("Could not find <model> or <world> element in sdf, so name and initial position cannot be applied");
02018 return;
02019 }
02020
02021 model_tixml = world_tixml->FirstChildElement("include");
02022 if (!model_tixml)
02023 {
02024 ROS_WARN("Could not find <include> element in sdf, so name and initial position cannot be applied");
02025 return;
02026 }
02027
02028
02029 TiXmlElement* name_tixml = model_tixml->FirstChildElement("name");
02030 if (!name_tixml)
02031 {
02032
02033 name_tixml = new TiXmlElement("name");
02034 model_tixml->LinkEndChild(name_tixml);
02035 }
02036
02037
02038 TiXmlText* text = new TiXmlText(model_name);
02039 name_tixml->LinkEndChild( text );
02040 }
02041
02042
02043
02044 pose_element = model_tixml->FirstChildElement("pose");
02045 gazebo::math::Pose model_pose;
02046
02047
02048
02049 if (pose_element)
02050 {
02051
02052 model_pose = this->parsePose(pose_element->GetText());
02053 model_tixml->RemoveChild(pose_element);
02054 }
02055
02056
02057 {
02058
02059 gazebo::math::Pose new_model_pose = model_pose + gazebo::math::Pose(initial_xyz, initial_q);
02060
02061
02062 std::ostringstream pose_stream;
02063 gazebo::math::Vector3 model_rpy = new_model_pose.rot.GetAsEuler();
02064 pose_stream << new_model_pose.pos.x << " " << new_model_pose.pos.y << " " << new_model_pose.pos.z << " "
02065 << model_rpy.x << " " << model_rpy.y << " " << model_rpy.z;
02066
02067
02068 TiXmlText* text = new TiXmlText(pose_stream.str());
02069 TiXmlElement* new_pose_element = new TiXmlElement("pose");
02070 new_pose_element->LinkEndChild(text);
02071 model_tixml->LinkEndChild(new_pose_element);
02072 }
02073 }
02074
02075 gazebo::math::Pose GazeboRosApiPlugin::parsePose(const std::string &str)
02076 {
02077 std::vector<std::string> pieces;
02078 std::vector<double> vals;
02079
02080 boost::split(pieces, str, boost::is_any_of(" "));
02081 for (unsigned int i = 0; i < pieces.size(); ++i)
02082 {
02083 if (pieces[i] != "")
02084 {
02085 try
02086 {
02087 vals.push_back(boost::lexical_cast<double>(pieces[i].c_str()));
02088 }
02089 catch(boost::bad_lexical_cast &e)
02090 {
02091 sdferr << "xml key [" << str
02092 << "][" << i << "] value [" << pieces[i]
02093 << "] is not a valid double from a 3-tuple\n";
02094 return gazebo::math::Pose();
02095 }
02096 }
02097 }
02098
02099 if (vals.size() == 6)
02100 return gazebo::math::Pose(vals[0], vals[1], vals[2], vals[3], vals[4], vals[5]);
02101 else
02102 {
02103 ROS_ERROR("Beware: failed to parse string [%s] as gazebo::math::Pose, returning zeros.", str.c_str());
02104 return gazebo::math::Pose();
02105 }
02106 }
02107
02108 gazebo::math::Vector3 GazeboRosApiPlugin::parseVector3(const std::string &str)
02109 {
02110 std::vector<std::string> pieces;
02111 std::vector<double> vals;
02112
02113 boost::split(pieces, str, boost::is_any_of(" "));
02114 for (unsigned int i = 0; i < pieces.size(); ++i)
02115 {
02116 if (pieces[i] != "")
02117 {
02118 try
02119 {
02120 vals.push_back(boost::lexical_cast<double>(pieces[i].c_str()));
02121 }
02122 catch(boost::bad_lexical_cast &e)
02123 {
02124 sdferr << "xml key [" << str
02125 << "][" << i << "] value [" << pieces[i]
02126 << "] is not a valid double from a 3-tuple\n";
02127 return gazebo::math::Vector3();
02128 }
02129 }
02130 }
02131
02132 if (vals.size() == 3)
02133 return gazebo::math::Vector3(vals[0], vals[1], vals[2]);
02134 else
02135 {
02136 ROS_ERROR("Beware: failed to parse string [%s] as gazebo::math::Vector3, returning zeros.", str.c_str());
02137 return gazebo::math::Vector3();
02138 }
02139 }
02140
02141 void GazeboRosApiPlugin::updateURDFModelPose(TiXmlDocument &gazebo_model_xml, gazebo::math::Vector3 initial_xyz, gazebo::math::Quaternion initial_q)
02142 {
02143 TiXmlElement* model_tixml = (gazebo_model_xml.FirstChildElement("robot"));
02144 if (model_tixml)
02145 {
02146
02147
02148 TiXmlElement* origin_key = model_tixml->FirstChildElement("origin");
02149
02150 if (!origin_key)
02151 {
02152 origin_key = new TiXmlElement("origin");
02153 model_tixml->LinkEndChild(origin_key);
02154 }
02155
02156 gazebo::math::Vector3 xyz;
02157 gazebo::math::Vector3 rpy;
02158 if (origin_key->Attribute("xyz"))
02159 {
02160 xyz = this->parseVector3(origin_key->Attribute("xyz"));
02161 origin_key->RemoveAttribute("xyz");
02162 }
02163 if (origin_key->Attribute("rpy"))
02164 {
02165 rpy = this->parseVector3(origin_key->Attribute("rpy"));
02166 origin_key->RemoveAttribute("rpy");
02167 }
02168
02169
02170 gazebo::math::Pose model_pose = gazebo::math::Pose(xyz, rpy) + gazebo::math::Pose(initial_xyz, initial_q);
02171
02172 std::ostringstream xyz_stream;
02173 xyz_stream << model_pose.pos.x << " " << model_pose.pos.y << " " << model_pose.pos.z;
02174
02175 std::ostringstream rpy_stream;
02176 gazebo::math::Vector3 model_rpy = model_pose.rot.GetAsEuler();
02177 rpy_stream << model_rpy.x << " " << model_rpy.y << " " << model_rpy.z;
02178
02179 origin_key->SetAttribute("xyz",xyz_stream.str());
02180 origin_key->SetAttribute("rpy",rpy_stream.str());
02181 }
02182 else
02183 ROS_WARN("could not find <model> element in sdf, so name and initial position is not applied");
02184 }
02185
02186 void GazeboRosApiPlugin::updateURDFName(TiXmlDocument &gazebo_model_xml, std::string model_name)
02187 {
02188 TiXmlElement* model_tixml = gazebo_model_xml.FirstChildElement("robot");
02189
02190 if (model_tixml)
02191 {
02192 if (model_tixml->Attribute("name") != NULL)
02193 {
02194
02195 model_tixml->RemoveAttribute("name");
02196 }
02197
02198 model_tixml->SetAttribute("name",model_name);
02199 }
02200 else
02201 ROS_WARN("could not find <robot> element in URDF, name not replaced");
02202 }
02203
02204 void GazeboRosApiPlugin::walkChildAddRobotNamespace(TiXmlNode* robot_xml)
02205 {
02206 TiXmlNode* child = 0;
02207 child = robot_xml->IterateChildren(child);
02208 while (child != NULL)
02209 {
02210 if (child->Type() == TiXmlNode::TINYXML_ELEMENT &&
02211 child->ValueStr().compare(std::string("plugin")) == 0)
02212 {
02213 if (child->FirstChildElement("robotNamespace") == NULL)
02214 {
02215 TiXmlElement* child_elem = child->ToElement()->FirstChildElement("robotNamespace");
02216 while (child_elem)
02217 {
02218 child->ToElement()->RemoveChild(child_elem);
02219 child_elem = child->ToElement()->FirstChildElement("robotNamespace");
02220 }
02221 TiXmlElement* key = new TiXmlElement("robotNamespace");
02222 TiXmlText* val = new TiXmlText(robot_namespace_);
02223 key->LinkEndChild(val);
02224 child->ToElement()->LinkEndChild(key);
02225 }
02226 }
02227 walkChildAddRobotNamespace(child);
02228 child = robot_xml->IterateChildren(child);
02229 }
02230 }
02231
02232 bool GazeboRosApiPlugin::spawnAndConform(TiXmlDocument &gazebo_model_xml, std::string model_name,
02233 gazebo_msgs::SpawnModel::Response &res)
02234 {
02235
02236 std::ostringstream stream;
02237 stream << gazebo_model_xml;
02238 std::string gazebo_model_xml_string = stream.str();
02239 ROS_DEBUG("Gazebo Model XML\n\n%s\n\n ",gazebo_model_xml_string.c_str());
02240
02241
02242 gazebo::msgs::Factory msg;
02243 gazebo::msgs::Init(msg, "spawn_model");
02244 msg.set_sdf( gazebo_model_xml_string );
02245
02246
02247
02248
02249
02250 gazebo::msgs::Request *entity_info_msg = gazebo::msgs::CreateRequest("entity_info", model_name);
02251 request_pub_->Publish(*entity_info_msg,true);
02252
02253
02254 gazebo::physics::ModelPtr model = world_->GetModel(model_name);
02255 if (model)
02256 {
02257 ROS_ERROR("SpawnModel: Failure - model name %s already exist.",model_name.c_str());
02258 res.success = false;
02259 res.status_message = "SpawnModel: Failure - model already exists.";
02260 return true;
02261 }
02262
02263
02264 factory_pub_->Publish(msg);
02267
02269 ros::Duration model_spawn_timeout(10.0);
02270 ros::Time timeout = ros::Time::now() + model_spawn_timeout;
02271
02272 while (ros::ok())
02273 {
02274 if (ros::Time::now() > timeout)
02275 {
02276 res.success = false;
02277 res.status_message = std::string("SpawnModel: Model pushed to spawn queue, but spawn service")
02278 + std::string(" timed out waiting for model to appear in simulation under the name ")
02279 + model_name;
02280 return true;
02281 }
02282
02283 {
02284
02285 if (world_->GetModel(model_name))
02286 break;
02287 }
02288
02289 ROS_DEBUG_STREAM_ONCE_NAMED("api_plugin","Waiting for " << timeout - ros::Time::now()
02290 << " for model " << model_name << " to spawn");
02291
02292 usleep(2000);
02293 }
02294
02295
02296 res.success = true;
02297 res.status_message = std::string("SpawnModel: Successfully spawned model");
02298 return true;
02299 }
02300
02301
02302 GZ_REGISTER_SYSTEM_PLUGIN(GazeboRosApiPlugin)
02303 }
02304