$search
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 <stdio.h> 00029 #include <stdlib.h> 00030 #include <signal.h> 00031 #include <errno.h> 00032 #include <iostream> 00033 00034 // urdf utilities 00035 #include <tinyxml.h> 00036 #include <gazebo/urdf2gazebo.h> 00037 00038 #include "gazebo/gazebo.h" 00039 #include "gazebo/gazebo_config.h" 00040 #include "gazebo/Simulator.hh" 00041 #include "gazebo/GazeboConfig.hh" 00042 #include "gazebo/GazeboError.hh" 00043 #include "gazebo/Global.hh" 00044 #include "gazebo/World.hh" 00045 #include "gazebo/Entity.hh" 00046 #include "gazebo/Model.hh" 00047 #include "gazebo/Body.hh" 00048 #include "gazebo/Geom.hh" 00049 #include "gazebo/Joint.hh" 00050 #include "gazebo/Mass.hh" 00051 #include "gazebo/Pose3d.hh" 00052 #include "gazebo/Vector3.hh" 00053 #include "gazebo/Quatern.hh" 00054 #include "gazebo/PhysicsEngine.hh" 00055 #include "gazebo/Mass.hh" 00056 00057 // ros 00058 #include <ros/ros.h> 00059 #include <ros/callback_queue.h> 00060 #include <ros/subscribe_options.h> 00061 #include <ros/package.h> 00062 #include <rosgraph_msgs/Clock.h> 00063 00064 // Messages 00065 #include <std_msgs/Bool.h> 00066 00067 // Services 00068 #include "std_srvs/Empty.h" 00069 00070 #include "gazebo_msgs/JointRequest.h" 00071 #include "gazebo_msgs/BodyRequest.h" 00072 00073 #include "gazebo_msgs/SpawnModel.h" 00074 #include "gazebo_msgs/DeleteModel.h" 00075 00076 #include "gazebo_msgs/ApplyBodyWrench.h" 00077 00078 #include "gazebo_msgs/SetPhysicsProperties.h" 00079 #include "gazebo_msgs/GetPhysicsProperties.h" 00080 00081 #include "gazebo_msgs/SetJointProperties.h" 00082 00083 #include "gazebo_msgs/GetWorldProperties.h" 00084 00085 #include "gazebo_msgs/GetModelProperties.h" 00086 #include "gazebo_msgs/GetModelState.h" 00087 #include "gazebo_msgs/SetModelState.h" 00088 00089 #include "gazebo_msgs/GetJointProperties.h" 00090 #include "gazebo_msgs/ApplyJointEffort.h" 00091 00092 #include "gazebo_msgs/GetLinkProperties.h" 00093 #include "gazebo_msgs/SetLinkProperties.h" 00094 #include "gazebo_msgs/SetLinkState.h" 00095 #include "gazebo_msgs/GetLinkState.h" 00096 00097 // Topics 00098 #include "gazebo_msgs/ModelState.h" 00099 #include "gazebo_msgs/LinkState.h" 00100 #include "gazebo_msgs/ModelStates.h" 00101 #include "gazebo_msgs/LinkStates.h" 00102 00103 #include "geometry_msgs/Vector3.h" 00104 #include "geometry_msgs/Wrench.h" 00105 #include "geometry_msgs/Pose.h" 00106 #include "geometry_msgs/Twist.h" 00107 00108 // For physics dynamics reconfigure 00109 #include <dynamic_reconfigure/server.h> 00110 #include <gazebo/PhysicsConfig.h> 00111 #include "gazebo_msgs/SetPhysicsProperties.h" 00112 #include "gazebo_msgs/GetPhysicsProperties.h" 00113 00114 // For model pose transform to set custom joint angles 00115 #include <ros/ros.h> 00116 #include <urdf/model.h> 00117 #include "LinearMath/btTransform.h" 00118 #include "LinearMath/btVector3.h" 00119 #include <gazebo_msgs/SetModelConfiguration.h> 00120 #include <boost/shared_ptr.hpp> 00121 #include <boost/algorithm/string.hpp> 00122 00123 #include <tf/transform_broadcaster.h> 00124 00125 // Command line options 00126 const char *worldFileName; 00127 const char *optLogFileName = NULL; 00128 unsigned int optServerId = 0; 00129 bool optServerForce = true; 00130 bool optGuiEnabled = true; 00131 bool optRenderEngineEnabled = true; 00132 double optTimeout = -1; 00133 unsigned int optMsgLevel = 1; 00134 int optTimeControl = 1; 00135 bool optPhysicsEnabled = true; 00136 bool optPaused = false; 00137 bool optWorldParam = false; 00138 const char *worldParamName = NULL; 00139 std::string worldParamData; 00140 bool optOgreLog = false; 00141 00143 // TODO: Implement these options 00144 void PrintUsage() 00145 { 00146 fprintf(stderr, "Usage: gazeboros [-hv] <worldfile>\n"); 00147 fprintf(stderr, " -h : Print this message.\n"); 00148 fprintf(stderr, " -s <id> : Use server id <id> (an integer); default is 0. If <0, shared memory iface disabled\n"); 00149 fprintf(stderr, " -f : Force usage of the server id (use with caution)\n"); 00150 fprintf(stderr, " -d <-1:9> : Verbose mode: -1 = none, 0 = critical (default), 9 = all)\n"); 00151 fprintf(stderr, " -t <sec> : Timeout and quit after <sec> seconds\n"); 00152 fprintf(stderr, " -g : Run without a GUI\n"); 00153 fprintf(stderr, " -r : Run without a rendering engine\n"); 00154 fprintf(stderr, " -l <logfile> : Log to indicated file.\n"); 00155 fprintf(stderr, " -n : Do not do any time control\n"); 00156 fprintf(stderr, " -p : Run without physics engine\n"); 00157 fprintf(stderr, " -u : Start the simulation paused\n"); 00158 fprintf(stderr, " -w <param> : World file ROS parameter name\n"); 00159 fprintf(stderr, " -o : Create an Ogre.log file\n"); 00160 fprintf(stderr, " <worldfile> : load the the indicated world file\n"); 00161 ros::shutdown(); 00162 return; 00163 } 00164 00166 // Print the version/licence string 00167 void PrintVersion() 00168 { 00169 fprintf(stderr, "Gazebo multi-robot simulator, version %s\n\n", GAZEBO_VERSION); 00170 fprintf(stderr, "Part of the Player/Stage Project " 00171 "[http://playerstage.sourceforge.net].\n"); 00172 fprintf(stderr, "Copyright (C) 2003 Nate Koenig, Andrew Howard, and contributors.\n"); 00173 fprintf(stderr, "Released under the GNU General Public License.\n\n"); 00174 return; 00175 } 00176 00178 // Parse the argument list. Options are placed in static variables. 00179 int ParseArgs(int argc, char **argv) 00180 { 00181 int ch; 00182 char *flags = (char*)("lw:hd:s:fgxt:nqperuo"); 00183 00184 // Get letter options 00185 while ((ch = getopt(argc, argv, flags)) != -1) 00186 { 00187 switch (ch) 00188 { 00189 case 'o': 00190 optOgreLog = true; 00191 break; 00192 00193 case 'u': 00194 optPaused = true; 00195 break; 00196 00197 case 'd': 00198 // Verbose mode 00199 optMsgLevel = atoi(optarg); 00200 break; 00201 00202 case 'f': 00203 // Force server id 00204 optServerForce = true; 00205 break; 00206 00207 case 'l': 00208 optLogFileName = optarg; 00209 break; 00210 00211 // Get world file from parameter server 00212 case 'w': 00213 optWorldParam = true; 00214 worldParamName = optarg; 00215 00216 if (!ros::param::get(std::string(worldParamName), worldParamData)) 00217 { 00218 ROS_FATAL("Unable to retrieve world parameter \"%s\" from server!", worldParamName); 00219 PrintUsage(); 00220 return -1; 00221 } 00222 00223 case 's': 00224 // Server id 00225 optServerId = atoi(optarg); 00226 optServerForce = false; 00227 break; 00228 00229 case 't': 00230 // Timeout and quit after x seconds 00231 optTimeout = atof(optarg); 00232 break; 00233 00234 case 'n': 00235 optTimeControl = 0; 00236 break; 00237 00238 case 'g': 00239 optGuiEnabled = false; 00240 break; 00241 00242 case 'r': 00243 optRenderEngineEnabled = false; 00244 break; 00245 00246 case 'p': 00247 optPhysicsEnabled = false; 00248 break; 00249 00250 case 'h': 00251 default: 00252 PrintUsage(); 00253 return -1; 00254 } 00255 } 00256 00257 argc -= optind; 00258 argv += optind; 00259 00260 if (argc < 1 && !optWorldParam) 00261 { 00262 ROS_FATAL("No world file argument specified"); 00263 PrintUsage(); 00264 return -1; 00265 } 00266 00267 // Get the world file name 00268 if (argc > 0) 00269 worldFileName = argv[0]; 00270 00271 return 0; 00272 } 00273 00275 // sighandler to shut everything down properly 00276 void SignalHandler( int /*dummy*/ ) 00277 { 00278 /* wait for every other nodes to shutdown before shutting down gazebo 00279 FIXME: should only wait for nodes associated with gazebo and plugins, is that even possible? 00280 ros::V_string nodes; 00281 ros::master::getNodes(nodes); 00282 while ((int)nodes.size() > 2) 00283 { 00284 nodes.clear(); 00285 ros::master::getNodes(nodes); 00286 ROS_DEBUG("Trying to shutdown nicely, [%d] nodes still alive, waiting...",(int)nodes.size()); 00287 for (ros::V_string::iterator it = nodes.begin(); it != nodes.end(); it++) 00288 { 00289 ROS_DEBUG(" node[%d]: [%s]",(int)nodes.size(),it->c_str()); 00290 usleep(100000); 00291 } 00292 00293 } 00294 ROS_DEBUG("Stopping gazebo"); 00295 */ 00296 00297 //TODO: use a boost::signal 00298 gazebo::Simulator::Instance()->SetUserQuit(); 00299 return; 00300 } 00301 00302 00303 class GazeboROSNode 00304 { 00305 public: 00306 GazeboROSNode() : rosnode_("~") 00307 { 00308 pub_gazebo_paused_ = this->rosnode_.advertise<std_msgs::Bool>("paused", 1, true); 00309 00311 this->physics_reconfigure_initialized_ = false; 00312 this->gazebo_callback_queue_thread_ = new boost::thread( &GazeboROSNode::gazeboQueueThread,this ); 00313 00315 this->physics_reconfigure_thread_ = new boost::thread(boost::bind(&GazeboROSNode::PhysicsReconfigureNode, this)); 00316 00318 this->AdvertiseServices(); 00319 00320 // connect helper function to signal for scheduling torque/forces, etc 00321 gazebo::World::Instance()->ConnectWorldUpdateStartSignal(boost::bind(&GazeboROSNode::wrenchBodySchedulerSlot,this)); 00322 gazebo::World::Instance()->ConnectWorldUpdateStartSignal(boost::bind(&GazeboROSNode::forceJointSchedulerSlot,this)); 00323 gazebo::World::Instance()->ConnectWorldUpdateStartSignal(boost::bind(&GazeboROSNode::publishSimTime,this)); 00324 00325 // for internal gazebo xml use 00326 this->xmlPrefix_ = std::string("<?xml version='1.0'?> <gazebo:world xmlns:xi='http://www.w3.org/2001/XInclude' xmlns:gazebo='http://playerstage.sourceforge.net/gazebo/xmlschema/#gz' xmlns:model='http://playerstage.sourceforge.net/gazebo/xmlschema/#model' xmlns:sensor='http://playerstage.sourceforge.net/gazebo/xmlschema/#sensor' xmlns:body='http://playerstage.sourceforge.net/gazebo/xmlschema/#body' xmlns:geom='http://playerstage.sourceforge.net/gazebo/xmlschema/#geom' xmlns:joint='http://playerstage.sourceforge.net/gazebo/xmlschema/#joint' xmlns:interface='http://playerstage.sourceforge.net/gazebo/xmlschema/#interface' xmlns:rendering='http://playerstage.sourceforge.net/gazebo/xmlschema/#rendering' xmlns:renderable='http://playerstage.sourceforge.net/gazebo/xmlschema/#renderable' xmlns:controller='http://playerstage.sourceforge.net/gazebo/xmlschema/#controller' xmlns:physics='http://playerstage.sourceforge.net/gazebo/xmlschema/#physics' >"); 00327 this->xmlSuffix_ = std::string("</gazebo:world>"); 00328 00329 // reset topic connection counts 00330 this->pub_link_states_connection_count_ = 0; 00331 this->pub_model_states_connection_count_ = 0; 00332 this->lastWrenchBodyUpdateTime = 0; 00333 this->lastForceJointUpdateTime = 0; 00334 } 00335 00336 ~GazeboROSNode() 00337 { 00338 // disconnect slots 00339 gazebo::World::Instance()->DisconnectWorldUpdateStartSignal(boost::bind(&GazeboROSNode::wrenchBodySchedulerSlot,this)); 00340 gazebo::World::Instance()->DisconnectWorldUpdateStartSignal(boost::bind(&GazeboROSNode::forceJointSchedulerSlot,this)); 00341 gazebo::World::Instance()->DisconnectWorldUpdateStartSignal(boost::bind(&GazeboROSNode::publishSimTime,this)); 00342 if (this->pub_link_states_connection_count_ > 0) // disconnect if there are subscribers on exit 00343 gazebo::World::Instance()->DisconnectWorldUpdateStartSignal(boost::bind(&GazeboROSNode::publishLinkStates,this)); 00344 if (this->pub_model_states_connection_count_ > 0) // disconnect if there are subscribers on exit 00345 gazebo::World::Instance()->DisconnectWorldUpdateStartSignal(boost::bind(&GazeboROSNode::publishModelStates,this)); 00346 00347 // shutdown ros 00348 this->rosnode_.shutdown(); 00349 00350 // shutdown ros queue 00351 this->gazebo_callback_queue_thread_->join(); 00352 delete this->gazebo_callback_queue_thread_; 00353 00354 this->physics_reconfigure_thread_->join(); 00355 delete this->physics_reconfigure_thread_; 00356 00357 this->lock_.lock(); 00358 for (std::vector<GazeboROSNode::ForceJointJob*>::iterator iter=this->force_joint_jobs.begin();iter!=this->force_joint_jobs.end();) 00359 { 00360 delete (*iter); 00361 this->force_joint_jobs.erase(iter); 00362 } 00363 for (std::vector<GazeboROSNode::WrenchBodyJob*>::iterator iter=this->wrench_body_jobs.begin();iter!=this->wrench_body_jobs.end();) 00364 { 00365 delete (*iter); 00366 this->wrench_body_jobs.erase(iter); 00367 } 00368 this->lock_.unlock(); 00369 } 00370 00372 void gazeboQueueThread() 00373 { 00374 ROS_DEBUG_STREAM("Callback thread id=" << boost::this_thread::get_id()); 00375 static const double timeout = 0.001; 00376 static const double status_timeout = 1.0; 00377 00378 ros::WallTime last_status_time; 00379 std_msgs::Bool stat; 00380 while (this->rosnode_.ok()) 00381 { 00382 this->gazebo_queue_.callAvailable(ros::WallDuration(timeout)); 00383 00384 if ((ros::WallTime::now() - last_status_time).toSec() > status_timeout) 00385 { 00386 stat.data = gazebo::Simulator::Instance()->IsPaused(); 00387 pub_gazebo_paused_.publish(stat); 00388 last_status_time = ros::WallTime::now(); 00389 } 00390 } 00391 } 00392 00394 void AdvertiseServices() 00395 { 00396 // Advertise spawn services on the custom queue 00397 std::string spawn_urdf_model_service_name("spawn_urdf_model"); 00398 ros::AdvertiseServiceOptions spawn_urdf_model_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SpawnModel>( 00399 spawn_urdf_model_service_name,boost::bind(&GazeboROSNode::spawnURDFModel,this,_1,_2), 00400 ros::VoidPtr(), &this->gazebo_queue_); 00401 spawn_urdf_model_service_ = this->rosnode_.advertiseService(spawn_urdf_model_aso); 00402 00403 // Advertise spawn services on the custom queue 00404 std::string spawn_gazebo_model_service_name("spawn_gazebo_model"); 00405 ros::AdvertiseServiceOptions spawn_gazebo_model_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SpawnModel>( 00406 spawn_gazebo_model_service_name,boost::bind(&GazeboROSNode::spawnGazeboModel,this,_1,_2), 00407 ros::VoidPtr(), &this->gazebo_queue_); 00408 spawn_urdf_gazebo_service_ = this->rosnode_.advertiseService(spawn_gazebo_model_aso); 00409 00410 // Advertise delete services on the custom queue 00411 std::string delete_model_service_name("delete_model"); 00412 ros::AdvertiseServiceOptions delete_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::DeleteModel>( 00413 delete_model_service_name,boost::bind(&GazeboROSNode::deleteModel,this,_1,_2), 00414 ros::VoidPtr(), &this->gazebo_queue_); 00415 delete_model_service_ = this->rosnode_.advertiseService(delete_aso); 00416 00417 // Advertise more services on the custom queue 00418 std::string get_model_properties_service_name("get_model_properties"); 00419 ros::AdvertiseServiceOptions get_model_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetModelProperties>( 00420 get_model_properties_service_name,boost::bind(&GazeboROSNode::getModelProperties,this,_1,_2), 00421 ros::VoidPtr(), &this->gazebo_queue_); 00422 get_model_properties_service_ = this->rosnode_.advertiseService(get_model_properties_aso); 00423 00424 // Advertise more services on the custom queue 00425 std::string get_model_state_service_name("get_model_state"); 00426 ros::AdvertiseServiceOptions get_model_state_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetModelState>( 00427 get_model_state_service_name,boost::bind(&GazeboROSNode::getModelState,this,_1,_2), 00428 ros::VoidPtr(), &this->gazebo_queue_); 00429 get_model_state_service_ = this->rosnode_.advertiseService(get_model_state_aso); 00430 00431 // Advertise more services on the custom queue 00432 std::string get_world_properties_service_name("get_world_properties"); 00433 ros::AdvertiseServiceOptions get_world_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetWorldProperties>( 00434 get_world_properties_service_name,boost::bind(&GazeboROSNode::getWorldProperties,this,_1,_2), 00435 ros::VoidPtr(), &this->gazebo_queue_); 00436 get_world_properties_service_ = this->rosnode_.advertiseService(get_world_properties_aso); 00437 00438 // Advertise more services on the custom queue 00439 std::string get_joint_properties_service_name("get_joint_properties"); 00440 ros::AdvertiseServiceOptions get_joint_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetJointProperties>( 00441 get_joint_properties_service_name,boost::bind(&GazeboROSNode::getJointProperties,this,_1,_2), 00442 ros::VoidPtr(), &this->gazebo_queue_); 00443 get_joint_properties_service_ = this->rosnode_.advertiseService(get_joint_properties_aso); 00444 00445 // Advertise more services on the custom queue 00446 std::string get_link_properties_service_name("get_link_properties"); 00447 ros::AdvertiseServiceOptions get_link_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetLinkProperties>( 00448 get_link_properties_service_name,boost::bind(&GazeboROSNode::getLinkProperties,this,_1,_2), 00449 ros::VoidPtr(), &this->gazebo_queue_); 00450 get_link_properties_service_ = this->rosnode_.advertiseService(get_link_properties_aso); 00451 00452 // Advertise more services on the custom queue 00453 std::string get_link_state_service_name("get_link_state"); 00454 ros::AdvertiseServiceOptions get_link_state_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetLinkState>( 00455 get_link_state_service_name,boost::bind(&GazeboROSNode::getLinkState,this,_1,_2), 00456 ros::VoidPtr(), &this->gazebo_queue_); 00457 get_link_state_service_ = this->rosnode_.advertiseService(get_link_state_aso); 00458 00459 // Advertise more services on the custom queue 00460 std::string set_link_properties_service_name("set_link_properties"); 00461 ros::AdvertiseServiceOptions set_link_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SetLinkProperties>( 00462 set_link_properties_service_name,boost::bind(&GazeboROSNode::setLinkProperties,this,_1,_2), 00463 ros::VoidPtr(), &this->gazebo_queue_); 00464 set_link_properties_service_ = this->rosnode_.advertiseService(set_link_properties_aso); 00465 00466 // Advertise more services on the custom queue 00467 std::string set_physics_properties_service_name("set_physics_properties"); 00468 ros::AdvertiseServiceOptions set_physics_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SetPhysicsProperties>( 00469 set_physics_properties_service_name,boost::bind(&GazeboROSNode::setPhysicsProperties,this,_1,_2), 00470 ros::VoidPtr(), &this->gazebo_queue_); 00471 set_physics_properties_service_ = this->rosnode_.advertiseService(set_physics_properties_aso); 00472 00473 // Advertise more services on the custom queue 00474 std::string get_physics_properties_service_name("get_physics_properties"); 00475 ros::AdvertiseServiceOptions get_physics_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::GetPhysicsProperties>( 00476 get_physics_properties_service_name,boost::bind(&GazeboROSNode::getPhysicsProperties,this,_1,_2), 00477 ros::VoidPtr(), &this->gazebo_queue_); 00478 get_physics_properties_service_ = this->rosnode_.advertiseService(get_physics_properties_aso); 00479 00480 // Advertise more services on the custom queue 00481 std::string apply_body_wrench_service_name("apply_body_wrench"); 00482 ros::AdvertiseServiceOptions apply_body_wrench_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::ApplyBodyWrench>( 00483 apply_body_wrench_service_name,boost::bind(&GazeboROSNode::applyBodyWrench,this,_1,_2), 00484 ros::VoidPtr(), &this->gazebo_queue_); 00485 apply_body_wrench_service_ = this->rosnode_.advertiseService(apply_body_wrench_aso); 00486 00487 // Advertise more services on the custom queue 00488 std::string set_model_state_service_name("set_model_state"); 00489 ros::AdvertiseServiceOptions set_model_state_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SetModelState>( 00490 set_model_state_service_name,boost::bind(&GazeboROSNode::setModelState,this,_1,_2), 00491 ros::VoidPtr(), &this->gazebo_queue_); 00492 set_model_state_service_ = this->rosnode_.advertiseService(set_model_state_aso); 00493 00494 // Advertise more services on the custom queue 00495 std::string apply_joint_effort_service_name("apply_joint_effort"); 00496 ros::AdvertiseServiceOptions apply_joint_effort_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::ApplyJointEffort>( 00497 apply_joint_effort_service_name,boost::bind(&GazeboROSNode::applyJointEffort,this,_1,_2), 00498 ros::VoidPtr(), &this->gazebo_queue_); 00499 apply_joint_effort_service_ = this->rosnode_.advertiseService(apply_joint_effort_aso); 00500 00501 // Advertise more services on the custom queue 00502 std::string set_joint_properties_service_name("set_joint_properties"); 00503 ros::AdvertiseServiceOptions set_joint_properties_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SetJointProperties>( 00504 set_joint_properties_service_name,boost::bind(&GazeboROSNode::setJointProperties,this,_1,_2), 00505 ros::VoidPtr(), &this->gazebo_queue_); 00506 set_joint_properties_service_ = this->rosnode_.advertiseService(set_joint_properties_aso); 00507 00508 // Advertise more services on the custom queue 00509 std::string set_model_configuration_service_name("set_model_configuration"); 00510 ros::AdvertiseServiceOptions set_model_configuration_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SetModelConfiguration>( 00511 set_model_configuration_service_name,boost::bind(&GazeboROSNode::setModelConfiguration,this,_1,_2), 00512 ros::VoidPtr(), &this->gazebo_queue_); 00513 set_model_configuration_service_ = this->rosnode_.advertiseService(set_model_configuration_aso); 00514 00515 // Advertise more services on the custom queue 00516 std::string set_link_state_service_name("set_link_state"); 00517 ros::AdvertiseServiceOptions set_link_state_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::SetLinkState>( 00518 set_link_state_service_name,boost::bind(&GazeboROSNode::setLinkState,this,_1,_2), 00519 ros::VoidPtr(), &this->gazebo_queue_); 00520 set_link_state_service_ = this->rosnode_.advertiseService(set_link_state_aso); 00521 00522 // Advertise more services on the custom queue 00523 std::string reset_simulation_service_name("reset_simulation"); 00524 ros::AdvertiseServiceOptions reset_simulation_aso = ros::AdvertiseServiceOptions::create<std_srvs::Empty>( 00525 reset_simulation_service_name,boost::bind(&GazeboROSNode::resetSimulation,this,_1,_2), 00526 ros::VoidPtr(), &this->gazebo_queue_); 00527 reset_simulation_service_ = this->rosnode_.advertiseService(reset_simulation_aso); 00528 00529 // Advertise more services on the custom queue 00530 std::string reset_world_service_name("reset_world"); 00531 ros::AdvertiseServiceOptions reset_world_aso = ros::AdvertiseServiceOptions::create<std_srvs::Empty>( 00532 reset_world_service_name,boost::bind(&GazeboROSNode::resetWorld,this,_1,_2), 00533 ros::VoidPtr(), &this->gazebo_queue_); 00534 reset_world_service_ = this->rosnode_.advertiseService(reset_world_aso); 00535 00536 // Advertise more services on the custom queue 00537 std::string pause_physics_service_name("pause_physics"); 00538 ros::AdvertiseServiceOptions pause_physics_aso = ros::AdvertiseServiceOptions::create<std_srvs::Empty>( 00539 pause_physics_service_name,boost::bind(&GazeboROSNode::pausePhysics,this,_1,_2), 00540 ros::VoidPtr(), &this->gazebo_queue_); 00541 pause_physics_service_ = this->rosnode_.advertiseService(pause_physics_aso); 00542 00543 // Advertise more services on the custom queue 00544 std::string unpause_physics_service_name("unpause_physics"); 00545 ros::AdvertiseServiceOptions unpause_physics_aso = ros::AdvertiseServiceOptions::create<std_srvs::Empty>( 00546 unpause_physics_service_name,boost::bind(&GazeboROSNode::unpausePhysics,this,_1,_2), 00547 ros::VoidPtr(), &this->gazebo_queue_); 00548 unpause_physics_service_ = this->rosnode_.advertiseService(unpause_physics_aso); 00549 00550 // Advertise more services on the custom queue 00551 std::string clear_joint_forces_service_name("clear_joint_forces"); 00552 ros::AdvertiseServiceOptions clear_joint_forces_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::JointRequest>( 00553 clear_joint_forces_service_name,boost::bind(&GazeboROSNode::clearJointForces,this,_1,_2), 00554 ros::VoidPtr(), &this->gazebo_queue_); 00555 clear_joint_forces_service_ = this->rosnode_.advertiseService(clear_joint_forces_aso); 00556 00557 // Advertise more services on the custom queue 00558 std::string clear_body_wrenches_service_name("clear_body_wrenches"); 00559 ros::AdvertiseServiceOptions clear_body_wrenches_aso = ros::AdvertiseServiceOptions::create<gazebo_msgs::BodyRequest>( 00560 clear_body_wrenches_service_name,boost::bind(&GazeboROSNode::clearBodyWrenches,this,_1,_2), 00561 ros::VoidPtr(), &this->gazebo_queue_); 00562 clear_body_wrenches_service_ = this->rosnode_.advertiseService(clear_body_wrenches_aso); 00563 00564 // Advertise topic on custom queue 00565 // topic callback version for set_link_state 00566 ros::SubscribeOptions link_state_so = ros::SubscribeOptions::create<gazebo_msgs::LinkState>( 00567 "set_link_state",10, boost::bind( &GazeboROSNode::updateLinkState,this,_1), 00568 ros::VoidPtr(), &this->gazebo_queue_); 00569 set_link_state_topic_ = this->rosnode_.subscribe(link_state_so); 00570 00571 // topic callback version for set_model_state 00572 ros::SubscribeOptions model_state_so = ros::SubscribeOptions::create<gazebo_msgs::ModelState>( 00573 "set_model_state",10, boost::bind( &GazeboROSNode::updateModelState,this,_1), 00574 ros::VoidPtr(), &this->gazebo_queue_); 00575 set_model_state_topic_ = this->rosnode_.subscribe(model_state_so); 00576 00577 // publish clock for simulated ros time 00578 pub_clock_ = this->rosnode_.advertise<rosgraph_msgs::Clock>("/clock",10); 00579 00580 // publish complete link states in world frame 00581 ros::AdvertiseOptions pub_link_states_ao = ros::AdvertiseOptions::create<gazebo_msgs::LinkStates>( 00582 "link_states",10, 00583 boost::bind(&GazeboROSNode::onLinkStatesConnect,this), 00584 boost::bind(&GazeboROSNode::onLinkStatesDisconnect,this), ros::VoidPtr(), &this->gazebo_queue_); 00585 pub_link_states_ = this->rosnode_.advertise(pub_link_states_ao); 00586 00587 // publish complete model states in world frame 00588 ros::AdvertiseOptions pub_model_states_ao = ros::AdvertiseOptions::create<gazebo_msgs::ModelStates>( 00589 "model_states",10, 00590 boost::bind(&GazeboROSNode::onModelStatesConnect,this), 00591 boost::bind(&GazeboROSNode::onModelStatesDisconnect,this), ros::VoidPtr(), &this->gazebo_queue_); 00592 pub_model_states_ = this->rosnode_.advertise(pub_model_states_ao); 00593 00594 00595 00596 00597 00598 // set param for use_sim_time if not set by user alread 00599 this->rosnode_.setParam("/use_sim_time", true); 00600 00601 // todo: contemplate setting environment variable ROBOT=sim here??? 00602 } 00603 00604 void onLinkStatesConnect() 00605 { 00606 this->pub_link_states_connection_count_++; 00607 if (this->pub_link_states_connection_count_ == 1) // connect on first subscriber 00608 gazebo::World::Instance()->ConnectWorldUpdateStartSignal(boost::bind(&GazeboROSNode::publishLinkStates,this)); 00609 } 00610 void onModelStatesConnect() 00611 { 00612 this->pub_model_states_connection_count_++; 00613 if (this->pub_model_states_connection_count_ == 1) // connect on first subscriber 00614 gazebo::World::Instance()->ConnectWorldUpdateStartSignal(boost::bind(&GazeboROSNode::publishModelStates,this)); 00615 } 00616 void onLinkStatesDisconnect() 00617 { 00618 this->pub_link_states_connection_count_--; 00619 if (this->pub_link_states_connection_count_ == 0) // disconnect with no subscribers 00620 gazebo::World::Instance()->DisconnectWorldUpdateStartSignal(boost::bind(&GazeboROSNode::publishLinkStates,this)); 00621 else if (this->pub_link_states_connection_count_ < 0) // should not be possible 00622 ROS_ERROR("one too mandy disconnect from pub_link_states_ in gazeboros.cpp? something weird"); 00623 } 00624 void onModelStatesDisconnect() 00625 { 00626 this->pub_model_states_connection_count_--; 00627 if (this->pub_model_states_connection_count_ == 0) // disconnect with no subscribers 00628 gazebo::World::Instance()->DisconnectWorldUpdateStartSignal(boost::bind(&GazeboROSNode::publishModelStates,this)); 00629 else if (this->pub_model_states_connection_count_ < 0) // should not be possible 00630 ROS_ERROR("one too mandy disconnect from pub_model_states_ in gazeboros.cpp? something weird"); 00631 } 00632 00633 bool spawnURDFModel(gazebo_msgs::SpawnModel::Request &req,gazebo_msgs::SpawnModel::Response &res) 00634 { 00635 // get flag on joint limits 00636 bool enforce_limits = true; //option to add req.enforce_limits?? 00637 00638 // get name space for the corresponding model plugins 00639 std::string robot_namespace = req.robot_namespace; 00640 00641 // incoming robot name 00642 std::string model_name = req.model_name; 00643 00644 // incoming robot model string 00645 std::string model_xml = req.model_xml; 00646 00647 if (!this->IsURDF(model_xml) && !IsColladaData(model_xml)) 00648 { 00649 ROS_ERROR("SpawnModel: Failure - model format is not URDF (nor COLLADA)."); 00650 res.success = false; 00651 res.status_message = "SpawnModel: Failure - model format is not URDF (nor COLLADA)."; 00652 return false; 00653 } 00654 00658 std::string open_bracket("<?"); 00659 std::string close_bracket("?>"); 00660 size_t pos1 = model_xml.find(open_bracket,0); 00661 size_t pos2 = model_xml.find(close_bracket,0); 00662 if (pos1 != std::string::npos && pos2 != std::string::npos) 00663 model_xml.replace(pos1,pos2-pos1+2,std::string("")); 00664 00665 ROS_DEBUG("Model XML\n\n%s\n\n ",model_xml.c_str()); 00666 00667 urdf2gazebo::URDF2Gazebo u2g; 00668 TiXmlDocument model_xml_doc; 00669 model_xml_doc.Parse(model_xml.c_str()); 00670 TiXmlDocument gazebo_model_xml; 00671 // initial xyz and rpy are empty, will be inserted in spawnGazeboModel 00672 u2g.convert(model_xml_doc, gazebo_model_xml, enforce_limits, urdf::Vector3(), urdf::Vector3(), model_name, robot_namespace); 00673 00674 // push to factory iface 00675 std::ostringstream stream; 00676 stream << gazebo_model_xml; 00677 std::string gazebo_model_xml_string = stream.str(); 00678 ROS_DEBUG("Gazebo Model XML\n\n%s\n\n ",gazebo_model_xml_string.c_str()); 00679 req.model_xml = gazebo_model_xml_string; 00680 00681 // publish gazebo model on parameter server as [robot_namespace]/gazebo/[model name]/robot_description 00682 // this->rosnode_.setParam(robot_namespace+std::string("/gazebo/")+model_name+std::string("/robot_description"),gazebo_model_xml_string); 00683 00684 return spawnGazeboModel(req,res); 00685 } 00686 00687 bool spawnGazeboModel(gazebo_msgs::SpawnModel::Request &req,gazebo_msgs::SpawnModel::Response &res) 00688 { 00689 // check to see if model name already exist as a model 00690 std::string model_name = req.model_name; 00691 if (gazebo::World::Instance()->GetEntityByName(model_name)) 00692 { 00693 ROS_ERROR("SpawnModel: Failure - model name %s already exist.",model_name.c_str()); 00694 res.success = false; 00695 res.status_message = "SpawnModel: Failure - model already exists."; 00696 return false; 00697 } 00698 00699 // get name space for the corresponding model plugins 00700 std::string robot_namespace = req.robot_namespace; 00701 00702 // get initial pose of model 00703 gazebo::Vector3 initial_xyz(req.initial_pose.position.x,req.initial_pose.position.y,req.initial_pose.position.z); 00704 // get initial roll pitch yaw (fixed frame transform) 00705 gazebo::Quatern initial_q(req.initial_pose.orientation.w,req.initial_pose.orientation.x,req.initial_pose.orientation.y,req.initial_pose.orientation.z); 00706 00707 // refernce frame for initial pose definition, modify initial pose if defined 00708 gazebo::Body* frame = dynamic_cast<gazebo::Body*>(gazebo::World::Instance()->GetEntityByName(req.reference_frame)); 00709 if (frame) 00710 { 00711 // convert to relative pose 00712 gazebo::Pose3d frame_pose = frame->GetWorldPose(); 00713 initial_xyz = frame_pose.rot.RotateVector(initial_xyz); 00714 initial_xyz += frame_pose.pos; 00715 initial_q = frame_pose.rot*initial_q; 00716 } 00717 00719 else if (req.reference_frame == "" || req.reference_frame == "world" || req.reference_frame == "map" || req.reference_frame == "/map") 00720 { 00721 ROS_DEBUG("SpawnModel: reference_frame is empty/world/map, using inertial frame"); 00722 } 00723 else 00724 { 00725 res.success = false; 00726 res.status_message = "SpawnModel: reference reference_frame not found, did you forget to scope the link by model name?"; 00727 return false; 00728 } 00729 00730 // incoming robot model string 00731 std::string model_xml = req.model_xml; 00732 00733 // store resulting Gazebo Model XML to be sent to spawn queue 00734 // get incoming string containg either an URDF or a Gazebo Model XML 00735 // grab from parameter server if necessary 00736 // convert to Gazebo Model XML if necessary 00737 if (!this->IsGazeboModelXML(model_xml)) 00738 { 00739 ROS_ERROR("GazeboROSNode SpawnModel Failure: input model_xml not Gazebo XML, or cannot be converted to Gazebo XML"); 00740 res.success = false; 00741 res.status_message = std::string("GazeboROSNode SpawnModel Failure: input model_xml not Gazebo XML, or cannot be converted to Gazebo XML"); 00742 return false; 00743 } 00744 00745 TiXmlDocument gazebo_model_xml; 00746 00747 // incoming robot model string is a string containing a Gazebo Model XML 00751 std::string open_bracket("<?"); 00752 std::string close_bracket("?>"); 00753 size_t pos1 = model_xml.find(open_bracket,0); 00754 size_t pos2 = model_xml.find(close_bracket,0); 00755 if (pos1 != std::string::npos && pos2 != std::string::npos) 00756 model_xml.replace(pos1,pos2-pos1+2,std::string("")); 00757 00758 // put string in TiXmlDocument for manipulation 00759 gazebo_model_xml.Parse(model_xml.c_str()); 00760 00761 // optional model manipulations: 00762 // * update initial pose 00763 // * replace model name 00764 TiXmlElement* model; 00765 model = gazebo_model_xml.FirstChildElement("model:physical"); 00766 if (model) 00767 { 00768 // replace initial pose of robot 00769 // find first instance of xyz and rpy, replace with initial pose 00770 TiXmlElement* xyz_key = model->FirstChildElement("xyz"); 00771 if (xyz_key) 00772 model->RemoveChild(xyz_key); 00773 TiXmlElement* rpy_key = model->FirstChildElement("rpy"); 00774 if (rpy_key) 00775 model->RemoveChild(rpy_key); 00776 00777 xyz_key = new TiXmlElement("xyz"); 00778 rpy_key = new TiXmlElement("rpy"); 00779 00780 std::ostringstream xyz_stream, rpy_stream; 00781 xyz_stream << initial_xyz.x << " " << initial_xyz.y << " " << initial_xyz.z; 00782 gazebo::Vector3 initial_rpy = initial_q.GetAsEuler(); // convert to Euler angles for Gazebo XML 00783 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) 00784 00785 00786 TiXmlText* xyz_txt = new TiXmlText(xyz_stream.str()); 00787 TiXmlText* rpy_txt = new TiXmlText(rpy_stream.str()); 00788 00789 xyz_key->LinkEndChild(xyz_txt); 00790 rpy_key->LinkEndChild(rpy_txt); 00791 00792 model->LinkEndChild(xyz_key); 00793 model->LinkEndChild(rpy_key); 00794 00795 // replace model name if one is specified by the user 00796 model->RemoveAttribute("name"); 00797 model->SetAttribute("name",model_name); 00798 00799 } 00800 00801 // push to factory iface 00802 std::ostringstream stream; 00803 stream << gazebo_model_xml; 00804 std::string gazebo_model_xml_string = stream.str(); 00805 ROS_DEBUG("Gazebo Model XML\n\n%s\n\n ",gazebo_model_xml_string.c_str()); 00806 00807 // Add the new models into the World 00808 std::string xmlMiddle = gazebo_model_xml_string; 00809 // Strip leading <?xml...?> tag, if present, to allow the client to 00810 // pass the contents of a valid .model file 00811 std::string xmlVersion = "<?xml version=\"1.0\"?>"; 00812 int i = xmlMiddle.find(xmlVersion); 00813 if(i >= 0) xmlMiddle.replace(i, xmlVersion.length(), ""); 00814 // insert entity into a queue for gazebo to process 00815 std::string xmlString = this->xmlPrefix_ + xmlMiddle + this->xmlSuffix_; 00816 { 00817 boost::recursive_mutex::scoped_lock mrlock(*gazebo::Simulator::Instance()->GetMRMutex()); 00818 gazebo::World::Instance()->InsertEntity(xmlString); 00819 } 00820 00821 // process spawning 00822 //gazebo::World::Instance()->ProcessEntitiesToLoad(); 00823 00825 ros::Duration model_spawn_timeout(60.0); 00826 ros::Time timeout = ros::Time::now() + model_spawn_timeout; 00827 while (true) 00828 { 00829 if (ros::Time::now() > timeout) 00830 { 00831 res.success = false; 00832 res.status_message = std::string("SpawnModel: Model pushed to spawn queue, but spawn service timed out waiting for model to appear in simulation"); 00833 return false; 00834 } 00835 { 00836 boost::recursive_mutex::scoped_lock lock(*gazebo::Simulator::Instance()->GetMRMutex()); 00837 if (gazebo::World::Instance()->GetEntityByName(model_name)) break; 00838 } 00839 ROS_DEBUG("Waiting for spawning model (%s)",model_name.c_str()); 00840 usleep(1000); 00841 } 00842 00843 // set result 00844 res.success = true; 00845 res.status_message = std::string("SpawnModel: successfully spawned model"); 00846 return true; 00847 00848 } 00849 00852 bool deleteModel(gazebo_msgs::DeleteModel::Request &req,gazebo_msgs::DeleteModel::Response &res) 00853 { 00854 // clear forces, etc for the body in question 00855 00856 gazebo::Model* model = dynamic_cast<gazebo::Model*>(gazebo::World::Instance()->GetEntityByName(req.model_name)); 00857 if (!model) 00858 { 00859 ROS_ERROR("DeleteModel: model [%s] does not exist",req.model_name.c_str()); 00860 res.success = false; 00861 res.status_message = "DeleteModel: model does not exist"; 00862 return false; 00863 } 00864 00865 // delete wrench jobs on bodies 00866 const std::vector<gazebo::Entity*> children = model->GetChildren(); 00867 for (std::vector<gazebo::Entity*>::const_iterator iter=children.begin();iter!=children.end();iter++) 00868 { 00869 gazebo::Body* body = (gazebo::Body*)(*iter); 00870 if (body) 00871 { 00872 // look for it in jobs, delete body wrench jobs 00873 this->clearBodyWrenches(body->GetScopedName()); 00874 } 00875 } 00876 // delete force jobs on joints 00877 for (unsigned int i=0;i< model->GetJointCount(); i++) 00878 { 00879 gazebo::Joint* joint = model->GetJoint(i); 00880 // look for it in jobs, delete joint force jobs 00881 this->clearJointForces(joint->GetName()); 00882 } 00883 00884 // delete model 00885 gazebo::World::Instance()->SetSelectedEntity(NULL); 00886 gazebo::World::Instance()->DeleteEntity(req.model_name); 00887 00888 ros::Duration model_spawn_timeout(60.0); 00889 ros::Time timeout = ros::Time::now() + model_spawn_timeout; 00890 // wait and verify that model is deleted 00891 while (true) 00892 { 00893 if (ros::Time::now() > timeout) 00894 { 00895 res.success = false; 00896 res.status_message = std::string("DeleteModel: Model pushed to delete queue, but delete service timed out waiting for model to disappear from simulation"); 00897 return false; 00898 } 00899 { 00900 boost::recursive_mutex::scoped_lock lock(*gazebo::Simulator::Instance()->GetMRMutex()); 00901 if (!gazebo::World::Instance()->GetEntityByName(req.model_name)) break; 00902 } 00903 ROS_DEBUG("Waiting for model deletion (%s)",req.model_name.c_str()); 00904 usleep(1000); 00905 } 00906 00907 // set result 00908 res.success = true; 00909 res.status_message = std::string("DeleteModel: successfully deleted model"); 00910 return true; 00911 } 00912 00915 bool getModelState(gazebo_msgs::GetModelState::Request &req,gazebo_msgs::GetModelState::Response &res) 00916 { 00917 gazebo::Model* model = dynamic_cast<gazebo::Model*>(gazebo::World::Instance()->GetEntityByName(req.model_name)); 00918 gazebo::Body* frame = dynamic_cast<gazebo::Body*>(gazebo::World::Instance()->GetEntityByName(req.relative_entity_name)); 00919 if (!model) 00920 { 00921 ROS_ERROR("GetModelState: model [%s] does not exist",req.model_name.c_str()); 00922 res.success = false; 00923 res.status_message = "GetModelState: model does not exist"; 00924 return false; 00925 } 00926 else 00927 { 00928 // get model pose 00929 gazebo::Pose3d model_pose = model->GetWorldPose(); // - this->myBody->GetCoMPose(); 00930 gazebo::Vector3 model_pos = model_pose.pos; 00931 gazebo::Quatern model_rot = model_pose.rot; 00932 00933 // get model twist 00934 gazebo::Vector3 model_linear_vel = model->GetWorldLinearVel(); 00935 gazebo::Vector3 model_angular_vel = model->GetWorldAngularVel(); 00936 00937 00938 if (frame) 00939 { 00940 // convert to relative pose 00941 gazebo::Pose3d frame_pose = frame->GetWorldPose(); 00942 model_pos = model_pos - frame_pose.pos; 00943 model_pos = frame_pose.rot.RotateVectorReverse(model_pos); 00944 model_rot *= frame_pose.rot.GetInverse(); 00945 00946 // convert to relative rates 00947 gazebo::Vector3 frame_vpos = frame->GetWorldLinearVel(); // get velocity in gazebo frame 00948 gazebo::Vector3 frame_veul = frame->GetWorldAngularVel(); // get velocity in gazebo frame 00949 model_linear_vel = frame_pose.rot.RotateVector(model_linear_vel - frame_vpos); 00950 model_angular_vel = frame_pose.rot.RotateVector(model_angular_vel - frame_veul); 00951 } 00953 else if (req.relative_entity_name == "" || req.relative_entity_name == "world" || req.relative_entity_name == "map" || req.relative_entity_name == "/map") 00954 { 00955 ROS_DEBUG("GetModelState: relative_entity_name is empty/world/map, using inertial frame"); 00956 } 00957 else 00958 { 00959 res.success = false; 00960 res.status_message = "GetModelState: reference relative_entity_name not found, did you forget to scope the body by model name?"; 00961 return false; 00962 } 00963 00964 // fill in response 00965 res.pose.position.x = model_pos.x; 00966 res.pose.position.y = model_pos.y; 00967 res.pose.position.z = model_pos.z; 00968 res.pose.orientation.w = model_rot.u; 00969 res.pose.orientation.x = model_rot.x; 00970 res.pose.orientation.y = model_rot.y; 00971 res.pose.orientation.z = model_rot.z; 00972 00973 res.twist.linear.x = model_linear_vel.x; 00974 res.twist.linear.y = model_linear_vel.y; 00975 res.twist.linear.z = model_linear_vel.z; 00976 res.twist.angular.x = model_angular_vel.x; 00977 res.twist.angular.y = model_angular_vel.y; 00978 res.twist.angular.z = model_angular_vel.z; 00979 00980 res.success = true; 00981 res.status_message = "GetModelState: got properties"; 00982 return true; 00983 } 00984 } 00985 00988 bool getModelProperties(gazebo_msgs::GetModelProperties::Request &req,gazebo_msgs::GetModelProperties::Response &res) 00989 { 00990 gazebo::Model* model = dynamic_cast<gazebo::Model*>(gazebo::World::Instance()->GetEntityByName(req.model_name)); 00991 if (!model) 00992 { 00993 ROS_ERROR("GetModelProperties: model [%s] does not exist",req.model_name.c_str()); 00994 res.success = false; 00995 res.status_message = "GetModelProperties: model does not exist"; 00996 return false; 00997 } 00998 else 00999 { 01000 // get model parent name 01001 gazebo::Entity* parent_model = model->GetParent(); 01002 if (parent_model) res.parent_model_name = parent_model->GetName(); 01003 01004 // get list of child bodies, geoms 01005 res.body_names.clear(); 01006 res.geom_names.clear(); 01007 const std::vector< gazebo::Entity* > entities = model->GetChildren(); 01008 for (std::vector< gazebo::Entity* >::const_iterator eiter = entities.begin();eiter!=entities.end();eiter++) 01009 { 01010 gazebo::Body* body = dynamic_cast<gazebo::Body*>(*eiter); 01011 if (body) 01012 { 01013 res.body_names.push_back(body->GetName()); 01014 // get list of geoms 01015 for (unsigned int i = 0; i < body->GetGeomCount() ; i++) 01016 res.geom_names.push_back(body->GetGeom(i)->GetName()); 01017 } 01018 } 01019 01020 // get list of joints 01021 res.joint_names.clear(); 01022 unsigned int jc = model->GetJointCount(); 01023 for (unsigned int i = 0; i < jc ; i++) 01024 res.joint_names.push_back( model->GetJoint(i)->GetName() ); 01025 01026 // get children model names 01027 res.child_model_names.clear(); 01028 const std::vector< gazebo::Entity* > children = model->GetChildren(); 01029 for (std::vector< gazebo::Entity* >::const_iterator citer = children.begin(); citer != children.end(); citer++) 01030 res.child_model_names.push_back((*citer)->GetName() ); 01031 01032 // is model static 01033 res.is_static = model->IsStatic(); 01034 01035 res.success = true; 01036 res.status_message = "GetModelProperties: got properties"; 01037 return true; 01038 } 01039 } 01040 01043 bool getWorldProperties(gazebo_msgs::GetWorldProperties::Request &req,gazebo_msgs::GetWorldProperties::Response &res) 01044 { 01045 res.sim_time = gazebo::Simulator::Instance()->GetSimTime().Double(); 01046 res.model_names.clear(); 01047 const std::vector<gazebo::Model*> models = gazebo::World::Instance()->GetModels(); 01048 for (std::vector<gazebo::Model*>::const_iterator miter = models.begin(); miter != models.end(); miter++) 01049 res.model_names.push_back((*miter)->GetName()); 01050 res.rendering_enabled = gazebo::Simulator::Instance()->GetRenderEngineEnabled(); 01051 res.success = true; 01052 res.status_message = "GetWorldProperties: got properties"; 01053 01054 return true; 01055 } 01056 01059 bool getJointProperties(gazebo_msgs::GetJointProperties::Request &req,gazebo_msgs::GetJointProperties::Response &res) 01060 { 01061 gazebo::Joint* joint = NULL; 01062 const std::vector<gazebo::Model*> models = gazebo::World::Instance()->GetModels(); 01063 for (std::vector<gazebo::Model*>::const_iterator miter = models.begin(); miter != models.end(); miter++) 01064 { 01065 joint = (*miter)->GetJoint(req.joint_name); 01066 if (joint) break; 01067 } 01068 01069 if (joint == NULL) 01070 { 01071 res.success = false; 01072 res.status_message = "GetJointProperties: joint not found"; 01073 return false; 01074 } 01075 else 01076 { 01078 res.type = res.REVOLUTE; 01079 01080 res.damping.clear(); // to be added to gazebo 01081 //res.damping.push_back(joint->GetDamping(0)); 01082 01083 res.position.clear(); // use GetAngle(i) 01084 res.position.push_back(joint->GetAngle(0).GetAsRadian()); 01085 01086 res.rate.clear(); // use GetVelocity(i) 01087 res.rate.push_back(joint->GetVelocity(0)); 01088 01089 res.success = true; 01090 res.status_message = "GetJointProperties: got properties"; 01091 return true; 01092 } 01093 } 01094 01097 bool getLinkProperties(gazebo_msgs::GetLinkProperties::Request &req,gazebo_msgs::GetLinkProperties::Response &res) 01098 { 01099 gazebo::Body* body = dynamic_cast<gazebo::Body*>(gazebo::World::Instance()->GetEntityByName(req.link_name)); 01100 if (body == NULL) 01101 { 01102 res.success = false; 01103 res.status_message = "GetLinkProperties: link not found, did you forget to scope the link by model name?"; 01104 return false; 01105 } 01106 else 01107 { 01109 res.gravity_mode = body->GetGravityMode(); 01110 01111 res.mass = body->GetMass().GetAsDouble(); 01112 01113 gazebo::Vector3 principalI = body->GetMass().GetPrincipalMoments(); 01114 gazebo::Vector3 productI = body->GetMass().GetProductsofInertia(); 01115 res.ixx = principalI.x; 01116 res.iyy = principalI.y; 01117 res.izz = principalI.z; 01118 res.ixy = productI.x; 01119 res.ixz = productI.y; 01120 res.iyz = productI.z; 01121 01122 gazebo::Vector3 com = body->GetMass().GetCoG(); 01123 res.com.position.x = com.x; 01124 res.com.position.y = com.y; 01125 res.com.position.z = com.z; 01126 res.com.orientation.x = 0; // @todo: gazebo do not support rotated inertia yet 01127 res.com.orientation.y = 0; 01128 res.com.orientation.z = 0; 01129 res.com.orientation.w = 1; 01130 01131 res.success = true; 01132 res.status_message = "GetLinkProperties: got properties"; 01133 return true; 01134 } 01135 return true; 01136 } 01137 01140 bool getLinkState(gazebo_msgs::GetLinkState::Request &req,gazebo_msgs::GetLinkState::Response &res) 01141 { 01142 gazebo::Body* body = dynamic_cast<gazebo::Body*>(gazebo::World::Instance()->GetEntityByName(req.link_name)); 01143 gazebo::Body* frame = dynamic_cast<gazebo::Body*>(gazebo::World::Instance()->GetEntityByName(req.reference_frame)); 01144 if (body == NULL) 01145 { 01146 res.success = false; 01147 res.status_message = "GetLinkState: link not found, did you forget to scope the link by model name?"; 01148 return false; 01149 } 01150 01151 // get body pose 01152 gazebo::Pose3d body_pose = body->GetWorldPose(); 01153 // Get inertial rates 01154 gazebo::Vector3 body_vpos = body->GetWorldLinearVel(); // get velocity in gazebo frame 01155 gazebo::Vector3 body_veul = body->GetWorldAngularVel(); // get velocity in gazebo frame 01156 01157 if (frame) 01158 { 01159 // convert to relative pose 01160 gazebo::Pose3d frame_pose = frame->GetWorldPose(); 01161 body_pose.pos = body_pose.pos - frame_pose.pos; 01162 body_pose.pos = frame_pose.rot.RotateVectorReverse(body_pose.pos); 01163 body_pose.rot *= frame_pose.rot.GetInverse(); 01164 01165 // convert to relative rates 01166 gazebo::Vector3 frame_vpos = frame->GetWorldLinearVel(); // get velocity in gazebo frame 01167 gazebo::Vector3 frame_veul = frame->GetWorldAngularVel(); // get velocity in gazebo frame 01168 body_vpos = frame_pose.rot.RotateVector(body_vpos - frame_vpos); 01169 body_veul = frame_pose.rot.RotateVector(body_veul - frame_veul); 01170 } 01172 else if (req.reference_frame == "" || req.reference_frame == "world" || req.reference_frame == "map" || req.reference_frame == "/map") 01173 { 01174 ROS_DEBUG("GetLinkState: reference_frame is empty/world/map, using inertial frame"); 01175 } 01176 else 01177 { 01178 res.success = false; 01179 res.status_message = "GetLinkState: reference reference_frame not found, did you forget to scope the link by model name?"; 01180 return false; 01181 } 01182 01183 res.link_state.link_name = req.link_name; 01184 res.link_state.pose.position.x = body_pose.pos.x; 01185 res.link_state.pose.position.y = body_pose.pos.y; 01186 res.link_state.pose.position.z = body_pose.pos.z; 01187 res.link_state.pose.orientation.x = body_pose.rot.x; 01188 res.link_state.pose.orientation.y = body_pose.rot.y; 01189 res.link_state.pose.orientation.z = body_pose.rot.z; 01190 res.link_state.pose.orientation.w = body_pose.rot.u; 01191 res.link_state.twist.linear.x = body_vpos.x; 01192 res.link_state.twist.linear.y = body_vpos.y; 01193 res.link_state.twist.linear.z = body_vpos.z; 01194 res.link_state.twist.angular.x = body_veul.x; 01195 res.link_state.twist.angular.y = body_veul.y; 01196 res.link_state.twist.angular.z = body_veul.x; 01197 res.link_state.reference_frame = req.reference_frame; 01198 01199 res.success = true; 01200 res.status_message = "GetLinkState: got state"; 01201 return true; 01202 } 01203 01206 bool setLinkProperties(gazebo_msgs::SetLinkProperties::Request &req,gazebo_msgs::SetLinkProperties::Response &res) 01207 { 01208 gazebo::Body* body = dynamic_cast<gazebo::Body*>(gazebo::World::Instance()->GetEntityByName(req.link_name)); 01209 if (body == NULL) 01210 { 01211 res.success = false; 01212 res.status_message = "SetLinkProperties: link not found, did you forget to scope the link by model name?"; 01213 return false; 01214 } 01215 else 01216 { 01217 gazebo::Mass mass; 01218 // @todo: FIXME: add inertia matrix rotation to Gazebo 01219 // mass.SetInertiaRotation(gazebo::Quaternion(req.com.orientation.w,res.com.orientation.x,req.com.orientation.y req.com.orientation.z)); 01220 mass.SetCoG(gazebo::Vector3(req.com.position.x,req.com.position.y,req.com.position.z)); 01221 mass.SetInertiaMatrix(req.ixx,req.iyy,req.izz,req.ixy,req.ixz,req.iyz); 01222 mass.SetMass(req.mass); 01223 body->SetMass(mass); 01224 body->SetGravityMode(req.gravity_mode); 01225 // @todo: mass change unverified 01226 res.success = true; 01227 res.status_message = "SetLinkProperties: properties set"; 01228 return true; 01229 } 01230 return true; 01231 } 01232 01235 bool setPhysicsProperties(gazebo_msgs::SetPhysicsProperties::Request &req,gazebo_msgs::SetPhysicsProperties::Response &res) 01236 { 01237 // pause simulation if requested 01238 bool is_paused = gazebo::Simulator::Instance()->IsPaused(); 01239 gazebo::Simulator::Instance()->SetPaused(true); 01240 01241 // supported updates 01242 gazebo::World::Instance()->GetPhysicsEngine()->SetStepTime(req.time_step); 01243 gazebo::World::Instance()->GetPhysicsEngine()->SetUpdateRate(req.max_update_rate); 01244 gazebo::World::Instance()->GetPhysicsEngine()->SetGravity(gazebo::Vector3(req.gravity.x,req.gravity.y,req.gravity.z)); 01245 01246 // stuff only works in ODE right now 01247 gazebo::World::Instance()->GetPhysicsEngine()->SetAutoDisableFlag(req.ode_config.auto_disable_bodies); 01248 gazebo::World::Instance()->GetPhysicsEngine()->SetSORPGSPreconIters(req.ode_config.sor_pgs_precon_iters); 01249 gazebo::World::Instance()->GetPhysicsEngine()->SetSORPGSIters(req.ode_config.sor_pgs_iters); 01250 gazebo::World::Instance()->GetPhysicsEngine()->SetRMSErrorTolerance(req.ode_config.sor_pgs_rms_error_tol); 01251 gazebo::World::Instance()->GetPhysicsEngine()->SetSORPGSW(req.ode_config.sor_pgs_w); 01252 gazebo::World::Instance()->GetPhysicsEngine()->SetContactSurfaceLayer(req.ode_config.contact_surface_layer); 01253 gazebo::World::Instance()->GetPhysicsEngine()->SetContactMaxCorrectingVel(req.ode_config.contact_max_correcting_vel); 01254 gazebo::World::Instance()->GetPhysicsEngine()->SetWorldCFM(req.ode_config.cfm); 01255 gazebo::World::Instance()->GetPhysicsEngine()->SetWorldERP(req.ode_config.erp); 01256 gazebo::World::Instance()->GetPhysicsEngine()->SetMaxContacts(req.ode_config.max_contacts); 01257 01258 01259 gazebo::Simulator::Instance()->SetPaused(is_paused); 01260 ROS_INFO("physics dynamics configure update complete"); 01261 01262 res.success = true; 01263 res.status_message = "physics engine updated"; 01264 return true; 01265 } 01266 01269 bool getPhysicsProperties(gazebo_msgs::GetPhysicsProperties::Request &req,gazebo_msgs::GetPhysicsProperties::Response &res) 01270 { 01271 // supported updates 01272 res.time_step = gazebo::World::Instance()->GetPhysicsEngine()->GetStepTime().Double(); 01273 res.pause = gazebo::Simulator::Instance()->IsPaused(); 01274 res.max_update_rate = gazebo::World::Instance()->GetPhysicsEngine()->GetUpdateRate(); 01275 gazebo::Vector3 gravity = gazebo::World::Instance()->GetPhysicsEngine()->GetGravity(); 01276 res.gravity.x = gravity.x; 01277 res.gravity.y = gravity.y; 01278 res.gravity.z = gravity.z; 01279 01280 // stuff only works in ODE right now 01281 res.ode_config.auto_disable_bodies = gazebo::World::Instance()->GetPhysicsEngine()->GetAutoDisableFlag(); 01282 res.ode_config.sor_pgs_precon_iters = gazebo::World::Instance()->GetPhysicsEngine()->GetSORPGSPreconIters(); 01283 res.ode_config.sor_pgs_iters = gazebo::World::Instance()->GetPhysicsEngine()->GetSORPGSIters(); 01284 res.ode_config.sor_pgs_rms_error_tol = gazebo::World::Instance()->GetPhysicsEngine()->GetRMSErrorTolerance(); 01285 res.ode_config.sor_pgs_w = gazebo::World::Instance()->GetPhysicsEngine()->GetSORPGSW(); 01286 res.ode_config.contact_surface_layer = gazebo::World::Instance()->GetPhysicsEngine()->GetContactSurfaceLayer(); 01287 res.ode_config.contact_max_correcting_vel = gazebo::World::Instance()->GetPhysicsEngine()->GetContactMaxCorrectingVel(); 01288 res.ode_config.cfm = gazebo::World::Instance()->GetPhysicsEngine()->GetWorldCFM(); 01289 res.ode_config.erp = gazebo::World::Instance()->GetPhysicsEngine()->GetWorldERP(); 01290 res.ode_config.max_contacts = gazebo::World::Instance()->GetPhysicsEngine()->GetMaxContacts(); 01291 01292 res.success = true; 01293 res.status_message = "GetPhysicsProperties: got properties"; 01294 return true; 01295 } 01296 01299 bool setJointProperties(gazebo_msgs::SetJointProperties::Request &req,gazebo_msgs::SetJointProperties::Response &res) 01300 { 01304 gazebo::Joint* joint = NULL; 01305 const std::vector<gazebo::Model*> models = gazebo::World::Instance()->GetModels(); 01306 for (std::vector<gazebo::Model*>::const_iterator miter = models.begin(); miter != models.end(); miter++) 01307 { 01308 joint = (*miter)->GetJoint(req.joint_name); 01309 if (joint) break; 01310 } 01311 01312 if (joint == NULL) 01313 { 01314 res.success = false; 01315 res.status_message = "SetJointProperties: joint not found"; 01316 return false; 01317 } 01318 else 01319 { 01320 for(unsigned int i=0;i< req.ode_joint_config.damping.size();i++) 01321 joint->SetDamping(i,req.ode_joint_config.damping[i]); 01322 for(unsigned int i=0;i< req.ode_joint_config.hiStop.size();i++) 01323 joint->SetAttribute(gazebo::Joint::HI_STOP,i,req.ode_joint_config.hiStop[i]); 01324 for(unsigned int i=0;i< req.ode_joint_config.loStop.size();i++) 01325 joint->SetAttribute(gazebo::Joint::LO_STOP,i,req.ode_joint_config.loStop[i]); 01326 for(unsigned int i=0;i< req.ode_joint_config.erp.size();i++) 01327 joint->SetAttribute(gazebo::Joint::ERP,i,req.ode_joint_config.erp[i]); 01328 for(unsigned int i=0;i< req.ode_joint_config.cfm.size();i++) 01329 joint->SetAttribute(gazebo::Joint::CFM,i,req.ode_joint_config.cfm[i]); 01330 for(unsigned int i=0;i< req.ode_joint_config.stop_erp.size();i++) 01331 joint->SetAttribute(gazebo::Joint::STOP_ERP,i,req.ode_joint_config.stop_erp[i]); 01332 for(unsigned int i=0;i< req.ode_joint_config.stop_cfm.size();i++) 01333 joint->SetAttribute(gazebo::Joint::STOP_CFM,i,req.ode_joint_config.stop_cfm[i]); 01334 for(unsigned int i=0;i< req.ode_joint_config.fudge_factor.size();i++) 01335 joint->SetAttribute(gazebo::Joint::FUDGE_FACTOR,i,req.ode_joint_config.fudge_factor[i]); 01336 for(unsigned int i=0;i< req.ode_joint_config.fmax.size();i++) 01337 joint->SetAttribute(gazebo::Joint::FMAX,i,req.ode_joint_config.fmax[i]); 01338 for(unsigned int i=0;i< req.ode_joint_config.vel.size();i++) 01339 joint->SetAttribute(gazebo::Joint::VEL,i,req.ode_joint_config.vel[i]); 01340 01341 res.success = true; 01342 res.status_message = "SetJointProperties: properties set"; 01343 return true; 01344 } 01345 } 01346 01349 bool setModelState(gazebo_msgs::SetModelState::Request &req,gazebo_msgs::SetModelState::Response &res) 01350 { 01351 gazebo::Vector3 target_pos(req.model_state.pose.position.x,req.model_state.pose.position.y,req.model_state.pose.position.z); 01352 gazebo::Quatern 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); 01353 gazebo::Pose3d target_pose(target_pos,target_rot); 01354 gazebo::Vector3 target_pos_dot(req.model_state.twist.linear.x,req.model_state.twist.linear.y,req.model_state.twist.linear.z); 01355 gazebo::Vector3 target_rot_dot(req.model_state.twist.angular.x,req.model_state.twist.angular.y,req.model_state.twist.angular.z); 01356 01357 gazebo::Model* model = dynamic_cast<gazebo::Model*>(gazebo::World::Instance()->GetEntityByName(req.model_state.model_name)); 01358 if (!model) 01359 { 01360 ROS_ERROR("SetModelState: model [%s] does not exist",req.model_state.model_name.c_str()); 01361 res.success = false; 01362 res.status_message = "SetModelState: model does not exist"; 01363 return false; 01364 } 01365 else 01366 { 01367 gazebo::Entity* relative_entity = gazebo::World::Instance()->GetEntityByName(req.model_state.reference_frame); 01368 if (relative_entity) 01369 { 01370 gazebo::Pose3d frame_pose = relative_entity->GetWorldPose(); // - this->myBody->GetCoMPose(); 01371 gazebo::Vector3 frame_pos = frame_pose.pos; 01372 gazebo::Quatern frame_rot = frame_pose.rot; 01373 01374 //std::cout << " debug : " << relative_entity->GetName() << " : " << frame_pose << " : " << target_pose << std::endl; 01375 //target_pose = frame_pose + target_pose; // seems buggy, use my own 01376 target_pose.pos = frame_pos + frame_rot.RotateVector(target_pos); 01377 target_pose.rot = frame_rot * target_pose.rot; 01378 } 01380 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" ) 01381 { 01382 ROS_DEBUG("SetModelState: reference frame is empty/world/map, usig inertial frame"); 01383 } 01384 else 01385 { 01386 ROS_ERROR("SetModelState: for model[%s], specified reference frame entity [%s] does not exist", 01387 req.model_state.model_name.c_str(),req.model_state.reference_frame.c_str()); 01388 res.success = false; 01389 res.status_message = "SetModelState: specified reference frame entity does not exist"; 01390 return false; 01391 } 01392 01393 //ROS_ERROR("target state: %f %f %f",target_pose.pos.x,target_pose.pos.y,target_pose.pos.z); 01394 bool is_paused = gazebo::Simulator::Instance()->IsPaused(); 01395 gazebo::Simulator::Instance()->SetPaused(true); 01396 model->SetWorldPose(target_pose); 01397 gazebo::Simulator::Instance()->SetPaused(is_paused); 01398 //gazebo::Pose3d p3d = model->GetWorldPose(); 01399 //ROS_ERROR("model updated state: %f %f %f",p3d.pos.x,p3d.pos.y,p3d.pos.z); 01400 01401 // set model velocity 01402 model->SetLinearVel(target_pos_dot); 01403 model->SetAngularVel(target_rot_dot); 01404 01405 res.success = true; 01406 res.status_message = "SetModelState: set model state done"; 01407 return true; 01408 } 01409 } 01410 01413 void updateModelState(const gazebo_msgs::ModelState::ConstPtr& model_state) 01414 { 01415 gazebo::Vector3 target_pos(model_state->pose.position.x,model_state->pose.position.y,model_state->pose.position.z); 01416 gazebo::Quatern target_rot(model_state->pose.orientation.w,model_state->pose.orientation.x,model_state->pose.orientation.y,model_state->pose.orientation.z); 01417 gazebo::Pose3d target_pose(target_pos,target_rot); 01418 gazebo::Vector3 target_pos_dot(model_state->twist.linear.x,model_state->twist.linear.y,model_state->twist.linear.z); 01419 gazebo::Vector3 target_rot_dot(model_state->twist.angular.x,model_state->twist.angular.y,model_state->twist.angular.z); 01420 01421 gazebo::Model* model = dynamic_cast<gazebo::Model*>(gazebo::World::Instance()->GetEntityByName(model_state->model_name)); 01422 if (!model) 01423 { 01424 ROS_ERROR("updateModelState: model [%s] does not exist",model_state->model_name.c_str()); 01425 return; 01426 } 01427 else 01428 { 01429 gazebo::Entity* relative_entity = NULL; 01430 01431 relative_entity = gazebo::World::Instance()->GetEntityByName(model_state->reference_frame); 01432 if (relative_entity) 01433 { 01434 gazebo::Pose3d frame_pose = relative_entity->GetWorldPose(); // - this->myBody->GetCoMPose(); 01435 gazebo::Vector3 frame_pos = frame_pose.pos; 01436 gazebo::Quatern frame_rot = frame_pose.rot; 01437 01438 //std::cout << " debug : " << relative_entity->GetName() << " : " << frame_pose << " : " << target_pose << std::endl; 01439 //target_pose = frame_pose + target_pose; // seems buggy, use my own 01440 target_pose.pos = frame_pos + frame_rot.RotateVector(target_pos); 01441 target_pose.rot = frame_rot * target_pose.rot; 01442 } 01443 else if (model_state->reference_frame == "" || model_state->reference_frame == "world" || model_state->reference_frame == "map" || model_state->reference_frame == "/map" ) 01444 { 01445 ROS_DEBUG("updateModelState: using inertial reference frame"); 01446 } 01447 else 01448 { 01449 ROS_ERROR("updateModelState: for model[%s], specified relative frame [%s] does not exist", 01450 model_state->model_name.c_str(),model_state->reference_frame.c_str()); 01451 return; 01452 } 01453 01454 bool is_paused = gazebo::Simulator::Instance()->IsPaused(); 01455 gazebo::Simulator::Instance()->SetPaused(true); 01456 model->SetWorldPose(target_pose); 01457 gazebo::Simulator::Instance()->SetPaused(is_paused); 01458 01459 // set model velocity to 0 01460 model->SetLinearVel(target_pos_dot); 01461 model->SetAngularVel(target_rot_dot); 01462 01463 return; 01464 } 01465 } 01466 01469 bool applyJointEffort(gazebo_msgs::ApplyJointEffort::Request &req,gazebo_msgs::ApplyJointEffort::Response &res) 01470 { 01471 gazebo::Joint* joint = NULL; 01472 const std::vector<gazebo::Model*> models = gazebo::World::Instance()->GetModels(); 01473 for (std::vector<gazebo::Model*>::const_iterator miter = models.begin(); miter != models.end(); miter++) 01474 { 01475 joint = (*miter)->GetJoint(req.joint_name); 01476 if (joint) break; 01477 } 01478 01479 if (joint == NULL) 01480 { 01481 res.success = false; 01482 res.status_message = "ApplyJointEffort: joint not found"; 01483 return false; 01484 } 01485 else 01486 { 01487 01488 GazeboROSNode::ForceJointJob* fjj = new GazeboROSNode::ForceJointJob; 01489 fjj->joint = joint; 01490 fjj->force = req.effort; 01491 fjj->start_time = req.start_time; 01492 if (fjj->start_time < ros::Time(gazebo::Simulator::Instance()->GetSimTime().Double())) 01493 fjj->start_time = ros::Time(gazebo::Simulator::Instance()->GetSimTime().Double()); 01494 fjj->duration = req.duration; 01495 this->lock_.lock(); 01496 this->force_joint_jobs.push_back(fjj); 01497 this->lock_.unlock(); 01498 01499 res.success = true; 01500 res.status_message = "ApplyJointEffort: effort set"; 01501 return true; 01502 } 01503 } 01504 01507 bool resetSimulation(std_srvs::Empty::Request &req,std_srvs::Empty::Response &res) 01508 { 01509 gazebo::World::Instance()->Reset(); 01510 return true; 01511 } 01512 01515 bool resetWorld(std_srvs::Empty::Request &req,std_srvs::Empty::Response &res) 01516 { 01517 gazebo::World::Instance()->Reset(); 01518 return true; 01519 } 01520 01523 bool pausePhysics(std_srvs::Empty::Request &req,std_srvs::Empty::Response &res) 01524 { 01525 gazebo::Simulator::Instance()->SetPaused(true); 01526 return true; 01527 } 01528 01531 bool unpausePhysics(std_srvs::Empty::Request &req,std_srvs::Empty::Response &res) 01532 { 01533 gazebo::Simulator::Instance()->SetPaused(false); 01534 return true; 01535 } 01536 01539 bool clearJointForces(gazebo_msgs::JointRequest::Request &req,gazebo_msgs::JointRequest::Response &res) 01540 { 01541 return this->clearJointForces(req.joint_name); 01542 } 01543 bool clearJointForces(std::string joint_name) 01544 { 01545 bool search = true; 01546 this->lock_.lock(); 01547 while(search) 01548 { 01549 search = false; 01550 for (std::vector<GazeboROSNode::ForceJointJob*>::iterator iter=this->force_joint_jobs.begin();iter!=this->force_joint_jobs.end();iter++) 01551 { 01552 if ((*iter)->joint->GetName() == joint_name) 01553 { 01554 // found one, search through again 01555 search = true; 01556 delete (*iter); 01557 this->force_joint_jobs.erase(iter); 01558 break; 01559 } 01560 } 01561 } 01562 this->lock_.unlock(); 01563 return true; 01564 } 01565 01568 bool clearBodyWrenches(gazebo_msgs::BodyRequest::Request &req,gazebo_msgs::BodyRequest::Response &res) 01569 { 01570 return this->clearBodyWrenches(req.body_name); 01571 } 01572 bool clearBodyWrenches(std::string body_name) 01573 { 01574 bool search = true; 01575 this->lock_.lock(); 01576 while(search) 01577 { 01578 search = false; 01579 for (std::vector<GazeboROSNode::WrenchBodyJob*>::iterator iter=this->wrench_body_jobs.begin();iter!=this->wrench_body_jobs.end();iter++) 01580 { 01581 //ROS_ERROR("search %s %s",(*iter)->body->GetScopedName().c_str(), body_name.c_str()); 01582 if ((*iter)->body->GetScopedName() == body_name) 01583 { 01584 // found one, search through again 01585 search = true; 01586 delete (*iter); 01587 this->wrench_body_jobs.erase(iter); 01588 break; 01589 } 01590 } 01591 } 01592 this->lock_.unlock(); 01593 return true; 01594 } 01595 01598 bool setModelConfiguration(gazebo_msgs::SetModelConfiguration::Request &req,gazebo_msgs::SetModelConfiguration::Response &res) 01599 { 01600 std::string gazebo_model_name = req.model_name; 01601 01602 // search for model with name 01603 gazebo::Model* gazebo_model = dynamic_cast<gazebo::Model*>(gazebo::World::Instance()->GetEntityByName(gazebo_model_name)); 01604 if (gazebo_model == NULL) 01605 { 01606 ROS_ERROR("SetModelConfiguration: model [%s] does not exist",gazebo_model_name.c_str()); 01607 res.success = false; 01608 res.status_message = "SetModelConfiguration: model does not exist"; 01609 return false; 01610 } 01611 01612 // make the service call to pause gazebo 01613 bool is_paused = gazebo::Simulator::Instance()->IsPaused(); 01614 if (!is_paused) gazebo::Simulator::Instance()->SetPaused(true); 01615 01616 setModelJointPositions(gazebo_model,req.joint_names,req.joint_positions); 01617 01618 // resume paused state before this call 01619 gazebo::Simulator::Instance()->SetPaused(is_paused); 01620 01621 res.success = true; 01622 res.status_message = "SetModelConfiguration: success"; 01623 return true; 01624 } 01625 01626 void setModelJointPositions(gazebo::Model* gazebo_model,std::vector<std::string> joint_names, std::vector<double> joint_positions) 01627 { 01628 01629 // go through all joints in this model and update each one 01630 // for each joint update, recursively update all children 01631 int joint_count = gazebo_model->GetJointCount(); 01632 for (int i = 0; i < joint_count ; i++) 01633 { 01634 gazebo::Joint* joint = gazebo_model->GetJoint(i); 01635 01636 double target_position; 01637 // only deal with hinge and revolute joints in the user request joint_names list 01638 gazebo::Joint::Type type = joint->GetType(); 01639 if ((type == gazebo::Joint::HINGE || type == gazebo::Joint::SLIDER) 01640 && findJointPosition(target_position,joint->GetName(),joint_names,joint_positions)) 01641 { 01642 gazebo::Vector3 anchor = joint->GetAnchor(0); // worldPose.pos of anchor point 01643 gazebo::Vector3 axis = joint->GetAxis(0); // joint axis in world frame 01644 double current_position = joint->GetAngle(0).GetAsRadian(); // joint position 01645 //std::cout << " name[" << joint->GetName() << "] axis[" << axis << "] target [" << target_position << "]\n"; 01646 01647 gazebo::Body* body0 = getParentBody(joint); 01648 gazebo::Body* body1 = getChildBody(joint); 01649 01650 if (body0 && body1 && body0->GetName() != body1->GetName()) 01651 { 01652 01653 // transform about the current anchor, about the axis 01654 switch(type) 01655 { 01656 case gazebo::Joint::HINGE: { 01657 // rotate child (body1) about anchor point, by delta-angle along axis 01658 double dangle = target_position - current_position; 01659 rotateBodyAndChildren(body1, anchor, axis, dangle); 01660 01661 break; 01662 } 01663 case gazebo::Joint::SLIDER: { 01664 double dposition = target_position - current_position; 01665 slideBodyAndChildren(body1, anchor, axis, dposition); 01666 01667 break; 01668 } 01669 default: { 01670 ROS_WARN("Setting non HINGE/SLIDER joint types not implemented [%s]",joint->GetName().c_str()); 01671 break; 01672 } 01673 } 01674 01675 } 01676 01677 } 01678 } 01679 } 01680 01681 gazebo::Body* getChildBody(gazebo::Joint* joint) 01682 { 01683 // anchor is with the child (same as urdf) 01684 if (joint->GetJointBody(0) == joint->anchorBody) 01685 return joint->GetJointBody(0); 01686 else if (joint->GetJointBody(1) == joint->anchorBody) 01687 return joint->GetJointBody(1); 01688 else 01689 return NULL; 01690 } 01691 01692 gazebo::Body* getParentBody(gazebo::Joint* joint) 01693 { 01694 if (joint->GetJointBody(0) == joint->anchorBody) 01695 return joint->GetJointBody(1); 01696 else if (joint->GetJointBody(1) == joint->anchorBody) 01697 return joint->GetJointBody(0); 01698 else 01699 return NULL; 01700 } 01701 01702 void rotateBodyAndChildren(gazebo::Body* body1, gazebo::Vector3 anchor, gazebo::Vector3 axis, double dangle, bool update_children = true) 01703 { 01704 gazebo::Pose3d world_pose = body1->GetWorldPose(); 01705 gazebo::Pose3d relative_pose(world_pose.pos - anchor,world_pose.rot); // relative to anchor point 01706 // take axis rotation and turn it int a quaternion 01707 gazebo::Quatern rotation; rotation.SetFromAxis(axis.x,axis.y,axis.z,dangle); 01708 // rotate relative pose by rotation 01709 gazebo::Pose3d new_relative_pose; 01710 new_relative_pose.pos = rotation.RotateVector(relative_pose.pos); 01711 new_relative_pose.rot = rotation * relative_pose.rot; 01712 gazebo::Pose3d new_world_pose(new_relative_pose.pos+anchor,new_relative_pose.rot); 01713 body1->SetWorldPose(new_world_pose); 01714 // std::cout << " body[" << body1->GetName() 01715 // << "] wp[" << world_pose 01716 // << "] anchor[" << anchor 01717 // << "] axis[" << axis 01718 // << "] dangle [" << dangle 01719 // << "]\n"; 01720 01721 // recurse through children bodies 01722 std::vector<gazebo::Body*> bodies; 01723 if (update_children) getAllChildrenBodies(bodies, body1->GetModel(), body1); 01724 for (std::vector<gazebo::Body*>::iterator bit = bodies.begin(); bit != bodies.end(); bit++) 01725 rotateBodyAndChildren((*bit), anchor, axis, dangle,false); 01726 01727 } 01728 01729 void slideBodyAndChildren(gazebo::Body* body1, gazebo::Vector3 anchor, gazebo::Vector3 axis, double dposition, bool update_children = true) 01730 { 01731 gazebo::Pose3d world_pose = body1->GetWorldPose(); 01732 gazebo::Pose3d relative_pose(world_pose.pos - anchor,world_pose.rot); // relative to anchor point 01733 // slide relative pose by dposition along axis 01734 gazebo::Pose3d new_relative_pose; 01735 new_relative_pose.pos = relative_pose.pos + axis * dposition; 01736 new_relative_pose.rot = relative_pose.rot; 01737 gazebo::Pose3d new_world_pose(new_relative_pose.pos+anchor,new_relative_pose.rot); 01738 body1->SetWorldPose(new_world_pose); 01739 // std::cout << " body[" << body1->GetName() 01740 // << "] wp[" << world_pose 01741 // << "] anchor[" << anchor 01742 // << "] axis[" << axis 01743 // << "] dposition [" << dposition 01744 // << "]\n"; 01745 01746 // recurse through children bodies 01747 std::vector<gazebo::Body*> bodies; 01748 if (update_children) getAllChildrenBodies(bodies, body1->GetModel(), body1); 01749 for (std::vector<gazebo::Body*>::iterator bit = bodies.begin(); bit != bodies.end(); bit++) 01750 slideBodyAndChildren((*bit), anchor, axis, dposition,false); 01751 01752 } 01753 01754 void getAllChildrenBodies(std::vector<gazebo::Body*> &bodies, gazebo::Model* model, gazebo::Body* body) 01755 { 01756 // strategy, for each child, recursively look for children 01757 // for each child, also look for parents to catch multiple roots 01758 if (model) 01759 { 01760 int joint_count = model->GetJointCount(); 01761 for (int i = 0; i < joint_count ; i++) 01762 { 01763 gazebo::Joint* joint = model->GetJoint(i); 01764 // recurse through children connected by joints 01765 gazebo::Body* body0 = getParentBody(joint); 01766 gazebo::Body* body1 = getChildBody(joint); 01767 if (body0 && body1 01768 && body0->GetName() != body1->GetName() 01769 && body0->GetName() == body->GetName() 01770 && !inBodies(body1,bodies)) 01771 { 01772 bodies.push_back(body1); 01773 getAllChildrenBodies(bodies, body1->GetModel(), body1); 01774 getAllParentBodies(bodies, body1->GetModel(), body1, body); 01775 } 01776 } 01777 } 01778 } 01779 void getAllParentBodies(std::vector<gazebo::Body*> &bodies, gazebo::Model* model, gazebo::Body* body, gazebo::Body* orig_parent_body) 01780 { 01781 if (model) 01782 { 01783 int joint_count = model->GetJointCount(); 01784 for (int i = 0; i < joint_count ; i++) 01785 { 01786 gazebo::Joint* joint = model->GetJoint(i); 01787 // recurse through children connected by joints 01788 gazebo::Body* body0 = getParentBody(joint); 01789 gazebo::Body* body1 = getChildBody(joint); 01790 if (body0 && body1 01791 && body0->GetName() != body1->GetName() 01792 && body1->GetName() == body->GetName() 01793 && body0->GetName() != orig_parent_body->GetName() 01794 && !inBodies(body0,bodies)) 01795 { 01796 bodies.push_back(body0); 01797 getAllParentBodies(bodies, body0->GetModel(), body1, orig_parent_body); 01798 } 01799 } 01800 } 01801 } 01802 01803 bool inBodies(gazebo::Body* body,std::vector<gazebo::Body*> bodies) 01804 { 01805 for (std::vector<gazebo::Body*>::iterator bit = bodies.begin(); bit != bodies.end(); bit++) 01806 if ((*bit)->GetName() == body->GetName()) return true; 01807 return false; 01808 } 01809 01810 bool findJointPosition(double &position, std::string name, std::vector<std::string> joint_names, std::vector<double> joint_positions) 01811 { 01812 position = 0; 01813 std::vector<std::string>::iterator jit = joint_names.begin(); 01814 std::vector<double>::iterator pit = joint_positions.begin(); 01815 for(;jit != joint_names.end(),pit != joint_positions.end(); jit++,pit++) 01816 { 01817 if (name == (*jit)) 01818 { 01819 position = (*pit); 01820 return true; 01821 } 01822 } 01823 return false; 01824 } 01825 01826 01829 bool setLinkState(gazebo_msgs::SetLinkState::Request &req,gazebo_msgs::SetLinkState::Response &res) 01830 { 01831 gazebo::Body* body = dynamic_cast<gazebo::Body*>(gazebo::World::Instance()->GetEntityByName(req.link_state.link_name)); 01832 gazebo::Body* frame = dynamic_cast<gazebo::Body*>(gazebo::World::Instance()->GetEntityByName(req.link_state.reference_frame)); 01833 if (!body) 01834 { 01835 ROS_ERROR("SetLinkState: link [%s] does not exist",req.link_state.link_name.c_str()); 01836 res.success = false; 01837 res.status_message = "SetLinkState: link does not exist"; 01838 return false; 01839 } 01840 01842 // get reference frame (body/model(link)) pose and 01843 // transform target pose to absolute world frame 01844 gazebo::Vector3 target_pos(req.link_state.pose.position.x,req.link_state.pose.position.y,req.link_state.pose.position.z); 01845 gazebo::Quatern 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); 01846 gazebo::Pose3d target_pose(target_pos,target_rot); 01847 gazebo::Vector3 target_linear_vel(req.link_state.twist.linear.x,req.link_state.twist.linear.y,req.link_state.twist.linear.z); 01848 gazebo::Vector3 target_angular_vel(req.link_state.twist.angular.x,req.link_state.twist.angular.y,req.link_state.twist.angular.z); 01849 01850 if (frame) 01851 { 01852 gazebo::Pose3d frame_pose = frame->GetWorldPose(); // - this->myBody->GetCoMPose(); 01853 gazebo::Vector3 frame_pos = frame_pose.pos; 01854 gazebo::Quatern frame_rot = frame_pose.rot; 01855 01856 //std::cout << " debug : " << frame->GetName() << " : " << frame_pose << " : " << target_pose << std::endl; 01857 //target_pose = frame_pose + target_pose; // seems buggy, use my own 01858 target_pose.pos = frame_pos + frame_rot.RotateVector(target_pos); 01859 target_pose.rot = frame_rot * target_pose.rot; 01860 01861 gazebo::Vector3 frame_linear_vel = frame->GetWorldLinearVel(); 01862 gazebo::Vector3 frame_angular_vel = frame->GetWorldAngularVel(); 01863 target_linear_vel -= frame_linear_vel; 01864 target_angular_vel -= frame_angular_vel; 01865 } 01866 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") 01867 { 01868 ROS_INFO("SetLinkState: reference_frame is empty/world/map, using inertial frame"); 01869 } 01870 else 01871 { 01872 ROS_ERROR("SetLinkState: reference_frame is not a valid link name"); 01873 res.success = false; 01874 res.status_message = "SetLinkState: failed"; 01875 return false; 01876 } 01877 //target_pose.rot.Normalize(); 01878 01879 //std::cout << " debug : " << target_pose << std::endl; 01880 //boost::recursive_mutex::scoped_lock lock(*Simulator::Instance()->GetMRMutex()); 01881 01882 bool is_paused = gazebo::Simulator::Instance()->IsPaused(); 01883 if (!is_paused) gazebo::Simulator::Instance()->SetPaused(true); 01884 body->SetWorldPose(target_pose); 01885 gazebo::Simulator::Instance()->SetPaused(is_paused); 01886 01887 // set body velocity to desired twist 01888 body->SetLinearVel(target_linear_vel); 01889 body->SetAngularVel(target_angular_vel); 01890 01891 res.success = true; 01892 res.status_message = "SetLinkState: success"; 01893 return true; 01894 } 01895 01898 void updateLinkState(const gazebo_msgs::LinkState::ConstPtr& link_state) 01899 { 01900 gazebo::Body* body = dynamic_cast<gazebo::Body*>(gazebo::World::Instance()->GetEntityByName(link_state->link_name)); 01901 gazebo::Body* frame = dynamic_cast<gazebo::Body*>(gazebo::World::Instance()->GetEntityByName(link_state->reference_frame)); 01902 if (!body) 01903 { 01904 ROS_ERROR("SetLinkState: link [%s] does not exist",link_state->link_name.c_str()); 01905 return; 01906 } 01907 else 01908 { 01910 // get reference frame (body/model(link)) pose and 01911 // transform target pose to absolute world frame 01912 gazebo::Vector3 target_pos(link_state->pose.position.x,link_state->pose.position.y,link_state->pose.position.z); 01913 gazebo::Quatern target_rot(link_state->pose.orientation.w,link_state->pose.orientation.x,link_state->pose.orientation.y,link_state->pose.orientation.z); 01914 gazebo::Pose3d target_pose(target_pos,target_rot); 01915 gazebo::Vector3 target_linear_vel(link_state->twist.linear.x,link_state->twist.linear.y,link_state->twist.linear.z); 01916 gazebo::Vector3 target_angular_vel(link_state->twist.angular.x,link_state->twist.angular.y,link_state->twist.angular.z); 01917 01918 if (frame) 01919 { 01920 gazebo::Pose3d frame_pose = frame->GetWorldPose(); // - this->myBody->GetCoMPose(); 01921 gazebo::Vector3 frame_pos = frame_pose.pos; 01922 gazebo::Quatern frame_rot = frame_pose.rot; 01923 01924 //std::cout << " debug : " << frame->GetName() << " : " << frame_pose << " : " << target_pose << std::endl; 01925 //target_pose = frame_pose + target_pose; // seems buggy, use my own 01926 target_pose.pos = frame_pos + frame_rot.RotateVector(target_pos); 01927 target_pose.rot = frame_rot * target_pose.rot; 01928 01929 gazebo::Vector3 frame_linear_vel = frame->GetWorldLinearVel(); 01930 gazebo::Vector3 frame_angular_vel = frame->GetWorldAngularVel(); 01931 target_linear_vel -= frame_linear_vel; 01932 target_angular_vel -= frame_angular_vel; 01933 } 01934 else if (link_state->reference_frame == "" || link_state->reference_frame == "world" || link_state->reference_frame == "map" || link_state->reference_frame == "/map") 01935 { 01936 ROS_DEBUG("SetLinkState: reference_frame is empty/world/map, using inertial frame"); 01937 } 01938 else 01939 { 01940 ROS_ERROR("SetLinkState: reference_frame is not a valid link name"); 01941 return; 01942 } 01943 01944 //std::cout << " debug : " << target_pose << std::endl; 01945 //boost::recursive_mutex::scoped_lock lock(*Simulator::Instance()->GetMRMutex()); 01946 01947 bool is_paused = gazebo::Simulator::Instance()->IsPaused(); 01948 gazebo::Simulator::Instance()->SetPaused(true); 01949 body->SetWorldPose(target_pose); 01950 gazebo::Simulator::Instance()->SetPaused(is_paused); 01951 01952 // set body velocity to desired twist 01953 body->SetLinearVel(target_linear_vel); 01954 body->SetAngularVel(target_angular_vel); 01955 01956 } 01957 01958 } 01959 01960 01964 void transformWrench( gazebo::Vector3 &target_force, gazebo::Vector3 &target_torque, 01965 gazebo::Vector3 reference_force, gazebo::Vector3 reference_torque, 01966 gazebo::Pose3d target_to_reference ) 01967 { 01968 // rotate force into target frame 01969 target_force = target_to_reference.rot.RotateVector(reference_force); 01970 // rotate torque into target frame 01971 target_torque = target_to_reference.rot.RotateVector(reference_torque); 01972 01973 // target force is the refence force rotated by the target->reference transform 01974 target_force = target_force; 01975 target_torque = target_torque + target_to_reference.pos.GetCrossProd(target_force); 01976 } 01977 01980 bool applyBodyWrench(gazebo_msgs::ApplyBodyWrench::Request &req,gazebo_msgs::ApplyBodyWrench::Response &res) 01981 { 01982 gazebo::Body* body = dynamic_cast<gazebo::Body*>(gazebo::World::Instance()->GetEntityByName(req.body_name)); 01983 gazebo::Body* frame = dynamic_cast<gazebo::Body*>(gazebo::World::Instance()->GetEntityByName(req.reference_frame)); 01984 01985 if (!body) 01986 { 01987 ROS_ERROR("ApplyBodyWrench: body [%s] does not exist",req.body_name.c_str()); 01988 res.success = false; 01989 res.status_message = "ApplyBodyWrench: body does not exist"; 01990 return false; 01991 } 01992 01993 // target wrench 01994 gazebo::Vector3 reference_force(req.wrench.force.x,req.wrench.force.y,req.wrench.force.z); 01995 gazebo::Vector3 reference_torque(req.wrench.torque.x,req.wrench.torque.y,req.wrench.torque.z); 01996 gazebo::Vector3 reference_point(req.reference_point.x,req.reference_point.y,req.reference_point.z); 01997 01998 gazebo::Vector3 target_force; 01999 gazebo::Vector3 target_torque; 02000 02003 reference_torque = reference_torque + reference_point.GetCrossProd(reference_force); 02004 02006 if (frame) 02007 { 02008 // FIXME 02009 // get reference frame (body/model(body)) pose and 02010 // transform target pose to absolute world frame 02011 // @todo: need to modify wrench (target force and torque by frame) 02012 // transform wrench from reference_point in reference_frame 02013 // into the reference frame of the body 02014 // first, translate by reference point to the body frame 02015 gazebo::Pose3d target_to_reference = frame->GetWorldPose() - body->GetWorldPose(); 02016 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]", 02017 body->GetWorldPose().pos.x, 02018 body->GetWorldPose().pos.y, 02019 body->GetWorldPose().pos.z, 02020 body->GetWorldPose().rot.GetAsEuler().x, 02021 body->GetWorldPose().rot.GetAsEuler().y, 02022 body->GetWorldPose().rot.GetAsEuler().z, 02023 frame->GetWorldPose().pos.x, 02024 frame->GetWorldPose().pos.y, 02025 frame->GetWorldPose().pos.z, 02026 frame->GetWorldPose().rot.GetAsEuler().x, 02027 frame->GetWorldPose().rot.GetAsEuler().y, 02028 frame->GetWorldPose().rot.GetAsEuler().z, 02029 target_to_reference.pos.x, 02030 target_to_reference.pos.y, 02031 target_to_reference.pos.z, 02032 target_to_reference.rot.GetAsEuler().x, 02033 target_to_reference.rot.GetAsEuler().y, 02034 target_to_reference.rot.GetAsEuler().z 02035 ); 02036 this->transformWrench(target_force, target_torque, reference_force, reference_torque, target_to_reference); 02037 ROS_ERROR("wrench defined as [%s]:[%f %f %f, %f %f %f] --> applied as [%s]:[%f %f %f, %f %f %f]", 02038 frame->GetName().c_str(), 02039 reference_force.x, 02040 reference_force.y, 02041 reference_force.z, 02042 reference_torque.x, 02043 reference_torque.y, 02044 reference_torque.z, 02045 body->GetName().c_str(), 02046 target_force.x, 02047 target_force.y, 02048 target_force.z, 02049 target_torque.x, 02050 target_torque.y, 02051 target_torque.z 02052 ); 02053 02054 } 02055 else if (req.reference_frame == "" || req.reference_frame == "world" || req.reference_frame == "map" || req.reference_frame == "/map") 02056 { 02057 ROS_INFO("ApplyBodyWrench: reference_frame is empty/world/map, using inertial frame, transferring from body relative to inertial frame"); 02058 // FIXME: transfer to inertial frame 02059 gazebo::Pose3d target_to_reference = body->GetWorldPose(); 02060 target_force = reference_force; 02061 target_torque = reference_torque; 02062 02063 } 02064 else 02065 { 02066 ROS_ERROR("ApplyBodyWrench: reference_frame is not a valid link name"); 02067 res.success = false; 02068 res.status_message = "ApplyBodyWrench: reference_frame not found"; 02069 return false; 02070 } 02071 02072 // apply wrench 02073 // schedule a job to do below at appropriate times: 02074 // body->SetForce(force) 02075 // body->SetTorque(torque) 02076 GazeboROSNode::WrenchBodyJob* wej = new GazeboROSNode::WrenchBodyJob; 02077 wej->body = body; 02078 wej->force = target_force; 02079 wej->torque = target_torque; 02080 wej->start_time = req.start_time; 02081 if (wej->start_time < ros::Time(gazebo::Simulator::Instance()->GetSimTime().Double())) 02082 wej->start_time = ros::Time(gazebo::Simulator::Instance()->GetSimTime().Double()); 02083 wej->duration = req.duration; 02084 this->lock_.lock(); 02085 this->wrench_body_jobs.push_back(wej); 02086 this->lock_.unlock(); 02087 02088 res.success = true; 02089 res.status_message = ""; 02090 return true; 02091 } 02092 02093 02094 private: 02095 ros::NodeHandle rosnode_; 02096 ros::CallbackQueue gazebo_queue_; 02097 boost::thread* gazebo_callback_queue_thread_; 02098 02099 ros::ServiceServer spawn_urdf_model_service_; 02100 ros::ServiceServer spawn_urdf_gazebo_service_; 02101 ros::ServiceServer delete_model_service_; 02102 ros::ServiceServer get_model_state_service_; 02103 ros::ServiceServer get_model_properties_service_; 02104 ros::ServiceServer get_world_properties_service_; 02105 ros::ServiceServer get_joint_properties_service_; 02106 ros::ServiceServer get_link_properties_service_; 02107 ros::ServiceServer get_link_state_service_; 02108 ros::ServiceServer set_link_properties_service_; 02109 ros::ServiceServer set_physics_properties_service_; 02110 ros::ServiceServer get_physics_properties_service_; 02111 ros::ServiceServer apply_body_wrench_service_; 02112 ros::ServiceServer set_joint_properties_service_; 02113 ros::ServiceServer set_model_state_service_; 02114 ros::ServiceServer apply_joint_effort_service_; 02115 ros::ServiceServer set_model_configuration_service_; 02116 ros::ServiceServer set_link_state_service_; 02117 ros::ServiceServer reset_simulation_service_; 02118 ros::ServiceServer reset_world_service_; 02119 ros::ServiceServer pause_physics_service_; 02120 ros::ServiceServer unpause_physics_service_; 02121 ros::ServiceServer clear_joint_forces_service_; 02122 ros::ServiceServer clear_body_wrenches_service_; 02123 ros::Subscriber set_link_state_topic_; 02124 ros::Subscriber set_model_state_topic_; 02125 ros::Publisher pub_clock_; 02126 ros::Publisher pub_link_states_; 02127 ros::Publisher pub_model_states_; 02128 ros::Publisher pub_gazebo_paused_; 02129 int pub_link_states_connection_count_; 02130 int pub_model_states_connection_count_; 02131 02132 // physics dynamic reconfigure 02133 boost::thread* physics_reconfigure_thread_; 02134 bool physics_reconfigure_initialized_; 02135 02136 ros::ServiceClient physics_reconfigure_set_client_; 02137 ros::ServiceClient physics_reconfigure_get_client_; 02138 02139 void PhysicsReconfigureCallback(gazebo::PhysicsConfig &config, uint32_t level) 02140 { 02141 if (!physics_reconfigure_initialized_) 02142 { 02143 gazebo_msgs::GetPhysicsProperties srv; 02144 this->physics_reconfigure_get_client_.call(srv); 02145 02146 config.time_step = srv.response.time_step; 02147 config.max_update_rate = srv.response.max_update_rate; 02148 config.gravity_x = srv.response.gravity.x; 02149 config.gravity_y = srv.response.gravity.y; 02150 config.gravity_z = srv.response.gravity.z; 02151 config.auto_disable_bodies = srv.response.ode_config.auto_disable_bodies; 02152 config.sor_pgs_precon_iters = srv.response.ode_config.sor_pgs_precon_iters; 02153 config.sor_pgs_iters = srv.response.ode_config.sor_pgs_iters; 02154 config.sor_pgs_rms_error_tol = srv.response.ode_config.sor_pgs_rms_error_tol; 02155 config.sor_pgs_w = srv.response.ode_config.sor_pgs_w; 02156 config.contact_surface_layer = srv.response.ode_config.contact_surface_layer; 02157 config.contact_max_correcting_vel = srv.response.ode_config.contact_max_correcting_vel; 02158 config.cfm = srv.response.ode_config.cfm; 02159 config.erp = srv.response.ode_config.erp; 02160 config.max_contacts = srv.response.ode_config.max_contacts; 02161 physics_reconfigure_initialized_ = true; 02162 } 02163 else 02164 { 02165 bool changed = false; 02166 gazebo_msgs::GetPhysicsProperties srv; 02167 this->physics_reconfigure_get_client_.call(srv); 02168 02169 // check for changes 02170 if (config.time_step != srv.response.time_step) changed = true; 02171 if (config.max_update_rate != srv.response.max_update_rate) changed = true; 02172 if (config.gravity_x != srv.response.gravity.x) changed = true; 02173 if (config.gravity_y != srv.response.gravity.y) changed = true; 02174 if (config.gravity_z != srv.response.gravity.z) changed = true; 02175 if (config.auto_disable_bodies != srv.response.ode_config.auto_disable_bodies) changed = true; 02176 if ((uint32_t)config.sor_pgs_precon_iters != srv.response.ode_config.sor_pgs_precon_iters) changed = true; 02177 if ((uint32_t)config.sor_pgs_iters != srv.response.ode_config.sor_pgs_iters) changed = true; 02178 if (config.sor_pgs_rms_error_tol != srv.response.ode_config.sor_pgs_rms_error_tol) changed = true; 02179 if (config.sor_pgs_w != srv.response.ode_config.sor_pgs_w) changed = true; 02180 if (config.contact_surface_layer != srv.response.ode_config.contact_surface_layer) changed = true; 02181 if (config.contact_max_correcting_vel != srv.response.ode_config.contact_max_correcting_vel) changed = true; 02182 if (config.cfm != srv.response.ode_config.cfm) changed = true; 02183 if (config.erp != srv.response.ode_config.erp) changed = true; 02184 if ((uint32_t)config.max_contacts != srv.response.ode_config.max_contacts) changed = true; 02185 02186 if (changed) 02187 { 02188 // pause simulation if requested 02189 gazebo_msgs::SetPhysicsProperties srv; 02190 srv.request.time_step = config.time_step ; 02191 srv.request.max_update_rate = config.max_update_rate ; 02192 srv.request.gravity.x = config.gravity_x ; 02193 srv.request.gravity.y = config.gravity_y ; 02194 srv.request.gravity.z = config.gravity_z ; 02195 srv.request.ode_config.auto_disable_bodies = config.auto_disable_bodies ; 02196 srv.request.ode_config.sor_pgs_precon_iters = config.sor_pgs_precon_iters ; 02197 srv.request.ode_config.sor_pgs_iters = config.sor_pgs_iters ; 02198 srv.request.ode_config.sor_pgs_rms_error_tol = config.sor_pgs_rms_error_tol ; 02199 srv.request.ode_config.sor_pgs_w = config.sor_pgs_w ; 02200 srv.request.ode_config.contact_surface_layer = config.contact_surface_layer ; 02201 srv.request.ode_config.contact_max_correcting_vel = config.contact_max_correcting_vel ; 02202 srv.request.ode_config.cfm = config.cfm ; 02203 srv.request.ode_config.erp = config.erp ; 02204 srv.request.ode_config.max_contacts = config.max_contacts ; 02205 this->physics_reconfigure_set_client_.call(srv); 02206 ROS_INFO("physics dynamics reconfigure update complete"); 02207 } 02208 ROS_INFO("physics dynamics reconfigure complete"); 02209 } 02210 } 02211 02212 void PhysicsReconfigureNode() 02213 { 02214 ros::NodeHandle node_handle; 02215 this->physics_reconfigure_set_client_ = node_handle.serviceClient<gazebo_msgs::SetPhysicsProperties>("/gazebo/set_physics_properties"); 02216 this->physics_reconfigure_get_client_ = node_handle.serviceClient<gazebo_msgs::GetPhysicsProperties>("/gazebo/get_physics_properties"); 02217 this->physics_reconfigure_set_client_.waitForExistence(); 02218 this->physics_reconfigure_get_client_.waitForExistence(); 02219 02220 // for dynamic reconfigure physics 02221 // for dynamic_reconfigure 02222 dynamic_reconfigure::Server<gazebo::PhysicsConfig> physics_reconfigure_srv; 02223 dynamic_reconfigure::Server<gazebo::PhysicsConfig>::CallbackType physics_reconfigure_f; 02224 02225 physics_reconfigure_f = boost::bind(&GazeboROSNode::PhysicsReconfigureCallback, this, _1, _2); 02226 physics_reconfigure_srv.setCallback(physics_reconfigure_f); 02227 02228 ROS_INFO("Starting to spin physics dynamic reconfigure node..."); 02229 ros::Rate r(10); 02230 while(ros::ok()) 02231 { 02232 ros::spinOnce(); 02233 r.sleep(); 02234 } 02235 } 02236 02237 02239 tf::TransformBroadcaster tfbr; 02240 02242 boost::mutex lock_; 02243 02245 std::string xmlPrefix_; 02246 std::string xmlSuffix_; 02247 02249 void SetupTransform(btTransform &transform, urdf::Pose pose) 02250 { 02251 btMatrix3x3 mat; 02252 mat.setRotation(btQuaternion(pose.rotation.x,pose.rotation.y,pose.rotation.z,pose.rotation.w)); 02253 transform = btTransform(mat,btVector3(pose.position.x,pose.position.y,pose.position.z)); 02254 } 02255 void SetupTransform(btTransform &transform, geometry_msgs::Pose pose) 02256 { 02257 btMatrix3x3 mat; 02258 mat.setRotation(btQuaternion(pose.orientation.x,pose.orientation.y,pose.orientation.z,pose.orientation.w)); 02259 transform = btTransform(mat,btVector3(pose.position.x,pose.position.y,pose.position.z)); 02260 } 02261 02262 02263 02264 02266 bool IsURDF(std::string model_xml) 02267 { 02268 TiXmlDocument doc_in; 02269 doc_in.Parse(model_xml.c_str()); 02270 if (doc_in.FirstChild("robot")) 02271 return true; 02272 else 02273 return false; 02274 } 02275 bool IsColladaData(const std::string& data) // copied from urdf/src/model.cpp 02276 { 02277 return data.find("<COLLADA") != std::string::npos; 02278 } 02279 bool IsGazeboModelXML(std::string model_xml) 02280 { 02281 TiXmlDocument doc_in; 02282 doc_in.Parse(model_xml.c_str()); 02283 if (doc_in.FirstChild("model:physical")) 02284 return true; 02285 else 02286 return false; 02287 } 02288 02290 gazebo::Joint* getJointByName(std::string joint_name) 02291 { 02292 // look through all models in the world, search for body name that matches frameName 02293 std::vector<gazebo::Model*> all_models = gazebo::World::Instance()->GetModels(); 02294 for (std::vector<gazebo::Model*>::iterator miter = all_models.begin(); miter != all_models.end(); miter++) 02295 { 02296 if ((*miter) && (*miter)->GetJoint(joint_name)) 02297 return (*miter)->GetJoint(joint_name); 02298 } 02299 return NULL; 02300 } 02301 02302 02303 class WrenchBodyJob 02304 { 02305 public: 02306 gazebo::Body* body; 02307 gazebo::Vector3 force; 02308 gazebo::Vector3 torque; 02309 ros::Time start_time; 02310 ros::Duration duration; 02311 }; 02312 02313 class ForceJointJob 02314 { 02315 public: 02316 gazebo::Joint* joint; 02317 double force; // should this be a array? 02318 ros::Time start_time; 02319 ros::Duration duration; 02320 }; 02321 02322 std::vector<GazeboROSNode::WrenchBodyJob*> wrench_body_jobs; 02323 std::vector<GazeboROSNode::ForceJointJob*> force_joint_jobs; 02324 02325 double lastWrenchBodyUpdateTime; 02326 double lastForceJointUpdateTime; 02327 02330 void wrenchBodySchedulerSlot() 02331 { 02332 if (this->lastWrenchBodyUpdateTime == gazebo::Simulator::Instance()->GetSimTime().Double()) 02333 return; 02334 // MDMutex locks in case model is getting deleted, don't have to do this if we delete jobs first 02335 // boost::recursive_mutex::scoped_lock lock(*gazebo::Simulator::Instance()->GetMDMutex()); 02336 this->lock_.lock(); 02337 for (std::vector<GazeboROSNode::WrenchBodyJob*>::iterator iter=this->wrench_body_jobs.begin();iter!=this->wrench_body_jobs.end();) 02338 { 02339 // check times and apply wrench if necessary 02340 if (ros::Time(gazebo::Simulator::Instance()->GetSimTime().Double()) >= (*iter)->start_time) 02341 if (ros::Time(gazebo::Simulator::Instance()->GetSimTime().Double()) <= (*iter)->start_time+(*iter)->duration || 02342 (*iter)->duration.toSec() < 0.0) 02343 { 02344 if ((*iter)->body) // if body exists 02345 { 02346 (*iter)->body->SetForce((*iter)->force); 02347 (*iter)->body->SetTorque((*iter)->torque); 02348 } 02349 else 02350 (*iter)->duration.fromSec(0.0); // mark for delete 02351 } 02352 02353 if (ros::Time(gazebo::Simulator::Instance()->GetSimTime().Double()) > (*iter)->start_time+(*iter)->duration && 02354 (*iter)->duration.toSec() >= 0.0) 02355 { 02356 // remove from queue once expires 02357 delete (*iter); 02358 this->wrench_body_jobs.erase(iter); 02359 } 02360 else 02361 iter++; 02362 } 02363 this->lastWrenchBodyUpdateTime = gazebo::Simulator::Instance()->GetSimTime().Double(); 02364 this->lock_.unlock(); 02365 } 02366 02369 void forceJointSchedulerSlot() 02370 { 02371 if (this->lastForceJointUpdateTime == gazebo::Simulator::Instance()->GetSimTime().Double()) 02372 return; 02373 // MDMutex locks in case model is getting deleted, don't have to do this if we delete jobs first 02374 // boost::recursive_mutex::scoped_lock lock(*gazebo::Simulator::Instance()->GetMDMutex()); 02375 this->lock_.lock(); 02376 for (std::vector<GazeboROSNode::ForceJointJob*>::iterator iter=this->force_joint_jobs.begin();iter!=this->force_joint_jobs.end();) 02377 { 02378 // check times and apply force if necessary 02379 if (ros::Time(gazebo::Simulator::Instance()->GetSimTime().Double()) >= (*iter)->start_time) 02380 if (ros::Time(gazebo::Simulator::Instance()->GetSimTime().Double()) <= (*iter)->start_time+(*iter)->duration || 02381 (*iter)->duration.toSec() < 0.0) 02382 { 02383 if ((*iter)->joint) // if joint exists 02384 (*iter)->joint->SetForce(0,(*iter)->force); 02385 else 02386 (*iter)->duration.fromSec(0.0); // mark for delete 02387 } 02388 02389 if (ros::Time(gazebo::Simulator::Instance()->GetSimTime().Double()) > (*iter)->start_time+(*iter)->duration && 02390 (*iter)->duration.toSec() >= 0.0) 02391 { 02392 // remove from queue once expires 02393 this->force_joint_jobs.erase(iter); 02394 } 02395 else 02396 iter++; 02397 } 02398 this->lastForceJointUpdateTime = gazebo::Simulator::Instance()->GetSimTime().Double(); 02399 this->lock_.unlock(); 02400 } 02401 02404 void publishSimTime() 02405 { 02406 gazebo::Time currentTime = gazebo::Simulator::Instance()->GetSimTime(); 02407 rosgraph_msgs::Clock ros_time_; 02408 ros_time_.clock.fromSec(currentTime.Double()); 02409 /***************************************************************/ 02410 /* */ 02411 /* publish time to ros */ 02412 /* */ 02413 /***************************************************************/ 02414 this->pub_clock_.publish(ros_time_); 02415 } 02416 02419 void publishLinkStates() 02420 { 02421 gazebo_msgs::LinkStates link_states; 02422 // fill link_states 02423 const std::vector<gazebo::Model*> models = gazebo::World::Instance()->GetModels(); 02424 for (std::vector<gazebo::Model*>::const_iterator miter = models.begin(); miter != models.end(); miter++) 02425 { 02426 const std::vector< gazebo::Entity* > entities = (*miter)->GetChildren(); 02427 for (std::vector< gazebo::Entity* >::const_iterator eiter = entities.begin();eiter!=entities.end();eiter++) 02428 { 02429 gazebo::Body* body = dynamic_cast<gazebo::Body*>(*eiter); 02430 if (body) 02431 { 02432 link_states.name.push_back(body->GetCompleteScopedName()); 02433 geometry_msgs::Pose pose; 02434 gazebo::Pose3d body_pose = body->GetWorldPose(); // - this->myBody->GetCoMPose(); 02435 gazebo::Vector3 pos = body_pose.pos; 02436 gazebo::Quatern rot = body_pose.rot; 02437 pose.position.x = pos.x; 02438 pose.position.y = pos.y; 02439 pose.position.z = pos.z; 02440 pose.orientation.w = rot.u; 02441 pose.orientation.x = rot.x; 02442 pose.orientation.y = rot.y; 02443 pose.orientation.z = rot.z; 02444 link_states.pose.push_back(pose); 02445 gazebo::Vector3 linear_vel = body->GetWorldLinearVel(); 02446 gazebo::Vector3 angular_vel = body->GetWorldAngularVel(); 02447 geometry_msgs::Twist twist; 02448 twist.linear.x = linear_vel.x; 02449 twist.linear.y = linear_vel.y; 02450 twist.linear.z = linear_vel.z; 02451 twist.angular.x = angular_vel.x; 02452 twist.angular.y = angular_vel.y; 02453 twist.angular.z = angular_vel.z; 02454 link_states.twist.push_back(twist); 02455 } 02456 } 02457 } 02458 this->pub_link_states_.publish(link_states); 02459 } 02460 02463 void publishModelStates() 02464 { 02465 gazebo_msgs::ModelStates model_states; 02466 // fill model_states 02467 const std::vector<gazebo::Model*> models = gazebo::World::Instance()->GetModels(); 02468 for (std::vector<gazebo::Model*>::const_iterator miter = models.begin(); miter != models.end(); miter++) 02469 { 02470 model_states.name.push_back((*miter)->GetCompleteScopedName()); 02471 geometry_msgs::Pose pose; 02472 gazebo::Pose3d model_pose = (*miter)->GetWorldPose(); // - this->myBody->GetCoMPose(); 02473 gazebo::Vector3 pos = model_pose.pos; 02474 gazebo::Quatern rot = model_pose.rot; 02475 pose.position.x = pos.x; 02476 pose.position.y = pos.y; 02477 pose.position.z = pos.z; 02478 pose.orientation.w = rot.u; 02479 pose.orientation.x = rot.x; 02480 pose.orientation.y = rot.y; 02481 pose.orientation.z = rot.z; 02482 model_states.pose.push_back(pose); 02483 gazebo::Vector3 linear_vel = (*miter)->GetWorldLinearVel(); 02484 gazebo::Vector3 angular_vel = (*miter)->GetWorldAngularVel(); 02485 geometry_msgs::Twist twist; 02486 twist.linear.x = linear_vel.x; 02487 twist.linear.y = linear_vel.y; 02488 twist.linear.z = linear_vel.z; 02489 twist.angular.x = angular_vel.x; 02490 twist.angular.y = angular_vel.y; 02491 twist.angular.z = angular_vel.z; 02492 model_states.twist.push_back(twist); 02493 } 02494 this->pub_model_states_.publish(model_states); 02495 } 02496 02497 }; 02498 02500 // Main function 02501 int main(int argc, char **argv) 02502 { 02503 02504 // start a gazebo ros node 02505 ros::init(argc,argv,"gazebo",ros::init_options::NoSigintHandler);//|ros::init_options::AnonymousName); 02506 02507 // force a cpu affinity for CPU 0, this slow down sim by about 4X 02508 // cpu_set_t cpuSet; 02509 // CPU_ZERO(&cpuSet); 02510 // CPU_SET(0, &cpuSet); 02511 // sched_setaffinity( 0, sizeof(cpuSet), &cpuSet); 02512 02513 //Application Setup 02514 if (ParseArgs(argc, argv) != 0) 02515 { 02516 ros::shutdown(); 02517 return -1; 02518 } 02519 02520 PrintVersion(); 02521 02522 if (signal(SIGINT, SignalHandler) == SIG_ERR) 02523 { 02524 std::cerr << "signal(2) failed while setting up for SIGINT" << std::endl; 02525 ros::shutdown(); 02526 return -1; 02527 } 02528 02529 gazebo::Simulator::Instance()->SetCreateOgreLog( optOgreLog ); 02530 gazebo::Simulator::Instance()->SetGuiEnabled( optGuiEnabled ); 02531 gazebo::Simulator::Instance()->SetRenderEngineEnabled( optRenderEngineEnabled ); 02532 02533 // setting Gazebo Path/Resources Configurations 02534 // GAZEBO_RESOURCE_PATH, GAZEBO_PLUGIN_PATH and OGRE_RESOURCE_PATH for 02535 // GazeboConfig::gazeboPaths, GazeboConfig::pluginPaths and GazeboConfig::ogrePaths 02536 // by adding paths to GazeboConfig based on ros::package 02537 // optional: setting environment variables according to ROS 02538 // e.g. setenv("OGRE_RESOURCE_PATH",ogre_package_path.c_str(),1); 02539 // set ogre library paths by searching for package named ogre 02540 gazebo::Simulator::Instance()->GetGazeboConfig()->ClearOgrePaths(); 02541 std::string ogre_package_name("ogre"); // @todo: un hardcode this??? 02542 std::string ogre_package_path = ros::package::getPath(ogre_package_name)+std::string("/ogre/lib/OGRE"); 02543 if (ogre_package_path.empty()) 02544 ROS_DEBUG("Package[%s] does not exist, assuming user must have set OGRE_RESOURCE_PATH already.",ogre_package_name.c_str()); 02545 else 02546 { 02547 ROS_DEBUG("ogre path %s",ogre_package_path.c_str()); 02548 gazebo::Simulator::Instance()->GetGazeboConfig()->AddOgrePaths(ogre_package_path); 02549 } 02550 02551 // set gazebo media paths by adding all packages that exports "gazebo_media_path" for gazebo 02552 gazebo::Simulator::Instance()->GetGazeboConfig()->ClearGazeboPaths(); 02553 std::vector<std::string> gazebo_media_paths; 02554 ros::package::getPlugins("gazebo","gazebo_media_path",gazebo_media_paths); 02555 for (std::vector<std::string>::iterator iter=gazebo_media_paths.begin(); iter != gazebo_media_paths.end(); iter++) 02556 { 02557 ROS_DEBUG("med path %s",iter->c_str()); 02558 gazebo::Simulator::Instance()->GetGazeboConfig()->AddGazeboPaths(iter->c_str()); 02559 } 02560 02561 // set gazebo plugins paths by adding all packages that exports "plugin" for gazebo 02562 gazebo::Simulator::Instance()->GetGazeboConfig()->ClearPluginPaths(); 02563 std::vector<std::string> plugin_paths; 02564 ros::package::getPlugins("gazebo","plugin_path",plugin_paths); 02565 for (std::vector<std::string>::iterator iter=plugin_paths.begin(); iter != plugin_paths.end(); iter++) 02566 { 02567 ROS_DEBUG("plugin path %s",(*iter).c_str()); 02568 gazebo::Simulator::Instance()->GetGazeboConfig()->AddPluginPaths(iter->c_str()); 02569 } 02570 02571 // set .gazeborc path to something else, so we don't pick up default ~/.gazeborc 02572 std::string gazeborc = ros::package::getPath("gazebo")+"/.do_not_use_gazeborc"; 02573 setenv("GAZEBORC",gazeborc.c_str(),1); 02574 02575 //Load the simulator 02576 try 02577 { 02578 if (optWorldParam) 02579 gazebo::Simulator::Instance()->LoadWorldString(worldParamData, optServerId); 02580 else 02581 gazebo::Simulator::Instance()->LoadWorldFile(worldFileName, optServerId); 02582 02583 gazebo::Simulator::Instance()->SetTimeout(optTimeout); 02584 gazebo::Simulator::Instance()->SetPhysicsEnabled(optPhysicsEnabled); 02585 } 02586 catch (gazebo::GazeboError e) 02587 { 02588 std::cerr << "Error Loading Gazebo" << std::endl; 02589 std::cerr << e << std::endl; 02590 gazebo::Simulator::Instance()->Fini(); 02591 ros::shutdown(); 02592 return -1; 02593 } 02594 02595 // Initialize the simulator 02596 try 02597 { 02598 gazebo::Simulator::Instance()->Init(); 02599 gazebo::Simulator::Instance()->SetPaused(optPaused); 02600 } 02601 catch (gazebo::GazeboError e) 02602 { 02603 std::cerr << "Initialization failed" << std::endl; 02604 std::cerr << e << std::endl; 02605 gazebo::Simulator::Instance()->Fini(); 02606 ros::shutdown(); 02607 return -1; 02608 } 02609 02610 // start a node 02611 GazeboROSNode grn; 02612 02613 // Main loop of the simulator 02614 try 02615 { 02616 gazebo::Simulator::Instance()->MainLoop(); 02617 } 02618 catch (gazebo::GazeboError e) 02619 { 02620 std::cerr << "Main simulation loop failed" << std::endl; 02621 std::cerr << e << std::endl; 02622 gazebo::Simulator::Instance()->Fini(); 02623 ros::shutdown(); 02624 return -1; 02625 } 02626 02627 // Finalization and clean up 02628 try 02629 { 02630 gazebo::Simulator::Instance()->Fini(); 02631 } 02632 catch (gazebo::GazeboError e) 02633 { 02634 std::cerr << "Finalization failed" << std::endl; 02635 std::cerr << e << std::endl; 02636 ros::shutdown(); 02637 return -1; 02638 } 02639 02640 printf("Done.\n"); 02641 ros::shutdown(); 02642 return 0; 02643 }