laser_robot_calibration_node.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  * Copyright (c) 2014 Markus Bader <markus.bader@tuwien.ac.at>
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  * 1. Redistributions of source code must retain the above copyright
00008  *    notice, this list of conditions and the following disclaimer.
00009  * 2. Redistributions in binary form must reproduce the above copyright
00010  *    notice, this list of conditions and the following disclaimer in the
00011  *    documentation and/or other materials provided with the distribution.
00012  * 3. All advertising materials mentioning features or use of this software
00013  *    must display the following acknowledgement:
00014  *    This product includes software developed by the TU-Wien.
00015  * 4. Neither the name of the TU-Wien nor the
00016  *    names of its contributors may be used to endorse or promote products
00017  *    derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY Markus Bader ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL Markus Bader BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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);   // scaling
00097     Matx<float, 3, 3 > Sp (-1, 0, 0, 0, 1, 0, 0, 0, 1);    // mirroring
00098     Matx<float, 3, 3 > R ( ca, -sa, 0, sa, ca, 0, 0, 0, 1); // rotation
00099     Matx<float, 3, 3 > T ( 1, 0, debug_view_.cols/2., 0, 1, debug_view_.rows/2., 0, 0, 1);  // translation
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 }


v4r_laser_robot_calibration
Author(s):
autogenerated on Wed Aug 26 2015 16:42:08