00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00043
00044 #include <ros/ros.h>
00045
00046 #include <geometry_msgs/Point.h>
00047 #include <sensor_msgs/PointCloud.h>
00048 #include <geometry_msgs/PoseStamped.h>
00049 #include <visualization_msgs/Marker.h>
00050
00051 #include <Eigen/Core>
00052 #include <point_cloud_mapping/geometry/point.h>
00053 #include <point_cloud_mapping/geometry/transforms.h>
00054
00055 #include <boost/thread/mutex.hpp>
00056
00057 #include <mapping_msgs/OrientedBoundingBox.h>
00058 #include <mapping_msgs/CollisionMap.h>
00059 #include <tabletop_srvs/RecordStaticMapTrigger.h>
00060 #include <tabletop_srvs/SubtractObjectFromCollisionMap.h>
00061
00062 #include <tf/transform_listener.h>
00063 #include <sys/time.h>
00064
00065 using namespace std;
00066 using namespace sensor_msgs;
00067 using namespace mapping_msgs;
00068 using namespace tabletop_srvs;
00069 using namespace visualization_msgs;
00070
00071 static const unsigned int MAX_CLOUD_SOURCES = 3;
00072
00073 struct CloudProcSettings {
00074 string cloud_name_;
00075 int frame_subsample_;
00076 int point_subsample_;
00077 };
00078
00079 struct Leaf
00080 {
00081 int i_, j_, k_;
00082 int nr_points_;
00083 };
00084
00086 bool
00087 compareLeaf (const Leaf &l1, const Leaf &l2)
00088 {
00089 if (l1.i_ < l2.i_)
00090 return (true);
00091 else if (l1.i_ > l2.i_)
00092 return (false);
00093 else if (l1.j_ < l2.j_)
00094 return (true);
00095 else if (l1.j_ > l2.j_)
00096 return (false);
00097 else if (l1.k_ < l2.k_)
00098 return (true);
00099 else
00100 return (false);
00101 }
00102
00103 class CollisionMapperBuffer
00104 {
00105 protected:
00106 ros::NodeHandle& node_;
00107
00108 public:
00109
00110
00111 sensor_msgs::PointCloud cloud_;
00112 CollisionMap final_collision_map_;
00113
00114
00115 vector<Leaf> static_leaves_, cur_leaves_, final_leaves_;
00116 list<std::pair<vector<Leaf>, ros::Time> > decaying_maps_;
00117
00118
00119 tf::TransformListener tf_;
00120
00121
00122 geometry_msgs::Point leaf_width_, robot_max_;
00123 int min_nr_points_;
00124 string end_effector_frame_l_, end_effector_frame_r_;
00125 string shared_frame_;
00126
00127
00128 boost::mutex static_map_lock_, object_subtract_lock_, cloud_frame_lock_, m_lock_;
00129
00130
00131 double window_time_;
00132 bool acquire_static_map_;
00133 ros::Time acquire_static_map_time_;
00134
00135
00136 string cloud_frame_;
00137 geometry_msgs::PoseStamped gripper_orientation_link_;
00138 geometry_msgs::Point32 min_object_b_, max_object_b_;
00139 bool subtract_object_;
00140 int m_id_;
00141
00142 CloudProcSettings cloud_source_[MAX_CLOUD_SOURCES];
00143 unsigned int cloud_counter_[MAX_CLOUD_SOURCES];
00144 unsigned int num_actual_sources_;
00145
00146 ros::Subscriber cloud_subscriber_[MAX_CLOUD_SOURCES];
00147 ros::Publisher collision_map_publisher_,visualization_publisher_;
00148
00149 ros::ServiceServer record_static_map_service_;
00150 ros::ServiceServer subtract_object_service_;
00151
00152
00153
00155 CollisionMapperBuffer (ros::NodeHandle& anode) : node_ (anode)
00156 {
00157 ros::NodeHandle priv("~");
00158
00159 priv.param("cloud_source/zero/name", cloud_source_[0].cloud_name_, string("/full_laser_cloud"));
00160 priv.param("cloud_source/zero/frame_subsample", cloud_source_[0].frame_subsample_, 1);
00161 priv.param("cloud_source/zero/point_subsample", cloud_source_[0].point_subsample_,1);
00162 num_actual_sources_ = 1;
00163 if(priv.hasParam ("cloud_source/one"))
00164 {
00165 priv.param("cloud_source/one/name", cloud_source_[1].cloud_name_, string("/full_stereo_cloud"));
00166 priv.param("cloud_source/one/frame_subsample", cloud_source_[1].frame_subsample_, 4);
00167 priv.param("cloud_source/one/point_subsample", cloud_source_[1].point_subsample_,4);
00168 num_actual_sources_ = 2;
00169 if(priv.hasParam("cloud_source/two"))
00170 {
00171 priv.param("cloud_source/two/name", cloud_source_[2].cloud_name_, string("/full_bonus_cloud"));
00172 priv.param("cloud_source/two/frame_subsample", cloud_source_[2].frame_subsample_, 4);
00173 priv.param("cloud_source/two/point_subsample", cloud_source_[2].point_subsample_,4);
00174 num_actual_sources_ = 3;
00175 }
00176 }
00177
00178
00179
00180
00181
00182 priv.param ("leaf_width_x", leaf_width_.x, 0.02);
00183 priv.param ("leaf_width_y", leaf_width_.y, 0.02);
00184 priv.param ("leaf_width_z", leaf_width_.z, 0.02);
00185
00186 priv.param ("robot_max_x", robot_max_.x, 1.5);
00187 priv.param ("robot_max_y", robot_max_.y, 1.5);
00188 priv.param ("robot_max_z", robot_max_.z, 1.5);
00189
00190 priv.param ("min_nr_points", min_nr_points_, 1);
00191
00192 ROS_INFO ("Using a default leaf of size: %g,%g,%g.", leaf_width_.x, leaf_width_.y, leaf_width_.z);
00193 ROS_INFO ("Using a maximum bounding box around the robot of size: %g,%g,%g.", robot_max_.x, robot_max_.y, robot_max_.z);
00194
00195 priv.param ("window_time", window_time_, 5.0);
00196 priv.param ("end_effector_frame_l", end_effector_frame_l_, string ("r_gripper_l_finger_tip_link"));
00197 priv.param ("end_effector_frame_r", end_effector_frame_r_, string ("r_gripper_r_finger_tip_link"));
00198
00199 priv.param ("shared_frame", shared_frame_, string("base_link"));
00200
00201
00202 robot_max_.x = robot_max_.x * robot_max_.x;
00203 robot_max_.y = robot_max_.y * robot_max_.y;
00204 robot_max_.z = robot_max_.z * robot_max_.z;
00205
00206 acquire_static_map_ = false;
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 ROS_DEBUG("Cloud 0 name %s 1 name %s", cloud_source_[0].cloud_name_.c_str(),cloud_source_[1].cloud_name_.c_str());
00225
00226 cloud_subscriber_[0] = node_.subscribe (cloud_source_[0].cloud_name_, 1, &CollisionMapperBuffer::cloudCb0, this);
00227 cloud_counter_[0] = 0;
00228
00229 if(num_actual_sources_ > 1) {
00230 cloud_subscriber_[1] = node_.subscribe (cloud_source_[1].cloud_name_, 1, &CollisionMapperBuffer::cloudCb1, this);
00231 cloud_counter_[1] = 0;
00232 }
00233
00234 if(num_actual_sources_ > 2) {
00235 cloud_subscriber_[2] = node_.subscribe (cloud_source_[2].cloud_name_, 1, &CollisionMapperBuffer::cloudCb2, this);
00236 cloud_counter_[2] = 0;
00237 }
00238
00239 collision_map_publisher_ = node_.advertise<CollisionMap> ("collision_map_buffer", 1);
00240
00241 record_static_map_service_ = node_.advertiseService ("record_static_map", &CollisionMapperBuffer::getStaticMap, this);
00242 subtract_object_service_ = node_.advertiseService ("subtract_object", &CollisionMapperBuffer::subtractObject, this);
00243
00244
00245 gripper_orientation_link_.pose.orientation.x = 0.0;
00246 gripper_orientation_link_.pose.orientation.y = 0.0;
00247 gripper_orientation_link_.pose.orientation.z = 0.0;
00248 gripper_orientation_link_.pose.orientation.w = 1.0;
00249 subtract_object_ = false;
00250
00251 m_id_ = 0;
00252 visualization_publisher_ = node_.advertise<visualization_msgs::Marker>("visualization_marker", 100);
00253 }
00254
00256 virtual ~CollisionMapperBuffer () { }
00257
00259 void
00260 updateParametersFromServer ()
00261 {
00262 ros::NodeHandle priv("~");
00263
00264
00265
00266 if (priv.hasParam ("leaf_width_x")) priv.getParam ("leaf_width_x", leaf_width_.x);
00267 if (priv.hasParam ("leaf_width_y")) priv.getParam ("leaf_width_y", leaf_width_.y);
00268 if (priv.hasParam ("leaf_width_z")) priv.getParam ("leaf_width_z", leaf_width_.z);
00269
00270 if (priv.hasParam ("window_time")) priv.getParam ("window_time", window_time_);
00271
00272 if (priv.hasParam ("robot_max_x"))
00273 {
00274 double rx;
00275 priv.getParam ("robot_max_x", rx);
00276 robot_max_.x = rx * rx;
00277 }
00278 if (priv.hasParam ("robot_max_y"))
00279 {
00280 double ry;
00281 priv.getParam ("robot_max_y", ry);
00282 robot_max_.y = ry * ry;
00283 }
00284 if (priv.hasParam ("robot_max_z"))
00285 {
00286 double rz;
00287 priv.getParam ("robot_max_z", rz);
00288 robot_max_.z = rz * rz;
00289 }
00290
00291 if (priv.hasParam ("min_nr_points")) priv.getParam ("min_nr_points", min_nr_points_);
00292 }
00293
00294
00296
00300 void
00301 computeCollisionMapFromLeaves (vector<Leaf> *leaves, CollisionMap &cmap)
00302 {
00303 cmap.boxes.resize (leaves->size ());
00304
00305 int nr_c = 0;
00306 for (unsigned int cl = 0; cl < leaves->size (); cl++)
00307 {
00308 if (leaves->at (cl).nr_points_ >= min_nr_points_)
00309 {
00310 cmap.boxes[nr_c].extents.x = leaf_width_.x / 2.0;
00311 cmap.boxes[nr_c].extents.y = leaf_width_.y / 2.0;
00312 cmap.boxes[nr_c].extents.z = leaf_width_.z / 2.0;
00313 cmap.boxes[nr_c].center.x = (leaves->at (cl).i_ + 1) * leaf_width_.x - cmap.boxes[nr_c].extents.x;
00314 cmap.boxes[nr_c].center.y = (leaves->at (cl).j_ + 1) * leaf_width_.y - cmap.boxes[nr_c].extents.y;
00315 cmap.boxes[nr_c].center.z = (leaves->at (cl).k_ + 1) * leaf_width_.z - cmap.boxes[nr_c].extents.z;
00316 cmap.boxes[nr_c].axis.x = cmap.boxes[nr_c].axis.y = cmap.boxes[nr_c].axis.z = 0.0;
00317 cmap.boxes[nr_c].angle = 0.0;
00318 nr_c++;
00319 }
00320 }
00321 cmap.boxes.resize (nr_c);
00322 }
00323
00325
00330 void
00331 computeLeaves (sensor_msgs::PointCloud *points, vector<Leaf> &leaves, sensor_msgs::PointCloud ¢ers)
00332 {
00333 geometry_msgs::PointStamped base_origin, torso_lift_origin;
00334 base_origin.point.x = base_origin.point.y = base_origin.point.z = 0.0;
00335 base_origin.header.frame_id = "torso_lift_link";
00336 base_origin.header.stamp = ros::Time ();
00337
00338 try
00339 {
00340 tf_.transformPoint (points->header.frame_id, base_origin, torso_lift_origin);
00341
00342 }
00343 catch (tf::ConnectivityException)
00344 {
00345 ROS_ERROR ("TF not running or wrong TF frame specified! Defaulting to 0,0,0.");
00346 torso_lift_origin = base_origin;
00347 }
00348
00349 vector<int> indices (cloud_.points.size ());
00350 int nr_p = 0;
00351
00352 geometry_msgs::Point32 minP, maxP;
00353 minP.x = minP.y = minP.z = FLT_MAX;
00354 maxP.x = maxP.y = maxP.z = FLT_MIN;
00355 double distance_sqr_x, distance_sqr_y, distance_sqr_z;
00356 for (unsigned int i = 0; i < points->points.size (); i++)
00357 {
00358
00359 distance_sqr_x = fabs ((points->points[i].x - torso_lift_origin.point.x) * (points->points[i].x - torso_lift_origin.point.x));
00360 distance_sqr_y = fabs ((points->points[i].y - torso_lift_origin.point.y) * (points->points[i].y - torso_lift_origin.point.y));
00361 distance_sqr_z = fabs ((points->points[i].z - torso_lift_origin.point.z) * (points->points[i].z - torso_lift_origin.point.z));
00362
00363
00364 if (distance_sqr_x < robot_max_.x && distance_sqr_y < robot_max_.y && distance_sqr_z < robot_max_.z)
00365 {
00366 minP.x = (points->points[i].x < minP.x) ? points->points[i].x : minP.x;
00367 minP.y = (points->points[i].y < minP.y) ? points->points[i].y : minP.y;
00368 minP.z = (points->points[i].z < minP.z) ? points->points[i].z : minP.z;
00369
00370 maxP.x = (points->points[i].x > maxP.x) ? points->points[i].x : maxP.x;
00371 maxP.y = (points->points[i].y > maxP.y) ? points->points[i].y : maxP.y;
00372 maxP.z = (points->points[i].z > maxP.z) ? points->points[i].z : maxP.z;
00373 indices[nr_p] = i;
00374 nr_p++;
00375 }
00376 }
00377 indices.resize (nr_p);
00378
00379
00380 geometry_msgs::Point32 minB, maxB, divB;
00381
00382 minB.x = (int)(floor (minP.x / leaf_width_.x));
00383 maxB.x = (int)(floor (maxP.x / leaf_width_.x));
00384
00385 minB.y = (int)(floor (minP.y / leaf_width_.y));
00386 maxB.y = (int)(floor (maxP.y / leaf_width_.y));
00387
00388 minB.z = (int)(floor (minP.z / leaf_width_.z));
00389 maxB.z = (int)(floor (maxP.z / leaf_width_.z));
00390
00391
00392 divB.x = maxB.x - minB.x + 1;
00393 divB.y = maxB.y - minB.y + 1;
00394 divB.z = maxB.z - minB.z + 1;
00395
00396
00397 if (leaves.capacity () < divB.x * divB.y * divB.z)
00398 leaves.reserve (divB.x * divB.y * divB.z);
00399
00400 leaves.resize (divB.x * divB.y * divB.z);
00401
00402 for (unsigned int cl = 0; cl < leaves.size (); cl++)
00403 {
00404 if (leaves[cl].nr_points_ > 0)
00405 leaves[cl].i_ = leaves[cl].j_ = leaves[cl].k_ = leaves[cl].nr_points_ = 0;
00406 }
00407
00408
00409 centers.header = points->header;
00410 centers.points.resize (indices.size ());
00411 float extents[3];
00412 extents[0] = leaf_width_.x / 2.0;
00413 extents[1] = leaf_width_.y / 2.0;
00414 extents[2] = leaf_width_.z / 2.0;
00415
00416
00417 int i = 0, j = 0, k = 0;
00418 for (unsigned int cp = 0; cp < indices.size (); cp++)
00419 {
00420 i = (int)(floor (points->points[indices.at (cp)].x / leaf_width_.x));
00421 j = (int)(floor (points->points[indices.at (cp)].y / leaf_width_.y));
00422 k = (int)(floor (points->points[indices.at (cp)].z / leaf_width_.z));
00423
00424 int idx = ( (k - minB.z) * divB.y * divB.x ) + ( (j - minB.y) * divB.x ) + (i - minB.x);
00425 leaves[idx].i_ = i;
00426 leaves[idx].j_ = j;
00427 leaves[idx].k_ = k;
00428 leaves[idx].nr_points_++;
00429
00430
00431 centers.points[cp].x = (i + 1) * leaf_width_.x - extents[0];
00432 centers.points[cp].y = (j + 1) * leaf_width_.y - extents[1];
00433 centers.points[cp].z = (k + 1) * leaf_width_.z - extents[2];
00434 }
00435
00436 sort (leaves.begin (), leaves.end (), compareLeaf);
00437 }
00438
00440 void
00441 sendMarker (geometry_msgs::Point32 pt, const std::string &frame_id, double radius = 0.02)
00442 {
00443 Marker mk;
00444 mk.header.stamp = ros::Time::now();
00445
00446 mk.header.frame_id = frame_id;
00447
00448 mk.ns = "collision_map_buffer";
00449 mk.id = ++m_id_;
00450 mk.type = Marker::SPHERE;
00451 mk.action = Marker::ADD;
00452 mk.pose.position.x = pt.x;
00453 mk.pose.position.y = pt.y;
00454 mk.pose.position.z = pt.z;
00455
00456 mk.pose.orientation.w = 1.0;
00457 mk.scale.x = mk.scale.y = mk.scale.z = radius * 2.0;
00458
00459 mk.color.a = 1.0;
00460 mk.color.r = 1.0;
00461 mk.color.g = 0.04;
00462 mk.color.b = 0.04;
00463
00464 visualization_publisher_.publish(mk);
00465 }
00466
00467
00469
00474 inline bool
00475 getEndEffectorPosition (string tgt_frame, ros::Time stamp, geometry_msgs::Point32 ¢er)
00476 {
00477 geometry_msgs::PointStamped src, tgt;
00478 src.header.frame_id = end_effector_frame_l_;
00479 src.header.stamp = stamp;
00480
00481 src.point.x = src.point.y = src.point.z = 0.0;
00482 try
00483 {
00484 tf_.transformPoint (tgt_frame, src, tgt);
00485 }
00486 catch (tf::ConnectivityException)
00487 {
00488 ROS_ERROR ("TF not running or wrong TF end_effector_frame specified!");
00489 return (false);
00490 }
00491 catch (tf::ExtrapolationException)
00492 {
00493 ROS_ERROR("Extrapolation exception from %s to %s.", tgt_frame.c_str(), src.header.frame_id.c_str());
00494 }
00495
00496 center.x = tgt.point.x; center.y = tgt.point.y; center.z = tgt.point.z;
00497
00498 src.header.frame_id = end_effector_frame_r_;
00499 try
00500 {
00501 tf_.transformPoint (tgt_frame, src, tgt);
00502 }
00503 catch (tf::ConnectivityException)
00504 {
00505 ROS_ERROR ("TF not running or wrong TF end_effector_frame specified!");
00506 return (false);
00507 }
00508 catch (tf::ExtrapolationException)
00509 {
00510 ROS_ERROR("Extrapolation exception from %s to %s.", tgt_frame.c_str(), src.header.frame_id.c_str());
00511 }
00512
00513 center.x += tgt.point.x; center.y += tgt.point.y; center.z += tgt.point.z;
00514 center.x /= 2.0; center.y /= 2.0; center.z /= 2.0;
00515 return (true);
00516
00517 }
00518
00520
00529 void pruneLeaves (vector<Leaf> &leaves, sensor_msgs::PointCloud *points, geometry_msgs::Point32 *center, string source_frame, string target_frame,
00530 geometry_msgs::Point32 *min_b, geometry_msgs::Point32 *max_b)
00531 {
00532 sensor_msgs::PointCloud points_tgt;
00533
00534
00535 try
00536 {
00537 tf_.transformPointCloud (target_frame, *points, points_tgt);
00538 }
00539 catch (tf::ConnectivityException)
00540 {
00541 ROS_ERROR ("TF not running or wrong TF end_effector_frame specified!");
00542 return;
00543 }
00544 catch (tf::ExtrapolationException)
00545 {
00546 ROS_ERROR("Extrapolation exception from %s to %s.", target_frame.c_str(), points->header.frame_id.c_str());
00547 }
00548
00549 vector<int> object_indices (points_tgt.points.size ());
00550 int nr_p = 0;
00551
00552 for (unsigned int i = 0; i < points_tgt.points.size (); i++)
00553 {
00554 if (points_tgt.points[i].x > min_b->x &&
00555 points_tgt.points[i].x < max_b->x &&
00556 points_tgt.points[i].y > min_b->y &&
00557 points_tgt.points[i].y < max_b->y &&
00558 points_tgt.points[i].z > min_b->z &&
00559 points_tgt.points[i].z < max_b->z)
00560 {
00561 object_indices[nr_p] = i;
00562 nr_p++;
00563 }
00564 }
00565 object_indices.resize (nr_p);
00566
00567
00568 sensor_msgs::PointCloud object_points;
00569 object_points.header = points_tgt.header;
00570 object_points.points.resize (object_indices.size ());
00571 for (unsigned int i = 0; i < object_indices.size (); i++)
00572 {
00573 object_points.points[i].x = points_tgt.points[object_indices.at (i)].x;
00574 object_points.points[i].y = points_tgt.points[object_indices.at (i)].y;
00575 object_points.points[i].z = points_tgt.points[object_indices.at (i)].z;
00576 }
00577
00578
00579
00580
00581
00582
00583
00584 sensor_msgs::PointCloud points_src;
00585 try
00586 {
00587 tf_.transformPointCloud (source_frame, object_points, points_src);
00588
00589 }
00590 catch (tf::ConnectivityException)
00591 {
00592 ROS_ERROR ("TF not running or wrong TF end_effector_frame specified!");
00593 return;
00594 }
00595
00596
00597
00598
00599 vector<Leaf> object_leaves;
00600 computeLeaves (&points_src, object_leaves, object_points);
00601
00602
00603 vector<Leaf> model_difference;
00604 set_difference (leaves.begin (), leaves.end (), object_leaves.begin (), object_leaves.end (),
00605 inserter (model_difference, model_difference.begin ()), compareLeaf);
00606 leaves = model_difference;
00607 }
00608
00609 double determineDecayingMapDuration() const {
00610
00611 ros::Time min_time = ros::TIME_MAX;
00612 ros::Time max_time = ros::TIME_MIN;
00613
00614 for( list<std::pair<vector<Leaf>, ros::Time> >::const_iterator dec_it = decaying_maps_.begin();
00615 dec_it != decaying_maps_.end();
00616 dec_it++) {
00617 if(dec_it->second < min_time) {
00618 min_time = dec_it->second;
00619 }
00620 if(dec_it->second > max_time) {
00621 max_time = dec_it->second;
00622 }
00623 }
00624 ros::Duration dur = max_time-min_time;
00625 return dur.toSec();
00626 }
00627
00628 void discardOutOfTimeWindowScans() {
00629 ros::Time max_time = ros::TIME_MIN;
00630
00631 for( list<std::pair<vector<Leaf>, ros::Time> >::const_iterator dec_cit = decaying_maps_.begin();
00632 dec_cit != decaying_maps_.end();
00633 dec_cit++) {
00634 if(dec_cit->second > max_time) {
00635 max_time = dec_cit->second;
00636 }
00637 }
00638
00639 ros::Time windowTime(max_time.toSec()-window_time_);
00640
00641 list<std::pair<vector<Leaf>, ros::Time> >::iterator dec_it = decaying_maps_.begin();
00642 while(dec_it != decaying_maps_.end()) {
00643 if(dec_it->second < windowTime) {
00644 dec_it = decaying_maps_.erase(dec_it);
00645 } else {
00646 dec_it++;
00647 }
00648 }
00649 }
00650
00651 void subsampleCloudPoints(const sensor_msgs::PointCloudConstPtr &msg, sensor_msgs::PointCloud& myMsg, unsigned int subsampleNum) {
00652 myMsg.points.clear();
00653 myMsg.header = (*msg).header;
00654
00655 sensor_msgs::PointCloud points_tgt;
00656
00657
00658 try
00659 {
00660 tf_.transformPointCloud (shared_frame_, (*msg), points_tgt);
00661 }
00662 catch (tf::ConnectivityException)
00663 {
00664 ROS_ERROR ("TF not running or wrong TF end_effector_frame specified!");
00665 return;
00666 }
00667 catch (tf::ExtrapolationException)
00668 {
00669 ROS_ERROR("Extrapolation exception.");
00670 }
00671 myMsg.header.frame_id=shared_frame_;
00672
00673 for(unsigned int i = 0; i < points_tgt.points.size(); i += subsampleNum) {
00674 myMsg.points.push_back(points_tgt.points[i]);
00675
00676
00677
00678 }
00679 }
00680
00681
00682
00683 void cloudCb0 (const sensor_msgs::PointCloudConstPtr &msg)
00684 {
00685
00686 if(cloud_counter_[0]++ % cloud_source_[0].frame_subsample_ == 0)
00687 {
00688 cloudCb(msg, cloud_source_[0]);
00689 }
00690 }
00691
00692 void cloudCb1 (const sensor_msgs::PointCloudConstPtr &msg)
00693 {
00694
00695 if(cloud_counter_[1]++ % cloud_source_[1].frame_subsample_ == 0)
00696 {
00697 cloudCb(msg, cloud_source_[1]);
00698 }
00699 }
00700
00701 void cloudCb2 (const sensor_msgs::PointCloudConstPtr &msg)
00702 {
00703
00704 if(cloud_counter_[2]++ % cloud_source_[2].frame_subsample_ == 0)
00705 {
00706 cloudCb(msg, cloud_source_[2]);
00707 }
00708 }
00709
00711
00712 void cloudCb (const sensor_msgs::PointCloudConstPtr &msg, const CloudProcSettings& settings)
00713 {
00714 ros::Time t1, t2, t3;
00715 t1 = ros::Time::now ();
00716 ROS_DEBUG ("Received %u data points.",(*msg).points.size ());
00717 subsampleCloudPoints(msg, cloud_,settings.point_subsample_);
00718 ROS_DEBUG ("After subsampling we have %u data points.",cloud_.points.size ());
00719
00720
00721
00722
00723
00724
00725
00726
00727 double time_spent;
00728
00729
00730 geometry_msgs::Point32 ee_center;
00731
00732
00733
00734
00735
00736 final_collision_map_.header = cloud_.header;
00737
00738
00739 if (acquire_static_map_)
00740 {
00741
00742 if (cloud_.header.stamp < acquire_static_map_time_)
00743 return;
00744
00745
00746
00747
00748
00749
00750 sensor_msgs::PointCloud centers;
00751 computeLeaves (&cloud_, static_leaves_, centers);
00752
00753
00754 static_map_lock_.lock ();
00755 acquire_static_map_ = false;
00756 static_map_lock_.unlock ();
00757
00758
00759 t2 = ros::Time::now ();
00760
00761 time_spent = (t2 - t1).toSec ();
00762 ROS_DEBUG ("Static collision map computed in %g seconds. Number of boxes: %u.", time_spent, (unsigned int)static_leaves_.size ());
00763
00764 }
00765 else
00766 {
00767 vector<Leaf> model_reunion;
00768
00769
00770
00771
00772
00773 sensor_msgs::PointCloud centers;
00774 m_lock_.lock ();
00775 computeLeaves (&cloud_, cur_leaves_, centers);
00776 m_lock_.unlock ();
00777
00778
00779 object_subtract_lock_.lock ();
00780
00781 pruneLeaves (cur_leaves_, ¢ers, &ee_center, cloud_.header.frame_id, end_effector_frame_l_, &min_object_b_, &max_object_b_);
00782 object_subtract_lock_.unlock ();
00783
00784 std::pair<vector<Leaf>, ros::Time> cur_leaves_with_time(cur_leaves_,(*msg).header.stamp);
00785
00786
00787 decaying_maps_.push_back (cur_leaves_with_time);
00788
00789
00790 ROS_DEBUG("Duration before %g",determineDecayingMapDuration());
00791
00792 final_leaves_.clear ();
00793 list<std::pair<vector<Leaf>, ros::Time> >::const_iterator it = decaying_maps_.begin ();
00794 for ( ; it != decaying_maps_.end (); ++it)
00795 {
00796
00797 set_union (final_leaves_.begin (), final_leaves_.end (), (*it).first.begin (), (*it).first.end (),
00798 inserter (model_reunion, model_reunion.begin ()), compareLeaf);
00799 final_leaves_ = model_reunion;
00800 model_reunion.clear ();
00801 }
00802 discardOutOfTimeWindowScans();
00803 ROS_DEBUG("Duration after %g",determineDecayingMapDuration());
00804
00805
00806
00807
00808
00809 set_union (final_leaves_.begin (), final_leaves_.end (), static_leaves_.begin (), static_leaves_.end (),
00810 inserter (model_reunion, model_reunion.begin ()), compareLeaf);
00811
00812 computeCollisionMapFromLeaves (&model_reunion, final_collision_map_);
00813
00814
00815 t2 = ros::Time::now ();
00816
00817 time_spent = (t2 - t1).toSec ();
00818 ROS_DEBUG ("Collision map with %u boxes computed in %g seconds. Total maps in the queue %d.",
00819 (unsigned int)final_collision_map_.boxes.size (), time_spent, (int)decaying_maps_.size ());
00820
00821 collision_map_publisher_.publish(final_collision_map_);
00822 }
00823 }
00824
00826
00827 bool getStaticMap (RecordStaticMapTrigger::Request &req, RecordStaticMapTrigger::Response &resp)
00828 {
00829 static_map_lock_.lock ();
00830 acquire_static_map_ = true;
00831 acquire_static_map_time_ = req.map_time;
00832 static_map_lock_.unlock ();
00833
00834 ROS_INFO ("Got a request to compute a new static map at %f.", acquire_static_map_time_.toSec ());
00835
00836
00837 ros::Duration tictoc (0, 10000000);
00838 while (acquire_static_map_)
00839 {
00840 tictoc.sleep ();
00841 }
00842
00843 resp.status = 0;
00844
00845 return (true);
00846 }
00847
00849
00850 bool subtractObject (SubtractObjectFromCollisionMap::Request &req, SubtractObjectFromCollisionMap::Response &resp)
00851 {
00852 ROS_INFO ("Got request to subtract object.");
00853 geometry_msgs::Point32 center;
00854 center.x = (req.object.min_bound.x + req.object.max_bound.x) / 2.0;
00855 center.y = (req.object.min_bound.y + req.object.max_bound.y) / 2.0;
00856 center.z = (req.object.min_bound.z + req.object.max_bound.z) / 2.0;
00857
00858 object_subtract_lock_.lock ();
00859
00860 min_object_b_.x = req.object.min_bound.x - center.x;
00861 min_object_b_.y = req.object.min_bound.y - center.y;
00862 min_object_b_.z = req.object.min_bound.z - center.z;
00863
00864 max_object_b_.x = req.object.max_bound.x - center.x;
00865 max_object_b_.y = req.object.max_bound.y - center.y;
00866 max_object_b_.z = req.object.max_bound.z - center.z;
00867
00868 subtract_object_ = true;
00869
00870 object_subtract_lock_.unlock ();
00871
00872 resp.status = 0;
00873
00874 return (true);
00875 }
00876 };
00877
00878
00879 int main (int argc, char** argv)
00880 {
00881 ros::init (argc, argv, "collision_map_buffer");
00882 ros::NodeHandle ros_node("");
00883 CollisionMapperBuffer p (ros_node);
00884
00885
00886
00887
00888
00889
00890
00891 ros::Duration tictoc (10.0, 0);
00892 tictoc.sleep ();
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903 ros::spin ();
00904
00905 return (0);
00906 }
00907
00908