00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <limits>
00019 #include <string>
00020 #include <vector>
00021
00022 #include "cob_obstacle_distance/distance_manager.hpp"
00023
00024
00025 #include <stdint.h>
00026
00027 #include <ros/ros.h>
00028
00029 #include <fcl/collision_object.h>
00030 #include <fcl/collision.h>
00031 #include <fcl/distance.h>
00032 #include <fcl/collision_data.h>
00033
00034 #include <std_msgs/Float64.h>
00035 #include <visualization_msgs/Marker.h>
00036
00037 #include "cob_control_msgs/ObstacleDistance.h"
00038 #include "cob_control_msgs/ObstacleDistances.h"
00039
00040 #include <boost/filesystem.hpp>
00041 #include <boost/filesystem/path.hpp>
00042 #include <boost/pointer_cast.hpp>
00043
00044 #include <eigen_conversions/eigen_kdl.h>
00045 #include <eigen_conversions/eigen_msg.h>
00046
00047 #include <kdl_conversions/kdl_msg.h>
00048
00049 #include <urdf/model.h>
00050
00051 #include <shape_msgs/Mesh.h>
00052 #include <shape_msgs/MeshTriangle.h>
00053 #include <shape_msgs/SolidPrimitive.h>
00054
00055 #define VEC_X 0
00056 #define VEC_Y 1
00057 #define VEC_Z 2
00058
00059
00060 uint32_t DistanceManager::seq_nr_ = 0;
00061
00062 DistanceManager::DistanceManager(ros::NodeHandle& nh) : nh_(nh), stop_sca_threads_(false)
00063 {}
00064
00065 DistanceManager::~DistanceManager()
00066 {
00067 this->clear();
00068 }
00069
00070 int DistanceManager::init()
00071 {
00072 this->stop_sca_threads_ = false;
00073
00074
00075 this->marker_pub_ = this->nh_.advertise<visualization_msgs::MarkerArray>("obstacle_distance/marker", 10, true);
00076 this->obstacle_distances_pub_ = this->nh_.advertise<cob_control_msgs::ObstacleDistances>("obstacle_distance", 1);
00077 obstacle_mgr_.reset(new ShapesManager(this->marker_pub_));
00078 object_of_interest_mgr_.reset(new ShapesManager(this->marker_pub_));
00079 KDL::Tree robot_structure;
00080 if (!kdl_parser::treeFromParam("/robot_description", robot_structure))
00081 {
00082 ROS_ERROR("Failed to construct kdl tree from parameter '/robot_description'.");
00083 return -1;
00084 }
00085
00086 if (!nh_.getParam("joint_names", this->joints_))
00087 {
00088 ROS_ERROR("Failed to get parameter \"joint_names\".");
00089 return -2;
00090 }
00091
00092 if (!nh_.getParam("root_frame", this->root_frame_id_))
00093 {
00094 ROS_ERROR("Failed to get parameter \"chain_base_link\".");
00095 return -3;
00096 }
00097
00098 if (!nh_.getParam("chain_base_link", this->chain_base_link_))
00099 {
00100 ROS_ERROR("Failed to get parameter \"chain_base_link\".");
00101 return -3;
00102 }
00103
00104 if (!nh_.getParam("chain_tip_link", this->chain_tip_link_))
00105 {
00106 ROS_ERROR("Failed to get parameter \"chain_tip_link\".");
00107 return -4;
00108 }
00109
00110 robot_structure.getChain(this->chain_base_link_, this->chain_tip_link_, this->chain_);
00111 if (chain_.getNrOfJoints() == 0)
00112 {
00113 ROS_ERROR("Failed to initialize kinematic chain");
00114 return -5;
00115 }
00116
00117 for (uint16_t i = 0; i < chain_.getNrOfSegments(); ++i)
00118 {
00119 KDL::Segment s = chain_.getSegment(i);
00120 this->segments_.push_back(s.getName());
00121 ROS_INFO_STREAM("Managing Segment Name: " << s.getName());
00122 }
00123
00124 adv_chn_fk_solver_vel_.reset(new AdvancedChainFkSolverVel_recursive(chain_));
00125 last_q_ = KDL::JntArray(chain_.getNrOfJoints());
00126 last_q_dot_ = KDL::JntArray(chain_.getNrOfJoints());
00127 if (!this->link_to_collision_.initParameter(this->root_frame_id_, "/robot_description"))
00128 {
00129 ROS_ERROR("Failed to initialize robot model from URDF by parameter \"/robot_description\".");
00130 return -6;
00131 }
00132 else
00133 {
00134 XmlRpc::XmlRpcValue scm;
00135 bool success = false;
00136 if (nh_.getParam("self_collision_map", scm))
00137 {
00138 success = this->link_to_collision_.initSelfCollision(scm, obstacle_mgr_);
00139 }
00140
00141 if (!success)
00142 {
00143 ROS_WARN("Parameter 'self_collision_map' not found or map empty.");
00144 }
00145
00146 for (LinkToCollision::MapSelfCollisions_t::iterator it = this->link_to_collision_.getSelfCollisionsIterBegin();
00147 it != this->link_to_collision_.getSelfCollisionsIterEnd();
00148 it++)
00149 {
00150 self_collision_transform_threads_.push_back(std::thread(&DistanceManager::transformSelfCollisionLinks, this, it->first));
00151 }
00152 }
00153
00154 return 0;
00155 }
00156
00157 void DistanceManager::clear()
00158 {
00159 this->stop_sca_threads_ = true;
00160 for (std::vector<std::thread>::iterator it = this->self_collision_transform_threads_.begin();
00161 it != this->self_collision_transform_threads_.end(); it++)
00162 {
00163 it->join();
00164 }
00165
00166 this->obstacle_mgr_->clear();
00167 this->object_of_interest_mgr_->clear();
00168 }
00169
00170
00171 void DistanceManager::addObstacle(const std::string& id, PtrIMarkerShape_t s)
00172 {
00173 this->obstacle_mgr_->addShape(id, s);
00174 }
00175
00176
00177 void DistanceManager::addObjectOfInterest(const std::string& id, PtrIMarkerShape_t s)
00178 {
00179 this->object_of_interest_mgr_->addShape(id, s);
00180 }
00181
00182
00183 void DistanceManager::drawObstacles()
00184 {
00185 this->obstacle_mgr_->draw();
00186 }
00187
00188
00189 void DistanceManager::drawObjectsOfInterest()
00190 {
00191 this->object_of_interest_mgr_->draw();
00192 }
00193
00194
00195 void DistanceManager::calculate()
00196 {
00197 cob_control_msgs::ObstacleDistances obstacle_distances;
00198
00199
00200
00201 if (this->object_of_interest_mgr_->count() > 0)
00202 {
00203 KDL::FrameVel p_dot_out;
00204 KDL::JntArrayVel jnt_arr(last_q_, last_q_dot_);
00205 adv_chn_fk_solver_vel_->JntToCart(jnt_arr, p_dot_out);
00206 }
00207
00208 for (ShapesManager::MapIter_t it = this->object_of_interest_mgr_->begin(); it != this->object_of_interest_mgr_->end(); ++it)
00209 {
00210 std::string object_of_interest_name = it->first;
00211 std::vector<std::string>::const_iterator str_it = std::find(this->segments_.begin(),
00212 this->segments_.end(),
00213 object_of_interest_name);
00214 if (this->segments_.end() == str_it)
00215 {
00216 ROS_ERROR_STREAM("Could not find: " << object_of_interest_name << ". Skipping it ...");
00217 continue;
00218 }
00219
00220
00221 PtrIMarkerShape_t ooi = it->second;
00222 uint16_t idx = str_it - this->segments_.begin();
00223 geometry_msgs::Pose origin_p = ooi->getOriginRelToFrame();
00224 KDL::Frame origin_f;
00225 tf::poseMsgToKDL(origin_p, origin_f);
00226
00227
00228 KDL::FrameVel frame_vel = adv_chn_fk_solver_vel_->getFrameVelAtSegment(idx);
00229 KDL::Frame frame_pos = frame_vel.GetFrame();
00230 KDL::Frame frame_with_offset = frame_pos * origin_f;
00231
00232 Eigen::Vector3d chainbase2frame_pos(frame_with_offset.p.x(),
00233 frame_with_offset.p.y(),
00234 frame_with_offset.p.z());
00235
00236 Eigen::Affine3d tmp_tf_cb_frame_bl = this->getSynchedCbToBlTransform();
00237 Eigen::Affine3d tmp_inv_tf_cb_frame_bl = tmp_tf_cb_frame_bl.inverse();
00238 Eigen::Vector3d abs_jnt_pos = tmp_inv_tf_cb_frame_bl * chainbase2frame_pos;
00239
00240 Eigen::Quaterniond q;
00241 tf::quaternionKDLToEigen(frame_with_offset.M, q);
00242 Eigen::Matrix3d x = (tmp_inv_tf_cb_frame_bl * q).rotation();
00243 Eigen::Quaterniond q_1(x);
00244
00245
00246 geometry_msgs::Vector3 v3;
00247 geometry_msgs::Quaternion quat;
00248 tf::quaternionEigenToMsg(q_1, quat);
00249 tf::vectorEigenToMsg(abs_jnt_pos, v3);
00250 ooi->updatePose(v3, quat);
00251
00252 fcl::CollisionObject ooi_co = ooi->getCollisionObject();
00253 fcl::FCL_REAL last_dist = std::numeric_limits<fcl::FCL_REAL>::max();
00254 {
00255 std::lock_guard<std::mutex> lock(obstacle_mgr_mtx_);
00256 for (ShapesManager::MapIter_t it = this->obstacle_mgr_->begin(); it != this->obstacle_mgr_->end(); ++it)
00257 {
00258 const std::string obstacle_id = it->first;
00259 if (this->link_to_collision_.ignoreSelfCollisionPart(object_of_interest_name, obstacle_id))
00260 {
00261
00262
00263 continue;
00264 }
00265
00266 PtrIMarkerShape_t obstacle = it->second;
00267 fcl::CollisionObject collision_obj = obstacle->getCollisionObject();
00268 fcl::DistanceResult dist_result;
00269 fcl::DistanceRequest dist_request(true, 5.0, 0.01);
00270 fcl::FCL_REAL dist = fcl::distance(&ooi_co, &collision_obj, dist_request, dist_result);
00271
00272
00273 Eigen::Vector3d abs_obst_vector(dist_result.nearest_points[1][VEC_X],
00274 dist_result.nearest_points[1][VEC_Y],
00275 dist_result.nearest_points[1][VEC_Z]);
00276 Eigen::Vector3d obst_vector = tmp_tf_cb_frame_bl * abs_obst_vector;
00277
00278 Eigen::Vector3d abs_jnt_pos_update(dist_result.nearest_points[0][VEC_X],
00279 dist_result.nearest_points[0][VEC_Y],
00280 dist_result.nearest_points[0][VEC_Z]);
00281
00282
00283 Eigen::Vector3d rel_base_link_frame_pos = tmp_tf_cb_frame_bl * abs_jnt_pos_update;
00284 ROS_DEBUG_STREAM("Link \"" << object_of_interest_name << "\": Minimal distance: " << dist_result.min_distance);
00285 if (dist_result.min_distance < MIN_DISTANCE)
00286 {
00287 cob_control_msgs::ObstacleDistance od_msg;
00288 od_msg.distance = dist_result.min_distance;
00289 od_msg.link_of_interest = object_of_interest_name;
00290 od_msg.obstacle_id = obstacle_id;
00291 od_msg.header.frame_id = chain_base_link_;
00292 od_msg.header.stamp = ros::Time::now();
00293 od_msg.header.seq = seq_nr_;
00294 tf::vectorEigenToMsg(obst_vector, od_msg.nearest_point_obstacle_vector);
00295 tf::vectorEigenToMsg(rel_base_link_frame_pos, od_msg.nearest_point_frame_vector);
00296 tf::vectorEigenToMsg(chainbase2frame_pos, od_msg.frame_vector);
00297 obstacle_distances.distances.push_back(od_msg);
00298 }
00299 }
00300 }
00301 }
00302
00303 if (obstacle_distances.distances.size() > 0)
00304 {
00305 this->obstacle_distances_pub_.publish(obstacle_distances);
00306 }
00307 }
00308
00309
00310 void DistanceManager::transform()
00311 {
00312 while (!this->stop_sca_threads_)
00313 {
00314 try
00315 {
00316 tf::StampedTransform cb_transform_bl;
00317 ros::Time time = ros::Time(0);
00318 if (tf_listener_.waitForTransform(chain_base_link_, root_frame_id_, time, ros::Duration(5.0)))
00319 {
00320 std::lock_guard<std::mutex> lock(mtx_);
00321 tf_listener_.lookupTransform(chain_base_link_, root_frame_id_, time, cb_transform_bl);
00322 tf::transformTFToEigen(cb_transform_bl, tf_cb_frame_bl_);
00323 }
00324 }
00325 catch (tf::TransformException& ex)
00326 {
00327 ROS_ERROR("%s", ex.what());
00328 }
00329
00330 ros::Duration(0.1).sleep();
00331 }
00332 }
00333
00334
00335 void DistanceManager::transformSelfCollisionLinks(const std::string link_name)
00336 {
00337 ROS_INFO_STREAM("Starting transform_listener thread for link name: " << link_name);
00338 while (!this->stop_sca_threads_)
00339 {
00340 try
00341 {
00342 ros::Time time = ros::Time(0);
00343
00344 if (tf_listener_.waitForTransform(root_frame_id_, link_name, time, ros::Duration(5.0)))
00345 {
00346 std::lock_guard<std::mutex> lock(obstacle_mgr_mtx_);
00347 tf::StampedTransform stamped_transform;
00348 geometry_msgs::Transform msg_transform;
00349 tf_listener_.lookupTransform(root_frame_id_, link_name, time, stamped_transform);
00350 PtrIMarkerShape_t shape_ptr;
00351 if (this->obstacle_mgr_->getShape(link_name, shape_ptr))
00352 {
00353 geometry_msgs::Pose origin_p = shape_ptr->getOriginRelToFrame();
00354 tf::Transform tf_origin_pose;
00355 tf::poseMsgToTF(origin_p, tf_origin_pose);
00356 tf::Transform updated_pose = tf::Transform(stamped_transform) * tf_origin_pose;
00357 tf::transformTFToMsg(updated_pose, msg_transform);
00358 shape_ptr->updatePose(msg_transform.translation, msg_transform.rotation);
00359 }
00360 }
00361 }
00362 catch (tf::TransformException& ex)
00363 {
00364 ROS_ERROR("%s", ex.what());
00365 }
00366
00367 ros::Duration(0.1).sleep();
00368 }
00369 }
00370
00371
00372 void DistanceManager::jointstateCb(const sensor_msgs::JointState::ConstPtr& msg)
00373 {
00374 KDL::JntArray q_temp = last_q_;
00375 KDL::JntArray q_dot_temp = last_q_dot_;
00376 uint16_t count = 0;
00377
00378 for (uint16_t j = 0; j < chain_.getNrOfJoints(); j++)
00379 {
00380 for (uint16_t i = 0; i < msg->name.size(); i++)
00381 {
00382 if (strcmp(msg->name[i].c_str(), joints_[j].c_str()) == 0)
00383 {
00384 q_temp(j) = msg->position[i];
00385 q_dot_temp(j) = msg->velocity[i];
00386 count++;
00387 break;
00388 }
00389 }
00390 }
00391
00392 if (joints_.size() == count)
00393 {
00394 last_q_ = q_temp;
00395 last_q_dot_ = q_dot_temp;
00396 }
00397 else
00398 {
00399 ROS_ERROR("jointstateCb: received unexpected 'joint_states'");
00400 }
00401 }
00402
00403
00404 void DistanceManager::registerObstacle(const moveit_msgs::CollisionObject::ConstPtr& msg)
00405 {
00406 std::lock_guard<std::mutex> lock(obstacle_mgr_mtx_);
00407
00408 const std::string frame_id = msg->header.frame_id;
00409 tf::StampedTransform frame_transform_root;
00410 Eigen::Affine3d tf_frame_root;
00411
00412 if (msg->meshes.size() > 0 && msg->primitives.size() > 0)
00413 {
00414 ROS_ERROR_STREAM("registerObstacle: Can either build mesh or primitive but not both in one message for one id.");
00415 return;
00416 }
00417
00418 if (msg->operation == msg->ADD && this->obstacle_mgr_->count(msg->id) > 0)
00419 {
00420 ROS_ERROR_STREAM("registerObstacle: Element " << msg->id << " exists already. ADD not allowed!");
00421 return;
00422 }
00423
00424 try
00425 {
00426 ros::Time time = ros::Time(0);
00427 tf_listener_.waitForTransform(root_frame_id_, msg->header.frame_id, time, ros::Duration(0.5));
00428 tf_listener_.lookupTransform(root_frame_id_, msg->header.frame_id, time, frame_transform_root);
00429 tf::transformTFToEigen(frame_transform_root, tf_frame_root);
00430 }
00431 catch (tf::TransformException& ex)
00432 {
00433 ROS_ERROR("TransformException: %s", ex.what());
00434 return;
00435 }
00436
00437 if ((msg->type.db.length() > 0 && 0 < msg->mesh_poses.size()) ||
00438 (msg->meshes.size() > 0 && msg->meshes.size() == msg->mesh_poses.size()))
00439 {
00440 this->buildObstacleMesh(msg, frame_transform_root);
00441 }
00442
00443 if (msg->primitives.size() > 0 && msg->primitives.size() == msg->primitive_poses.size())
00444 {
00445 this->buildObstaclePrimitive(msg, frame_transform_root);
00446 }
00447
00448 this->drawObstacles();
00449 }
00450
00451
00452 void DistanceManager::buildObstacleMesh(const moveit_msgs::CollisionObject::ConstPtr& msg, const tf::StampedTransform& transform)
00453 {
00454 uint32_t m_size = msg->mesh_poses.size();
00455 const std::string package_file_name = msg->type.db;
00456
00457 if (msg->mesh_poses.size() > 1)
00458 {
00459 ROS_WARN("Currenty only one mesh per message is supported! So only the first one is processed ...");
00460 m_size = 1;
00461 }
00462
00463 if (package_file_name.length() <= 0 && msg->mesh_poses.size() != msg->meshes.size())
00464 {
00465 ROS_ERROR("Mesh poses and meshes do not have the same size. If package resource string is empty then the sizes must be equal!");
00466 return;
00467 }
00468
00469 if (msg->ADD == msg->operation)
00470 {
00471 for (uint32_t i = 0; i < m_size; ++i)
00472 {
00473 geometry_msgs::Pose p = msg->mesh_poses[i];
00474 tf::Pose tf_p;
00475 tf::poseMsgToTF(p, tf_p);
00476 tf::Pose new_tf_p = transform * tf_p;
00477 tf::poseTFToMsg(new_tf_p, p);
00478 PtrIMarkerShape_t sptr_Bvh;
00479 if (package_file_name.length() > 0)
00480 {
00481 sptr_Bvh.reset(new MarkerShape<BVH_RSS_t>(this->root_frame_id_,
00482 package_file_name,
00483 p,
00484 g_shapeMsgTypeToVisMarkerType.obstacle_color_));
00485 }
00486 else
00487 {
00488 shape_msgs::Mesh m = msg->meshes[i];
00489 sptr_Bvh.reset(new MarkerShape<BVH_RSS_t>(this->root_frame_id_,
00490 m,
00491 p,
00492 g_shapeMsgTypeToVisMarkerType.obstacle_color_));
00493 }
00494
00495 this->addObstacle(msg->id, sptr_Bvh);
00496 }
00497 }
00498 else if (msg->MOVE == msg->operation)
00499 {
00500 PtrIMarkerShape_t sptr;
00501 for (uint32_t i = 0; i < m_size; ++i)
00502 {
00503 if (this->obstacle_mgr_->getShape(msg->id, sptr))
00504 {
00505 geometry_msgs::Pose p = msg->mesh_poses[i];
00506 tf::Pose tf_p;
00507 tf::poseMsgToTF(p, tf_p);
00508 tf::Pose new_tf_p = transform * tf_p;
00509 tf::poseTFToMsg(new_tf_p, p);
00510 sptr->updatePose(p);
00511 }
00512 }
00513 }
00514 else if (msg->REMOVE == msg->operation)
00515 {
00516 this->obstacle_mgr_->removeShape(msg->id);
00517 }
00518 else
00519 {
00520 ROS_ERROR_STREAM("Operation not supported!");
00521 }
00522 }
00523
00524
00525 void DistanceManager::buildObstaclePrimitive(const moveit_msgs::CollisionObject::ConstPtr& msg, const tf::StampedTransform& transform)
00526 {
00527 uint32_t p_size = msg->primitives.size();
00528 if (msg->primitives.size() > 1)
00529 {
00530 ROS_WARN("Currenty only one primitive per message is supported! So only the first one is processed ...");
00531 p_size = 1;
00532 }
00533
00534 if (msg->ADD == msg->operation)
00535 {
00536 for (uint32_t i = 0; i < p_size; ++i)
00537 {
00538 shape_msgs::SolidPrimitive sp = msg->primitives[i];
00539 geometry_msgs::Pose p = msg->primitive_poses[i];
00540 tf::Pose tf_p;
00541 tf::poseMsgToTF(p, tf_p);
00542 tf::Pose new_tf_p = transform * tf_p;
00543 tf::poseTFToMsg(new_tf_p, p);
00544
00545 PtrIMarkerShape_t sptr;
00546 Eigen::Vector3d dim;
00547 if (shape_msgs::SolidPrimitive::BOX == sp.type)
00548 {
00549 dim(FCL_BOX_X) = sp.dimensions[shape_msgs::SolidPrimitive::BOX_X];
00550 dim(FCL_BOX_Y) = sp.dimensions[shape_msgs::SolidPrimitive::BOX_Y];
00551 dim(FCL_BOX_Z) = sp.dimensions[shape_msgs::SolidPrimitive::BOX_Z];
00552 }
00553 else if (shape_msgs::SolidPrimitive::SPHERE == sp.type)
00554 {
00555 dim(FCL_RADIUS) = sp.dimensions[shape_msgs::SolidPrimitive::SPHERE_RADIUS];
00556 }
00557 else if (shape_msgs::SolidPrimitive::CYLINDER == sp.type)
00558 {
00559 dim(FCL_RADIUS) = sp.dimensions[shape_msgs::SolidPrimitive::CYLINDER_RADIUS];
00560 dim(FCL_CYL_LENGTH) = sp.dimensions[shape_msgs::SolidPrimitive::CYLINDER_HEIGHT];
00561 }
00562 else
00563 {
00564 ROS_ERROR_STREAM("Shape type not supported: " << sp.type);
00565 break;
00566 }
00567
00568 uint32_t shape_type = g_shapeMsgTypeToVisMarkerType.map_[sp.type];
00569 this->link_to_collision_.getMarkerShapeFromType(shape_type,
00570 p,
00571 msg->id,
00572 dim,
00573 sptr);
00574 this->addObstacle(msg->id, sptr);
00575 }
00576 }
00577 else if (msg->MOVE == msg->operation)
00578 {
00579 PtrIMarkerShape_t sptr;
00580 for (uint32_t i = 0; i < p_size; ++i)
00581 {
00582 if (this->obstacle_mgr_->getShape(msg->id, sptr))
00583 {
00584 geometry_msgs::Pose p = msg->primitive_poses[i];
00585 tf::Pose tf_p;
00586 tf::poseMsgToTF(p, tf_p);
00587 tf::Pose new_tf_p = transform * tf_p;
00588 tf::poseTFToMsg(new_tf_p, p);
00589 sptr->updatePose(p);
00590 }
00591 }
00592 }
00593 else if (msg->REMOVE == msg->operation)
00594 {
00595 this->obstacle_mgr_->removeShape(msg->id);
00596 }
00597 else
00598 {
00599 ROS_ERROR_STREAM("Operation not supported!");
00600 }
00601 }
00602
00603
00604 bool DistanceManager::registerLinkOfInterest(cob_srvs::SetString::Request& request,
00605 cob_srvs::SetString::Response& response)
00606 {
00607 if (this->object_of_interest_mgr_->count(request.data) > 0)
00608 {
00609 response.success = true;
00610 response.message = "Element " + request.data + " already registered.";
00611 }
00612 else
00613 {
00614 try
00615 {
00616 PtrIMarkerShape_t ooi;
00617 Eigen::Quaterniond q;
00618 Eigen::Vector3d v3;
00619 if (this->link_to_collision_.getMarkerShapeFromUrdf(v3, q, request.data, ooi))
00620 {
00621 this->addObjectOfInterest(request.data, ooi);
00622 response.success = true;
00623 response.message = "Successfully registered element " + request.data + ".";
00624 }
00625 else
00626 {
00627 response.success = false;
00628 response.message = "Failed to register element " + request.data + "!";
00629 }
00630 }
00631 catch(...)
00632 {
00633 response.success = false;
00634 response.message = "Failed to register element " + request.data + "!";
00635 ROS_ERROR_STREAM(response.message);
00636 }
00637 }
00638
00639 ROS_INFO_STREAM("DistanceManager::Registration: " << response.message);
00640 return true;
00641 }
00642
00643
00644 Eigen::Affine3d DistanceManager::getSynchedCbToBlTransform()
00645 {
00646 std::lock_guard<std::mutex> lock(mtx_);
00647 return this->tf_cb_frame_bl_;
00648 }