ellipses_nodelet.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (c) 2014 Markus Bader <markus.bader@tuwien.ac.at>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. All advertising materials mentioning features or use of this software
13  * must display the following acknowledgement:
14  * This product includes software developed by the TU-Wien.
15  * 4. Neither the name of the TU-Wien nor the
16  * names of its contributors may be used to endorse or promote products
17  * derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY Markus Bader ''AS IS'' AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL Markus Bader BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  ***************************************************************************/
30 #include "ellipses_nodelet.h"
31 #include <iomanip>
32 #include <opencv2/highgui/highgui.hpp>
34 #include <boost/date_time/posix_time/posix_time.hpp>
36 #include <marker_msgs/MarkerDetection.h>
37 
40 using namespace tuw;
41 
43 }
44 
45 EllipsesDetectionNode::EllipsesDetectionNode() :
46  EllipsesDetection(new EllipsesDetectionNode::ParametersNode()), n_(), callback_counter_(0), imageTransport_(n_) {
47 
48 }
49 
52 }
53 
56  pub_perceptions_ = n_.advertise<marker_msgs::MarkerDetection>("marker", 1000);
57  pub_fiducials_ = n_.advertise<marker_msgs::FiducialDetection>("fiducials", 1000);
58 }
59 
60 void EllipsesDetectionNode::imageCallback(const sensor_msgs::ImageConstPtr& image_msg, const sensor_msgs::CameraInfoConstPtr& camer_info) {
61 
62  if(callback_counter_ == 0) timeCallbackReceived_ = boost::posix_time::microsec_clock::local_time();
64  if((param()->image_skip >= 0) && (callback_counter_ % (param()->image_skip+1) != 0)) return;
66  timeCallbackReceived_ = boost::posix_time::microsec_clock::local_time();
67 
69  cam_model.fromCameraInfo ( camer_info );
70  try {
71  if((image_mono_ == NULL) || !param()->debug_freeze) {
73  camera_info_ = camer_info;
74  }
75  } catch (cv_bridge::Exception& e) {
76  ROS_ERROR("cv_bridge exception: %s", e.what());
77  return;
78  }
79 
80  //cv::Mat image = cv::imread("/home/max/Downloads/image001.png", CV_LOAD_IMAGE_COLOR); cv::cvtColor(image, image_mono_->image, CV_RGB2GRAY);
81  timeDetectionStart_ = boost::posix_time::microsec_clock::local_time();
82  next();
83  std::vector<cv::RotatedRect> ellipses;
84  cv::Mat intrinsic(cam_model.intrinsicMatrix());
85  cv::Mat projection(cam_model.projectionMatrix());
86  fit_ellipses_opencv (image_mono_->image, intrinsic, cam_model.distortionCoeffs(), projection, image_msg->header.stamp.toBoost() );
87  createRings();
88  createTransforms(image_msg->header);
89  timeDetectionEnd_ = boost::posix_time::microsec_clock::local_time();
90  if(param()->publishTF) publishTf();
91  if(param()->publishMarker) publishMarker(image_msg->header);
92  if(param()->publishFiducials) publishFiducials(image_msg->header);
93 
94  if (param()->show_camera_image) {
95  cv::Mat img_debug;
96  std::stringstream ss;
97  ss << "capture: " << std::setw(3) << (timeDetectionStart_ - timeCallbackReceived_).total_milliseconds() << "ms, ";
98  ss << "detection: " << std::setw(3) << (timeDetectionEnd_ - timeDetectionStart_).total_milliseconds() << "ms, ";
99  ss << "total: " << std::setw(3) << (timeDetectionEnd_ - timeCallbackReceived_).total_milliseconds() << "ms, ";
100  ss << "interval: " << std::setw(3) << (timeCallbackReceived_ - timeCallbackReceivedLast_).total_milliseconds() << "ms";
101  if((timeCallbackReceived_ - timeCallbackReceivedLast_).total_milliseconds() > 0) {
102  ss << " = " << std::setw(3) << 1000 /(timeCallbackReceived_ - timeCallbackReceivedLast_).total_milliseconds() << "Hz";
103  }
104  cvtColor(image_mono_->image, img_debug, CV_GRAY2BGR);
105  draw_ellipses(img_debug);
106  cv::putText(img_debug, ss.str(), cv::Point(10, 15), cv::FONT_HERSHEY_PLAIN, 0.6, cv::Scalar::all(0), 1, CV_AA);
107  cv::imshow( param()->node_name + std::string(" - input"), img_debug);
108  if(param()->debug) {
109  cv::imshow( param()->node_name + std::string(" - edges"), imgEdges_);
110  if(!imgGradient_.empty()) {
111  cv::imshow( param()->node_name + std::string(" - gradient"), imgGradient_ * (0xFFFF/0x1FF));
112  }
113  if(!imgDirection_.empty()) {
114  cv::imshow( param()->node_name + std::string(" - direction"), imgDirection_ * 0xFFFF/0x1FF);
115  }
116  if(!imgSobelDx_.empty()) {
117  cv::imshow( param()->node_name + std::string(" - imgSobelDx_"), imgSobelDx_ * (0xFFFF/0x1FF));
118  }
119  if(!imgSobelDy_.empty()) {
120  cv::imshow( param()->node_name + std::string(" - imgSobelDy_"), imgSobelDy_ * (0xFFFF/0x1FF));
121  }
122  }
123  cv::waitKey(param()->show_camera_image_waitkey);
124  }
125 }
126 
128 {
129  init();
130 }
131 
132 void EllipsesDetectionNode::createTransforms(const std_msgs::Header &header) {
133  if(param()->pose_estimation == POSE_ESTIMATION_OFF) return;
134  estimatePoses();
135  tf::Transform trans;
137  char frame[0xFF];
138  markerTransforms_.clear();
139  for(unsigned int i = 0; i < 2; i++) {
140  if(param()->skip_second_tf && (i == 1)) continue;
141  for(std::list<Marker>::iterator it = markers_.begin(); it != markers_.end(); it++) {
142  Marker &m = *it;
143  sprintf(frame, "t%i-%i", i, m.id);
144  std::string child_frame = tf::resolve(param()->tf_prefix, frame);
145  tf::Quaternion roation;
146  tf::Vector3 translation;
147  tf::Matrix3x3 R;
148  translation.setValue(m.translations[i].x, m.translations[i].y, m.translations[i].z);
149  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));
150  R.getRotation(roation);
151  trans = tf::Transform(roation, translation);
152  st = tf::StampedTransform(trans, header.stamp, header.frame_id, child_frame);
153  markerTransforms_.push_back(st);
154  }
155  }
156 }
157 
158 
160  for(std::list<tf::StampedTransform>::iterator it = markerTransforms_.begin(); it != markerTransforms_.end(); it++) {
162  }
163 
164 }
165 
166 void EllipsesDetectionNode::publishMarker (const std_msgs::Header &header) {
167  if(pub_perceptions_.getNumSubscribers() < 1) return;
168  marker_msgs::MarkerDetection msg;
169  if(markerTransforms_.size() > 0) {
170  msg.header = header;
171  msg.distance_min = 0; //TODO
172  msg.distance_max = 8; //TODO
173  msg.distance_max_id = 5; //TODO
174  msg.view_direction.x = 0; //TODO
175  msg.view_direction.y = 0; //TODO
176  msg.view_direction.z = 0; //TODO
177  msg.view_direction.w = 1; //TODO
178  msg.fov_horizontal = 6; //TODO
179  msg.fov_vertical = 0; //TODO
180  msg.type = "ellipses";
181  msg.markers.resize(markerTransforms_.size());
182  std::list<tf::StampedTransform>::iterator it = markerTransforms_.begin();
183  for(size_t i = 0; i < markerTransforms_.size(); it++, i++) {
184  marker_msgs::Marker &marker = msg.markers[i];
185  // marker.ids ellipses have no id
186  // marker.ids_confidence ellipses have no id
187  tf::Vector3 &srcT = it->getOrigin();
188  marker.pose.position.x = srcT.x();
189  marker.pose.position.y = srcT.y();
190  marker.pose.position.z = srcT.z();
191  tf::Quaternion srcQ = it->getRotation();
192  marker.pose.orientation.x = srcQ.x();
193  marker.pose.orientation.y = srcQ.y();
194  marker.pose.orientation.z = srcQ.z();
195  marker.pose.orientation.w = srcQ.w();
196  }
198  }
199 
200 }
201 
202 void EllipsesDetectionNode::publishFiducials(const std_msgs::Header &header) {
203  marker_msgs::FiducialDetection msg;
204  msg.header = header;
205  msg.camera_k = camera_info_->K;
206  msg.camera_d = camera_info_->D;
207 
208  for (std::vector<Ellipse>::iterator it = ellipses_.begin(); it != ellipses_.end(); it++) {
209  Ellipse &e = *it;
210  if(e.detection != VALID) continue;
211 
212  marker_msgs::Fiducial fiducial;
213 
214  geometry_msgs::Point objectPoint;
215  objectPoint.x = 0.0f;
216  objectPoint.y = 0.0f;
217  objectPoint.z = 0.0f;
218  fiducial.object_points.push_back(objectPoint);
219 
220  geometry_msgs::Point imagePoint;
221  imagePoint.x = e.boxEllipse.center.x;
222  imagePoint.y = e.boxEllipse.center.y;
223  imagePoint.z = 0.0f; // imagePoints are 2d
224  fiducial.image_points.push_back(imagePoint);
225 
226  fiducial.ids.resize(0);
227  fiducial.ids_confidence.resize(0);
228 
229  msg.fiducial.push_back(fiducial);
230  }
231 
232  pub_fiducials_.publish(msg);
233 }
const cv::Matx33d & intrinsicMatrix() const
std::list< Marker > markers_
const ParametersNode * param()
void publish(const boost::shared_ptr< M > &message) const
void draw_ellipses(cv::Mat &m)
CameraSubscriber subscribeCamera(const std::string &base_topic, uint32_t queue_size, const CameraSubscriber::Callback &callback, const ros::VoidPtr &tracked_object=ros::VoidPtr(), const TransportHints &transport_hints=TransportHints())
tf::TransformBroadcaster transformBroadcaster_
boost::posix_time::ptime timeCallbackReceivedLast_
boost::posix_time::ptime timeDetectionStart_
void setValue(const tfScalar &xx, const tfScalar &xy, const tfScalar &xz, const tfScalar &yx, const tfScalar &yy, const tfScalar &yz, const tfScalar &zx, const tfScalar &zy, const tfScalar &zz)
std::list< tf::StampedTransform > markerTransforms_
TFSIMD_FORCE_INLINE void setValue(const tfScalar &x, const tfScalar &y, const tfScalar &z)
#define PLUGINLIB_DECLARE_CLASS(pkg, class_name, class_type, base_class_type)
void getRotation(Quaternion &q) const
std::string resolve(const std::string &prefix, const std::string &frame_name)
TFSIMD_FORCE_INLINE const tfScalar & x() const
boost::posix_time::ptime timeDetectionEnd_
void imageCallback(const sensor_msgs::ImageConstPtr &image_msg, const sensor_msgs::CameraInfoConstPtr &info_msg)
std::vector< Ellipse > ellipses_
TFSIMD_FORCE_INLINE const tfScalar & z() const
CvImagePtr cvtColor(const CvImageConstPtr &source, const std::string &encoding)
sensor_msgs::CameraInfoConstPtr camera_info_
bool fromCameraInfo(const sensor_msgs::CameraInfo &msg)
boost::posix_time::ptime timeCallbackReceived_
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
TFSIMD_FORCE_INLINE const tfScalar & y() const
void sendTransform(const StampedTransform &transform)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
cv::Mat_< double > R[2]
two plausible translations solutions
uint32_t getNumSubscribers() const
cv_bridge::CvImagePtr image_mono_
image_transport::CameraSubscriber sub_camera_
const cv::Matx34d & projectionMatrix() const
void createTransforms(const std_msgs::Header &header)
image_transport::ImageTransport imageTransport_
const cv::Mat_< double > & distortionCoeffs() const
void publishFiducials(const std_msgs::Header &header)
void fit_ellipses_opencv(const cv::Mat &m, const cv::Mat cameraMatrix, const cv::Mat distCoeffs, const cv::Mat projectionMatrix, const boost::posix_time::ptime &tstamp)
#define ROS_ERROR(...)
cv::Point3d translations[2]
ellipse equation
void publishMarker(const std_msgs::Header &header)


tuw_ellipses
Author(s): Markus Bader
autogenerated on Mon Jun 10 2019 15:42:10