00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #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
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)
00048 gazebo::event::Events::DisconnectWorldUpdateStart(this->pub_link_states_event_);
00049 if (this->pub_model_states_connection_count_ > 0)
00050 gazebo::event::Events::DisconnectWorldUpdateStart(this->pub_model_states_event_);
00051
00052
00053 this->rosnode_->shutdown();
00054 delete this->rosnode_;
00055
00056
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
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
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
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
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
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
00122
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
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
00135 this->pub_link_states_connection_count_ = 0;
00136 this->pub_model_states_connection_count_ = 0;
00137
00139 this->AdvertiseServices();
00140
00141
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
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
00169 pub_clock_ = this->rosnode_->advertise<rosgraph_msgs::Clock>("/clock",10);
00170
00171
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
00340
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
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
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
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
00367 this->rosnode_->setParam("/use_sim_time", true);
00368
00369
00370
00371 }
00372
00373 void GazeboRosApiPlugin::onLinkStatesConnect()
00374 {
00375 this->pub_link_states_connection_count_++;
00376 if (this->pub_link_states_connection_count_ == 1)
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)
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)
00389 {
00390 gazebo::event::Events::DisconnectWorldUpdateStart(this->pub_link_states_event_);
00391 if (this->pub_link_states_connection_count_ < 0)
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)
00399 {
00400 gazebo::event::Events::DisconnectWorldUpdateStart(this->pub_model_states_event_);
00401 if (this->pub_model_states_connection_count_ < 0)
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
00409 this->robot_namespace_ = req.robot_namespace;
00410
00411
00412 std::string model_name = req.model_name;
00413
00414
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
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
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
00478 std::string model_name = req.model_name;
00479
00480
00481 this->robot_namespace_ = req.robot_namespace;
00482
00483
00484 gazebo::math::Vector3 initial_xyz(req.initial_pose.position.x,req.initial_pose.position.y,req.initial_pose.position.z);
00485
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
00489 gazebo::physics::LinkPtr frame = boost::shared_dynamic_cast<gazebo::physics::Link>(this->world->GetEntity(req.reference_frame));
00490 if (frame)
00491 {
00492
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
00512 std::string model_xml = req.model_xml;
00513
00514
00515
00516
00517
00518
00519
00520 this->stripXmlDeclaration(model_xml);
00521
00522
00523
00524 TiXmlDocument gazebo_model_xml;
00525 gazebo_model_xml.Parse(model_xml.c_str());
00526
00527
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
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
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
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
00597 this->clearBodyWrenches(body->GetScopedName());
00598 }
00599 }
00600
00601
00602 gazebo::physics::Joint_V joints = model->GetJoints();
00603 for (unsigned int i=0;i< joints.size(); i++)
00604 {
00605
00606 this->clearJointForces(joints[i]->GetName());
00607 }
00608
00609
00610 gazebo::event::Events::setSelectedEntity(req.model_name, "normal");
00611
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
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
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
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
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
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
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
00674 gazebo::math::Vector3 frame_vpos = frame->GetWorldLinearVel();
00675 gazebo::math::Vector3 frame_veul = frame->GetWorldAngularVel();
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
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
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
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
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
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
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
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;
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();
00815
00816
00817 res.position.clear();
00818 res.position.push_back(joint->GetAngle(0).Radian());
00819
00820 res.rate.clear();
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;
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
00885 gazebo::math::Pose body_pose = body->GetWorldPose();
00886
00887 gazebo::math::Vector3 body_vpos = body->GetWorldLinearVel();
00888 gazebo::math::Vector3 body_veul = body->GetWorldAngularVel();
00889
00890 if (frame)
00891 {
00892
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
00899 gazebo::math::Vector3 frame_vpos = frame->GetWorldLinearVel();
00900 gazebo::math::Vector3 frame_veul = frame->GetWorldAngularVel();
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
00952
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
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
00969 bool is_paused = this->world->IsPaused();
00970 this->world->SetPaused(true);
00971
00972
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
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
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
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();
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();
01097 gazebo::math::Vector3 frame_pos = frame_pose.pos;
01098 gazebo::math::Quaternion frame_rot = frame_pose.rot;
01099
01100
01101
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
01120 bool is_paused = this->world->IsPaused();
01121 this->world->SetPaused(true);
01122 model->SetWorldPose(target_pose);
01123 this->world->SetPaused(is_paused);
01124
01125
01126
01127
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 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
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
01256 if ((*iter)->body->GetScopedName() == body_name)
01257 {
01258
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
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
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
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
01333
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();
01343 gazebo::math::Vector3 frame_pos = frame_pose.pos;
01344 gazebo::math::Quaternion frame_rot = frame_pose.rot;
01345
01346
01347
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
01369
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
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 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
01404 target_force = target_to_reference.rot.RotateVector(reference_force);
01405
01406 target_torque = target_to_reference.rot.RotateVector(reference_torque);
01407
01408
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
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
01443
01444
01445
01446
01447
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
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
01506
01507
01508
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
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
01551 TiXmlDocument doc_in;
01552 doc_in.Parse(model_xml.c_str());
01553 if (doc_in.FirstChild("model:physical"))
01554 return true;
01555 else
01556 return false;
01557 }
01558 bool GazeboRosApiPlugin::IsSDF(std::string model_xml)
01559 {
01560
01561 TiXmlDocument doc_in;
01562 doc_in.Parse(model_xml.c_str());
01563 if (doc_in.FirstChild("gazebo") ||
01564 doc_in.FirstChild("sdf"))
01565 return true;
01566 else
01567 return false;
01568 }
01569
01572 void GazeboRosApiPlugin::wrenchBodySchedulerSlot()
01573 {
01574
01575
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
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)
01585 {
01586 (*iter)->body->SetForce((*iter)->force);
01587 (*iter)->body->SetTorque((*iter)->torque);
01588 }
01589 else
01590 (*iter)->duration.fromSec(0.0);
01591 }
01592
01593 if (ros::Time(this->world->GetSimTime().Double()) > (*iter)->start_time+(*iter)->duration &&
01594 (*iter)->duration.toSec() >= 0.0)
01595 {
01596
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
01611
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
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)
01621 (*iter)->joint->SetForce(0,(*iter)->force);
01622 else
01623 (*iter)->duration.fromSec(0.0);
01624 }
01625
01626 if (ros::Time(this->world->GetSimTime().Double()) > (*iter)->start_time+(*iter)->duration &&
01627 (*iter)->duration.toSec() >= 0.0)
01628 {
01629
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
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
01655 this->pub_clock_.publish(ros_time_);
01656 }
01657
01658
01661 void GazeboRosApiPlugin::publishLinkStates()
01662 {
01663 gazebo_msgs::LinkStates link_states;
01664
01665
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();
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
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();
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
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
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
01825
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
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");
01862 if (model_tixml)
01863 {
01864
01865
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();
01879 rpy_stream << initial_rpy.x*180.0/M_PI << " " << initial_rpy.y*180.0/M_PI << " " << initial_rpy.z*180.0/M_PI;
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");
01900
01901 if (model_tixml)
01902 {
01903 if (model_tixml->Attribute("name") != NULL)
01904 {
01905
01906 model_tixml->RemoveAttribute("name");
01907 }
01908
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
01926
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();
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
01962 model_tixml->RemoveAttribute("name");
01963 }
01964
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
01982
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();
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
02016 if (model_tixml)
02017 {
02018 if (model_tixml->Attribute("name") != NULL)
02019 {
02020
02021 model_tixml->RemoveAttribute("name");
02022 }
02023
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
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
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
02077 gazebo::msgs::Factory msg;
02078 gazebo::msgs::Init(msg, "spawn_model");
02079 msg.set_sdf( gazebo_model_xml_string );
02080
02081
02082
02083
02084
02085 gazebo::msgs::Request *entity_info_msg = gazebo::msgs::CreateRequest("entity_info", model_name);
02086 this->request_pub_->Publish(*entity_info_msg,true);
02087
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
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
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
02123 res.success = true;
02124 res.status_message = std::string("SpawnModel: successfully spawned model");
02125 return true;
02126 }
02127
02128
02129 GZ_REGISTER_SYSTEM_PLUGIN(GazeboRosApiPlugin)
02130 }
02131