ObjectMessageGenerator.cpp
Go to the documentation of this file.
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         //ROS_INFO("%s\n",pch);
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         //ROS_INFO("%s\n",pch);
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     //ROS_INFO("ObjectMessageGenerator: subscriber CONNECTING");
00097 
00098     mutex.lock();
00099     // get all collision objects currently in the scene
00100     addedObjects = getCurrentCollisionObjectNames();
00101 
00102     // also add the always allowed collision links for each object:
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     //ROS_INFO("ObjectMessageGenerator: a subscriber is DISCONNECTING");
00125     if (!isConnected())
00126     {
00127         // lost connection to subscribers, so require new initialisation
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         //ROS_INFO_STREAM("ObjectMessagGenerator: Publishing "<<it->second);
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         // lost connection to subscribers, so require new initialisation
00163         // ROS_INFO("ObjectMessageGenerator: No subscribers");
00164         initExistingObj = false;
00165         return;
00166     }
00167 
00168     if (!initExistingObj)
00169     {
00170         ROS_WARN("ObjectMessageGenerator: No initialisation of objects yet.");
00171         return; //the existing objects haven't been initialised yet
00172     }
00173 
00174     // ROS_INFO_STREAM("ObjectMessageGenerator: Received object message to re-map to moveit collision objects.");//: "<<msg);
00175 
00176     std::string id = msg.name;
00177     if (skipObjects.find(id) != skipObjects.end())
00178     {
00179         // this is an object to be skipped
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     {   // if attached to the robot, we cannot send collision updates,
00186         // as the object has purposedly been removed from the planning scene
00187         // ROS_INFO_STREAM("Object '"<<id<<"' is currently attached to robot, so not updating the collision object");
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         //we already have this object to publish, so only allow
00198         //to overwrite the poses
00199         updatePose(msg, existing->second);
00200         return;
00201     }
00202 
00203     moveit_msgs::CollisionObject obj;
00204     if (addedObjects.find(id) == addedObjects.end())
00205     {
00206         // this is a new object
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  // We already have had geometry sent for this object.
00225     {   
00226         // We may want to enforce a MOVE operation.
00227         // Only if the object is not currently in the MoveIt! collision environment, or
00228         // if geometry is actually specified in the message (e.g. to change shape), we'll consider another ADD.
00229 
00230         if ((msg.content == object_msgs::Object::SHAPE) && !msg.primitives.empty())
00231         {   // full geometry specified in msg of type ADD. Use the full geometry.
00232             obj = transferContent(msg, false);
00233         }
00234         else
00235         {   // this is either a MOVE operation, or the geometry is empty.
00236             // if the object is not in the MoveIt! collision environment, we have to request the geometry.
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             // if the object is not in the MoveIt! environment, or this is a SHAPE operation but the
00243             // geometry was not specivied, then retrieve the geometry, as we have to do a MoveIt ADD operation.
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                 {   // successfully retrieved geometry.
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);  // transfer all content except geometry
00262 
00263             if (use_current_object_geometry)
00264             {
00265                 obj.primitives = current_object.primitives;
00266                 // obj.primitive_poses will have been set by the message (msg)
00267                 obj.meshes = current_object.meshes;
00268                 // XXX not sure if this is needed, need to define precisely whether they are always
00269                 // included (also in MOVE operation) or only when geometry is included as well. Copy the most recent
00270                 // information just to be sure.
00271                 obj.mesh_poses = current_object.mesh_poses;
00272             }
00273                 
00274             // if the object is not in the scene, we have to enforce an ADD operation.
00275             if (!object_in_scene) obj.operation=moveit_msgs::CollisionObject::ADD;
00276         }
00277     }
00278 
00279     /*if (obj.operation==moveit_msgs::CollisionObject::ADD) {
00280         ROS_INFO("ObjectMessageGenerator: Sending operation ADD for %s",obj.id.c_str()); //ROS_INFO_STREAM(obj);
00281     } else {
00282         ROS_INFO("ObjectMessageGenerator: Sending operation MOVE for %s",obj.id.c_str()); //ROS_INFO_STREAM(obj);
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     /*while (!object_info_client.exists() && !object_info_client.waitForExistence(ros::Duration(1))) {
00292         ROS_INFO("ObjectMessageGenerator: Waiting for planning scene service (topic %s) to become available...",GET_PLANNING_SCENE_SERVICE.c_str());
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     //obj.type.key="Box";
00326     //obj.type.db="";
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         //ROS_INFO("ObjectMessageGenerator: Sending operation ADD for %s",obj.id.c_str()); //ROS_INFO_STREAM(obj);
00341         obj.operation = moveit_msgs::CollisionObject::ADD;
00342         //obj.operation=moveit_msgs::CollisionObject::APPEND;
00343         //obj.operation=moveit_msgs::CollisionObject::REMOVE;
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     /*while (!planning_scene_client.exists() && !planning_scene_client.waitForExistence(ros::Duration(1))) {
00356         ROS_INFO("Waiting for planning scene service (topic %s) to become available...",GET_PLANNING_SCENE_SERVICE.c_str());
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     /*while (!planning_scene_client.exists() && !planning_scene_client.waitForExistence(ros::Duration(1))) {
00396         ROS_INFO("Waiting for planning scene service (topic %s) to become available...",GET_PLANNING_SCENE_SERVICE.c_str());
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 


moveit_object_handling
Author(s): Jennifer Buehler
autogenerated on Sat Mar 2 2019 03:50:51