00001 #include <moveit_object_handling/ObjectMessageGenerator.h>
00002
00003 #include <iostream>
00004
00005 #define DEFAULT_COLLISION_OBJECT_TOPIC "collision_object"
00006 #define DEFAULT_OBJECTS_TOPIC "world/objects"
00007 #define DEFAULT_REQUEST_OBJECTS_TOPIC "world/request_object"
00008 #define DEFAULT_GET_PLANNING_SCENE_SERVICE "/get_planning_scene"
00009 #define DEFAULT_SET_PLANNING_SCENE_TOPIC "/planning_scene"
00010 #define DEFAULT_USE_PLANNING_SCENE_DIFF true
00011
00012 #define DEFAULT_PUBLISH_COLLISION_RATE 30
00013
00014 using moveit_object_handling::ObjectMessageGenerator;
00015
00016 ObjectMessageGenerator::ObjectMessageGenerator(ros::NodeHandle& _node_priv, ros::NodeHandle& _node_pub) :
00017 node_priv(_node_priv),
00018 node(_node_pub),
00019 acmManip(_node_priv)
00020 {
00021
00022 ros::NodeHandle _node("/moveit_object_handling");
00023 _node.param<std::string>("world_objects_topic", OBJECTS_TOPIC, DEFAULT_OBJECTS_TOPIC);
00024 ROS_INFO("Got objects topic name: <%s>", OBJECTS_TOPIC.c_str());
00025
00026 _node.param<std::string>("request_object_service", REQUEST_OBJECTS_TOPIC, DEFAULT_REQUEST_OBJECTS_TOPIC);
00027 ROS_INFO("Got object service topic name: <%s>", REQUEST_OBJECTS_TOPIC.c_str());
00028
00029 _node.param<std::string>("collision_object_topic", COLLISION_OBJECT_TOPIC, DEFAULT_COLLISION_OBJECT_TOPIC);
00030 ROS_INFO("Got collision objects topic name: <%s>", COLLISION_OBJECT_TOPIC.c_str());
00031
00032 GET_PLANNING_SCENE_SERVICE = DEFAULT_GET_PLANNING_SCENE_SERVICE;
00033 _node.param<std::string>("moveit_get_planning_scene_topic", GET_PLANNING_SCENE_SERVICE, GET_PLANNING_SCENE_SERVICE);
00034 ROS_INFO("Got moveit_get_planning_scene_topic: <%s>", GET_PLANNING_SCENE_SERVICE.c_str());
00035
00036 SET_PLANNING_SCENE_TOPIC = DEFAULT_SET_PLANNING_SCENE_TOPIC;
00037 _node.param<std::string>("moveit_set_planning_scene_topic", SET_PLANNING_SCENE_TOPIC, SET_PLANNING_SCENE_TOPIC);
00038 ROS_INFO("Got moveit_set_planning_scene_topic: <%s>", SET_PLANNING_SCENE_TOPIC.c_str());
00039
00040 _node.param<bool>("use_planning_scene_diff", USE_PLANNING_SCENE_DIFF, DEFAULT_USE_PLANNING_SCENE_DIFF);
00041 ROS_INFO("Got use_planning_scene_diff: <%i>", USE_PLANNING_SCENE_DIFF);
00042
00043 std::stringstream def_coll_rate;
00044 def_coll_rate << DEFAULT_PUBLISH_COLLISION_RATE;
00045 std::string _PUBLISH_COLLISION_RATE = def_coll_rate.str();
00046 _node.param<std::string>("publish_collision_rate", _PUBLISH_COLLISION_RATE, _PUBLISH_COLLISION_RATE);
00047 PUBLISH_COLLISION_RATE = atof(_PUBLISH_COLLISION_RATE.c_str());
00048
00049 std::string skip_string;
00050 _node.param<std::string>("skip_objects", skip_string, "");
00051 ROS_INFO("Objects to skip: %s", skip_string.c_str());
00052 char * str = (char*)skip_string.c_str();
00053 char * pch = strtok(str, " ,;");
00054 while (pch != NULL)
00055 {
00056
00057 skipObjects.insert(std::string(pch));
00058 pch = strtok(NULL, " ,;");
00059 }
00060
00061 std::string allowed_coll_string;
00062 _node.param<std::string>("allowed_collision_links", allowed_coll_string, "");
00063 ROS_INFO("Objects to allow collide: %s", allowed_coll_string.c_str());
00064 str = (char*)allowed_coll_string.c_str();
00065 pch = strtok(str, " ,;");
00066 while (pch != NULL)
00067 {
00068
00069 allowedCollisionLinks.push_back(std::string(pch));
00070 pch = strtok(NULL, " ,;");
00071 }
00072
00073 if (REQUEST_OBJECTS_TOPIC != "") object_info_client = node.serviceClient<object_msgs::ObjectInfo>(REQUEST_OBJECTS_TOPIC);
00074 planning_scene_client = node.serviceClient<moveit_msgs::GetPlanningScene>(GET_PLANNING_SCENE_SERVICE);
00075
00076 object_sub = node.subscribe(OBJECTS_TOPIC, 100, &ObjectMessageGenerator::receiveObject, this);
00077
00078 ros::SubscriberStatusCallback conn = boost::bind(&ObjectMessageGenerator::connectPub, this, _1);
00079 ros::SubscriberStatusCallback disconn = boost::bind(&ObjectMessageGenerator::disconnectPub, this, _1);
00080 if (!USE_PLANNING_SCENE_DIFF)
00081 collision_pub = node.advertise<moveit_msgs::CollisionObject>(COLLISION_OBJECT_TOPIC, 100, conn, disconn);
00082 else
00083 planning_scene_pub = node.advertise<moveit_msgs::PlanningScene>(SET_PLANNING_SCENE_TOPIC, 100, conn, disconn);
00084 ros::Rate rate(PUBLISH_COLLISION_RATE);
00085 publishCollisionsTimer = node_priv.createTimer(rate, &ObjectMessageGenerator::publishCollisionsEvent, this);
00086
00087 initExistingObj = false;
00088 }
00089
00090 ObjectMessageGenerator::~ObjectMessageGenerator()
00091 {
00092 }
00093
00094 void ObjectMessageGenerator::connectPub(const ros::SingleSubscriberPublisher& p)
00095 {
00096
00097
00098 mutex.lock();
00099
00100 addedObjects = getCurrentCollisionObjectNames();
00101
00102
00103 for (std::set<std::string>::iterator it = addedObjects.begin();
00104 it != addedObjects.end(); ++it)
00105 {
00106 acmManip.addAllowedMoveItCollision(*it, allowedCollisionLinks);
00107 }
00108 mutex.unlock();
00109 initExistingObj = true;
00110 }
00111
00112 bool ObjectMessageGenerator::isConnected() const
00113 {
00114 bool connected = false;
00115 if (!USE_PLANNING_SCENE_DIFF)
00116 connected = (collision_pub.getNumSubscribers() > 0);
00117 else
00118 connected = (planning_scene_pub.getNumSubscribers() > 0);
00119 return connected;
00120 }
00121
00122 void ObjectMessageGenerator::disconnectPub(const ros::SingleSubscriberPublisher& p)
00123 {
00124
00125 if (!isConnected())
00126 {
00127
00128 initExistingObj = false;
00129 }
00130 }
00131
00132 void ObjectMessageGenerator::publishCollisionsEvent(const ros::TimerEvent& e)
00133 {
00134 if (!isConnected()) return;
00135
00136 mutex.lock();
00137 ObjToPublishMap::iterator it;
00138 for (it = objsToPublish.begin(); it != objsToPublish.end(); ++it)
00139 {
00140
00141 if (!USE_PLANNING_SCENE_DIFF)
00142 {
00143 collision_pub.publish(it->second);
00144 }
00145 else
00146 {
00147 moveit_msgs::PlanningScene planning_scene;
00148 planning_scene.world.collision_objects.push_back(it->second);
00149 planning_scene.is_diff = true;
00150 planning_scene_pub.publish(planning_scene);
00151 }
00152 }
00153 objsToPublish.clear();
00154 mutex.unlock();
00155 }
00156
00157
00158 void ObjectMessageGenerator::receiveObject(const ObjectMsg& msg)
00159 {
00160 if (!isConnected())
00161 {
00162
00163
00164 initExistingObj = false;
00165 return;
00166 }
00167
00168 if (!initExistingObj)
00169 {
00170 ROS_WARN("ObjectMessageGenerator: No initialisation of objects yet.");
00171 return;
00172 }
00173
00174
00175
00176 std::string id = msg.name;
00177 if (skipObjects.find(id) != skipObjects.end())
00178 {
00179
00180 return;
00181 }
00182
00183 std::set<std::string> curr_attached_objs = getCurrentAttachedCollisionObjectNames();
00184 if (curr_attached_objs.find(id) != curr_attached_objs.end())
00185 {
00186
00187
00188 return;
00189 }
00190
00191
00192 boost::unique_lock<boost::mutex>(mutex);
00193
00194 ObjToPublishMap::iterator existing = objsToPublish.find(id);
00195 if (existing != objsToPublish.end())
00196 {
00197
00198
00199 updatePose(msg, existing->second);
00200 return;
00201 }
00202
00203 moveit_msgs::CollisionObject obj;
00204 if (addedObjects.find(id) == addedObjects.end())
00205 {
00206
00207 if (msg.content == object_msgs::Object::POSE)
00208 {
00209 ROS_INFO("Object not added yet to the system, so retreiving object geometry... %s", __FILE__);
00210 obj = getCollisionGeometry(id);
00211 if (obj.id != id)
00212 {
00213 ROS_ERROR_STREAM("Object '" << id << "' geometry could not be retrieved. It cannot be properly added to MoveIt!");
00214 return;
00215 }
00216 }
00217 else
00218 {
00219 obj = transferContent(msg, false);
00220 }
00221 addedObjects.insert(id);
00222 acmManip.addAllowedMoveItCollision(id, allowedCollisionLinks);
00223 }
00224 else
00225 {
00226
00227
00228
00229
00230 if ((msg.content == object_msgs::Object::SHAPE) && !msg.primitives.empty())
00231 {
00232 obj = transferContent(msg, false);
00233 }
00234 else
00235 {
00236
00237
00238 std::set<std::string> curr_coll_objs = getCurrentCollisionObjectNames();
00239 bool object_in_scene = curr_coll_objs.find(id) != curr_coll_objs.end();
00240 moveit_msgs::CollisionObject current_object;
00241 bool use_current_object_geometry = false;
00242
00243
00244 if (!object_in_scene || ((msg.content == object_msgs::Object::SHAPE) && msg.primitives.empty()))
00245 {
00246 ROS_INFO_STREAM("Object '" << id << "'not added yet to the system, so retreiving object geometry...");
00247 current_object = getCollisionGeometry(id);
00248 if ((current_object.id == id) && (!current_object.primitives.empty()))
00249 {
00250 use_current_object_geometry = true;
00251 }
00252 else
00253 {
00254 ROS_ERROR_STREAM("Object '" << id << "' geometry could not be retrieved. It cannot be properly added to MoveIt! again.");
00255 }
00256 }
00257
00258 if ((msg.content == object_msgs::Object::SHAPE) && object_in_scene)
00259 ROS_WARN("We already have had geometry sent for object '%s', so enforcing a MOVE operation.", msg.name.c_str());
00260
00261 obj = transferContent(msg, true);
00262
00263 if (use_current_object_geometry)
00264 {
00265 obj.primitives = current_object.primitives;
00266
00267 obj.meshes = current_object.meshes;
00268
00269
00270
00271 obj.mesh_poses = current_object.mesh_poses;
00272 }
00273
00274
00275 if (!object_in_scene) obj.operation=moveit_msgs::CollisionObject::ADD;
00276 }
00277 }
00278
00279
00280
00281
00282
00283
00284
00285 objsToPublish.insert(std::make_pair(id, obj));
00286 }
00287
00288 moveit_msgs::CollisionObject ObjectMessageGenerator::getCollisionGeometry(const std::string& name)
00289 {
00290 ROS_INFO("Received information for new object %s, adding it by requesting mesh information...", name.c_str());
00291
00292
00293
00294 object_msgs::ObjectInfo srv;
00295 srv.request.name = name;
00296 srv.request.get_geometry = true;
00297 if (!object_info_client.call(srv))
00298 {
00299 ROS_ERROR("Could not add object %s because service request failed.", name.c_str());
00300 return moveit_msgs::CollisionObject();
00301 }
00302 ROS_INFO("Object added.");
00303 return transferContent(srv.response.object, false);
00304 }
00305
00306 void ObjectMessageGenerator::updatePose(const ObjectMsg& newObj, moveit_msgs::CollisionObject& obj)
00307 {
00308 if (obj.header.frame_id != newObj.header.frame_id) ROS_WARN("messages not specified in same frame! %s %s", obj.header.frame_id.c_str(), newObj.header.frame_id.c_str());
00309 if (obj.id != newObj.name) ROS_ERROR("Not referring to same object to update the pose!");
00310
00311 obj.header = newObj.header;
00312 obj.primitive_poses = newObj.primitive_poses;
00313 obj.mesh_poses = newObj.mesh_poses;
00314 }
00315
00316
00317 moveit_msgs::CollisionObject ObjectMessageGenerator::transferContent(const ObjectMsg& msg, bool skipGeometry)
00318 {
00319
00320 moveit_msgs::CollisionObject obj;
00321
00322 obj.header = msg.header;
00323
00324 obj.id = msg.name;
00325
00326
00327
00328 if (!skipGeometry) obj.primitives = msg.primitives;
00329 obj.primitive_poses = msg.primitive_poses;
00330
00331 if (!skipGeometry) obj.meshes = msg.meshes;
00332 obj.mesh_poses = msg.mesh_poses;
00333
00334 if ((msg.content == ObjectMsg::POSE) || skipGeometry)
00335 {
00336 obj.operation = moveit_msgs::CollisionObject::MOVE;
00337 }
00338 else if (msg.content == ObjectMsg::SHAPE)
00339 {
00340
00341 obj.operation = moveit_msgs::CollisionObject::ADD;
00342
00343
00344 }
00345
00346 return obj;
00347
00348 }
00349
00350
00351 std::vector<moveit_msgs::CollisionObject> ObjectMessageGenerator::getCurrentCollisionObjects(bool only_names)
00352 {
00353 if (!planning_scene_client.exists()) return std::vector<moveit_msgs::CollisionObject>();
00354
00355
00356
00357
00358
00359 moveit_msgs::GetPlanningScene srv;
00360 srv.request.components.components =
00361 moveit_msgs::PlanningSceneComponents::WORLD_OBJECT_NAMES;
00362 if (!only_names)
00363 srv.request.components.components =
00364 srv.request.components.components |
00365 moveit_msgs::PlanningSceneComponents::WORLD_OBJECT_GEOMETRY;
00366
00367
00368 if (!planning_scene_client.call(srv))
00369 {
00370 ROS_ERROR("Can't obtain planning scene");
00371 return std::vector<moveit_msgs::CollisionObject>();
00372 }
00373
00374 moveit_msgs::PlanningScene& scene = srv.response.scene;
00375 return scene.world.collision_objects;
00376 }
00377
00378
00379
00380 std::set<std::string> ObjectMessageGenerator::getCurrentCollisionObjectNames()
00381 {
00382 std::vector<moveit_msgs::CollisionObject> obj = getCurrentCollisionObjects(true);
00383 std::set<std::string> ret;
00384 for (std::vector<moveit_msgs::CollisionObject>::iterator it = obj.begin(); it != obj.end(); ++it)
00385 {
00386 ret.insert(it->id);
00387 }
00388 return ret;
00389 }
00390
00391 std::vector<moveit_msgs::AttachedCollisionObject> ObjectMessageGenerator::getCurrentAttachedCollisionObjects()
00392 {
00393 if (!planning_scene_client.exists()) return std::vector<moveit_msgs::AttachedCollisionObject>();
00394
00395
00396
00397
00398
00399 moveit_msgs::GetPlanningScene srv;
00400 srv.request.components.components =
00401 moveit_msgs::PlanningSceneComponents::ROBOT_STATE_ATTACHED_OBJECTS;
00402
00403 if (!planning_scene_client.call(srv))
00404 {
00405 ROS_ERROR("Can't obtain planning scene");
00406 return std::vector<moveit_msgs::AttachedCollisionObject>();
00407 }
00408
00409 moveit_msgs::PlanningScene& scene = srv.response.scene;
00410 return scene.robot_state.attached_collision_objects;
00411 }
00412
00413
00414
00415 std::set<std::string> ObjectMessageGenerator::getCurrentAttachedCollisionObjectNames()
00416 {
00417 std::vector<moveit_msgs::AttachedCollisionObject> obj = getCurrentAttachedCollisionObjects();
00418 std::set<std::string> ret;
00419 for (std::vector<moveit_msgs::AttachedCollisionObject>::iterator it = obj.begin(); it != obj.end(); ++it)
00420 {
00421 ret.insert(it->object.id);
00422 }
00423 return ret;
00424 }
00425