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 #include <industrial_extrinsic_cal/ros_camera_observer.h>
00020
00021 namespace industrial_extrinsic_cal
00022 {
00023
00024 ROSCameraObserver::ROSCameraObserver(const std::string &camera_topic) :
00025 sym_circle_(true), pattern_(pattern_options::Chessboard), pattern_rows_(0), pattern_cols_(0)
00026 {
00027 image_topic_ = camera_topic;
00028
00029 results_pub_ = nh_.advertise<sensor_msgs::Image>("observer_results_image", 100);
00030 }
00031
00032 bool ROSCameraObserver::addTarget(boost::shared_ptr<Target> targ, Roi &roi)
00033 {
00034
00035 ROS_INFO_STREAM("Target type: "<<targ->target_type);
00036 instance_target_ = targ;
00037 switch (targ->target_type)
00038 {
00039 case pattern_options::Chessboard:
00040 pattern_ = pattern_options::Chessboard;
00041 break;
00042 case pattern_options::CircleGrid:
00043 pattern_ = pattern_options::CircleGrid;
00044 break;
00045 case pattern_options::ARtag:
00046 pattern_ = pattern_options::ARtag;
00047 break;
00048 default:
00049 ROS_ERROR_STREAM("target_type does not correlate to a known pattern option (Chessboard, CircleGrid or ARTag)");
00050 return false;
00051 break;
00052 }
00053
00054 if (pattern_ != 0 && pattern_ != 1 && pattern_ != 2)
00055 {
00056 ROS_ERROR_STREAM("Unknown pattern, based on target_type");
00057 return false;
00058 }
00059
00060
00061 switch (pattern_)
00062 {
00063 case pattern_options::Chessboard:
00064 pattern_rows_ = targ->checker_board_parameters.pattern_rows;
00065 pattern_cols_ = targ->checker_board_parameters.pattern_cols;
00066 break;
00067 case pattern_options::CircleGrid:
00068 pattern_rows_ = targ->circle_grid_parameters.pattern_rows;
00069 pattern_cols_ = targ->circle_grid_parameters.pattern_cols;
00070 sym_circle_ = targ->circle_grid_parameters.is_symmetric;
00071 break;
00072 case pattern_options::ARtag:
00073 ROS_ERROR_STREAM("AR Tag recognized but pattern not supported yet");
00074 return false;
00075 break;
00076 default:
00077 ROS_ERROR_STREAM("pattern_ does not correlate to a known pattern option (Chessboard, CircleGrid or ARTag)");
00078 return false;
00079 break;
00080 }
00081
00082 input_roi_.x=roi.x_min;
00083 input_roi_.y= roi.y_min;
00084 input_roi_.width= roi.x_max - roi.x_min;
00085 input_roi_.height= roi.y_max - roi.y_min;
00086 ROS_INFO_STREAM("ROSCameraObserver added target and roi");
00087
00088 return true;
00089 }
00090
00091 void ROSCameraObserver::clearTargets()
00092 {
00093 instance_target_.reset();
00094
00095 }
00096
00097 void ROSCameraObserver::clearObservations()
00098 {
00099 camera_obs_.observations.clear();
00100
00101 }
00102
00103 int ROSCameraObserver::getObservations(CameraObservations &cam_obs)
00104 {
00105 bool successful_find = false;
00106
00107 ROS_INFO_STREAM("image ROI region created: "<<input_roi_.x<<" "<<input_roi_.y<<" "<<input_roi_.width<<" "<<input_roi_.height);
00108 if (input_bridge_->image.cols < input_roi_.width || input_bridge_->image.rows < input_roi_.height)
00109 {
00110 ROS_ERROR_STREAM("ROI too big for image size");
00111 return 0;
00112 }
00113
00114 image_roi_ = input_bridge_->image(input_roi_);
00115
00116 output_bridge_->image = output_bridge_->image(input_roi_);
00117 out_bridge_->image = image_roi_;
00118 ROS_INFO_STREAM("output image size: " <<output_bridge_->image.rows<<" x "<<output_bridge_->image.cols);
00119 results_pub_.publish(out_bridge_->toImageMsg());
00120
00121 switch (pattern_)
00122 {
00123 case pattern_options::Chessboard:
00124 ROS_INFO_STREAM("Finding Chessboard Corners...");
00125 successful_find = cv::findChessboardCorners(image_roi_, cv::Size(pattern_rows_, pattern_cols_), observation_pts_,
00126 cv::CALIB_CB_ADAPTIVE_THRESH);
00127 break;
00128 case pattern_options::CircleGrid:
00129 if (sym_circle_)
00130 {
00131 ROS_INFO_STREAM("Finding Circles in grid, symmetric...");
00132 successful_find = cv::findCirclesGrid(image_roi_, cv::Size(pattern_rows_, pattern_cols_), observation_pts_,
00133 cv::CALIB_CB_SYMMETRIC_GRID);
00134 }
00135 else
00136 {
00137 ROS_INFO_STREAM("Finding Circles in grid, asymmetric...");
00138 successful_find = cv::findCirclesGrid(image_roi_, cv::Size(pattern_rows_, pattern_cols_), observation_pts_,
00139 cv::CALIB_CB_ASYMMETRIC_GRID | cv::CALIB_CB_CLUSTERING);
00140 }
00141 break;
00142 }
00143 if (!successful_find)
00144 {
00145 ROS_WARN_STREAM("Pattern not found for pattern: "<<pattern_ <<" with symmetry: "<< sym_circle_);
00146 return 0;
00147 }
00148
00149 ROS_INFO_STREAM("Number of points found on board: "<<observation_pts_.size());
00150 camera_obs_.observations.resize(observation_pts_.size());
00151 for (int i = 0; i < observation_pts_.size(); i++)
00152 {
00153 camera_obs_.observations.at(i).target = instance_target_;
00154 camera_obs_.observations.at(i).point_id = i;
00155 camera_obs_.observations.at(i).image_loc_x = observation_pts_.at(i).x;
00156 camera_obs_.observations.at(i).image_loc_y = observation_pts_.at(i).y;
00157 }
00158
00159 cam_obs = camera_obs_;
00160 return 1;
00161 }
00162
00163 void ROSCameraObserver::triggerCamera()
00164 {
00165
00166 sensor_msgs::ImageConstPtr recent_image = ros::topic::waitForMessage<sensor_msgs::Image>(image_topic_);
00167
00168 try
00169 {
00170 input_bridge_ = cv_bridge::toCvCopy(recent_image, "mono8");
00171 output_bridge_ = cv_bridge::toCvCopy(recent_image, "bgr8");
00172 out_bridge_ = cv_bridge::toCvCopy(recent_image, "mono8");
00173 ROS_INFO_STREAM("cv image created based on ros image");
00174 }
00175 catch (cv_bridge::Exception& ex)
00176 {
00177 ROS_ERROR("Failed to convert image");
00178 ROS_WARN_STREAM("cv_bridge exception: "<<ex.what());
00179
00180 return;
00181 }
00182
00183 }
00184
00185 bool ROSCameraObserver::observationsDone()
00186 {
00187
00188 if(!input_bridge_)
00189 {
00190 return false;
00191 }
00192 return true;
00193 }
00194 }