gazebo_ros_api_plugin.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2013 Open Source Robotics Foundation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  *
00016 */
00017 
00018 /* Desc: External interfaces for Gazebo
00019  * Author: Nate Koenig, John Hsu, Dave Coleman
00020  * Date: Jun 10 2013
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   // Unload the sigint event
00046   gazebo::event::Events::DisconnectSigInt(sigint_event_);
00047   ROS_DEBUG_STREAM_NAMED("api_plugin","After sigint_event unload");
00048 
00049   // Don't attempt to unload this plugin if it was never loaded in the Load() function
00050   if(!plugin_loaded_)
00051   {
00052     ROS_DEBUG_STREAM_NAMED("api_plugin","Deconstructor skipped because never loaded");
00053     return;
00054   }
00055 
00056   // Disconnect slots
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) // disconnect if there are subscribers on exit
00064     gazebo::event::Events::DisconnectWorldUpdateBegin(pub_link_states_event_);
00065   if (pub_model_states_connection_count_ > 0) // disconnect if there are subscribers on exit
00066     gazebo::event::Events::DisconnectWorldUpdateBegin(pub_model_states_event_);
00067   ROS_DEBUG_STREAM_NAMED("api_plugin","Disconnected World Updates");
00068 
00069   // Stop the multi threaded ROS spinner
00070   async_ros_spin_->stop();
00071   ROS_DEBUG_STREAM_NAMED("api_plugin","Async ROS Spin Stopped");
00072 
00073   // Shutdown the ROS node
00074   nh_->shutdown();
00075   ROS_DEBUG_STREAM_NAMED("api_plugin","Node Handle Shutdown");
00076 
00077   // Shutdown ROS queue
00078   gazebo_callback_queue_thread_->join();
00079   ROS_DEBUG_STREAM_NAMED("api_plugin","Callback Queue Joined");
00080 
00081   // Physics Dynamic Reconfigure
00082   physics_reconfigure_thread_->join();
00083   ROS_DEBUG_STREAM_NAMED("api_plugin","Physics reconfigure joined");
00084 
00085   // Delete Force and Wrench Jobs
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   // connect to sigint event
00117   sigint_event_ = gazebo::event::Events::ConnectSigInt(boost::bind(&GazeboRosApiPlugin::shutdownSignal,this));
00118 
00119   // setup ros related
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   // check if the ros master is available - required
00126   while(!ros::master::check())
00127   {
00128     ROS_WARN_STREAM_NAMED("api_plugin","No ROS master - start roscore to continue...");
00129     // wait 0.5 second
00130     usleep(500*1000); // can't use ROS Time here b/c node handle is not yet initialized
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("~")); // advertise topics and services in this node's namespace
00140 
00141   // Built-in multi-threaded ROS spinning
00142   async_ros_spin_.reset(new ros::AsyncSpinner(0)); // will use a thread for each CPU core
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   // below needs the world to be created first
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   // make sure things are only called once
00161   lock_.lock();
00162   if (world_created_)
00163   {
00164     lock_.unlock();
00165     return;
00166   }
00167 
00168   // set flag to true and load this plugin
00169   world_created_ = true;
00170   lock_.unlock();
00171 
00172   world_ = gazebo::physics::get_world(world_name);
00173   if (!world_)
00174   {
00175     //ROS_ERROR("world name: [%s]",world->GetName().c_str());
00176     // connect helper function to signal for scheduling torque/forces, etc
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   //stat_sub_ = gazebonode_->Subscribe("~/world_stats", &GazeboRosApiPlugin::publishSimTime, this); // TODO: does not work in server plugin?
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   // reset topic connection counts
00189   pub_link_states_connection_count_ = 0;
00190   pub_model_states_connection_count_ = 0;
00191 
00193   advertiseServices();
00194 
00195   // hooks for applying forces, publishing simtime on /clock
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   // publish clock for simulated ros time
00218   pub_clock_ = nh_->advertise<rosgraph_msgs::Clock>("/clock",10);
00219 
00220   // Advertise spawn services on the custom queue - DEPRECATED IN HYDRO
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   // Advertise spawn services on the custom queue
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   // Advertise spawn services on the custom queue
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   // Advertise delete services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // publish complete link states in world frame
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   // publish complete model states in world frame
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise topic on custom queue
00392   // topic callback version for set_link_state
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   // topic callback version for set_model_state
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // Advertise more services on the custom queue
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   // set param for use_sim_time if not set by user already
00482   nh_->setParam("/use_sim_time", true);
00483 
00484   // todo: contemplate setting environment variable ROBOT=sim here???
00485 
00486 }
00487 
00488 void GazeboRosApiPlugin::onLinkStatesConnect()
00489 {
00490   pub_link_states_connection_count_++;
00491   if (pub_link_states_connection_count_ == 1) // connect on first subscriber
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) // connect on first subscriber
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) // disconnect with no subscribers
00506   {
00507     gazebo::event::Events::DisconnectWorldUpdateBegin(pub_link_states_event_);
00508     if (pub_link_states_connection_count_ < 0) // should not be possible
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) // disconnect with no subscribers
00517   {
00518     gazebo::event::Events::DisconnectWorldUpdateBegin(pub_model_states_event_);
00519     if (pub_model_states_connection_count_ < 0) // should not be possible
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   // get name space for the corresponding model plugins
00528   robot_namespace_ = req.robot_namespace;
00529 
00530   // incoming robot model string
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   // Now, replace package://xxx with the full path to the package
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       //ROS_DEBUG(" pos %d %d",(int)pos1, (int)pos2);
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       //ROS_DEBUG("package name [%s]", package_name.c_str());
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   // ROS_DEBUG("Model XML\n\n%s\n\n ",model_xml.c_str());
00584 
00585   req.model_xml = model_xml;
00586 
00587   // Model is now considered convert to SDF
00588   return spawnSDFModel(req,res);
00589 }
00590 
00591 // DEPRECATED IN HYDRO
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   // incoming robot name
00603   std::string model_name = req.model_name;
00604 
00605   // get name space for the corresponding model plugins
00606   robot_namespace_ = req.robot_namespace;
00607 
00608   // get initial pose of model
00609   gazebo::math::Vector3 initial_xyz(req.initial_pose.position.x,req.initial_pose.position.y,req.initial_pose.position.z);
00610   // get initial roll pitch yaw (fixed frame transform)
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   // refernce frame for initial pose definition, modify initial pose if defined
00614   gazebo::physics::LinkPtr frame = boost::dynamic_pointer_cast<gazebo::physics::Link>(world_->GetEntity(req.reference_frame));
00615   if (frame)
00616   {
00617     // convert to relative pose
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   // incoming robot model string
00637   std::string model_xml = req.model_xml;
00638 
00639   // store resulting Gazebo Model XML to be sent to spawn queue
00640   // get incoming string containg either an URDF or a Gazebo Model XML
00641   // grab from parameter server if necessary convert to SDF if necessary
00642   stripXmlDeclaration(model_xml);
00643 
00644   // put string in TiXmlDocument for manipulation
00645   TiXmlDocument gazebo_model_xml;
00646   gazebo_model_xml.Parse(model_xml.c_str());
00647 
00648   // optional model manipulations: update initial pose && replace model name
00649   if (isSDF(model_xml))
00650   {
00651     updateSDFAttributes(gazebo_model_xml, model_name, initial_xyz, initial_q);
00652 
00653     // Walk recursively through the entire SDF, locate plugin tags and
00654     // add robotNamespace as a child with the correct namespace
00655     if (!this->robot_namespace_.empty())
00656     {
00657       // Get root element for SDF
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     // Walk recursively through the entire URDF, locate plugin tags and
00677     // add robotNamespace as a child with the correct namespace
00678     if (!this->robot_namespace_.empty())
00679     {
00680       // Get root element for URDF
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   // do spawning check if spawn worked, return response
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   // clear forces, etc for the body in question
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   // delete wrench jobs on bodies
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       // look for it in jobs, delete body wrench jobs
00724       clearBodyWrenches(body->GetScopedName());
00725     }
00726   }
00727 
00728   // delete force jobs on joints
00729   gazebo::physics::Joint_V joints = model->GetJoints();
00730   for (unsigned int i=0;i< joints.size(); i++)
00731   {
00732     // look for it in jobs, delete joint force jobs
00733     clearJointForces(joints[i]->GetName());
00734   }
00735 
00736   // send delete model request
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   // wait and verify that model is deleted
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       //boost::recursive_mutex::scoped_lock lock(*world->GetMRMutex());
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   // set result
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     // get model pose
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     // get model twist
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       // convert to relative pose
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       // convert to relative rates
00798       gazebo::math::Vector3 frame_vpos = frame->GetWorldLinearVel(); // get velocity in gazebo frame
00799       gazebo::math::Vector3 frame_veul = frame->GetWorldAngularVel(); // get velocity in gazebo frame
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     // fill in response
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     // get model parent name
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     // get list of child bodies, geoms
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         // get list of geoms
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     // get list of joints
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     // get children model names
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     // is model static
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; //world->GetRenderEngineEnabled();
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(); // to be added to gazebo
00936     //res.damping.push_back(joint->GetDamping(0));
00937 
00938     res.position.clear(); // use GetAngle(i)
00939     res.position.push_back(joint->GetAngle(0).Radian());
00940 
00941     res.rate.clear(); // use GetVelocity(i)
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; // @todo: gazebo do not support rotated inertia yet
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   // get body pose
01004   gazebo::math::Pose body_pose = body->GetWorldPose();
01005   // Get inertial rates
01006   gazebo::math::Vector3 body_vpos = body->GetWorldLinearVel(); // get velocity in gazebo frame
01007   gazebo::math::Vector3 body_veul = body->GetWorldAngularVel(); // get velocity in gazebo frame
01008 
01009   if (frame)
01010   {
01011     // convert to relative pose
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     // convert to relative rates
01018     gazebo::math::Vector3 frame_vpos = frame->GetWorldLinearVel(); // get velocity in gazebo frame
01019     gazebo::math::Vector3 frame_veul = frame->GetWorldAngularVel(); // get velocity in gazebo frame
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     // @todo: FIXME: add inertia matrix rotation to Gazebo
01070     // mass.SetInertiaRotation(gazebo::math::Quaternionion(req.com.orientation.w,res.com.orientation.x,req.com.orientation.y req.com.orientation.z));
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     // @todo: mass change unverified
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   // pause simulation if requested
01086   bool is_paused = world_->IsPaused();
01087   world_->SetPaused(true);
01088 
01089   // supported updates
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     // stuff only works in ODE right now
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   // supported updates
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   // stuff only works in ODE right now
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(); // eliminates invalid rotation (0, 0, 0, 0)
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(); // - myBody->GetCoMPose();
01285       gazebo::math::Vector3 frame_pos = frame_pose.pos;
01286       gazebo::math::Quaternion frame_rot = frame_pose.rot;
01287 
01288       //std::cout << " debug : " << relative_entity->GetName() << " : " << frame_pose << " : " << target_pose << std::endl;
01289       //target_pose = frame_pose + target_pose; // seems buggy, use my own
01290       target_pose.pos = model->GetWorldPose().pos + frame_rot.RotateVector(target_pos);
01291       target_pose.rot = frame_rot * target_pose.rot;
01292 
01293       // Velocities should be commanded in the requested reference
01294       // frame, so we need to translate them to the world frame
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     //ROS_ERROR("target state: %f %f %f",target_pose.pos.x,target_pose.pos.y,target_pose.pos.z);
01313     bool is_paused = world_->IsPaused();
01314     world_->SetPaused(true);
01315     model->SetWorldPose(target_pose);
01316     world_->SetPaused(is_paused);
01317     //gazebo::math::Pose p3d = model->GetWorldPose();
01318     //ROS_ERROR("model updated state: %f %f %f",p3d.pos.x,p3d.pos.y,p3d.pos.z);
01319 
01320     // set model velocity
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   /*bool success =*/ 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         // found one, search through again
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       //ROS_ERROR("search %s %s",(*iter)->body->GetScopedName().c_str(), body_name.c_str());
01436       if ((*iter)->body->GetScopedName() == body_name)
01437       {
01438         // found one, search through again
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   // search for model with name
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     // make the service call to pause gazebo
01474     bool is_paused = world_->IsPaused();
01475     if (!is_paused) world_->SetPaused(true);
01476 
01477     gazebo_model->SetJointPositions(joint_position_map);
01478 
01479     // resume paused state before this call
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   // get reference frame (body/model(link)) pose and
01509   // transform target pose to absolute world frame
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(); // - myBody->GetCoMPose();
01519     gazebo::math::Vector3 frame_pos = frame_pose.pos;
01520     gazebo::math::Quaternion frame_rot = frame_pose.rot;
01521 
01522     //std::cout << " debug : " << frame->GetName() << " : " << frame_pose << " : " << target_pose << std::endl;
01523     //target_pose = frame_pose + target_pose; // seems buggy, use my own
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   //std::cout << " debug : " << target_pose << std::endl;
01545   //boost::recursive_mutex::scoped_lock lock(*world->GetMRMutex());
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   // set body velocity to desired twist
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   /*bool success = */ 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   // rotate force into target frame
01574   target_force = target_to_reference.rot.RotateVector(reference_force);
01575   // rotate torque into target frame
01576   target_torque = target_to_reference.rot.RotateVector(reference_torque);
01577 
01578   // target force is the refence force rotated by the target->reference transform
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   // target wrench
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     // get reference frame (body/model(body)) pose and
01611     // transform target pose to absolute world frame
01612     // @todo: need to modify wrench (target force and torque by frame)
01613     //        transform wrench from reference_point in reference_frame
01614     //        into the reference frame of the body
01615     //        first, translate by reference point to the body frame
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     // FIXME: transfer to inertial frame
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   // apply wrench
01674   // schedule a job to do below at appropriate times:
01675   // body->SetForce(force)
01676   // body->SetTorque(torque)
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   // FIXME: very crude check
01707   TiXmlDocument doc_in;
01708   doc_in.Parse(model_xml.c_str());
01709   if (doc_in.FirstChild("gazebo") ||
01710       doc_in.FirstChild("sdf")) // sdf
01711     return true;
01712   else
01713     return false;
01714 }
01715 
01716 void GazeboRosApiPlugin::wrenchBodySchedulerSlot()
01717 {
01718   // MDMutex locks in case model is getting deleted, don't have to do this if we delete jobs first
01719   // boost::recursive_mutex::scoped_lock lock(*world->GetMDMutex());
01720   lock_.lock();
01721   for (std::vector<GazeboRosApiPlugin::WrenchBodyJob*>::iterator iter=wrench_body_jobs_.begin();iter!=wrench_body_jobs_.end();)
01722   {
01723     // check times and apply wrench if necessary
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) // if body exists
01729         {
01730           (*iter)->body->SetForce((*iter)->force);
01731           (*iter)->body->SetTorque((*iter)->torque);
01732         }
01733         else
01734           (*iter)->duration.fromSec(0.0); // mark for delete
01735       }
01736 
01737     if (ros::Time(world_->GetSimTime().Double()) > (*iter)->start_time+(*iter)->duration &&
01738         (*iter)->duration.toSec() >= 0.0)
01739     {
01740       // remove from queue once expires
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   // MDMutex locks in case model is getting deleted, don't have to do this if we delete jobs first
01753   // boost::recursive_mutex::scoped_lock lock(*world->GetMDMutex());
01754   lock_.lock();
01755   for (std::vector<GazeboRosApiPlugin::ForceJointJob*>::iterator iter=force_joint_jobs_.begin();iter!=force_joint_jobs_.end();)
01756   {
01757     // check times and apply force if necessary
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) // if joint exists
01763           (*iter)->joint->SetForce(0,(*iter)->force);
01764         else
01765           (*iter)->duration.fromSec(0.0); // mark for delete
01766       }
01767 
01768     if (ros::Time(world_->GetSimTime().Double()) > (*iter)->start_time+(*iter)->duration &&
01769         (*iter)->duration.toSec() >= 0.0)
01770     {
01771       // remove from queue once expires
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   //  publish time to ros
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   //  publish time to ros
01795   pub_clock_.publish(ros_time_);
01796 }
01797 
01798 void GazeboRosApiPlugin::publishLinkStates()
01799 {
01800   gazebo_msgs::LinkStates link_states;
01801 
01802   // fill link_states
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(); // - myBody->GetCoMPose();
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   // fill model_states
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(); // - myBody->GetCoMPose();
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     // check for changes
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       // pause simulation if requested
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   // Wait until the rest of this plugin is loaded and the services are being offered
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   // incoming robot model string is a string containing a Gazebo Model XML
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   // This function can handle both regular SDF files and <include> SDFs that are used with the
01986   // Gazebo Model Database
01987 
01988   TiXmlElement* pose_element; // This is used by both reguar and database SDFs
01989 
01990   // Check SDF for requires SDF element
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   // Check SDF for optional model element. May not have one
01999   TiXmlElement* model_tixml = gazebo_tixml->FirstChildElement("model");
02000   if (model_tixml)
02001   {
02002     // Update model name
02003     if (model_tixml->Attribute("name") != NULL)
02004     {
02005       // removing old model name
02006       model_tixml->RemoveAttribute("name");
02007     }
02008     // replace with user specified name
02009     model_tixml->SetAttribute("name",model_name);
02010   }
02011   else
02012   {
02013     // Check SDF for world element
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     // If not <model> element, check SDF for required include element
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     // Check for name element
02029     TiXmlElement* name_tixml = model_tixml->FirstChildElement("name");
02030     if (!name_tixml)
02031     {
02032       // Create the name element
02033       name_tixml = new TiXmlElement("name");
02034       model_tixml->LinkEndChild(name_tixml);
02035     }
02036 
02037     // Set the text within the name element
02038     TiXmlText* text = new TiXmlText(model_name);
02039     name_tixml->LinkEndChild( text );
02040   }
02041 
02042 
02043   // Check for the pose element
02044   pose_element = model_tixml->FirstChildElement("pose");
02045   gazebo::math::Pose model_pose;
02046 
02047   // Create the pose element if it doesn't exist
02048   // Remove it if it exists, since we are inserting a new one
02049   if (pose_element)
02050   {
02051     // save pose_element in math::Pose and remove child
02052     model_pose = this->parsePose(pose_element->GetText());
02053     model_tixml->RemoveChild(pose_element);
02054   }
02055 
02056   // Set and link the pose element after adding initial pose
02057   {
02058     // add pose_element Pose to initial pose
02059     gazebo::math::Pose new_model_pose = model_pose + gazebo::math::Pose(initial_xyz, initial_q);
02060 
02061     // Create the string of 6 numbers
02062     std::ostringstream pose_stream;
02063     gazebo::math::Vector3 model_rpy = new_model_pose.rot.GetAsEuler(); // convert to Euler angles for Gazebo XML
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     // Add value to pose element
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     // replace initial pose of robot
02147     // find first instance of xyz and rpy, replace with initial pose
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     // add xyz, rpy to initial pose
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(); // convert to Euler angles for Gazebo XML
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   // replace model name if one is specified by the user
02190   if (model_tixml)
02191   {
02192     if (model_tixml->Attribute("name") != NULL)
02193     {
02194       // removing old model name
02195       model_tixml->RemoveAttribute("name");
02196     }
02197     // replace with user specified name
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   // push to factory iface
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   // publish to factory topic
02242   gazebo::msgs::Factory msg;
02243   gazebo::msgs::Init(msg, "spawn_model");
02244   msg.set_sdf( gazebo_model_xml_string );
02245 
02246   //ROS_ERROR("attempting to spawn model name [%s] [%s]", model_name.c_str(),gazebo_model_xml_string.c_str());
02247 
02248   // FIXME: should use entity_info or add lock to World::receiveMutex
02249   // looking for Model to see if it exists already
02250   gazebo::msgs::Request *entity_info_msg = gazebo::msgs::CreateRequest("entity_info", model_name);
02251   request_pub_->Publish(*entity_info_msg,true);
02252   // todo: should wait for response response_sub_, check to see that if _msg->response == "nonexistant"
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   // Publish the factory message
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       //boost::recursive_mutex::scoped_lock lock(*world->GetMRMutex());
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   // set result
02296   res.success = true;
02297   res.status_message = std::string("SpawnModel: Successfully spawned model");
02298   return true;
02299 }
02300 
02301 // Register this plugin with the simulator
02302 GZ_REGISTER_SYSTEM_PLUGIN(GazeboRosApiPlugin)
02303 }
02304 


gazebo_ros
Author(s): John Hsu, Nate Koenig, Dave Coleman
autogenerated on Thu Jun 6 2019 18:41:02