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/checkerboard_finder.h>
00021 #include <sensor_msgs/point_cloud2_iterator.h>
00022
00023 namespace robot_calibration
00024 {
00025
00026
00027 const unsigned X = 0;
00028 const unsigned Y = 1;
00029 const unsigned Z = 2;
00030
00031 CheckerboardFinder::CheckerboardFinder(ros::NodeHandle & nh) :
00032 FeatureFinder(nh),
00033 waiting_(false)
00034 {
00035
00036 std::string topic_name;
00037 nh.param<std::string>("topic", topic_name, "/points");
00038 subscriber_ = nh.subscribe(topic_name,
00039 1,
00040 &CheckerboardFinder::cameraCallback,
00041 this);
00042
00043
00044 nh.param<int>("points_x", points_x_, 5);
00045 nh.param<int>("points_y", points_y_, 4);
00046 nh.param<double>("size", square_size_, 0.0245);
00047
00048
00049 nh.param<bool>("debug", output_debug_, false);
00050
00051
00052 nh.param<std::string>("camera_sensor_name", camera_sensor_name_, "camera");
00053 nh.param<std::string>("chain_sensor_name", chain_sensor_name_, "arm");
00054
00055
00056 publisher_ = nh.advertise<sensor_msgs::PointCloud2>("checkerboard_points", 10);
00057
00058
00059 if (!depth_camera_manager_.init(nh))
00060 {
00061
00062 throw;
00063 }
00064 }
00065
00066 void CheckerboardFinder::cameraCallback(const sensor_msgs::PointCloud2& cloud)
00067 {
00068 if (waiting_)
00069 {
00070 cloud_ = cloud;
00071 waiting_ = false;
00072 }
00073 }
00074
00075
00076 bool CheckerboardFinder::waitForCloud()
00077 {
00078
00079 ros::Duration(1/10.0).sleep();
00080
00081 waiting_ = true;
00082 int count = 250;
00083 while (--count)
00084 {
00085 if (!waiting_)
00086 {
00087
00088 return true;
00089 }
00090 ros::Duration(0.01).sleep();
00091 ros::spinOnce();
00092 }
00093 ROS_ERROR("Failed to get cloud");
00094 return !waiting_;
00095 }
00096
00097 bool CheckerboardFinder::find(robot_calibration_msgs::CalibrationData * msg)
00098 {
00099
00100 for (int i = 0; i < 50; ++i)
00101 {
00102
00103 robot_calibration_msgs::CalibrationData tmp_msg(*msg);
00104 if (findInternal(&tmp_msg))
00105 {
00106 *msg = tmp_msg;
00107 return true;
00108 }
00109 }
00110 return false;
00111 }
00112
00113 bool CheckerboardFinder::findInternal(robot_calibration_msgs::CalibrationData * msg)
00114 {
00115 geometry_msgs::PointStamped rgbd;
00116 geometry_msgs::PointStamped world;
00117
00118
00119 if (!waitForCloud())
00120 {
00121 ROS_ERROR("No point cloud data");
00122 return false;
00123 }
00124
00125
00126 sensor_msgs::ImagePtr image_msg(new sensor_msgs::Image);
00127 sensor_msgs::PointCloud2ConstIterator<uint8_t> rgb(cloud_, "rgb");
00128 image_msg->encoding = "bgr8";
00129 image_msg->height = cloud_.height;
00130 image_msg->width = cloud_.width;
00131 image_msg->step = image_msg->width * sizeof (uint8_t) * 3;
00132 image_msg->data.resize(image_msg->step * image_msg->height);
00133 for (size_t y = 0; y < cloud_.height; y++)
00134 {
00135 for (size_t x = 0; x < cloud_.width; x++)
00136 {
00137 uint8_t* pixel = &(image_msg->data[y * image_msg->step + x * 3]);
00138 pixel[0] = rgb[0];
00139 pixel[1] = rgb[1];
00140 pixel[2] = rgb[2];
00141 ++rgb;
00142 }
00143 }
00144
00145
00146 cv_bridge::CvImagePtr bridge;
00147 try
00148 {
00149 bridge = cv_bridge::toCvCopy(image_msg, "mono8");
00150 }
00151 catch(cv_bridge::Exception& e)
00152 {
00153 ROS_ERROR("Conversion failed");
00154 return false;
00155 }
00156
00157
00158 std::vector<cv::Point2f> points;
00159 points.resize(points_x_ * points_y_);
00160 cv::Size checkerboard_size(points_x_, points_y_);
00161 int found = cv::findChessboardCorners(bridge->image, checkerboard_size,
00162 points, CV_CALIB_CB_ADAPTIVE_THRESH);
00163
00164 if (found)
00165 {
00166 ROS_INFO("Found the checkboard");
00167
00168
00169 sensor_msgs::PointCloud2 cloud;
00170 cloud.width = 0;
00171 cloud.height = 0;
00172 cloud.header.stamp = ros::Time::now();
00173 cloud.header.frame_id = cloud_.header.frame_id;
00174 sensor_msgs::PointCloud2Modifier cloud_mod(cloud);
00175 cloud_mod.setPointCloud2FieldsByString(1, "xyz");
00176 cloud_mod.resize(points_x_ * points_y_);
00177 sensor_msgs::PointCloud2Iterator<float> iter_cloud(cloud_, "x");
00178
00179
00180 int idx_cam = msg->observations.size() + 0;
00181 int idx_chain = msg->observations.size() + 1;
00182 msg->observations.resize(msg->observations.size() + 2);
00183 msg->observations[idx_cam].sensor_name = camera_sensor_name_;
00184 msg->observations[idx_chain].sensor_name = chain_sensor_name_;
00185
00186 msg->observations[idx_cam].features.resize(points_x_ * points_y_);
00187 msg->observations[idx_chain].features.resize(points_x_ * points_y_);
00188
00189
00190
00191 rgbd.header = cloud_.header;
00192 world.header.frame_id = "checkerboard";
00193
00194
00195 sensor_msgs::PointCloud2ConstIterator<float> xyz(cloud_, "x");
00196 for (size_t i = 0; i < points.size(); ++i)
00197 {
00198
00199
00200 world.point.z = (i % points_x_) * -square_size_;
00201 world.point.x = (i / points_x_) * -square_size_;
00202
00203
00204 int index = (int)(points[i].y) * cloud_.width + (int)(points[i].x);
00205 rgbd.point.x = (xyz + index)[X];
00206 rgbd.point.y = (xyz + index)[Y];
00207 rgbd.point.z = (xyz + index)[Z];
00208
00209
00210 if (isnan(rgbd.point.x) ||
00211 isnan(rgbd.point.y) ||
00212 isnan(rgbd.point.z))
00213 {
00214 ROS_ERROR_STREAM("NAN point on " << i);
00215 return false;
00216 }
00217
00218 msg->observations[idx_cam].features[i] = rgbd;
00219 msg->observations[idx_cam].ext_camera_info = depth_camera_manager_.getDepthCameraInfo();
00220 msg->observations[idx_chain].features[i] = world;
00221
00222
00223 iter_cloud[0] = rgbd.point.x;
00224 iter_cloud[1] = rgbd.point.y;
00225 iter_cloud[2] = rgbd.point.z;
00226 ++iter_cloud;
00227 }
00228
00229
00230 if (output_debug_)
00231 {
00232 msg->observations[idx_cam].cloud = cloud_;
00233 }
00234
00235
00236 publisher_.publish(cloud);
00237
00238
00239 return true;
00240 }
00241
00242 return false;
00243 }
00244
00245 }