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
00031
00032
00033 #include <ros/ros.h>
00034 #include <std_msgs/String.h>
00035
00036 #include <sensor_msgs/CameraInfo.h>
00037 #include <stereo_msgs/DisparityImage.h>
00038
00039 #include <fast_plane_detection/Plane.h>
00040
00041 #include <visualization_msgs/Marker.h>
00042
00043 #include <tf/transform_listener.h>
00044
00045 #include "fast_plane_detector/plane_detection.h"
00046 #include "fast_plane_detector/plane_transform.h"
00047
00048 #include "fast_plane_detector/timercpu.h"
00049 #include "fast_plane_detector/utils.h"
00050
00051 #include <fast_plane_detection/SetPosition.h>
00052 #include <fast_plane_detection/SlavePoint.h>
00053
00054
00055 namespace fast_plane_detection {
00056
00057 class FastRegionPlaneDetector {
00058
00059 private:
00060
00061 bool maskDisparityImage(
00062 const stereo_msgs::DisparityImage::ConstPtr& disparity,
00063 const sensor_msgs::CameraInfo::ConstPtr& camera_info,
00064 const stereo_msgs::DisparityImage::Ptr &masked_disparity);
00066 ros::NodeHandle root_nh_;
00068 ros::NodeHandle priv_nh_;
00069
00071 ros::Subscriber camera_info_sub_;
00072 std::string camera_info_topic_;
00073
00075 ros::Subscriber disparity_image_sub_;
00076 std::string disparity_image_topic_;
00077
00079 int buffer_size_;
00080
00082 stereo_msgs::DisparityImage::ConstPtr disparity_image_;
00083
00085 stereo_msgs::DisparityImage disparity_masked_;
00086 stereo_msgs::DisparityImage::Ptr disparity_masked_ptr;
00087
00089 sensor_msgs::CameraInfo::ConstPtr camera_info_;
00090
00092 ros::Publisher plane_marker_pub_;
00093
00095 ros::Publisher pos_marker_pub_;
00096
00098 ros::Publisher plane_msg_pub_;
00099
00101 ros::Publisher disparity_image_pub_;
00102
00103 tf::TransformListener listener_;
00104
00105 tf::TransformListener listener_check_;
00106 tf::StampedTransform transform_check_;
00107
00108 tf::TransformListener listener_check2_;
00109 tf::StampedTransform transform_check2_;
00110
00112 PlaneDetection* plane_detect_;
00113
00115 bool find_table_;
00116
00118 PlaneTransform* plane_transform_;
00119
00121 double up_direction_;
00122
00124 int inlier_threshold_;
00125 int number_inliers_;
00126 double percentage_inliers_;
00127 float mean_error_;
00128
00129
00130 ros::ServiceServer srv_position_;
00131 double X_;
00132 double Y_;
00133 double Z_;
00134 bool manual_;
00135 bool in_contact_;
00136
00137 ros::Subscriber sub_position_;
00138
00140 geometry_msgs::Vector3Stamped point_;
00141 int region_width_;
00142 int region_height_;
00143
00144 int marker_id_;
00145 int marker2_id_;
00146
00147
00148 std::string source_frame_;
00149 std::string camera_frame_;
00150
00151
00152 std_msgs::ColorRGBA green_;
00153 std_msgs::ColorRGBA red_;
00154
00155 public:
00156
00157 FastRegionPlaneDetector(int buffer_size);
00158 ~FastRegionPlaneDetector();
00159
00160
00161
00163 void planeCallback(
00164 const stereo_msgs::DisparityImage::ConstPtr& disparity_image);
00165
00166
00167 bool setPosition(fast_plane_detection::SetPosition::Request& req,
00168 fast_plane_detection::SetPosition::Response& resp);
00169
00170
00171 void Pr2Callback(const fast_plane_detection::SlavePoint msg_pose);
00172
00173
00174
00176 Plane plane_;
00177
00178 };
00179
00180 FastRegionPlaneDetector::FastRegionPlaneDetector(int buffer_size)
00181 : root_nh_("")
00182 , priv_nh_("~")
00183 , X_(0)
00184 , Y_(0)
00185 , Z_(1)
00186 , number_inliers_(0)
00187 , percentage_inliers_(0)
00188 , buffer_size_(buffer_size)
00189 , region_width_(10)
00190 , region_height_(40)
00191 , manual_(false)
00192 , marker_id_(354345)
00193 , marker2_id_(154345)
00194 , source_frame_("/torso_lift_link")
00195 , camera_frame_("/narrow_stereo_optical_frame")
00196 {
00197
00198 green_.r = 0, green_.g = 0.8, green_.b = 0, green_.a = 1;
00199 red_.r = 1, red_.g = 0, red_.b = 0, red_.a = 1;
00200
00201
00202 priv_nh_.param<std::string> ("camera_info_topic", camera_info_topic_,
00203 "/narrow_stereo_textured/left/camera_info");
00204 priv_nh_.param<std::string> ("disparity_image_topic",
00205 disparity_image_topic_, "/narrow_stereo_textured/disparity");
00206 priv_nh_.param<bool> ("find_table", find_table_, false);
00207 priv_nh_.param<double> ("up_direction", up_direction_, -1.0f);
00208 priv_nh_.param<int> ("inlier_threshold", inlier_threshold_, 300);
00209
00210
00211
00212 while (!camera_info_ || !disparity_image_) {
00213 if (!camera_info_) {
00214 ROS_INFO_STREAM(" Waiting for message on topic "
00215 << camera_info_topic_);
00216 camera_info_ = ros::topic::waitForMessage<sensor_msgs::CameraInfo>(
00217 camera_info_topic_, root_nh_, ros::Duration(0.5));
00218 }
00219
00220 if (!disparity_image_) {
00221 ROS_INFO_STREAM(" Waiting for message on topic "
00222 << disparity_image_topic_);
00223 disparity_image_ = ros::topic::waitForMessage<
00224 stereo_msgs::DisparityImage>(disparity_image_topic_,
00225 root_nh_, ros::Duration(1.0));
00226 }
00227 }
00228
00229
00230 disparity_masked_.header = disparity_image_->header;
00231 disparity_masked_.image.header = disparity_image_->image.header;
00232 disparity_masked_.image.height = disparity_image_->image.height;
00233 disparity_masked_.image.width = disparity_image_->image.width;
00234 disparity_masked_.image.encoding = disparity_image_->image.encoding;
00235 disparity_masked_.image.is_bigendian = disparity_image_->image.is_bigendian;
00236
00237
00238 disparity_masked_.image.step = disparity_image_->image.step;
00239 size_t size = disparity_masked_.image.step * disparity_masked_.image.height;
00240 disparity_masked_.image.data.resize(size, 0);
00241
00242 disparity_masked_.f = disparity_image_->f;
00243 disparity_masked_.T = disparity_image_->T;
00244 disparity_masked_.min_disparity = disparity_image_->min_disparity;
00245 disparity_masked_.max_disparity = disparity_image_->max_disparity;
00246 disparity_masked_.delta_d = disparity_image_->delta_d;
00247
00248
00249
00250
00251
00252
00253 float drange = disparity_image_->max_disparity
00254 - disparity_image_->min_disparity;
00255 int w = disparity_image_->image.width;
00256 int h = disparity_image_->image.height;
00257
00258 plane_detect_ = new PlaneDetection((int) drange, w, h, find_table_,
00259 disparity_image_->image.header);
00260
00261 plane_transform_ = new PlaneTransform(*camera_info_, disparity_image_->T,
00262 up_direction_);
00263
00264
00265 std::string topic_disp = root_nh_.resolveName("disparity_in");
00266 disparity_image_sub_ = root_nh_.subscribe(topic_disp, buffer_size_,
00267 &FastRegionPlaneDetector::planeCallback, this);
00268
00269
00270 plane_marker_pub_ = root_nh_.advertise<visualization_msgs::Marker> (
00271 "region_plane_markers", 1);
00272
00273
00274 pos_marker_pub_ = root_nh_.advertise<visualization_msgs::Marker> (
00275 "slave_pos_marker", 1);
00276
00277
00278 plane_msg_pub_ = root_nh_.advertise<Plane> ("region_plane_msg", 1);
00279
00280
00281 std::string topic = root_nh_.resolveName(
00282 "/plane_detection/masked_disparity");
00283 disparity_image_pub_ = root_nh_.advertise<stereo_msgs::DisparityImage> (
00284 topic, 1);
00285
00286
00287 srv_position_ = root_nh_.advertiseService("set_position", &FastRegionPlaneDetector::setPosition, this);
00288
00289
00290 sub_position_ = root_nh_.subscribe("/bilateral_teleop/slave_point", 1, &FastRegionPlaneDetector::Pr2Callback,this);
00291
00292 }
00293
00294 FastRegionPlaneDetector::~FastRegionPlaneDetector() {
00295 delete plane_detect_;
00296 delete plane_transform_;
00297 }
00298
00299 void FastRegionPlaneDetector::planeCallback(
00300 const stereo_msgs::DisparityImage::ConstPtr& disparity_image) {
00301 ROS_INFO("-----------------");
00302 TimerCPU timer(2800);
00303
00304 stereo_msgs::DisparityImage::Ptr disparity_masked_ptr = boost::make_shared<
00305 stereo_msgs::DisparityImage>(disparity_masked_);
00306
00307
00308 if (!maskDisparityImage(disparity_image, camera_info_, disparity_masked_ptr)) {
00309 ROS_WARN("Could not project input point to disparity image");
00310 plane_.result = Plane::OTHER_ERROR;
00311 return;
00312 }
00313
00314 disparity_image_pub_.publish(*disparity_masked_ptr);
00315 plane_detect_->Update(disparity_masked_ptr);
00316
00317 float alpha, beta, d;
00318 int min_x, max_x, min_y, max_y;
00319 plane_detect_->GetPlaneParameters(alpha, beta, d,
00320 min_x, max_x, min_y,
00321 max_y);
00322
00323 sensor_msgs::Image labels;
00324 plane_detect_->GetLabels(labels);
00325
00326
00327
00328 int sum = 0;
00329 for (unsigned int i = 0; i < labels.height; ++i)
00330 for (unsigned int j = 0; j < labels.width; ++j) {
00331 int adr = i * labels.width + j;
00332 sum += (labels.data[adr]) / 255;
00333 }
00334 number_inliers_ = sum;
00335
00336
00337
00338
00339 plane_detect_->GetMeanSquaredError(mean_error_);
00340
00341
00342 inlier_threshold_ = (region_width_ * region_height_) / 3;
00343 percentage_inliers_ =
00344 100*number_inliers_/(region_width_ * region_height_);
00345
00346 plane_transform_->setParameters(alpha, beta, d,
00347 min_x, max_x, min_y, max_y,
00348 disparity_image->header);
00349
00350 if (!plane_transform_->getPlane(plane_)) {
00351 ROS_WARN("No Plane found");
00352 plane_.result = Plane::NO_PLANE;
00353 plane_msg_pub_.publish(plane_);
00354 return;
00355 } else {
00356
00357
00358 try {
00359 listener_check2_.lookupTransform(source_frame_,
00360 camera_frame_,
00361 ros::Time(0),
00362 transform_check2_);
00363 } catch (tf::TransformException ex) {
00364 ROS_ERROR("%s", ex.what());
00365 }
00366
00367 tf::Vector3 point1(plane_.pose.pose.position.x,
00368 plane_.pose.pose.position.y,
00369 plane_.pose.pose.position.z);
00370 point1 = transform_check2_.getBasis() * point1 +
00371 transform_check2_.getOrigin();
00372 geometry_msgs::PointStamped plane_point;
00373 plane_point.header.frame_id = "torso_lift_link";
00374 plane_point.header.stamp = ros::Time::now();
00375 plane_point.point.x = point1.x();
00376 plane_point.point.y = point1.y();
00377 plane_point.point.z = point1.z();
00378 plane_.plane_point = plane_point;
00379
00380 tf::Vector3 point2(plane_.normal.vector.x,
00381 plane_.normal.vector.y,
00382 plane_.normal.vector.z);
00383 point2 = transform_check2_.getBasis() * point2;
00384 ROS_INFO("Normal of plane: %f %f %f",
00385 plane_.normal.vector.x, plane_.normal.vector.y,
00386 plane_.normal.vector.z);
00387 geometry_msgs::Vector3Stamped plane_normal;
00388 plane_normal.header.frame_id = "torso_lift_link";
00389 plane_normal.header.stamp = ros::Time::now();
00390 plane_normal.vector.x = point2.x();
00391 plane_normal.vector.y = point2.y();
00392 plane_normal.vector.z = point2.z();
00393 plane_.normal = plane_normal;
00394
00395 geometry_msgs::PointStamped slave_point;
00396 slave_point.header.frame_id = "torso_lift_link";
00397 slave_point.header.stamp = ros::Time::now();
00398 slave_point.point.x = X_;
00399 slave_point.point.y = Y_;
00400 slave_point.point.z = Z_;
00401 plane_.slave_point = slave_point;
00402
00403 if(number_inliers_<inlier_threshold_){
00404 ROS_WARN("Percentage of inliers is only %f", percentage_inliers_);
00405 plane_.result = Plane::FEW_INLIERS;
00406 }
00407 else{
00408 ROS_INFO("Percentage of inliers is %f", percentage_inliers_);
00409 plane_.result = Plane::SUCCESS;
00410 }
00411 ROS_INFO("Mean squared error is %f", mean_error_);
00412 plane_.percentage_inliers = percentage_inliers_;
00413 plane_.error = mean_error_;
00414 plane_msg_pub_.publish(plane_);
00415
00416 visualization_msgs::Marker delete_marker;
00417 delete_marker.header.stamp = ros::Time::now();
00418 delete_marker.header.frame_id = disparity_image->header.frame_id;
00419 delete_marker.id = marker_id_;
00420 delete_marker.action = visualization_msgs::Marker::DELETE;
00421 delete_marker.ns = "tabletop_node";
00422 plane_marker_pub_.publish(delete_marker);
00423
00424 visualization_msgs::Marker planeMarker
00425 = getPlaneMarker(
00426 plane_.top_left, plane_.top_right,
00427 plane_.bottom_left,
00428 plane_.bottom_right);
00429 planeMarker.header = disparity_image->header;
00430 planeMarker.pose = plane_.pose.pose;
00431 planeMarker.ns = "tabletop_node";
00432 planeMarker.id = marker_id_;
00433 if(in_contact_)
00434 planeMarker.color = red_;
00435 else
00436 planeMarker.color = green_;
00437 planeMarker.scale.x = 0.002;
00438 plane_marker_pub_.publish(planeMarker);
00439
00440 }
00441
00442
00443
00444
00445 }
00446
00447 bool FastRegionPlaneDetector::maskDisparityImage(
00448 const stereo_msgs::DisparityImage::ConstPtr& disparity,
00449 const sensor_msgs::CameraInfo::ConstPtr& camera_info,
00450 const stereo_msgs::DisparityImage::Ptr &masked_disparity)
00451
00452 {
00453
00454 try {
00455 listener_check_.lookupTransform(camera_frame_, source_frame_, ros::Time(0), transform_check_);
00456 } catch (tf::TransformException ex) {
00457 ROS_ERROR("%s", ex.what());
00458 }
00459
00460 tf::Vector3 point(X_,Y_,Z_);
00461
00462 point = transform_check_ * point;
00463
00465 visualization_msgs::Marker delete_posMarker;
00466 delete_posMarker.header.stamp = ros::Time::now();
00467 delete_posMarker.header.frame_id = camera_frame_;
00468 delete_posMarker.id = marker2_id_;
00469 delete_posMarker.action = visualization_msgs::Marker::DELETE;
00470 delete_posMarker.ns = "tabletop_node";
00471 pos_marker_pub_.publish(delete_posMarker);
00472
00473 visualization_msgs::Marker posMarker;
00474 posMarker.header.frame_id = camera_frame_;
00475 posMarker.header.stamp = ros::Time::now();
00476 posMarker.ns = "tabletop_node";
00477 posMarker.id = marker2_id_;
00478 posMarker.type = visualization_msgs::Marker::SPHERE;
00479
00480
00481 posMarker.pose.position.x = point.x();
00482 posMarker.pose.position.y = point.y();
00483 posMarker.pose.position.z = point.z();
00484
00485 posMarker.scale.x = 0.01;
00486 posMarker.scale.y = 0.01;
00487 posMarker.scale.z = 0.01;
00488
00489 if(in_contact_)
00490 posMarker.color = red_;
00491 else
00492 posMarker.color = green_;
00493 pos_marker_pub_.publish(posMarker);
00494
00495
00496
00497 float f = disparity->f;
00498 float T = disparity->T;
00499
00500 float fx = camera_info->P[0 * 4 + 0];
00501 float fy = camera_info->P[1 * 4 + 1];
00502 float cx = camera_info->P[0 * 4 + 2];
00503 float cy = camera_info->P[1 * 4 + 2];
00504
00505
00506 int u = point.x() / point.z() * fx + cx;
00507 int v = point.y() / point.z() * fy + cy;
00508
00509 int d = (f * T) / point.z();
00510
00511 ROS_INFO("3D point: (%f, %f, %f) -> Pixel position (%d, %d) ",X_, Y_,Z_, u, v);
00512
00513 float *dimd_in = (float*) &(disparity->image.data[0]);
00514 float *dimd_out = (float*) &(masked_disparity->image.data[0]);
00515
00516 for (int y = 0; y < (int) masked_disparity->image.height; y++) {
00517 for (int x = 0; x < (int) masked_disparity->image.width; x++) {
00518 int adr = y * masked_disparity->image.width + x;
00519 if (x > u - region_width_ / 2 && x < u + region_width_ / 2 && y > v
00520 - region_height_ / 2 && y < v + region_height_ / 2) {
00521 dimd_out[adr] = dimd_in[adr];
00522 } else
00523 dimd_out[adr] = -1.0f;
00524 }
00525 }
00526
00527 return true;
00528 }
00529
00531 bool FastRegionPlaneDetector::setPosition(
00532 fast_plane_detection::SetPosition::Request& req,
00533 fast_plane_detection::SetPosition::Response& resp) {
00534 if (req.transform){
00535 X_ = req.x;
00536 Y_ = req.y;
00537 Z_ = req.z;
00538 }
00539 region_width_ = req.width;
00540 region_height_ = req.height;
00541 manual_ = req.transform;
00542 ROS_INFO("Fast Plane Detector: Position changed");
00543
00544 resp.x = X_;
00545 resp.y = Y_;
00546 resp.z = Z_;
00547 resp.transform = manual_;
00548 resp.width = region_width_;
00549 resp.height = region_height_;
00550 return true;
00551 }
00552
00554 void FastRegionPlaneDetector::Pr2Callback(const fast_plane_detection::SlavePoint msg_pose)
00555 {
00556 if (!manual_){
00557 X_ = msg_pose.end_effector.x;
00558 Y_ = msg_pose.end_effector.y;
00559 Z_ = msg_pose.end_effector.z;
00560 }
00561 in_contact_ = msg_pose.contact;
00562
00563
00564 }
00565
00566 }
00567
00568 int main(int argc, char **argv) {
00569 ros::init(argc, argv, "fast_plane_detection_node");
00570
00572 int buffer_size_ = 1;
00573 fast_plane_detection::FastRegionPlaneDetector node_(buffer_size_);
00574 ros::spin();
00575
00576 return 0;
00577 }