v4r_ellipses_nodelet.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 #include "v4r_ellipses_nodelet.h"
00031 #include <iomanip>
00032 #include <opencv/cv.h>
00033 #include <opencv/highgui.h>
00034 #include <sensor_msgs/image_encodings.h>
00035 #include "boost/date_time/posix_time/posix_time.hpp"
00036 #include <image_geometry/pinhole_camera_model.h>
00037 #include <v4r_ellipses/TransformArrayStamped.h>
00038 
00039 #include <pluginlib/class_list_macros.h>
00040 PLUGINLIB_DECLARE_CLASS(V4R, EllipsesDetectionNode, V4R::EllipsesDetectionNode, nodelet::Nodelet)
00041 using namespace V4R;
00042 
00043 EllipsesDetectionNode::~EllipsesDetectionNode() {
00044 }
00045 
00046 EllipsesDetectionNode::EllipsesDetectionNode() :
00047     EllipsesDetection(new EllipsesDetectionNode::ParametersNode()), n_(), callback_counter_(0), imageTransport_(n_) {
00048 
00049 }
00050 
00051 const EllipsesDetectionNode::ParametersNode *EllipsesDetectionNode::param() {
00052     return (EllipsesDetectionNode::ParametersNode*) param_;
00053 }
00054 
00055 void EllipsesDetectionNode::init() {
00056     sub_camera_ = imageTransport_.subscribeCamera( "image", 1, &EllipsesDetectionNode::imageCallback, this );
00057     pub_viz_marker_ =  n_.advertise<visualization_msgs::Marker>("visualization_marker", 1000);
00058     pub_perceptions_ =  n_.advertise<v4r_ellipses::TransformArrayStamped>("perceptions", 1000);
00059 }
00060 
00061 void EllipsesDetectionNode::imageCallback(const sensor_msgs::ImageConstPtr& image_msg, const sensor_msgs::CameraInfoConstPtr& camer_info) {
00062 
00063     if(callback_counter_ == 0) timeCallbackReceived_ = boost::posix_time::microsec_clock::local_time();
00064     callback_counter_++;
00065     if((param()->image_skip >= 0) && (callback_counter_ % (param()->image_skip+1) != 0)) return;
00066     timeCallbackReceivedLast_ = timeCallbackReceived_;
00067     timeCallbackReceived_ = boost::posix_time::microsec_clock::local_time();
00068 
00069     image_geometry::PinholeCameraModel cam_model;
00070     cam_model.fromCameraInfo ( camer_info );
00071     try {
00072         if((image_mono_ == NULL) || !param()->debug_freeze) {
00073             image_mono_ = cv_bridge::toCvCopy(image_msg, sensor_msgs::image_encodings::MONO8);
00074             camera_info_ = camer_info;
00075         }
00076     } catch (cv_bridge::Exception& e) {
00077         ROS_ERROR("cv_bridge exception: %s", e.what());
00078         return;
00079     }
00080 
00081     //cv::Mat image = cv::imread("/home/max/Downloads/image001.png", CV_LOAD_IMAGE_COLOR); cv::cvtColor(image, image_mono_->image, CV_RGB2GRAY);
00082     timeDetectionStart_ = boost::posix_time::microsec_clock::local_time();
00083     next();
00084     std::vector<cv::RotatedRect> ellipses;
00085     cv::Mat intrinsicMatrix(cam_model.intrinsicMatrix());
00086     cv::Mat distortionCoeffs(cam_model.distortionCoeffs());
00087     cv::Mat projectionMatrix(cam_model.projectionMatrix());
00088     fit_ellipses_opencv (image_mono_->image, intrinsicMatrix, distortionCoeffs, projectionMatrix, image_msg->header.stamp.toBoost() );
00089     createRings();
00090     createTransforms(image_msg->header);
00091     timeDetectionEnd_ = boost::posix_time::microsec_clock::local_time();
00092     publishTf();
00093     publishPerceptions(image_msg->header);
00094     publishMarker(image_msg->header);
00095 
00096     if (param()->show_camera_image) {
00097         cv::Mat img_debug;
00098         std::stringstream ss;
00099         ss << "capture: " << std::setw(3) << (timeDetectionStart_ - timeCallbackReceived_).total_milliseconds() << "ms, ";
00100         ss << "detection: " << std::setw(3) << (timeDetectionEnd_ - timeDetectionStart_).total_milliseconds() << "ms, ";
00101         ss << "total: " << std::setw(3) << (timeDetectionEnd_ - timeCallbackReceived_).total_milliseconds() << "ms, ";
00102         ss << "interval: " << std::setw(3) << (timeCallbackReceived_ - timeCallbackReceivedLast_).total_milliseconds() << "ms";
00103         if((timeCallbackReceived_ - timeCallbackReceivedLast_).total_milliseconds() > 0) {
00104             ss << " = " << std::setw(3) << 1000 /(timeCallbackReceived_ - timeCallbackReceivedLast_).total_milliseconds() << "Hz";
00105         }
00106         cvtColor(image_mono_->image, img_debug, CV_GRAY2BGR);
00107         draw_ellipses(img_debug);
00108         cv::putText(img_debug, ss.str(), cv::Point(10, 15), cv::FONT_HERSHEY_PLAIN, 0.6, cv::Scalar::all(0), 1, CV_AA);
00109         cv::imshow( param()->node_name + std::string(" - input"), img_debug);
00110         if(param()->debug) {
00111             cv::imshow( param()->node_name + std::string(" - edges"), imgEdges_);
00112             if(!imgGradient_.empty()) {
00113                 cv::imshow( param()->node_name + std::string(" - gradient"), imgGradient_ * (0xFFFF/0x1FF));
00114             }
00115             if(!imgDirection_.empty()) {
00116                 cv::imshow( param()->node_name + std::string(" - direction"), imgDirection_ * 0xFFFF/0x1FF);
00117             }
00118             if(!imgSobelDx_.empty()) {
00119                 cv::imshow( param()->node_name + std::string(" - imgSobelDx_"), imgSobelDx_ * (0xFFFF/0x1FF));
00120             }
00121             if(!imgSobelDy_.empty()) {
00122                 cv::imshow( param()->node_name + std::string(" - imgSobelDy_"), imgSobelDy_ * (0xFFFF/0x1FF));
00123             }
00124         }
00125         cv::waitKey(param()->show_camera_image_waitkey);
00126     }
00127 }
00128 
00129 void EllipsesDetectionNode::onInit()
00130 {
00131     init();
00132 }
00133 
00134 void EllipsesDetectionNode::createTransforms(const std_msgs::Header &header) {
00135     if(param()->pose_estimation == POSE_ESTIMATION_OFF) return;
00136     estimatePoses();
00137     tf::Transform trans;
00138     tf::StampedTransform st;
00139     char frame[0xFF];
00140     markerTransforms_.clear();
00141     for(unsigned int i = 0; i < 2; i++) {
00142         if(param()->skip_second_tf && (i == 1)) continue;
00143         for(std::list<Marker>::iterator it = markers_.begin(); it != markers_.end(); it++) {
00144             Marker &m = *it;
00145             sprintf(frame, "t%i-%i", i, m.id);
00146             std::string child_frame = tf::resolve(param()->tf_prefix, frame);
00147             tf::Quaternion roation;
00148             tf::Vector3 translation;
00149             tf::Matrix3x3 R;
00150             translation.setValue(m.translations[i].x, m.translations[i].y, m.translations[i].z);
00151             R.setValue (m.R[i](0,0), m.R[i](0,1), m.R[i](0,2), m.R[i](1,0), m.R[i](1,1), m.R[i](1,2), m.R[i](2,0), m.R[i](2,1), m.R[i](2,2));
00152             R.getRotation(roation);
00153             trans = tf::Transform(roation, translation);
00154             st = tf::StampedTransform(trans, header.stamp, header.frame_id, child_frame);
00155             markerTransforms_.push_back(st);
00156         }
00157     }
00158 }
00159 
00160 
00161 void EllipsesDetectionNode::publishTf() {
00162     for(std::list<tf::StampedTransform>::iterator it =  markerTransforms_.begin(); it != markerTransforms_.end(); it++) {
00163         transformBroadcaster_.sendTransform(*it);
00164     }
00165 
00166 }
00167 
00168 void EllipsesDetectionNode::publishMarker (const std_msgs::Header &header) {
00169     msg_line_list_.header = header;
00170     msg_line_list_.ns = "nomrals";
00171     msg_line_list_.action = visualization_msgs::Marker::ADD;
00172     msg_line_list_.pose.orientation.w = 1.0;
00173     msg_line_list_.id = 0;
00174     msg_line_list_.type = visualization_msgs::Marker::LINE_LIST;
00175     msg_line_list_.scale.x = 0.01;
00176     msg_line_list_.color.r = 1.0;
00177     msg_line_list_.color.g = 0.0;
00178     msg_line_list_.color.b = 0.0;
00179     msg_line_list_.color.a = 1.0;
00180     geometry_msgs::Point p0, p1;
00181     for(unsigned int i = 0; i < 2; i++) {
00182         msg_line_list_.points.clear();
00183         msg_line_list_.ns = "nomrals-" + boost::lexical_cast<std::string>(i);
00184         msg_line_list_.color.r = 0.5 + 0.5*i;
00185         for(std::list<Marker>::iterator it = markers_.begin(); it != markers_.end(); it++) {
00186             Marker &m = *it;
00187             p0.x = m.translations[i].x, p0.y = m.translations[i].y, p0.z = m.translations[i].z;
00188             p1.x = p0.x +  m.normals[i][0]/2., p1.y = p0.y + m.normals[i][1]/2., p1.z = p0.z + m.normals[i][2]/2.;
00189             msg_line_list_.points.push_back(p0);
00190             msg_line_list_.points.push_back(p1);
00191         }
00192         pub_viz_marker_.publish(msg_line_list_);
00193     }
00194 }
00195 
00196 void EllipsesDetectionNode::publishPerceptions (const std_msgs::Header &header) {
00197     if(pub_perceptions_.getNumSubscribers() < 1) return;
00198     v4r_ellipses::TransformArrayStamped msg;
00199     if(markerTransforms_.size() > 0) {
00200         msg.header = header;
00201         msg.child_frame_id.resize(markerTransforms_.size());
00202         msg.transform.resize(markerTransforms_.size());
00203         std::list<tf::StampedTransform>::iterator it =  markerTransforms_.begin();
00204         for(unsigned int i; i < markerTransforms_.size(); it++, i++) {
00205             geometry_msgs::Vector3 &desT = msg.transform[i].translation;
00206             geometry_msgs::Quaternion &desQ = msg.transform[i].rotation;
00207             tf::Vector3 &srcT = it->getOrigin();
00208             tf::Quaternion srcQ = it->getRotation();
00209             desT.x = srcT.x(), desT.y = srcT.y(), desT.z = srcT.z();
00210             desQ.x = srcQ.x(), desQ.y = srcQ.y(), desQ.z = srcQ.z(), desQ.w = srcQ.w();
00211             msg.child_frame_id[i] = it->child_frame_id_;
00212         }
00213         pub_perceptions_.publish(msg);
00214     }
00215 
00216 }


v4r_ellipses
Author(s):
autogenerated on Wed Aug 26 2015 16:41:40