Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <robot_calibration/capture/plane_finder.h>
00021 #include <sensor_msgs/point_cloud2_iterator.h>
00022 #include <math.h>
00023 #include <tf2_ros/transform_listener.h>
00024 #include <tf2_geometry_msgs/tf2_geometry_msgs.h>
00025
00026 namespace robot_calibration
00027 {
00028
00029 const unsigned X = 0;
00030 const unsigned Y = 1;
00031 const unsigned Z = 2;
00032
00033 PlaneFinder::PlaneFinder(ros::NodeHandle & nh) :
00034 FeatureFinder(nh),
00035 waiting_(false)
00036 {
00037 std::string topic_name;
00038 nh.param<std::string>("topic", topic_name, "/points");
00039 subscriber_ = nh.subscribe(topic_name,
00040 1,
00041 &PlaneFinder::cameraCallback,
00042 this);
00043
00044 nh.param<std::string>("camera_sensor_name", camera_sensor_name_, "camera");
00045 nh.param<double>("points_max", points_max_, 60);
00046 nh.param<double>("min_x", min_x_, -2.0);
00047 nh.param<double>("max_x", max_x_, 2.0);
00048 nh.param<double>("min_y", min_y_, -2.0);
00049 nh.param<double>("max_y", max_y_, 2.0);
00050 nh.param<double>("min_z", min_z_, 0.0);
00051 nh.param<double>("max_z", max_z_, 2.0);
00052 nh.param<std::string>("transform_frame", transform_frame_, "base_link");
00053
00054 publisher_ = nh.advertise<sensor_msgs::PointCloud2>("plane_points", 10);
00055 if (!depth_camera_manager_.init(nh))
00056 {
00057
00058 throw;
00059 }
00060
00061 }
00062
00063 void PlaneFinder::cameraCallback(const sensor_msgs::PointCloud2& cloud)
00064 {
00065 if (waiting_)
00066 {
00067 cloud_ = cloud;
00068 waiting_ = false;
00069 }
00070 }
00071
00072 bool PlaneFinder::waitForCloud()
00073 {
00074 ros::Duration(1/10.0).sleep();
00075
00076 waiting_ = true;
00077 int count = 250;
00078 while (--count)
00079 {
00080 if (!waiting_)
00081 {
00082
00083 return true;
00084 }
00085 ros::Duration(0.01).sleep();
00086 ros::spinOnce();
00087 }
00088 ROS_ERROR("Failed to get cloud");
00089 return !waiting_;
00090 }
00091
00092 bool PlaneFinder::find(robot_calibration_msgs::CalibrationData * msg)
00093 {
00094 geometry_msgs::PointStamped rgbd;
00095 geometry_msgs::PointStamped world;
00096
00097 if (!waitForCloud())
00098 {
00099 ROS_ERROR("No point cloud data");
00100 return false;
00101 }
00102
00103
00104 size_t num_points = cloud_.width * cloud_.height;
00105 sensor_msgs::PointCloud2ConstIterator<float> xyz(cloud_, "x");
00106 sensor_msgs::PointCloud2Iterator<float> iter(cloud_, "x");
00107
00108 tf2_ros::Buffer tfBuffer;
00109 tf2_ros::TransformListener tfListener(tfBuffer);
00110 geometry_msgs::TransformStamped transformStamped;
00111 try
00112 {
00113 transformStamped = tfBuffer.lookupTransform("base_link", cloud_.header.frame_id,
00114 ros::Time(0), ros::Duration(10.0));
00115 }
00116 catch (tf2::TransformException ex)
00117 {
00118 ROS_ERROR("%s",ex.what());
00119 ros::Duration(1.0).sleep();
00120 }
00121
00122 size_t j = 0;
00123 for (size_t i = 0; i < num_points; i++)
00124 {
00125 geometry_msgs::PointStamped p;
00126 p.point.x = (xyz + i)[X];
00127 p.point.y = (xyz + i)[Y];
00128 p.point.z = (xyz + i)[Z];
00129 p.header.stamp = ros::Time(0);
00130 p.header.frame_id = cloud_.header.frame_id;
00131
00132 geometry_msgs::PointStamped p_out;
00133 try
00134 {
00135 tfBuffer.transform(p, p_out, transform_frame_);
00136 }
00137 catch (tf2::TransformException ex)
00138 {
00139 ROS_ERROR("%s", ex.what());
00140 ros::Duration(1.0).sleep();
00141 }
00142
00143
00144 if (!std::isfinite(p.point.x) || !std::isfinite(p.point.y) || !std::isfinite(p.point.z))
00145 continue;
00146
00147
00148
00149 if (p.point.z == 0)
00150 continue;
00151
00152
00153 if (p_out.point.x < min_x_ || p_out.point.x > max_x_ || p_out.point.y < min_y_ || p_out.point.y > max_y_ ||
00154 p_out.point.z < min_z_ || p_out.point.z > max_z_)
00155 {
00156 continue;
00157 }
00158
00159 (iter + j)[X] = (xyz + i)[X];
00160 (iter + j)[Y] = (xyz + i)[Y];
00161 (iter + j)[Z] = (xyz + i)[Z];
00162 j++;
00163 }
00164
00165 cloud_.height = 1;
00166 cloud_.width = j;
00167 cloud_.data.resize(cloud_.width * cloud_.point_step);
00168
00169 size_t points_total = std::min(static_cast<size_t>(points_max_), j);
00170 std::vector<cv::Point2f> points;
00171 points.resize(points_total);
00172
00173
00174 sensor_msgs::PointCloud2 cloud;
00175 cloud.width = 0;
00176 cloud.height = 0;
00177 cloud.header.stamp = ros::Time::now();
00178 cloud.header.frame_id = cloud_.header.frame_id;
00179 sensor_msgs::PointCloud2Modifier cloud_mod(cloud);
00180 cloud_mod.setPointCloud2FieldsByString(1, "xyz");
00181 cloud_mod.resize(points_total);
00182 sensor_msgs::PointCloud2Iterator<float> iter_cloud(cloud, "x");
00183
00184
00185 int idx_cam = msg->observations.size() + 0;
00186 msg->observations.resize(msg->observations.size() + 1);
00187 msg->observations[idx_cam].sensor_name = camera_sensor_name_;
00188 msg->observations[idx_cam].features.resize(points_total);
00189
00190 size_t step = cloud_.width/(points_total);
00191 size_t k = 0;
00192
00193 for (size_t i = step; i < cloud_.width && k < points_total; i += step)
00194 {
00195 points[k].x = i;
00196 k++;
00197 }
00198
00199 for (size_t i = 0; i < points.size(); i++)
00200 {
00201
00202 int index = static_cast<int>(points[i].x);
00203 rgbd.point.x = (xyz + index)[X];
00204 rgbd.point.y = (xyz + index)[Y];
00205 rgbd.point.z = (xyz + index)[Z];
00206 msg->observations[idx_cam].features[i] = rgbd;
00207 msg->observations[idx_cam].ext_camera_info = depth_camera_manager_.getDepthCameraInfo();
00208
00209 iter_cloud[0] = rgbd.point.x;
00210 iter_cloud[1] = rgbd.point.y;
00211 iter_cloud[2] = rgbd.point.z;
00212 ++iter_cloud;
00213 }
00214
00215
00216 msg->observations[idx_cam].cloud = cloud_;
00217 publisher_.publish(cloud);
00218 return true;
00219 }
00220 }