gazebo_ros_api_plugin.cpp
Go to the documentation of this file.
00001 /*
00002  *  Gazebo - Outdoor Multi-Robot Simulator
00003  *  Copyright (C) 2003
00004  *     Nate Koenig & Andrew Howard
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 /* Desc: External interfaces for Gazebo
00023  * Author: John Hsu adapted original gazebo main.cc by Nate Koenig
00024  * Date: 25 Apr 2010
00025  * SVN: $Id: main.cc 8598 2010-03-22 21:59:24Z hsujohnhsu $
00026  */
00027 
00028 #include "common/Events.hh"
00029 #include <gazebo/gazebo_ros_api_plugin.h>
00030 
00031 namespace gazebo
00032 {
00033 
00034     GazeboRosApiPlugin::GazeboRosApiPlugin()
00035     {
00036       this->robot_namespace_.clear();
00037       this->world_created_ = false;
00038     }
00039 
00040     GazeboRosApiPlugin::~GazeboRosApiPlugin()
00041     {
00042       // disconnect slots
00043       gazebo::event::Events::DisconnectWorldUpdateStart(this->wrench_update_event_);
00044       gazebo::event::Events::DisconnectWorldUpdateStart(this->force_update_event_);
00045       gazebo::event::Events::DisconnectWorldUpdateStart(this->time_update_event_);
00046 
00047       if (this->pub_link_states_connection_count_ > 0) // disconnect if there are subscribers on exit
00048         gazebo::event::Events::DisconnectWorldUpdateStart(this->pub_link_states_event_);
00049       if (this->pub_model_states_connection_count_ > 0) // disconnect if there are subscribers on exit
00050         gazebo::event::Events::DisconnectWorldUpdateStart(this->pub_model_states_event_);
00051 
00052       // shutdown ros
00053       this->rosnode_->shutdown();
00054       delete this->rosnode_;
00055 
00056       // shutdown ros queue
00057       this->gazebo_callback_queue_thread_->join();
00058       delete this->gazebo_callback_queue_thread_;
00059 
00060       this->physics_reconfigure_thread_->join();
00061       delete this->physics_reconfigure_thread_;
00062 
00063       this->ros_spin_thread_->join();
00064       delete this->ros_spin_thread_;
00065 
00066       /* Delete Force and Wrench Jobs */
00067       this->lock_.lock();
00068       for (std::vector<GazeboRosApiPlugin::ForceJointJob*>::iterator iter=this->force_joint_jobs.begin();iter!=this->force_joint_jobs.end();)
00069       {
00070         delete (*iter);
00071         this->force_joint_jobs.erase(iter);
00072       }
00073       for (std::vector<GazeboRosApiPlugin::WrenchBodyJob*>::iterator iter=this->wrench_body_jobs.begin();iter!=this->wrench_body_jobs.end();)
00074       {
00075         delete (*iter);
00076         this->wrench_body_jobs.erase(iter);
00077       }
00078       this->lock_.unlock();
00079     }
00080 
00081     void GazeboRosApiPlugin::Load(int argc, char** argv)
00082     {
00083       // setup ros related
00084       if (!ros::isInitialized())
00085         ros::init(argc,argv,"gazebo",ros::init_options::NoSigintHandler);
00086       else
00087         ROS_ERROR("Something other than this gazebo_ros_api plugin started ros::init(...), command line arguments may not be parsed properly.");
00088 
00089       this->rosnode_ = new ros::NodeHandle("~");
00090 
00092       gazebo_callback_queue_thread_ = new boost::thread( &GazeboRosApiPlugin::gazeboQueueThread,this );
00093 
00095       this->physics_reconfigure_thread_ = new boost::thread(boost::bind(&GazeboRosApiPlugin::PhysicsReconfigureNode, this));
00096       this->physics_reconfigure_initialized_ = false;
00097 
00098       // below needs the world to be created first
00099       this->load_gazebo_ros_api_plugin_event_ = gazebo::event::Events::ConnectWorldCreated(boost::bind(&GazeboRosApiPlugin::LoadGazeboRosApiPlugin,this,_1));
00100     }
00101 
00102     void GazeboRosApiPlugin::LoadGazeboRosApiPlugin(std::string _worldName)
00103     {
00104       // make sure things are only called once
00105       gazebo::event::Events::DisconnectWorldCreated(this->load_gazebo_ros_api_plugin_event_);
00106       this->lock_.lock();
00107       if (this->world_created_)
00108       {
00109         this->lock_.unlock();
00110         return;
00111       }
00112 
00113       // set flag to true and load this plugin
00114       this->world_created_ = true;
00115       this->lock_.unlock();
00116 
00117 
00118       this->world = gazebo::physics::get_world(_worldName);
00119       if (!this->world)
00120       {
00121         //ROS_ERROR("world name: [%s]",this->world->GetName().c_str());
00122         // connect helper function to signal for scheduling torque/forces, etc
00123         ROS_FATAL("cannot load gazebo ros api server plugin, physics::get_world() fails to return world");
00124         return;
00125       }
00126 
00127       this->gazebonode_ = gazebo::transport::NodePtr(new gazebo::transport::Node());
00128       this->gazebonode_->Init(_worldName);
00129       //this->stat_sub_ = this->gazebonode_->Subscribe("~/world_stats", &GazeboRosApiPlugin::publishSimTime, this); // TODO: does not work in server plugin?
00130       this->factory_pub_ = this->gazebonode_->Advertise<gazebo::msgs::Factory>("~/factory");
00131       this->request_pub_ = this->gazebonode_->Advertise<gazebo::msgs::Request>("~/request");
00132       this->response_sub_ = this->gazebonode_->Subscribe("~/response",&GazeboRosApiPlugin::OnResponse, this);
00133 
00134       // reset topic connection counts
00135       this->pub_link_states_connection_count_ = 0;
00136       this->pub_model_states_connection_count_ = 0;
00137 
00139       this->AdvertiseServices();
00140 
00141       // hooks for applying forces, publishing simtime on /clock
00142       this->wrench_update_event_ = gazebo::event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboRosApiPlugin::wrenchBodySchedulerSlot,this));
00143       this->force_update_event_  = gazebo::event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboRosApiPlugin::forceJointSchedulerSlot,this));
00144       this->time_update_event_   = gazebo::event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboRosApiPlugin::publishSimTime,this));
00145 
00146       // spin ros, is this needed?
00147       this->ros_spin_thread_ = new boost::thread(boost::bind(&GazeboRosApiPlugin::spin, this));
00148 
00149     }
00150 
00151     void GazeboRosApiPlugin::OnResponse(ConstResponsePtr &_response)
00152     {
00153       
00154     }
00155 
00157     void GazeboRosApiPlugin::gazeboQueueThread()
00158     {
00159       ROS_DEBUG_STREAM("Callback thread id=" << boost::this_thread::get_id());
00160       static const double timeout = 0.001;
00161       while (this->rosnode_->ok())
00162         this->gazebo_queue_.callAvailable(ros::WallDuration(timeout));
00163     }
00164 
00166     void GazeboRosApiPlugin::AdvertiseServices()
00167     {
00168       // publish clock for simulated ros time
00169       pub_clock_ = this->rosnode_->advertise<rosgraph_msgs::Clock>("/clock",10);
00170 
00171       // Advertise spawn services on the custom queue
00172       std::string spawn_gazebo_model_service_name("spawn_gazebo_model");
00173       ros::AdvertiseServiceOptions spawn_gazebo_model_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SpawnModel>(
00174           spawn_gazebo_model_service_name,boost::bind(&GazeboRosApiPlugin::spawnGazeboModel,this,_1,_2),
00175           ros::VoidPtr(), &this->gazebo_queue_);
00176       spawn_urdf_gazebo_service_ = this->rosnode_->advertiseService(spawn_gazebo_model_aso);
00177 
00178       // Advertise spawn services on the custom queue
00179       std::string spawn_urdf_model_service_name("spawn_urdf_model");
00180       ros::AdvertiseServiceOptions spawn_urdf_model_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SpawnModel>(
00181           spawn_urdf_model_service_name,boost::bind(&GazeboRosApiPlugin::spawnURDFModel,this,_1,_2),
00182           ros::VoidPtr(), &this->gazebo_queue_);
00183       spawn_urdf_model_service_ = this->rosnode_->advertiseService(spawn_urdf_model_aso);
00184 
00185       // Advertise delete services on the custom queue
00186       std::string delete_model_service_name("delete_model");
00187       ros::AdvertiseServiceOptions delete_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::DeleteModel>(
00188           delete_model_service_name,boost::bind(&GazeboRosApiPlugin::deleteModel,this,_1,_2),
00189           ros::VoidPtr(), &this->gazebo_queue_);
00190       delete_model_service_ = this->rosnode_->advertiseService(delete_aso);
00191 
00192       // Advertise more services on the custom queue
00193       std::string get_model_properties_service_name("get_model_properties");
00194       ros::AdvertiseServiceOptions get_model_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetModelProperties>(
00195           get_model_properties_service_name,boost::bind(&GazeboRosApiPlugin::getModelProperties,this,_1,_2),
00196           ros::VoidPtr(), &this->gazebo_queue_);
00197       get_model_properties_service_ = this->rosnode_->advertiseService(get_model_properties_aso);
00198 
00199       // Advertise more services on the custom queue
00200       std::string get_model_state_service_name("get_model_state");
00201       ros::AdvertiseServiceOptions get_model_state_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetModelState>(
00202           get_model_state_service_name,boost::bind(&GazeboRosApiPlugin::getModelState,this,_1,_2),
00203           ros::VoidPtr(), &this->gazebo_queue_);
00204       get_model_state_service_ = this->rosnode_->advertiseService(get_model_state_aso);
00205 
00206       // Advertise more services on the custom queue
00207       std::string get_world_properties_service_name("get_world_properties");
00208       ros::AdvertiseServiceOptions get_world_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetWorldProperties>(
00209           get_world_properties_service_name,boost::bind(&GazeboRosApiPlugin::getWorldProperties,this,_1,_2),
00210           ros::VoidPtr(), &this->gazebo_queue_);
00211       get_world_properties_service_ = this->rosnode_->advertiseService(get_world_properties_aso);
00212 
00213       // Advertise more services on the custom queue
00214       std::string get_joint_properties_service_name("get_joint_properties");
00215       ros::AdvertiseServiceOptions get_joint_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetJointProperties>(
00216           get_joint_properties_service_name,boost::bind(&GazeboRosApiPlugin::getJointProperties,this,_1,_2),
00217           ros::VoidPtr(), &this->gazebo_queue_);
00218       get_joint_properties_service_ = this->rosnode_->advertiseService(get_joint_properties_aso);
00219 
00220       // Advertise more services on the custom queue
00221       std::string get_link_properties_service_name("get_link_properties");
00222       ros::AdvertiseServiceOptions get_link_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetLinkProperties>(
00223           get_link_properties_service_name,boost::bind(&GazeboRosApiPlugin::getLinkProperties,this,_1,_2),
00224           ros::VoidPtr(), &this->gazebo_queue_);
00225       get_link_properties_service_ = this->rosnode_->advertiseService(get_link_properties_aso);
00226 
00227       // Advertise more services on the custom queue
00228       std::string get_link_state_service_name("get_link_state");
00229       ros::AdvertiseServiceOptions get_link_state_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetLinkState>(
00230           get_link_state_service_name,boost::bind(&GazeboRosApiPlugin::getLinkState,this,_1,_2),
00231           ros::VoidPtr(), &this->gazebo_queue_);
00232       get_link_state_service_ = this->rosnode_->advertiseService(get_link_state_aso);
00233 
00234       // Advertise more services on the custom queue
00235       std::string set_link_properties_service_name("set_link_properties");
00236       ros::AdvertiseServiceOptions set_link_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SetLinkProperties>(
00237           set_link_properties_service_name,boost::bind(&GazeboRosApiPlugin::setLinkProperties,this,_1,_2),
00238           ros::VoidPtr(), &this->gazebo_queue_);
00239       set_link_properties_service_ = this->rosnode_->advertiseService(set_link_properties_aso);
00240 
00241       // Advertise more services on the custom queue
00242       std::string set_physics_properties_service_name("set_physics_properties");
00243       ros::AdvertiseServiceOptions set_physics_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SetPhysicsProperties>(
00244           set_physics_properties_service_name,boost::bind(&GazeboRosApiPlugin::setPhysicsProperties,this,_1,_2),
00245           ros::VoidPtr(), &this->gazebo_queue_);
00246       set_physics_properties_service_ = this->rosnode_->advertiseService(set_physics_properties_aso);
00247 
00248       // Advertise more services on the custom queue
00249       std::string get_physics_properties_service_name("get_physics_properties");
00250       ros::AdvertiseServiceOptions get_physics_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetPhysicsProperties>(
00251           get_physics_properties_service_name,boost::bind(&GazeboRosApiPlugin::getPhysicsProperties,this,_1,_2),
00252           ros::VoidPtr(), &this->gazebo_queue_);
00253       get_physics_properties_service_ = this->rosnode_->advertiseService(get_physics_properties_aso);
00254 
00255       // Advertise more services on the custom queue
00256       std::string apply_body_wrench_service_name("apply_body_wrench");
00257       ros::AdvertiseServiceOptions apply_body_wrench_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::ApplyBodyWrench>(
00258           apply_body_wrench_service_name,boost::bind(&GazeboRosApiPlugin::applyBodyWrench,this,_1,_2),
00259           ros::VoidPtr(), &this->gazebo_queue_);
00260       apply_body_wrench_service_ = this->rosnode_->advertiseService(apply_body_wrench_aso);
00261 
00262       // Advertise more services on the custom queue
00263       std::string set_model_state_service_name("set_model_state");
00264       ros::AdvertiseServiceOptions set_model_state_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SetModelState>(
00265           set_model_state_service_name,boost::bind(&GazeboRosApiPlugin::setModelState,this,_1,_2),
00266           ros::VoidPtr(), &this->gazebo_queue_);
00267       set_model_state_service_ = this->rosnode_->advertiseService(set_model_state_aso);
00268 
00269       // Advertise more services on the custom queue
00270       std::string apply_joint_effort_service_name("apply_joint_effort");
00271       ros::AdvertiseServiceOptions apply_joint_effort_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::ApplyJointEffort>(
00272           apply_joint_effort_service_name,boost::bind(&GazeboRosApiPlugin::applyJointEffort,this,_1,_2),
00273           ros::VoidPtr(), &this->gazebo_queue_);
00274       apply_joint_effort_service_ = this->rosnode_->advertiseService(apply_joint_effort_aso);
00275 
00276       // Advertise more services on the custom queue
00277       std::string set_joint_properties_service_name("set_joint_properties");
00278       ros::AdvertiseServiceOptions set_joint_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SetJointProperties>(
00279           set_joint_properties_service_name,boost::bind(&GazeboRosApiPlugin::setJointProperties,this,_1,_2),
00280           ros::VoidPtr(), &this->gazebo_queue_);
00281       set_joint_properties_service_ = this->rosnode_->advertiseService(set_joint_properties_aso);
00282 
00283       // Advertise more services on the custom queue
00284       std::string set_model_configuration_service_name("set_model_configuration");
00285       ros::AdvertiseServiceOptions set_model_configuration_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SetModelConfiguration>(
00286           set_model_configuration_service_name,boost::bind(&GazeboRosApiPlugin::setModelConfiguration,this,_1,_2),
00287           ros::VoidPtr(), &this->gazebo_queue_);
00288       set_model_configuration_service_ = this->rosnode_->advertiseService(set_model_configuration_aso);
00289 
00290       // Advertise more services on the custom queue
00291       std::string set_link_state_service_name("set_link_state");
00292       ros::AdvertiseServiceOptions set_link_state_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SetLinkState>(
00293           set_link_state_service_name,boost::bind(&GazeboRosApiPlugin::setLinkState,this,_1,_2),
00294           ros::VoidPtr(), &this->gazebo_queue_);
00295       set_link_state_service_ = this->rosnode_->advertiseService(set_link_state_aso);
00296 
00297       // Advertise more services on the custom queue
00298       std::string reset_simulation_service_name("reset_simulation");
00299       ros::AdvertiseServiceOptions reset_simulation_aso = ros::AdvertiseServiceOptions::create<std_srvs::Empty>(
00300           reset_simulation_service_name,boost::bind(&GazeboRosApiPlugin::resetSimulation,this,_1,_2),
00301           ros::VoidPtr(), &this->gazebo_queue_);
00302       reset_simulation_service_ = this->rosnode_->advertiseService(reset_simulation_aso);
00303 
00304       // Advertise more services on the custom queue
00305       std::string reset_world_service_name("reset_world");
00306       ros::AdvertiseServiceOptions reset_world_aso = ros::AdvertiseServiceOptions::create<std_srvs::Empty>(
00307           reset_world_service_name,boost::bind(&GazeboRosApiPlugin::resetWorld,this,_1,_2),
00308           ros::VoidPtr(), &this->gazebo_queue_);
00309       reset_world_service_ = this->rosnode_->advertiseService(reset_world_aso);
00310 
00311       // Advertise more services on the custom queue
00312       std::string pause_physics_service_name("pause_physics");
00313       ros::AdvertiseServiceOptions pause_physics_aso = ros::AdvertiseServiceOptions::create<std_srvs::Empty>(
00314           pause_physics_service_name,boost::bind(&GazeboRosApiPlugin::pausePhysics,this,_1,_2),
00315           ros::VoidPtr(), &this->gazebo_queue_);
00316       pause_physics_service_ = this->rosnode_->advertiseService(pause_physics_aso);
00317 
00318       // Advertise more services on the custom queue
00319       std::string unpause_physics_service_name("unpause_physics");
00320       ros::AdvertiseServiceOptions unpause_physics_aso = ros::AdvertiseServiceOptions::create<std_srvs::Empty>(
00321           unpause_physics_service_name,boost::bind(&GazeboRosApiPlugin::unpausePhysics,this,_1,_2),
00322           ros::VoidPtr(), &this->gazebo_queue_);
00323       unpause_physics_service_ = this->rosnode_->advertiseService(unpause_physics_aso);
00324 
00325       // Advertise more services on the custom queue
00326       std::string clear_joint_forces_service_name("clear_joint_forces");
00327       ros::AdvertiseServiceOptions clear_joint_forces_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::JointRequest>(
00328           clear_joint_forces_service_name,boost::bind(&GazeboRosApiPlugin::clearJointForces,this,_1,_2),
00329           ros::VoidPtr(), &this->gazebo_queue_);
00330       clear_joint_forces_service_ = this->rosnode_->advertiseService(clear_joint_forces_aso);
00331 
00332       // Advertise more services on the custom queue
00333       std::string clear_body_wrenches_service_name("clear_body_wrenches");
00334       ros::AdvertiseServiceOptions clear_body_wrenches_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::BodyRequest>(
00335           clear_body_wrenches_service_name,boost::bind(&GazeboRosApiPlugin::clearBodyWrenches,this,_1,_2),
00336           ros::VoidPtr(), &this->gazebo_queue_);
00337       clear_body_wrenches_service_ = this->rosnode_->advertiseService(clear_body_wrenches_aso);
00338 
00339       // Advertise topic on custom queue
00340       // topic callback version for set_link_state
00341       ros::SubscribeOptions link_state_so = ros::SubscribeOptions::create<gazebo_msgs::LinkState>(
00342         "set_link_state",10, boost::bind( &GazeboRosApiPlugin::updateLinkState,this,_1),
00343         ros::VoidPtr(), &this->gazebo_queue_);
00344       set_link_state_topic_ = this->rosnode_->subscribe(link_state_so);
00345 
00346       // topic callback version for set_model_state
00347       ros::SubscribeOptions model_state_so = ros::SubscribeOptions::create<gazebo_msgs::ModelState>(
00348         "set_model_state",10, boost::bind( &GazeboRosApiPlugin::updateModelState,this,_1),
00349         ros::VoidPtr(), &this->gazebo_queue_);
00350       set_model_state_topic_ = this->rosnode_->subscribe(model_state_so);
00351 
00352       // publish complete link states in world frame
00353       ros::AdvertiseOptions pub_link_states_ao = ros::AdvertiseOptions::create<gazebo_msgs::LinkStates>(
00354         "link_states",10,
00355         boost::bind(&GazeboRosApiPlugin::onLinkStatesConnect,this),
00356         boost::bind(&GazeboRosApiPlugin::onLinkStatesDisconnect,this), ros::VoidPtr(), &this->gazebo_queue_);
00357       pub_link_states_ = this->rosnode_->advertise(pub_link_states_ao);
00358 
00359       // publish complete model states in world frame
00360       ros::AdvertiseOptions pub_model_states_ao = ros::AdvertiseOptions::create<gazebo_msgs::ModelStates>(
00361         "model_states",10,
00362         boost::bind(&GazeboRosApiPlugin::onModelStatesConnect,this),
00363         boost::bind(&GazeboRosApiPlugin::onModelStatesDisconnect,this), ros::VoidPtr(), &this->gazebo_queue_);
00364       pub_model_states_ = this->rosnode_->advertise(pub_model_states_ao);
00365 
00366       // set param for use_sim_time if not set by user alread
00367       this->rosnode_->setParam("/use_sim_time", true);
00368 
00369       // todo: contemplate setting environment variable ROBOT=sim here???
00370 
00371     }
00372 
00373     void GazeboRosApiPlugin::onLinkStatesConnect()
00374     {
00375       this->pub_link_states_connection_count_++;
00376       if (this->pub_link_states_connection_count_ == 1) // connect on first subscriber
00377         this->pub_link_states_event_   = gazebo::event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboRosApiPlugin::publishLinkStates,this));
00378     }
00379     void GazeboRosApiPlugin::onModelStatesConnect()
00380     {
00381       this->pub_model_states_connection_count_++;
00382       if (this->pub_model_states_connection_count_ == 1) // connect on first subscriber
00383         this->pub_model_states_event_   = gazebo::event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboRosApiPlugin::publishModelStates,this));
00384     }
00385     void GazeboRosApiPlugin::onLinkStatesDisconnect()
00386     {
00387       this->pub_link_states_connection_count_--;
00388       if (this->pub_link_states_connection_count_ <= 0) // disconnect with no subscribers
00389       {
00390         gazebo::event::Events::DisconnectWorldUpdateStart(this->pub_link_states_event_);
00391         if (this->pub_link_states_connection_count_ < 0) // should not be possible
00392           ROS_ERROR("one too mandy disconnect from pub_link_states_ in gazebo_ros.cpp? something weird");
00393       }
00394     }
00395     void GazeboRosApiPlugin::onModelStatesDisconnect()
00396     {
00397       this->pub_model_states_connection_count_--;
00398       if (this->pub_model_states_connection_count_ <= 0) // disconnect with no subscribers
00399       {
00400         gazebo::event::Events::DisconnectWorldUpdateStart(this->pub_model_states_event_);
00401         if (this->pub_model_states_connection_count_ < 0) // should not be possible
00402           ROS_ERROR("one too mandy disconnect from pub_model_states_ in gazebo_ros.cpp? something weird");
00403       }
00404     }
00405 
00406     bool GazeboRosApiPlugin::spawnURDFModel(gazebo_msgs::SpawnModel::Request &req,gazebo_msgs::SpawnModel::Response &res)
00407     {
00408       // get name space for the corresponding model plugins
00409       this->robot_namespace_ = req.robot_namespace;
00410 
00411       // incoming robot name
00412       std::string model_name = req.model_name;
00413 
00414       // incoming robot model string
00415       std::string model_xml = req.model_xml;
00416 
00417       if (!this->IsURDF(model_xml))
00418       {
00419         ROS_ERROR("SpawnModel: Failure - model format is not URDF.");
00420         res.success = false;
00421         res.status_message = "SpawnModel: Failure - model format is not URDF.";
00422         return false;
00423       }
00424 
00428       {
00429         std::string open_bracket("<?");
00430         std::string close_bracket("?>");
00431         size_t pos1 = model_xml.find(open_bracket,0);
00432         size_t pos2 = model_xml.find(close_bracket,0);
00433         if (pos1 != std::string::npos && pos2 != std::string::npos)
00434           model_xml.replace(pos1,pos2-pos1+2,std::string(""));
00435       }
00436 
00437 
00438       // Now, replace package://xxx with the full path to the package
00439       {
00440         std::string package_prefix("package://");
00441         size_t pos1 = model_xml.find(package_prefix,0);
00442         while (pos1 != std::string::npos)
00443         {
00444           size_t pos2 = model_xml.find("/", pos1+10);
00445           ROS_DEBUG(" pos %d %d",(int)pos1, (int)pos2);
00446           if (pos2 == std::string::npos || pos1 >= pos2)
00447           {
00448             ROS_ERROR("malformed package name?");
00449             break;
00450           }
00451 
00452           std::string package_name = model_xml.substr(pos1+10,pos2-pos1-10);
00453           ROS_DEBUG("package name [%s]", package_name.c_str());
00454           std::string package_path = ros::package::getPath(package_name);
00455           if (package_path.empty())
00456           {
00457             ROS_FATAL("Package[%s] does not have a path",package_name.c_str());
00458             res.success = false;
00459             res.status_message = std::string("urdf reference package name does not exist: ")+package_name;
00460             return false;
00461           }
00462           ROS_DEBUG("package name [%s] has path [%s]", package_name.c_str(), package_path.c_str());
00463 
00464           model_xml.replace(pos1,(pos2-pos1),package_path);
00465           pos1 = model_xml.find(package_prefix,0);
00466         }
00467       }
00468       // ROS_DEBUG("Model XML\n\n%s\n\n ",model_xml.c_str());
00469 
00470       req.model_xml = model_xml;
00471 
00472       return spawnGazeboModel(req,res);
00473     }
00474 
00475     bool GazeboRosApiPlugin::spawnGazeboModel(gazebo_msgs::SpawnModel::Request &req,gazebo_msgs::SpawnModel::Response &res)
00476     {
00477       // incoming robot name
00478       std::string model_name = req.model_name;
00479 
00480       // get name space for the corresponding model plugins
00481       this->robot_namespace_ = req.robot_namespace;
00482 
00483       // get initial pose of model
00484       gazebo::math::Vector3 initial_xyz(req.initial_pose.position.x,req.initial_pose.position.y,req.initial_pose.position.z);
00485       // get initial roll pitch yaw (fixed frame transform)
00486       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);
00487 
00488       // refernce frame for initial pose definition, modify initial pose if defined
00489       gazebo::physics::LinkPtr frame = boost::shared_dynamic_cast<gazebo::physics::Link>(this->world->GetEntity(req.reference_frame));
00490       if (frame)
00491       {
00492         // convert to relative pose
00493         gazebo::math::Pose frame_pose = frame->GetWorldPose();
00494         initial_xyz = frame_pose.rot.RotateVector(initial_xyz);
00495         initial_xyz += frame_pose.pos;
00496         initial_q *= frame_pose.rot;
00497       }
00498 
00500       else if (req.reference_frame == "" || req.reference_frame == "world" || req.reference_frame == "map" || req.reference_frame == "/map")
00501       {
00502           ROS_DEBUG("SpawnModel: reference_frame is empty/world/map, using inertial frame");
00503       }
00504       else
00505       {
00506         res.success = false;
00507         res.status_message = "SpawnModel: reference reference_frame not found, did you forget to scope the link by model name?";
00508         return false;
00509       }
00510 
00511       // incoming robot model string
00512       std::string model_xml = req.model_xml;
00513 
00514       // store resulting Gazebo Model XML to be sent to spawn queue
00515       // get incoming string containg either an URDF or a Gazebo Model XML
00516       // grab from parameter server if necessary
00517       // convert to Gazebo Model XML if necessary
00518 
00519 
00520       this->stripXmlDeclaration(model_xml);
00521 
00522 
00523       // put string in TiXmlDocument for manipulation
00524       TiXmlDocument gazebo_model_xml;
00525       gazebo_model_xml.Parse(model_xml.c_str());
00526 
00527       // optional model manipulations: update initial pose && replace model name
00528       if (this->IsGazeboModelXML(model_xml))
00529       {
00530         this->updateGazeboXmlModelPose(gazebo_model_xml, initial_xyz, initial_q);
00531         this->updateGazeboXmlName(gazebo_model_xml, model_name);
00534       }
00535       else if (IsSDF(model_xml))
00536       {
00537         this->updateGazeboSDFModelPose(gazebo_model_xml, initial_xyz, initial_q);
00538         this->updateGazeboSDFName(gazebo_model_xml, model_name);
00539         if (!this->robot_namespace_.empty()) {
00540           TiXmlNode* model_tixml = gazebo_model_xml.FirstChild("sdf");
00541           model_tixml = (!model_tixml) ? gazebo_model_xml.FirstChild("gazebo") : model_tixml;
00542           if (model_tixml) {
00543             walkChildAddRobotNamespace(model_tixml);
00544           } else {
00545             ROS_WARN("Unable to add robot namespace to xml");
00546           }
00547         }
00548       }
00549       else if (IsURDF(model_xml))
00550       {
00551         this->updateURDFModelPose(gazebo_model_xml, initial_xyz, initial_q);
00552         this->updateURDFName(gazebo_model_xml, model_name);
00553         if (!this->robot_namespace_.empty()) {
00554           TiXmlNode* model_tixml = gazebo_model_xml.FirstChild("robot");
00555           if (model_tixml) {
00556             walkChildAddRobotNamespace(model_tixml);
00557           } else {
00558             ROS_WARN("Unable to add robot namespace to xml");
00559           }
00560         }
00561       }
00562       else
00563       {
00564         ROS_ERROR("GazeboRosApiPlugin SpawnModel Failure: input xml format not recognized");
00565         res.success = false;
00566         res.status_message = std::string("GazeboRosApiPlugin SpawnModel Failure: input model_xml not Gazebo XML, or cannot be converted to Gazebo XML");
00567         return false;
00568       }
00569 
00570       // do spawning check if spawn worked, return response
00571       return this->spawnAndConform(gazebo_model_xml, model_name, res);
00572 
00573     }
00574 
00577     bool GazeboRosApiPlugin::deleteModel(gazebo_msgs::DeleteModel::Request &req,gazebo_msgs::DeleteModel::Response &res)
00578     {
00579 
00580       // clear forces, etc for the body in question
00581       gazebo::physics::ModelPtr model = this->world->GetModel(req.model_name);
00582       if (!model)
00583       {
00584         ROS_ERROR("DeleteModel: model [%s] does not exist",req.model_name.c_str());
00585         res.success = false;
00586         res.status_message = "DeleteModel: model does not exist";
00587         return false;
00588       }
00589 
00590       // delete wrench jobs on bodies
00591       for (unsigned int i = 0 ; i < model->GetChildCount(); i ++)
00592       {
00593         gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(model->GetChild(i));
00594         if (body)
00595         {
00596           // look for it in jobs, delete body wrench jobs
00597           this->clearBodyWrenches(body->GetScopedName());
00598         }
00599       }
00600 
00601       // delete force jobs on joints
00602       gazebo::physics::Joint_V joints = model->GetJoints();
00603       for (unsigned int i=0;i< joints.size(); i++)
00604       {
00605         // look for it in jobs, delete joint force jobs
00606         this->clearJointForces(joints[i]->GetName());
00607       }
00608 
00609       // clear entity from selection @todo: need to clear links if selected individually
00610       gazebo::event::Events::setSelectedEntity(req.model_name, "normal");
00611       // send delete model request
00612       gazebo::msgs::Request *msg = gazebo::msgs::CreateRequest("entity_delete",req.model_name);
00613       this->request_pub_->Publish(*msg,true);
00614 
00615       ros::Duration model_spawn_timeout(60.0);
00616       ros::Time timeout = ros::Time::now() + model_spawn_timeout;
00617       // wait and verify that model is deleted
00618       while (true)
00619       {
00620         if (ros::Time::now() > timeout)
00621         {
00622           res.success = false;
00623           res.status_message = std::string("DeleteModel: Model pushed to delete queue, but delete service timed out waiting for model to disappear from simulation");
00624           return false;
00625         }
00626         {
00627           //boost::recursive_mutex::scoped_lock lock(*this->world->GetMRMutex());
00628           if (!this->world->GetModel(req.model_name)) break;
00629         }
00630         ROS_DEBUG("Waiting for model deletion (%s)",req.model_name.c_str());
00631         usleep(1000);
00632       }
00633 
00634       // set result
00635       res.success = true;
00636       res.status_message = std::string("DeleteModel: successfully deleted model");
00637       return true;
00638     }
00639 
00642     bool GazeboRosApiPlugin::getModelState(gazebo_msgs::GetModelState::Request &req,gazebo_msgs::GetModelState::Response &res)
00643     {
00644       gazebo::physics::ModelPtr model = this->world->GetModel(req.model_name);
00645       gazebo::physics::LinkPtr frame = boost::dynamic_pointer_cast<gazebo::physics::Link>(this->world->GetEntity(req.relative_entity_name));
00646       if (!model)
00647       {
00648         ROS_ERROR("GetModelState: model [%s] does not exist",req.model_name.c_str());
00649         res.success = false;
00650         res.status_message = "GetModelState: model does not exist";
00651         return false;
00652       }
00653       else
00654       {
00655         // get model pose
00656         gazebo::math::Pose       model_pose = model->GetWorldPose();
00657         gazebo::math::Vector3    model_pos = model_pose.pos;
00658         gazebo::math::Quaternion model_rot = model_pose.rot;
00659 
00660         // get model twist
00661         gazebo::math::Vector3 model_linear_vel  = model->GetWorldLinearVel();
00662         gazebo::math::Vector3 model_angular_vel = model->GetWorldAngularVel();
00663 
00664 
00665         if (frame)
00666         {
00667           // convert to relative pose
00668           gazebo::math::Pose frame_pose = frame->GetWorldPose();
00669           model_pos = model_pos - frame_pose.pos;
00670           model_pos = frame_pose.rot.RotateVectorReverse(model_pos);
00671           model_rot *= frame_pose.rot.GetInverse();
00672 
00673           // convert to relative rates
00674           gazebo::math::Vector3 frame_vpos = frame->GetWorldLinearVel(); // get velocity in gazebo frame
00675           gazebo::math::Vector3 frame_veul = frame->GetWorldAngularVel(); // get velocity in gazebo frame
00676           model_linear_vel = frame_pose.rot.RotateVector(model_linear_vel - frame_vpos);
00677           model_angular_vel = frame_pose.rot.RotateVector(model_angular_vel - frame_veul);
00678         }
00680         else if (req.relative_entity_name == "" || req.relative_entity_name == "world" || req.relative_entity_name == "map" || req.relative_entity_name == "/map")
00681         {
00682             ROS_DEBUG("GetModelState: relative_entity_name is empty/world/map, using inertial frame");
00683         }
00684         else
00685         {
00686           res.success = false;
00687           res.status_message = "GetModelState: reference relative_entity_name not found, did you forget to scope the body by model name?";
00688           return false;
00689         }
00690 
00691         // fill in response
00692         res.pose.position.x = model_pos.x;
00693         res.pose.position.y = model_pos.y;
00694         res.pose.position.z = model_pos.z;
00695         res.pose.orientation.w = model_rot.w;
00696         res.pose.orientation.x = model_rot.x;
00697         res.pose.orientation.y = model_rot.y;
00698         res.pose.orientation.z = model_rot.z;
00699 
00700         res.twist.linear.x = model_linear_vel.x;
00701         res.twist.linear.y = model_linear_vel.y;
00702         res.twist.linear.z = model_linear_vel.z;
00703         res.twist.angular.x = model_angular_vel.x;
00704         res.twist.angular.y = model_angular_vel.y;
00705         res.twist.angular.z = model_angular_vel.z;
00706 
00707         res.success = true;
00708         res.status_message = "GetModelState: got properties";
00709         return true;
00710       }
00711       return true;
00712     }
00713 
00716     bool GazeboRosApiPlugin::getModelProperties(gazebo_msgs::GetModelProperties::Request &req,gazebo_msgs::GetModelProperties::Response &res)
00717     {
00718       gazebo::physics::ModelPtr model = this->world->GetModel(req.model_name);
00719       if (!model)
00720       {
00721         ROS_ERROR("GetModelProperties: model [%s] does not exist",req.model_name.c_str());
00722         res.success = false;
00723         res.status_message = "GetModelProperties: model does not exist";
00724         return false;
00725       }
00726       else
00727       {
00728         // get model parent name
00729         gazebo::physics::ModelPtr parent_model = boost::dynamic_pointer_cast<gazebo::physics::Model>(model->GetParent());
00730         if (parent_model) res.parent_model_name = parent_model->GetName();
00731 
00732         // get list of child bodies, geoms
00733         res.body_names.clear();
00734         res.geom_names.clear();
00735         for (unsigned int i = 0 ; i < model->GetChildCount(); i ++)
00736         {
00737           gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(model->GetChild(i));
00738           if (body)
00739           {
00740             res.body_names.push_back(body->GetName());
00741             // get list of geoms
00742             for (unsigned int j = 0; j < body->GetChildCount() ; j++)
00743             {
00744               gazebo::physics::CollisionPtr geom = boost::dynamic_pointer_cast<gazebo::physics::Collision>(body->GetChild(j));
00745               if (geom)
00746                 res.geom_names.push_back(geom->GetName());
00747             }
00748           }
00749         }
00750 
00751         // get list of joints
00752         res.joint_names.clear();
00753 
00754         gazebo::physics::Joint_V joints = model->GetJoints();
00755         for (unsigned int i=0;i< joints.size(); i++)
00756           res.joint_names.push_back( joints[i]->GetName() );
00757 
00758         // get children model names
00759         res.child_model_names.clear();
00760         for (unsigned int j = 0; j < model->GetChildCount(); j++)
00761         {
00762           gazebo::physics::ModelPtr child_model = boost::dynamic_pointer_cast<gazebo::physics::Model>(model->GetChild(j));
00763           if (child_model)
00764             res.child_model_names.push_back(child_model->GetName() );
00765         }
00766 
00767         // is model static
00768         res.is_static = model->IsStatic();
00769 
00770         res.success = true;
00771         res.status_message = "GetModelProperties: got properties";
00772         return true;
00773       }
00774       return true;
00775     }
00776 
00779     bool GazeboRosApiPlugin::getWorldProperties(gazebo_msgs::GetWorldProperties::Request &req,gazebo_msgs::GetWorldProperties::Response &res)
00780     {
00781       res.sim_time = this->world->GetSimTime().Double();
00782       res.model_names.clear();
00783       for (unsigned int i = 0; i < this->world->GetModelCount(); i ++)
00784         res.model_names.push_back(this->world->GetModel(i)->GetName());
00785       gzerr << "disablign rendering has not been implemented, rendering is always enabled\n";
00786       res.rendering_enabled = true; //this->world->GetRenderEngineEnabled();
00787       res.success = true;
00788       res.status_message = "GetWorldProperties: got properties";
00789       return true;
00790     }
00791 
00794     bool GazeboRosApiPlugin::getJointProperties(gazebo_msgs::GetJointProperties::Request &req,gazebo_msgs::GetJointProperties::Response &res)
00795     {
00796       gazebo::physics::JointPtr joint;
00797       for (unsigned int i = 0; i < this->world->GetModelCount(); i ++)
00798       {
00799         joint = this->world->GetModel(i)->GetJoint(req.joint_name);
00800         if (joint) break;
00801       }
00802 
00803       if (!joint)
00804       {
00805         res.success = false;
00806         res.status_message = "GetJointProperties: joint not found";
00807         return false;
00808       }
00809       else
00810       {
00812         res.type = res.REVOLUTE;
00813 
00814         res.damping.clear(); // to be added to gazebo
00815         //res.damping.push_back(joint->GetDamping(0));
00816 
00817         res.position.clear(); // use GetAngle(i)
00818         res.position.push_back(joint->GetAngle(0).Radian());
00819 
00820         res.rate.clear(); // use GetVelocity(i)
00821         res.rate.push_back(joint->GetVelocity(0));
00822 
00823         res.success = true;
00824         res.status_message = "GetJointProperties: got properties";
00825         return true;
00826       }
00827     }
00828 
00831     bool GazeboRosApiPlugin::getLinkProperties(gazebo_msgs::GetLinkProperties::Request &req,gazebo_msgs::GetLinkProperties::Response &res)
00832     {
00833       gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(this->world->GetEntity(req.link_name));
00834       if (!body)
00835       {
00836         res.success = false;
00837         res.status_message = "GetLinkProperties: link not found, did you forget to scope the link by model name?";
00838         return false;
00839       }
00840       else
00841       {
00843         res.gravity_mode = body->GetGravityMode();
00844 
00845         res.mass = body->GetInertial()->GetMass();
00846 
00847         gazebo::physics::InertialPtr inertia = body->GetInertial();
00848         res.ixx = inertia->GetIXX();
00849         res.iyy = inertia->GetIYY();
00850         res.izz = inertia->GetIZZ();
00851         res.ixy = inertia->GetIXY();
00852         res.ixz = inertia->GetIXZ();
00853         res.iyz = inertia->GetIYZ();
00854 
00855         gazebo::math::Vector3 com = body->GetInertial()->GetCoG();
00856         res.com.position.x = com.x;
00857         res.com.position.y = com.y;
00858         res.com.position.z = com.z;
00859         res.com.orientation.x = 0; // @todo: gazebo do not support rotated inertia yet
00860         res.com.orientation.y = 0;
00861         res.com.orientation.z = 0;
00862         res.com.orientation.w = 1;
00863 
00864         res.success = true;
00865         res.status_message = "GetLinkProperties: got properties";
00866         return true;
00867       }
00868     }
00869 
00872     bool GazeboRosApiPlugin::getLinkState(gazebo_msgs::GetLinkState::Request &req,gazebo_msgs::GetLinkState::Response &res)
00873     {
00874       gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(this->world->GetEntity(req.link_name));
00875       gazebo::physics::LinkPtr frame = boost::dynamic_pointer_cast<gazebo::physics::Link>(this->world->GetEntity(req.reference_frame));
00876 
00877       if (!body)
00878       {
00879         res.success = false;
00880         res.status_message = "GetLinkState: link not found, did you forget to scope the link by model name?";
00881         return false;
00882       }
00883 
00884       // get body pose
00885       gazebo::math::Pose body_pose = body->GetWorldPose();
00886       // Get inertial rates
00887       gazebo::math::Vector3 body_vpos = body->GetWorldLinearVel(); // get velocity in gazebo frame
00888       gazebo::math::Vector3 body_veul = body->GetWorldAngularVel(); // get velocity in gazebo frame
00889 
00890       if (frame)
00891       {
00892         // convert to relative pose
00893         gazebo::math::Pose frame_pose = frame->GetWorldPose();
00894         body_pose.pos = body_pose.pos - frame_pose.pos;
00895         body_pose.pos = frame_pose.rot.RotateVectorReverse(body_pose.pos);
00896         body_pose.rot *= frame_pose.rot.GetInverse();
00897 
00898         // convert to relative rates
00899         gazebo::math::Vector3 frame_vpos = frame->GetWorldLinearVel(); // get velocity in gazebo frame
00900         gazebo::math::Vector3 frame_veul = frame->GetWorldAngularVel(); // get velocity in gazebo frame
00901         body_vpos = frame_pose.rot.RotateVector(body_vpos - frame_vpos);
00902         body_veul = frame_pose.rot.RotateVector(body_veul - frame_veul);
00903       }
00905       else if (req.reference_frame == "" || req.reference_frame == "world" || req.reference_frame == "map" || req.reference_frame == "/map")
00906       {
00907           ROS_DEBUG("GetLinkState: reference_frame is empty/world/map, using inertial frame");
00908       }
00909       else
00910       {
00911         res.success = false;
00912         res.status_message = "GetLinkState: reference reference_frame not found, did you forget to scope the link by model name?";
00913         return false;
00914       }
00915 
00916       res.link_state.link_name = req.link_name;
00917       res.link_state.pose.position.x = body_pose.pos.x;
00918       res.link_state.pose.position.y = body_pose.pos.y;
00919       res.link_state.pose.position.z = body_pose.pos.z;
00920       res.link_state.pose.orientation.x = body_pose.rot.x;
00921       res.link_state.pose.orientation.y = body_pose.rot.y;
00922       res.link_state.pose.orientation.z = body_pose.rot.z;
00923       res.link_state.pose.orientation.w = body_pose.rot.w;
00924       res.link_state.twist.linear.x = body_vpos.x;
00925       res.link_state.twist.linear.y = body_vpos.y;
00926       res.link_state.twist.linear.z = body_vpos.z;
00927       res.link_state.twist.angular.x = body_veul.x;
00928       res.link_state.twist.angular.y = body_veul.y;
00929       res.link_state.twist.angular.z = body_veul.x;
00930       res.link_state.reference_frame = req.reference_frame;
00931 
00932       res.success = true;
00933       res.status_message = "GetLinkState: got state";
00934       return true;
00935     }
00936 
00939     bool GazeboRosApiPlugin::setLinkProperties(gazebo_msgs::SetLinkProperties::Request &req,gazebo_msgs::SetLinkProperties::Response &res)
00940     {
00941       gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(this->world->GetEntity(req.link_name));
00942       if (!body)
00943       {
00944         res.success = false;
00945         res.status_message = "SetLinkProperties: link not found, did you forget to scope the link by model name?";
00946         return false;
00947       }
00948       else
00949       {
00950         gazebo::physics::InertialPtr mass = body->GetInertial();
00951         // @todo: FIXME: add inertia matrix rotation to Gazebo
00952         // mass.SetInertiaRotation(gazebo::math::Quaternionion(req.com.orientation.w,res.com.orientation.x,req.com.orientation.y req.com.orientation.z));
00953         mass->SetCoG(gazebo::math::Vector3(req.com.position.x,req.com.position.y,req.com.position.z));
00954         mass->SetInertiaMatrix(req.ixx,req.iyy,req.izz,req.ixy,req.ixz,req.iyz);
00955         mass->SetMass(req.mass);
00956         body->SetGravityMode(req.gravity_mode);
00957         // @todo: mass change unverified
00958         res.success = true;
00959         res.status_message = "SetLinkProperties: properties set";
00960         return true;
00961       }
00962     }
00963 
00966     bool GazeboRosApiPlugin::setPhysicsProperties(gazebo_msgs::SetPhysicsProperties::Request &req,gazebo_msgs::SetPhysicsProperties::Response &res)
00967     {
00968       // pause simulation if requested
00969       bool is_paused = this->world->IsPaused();
00970       this->world->SetPaused(true);
00971 
00972       // supported updates
00973       gazebo::physics::PhysicsEnginePtr ode_pe = (this->world->GetPhysicsEngine());
00974       ode_pe->SetStepTime(req.time_step);
00975       ode_pe->SetUpdateRate(req.max_update_rate);
00976       ode_pe->SetGravity(gazebo::math::Vector3(req.gravity.x,req.gravity.y,req.gravity.z));
00977 
00978       // stuff only works in ODE right now
00979       ode_pe->SetAutoDisableFlag(req.ode_config.auto_disable_bodies);
00980       ode_pe->SetSORPGSPreconIters(req.ode_config.sor_pgs_precon_iters);
00981       ode_pe->SetSORPGSIters(req.ode_config.sor_pgs_iters);
00982       ode_pe->SetSORPGSW(req.ode_config.sor_pgs_w);
00983       ode_pe->SetWorldCFM(req.ode_config.cfm);
00984       ode_pe->SetWorldERP(req.ode_config.erp);
00985       ode_pe->SetContactSurfaceLayer(req.ode_config.contact_surface_layer);
00986       ode_pe->SetContactMaxCorrectingVel(req.ode_config.contact_max_correcting_vel);
00987       ode_pe->SetMaxContacts(req.ode_config.max_contacts);
00988 
00989       this->world->SetPaused(is_paused);
00990 
00991       res.success = true;
00992       res.status_message = "physics engine updated";
00993       return true;
00994     }
00995 
00998     bool GazeboRosApiPlugin::getPhysicsProperties(gazebo_msgs::GetPhysicsProperties::Request &req,gazebo_msgs::GetPhysicsProperties::Response &res)
00999     {
01000       // supported updates
01001       res.time_step = this->world->GetPhysicsEngine()->GetStepTime();
01002       res.pause = this->world->IsPaused();
01003       res.max_update_rate = this->world->GetPhysicsEngine()->GetUpdateRate();
01004       gazebo::math::Vector3 gravity = this->world->GetPhysicsEngine()->GetGravity();
01005       res.gravity.x = gravity.x;
01006       res.gravity.y = gravity.y;
01007       res.gravity.z = gravity.z;
01008 
01009       // stuff only works in ODE right now
01010       res.ode_config.auto_disable_bodies = this->world->GetPhysicsEngine()->GetAutoDisableFlag();
01011       res.ode_config.sor_pgs_precon_iters = this->world->GetPhysicsEngine()->GetSORPGSPreconIters();
01012       res.ode_config.sor_pgs_iters = this->world->GetPhysicsEngine()->GetSORPGSIters();
01013       res.ode_config.sor_pgs_w = this->world->GetPhysicsEngine()->GetSORPGSW();
01014       res.ode_config.contact_surface_layer = this->world->GetPhysicsEngine()->GetContactSurfaceLayer();
01015       res.ode_config.contact_max_correcting_vel = this->world->GetPhysicsEngine()->GetContactMaxCorrectingVel();
01016       res.ode_config.cfm = this->world->GetPhysicsEngine()->GetWorldCFM();
01017       res.ode_config.erp = this->world->GetPhysicsEngine()->GetWorldERP();
01018       res.ode_config.max_contacts = this->world->GetPhysicsEngine()->GetMaxContacts();
01019 
01020       res.success = true;
01021       res.status_message = "GetPhysicsProperties: got properties";
01022       return true;
01023     }
01024 
01027     bool GazeboRosApiPlugin::setJointProperties(gazebo_msgs::SetJointProperties::Request &req,gazebo_msgs::SetJointProperties::Response &res)
01028     {
01030       gazebo::physics::JointPtr joint;
01031       for (unsigned int i = 0; i < this->world->GetModelCount(); i ++)
01032       {
01033         joint = this->world->GetModel(i)->GetJoint(req.joint_name);
01034         if (joint) break;
01035       }
01036 
01037       if (!joint)
01038       {
01039         res.success = false;
01040         res.status_message = "SetJointProperties: joint not found";
01041         return false;
01042       }
01043       else
01044       {
01045         for(unsigned int i=0;i< req.ode_joint_config.damping.size();i++)
01046           joint->SetDamping(i,req.ode_joint_config.damping[i]);
01047         for(unsigned int i=0;i< req.ode_joint_config.hiStop.size();i++)
01048           joint->SetAttribute("hi_stop",i,req.ode_joint_config.hiStop[i]);
01049         for(unsigned int i=0;i< req.ode_joint_config.loStop.size();i++)
01050           joint->SetAttribute("lo_stop",i,req.ode_joint_config.loStop[i]);
01051         for(unsigned int i=0;i< req.ode_joint_config.erp.size();i++)
01052           joint->SetAttribute("erp",i,req.ode_joint_config.erp[i]);
01053         for(unsigned int i=0;i< req.ode_joint_config.cfm.size();i++)
01054           joint->SetAttribute("cfm",i,req.ode_joint_config.cfm[i]);
01055         for(unsigned int i=0;i< req.ode_joint_config.stop_erp.size();i++)
01056           joint->SetAttribute("stop_erp",i,req.ode_joint_config.stop_erp[i]);
01057         for(unsigned int i=0;i< req.ode_joint_config.stop_cfm.size();i++)
01058           joint->SetAttribute("stop_cfm",i,req.ode_joint_config.stop_cfm[i]);
01059         for(unsigned int i=0;i< req.ode_joint_config.fudge_factor.size();i++)
01060           joint->SetAttribute("fudge_factor",i,req.ode_joint_config.fudge_factor[i]);
01061         for(unsigned int i=0;i< req.ode_joint_config.fmax.size();i++)
01062           joint->SetAttribute("fmax",i,req.ode_joint_config.fmax[i]);
01063         for(unsigned int i=0;i< req.ode_joint_config.vel.size();i++)
01064           joint->SetAttribute("vel",i,req.ode_joint_config.vel[i]);
01065 
01066         res.success = true;
01067         res.status_message = "SetJointProperties: properties set";
01068         return true;
01069       }
01070     }
01071 
01074     bool GazeboRosApiPlugin::setModelState(gazebo_msgs::SetModelState::Request &req,gazebo_msgs::SetModelState::Response &res)
01075     {
01076       gazebo::math::Vector3 target_pos(req.model_state.pose.position.x,req.model_state.pose.position.y,req.model_state.pose.position.z);
01077       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);
01078       target_rot.Normalize(); // eliminates invalid rotation (0, 0, 0, 0)
01079       gazebo::math::Pose target_pose(target_pos,target_rot);
01080       gazebo::math::Vector3 target_pos_dot(req.model_state.twist.linear.x,req.model_state.twist.linear.y,req.model_state.twist.linear.z);
01081       gazebo::math::Vector3 target_rot_dot(req.model_state.twist.angular.x,req.model_state.twist.angular.y,req.model_state.twist.angular.z);
01082 
01083       gazebo::physics::ModelPtr model = this->world->GetModel(req.model_state.model_name);
01084       if (!model)
01085       {
01086         ROS_ERROR("Updating ModelState: model [%s] does not exist",req.model_state.model_name.c_str());
01087         res.success = false;
01088         res.status_message = "SetModelState: model does not exist";
01089         return false;
01090       }
01091       else
01092       {
01093         gazebo::physics::LinkPtr relative_entity = boost::dynamic_pointer_cast<gazebo::physics::Link>(this->world->GetEntity(req.model_state.reference_frame));
01094         if (relative_entity)
01095         {
01096           gazebo::math::Pose  frame_pose = relative_entity->GetWorldPose(); // - this->myBody->GetCoMPose();
01097           gazebo::math::Vector3 frame_pos = frame_pose.pos;
01098           gazebo::math::Quaternion frame_rot = frame_pose.rot;
01099 
01100           //std::cout << " debug : " << relative_entity->GetName() << " : " << frame_pose << " : " << target_pose << std::endl;
01101           //target_pose = frame_pose + target_pose; // seems buggy, use my own
01102           target_pose.pos = frame_pos + frame_rot.RotateVector(target_pos);
01103           target_pose.rot = frame_rot * target_pose.rot;
01104         }
01106         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" )
01107         {
01108           ROS_DEBUG("Updating ModelState: reference frame is empty/world/map, usig inertial frame");
01109         }
01110         else
01111         {
01112           ROS_ERROR("Updating ModelState: for model[%s], specified reference frame entity [%s] does not exist",
01113                     req.model_state.model_name.c_str(),req.model_state.reference_frame.c_str());
01114           res.success = false;
01115           res.status_message = "SetModelState: specified reference frame entity does not exist";
01116           return false;
01117         }
01118 
01119         //ROS_ERROR("target state: %f %f %f",target_pose.pos.x,target_pose.pos.y,target_pose.pos.z);
01120         bool is_paused = this->world->IsPaused();
01121         this->world->SetPaused(true);
01122         model->SetWorldPose(target_pose);
01123         this->world->SetPaused(is_paused);
01124         //gazebo::math::Pose p3d = model->GetWorldPose();
01125         //ROS_ERROR("model updated state: %f %f %f",p3d.pos.x,p3d.pos.y,p3d.pos.z);
01126 
01127         // set model velocity
01128         model->SetLinearVel(target_pos_dot);
01129         model->SetAngularVel(target_rot_dot);
01130 
01131         res.success = true;
01132         res.status_message = "SetModelState: set model state done";
01133         return true;
01134       }
01135     }
01136 
01139     void GazeboRosApiPlugin::updateModelState(const gazebo_msgs::ModelState::ConstPtr& model_state)
01140     {
01141       gazebo_msgs::SetModelState::Response res;
01142       gazebo_msgs::SetModelState::Request req;
01143       req.model_state = *model_state;
01144       /*bool success =*/ this->setModelState(req,res);
01145     }
01146 
01149     bool GazeboRosApiPlugin::applyJointEffort(gazebo_msgs::ApplyJointEffort::Request &req,gazebo_msgs::ApplyJointEffort::Response &res)
01150     {
01151       gazebo::physics::JointPtr joint;
01152       for (unsigned int i = 0; i < this->world->GetModelCount(); i ++)
01153       {
01154         joint = this->world->GetModel(i)->GetJoint(req.joint_name);
01155         if (joint)
01156         {
01157           GazeboRosApiPlugin::ForceJointJob* fjj = new GazeboRosApiPlugin::ForceJointJob;
01158           fjj->joint = joint;
01159           fjj->force = req.effort;
01160           fjj->start_time = req.start_time;
01161           if (fjj->start_time < ros::Time(this->world->GetSimTime().Double()))
01162             fjj->start_time = ros::Time(this->world->GetSimTime().Double());
01163           fjj->duration = req.duration;
01164           this->lock_.lock();
01165           this->force_joint_jobs.push_back(fjj);
01166           this->lock_.unlock();
01167 
01168           res.success = true;
01169           res.status_message = "ApplyJointEffort: effort set";
01170           return true;
01171         }
01172       }
01173 
01174       res.success = false;
01175       res.status_message = "ApplyJointEffort: joint not found";
01176       return false;
01177     }
01178 
01181     bool GazeboRosApiPlugin::resetSimulation(std_srvs::Empty::Request &req,std_srvs::Empty::Response &res)
01182     {
01183       this->world->Reset();
01184       return true;
01185     }
01186 
01189     bool GazeboRosApiPlugin::resetWorld(std_srvs::Empty::Request &req,std_srvs::Empty::Response &res)
01190     {
01191       this->world->ResetEntities(gazebo::physics::Base::MODEL);
01192       return true;
01193     }
01194 
01197     bool GazeboRosApiPlugin::pausePhysics(std_srvs::Empty::Request &req,std_srvs::Empty::Response &res)
01198     {
01199       this->world->SetPaused(true);
01200       return true;
01201     }
01202 
01205     bool GazeboRosApiPlugin::unpausePhysics(std_srvs::Empty::Request &req,std_srvs::Empty::Response &res)
01206     {
01207       this->world->SetPaused(false);
01208       return true;
01209     }
01210 
01213     bool GazeboRosApiPlugin::clearJointForces(gazebo_msgs::JointRequest::Request &req,gazebo_msgs::JointRequest::Response &res)
01214     {
01215       return this->clearJointForces(req.joint_name);
01216     }
01217     bool GazeboRosApiPlugin::clearJointForces(std::string joint_name)
01218     {
01219       bool search = true;
01220       this->lock_.lock();
01221       while(search)
01222       {
01223         search = false;
01224         for (std::vector<GazeboRosApiPlugin::ForceJointJob*>::iterator iter=this->force_joint_jobs.begin();iter!=this->force_joint_jobs.end();iter++)
01225         {
01226           if ((*iter)->joint->GetName() == joint_name)
01227           {
01228             // found one, search through again
01229             search = true;
01230             delete (*iter);
01231             this->force_joint_jobs.erase(iter);
01232             break;
01233           }
01234         }
01235       }
01236       this->lock_.unlock();
01237       return true;
01238     }
01239 
01242     bool GazeboRosApiPlugin::clearBodyWrenches(gazebo_msgs::BodyRequest::Request &req,gazebo_msgs::BodyRequest::Response &res)
01243     {
01244       return this->clearBodyWrenches(req.body_name);
01245     }
01246     bool GazeboRosApiPlugin::clearBodyWrenches(std::string body_name)
01247     {
01248       bool search = true;
01249       this->lock_.lock();
01250       while(search)
01251       {
01252         search = false;
01253         for (std::vector<GazeboRosApiPlugin::WrenchBodyJob*>::iterator iter=this->wrench_body_jobs.begin();iter!=this->wrench_body_jobs.end();iter++)
01254         {
01255           //ROS_ERROR("search %s %s",(*iter)->body->GetScopedName().c_str(), body_name.c_str());
01256           if ((*iter)->body->GetScopedName() == body_name)
01257           {
01258             // found one, search through again
01259             search = true;
01260             delete (*iter);
01261             this->wrench_body_jobs.erase(iter);
01262             break;
01263           }
01264         }
01265       }
01266       this->lock_.unlock();
01267       return true;
01268     }
01269 
01274     bool GazeboRosApiPlugin::setModelConfiguration(gazebo_msgs::SetModelConfiguration::Request &req,gazebo_msgs::SetModelConfiguration::Response &res)
01275     {
01276       std::string gazebo_model_name = req.model_name;
01277 
01278       // search for model with name
01279       gazebo::physics::ModelPtr gazebo_model = this->world->GetModel(req.model_name);
01280       if (!gazebo_model)
01281       {
01282         ROS_ERROR("SetModelConfiguration: model [%s] does not exist",gazebo_model_name.c_str());
01283         res.success = false;
01284         res.status_message = "SetModelConfiguration: model does not exist";
01285         return false;
01286       }
01287 
01288       if (req.joint_names.size() == req.joint_positions.size())
01289       {
01290         std::map<std::string, double> joint_position_map;
01291         for (unsigned int i = 0; i < req.joint_names.size(); i++)
01292         {
01293           joint_position_map[req.joint_names[i]] = req.joint_positions[i];
01294         }
01295 
01296         // make the service call to pause gazebo
01297         bool is_paused = this->world->IsPaused();
01298         if (!is_paused) this->world->SetPaused(true);
01299 
01300         gazebo_model->SetJointPositions(joint_position_map);
01301 
01302         // resume paused state before this call
01303         this->world->SetPaused(is_paused);
01304 
01305         res.success = true;
01306         res.status_message = "SetModelConfiguration: success";
01307         return true;
01308       }
01309       else
01310       {
01311         res.success = false;
01312         res.status_message = "SetModelConfiguration: joint name and position list have different lengths";
01313         return false;
01314       }
01315     }
01316 
01319     bool GazeboRosApiPlugin::setLinkState(gazebo_msgs::SetLinkState::Request &req,gazebo_msgs::SetLinkState::Response &res)
01320     {
01321       gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(this->world->GetEntity(req.link_state.link_name));
01322       gazebo::physics::LinkPtr frame = boost::dynamic_pointer_cast<gazebo::physics::Link>(this->world->GetEntity(req.link_state.reference_frame));
01323       if (!body)
01324       {
01325         ROS_ERROR("Updating LinkState: link [%s] does not exist",req.link_state.link_name.c_str());
01326         res.success = false;
01327         res.status_message = "SetLinkState: link does not exist";
01328         return false;
01329       }
01330 
01332       // get reference frame (body/model(link)) pose and
01333       // transform target pose to absolute world frame
01334       gazebo::math::Vector3 target_pos(req.link_state.pose.position.x,req.link_state.pose.position.y,req.link_state.pose.position.z);
01335       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);
01336       gazebo::math::Pose target_pose(target_pos,target_rot);
01337       gazebo::math::Vector3 target_linear_vel(req.link_state.twist.linear.x,req.link_state.twist.linear.y,req.link_state.twist.linear.z);
01338       gazebo::math::Vector3 target_angular_vel(req.link_state.twist.angular.x,req.link_state.twist.angular.y,req.link_state.twist.angular.z);
01339 
01340       if (frame)
01341       {
01342         gazebo::math::Pose  frame_pose = frame->GetWorldPose(); // - this->myBody->GetCoMPose();
01343         gazebo::math::Vector3 frame_pos = frame_pose.pos;
01344         gazebo::math::Quaternion frame_rot = frame_pose.rot;
01345 
01346         //std::cout << " debug : " << frame->GetName() << " : " << frame_pose << " : " << target_pose << std::endl;
01347         //target_pose = frame_pose + target_pose; // seems buggy, use my own
01348         target_pose.pos = frame_pos + frame_rot.RotateVector(target_pos);
01349         target_pose.rot = frame_rot * target_pose.rot;
01350 
01351         gazebo::math::Vector3 frame_linear_vel = frame->GetWorldLinearVel();
01352         gazebo::math::Vector3 frame_angular_vel = frame->GetWorldAngularVel();
01353         target_linear_vel -= frame_linear_vel;
01354         target_angular_vel -= frame_angular_vel;
01355       }
01356       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")
01357       {
01358         ROS_INFO("Updating LinkState: reference_frame is empty/world/map, using inertial frame");
01359       }
01360       else
01361       {
01362         ROS_ERROR("Updating LinkState: reference_frame is not a valid link name");
01363         res.success = false;
01364         res.status_message = "SetLinkState: failed";
01365         return false;
01366       }
01367 
01368       //std::cout << " debug : " << target_pose << std::endl;
01369       //boost::recursive_mutex::scoped_lock lock(*this->world->GetMRMutex());
01370 
01371       bool is_paused = this->world->IsPaused();
01372       if (!is_paused) this->world->SetPaused(true);
01373       body->SetWorldPose(target_pose);
01374       this->world->SetPaused(is_paused);
01375 
01376       // set body velocity to desired twist
01377       body->SetLinearVel(target_linear_vel);
01378       body->SetAngularVel(target_angular_vel);
01379 
01380       res.success = true;
01381       res.status_message = "SetLinkState: success";
01382       return true;
01383     }
01384 
01387     void GazeboRosApiPlugin::updateLinkState(const gazebo_msgs::LinkState::ConstPtr& link_state)
01388     {
01389       gazebo_msgs::SetLinkState::Request req;
01390       gazebo_msgs::SetLinkState::Response res;
01391       req.link_state = *link_state;
01392       /*bool success = */ this->setLinkState(req,res);
01393     }
01394 
01395 
01399     void GazeboRosApiPlugin::transformWrench( gazebo::math::Vector3 &target_force, gazebo::math::Vector3 &target_torque,
01400                                gazebo::math::Vector3 reference_force, gazebo::math::Vector3 reference_torque,
01401                                gazebo::math::Pose target_to_reference )
01402     {
01403       // rotate force into target frame
01404       target_force = target_to_reference.rot.RotateVector(reference_force);
01405       // rotate torque into target frame
01406       target_torque = target_to_reference.rot.RotateVector(reference_torque);
01407 
01408       // target force is the refence force rotated by the target->reference transform
01409       target_force = target_force;
01410       target_torque = target_torque + target_to_reference.pos.Cross(target_force);
01411     }
01412 
01415     bool GazeboRosApiPlugin::applyBodyWrench(gazebo_msgs::ApplyBodyWrench::Request &req,gazebo_msgs::ApplyBodyWrench::Response &res)
01416     {
01417       gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(this->world->GetEntity(req.body_name));
01418       gazebo::physics::LinkPtr frame = boost::dynamic_pointer_cast<gazebo::physics::Link>(this->world->GetEntity(req.reference_frame));
01419       if (!body)
01420       {
01421         ROS_ERROR("ApplyBodyWrench: body [%s] does not exist",req.body_name.c_str());
01422         res.success = false;
01423         res.status_message = "ApplyBodyWrench: body does not exist";
01424         return false;
01425       }
01426 
01427       // target wrench
01428       gazebo::math::Vector3 reference_force(req.wrench.force.x,req.wrench.force.y,req.wrench.force.z);
01429       gazebo::math::Vector3 reference_torque(req.wrench.torque.x,req.wrench.torque.y,req.wrench.torque.z);
01430       gazebo::math::Vector3 reference_point(req.reference_point.x,req.reference_point.y,req.reference_point.z);
01431 
01432       gazebo::math::Vector3 target_force;
01433       gazebo::math::Vector3 target_torque;
01434 
01437       reference_torque = reference_torque + reference_point.Cross(reference_force);
01438 
01440       if (frame)
01441       {
01442         // get reference frame (body/model(body)) pose and
01443         // transform target pose to absolute world frame
01444         // @todo: need to modify wrench (target force and torque by frame)
01445         //        transform wrench from reference_point in reference_frame
01446         //        into the reference frame of the body
01447         //        first, translate by reference point to the body frame
01448         gazebo::math::Pose target_to_reference = frame->GetWorldPose() - body->GetWorldPose();
01449         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]",
01450                    body->GetWorldPose().pos.x,
01451                    body->GetWorldPose().pos.y,
01452                    body->GetWorldPose().pos.z,
01453                    body->GetWorldPose().rot.GetAsEuler().x,
01454                    body->GetWorldPose().rot.GetAsEuler().y,
01455                    body->GetWorldPose().rot.GetAsEuler().z,
01456                    frame->GetWorldPose().pos.x,
01457                    frame->GetWorldPose().pos.y,
01458                    frame->GetWorldPose().pos.z,
01459                    frame->GetWorldPose().rot.GetAsEuler().x,
01460                    frame->GetWorldPose().rot.GetAsEuler().y,
01461                    frame->GetWorldPose().rot.GetAsEuler().z,
01462                    target_to_reference.pos.x,
01463                    target_to_reference.pos.y,
01464                    target_to_reference.pos.z,
01465                    target_to_reference.rot.GetAsEuler().x,
01466                    target_to_reference.rot.GetAsEuler().y,
01467                    target_to_reference.rot.GetAsEuler().z
01468                  );
01469         this->transformWrench(target_force, target_torque, reference_force, reference_torque, target_to_reference);
01470         ROS_ERROR("wrench defined as [%s]:[%f %f %f, %f %f %f] --> applied as [%s]:[%f %f %f, %f %f %f]",
01471                    frame->GetName().c_str(),
01472                    reference_force.x,
01473                    reference_force.y,
01474                    reference_force.z,
01475                    reference_torque.x,
01476                    reference_torque.y,
01477                    reference_torque.z,
01478                    body->GetName().c_str(),
01479                    target_force.x,
01480                    target_force.y,
01481                    target_force.z,
01482                    target_torque.x,
01483                    target_torque.y,
01484                    target_torque.z
01485                  );
01486 
01487       }
01488       else if (req.reference_frame == "" || req.reference_frame == "world" || req.reference_frame == "map" || req.reference_frame == "/map")
01489       {
01490         ROS_INFO("ApplyBodyWrench: reference_frame is empty/world/map, using inertial frame, transferring from body relative to inertial frame");
01491         // FIXME: transfer to inertial frame
01492         gazebo::math::Pose target_to_reference = body->GetWorldPose();
01493         target_force = reference_force;
01494         target_torque = reference_torque;
01495 
01496       }
01497       else
01498       {
01499         ROS_ERROR("ApplyBodyWrench: reference_frame is not a valid link name");
01500         res.success = false;
01501         res.status_message = "ApplyBodyWrench: reference_frame not found";
01502         return false;
01503       }
01504 
01505       // apply wrench
01506       // schedule a job to do below at appropriate times:
01507       // body->SetForce(force)
01508       // body->SetTorque(torque)
01509       GazeboRosApiPlugin::WrenchBodyJob* wej = new GazeboRosApiPlugin::WrenchBodyJob;
01510       wej->body = body;
01511       wej->force = target_force;
01512       wej->torque = target_torque;
01513       wej->start_time = req.start_time;
01514       if (wej->start_time < ros::Time(this->world->GetSimTime().Double()))
01515         wej->start_time = ros::Time(this->world->GetSimTime().Double());
01516       wej->duration = req.duration;
01517       this->lock_.lock();
01518       this->wrench_body_jobs.push_back(wej);
01519       this->lock_.unlock();
01520 
01521       res.success = true;
01522       res.status_message = "";
01523       return true;
01524     }
01525 
01526 
01527     void GazeboRosApiPlugin::spin()
01528     {
01529       // todo: make a wait loop that does not provide extra ros::spin()
01530       ros::Rate r(10);
01531       while(ros::ok())
01532       {
01533         ros::spinOnce();
01534         r.sleep();
01535       }
01536     }
01537 
01539     bool GazeboRosApiPlugin::IsURDF(std::string model_xml)
01540     {
01541       TiXmlDocument doc_in;
01542       doc_in.Parse(model_xml.c_str());
01543       if (doc_in.FirstChild("robot"))
01544         return true;
01545       else
01546         return false;
01547     }
01548     bool GazeboRosApiPlugin::IsGazeboModelXML(std::string model_xml)
01549     {
01550       // FIXME: very crude check
01551       TiXmlDocument doc_in;
01552       doc_in.Parse(model_xml.c_str());
01553       if (doc_in.FirstChild("model:physical")) // old gazebo xml
01554         return true;
01555       else
01556         return false;
01557     }
01558     bool GazeboRosApiPlugin::IsSDF(std::string model_xml)
01559     {
01560       // FIXME: very crude check
01561       TiXmlDocument doc_in;
01562       doc_in.Parse(model_xml.c_str());
01563       if (doc_in.FirstChild("gazebo") ||
01564           doc_in.FirstChild("sdf")) // sdf
01565         return true;
01566       else
01567         return false;
01568     }
01569 
01572     void GazeboRosApiPlugin::wrenchBodySchedulerSlot()
01573     {
01574       // MDMutex locks in case model is getting deleted, don't have to do this if we delete jobs first
01575       // boost::recursive_mutex::scoped_lock lock(*this->world->GetMDMutex());
01576       this->lock_.lock();
01577       for (std::vector<GazeboRosApiPlugin::WrenchBodyJob*>::iterator iter=this->wrench_body_jobs.begin();iter!=this->wrench_body_jobs.end();)
01578       {
01579         // check times and apply wrench if necessary
01580         if (ros::Time(this->world->GetSimTime().Double()) >= (*iter)->start_time)
01581           if (ros::Time(this->world->GetSimTime().Double()) <= (*iter)->start_time+(*iter)->duration ||
01582               (*iter)->duration.toSec() < 0.0)
01583           {
01584             if ((*iter)->body) // if body exists
01585             {
01586               (*iter)->body->SetForce((*iter)->force);
01587               (*iter)->body->SetTorque((*iter)->torque);
01588             }
01589             else
01590               (*iter)->duration.fromSec(0.0); // mark for delete
01591           }
01592 
01593         if (ros::Time(this->world->GetSimTime().Double()) > (*iter)->start_time+(*iter)->duration &&
01594             (*iter)->duration.toSec() >= 0.0)
01595         {
01596           // remove from queue once expires
01597           delete (*iter);
01598           this->wrench_body_jobs.erase(iter);
01599         }
01600         else
01601           iter++;
01602       }
01603       this->lock_.unlock();
01604     }
01605 
01608     void GazeboRosApiPlugin::forceJointSchedulerSlot()
01609     {
01610       // MDMutex locks in case model is getting deleted, don't have to do this if we delete jobs first
01611       // boost::recursive_mutex::scoped_lock lock(*this->world->GetMDMutex());
01612       this->lock_.lock();
01613       for (std::vector<GazeboRosApiPlugin::ForceJointJob*>::iterator iter=this->force_joint_jobs.begin();iter!=this->force_joint_jobs.end();)
01614       {
01615         // check times and apply force if necessary
01616         if (ros::Time(this->world->GetSimTime().Double()) >= (*iter)->start_time)
01617           if (ros::Time(this->world->GetSimTime().Double()) <= (*iter)->start_time+(*iter)->duration ||
01618               (*iter)->duration.toSec() < 0.0)
01619             {
01620               if ((*iter)->joint) // if joint exists
01621                 (*iter)->joint->SetForce(0,(*iter)->force);
01622               else
01623                 (*iter)->duration.fromSec(0.0); // mark for delete
01624             }
01625 
01626         if (ros::Time(this->world->GetSimTime().Double()) > (*iter)->start_time+(*iter)->duration &&
01627             (*iter)->duration.toSec() >= 0.0)
01628         {
01629           // remove from queue once expires
01630           this->force_joint_jobs.erase(iter);
01631         }
01632         else
01633           iter++;
01634       }
01635       this->lock_.unlock();
01636     }
01637 
01640     void GazeboRosApiPlugin::publishSimTime(const boost::shared_ptr<gazebo::msgs::WorldStatistics const> &msg)
01641     {
01642       ROS_ERROR("CLOCK2");
01643       gazebo::common::Time currentTime = gazebo::msgs::Convert( msg->sim_time() );
01644       rosgraph_msgs::Clock ros_time_;
01645       ros_time_.clock.fromSec(currentTime.Double());
01646       //  publish time to ros
01647       this->pub_clock_.publish(ros_time_);
01648     }
01649     void GazeboRosApiPlugin::publishSimTime()
01650     {
01651       gazebo::common::Time currentTime = this->world->GetSimTime();
01652       rosgraph_msgs::Clock ros_time_;
01653       ros_time_.clock.fromSec(currentTime.Double());
01654       //  publish time to ros
01655       this->pub_clock_.publish(ros_time_);
01656     }
01657 
01658 
01661     void GazeboRosApiPlugin::publishLinkStates()
01662     {
01663       gazebo_msgs::LinkStates link_states;
01664 
01665       // fill link_states
01666       for (unsigned int i = 0; i < this->world->GetModelCount(); i ++)
01667       {
01668         gazebo::physics::ModelPtr model = this->world->GetModel(i);
01669 
01670         for (unsigned int j = 0 ; j < model->GetChildCount(); j ++)
01671         {
01672           gazebo::physics::LinkPtr body = boost::dynamic_pointer_cast<gazebo::physics::Link>(model->GetChild(j));
01673 
01674           if (body)
01675           {
01676             link_states.name.push_back(body->GetScopedName());
01677             geometry_msgs::Pose pose;
01678             gazebo::math::Pose  body_pose = body->GetWorldPose(); // - this->myBody->GetCoMPose();
01679             gazebo::math::Vector3 pos = body_pose.pos;
01680             gazebo::math::Quaternion rot = body_pose.rot;
01681             pose.position.x = pos.x;
01682             pose.position.y = pos.y;
01683             pose.position.z = pos.z;
01684             pose.orientation.w = rot.w;
01685             pose.orientation.x = rot.x;
01686             pose.orientation.y = rot.y;
01687             pose.orientation.z = rot.z;
01688             link_states.pose.push_back(pose);
01689             gazebo::math::Vector3 linear_vel  = body->GetWorldLinearVel();
01690             gazebo::math::Vector3 angular_vel = body->GetWorldAngularVel();
01691             geometry_msgs::Twist twist;
01692             twist.linear.x = linear_vel.x;
01693             twist.linear.y = linear_vel.y;
01694             twist.linear.z = linear_vel.z;
01695             twist.angular.x = angular_vel.x;
01696             twist.angular.y = angular_vel.y;
01697             twist.angular.z = angular_vel.z;
01698             link_states.twist.push_back(twist);
01699           }
01700         }
01701       }
01702 
01703       this->pub_link_states_.publish(link_states);
01704     }
01705 
01708     void GazeboRosApiPlugin::publishModelStates()
01709     {
01710       gazebo_msgs::ModelStates model_states;
01711 
01712       // fill model_states
01713       for (unsigned int i = 0; i < this->world->GetModelCount(); i ++)
01714       {
01715         gazebo::physics::ModelPtr model = this->world->GetModel(i);
01716         model_states.name.push_back(model->GetName());
01717         geometry_msgs::Pose pose;
01718         gazebo::math::Pose  model_pose = model->GetWorldPose(); // - this->myBody->GetCoMPose();
01719         gazebo::math::Vector3 pos = model_pose.pos;
01720         gazebo::math::Quaternion rot = model_pose.rot;
01721         pose.position.x = pos.x;
01722         pose.position.y = pos.y;
01723         pose.position.z = pos.z;
01724         pose.orientation.w = rot.w;
01725         pose.orientation.x = rot.x;
01726         pose.orientation.y = rot.y;
01727         pose.orientation.z = rot.z;
01728         model_states.pose.push_back(pose);
01729         gazebo::math::Vector3 linear_vel  = model->GetWorldLinearVel();
01730         gazebo::math::Vector3 angular_vel = model->GetWorldAngularVel();
01731         geometry_msgs::Twist twist;
01732         twist.linear.x = linear_vel.x;
01733         twist.linear.y = linear_vel.y;
01734         twist.linear.z = linear_vel.z;
01735         twist.angular.x = angular_vel.x;
01736         twist.angular.y = angular_vel.y;
01737         twist.angular.z = angular_vel.z;
01738         model_states.twist.push_back(twist);
01739       }
01740       this->pub_model_states_.publish(model_states);
01741     }
01742 
01743     void GazeboRosApiPlugin::PhysicsReconfigureCallback(gazebo::PhysicsConfig &config, uint32_t level)
01744     {
01745       if (!physics_reconfigure_initialized_)
01746       {
01747         gazebo_msgs::GetPhysicsProperties srv;
01748         this->physics_reconfigure_get_client_.call(srv);
01749 
01750         config.time_step                   = srv.response.time_step;
01751         config.max_update_rate             = srv.response.max_update_rate;
01752         config.gravity_x                   = srv.response.gravity.x;
01753         config.gravity_y                   = srv.response.gravity.y;
01754         config.gravity_z                   = srv.response.gravity.z;
01755         config.auto_disable_bodies         = srv.response.ode_config.auto_disable_bodies;
01756         config.sor_pgs_precon_iters        = srv.response.ode_config.sor_pgs_precon_iters;
01757         config.sor_pgs_iters               = srv.response.ode_config.sor_pgs_iters;
01758         config.sor_pgs_rms_error_tol       = srv.response.ode_config.sor_pgs_rms_error_tol;
01759         config.sor_pgs_w                   = srv.response.ode_config.sor_pgs_w;
01760         config.contact_surface_layer       = srv.response.ode_config.contact_surface_layer;
01761         config.contact_max_correcting_vel  = srv.response.ode_config.contact_max_correcting_vel;
01762         config.cfm                         = srv.response.ode_config.cfm;
01763         config.erp                         = srv.response.ode_config.erp;
01764         config.max_contacts                = srv.response.ode_config.max_contacts;
01765         physics_reconfigure_initialized_ = true;
01766       }
01767       else
01768       {
01769         bool changed = false;
01770         gazebo_msgs::GetPhysicsProperties srv;
01771         this->physics_reconfigure_get_client_.call(srv);
01772 
01773         // check for changes
01774         if (config.time_step                      != srv.response.time_step)                                 changed = true;
01775         if (config.max_update_rate                != srv.response.max_update_rate)                           changed = true;
01776         if (config.gravity_x                      != srv.response.gravity.x)                                 changed = true;
01777         if (config.gravity_y                      != srv.response.gravity.y)                                 changed = true;
01778         if (config.gravity_z                      != srv.response.gravity.z)                                 changed = true;
01779         if (config.auto_disable_bodies            != srv.response.ode_config.auto_disable_bodies)            changed = true;
01780         if ((uint32_t)config.sor_pgs_precon_iters != srv.response.ode_config.sor_pgs_precon_iters)           changed = true;
01781         if ((uint32_t)config.sor_pgs_iters        != srv.response.ode_config.sor_pgs_iters)                  changed = true;
01782         if (config.sor_pgs_rms_error_tol          != srv.response.ode_config.sor_pgs_rms_error_tol)          changed = true;
01783         if (config.sor_pgs_w                      != srv.response.ode_config.sor_pgs_w)                      changed = true;
01784         if (config.contact_surface_layer          != srv.response.ode_config.contact_surface_layer)          changed = true;
01785         if (config.contact_max_correcting_vel     != srv.response.ode_config.contact_max_correcting_vel)     changed = true;
01786         if (config.cfm                            != srv.response.ode_config.cfm)                            changed = true;
01787         if (config.erp                            != srv.response.ode_config.erp)                            changed = true;
01788         if ((uint32_t)config.max_contacts         != srv.response.ode_config.max_contacts)                   changed = true;
01789 
01790         if (changed)
01791         {
01792           // pause simulation if requested
01793           gazebo_msgs::SetPhysicsProperties srv;
01794           srv.request.time_step                             = config.time_step                   ;
01795           srv.request.max_update_rate                       = config.max_update_rate             ;
01796           srv.request.gravity.x                             = config.gravity_x                   ;
01797           srv.request.gravity.y                             = config.gravity_y                   ;
01798           srv.request.gravity.z                             = config.gravity_z                   ;
01799           srv.request.ode_config.auto_disable_bodies        = config.auto_disable_bodies         ;
01800           srv.request.ode_config.sor_pgs_precon_iters       = config.sor_pgs_precon_iters        ;
01801           srv.request.ode_config.sor_pgs_iters              = config.sor_pgs_iters               ;
01802           srv.request.ode_config.sor_pgs_rms_error_tol      = config.sor_pgs_rms_error_tol       ;
01803           srv.request.ode_config.sor_pgs_w                  = config.sor_pgs_w                   ;
01804           srv.request.ode_config.contact_surface_layer      = config.contact_surface_layer       ;
01805           srv.request.ode_config.contact_max_correcting_vel = config.contact_max_correcting_vel  ;
01806           srv.request.ode_config.cfm                        = config.cfm                         ;
01807           srv.request.ode_config.erp                        = config.erp                         ;
01808           srv.request.ode_config.max_contacts               = config.max_contacts                ;
01809           this->physics_reconfigure_set_client_.call(srv);
01810           ROS_INFO("physics dynamics reconfigure update complete");
01811         }
01812         ROS_INFO("physics dynamics reconfigure complete");
01813       }
01814     }
01815 
01816     void GazeboRosApiPlugin::PhysicsReconfigureNode()
01817     {
01818       ros::NodeHandle node_handle;
01819       this->physics_reconfigure_set_client_ = node_handle.serviceClient<gazebo_msgs::SetPhysicsProperties>("/gazebo/set_physics_properties");
01820       this->physics_reconfigure_get_client_ = node_handle.serviceClient<gazebo_msgs::GetPhysicsProperties>("/gazebo/get_physics_properties");
01821       this->physics_reconfigure_set_client_.waitForExistence();
01822       this->physics_reconfigure_get_client_.waitForExistence();
01823 
01824       // for dynamic reconfigure physics
01825       // for dynamic_reconfigure
01826       dynamic_reconfigure::Server<gazebo::PhysicsConfig> physics_reconfigure_srv;
01827       dynamic_reconfigure::Server<gazebo::PhysicsConfig>::CallbackType physics_reconfigure_f;
01828 
01829       physics_reconfigure_f = boost::bind(&GazeboRosApiPlugin::PhysicsReconfigureCallback, this, _1, _2);
01830       physics_reconfigure_srv.setCallback(physics_reconfigure_f);
01831 
01832       ROS_INFO("Starting to spin physics dynamic reconfigure node...");
01833       ros::Rate r(10);
01834       while(ros::ok())
01835       {
01836         ros::spinOnce();
01837         r.sleep();
01838       }
01839     }
01840 
01843     void GazeboRosApiPlugin::stripXmlDeclaration(std::string &model_xml)
01844     {
01845       // incoming robot model string is a string containing a Gazebo Model XML
01849       std::string open_bracket("<?");
01850       std::string close_bracket("?>");
01851       size_t pos1 = model_xml.find(open_bracket,0);
01852       size_t pos2 = model_xml.find(close_bracket,0);
01853       if (pos1 != std::string::npos && pos2 != std::string::npos)
01854         model_xml.replace(pos1,pos2-pos1+2,std::string(""));
01855     }
01856 
01859     void GazeboRosApiPlugin::updateGazeboXmlModelPose(TiXmlDocument &gazebo_model_xml, gazebo::math::Vector3 initial_xyz, gazebo::math::Quaternion initial_q)
01860     {
01861       TiXmlElement* model_tixml = gazebo_model_xml.FirstChildElement("model:physical"); // old gazebo pre 1.0.0
01862       if (model_tixml)
01863       {
01864         // replace initial pose of robot
01865         // find first instance of xyz and rpy, replace with initial pose
01866         TiXmlElement* xyz_key = model_tixml->FirstChildElement("xyz");
01867         if (xyz_key)
01868           model_tixml->RemoveChild(xyz_key);
01869         TiXmlElement* rpy_key = model_tixml->FirstChildElement("rpy");
01870         if (rpy_key)
01871           model_tixml->RemoveChild(rpy_key);
01872 
01873         xyz_key = new TiXmlElement("xyz");
01874         rpy_key = new TiXmlElement("rpy");
01875 
01876         std::ostringstream xyz_stream, rpy_stream;
01877         xyz_stream << initial_xyz.x << " " << initial_xyz.y << " " << initial_xyz.z;
01878         gazebo::math::Vector3 initial_rpy = initial_q.GetAsEuler(); // convert to Euler angles for Gazebo XML
01879         rpy_stream << initial_rpy.x*180.0/M_PI << " " << initial_rpy.y*180.0/M_PI << " " << initial_rpy.z*180.0/M_PI; // convert to degrees for Gazebo (though ROS is in Radians)
01880 
01881 
01882         TiXmlText* xyz_txt = new TiXmlText(xyz_stream.str());
01883         TiXmlText* rpy_txt = new TiXmlText(rpy_stream.str());
01884 
01885         xyz_key->LinkEndChild(xyz_txt);
01886         rpy_key->LinkEndChild(rpy_txt);
01887 
01888         model_tixml->LinkEndChild(xyz_key);
01889         model_tixml->LinkEndChild(rpy_key);
01890       }
01891       else
01892         ROS_ERROR("could not find <gazebo> element in sdf, so new name not applied");
01893     }
01894 
01897     void GazeboRosApiPlugin::updateGazeboXmlName(TiXmlDocument &gazebo_model_xml, std::string model_name)
01898     {
01899       TiXmlElement* model_tixml = gazebo_model_xml.FirstChildElement("model:physical"); // old gazebo pre 1.0.0
01900       // replace model name if one is specified by the user
01901       if (model_tixml)
01902       {
01903         if (model_tixml->Attribute("name") != NULL)
01904         {
01905           // removing old model name
01906           model_tixml->RemoveAttribute("name");
01907         }
01908         // replace with user specified name
01909         model_tixml->SetAttribute("name",model_name);
01910       }
01911       else
01912         ROS_ERROR("could not find <gazebo> element in sdf, so new name not applied");
01913     }
01914 
01917     void GazeboRosApiPlugin::updateGazeboSDFModelPose(TiXmlDocument &gazebo_model_xml, gazebo::math::Vector3 initial_xyz, gazebo::math::Quaternion initial_q)
01918     {
01919       TiXmlElement* gazebo_tixml = gazebo_model_xml.FirstChildElement("gazebo");
01920       if (gazebo_tixml)
01921       {
01922         TiXmlElement* model_tixml = gazebo_tixml->FirstChildElement("model");
01923         if (model_tixml)
01924         {
01925           // replace initial pose of robot
01926           // find first instance of xyz and rpy, replace with initial pose
01927           TiXmlElement* origin_key = model_tixml->FirstChildElement("origin");
01928 
01929           if (!origin_key)
01930           {
01931             origin_key = new TiXmlElement("origin");
01932             model_tixml->LinkEndChild(origin_key);
01933           }
01934 
01935           std::ostringstream origin_stream;
01936           gazebo::math::Vector3 initial_rpy = initial_q.GetAsEuler(); // convert to Euler angles for Gazebo XML
01937           origin_stream << initial_xyz.x << " " << initial_xyz.y << " " << initial_xyz.z << " "
01938                         << initial_rpy.x << " " << initial_rpy.y << " " << initial_rpy.z;
01939 
01940           origin_key->SetAttribute("pose",origin_stream.str());
01941         }
01942         else
01943           ROS_ERROR("could not find <model> element in sdf, so name and initial position is not applied");
01944       }
01945       else
01946         ROS_ERROR("could not find <gazebo> element in sdf, so new name not applied");
01947     }
01948 
01951     void GazeboRosApiPlugin::updateGazeboSDFName(TiXmlDocument &gazebo_model_xml, std::string model_name)
01952     {
01953       TiXmlElement* gazebo_tixml = gazebo_model_xml.FirstChildElement("gazebo");
01954       if (gazebo_tixml)
01955       {
01956         TiXmlElement* model_tixml = gazebo_tixml->FirstChildElement("model");
01957         if (model_tixml)
01958         {
01959           if (model_tixml->Attribute("name") != NULL)
01960           {
01961             // removing old model name
01962             model_tixml->RemoveAttribute("name");
01963           }
01964           // replace with user specified name
01965           model_tixml->SetAttribute("name",model_name);
01966         }
01967         else
01968           ROS_ERROR("could not find <model> element in sdf, so name and initial position is not applied");
01969       }
01970       else
01971         ROS_ERROR("could not find <gazebo> element in sdf, so new name not applied");
01972     }
01973 
01976     void GazeboRosApiPlugin::updateURDFModelPose(TiXmlDocument &gazebo_model_xml, gazebo::math::Vector3 initial_xyz, gazebo::math::Quaternion initial_q)
01977     {
01978       TiXmlElement* model_tixml = (gazebo_model_xml.FirstChildElement("robot"));
01979       if (model_tixml)
01980       {
01981         // replace initial pose of robot
01982         // find first instance of xyz and rpy, replace with initial pose
01983         TiXmlElement* origin_key = model_tixml->FirstChildElement("origin");
01984 
01985         if (!origin_key)
01986         {
01987           origin_key = new TiXmlElement("origin");
01988           model_tixml->LinkEndChild(origin_key);
01989         }
01990 
01991         if (origin_key->Attribute("xyz"))
01992           origin_key->RemoveAttribute("xyz");
01993         if (origin_key->Attribute("rpy"))
01994           origin_key->RemoveAttribute("rpy");
01995 
01996         std::ostringstream xyz_stream;
01997         xyz_stream << initial_xyz.x << " " << initial_xyz.y << " " << initial_xyz.z;
01998 
01999         std::ostringstream rpy_stream;
02000         gazebo::math::Vector3 initial_rpy = initial_q.GetAsEuler(); // convert to Euler angles for Gazebo XML
02001         rpy_stream << initial_rpy.x << " " << initial_rpy.y << " " << initial_rpy.z;
02002 
02003         origin_key->SetAttribute("xyz",xyz_stream.str());
02004         origin_key->SetAttribute("rpy",rpy_stream.str());
02005       }
02006       else
02007         ROS_ERROR("could not find <model> element in sdf, so name and initial position is not applied");
02008     }
02009 
02012     void GazeboRosApiPlugin::updateURDFName(TiXmlDocument &gazebo_model_xml, std::string model_name)
02013     {
02014       TiXmlElement* model_tixml = gazebo_model_xml.FirstChildElement("robot");
02015       // replace model name if one is specified by the user
02016       if (model_tixml)
02017       {
02018         if (model_tixml->Attribute("name") != NULL)
02019         {
02020           // removing old model name
02021           model_tixml->RemoveAttribute("name");
02022         }
02023         // replace with user specified name
02024         model_tixml->SetAttribute("name",model_name);
02025       }
02026       else
02027         ROS_ERROR("could not find <robot> element in URDF, name not replaced");
02028     }
02029 
02032     void GazeboRosApiPlugin::walkChildAddRobotNamespace(TiXmlNode* robot_xml)
02033     {
02034       TiXmlNode* child = 0;
02035       child = robot_xml->IterateChildren(child);
02036       while (child != NULL)
02037       {
02038         if (child->ValueStr().find(std::string("plugin")) == 0)
02039         {
02040           ROS_DEBUG("recursively walking gazebo extension for %s --> %d",child->ValueStr().c_str(),(int)child->ValueStr().find(std::string("plugin")));
02041           if (child->FirstChildElement("robotNamespace") == NULL)
02042           {
02043             ROS_DEBUG("    adding robotNamespace for %s",child->ValueStr().c_str());
02044             //addKeyValue(child->ToElement(), "robotNamespace", this->robot_namespace_);
02045             TiXmlElement* child_elem = child->ToElement()->FirstChildElement("robotNamespace");
02046             while (child_elem)
02047             {
02048               child->ToElement()->RemoveChild(child_elem);
02049               child_elem = child->ToElement()->FirstChildElement("robotNamespace");
02050             }
02051             TiXmlElement* key = new TiXmlElement("robotNamespace");
02052             TiXmlText* val = new TiXmlText(this->robot_namespace_);
02053             key->LinkEndChild(val);
02054             child->ToElement()->LinkEndChild(key);
02055           }
02056           else
02057           {
02058             ROS_DEBUG("    robotNamespace already exists for %s",child->ValueStr().c_str());
02059           }
02060         }
02061         this->walkChildAddRobotNamespace(child);
02062         child = robot_xml->IterateChildren(child);
02063       }
02064     }
02065 
02068     bool GazeboRosApiPlugin::spawnAndConform(TiXmlDocument &gazebo_model_xml, std::string model_name, gazebo_msgs::SpawnModel::Response &res)
02069     {
02070       // push to factory iface
02071       std::ostringstream stream;
02072       stream << gazebo_model_xml;
02073       std::string gazebo_model_xml_string = stream.str();
02074       ROS_DEBUG("Gazebo Model XML\n\n%s\n\n ",gazebo_model_xml_string.c_str());
02075 
02076       // publish to factory topic
02077       gazebo::msgs::Factory msg;
02078       gazebo::msgs::Init(msg, "spawn_model");
02079       msg.set_sdf( gazebo_model_xml_string );
02080 
02081       //ROS_ERROR("attempting to spawn model name [%s] [%s]", model_name.c_str(),gazebo_model_xml_string.c_str());
02082 
02083       // FIXME: should use entity_info or add lock to World::receiveMutex
02084       // looking for Model to see if it exists already
02085       gazebo::msgs::Request *entity_info_msg = gazebo::msgs::CreateRequest("entity_info", model_name);
02086       this->request_pub_->Publish(*entity_info_msg,true);
02087       // todo: should wait for response response_sub_, check to see that if _msg->response == "nonexistant"
02088       
02089       gazebo::physics::ModelPtr model = this->world->GetModel(model_name);
02090       if (model)
02091       {
02092         ROS_ERROR("SpawnModel: Failure - model name %s already exist.",model_name.c_str());
02093         res.success = false;
02094         res.status_message = "SpawnModel: Failure - model already exists.";
02095         return false;
02096       }
02097 
02098       // Publish the factory message
02099       this->factory_pub_->Publish(msg);
02102 
02104       ros::Duration model_spawn_timeout(60.0);
02105       ros::Time timeout = ros::Time::now() + model_spawn_timeout;
02106       while (true)
02107       {
02108         if (ros::Time::now() > timeout)
02109         {
02110           res.success = false;
02111           res.status_message = std::string("SpawnModel: Model pushed to spawn queue, but spawn service timed out waiting for model to appear in simulation");
02112           return false;
02113         }
02114         {
02115           //boost::recursive_mutex::scoped_lock lock(*this->world->GetMRMutex());
02116           if (this->world->GetModel(model_name)) break;
02117         }
02118         ROS_DEBUG("Waiting for spawning model (%s)",model_name.c_str());
02119         usleep(1000);
02120       }
02121 
02122       // set result
02123       res.success = true;
02124       res.status_message = std::string("SpawnModel: successfully spawned model");
02125       return true;
02126     }
02127 
02128 // Register this plugin with the simulator
02129 GZ_REGISTER_SYSTEM_PLUGIN(GazeboRosApiPlugin)
02130 }
02131 


gazebo
Author(s): Nate Koenig, Andrew Howard, with contributions from many others. See web page for a full credits llist.
autogenerated on Mon Oct 6 2014 12:15:20