00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
00226 for (unsigned int i=0; i< req.links.size(); ++i)
00227 {
00228 if (req.objects.size() == 0)
00229 {
00230
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
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);
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
00276 if(object_a->getObjectType() == fcl::OT_GEOM && object_b->getObjectType() == fcl::OT_BVH)
00277 {
00278
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
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
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
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
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
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;
00359 double update_frequency = 50.0;
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
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
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);
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 }