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 #include "v4r_laser_robot_calibration/laser_robot_calibration_node.h"
00032
00033 using namespace cv;
00034
00035 Point2f operator*( const Matx<float, 3, 3 > &M, const Point2f& p )
00036 {
00037 return Point2f(M(0,0)*p.x+M(0,1)*p.y+M(0,2), M(1,0)*p.x+M(1,1)*p.y+M(1,2));
00038 }
00039
00040 Scalar green ( 0, 255, 0);
00041 Scalar green_bright ( 51, 255, 51);
00042 Scalar green_dark ( 0, 102, 0);
00043 Scalar red ( 0, 0, 255);
00044 Scalar blue ( 255, 0, 0);
00045 Scalar blue_bright ( 255, 51, 51);
00046 Scalar blue_dark ( 139, 0, 0);
00047 Scalar orange ( 0, 128, 255);
00048 Scalar yellow ( 0, 255, 255);
00049 Scalar cyan ( 255, 255, 0);
00050 Scalar magenta ( 255, 0, 255);
00051 Scalar gray ( 128, 128, 128);
00052 Scalar black ( 0, 0, 0);
00053 Scalar white ( 255, 255, 255);
00054
00055 int main(int argc, char **argv) {
00056
00057 ros::init(argc, argv, "LaserRobotCalibration");
00058 ros::NodeHandle n;
00059 LaserRobotCalibrationNode my_node(n);
00060 ros::Rate rate(10);
00061 while (ros::ok()) {
00062 my_node.stateMashine();
00063 ros::spinOnce();
00064 rate.sleep();
00065 }
00066 return 0;
00067 }
00068 LaserRobotCalibrationNode::LaserRobotCalibrationNode ( ros::NodeHandle &n )
00069 :n_ ( n ), n_param_ ( "~" ), callbackCount(0), state_(INIT) {
00070 sub_laser_ = n.subscribe("scan", 1, &LaserRobotCalibrationNode::callbackLaser, this);
00071 sub_marker_ = n.subscribe("marker", 1, &LaserRobotCalibrationNode::callbackMarker, this);
00072 pub_cmd_ = n.advertise<geometry_msgs::Twist>("cmd_vel", 1);
00073 cv::namedWindow(n.getNamespace(), 1);
00074 cv::moveWindow(n.getNamespace(), 20, 100);
00075 cvSetMouseCallback ( n.getNamespace().c_str(), this->mouseCallBack, this);
00076 }
00077
00078 void LaserRobotCalibrationNode::callbackLaser (const sensor_msgs::LaserScan::ConstPtr& msg) {
00079 msg_scan_ = *msg;
00080
00081 }
00082 void LaserRobotCalibrationNode::callbackMarker (const geometry_msgs::PoseArray::ConstPtr& msg) {
00083 msg_marker_ = *msg;
00084 draw_debug_view();
00085 }
00086
00087 void LaserRobotCalibrationNode::draw_debug_view() {
00088 cv::Rect rectView(0,0, 500, 500);
00089 debug_view_.create(rectView.size(), CV_8UC3);
00090 debug_view_.setTo(Scalar(0xFF,0xFF,0xFF));
00091 float sx = debug_view_.cols/ msg_scan_.range_max*2;
00092 float sy = debug_view_.rows/ msg_scan_.range_max*2;
00093 float robot_view_angle_ = 0;
00094 float ca = cos(robot_view_angle_+M_PI/2), sa = sin(robot_view_angle_+M_PI/2);
00095
00096 Matx<float, 3, 3 > Sc (sx, 0, 0, 0, sy, 0, 0, 0, 1);
00097 Matx<float, 3, 3 > Sp (-1, 0, 0, 0, 1, 0, 0, 0, 1);
00098 Matx<float, 3, 3 > R ( ca, -sa, 0, sa, ca, 0, 0, 0, 1);
00099 Matx<float, 3, 3 > T ( 1, 0, debug_view_.cols/2., 0, 1, debug_view_.rows/2., 0, 0, 1);
00100 Mr2v_ = T * R * Sp * Sc;
00101
00102 std::vector<Point2f> laser_points(msg_scan_.ranges.size());
00103 for (int i = 0; i < msg_scan_.ranges.size(); i++) {
00104 float d = msg_scan_.ranges[i];
00105 float angle = msg_scan_.angle_min + ( msg_scan_.angle_increment * i );
00106 laser_points[i].x = cos(angle) * d;
00107 laser_points[i].y = sin(angle) * d;
00108 Point2f p = Mr2v_ * laser_points[i];
00109 if(p.inside(rectView)) {
00110 debug_view_.at<cv::Vec3b>(p) = cv::Vec3b(50,10,10);
00111 }
00112 }
00113 std::vector<Point2f> marker_points(msg_marker_.poses.size());
00114 std::vector<float> marker_angles(msg_marker_.poses.size());
00115 for (int i = 0; i < msg_marker_.poses.size(); i++) {
00116 marker_points[i].x = msg_marker_.poses[i].position.x;
00117 marker_points[i].y = msg_marker_.poses[i].position.y;
00118 Point2f p = Mr2v_ * marker_points[i];
00119 if(p.inside(rectView)) {
00120 circle(debug_view_,p, 2, green,1, CV_AA);
00121 }
00122 }
00123
00124 circle(debug_view_,Mr2v_ * anchor_, 50, blue,1, CV_AA);
00125 circle(debug_view_,Mr2v_ * Point2f(marker_[0], marker_[1]), 3, red,1, CV_AA);
00126
00127 imshow(n_.getNamespace(),debug_view_);
00128 waitKey(100);
00129
00130 }
00131
00132 void LaserRobotCalibrationNode::rotateToMarkerNearPoint(cv::Point2f p) {
00133 anchor_ = p;
00134 state_ = ROTATE_TO_MARKER;
00135 }
00136
00137 void LaserRobotCalibrationNode::stateMashine() {
00138 if((state_ == ROTATE_TO_MARKER) || (state_ == ROTATE_NORMAL_TO_MARKER)) {
00139 double min_d = msg_scan_.range_max;
00140 int min_idx;
00141 for (int i = 0; i < msg_marker_.poses.size(); i++) {
00142 cv::Point2f m(msg_marker_.poses[i].position.x, msg_marker_.poses[i].position.y);
00143 double d = cv::norm(cv::Vec2f(m.x - anchor_.x, m.y - anchor_.y));
00144 if( d < min_d) {
00145 min_idx = i;
00146 min_d = d;
00147 }
00148 }
00149 anchor_ = cv::Point2f(marker_[0], marker_[1]);
00150 marker_ = cv::Vec3f (msg_marker_.poses[min_idx].position.x, msg_marker_.poses[min_idx].position.y, 0);
00151 double alpha = atan2(marker_[1], marker_[0]);
00152 geometry_msgs::Twist cmd;
00153 cmd.linear.x = 0;
00154 if(state_ == ROTATE_TO_MARKER) {
00155 ROS_INFO ("ROTATE_TO_MARKER alpha = %f, marker = <%4.3f,%4.3f>\n", alpha, marker_[0], marker_[1]);
00156 if(fabs(alpha) < 0.01) {
00157 cmd.angular.z = 0.0;
00158 state_ = ROTATE_NORMAL_TO_MARKER;
00159 } else {
00160 cmd.angular.z = alpha/4;
00161 pub_cmd_.publish(cmd);
00162 }
00163 pub_cmd_.publish(cmd);
00164 }
00165 if(state_ == ROTATE_NORMAL_TO_MARKER) {
00166 ROS_INFO ("ROTATE_NORMAL_TO_MARKER alpha = %f, marker = <%4.3f,%4.3f>\n", alpha, marker_[0], marker_[1]);
00167 alpha = alpha - M_PI/2.0;
00168 if(fabs(alpha) < 0.01) {
00169 cmd.angular.z = 0.0;
00170 state_ = INIT;
00171 } else {
00172 cmd.angular.z = alpha/4;
00173 pub_cmd_.publish(cmd);
00174 }
00175 pub_cmd_.publish(cmd);
00176 }
00177
00178 }
00179 }