obstacle_distance_moveit.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *   http://www.apache.org/licenses/LICENSE-2.0
00009 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016  
00017 
00018 #include <cob_obstacle_distance_moveit/obstacle_distance_moveit.h>
00019 
00020 class CreateCollisionWorld : public collision_detection::CollisionWorldFCL
00021 {
00022 public:
00023     CreateCollisionWorld(const collision_detection::WorldPtr &world) :
00024             CollisionWorldFCL(world)
00025     {}
00026 
00027     void getCollisionObject(std::vector<boost::shared_ptr<fcl::CollisionObject> > &obj)
00028     {
00029         std::map<std::string, collision_detection::FCLObject>::iterator it = fcl_objs_.begin();
00030         obj.reserve(fcl_objs_.size());
00031 
00032         for (it; it != fcl_objs_.end(); ++it)
00033         {
00034             obj.push_back(it->second.collision_objects_[0]);
00035         }
00036     }
00037 };
00038 
00039 class CreateCollisionRobot : public collision_detection::CollisionRobotFCL
00040 {
00041 public:
00042     CreateCollisionRobot(const robot_model::RobotModelConstPtr &model) :
00043             CollisionRobotFCL(model)
00044     {}
00045 
00046     void getCollisionObject(const robot_state::RobotState &state,
00047                             std::vector<boost::shared_ptr<fcl::CollisionObject> > &obj)
00048     {
00049         collision_detection::FCLObject fcl_obj;
00050         constructFCLObject(state, fcl_obj);
00051         obj = fcl_obj.collision_objects_;
00052     }
00053 };
00054 
00055 void ObstacleDistanceMoveit::updatedScene(planning_scene_monitor::PlanningSceneMonitor::SceneUpdateType type)
00056 {
00057     planning_scene_monitor::LockedPlanningSceneRO ps(planning_scene_monitor_);
00058     planning_scene::PlanningScenePtr planning_scene_ptr = ps->diff();
00059 
00060     std::vector<boost::shared_ptr<fcl::CollisionObject> > robot_obj, world_obj;
00061     robot_state::RobotState robot_state(planning_scene_ptr->getCurrentState());
00062 
00063     CreateCollisionWorld collision_world(planning_scene_ptr->getWorldNonConst());
00064     collision_world.getCollisionObject(world_obj);
00065 
00066     CreateCollisionRobot collision_robot(robot_state.getRobotModel());
00067     collision_robot.getCollisionObject(robot_state, robot_obj);
00068 
00069     this->robot_links_.clear();
00070     this->collision_objects_.clear();
00071 
00072     for (unsigned int i = 0; i < robot_obj.size(); i++)
00073     {
00074         const collision_detection::CollisionGeometryData *robot_link =
00075                 static_cast<const collision_detection::CollisionGeometryData *>(robot_obj[i]->collisionGeometry()->getUserData());
00076         this->robot_links_[robot_link->getID()] = robot_obj[i];
00077     }
00078 
00079     for (unsigned int i = 0; i < world_obj.size(); i++)
00080     {
00081         const collision_detection::CollisionGeometryData *collision_object =
00082                 static_cast<const collision_detection::CollisionGeometryData *>(world_obj[i]->collisionGeometry()->getUserData());
00083         this->collision_objects_[collision_object->getID()] = world_obj[i];
00084     }
00085 }
00086 
00087 bool ObstacleDistanceMoveit::planningSceneCallback(moveit_msgs::GetPlanningScene::Request &req, moveit_msgs::GetPlanningScene::Response &res)
00088 {
00089     planning_scene_monitor::LockedPlanningSceneRO ps(planning_scene_monitor_);
00090     planning_scene::PlanningScenePtr planning_scene_ptr = ps->diff();
00091 
00092     planning_scene_ptr->getPlanningSceneMsg(res.scene, req.components);
00093 
00094     return true;
00095 }
00096 
00097 bool ObstacleDistanceMoveit::registerCallback(cob_srvs::SetString::Request &req,
00098                                               cob_srvs::SetString::Response &res)
00099 {
00100     boost::mutex::scoped_lock lock(registered_links_mutex_);
00101     std::pair<std::set<std::string>::iterator, bool> ret = registered_links_.insert(req.data);
00102 
00103     res.success = true;
00104     res.message = (ret.second) ? (req.data + " successfully registered") : (req.data + " already registered");
00105     return true;
00106 }
00107 
00108 bool ObstacleDistanceMoveit::unregisterCallback(cob_srvs::SetString::Request &req,
00109                                                 cob_srvs::SetString::Response &res)
00110 {
00111     boost::mutex::scoped_lock lock(registered_links_mutex_);
00112     std::set<std::string>::iterator it = registered_links_.find(req.data);
00113     
00114     if (it != registered_links_.end())
00115     {
00116         registered_links_.erase(it);
00117 
00118         res.success = true;
00119         res.message = req.data + " successfully unregistered";
00120     }
00121     else
00122     {
00123         res.success = true;
00124         res.message = req.data + " has not been registered before";
00125     }
00126 
00127     return true;
00128 }
00129 
00130 void ObstacleDistanceMoveit::calculateDistanceTimerCallback(const ros::TimerEvent& event)
00131 {
00132     std::map<std::string, boost::shared_ptr<fcl::CollisionObject> > robot_links = this->robot_links_;
00133     std::map<std::string, boost::shared_ptr<fcl::CollisionObject> > collision_objects = this->collision_objects_;
00134 
00135     boost::mutex::scoped_lock lock(registered_links_mutex_);
00136     cob_control_msgs::ObstacleDistances distance_infos;
00137     
00138     planning_scene_monitor::LockedPlanningSceneRO ps(planning_scene_monitor_);
00139     planning_scene::PlanningScenePtr planning_scene_ptr = ps->diff();
00140 
00141     std::string planning_frame = planning_scene_ptr->getPlanningFrame();
00142 
00143     std::set<std::string>::iterator link_it;
00144     for (link_it = registered_links_.begin(); link_it!=registered_links_.end(); ++link_it)
00145     {
00146         std::string robot_link_name = *link_it;
00147 
00148         const boost::shared_ptr<fcl::CollisionObject> robot_object = robot_links[robot_link_name];
00149         ROS_DEBUG_STREAM("RobotLink: " << robot_link_name << ", Type: " << robot_object->getObjectType());
00150 
00151         std::map<std::string, boost::shared_ptr<fcl::CollisionObject> >::iterator obj_it;
00152         for (obj_it = collision_objects.begin(); obj_it != collision_objects.end(); ++obj_it)
00153         {
00154             std::string collision_object_name = obj_it->first;
00155             const boost::shared_ptr<fcl::CollisionObject> collision_object = collision_objects[collision_object_name];
00156             ROS_DEBUG_STREAM("CollisionLink: " << collision_object_name << ", Type: " << collision_object->getObjectType());
00157 
00158             if(collision_object->getObjectType() == fcl::OT_OCTREE)
00159             {
00160                 ROS_WARN_THROTTLE(1, "Consideration of <octomap> not yet implemented");
00161                 continue;
00162             }
00163 
00164             cob_control_msgs::ObstacleDistance info;
00165             info = getDistanceInfo(robot_object, collision_object);
00166 
00167             info.header.frame_id = planning_frame;
00168             info.header.stamp = event.current_real;
00169             info.link_of_interest = robot_link_name;
00170             info.obstacle_id = collision_object_name;
00171 
00172             distance_infos.distances.push_back(info);
00173         }
00174 
00175         std::map<std::string, boost::shared_ptr<fcl::CollisionObject> >::iterator selfcollision_it;
00176         for (selfcollision_it = robot_links.begin(); selfcollision_it != robot_links.end(); ++selfcollision_it)
00177         {
00178             std::string robot_self_name = selfcollision_it->first;
00179             collision_detection::AllowedCollision::Type type;
00180 
00181             if(acm_.getEntry(robot_link_name, robot_self_name, type))
00182             {
00183                 if(type == collision_detection::AllowedCollision::NEVER)
00184                 {
00185                     const boost::shared_ptr<fcl::CollisionObject> robot_self_object = robot_links[robot_self_name];
00186                     ROS_DEBUG_STREAM("CollisionLink: " << robot_self_name << ", Type: " << robot_self_object->getObjectType());
00187 
00188                     cob_control_msgs::ObstacleDistance info;
00189                     info = getDistanceInfo(robot_object, robot_self_object);
00190 
00191                     info.header.frame_id = planning_frame;
00192                     info.header.stamp = event.current_real;
00193                     info.link_of_interest = robot_link_name;
00194                     info.obstacle_id = robot_self_name;
00195 
00196                     distance_infos.distances.push_back(info);
00197                 }
00198                 else
00199                 {
00200                     // This is diagonal of allowed collision matrix
00201                 }
00202             }
00203         }
00204     }
00205     distance_pub_.publish(distance_infos);
00206 }
00207 
00208 void ObstacleDistanceMoveit::planningSceneTimerCallback(const ros::TimerEvent& event)
00209 {
00210     planning_scene_monitor::LockedPlanningSceneRO ps(planning_scene_monitor_);
00211     planning_scene::PlanningScenePtr planning_scene_ptr = ps->diff();
00212 
00213     moveit_msgs::PlanningScene scene;
00214     planning_scene_ptr->getPlanningSceneMsg(scene);
00215     monitored_scene_pub_.publish(scene);
00216 }
00217 
00218 
00219 bool ObstacleDistanceMoveit::calculateDistanceServiceCallback(cob_control_msgs::GetObstacleDistance::Request &req,
00220                                                               cob_control_msgs::GetObstacleDistance::Response &resp)
00221 {
00222     std::map<std::string, boost::shared_ptr<fcl::CollisionObject> > robot_links = this->robot_links_;
00223     std::map<std::string, boost::shared_ptr<fcl::CollisionObject> > collision_objects = this->collision_objects_;
00224     
00225     // Links
00226     for (unsigned int i=0; i< req.links.size(); ++i)
00227     {
00228         if (req.objects.size() == 0)
00229         {
00230             // All objects
00231             std::map<std::string, boost::shared_ptr<fcl::CollisionObject> >::iterator it;
00232             for (it = collision_objects.begin(); it != collision_objects.end(); ++it)
00233             {
00234                 const boost::shared_ptr<fcl::CollisionObject> collision_object = collision_objects[it->first];
00235                 if(collision_object->getObjectType() == fcl::OT_OCTREE)
00236                 {
00237                     ROS_WARN_THROTTLE(1, "Consideration of <octomap> not yet implemented");
00238                     continue;
00239                 }
00240                 resp.link_to_object.push_back(req.links[i] + "_to_" + it->first);
00241                 resp.distances.push_back(getDistanceInfo(robot_links[req.links[i]], collision_object).distance);
00242             }
00243         }
00244         else
00245         {
00246             // Specific objects
00247             for (int y = 0; y < req.objects.size(); y++)
00248             {
00249                 const boost::shared_ptr<fcl::CollisionObject> collision_object = collision_objects[req.objects[y]];
00250                 if(collision_object->getObjectType() == fcl::OT_OCTREE)
00251                 {
00252                     ROS_WARN_THROTTLE(1, "Consideration of <octomap> not yet implemented");
00253                     continue;
00254                 }
00255                 resp.link_to_object.push_back(req.links[i] + " to " + req.objects[y]);
00256                 resp.distances.push_back(getDistanceInfo(robot_links[req.links[i]], collision_object).distance);
00257             }
00258         }
00259     }
00260     return true;
00261 }
00262 
00263 cob_control_msgs::ObstacleDistance ObstacleDistanceMoveit::getDistanceInfo(const boost::shared_ptr<fcl::CollisionObject> object_a,
00264                                                                            const boost::shared_ptr<fcl::CollisionObject> object_b)
00265 {
00266     fcl::DistanceRequest req(true);  // enable_nearest_points
00267     fcl::DistanceResult res;
00268     res.update(MAXIMAL_MINIMAL_DISTANCE, NULL, NULL, fcl::DistanceResult::NONE, fcl::DistanceResult::NONE);
00269 
00270     Eigen::Vector3d np_object_a;
00271     Eigen::Vector3d np_object_b;
00272 
00273     double dist = fcl::distance(object_a.get(), object_b.get(), req, res);
00274 
00275     // this is to prevent what seems to be a nasty bug in fcl
00276     if(object_a->getObjectType() == fcl::OT_GEOM && object_b->getObjectType() == fcl::OT_BVH)
00277     {
00278         // res.nearest_points is swapped in this case
00279         np_object_a(0) = res.nearest_points[1][0];
00280         np_object_a(1) = res.nearest_points[1][1];
00281         np_object_a(2) = res.nearest_points[1][2];
00282 
00283         np_object_b(0) = res.nearest_points[0][0];
00284         np_object_b(1) = res.nearest_points[0][1];
00285         np_object_b(2) = res.nearest_points[0][2];
00286     }
00287     else
00288     {
00289         np_object_a(0) = res.nearest_points[0][0];
00290         np_object_a(1) = res.nearest_points[0][1];
00291         np_object_a(2) = res.nearest_points[0][2];
00292 
00293         np_object_b(0) = res.nearest_points[1][0];
00294         np_object_b(1) = res.nearest_points[1][1];
00295         np_object_b(2) = res.nearest_points[1][2];
00296     }
00297     // ToDo: are there other cases? OT_OCTREE? see fcl::OBJECT_TYPE
00298 
00299     geometry_msgs::Vector3 np_object_a_msg;
00300     tf::vectorEigenToMsg(np_object_a, np_object_a_msg);
00301     ROS_DEBUG_STREAM("NearestPoint OBJ_A: \n" << np_object_a_msg);
00302 
00303     geometry_msgs::Vector3 np_object_b_msg;
00304     tf::vectorEigenToMsg(np_object_b, np_object_b_msg);
00305     ROS_DEBUG_STREAM("NearestPoint OBJ_B: \n" << np_object_b_msg);
00306 
00307     // Transformation for object_a
00308     fcl::Transform3f fcl_trans_object_a = object_a->getTransform();
00309     fcl::Vec3f fcl_vec_object_a = fcl_trans_object_a.getTranslation();
00310     fcl::Quaternion3f fcl_quat_object_a = fcl_trans_object_a.getQuatRotation();
00311 
00312     Eigen::Affine3d eigen_trans_object_a;
00313     tf::Transform tf_trans_object_a(tf::Quaternion(fcl_quat_object_a.getX(),fcl_quat_object_a.getY(),fcl_quat_object_a.getZ(),fcl_quat_object_a.getW()),
00314                                     tf::Vector3(fcl_vec_object_a[0],fcl_vec_object_a[1],fcl_vec_object_a[2]));
00315     tf::transformTFToEigen(tf_trans_object_a, eigen_trans_object_a);
00316 
00317     geometry_msgs::Transform trans_object_a_msg;
00318     tf::transformTFToMsg(tf_trans_object_a, trans_object_a_msg);
00319     ROS_DEBUG_STREAM("Transform OBJ_A: \n" << trans_object_a_msg);
00320 
00321     // Transformation for object_b
00322     fcl::Transform3f fcl_trans_object_b = object_b->getTransform();
00323     fcl::Vec3f fcl_vec_object_b = fcl_trans_object_b.getTranslation();
00324     fcl::Quaternion3f fcl_quat_object_b = fcl_trans_object_b.getQuatRotation();
00325 
00326     Eigen::Affine3d eigen_trans_object_b;
00327     tf::Transform tf_trans_object_b(tf::Quaternion(fcl_quat_object_b.getX(),fcl_quat_object_b.getY(),fcl_quat_object_b.getZ(),fcl_quat_object_b.getW()),
00328                                     tf::Vector3(fcl_vec_object_b[0],fcl_vec_object_b[1],fcl_vec_object_b[2]));
00329     tf::transformTFToEigen(tf_trans_object_b, eigen_trans_object_b);
00330 
00331     geometry_msgs::Transform trans_object_b_msg;
00332     tf::transformTFToMsg(tf_trans_object_b, trans_object_b_msg);
00333     ROS_DEBUG_STREAM("Transform OBJ_B: \n" << trans_object_b_msg);
00334 
00335     //  in case both objects are of OBJECT_TYPE OT_BVH the nearest points are already given in PlanningFrame coordinates
00336     if(!(object_a->getObjectType() == fcl::OT_BVH && object_b->getObjectType() == fcl::OT_BVH))
00337     {
00338         np_object_a = eigen_trans_object_a * np_object_a;
00339         np_object_b = eigen_trans_object_b * np_object_b;
00340     }
00341     // ToDo: are there other cases? OT_OCTREE? see fcl::OBJECT_TYPE
00342 
00343     if (dist < 0) dist = 0;
00344 
00345     cob_control_msgs::ObstacleDistance info;
00346     info.distance = dist;
00347 
00348     tf::vectorEigenToMsg(np_object_a, info.nearest_point_frame_vector);
00349     tf::vectorEigenToMsg(np_object_b, info.nearest_point_obstacle_vector);    
00350     ROS_DEBUG_STREAM("NearestPointTransformed OBJ_A: \n" << info.nearest_point_frame_vector);
00351     ROS_DEBUG_STREAM("NearestPointTransformed OBJ_B: \n" << info.nearest_point_obstacle_vector);
00352 
00353     return info;
00354 }
00355 
00356 ObstacleDistanceMoveit::ObstacleDistanceMoveit()
00357 {
00358     MAXIMAL_MINIMAL_DISTANCE = 5.0; //m
00359     double update_frequency = 50.0; //Hz
00360 
00361     std::string robot_description = "/robot_description";
00362     std::string robot_description_semantic = "/robot_description_semantic";
00363     std::string distance_service = "/calculate_distance";
00364     std::string register_service = "/register_links";
00365     std::string unregister_service = "/unregister_links";
00366     std::string distance_topic = "/obstacle_distances";
00367 
00368 
00369     // Get AllowedCollisionMatrix
00370     robot_model_loader::RobotModelLoader robot_model_loader("robot_description", "robot_description_semantic");
00371     planning_scene::PlanningScene pss(robot_model_loader.getURDF(), robot_model_loader.getSRDF());
00372     acm_ = pss.getAllowedCollisionMatrix();
00373 
00374     //Initialize planning scene monitor
00375     boost::shared_ptr<tf::TransformListener> tf_listener_(new tf::TransformListener(ros::Duration(2.0)));
00376     planning_scene_monitor_ = boost::make_shared<planning_scene_monitor::PlanningSceneMonitor>(robot_description, tf_listener_);
00377 
00378     planning_scene_monitor_->setStateUpdateFrequency(update_frequency);
00379     planning_scene_monitor_->startSceneMonitor(planning_scene_monitor::PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_TOPIC);
00380     planning_scene_monitor_->startWorldGeometryMonitor(planning_scene_monitor::PlanningSceneMonitor::DEFAULT_COLLISION_OBJECT_TOPIC,
00381                                                        planning_scene_monitor::PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_WORLD_TOPIC,
00382                                                        true);  // load_octomap_monitor
00383     planning_scene_monitor_->startStateMonitor(planning_scene_monitor::PlanningSceneMonitor::DEFAULT_JOINT_STATES_TOPIC,
00384                                                planning_scene_monitor::PlanningSceneMonitor::DEFAULT_ATTACHED_COLLISION_OBJECT_TOPIC);
00385     planning_scene_monitor_->addUpdateCallback(boost::bind(&ObstacleDistanceMoveit::updatedScene, this, _1));
00386 
00387     registered_links_.clear();
00388 
00389     calculate_obstacle_distance_ = nh_.advertiseService(distance_service, &ObstacleDistanceMoveit::calculateDistanceServiceCallback, this);
00390     register_server_ = nh_.advertiseService(register_service, &ObstacleDistanceMoveit::registerCallback, this);
00391     unregister_server_ = nh_.advertiseService(unregister_service, &ObstacleDistanceMoveit::unregisterCallback, this);
00392     distance_timer_ = nh_.createTimer(ros::Duration(1.0/update_frequency), &ObstacleDistanceMoveit::calculateDistanceTimerCallback, this);
00393     distance_pub_ = nh_.advertise<cob_control_msgs::ObstacleDistances>(distance_topic, 1);
00394 
00395     monitored_scene_pub_ = nh_.advertise<moveit_msgs::PlanningScene>("/monitored_planning_scene", 1);
00396     monitored_scene_server_ = nh_.advertiseService("/get_planning_scene", &ObstacleDistanceMoveit::planningSceneCallback, this);
00397     planning_scene_timer_ = nh_.createTimer(ros::Duration(1.0/update_frequency), &ObstacleDistanceMoveit::planningSceneTimerCallback, this);
00398 }


cob_obstacle_distance_moveit
Author(s): Florian Koehler , Felix Messmer
autogenerated on Thu Jun 6 2019 21:23:10