Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <algorithm>
00024 #include <assert.h>
00025
00026 #include <boost/bind.hpp>
00027 #include <boost/thread/mutex.hpp>
00028
00029 #include <gazebo/common/common.hh>
00030
00031 #include <gazebo_plugins/gazebo_ros_moveit_planning_scene.h>
00032
00033 namespace gazebo
00034 {
00035 GZ_REGISTER_MODEL_PLUGIN(GazeboRosMoveItPlanningScene);
00036
00038
00039 GazeboRosMoveItPlanningScene::GazeboRosMoveItPlanningScene()
00040 {
00041 }
00042
00044
00045 GazeboRosMoveItPlanningScene::~GazeboRosMoveItPlanningScene()
00046 {
00047 event::Events::DisconnectWorldUpdateBegin(this->update_connection_);
00048
00049
00050 this->queue_.clear();
00051 this->queue_.disable();
00052 this->rosnode_->shutdown();
00053 this->callback_queue_thread_.join();
00054 }
00055
00057
00058 void GazeboRosMoveItPlanningScene::Load(physics::ModelPtr _model, sdf::ElementPtr _sdf)
00059 {
00060
00061 this->world_ = _model->GetWorld();
00062
00063 this->model_name_ = _model->GetName();
00064
00065
00066 if (_sdf->HasElement("robotNamespace")) {
00067 this->robot_namespace_ = _sdf->GetElement("robotNamespace")->Get<std::string>() + "/";
00068 } else {
00069 this->robot_namespace_ = "";
00070 }
00071
00072 if (!_sdf->HasElement("robotName")) {
00073 this->robot_name_ = _model->GetName();
00074 } else {
00075 this->robot_name_ = _sdf->GetElement("robotName")->Get<std::string>();
00076 }
00077
00078 if (!_sdf->HasElement("topicName")) {
00079 this->topic_name_ = "planning_scene";
00080 } else {
00081 this->topic_name_ = _sdf->GetElement("topicName")->Get<std::string>();
00082 }
00083
00084 if (!_sdf->HasElement("sceneName")) {
00085 this->scene_name_ = "";
00086 } else {
00087 this->scene_name_ = _sdf->GetElement("sceneName")->Get<std::string>();
00088 }
00089
00090 if (!_sdf->HasElement("updatePeriod")) {
00091 this->publish_period_ = ros::Duration(0.0);
00092 } else {
00093 this->publish_period_ = ros::Duration(_sdf->GetElement("updatePeriod")->Get<double>());
00094 }
00095
00096
00097
00098 if (!ros::isInitialized())
00099 {
00100 ROS_FATAL_STREAM("A ROS node for Gazebo has not been initialized, unable to load plugin. "
00101 << "Load the Gazebo system plugin 'libgazebo_ros_api_plugin.so' in the gazebo_ros package)");
00102 return;
00103 }
00104
00105 this->rosnode_.reset(new ros::NodeHandle(this->robot_namespace_));
00106
00107 last_publish_time_ = ros::Time(0,0);
00108
00109 planning_scene_pub_ = this->rosnode_->advertise<moveit_msgs::PlanningScene>(this->topic_name_, 1);
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 this->callback_queue_thread_ = boost::thread( boost::bind( &GazeboRosMoveItPlanningScene::QueueThread,this ) );
00122
00123
00124 ros::AdvertiseServiceOptions aso;
00125 boost::function<bool(std_srvs::Empty::Request&, std_srvs::Empty::Response&)> srv_cb =
00126 boost::bind(&GazeboRosMoveItPlanningScene::PublishPlanningSceneCB, this, _1, _2);
00127 aso.init("publish_planning_scene", srv_cb);
00128 aso.callback_queue = &this->queue_;
00129
00130 publish_planning_scene_service_ = this->rosnode_->advertiseService(aso);
00131
00132
00133 publish_full_scene_ = false;
00134
00135
00136
00137
00138 this->update_connection_ = event::Events::ConnectWorldUpdateBegin(
00139 boost::bind(&GazeboRosMoveItPlanningScene::UpdateCB, this));
00140 }
00141
00143
00144 bool GazeboRosMoveItPlanningScene::PublishPlanningSceneCB(
00145 std_srvs::Empty::Request& req,
00146 std_srvs::Empty::Response& resp)
00147 {
00148 boost::mutex::scoped_lock lock(this->mutex_);
00149
00150
00151 publish_full_scene_ = true;
00152
00153 return true;
00154 }
00155
00157
00158 void GazeboRosMoveItPlanningScene::UpdateCB()
00159 {
00160 boost::mutex::scoped_lock lock(this->mutex_);
00161
00162 using namespace gazebo::common;
00163 using namespace gazebo::physics;
00164
00165 if(!publish_full_scene_) {
00166 if(publish_period_.isZero() || (ros::Time::now() - last_publish_time_) < publish_period_) {
00167 return;
00168 } else {
00169 last_publish_time_ = ros::Time::now();
00170 }
00171 } else {
00172 publish_full_scene_ = false;
00173 }
00174
00175
00176
00177 for(std::map<std::string,moveit_msgs::CollisionObject>::iterator object_it = collision_object_map_.begin();
00178 object_it != collision_object_map_.end();
00179 ++object_it)
00180 {
00181
00182 moveit_msgs::CollisionObject &object = object_it->second;
00183
00184
00185 object.operation = moveit_msgs::CollisionObject::REMOVE;
00186
00187
00188 object.primitives.clear();
00189 object.primitive_poses.clear();
00190
00191 object.meshes.clear();
00192 object.mesh_poses.clear();
00193
00194 object.planes.clear();
00195 object.plane_poses.clear();
00196 }
00197
00198
00199 std::vector<ModelPtr> models = this->world_->GetModels();
00200 for(std::vector<ModelPtr>::const_iterator model_it = models.begin();
00201 model_it != models.end();
00202 ++model_it)
00203 {
00204 const ModelPtr &model = *model_it;
00205 const std::string model_name = model->GetName();
00206
00207
00208 if(model_name == model_name_) {
00209 continue;
00210 }
00211
00212
00213 std::map<std::string, moveit_msgs::CollisionObject>::iterator found_collision_object =
00214 collision_object_map_.find(model_name);
00215
00216
00217 if(found_collision_object == collision_object_map_.end()) {
00218 moveit_msgs::CollisionObject new_object;
00219 new_object.id = model_name;
00220 new_object.header.frame_id = "world";
00221 new_object.operation = moveit_msgs::CollisionObject::ADD;
00222
00223 collision_object_map_[model_name] = new_object;
00224 ROS_DEBUG_STREAM_NAMED("GazeboRosMoveItPlanningScene","Adding object: "<<model_name);
00225 } else {
00226
00227 collision_object_map_[model_name].operation = moveit_msgs::CollisionObject::MOVE;
00228 ROS_DEBUG_STREAM_NAMED("GazeboRosMoveItPlanningScene","Moving object: "<<model_name);
00229 }
00230
00231
00232 moveit_msgs::CollisionObject &object = collision_object_map_[model_name];
00233
00234
00235
00236
00237
00238
00239 std::vector<LinkPtr> links = model->GetLinks();
00240 for(std::vector<LinkPtr>::const_iterator link_it = links.begin();
00241 link_it != links.end();
00242 ++link_it)
00243 {
00244 const LinkPtr &link = *link_it;
00245
00246 gazebo::math::Pose link_pose = link->GetWorldPose();
00247 geometry_msgs::Pose link_pose_msg;
00248 link_pose_msg.position.x = link_pose.pos.x;
00249 link_pose_msg.position.y = link_pose.pos.y;
00250 link_pose_msg.position.z = link_pose.pos.z;
00251 link_pose_msg.orientation.x = link_pose.rot.x;
00252 link_pose_msg.orientation.y = link_pose.rot.y;
00253 link_pose_msg.orientation.z = link_pose.rot.z;
00254 link_pose_msg.orientation.w = link_pose.rot.w;
00255
00256
00257
00258 std::vector<CollisionPtr> collisions = link->GetCollisions();
00259 for(std::vector<CollisionPtr>::const_iterator coll_it = collisions.begin();
00260 coll_it != collisions.end();
00261 ++coll_it)
00262 {
00263 const CollisionPtr &collision = *coll_it;
00264 const ShapePtr shape = collision->GetShape();
00265
00266
00267 gazebo::math::Pose collision_pose = collision->GetRelativePose()*link_pose;
00268 geometry_msgs::Pose collision_pose_msg;
00269 collision_pose_msg.position.x = collision_pose.pos.x;
00270 collision_pose_msg.position.y = collision_pose.pos.y;
00271 collision_pose_msg.position.z = collision_pose.pos.z;
00272 collision_pose_msg.orientation.x = collision_pose.rot.x;
00273 collision_pose_msg.orientation.y = collision_pose.rot.y;
00274 collision_pose_msg.orientation.z = collision_pose.rot.z;
00275 collision_pose_msg.orientation.w = collision_pose.rot.w;
00276
00277
00278
00279 if(shape->HasType(Base::MESH_SHAPE)) {
00280 object.mesh_poses.push_back(collision_pose_msg);
00281 } else if(shape->HasType(Base::PLANE_SHAPE)) {
00282 object.plane_poses.push_back(collision_pose_msg);
00283 } else {
00284 object.primitive_poses.push_back(collision_pose_msg);
00285 }
00286
00287
00288 if(object.operation == moveit_msgs::CollisionObject::ADD || object.operation == moveit_msgs::CollisionObject::APPEND)
00289 {
00290 if(shape->HasType(Base::MESH_SHAPE))
00291 {
00292
00293 boost::shared_ptr<MeshShape> mesh_shape = boost::dynamic_pointer_cast<MeshShape>(shape);
00294 std::string name = mesh_shape->GetName();
00295 std::string uri = mesh_shape->GetMeshURI();
00296 const Mesh *mesh = MeshManager::Instance()->GetMesh(uri);
00297
00298 if(!mesh) {
00299 gzwarn << "Shape has mesh type but mesh could not be retried from the MeshManager. Loading ad-hoc!" << std::endl;
00300 gzwarn << " mesh uri: " <<uri<< std::endl;
00301
00302
00303
00304 mesh = MeshManager::Instance()->Load(uri);
00305
00306 if(!mesh) {
00307 gzwarn << "Mesh could not be loded: " << uri << std::endl;
00308 continue;
00309 }
00310 }
00311
00312
00313 unsigned n_submeshes = mesh->GetSubMeshCount();
00314
00315 for(unsigned m=0; m < n_submeshes; m++) {
00316
00317 const SubMesh *submesh = mesh->GetSubMesh(m);
00318 unsigned n_vertices = submesh->GetVertexCount();
00319
00320 switch(submesh->GetPrimitiveType())
00321 {
00322 case SubMesh::POINTS:
00323 case SubMesh::LINES:
00324 case SubMesh::LINESTRIPS:
00325
00326 break;
00327 case SubMesh::TRIANGLES:
00328 {
00329
00330 shape_msgs::Mesh mesh_msg;
00331 mesh_msg.vertices.resize(n_vertices);
00332 mesh_msg.triangles.resize(n_vertices/3);
00333
00334 for(size_t v=0; v < n_vertices; v++) {
00335
00336 const int index = submesh->GetIndex(v);
00337 const gazebo::math::Vector3 vertex = submesh->GetVertex(v);
00338
00339 mesh_msg.vertices[index].x = vertex.x;
00340 mesh_msg.vertices[index].y = vertex.y;
00341 mesh_msg.vertices[index].z = vertex.z;
00342
00343 mesh_msg.triangles[v/3].vertex_indices[v%3] = index;
00344 }
00345
00346 object.meshes.push_back(mesh_msg);
00347 break;
00348 }
00349 case SubMesh::TRISTRIPS:
00350 {
00351
00352 shape_msgs::Mesh mesh_msg;
00353 mesh_msg.vertices.resize(n_vertices);
00354 mesh_msg.triangles.resize(n_vertices-2);
00355
00356 for(size_t v=0; v < n_vertices; v++) {
00357 const int index = submesh->GetIndex(v);
00358 const gazebo::math::Vector3 vertex = submesh->GetVertex(v);
00359
00360 mesh_msg.vertices[index].x = vertex.x;
00361 mesh_msg.vertices[index].y = vertex.y;
00362 mesh_msg.vertices[index].z = vertex.z;
00363
00364 if(v < n_vertices-2) mesh_msg.triangles[v].vertex_indices[0] = index;
00365 if(v > 0 && v < n_vertices-1) mesh_msg.triangles[v-1].vertex_indices[1] = index;
00366 if(v > 1) mesh_msg.triangles[v-2].vertex_indices[2] = index;
00367 }
00368
00369 object.meshes.push_back(mesh_msg);
00370 break;
00371 }
00372 case SubMesh::TRIFANS:
00373
00374 gzerr << "TRIFANS not supported yet." << std::endl;
00375 break;
00376 };
00377 }
00378 }
00379 else if(shape->HasType(Base::PLANE_SHAPE))
00380 {
00381
00382 boost::shared_ptr<PlaneShape> plane_shape = boost::dynamic_pointer_cast<PlaneShape>(shape);
00383 shape_msgs::Plane plane_msg;
00384
00385 plane_msg.coef[0] = plane_shape->GetNormal().x;
00386 plane_msg.coef[1] = plane_shape->GetNormal().y;
00387 plane_msg.coef[2] = plane_shape->GetNormal().z;
00388 plane_msg.coef[3] = 0;
00389
00390 object.planes.push_back(plane_msg);
00391 }
00392 else
00393 {
00394
00395 shape_msgs::SolidPrimitive primitive_msg;
00396
00397 if(shape->HasType(Base::BOX_SHAPE)) {
00398
00399 boost::shared_ptr<BoxShape> box_shape = boost::dynamic_pointer_cast<BoxShape>(shape);
00400
00401 primitive_msg.type = primitive_msg.BOX;
00402 primitive_msg.dimensions.resize(3);
00403 primitive_msg.dimensions[0] = box_shape->GetSize().x;
00404 primitive_msg.dimensions[1] = box_shape->GetSize().y;
00405 primitive_msg.dimensions[2] = box_shape->GetSize().z;
00406
00407 } else if(shape->HasType(Base::CYLINDER_SHAPE)) {
00408
00409 boost::shared_ptr<CylinderShape> cylinder_shape = boost::dynamic_pointer_cast<CylinderShape>(shape);
00410
00411 primitive_msg.type = primitive_msg.CYLINDER;
00412 primitive_msg.dimensions.resize(2);
00413 primitive_msg.dimensions[0] = cylinder_shape->GetLength();
00414 primitive_msg.dimensions[1] = cylinder_shape->GetRadius();
00415
00416 } else if(shape->HasType(Base::SPHERE_SHAPE)) {
00417
00418 boost::shared_ptr<SphereShape> sphere_shape = boost::dynamic_pointer_cast<SphereShape>(shape);
00419
00420 primitive_msg.type = primitive_msg.SPHERE;
00421 primitive_msg.dimensions.resize(1);
00422 primitive_msg.dimensions[0] = sphere_shape->GetRadius();
00423
00424 } else {
00425
00426
00427 continue;
00428 }
00429
00430 object.primitives.push_back(primitive_msg);
00431 }
00432 }
00433 }
00434 }
00435 }
00436
00437
00438 planning_scene_msg_.name = scene_name_;
00439 planning_scene_msg_.robot_model_name = robot_name_;
00440 planning_scene_msg_.is_diff = true;
00441 planning_scene_msg_.world.collision_objects.clear();
00442
00443
00444 for(std::map<std::string,moveit_msgs::CollisionObject>::iterator object_it = collision_object_map_.begin();
00445 object_it != collision_object_map_.end();)
00446 {
00447
00448 planning_scene_msg_.world.collision_objects.push_back(object_it->second);
00449
00450
00451 if(object_it->second.operation == moveit_msgs::CollisionObject::REMOVE) {
00452
00453 ROS_DEBUG_STREAM_NAMED("GazeboRosMoveItPlanningScene","Removing object: "<<object_it->second.id);
00454 collision_object_map_.erase(object_it++);
00455 } else {
00456 ++object_it;
00457 }
00458
00459 }
00460
00461 planning_scene_pub_.publish(planning_scene_msg_);
00462 }
00463
00464
00466
00467 void GazeboRosMoveItPlanningScene::QueueThread()
00468 {
00469 static const double timeout = 0.01;
00470
00471 while (this->rosnode_->ok())
00472 {
00473 this->queue_.callAvailable(ros::WallDuration(timeout));
00474 }
00475 }
00476
00477 }