artoolkitplus.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2013 by Markus Bader *
3  * markus.bader@tuwien.ac.at *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
20 
23 
24 #include <tuw_artoolkitplus/TransformArrayStamped.h>
25 
26 #include <cv_bridge/cv_bridge.h>
27 #include <opencv2/highgui/highgui.hpp>
29 
33 
34 
35 
36 class MyLogger: public ARToolKitPlus::Logger {
37  void artLog ( const char* nStr ) {
38  printf ( "%s", nStr );
39  }
40 };
41 
43  n_ ( n ), n_param_ ( "~" ), callback_counter_ ( 0 ), imageTransport_ ( n_ ), logger_ ( NULL ), param_() {
44 
45  init();
46  pub_markers_ = n_.advertise<marker_msgs::MarkerDetection>("markers", 10);
48 
50  reconfigureFnc_ = boost::bind(&ARToolKitPlusNode::callbackParameters, this , _1, _2);
52 }
53 
54 
56  if ( logger_ != NULL )
57  delete logger_;
58 }
59 
61 public:
62  virtual ~ARCamera() {
63  };
64 
66  if ( undist_iterations == 1 ) {
67  return false;
68  } else {
69  return true;
70  }
71  }
72 
73  ARCamera ( const sensor_msgs::CameraInfoConstPtr& _camer_info, int _undist_iterations, bool _input_distorted ) {
74 
75 
76  // ARToolKitPlus::CameraAdvImpl Parameter
77  if ( _input_distorted ) {
78  // using the ros Intrinsic camera matrix for the raw (distorted) images.
79  this->fc[0] = ( ARFloat ) _camer_info->K[0];
80  this->fc[1] = ( ARFloat ) _camer_info->K[4];
81  this->cc[0] = ( ARFloat ) _camer_info->K[2];
82  this->cc[1] = ( ARFloat ) _camer_info->K[5];
83 
84  undist_iterations = _undist_iterations;
85 
86  this->kc[0] = ( ARFloat ) _camer_info->D[0];
87  this->kc[1] = ( ARFloat ) _camer_info->D[1];
88  this->kc[2] = ( ARFloat ) _camer_info->D[2];
89  this->kc[3] = ( ARFloat ) _camer_info->D[3];
90  this->kc[4] = ( ARFloat ) _camer_info->D[4];
91  this->kc[5] = ( ARFloat ) 0.;
92 
93  } else {
94  // using the ros Projection/camera matrix
95  this->fc[0] = ( ARFloat ) _camer_info->P[0];
96  this->fc[1] = ( ARFloat ) _camer_info->P[5];
97  this->cc[0] = ( ARFloat ) _camer_info->P[2];
98  this->cc[1] = ( ARFloat ) _camer_info->P[6];
99 
100  undist_iterations = 1;
101 
102  for ( int i = 0; i < 6; i++ )
103  this->kc[i] = ( ARFloat ) 0.;
104 
105  }
106 
107  // ARToolKitPlus::Camera Parameter
108  // fileName
109 
110  // ARToolKit::ARParam Parameter
111  xsize = _camer_info->width;
112  ysize = _camer_info->height;
113 
114  for ( int i = 0; i < 3; i++ )
115  for ( int j = 0; j < 4; j++ )
116  this->mat[i][j] = ( ARFloat ) 0.;
117 
118  mat[0][0] = fc[0]; // fc_x
119  mat[1][1] = fc[1]; // fc_y
120  mat[0][2] = cc[0]; // cc_x
121  mat[1][2] = cc[1]; // cc_y
122  mat[2][2] = 1.0;
123 
124  if ( _input_distorted == false ) {
125  // using the ros Projection/camera matrix
126  mat[0][3] = ( ARFloat ) _camer_info->P[3];
127  mat[1][3] = ( ARFloat ) _camer_info->P[7];
128  }
129 
130  for ( int i = 0; i < 4; i++ )
131  this->dist_factor[i] = this->kc[i];
132  }
133 };
134 
135 
136 void ARToolKitPlusNode::initTrackerMultiMarker ( const sensor_msgs::CameraInfoConstPtr& camer_info ) {
138  const char* description = trackerMultiMarker_->getDescription();
139  ROS_INFO ( "%s: compile-time information:\n%s", param_.node_name.c_str(), description );
140 
141 // set a logger so we can output error messages
142  if ( logger_ == NULL ) logger_ = new MyLogger();
143  trackerMultiMarker_->setLogger ( logger_ );
145 
146  ARCamera *camera = new ARCamera ( camer_info, param_.undist_iterations, param_.distorted_input );
147  if ( !trackerMultiMarker_->init ( camera, param_.pattern_file.c_str(), 1.0f, 1000.0f ) ) {
148  ROS_ERROR ( "ERROR: init() failed" );
149  }
150 
151 }
152 
153 void ARToolKitPlusNode::initTrackerSingleMarker ( const sensor_msgs::CameraInfoConstPtr& camer_info ) {
155  const char* description = trackerSingleMarker_->getDescription();
156  ROS_INFO ( "%s: compile-time information:\n%s", param_.node_name.c_str(), description );
157 
158 // set a logger so we can output error messages
159  trackerSingleMarker_->setLogger ( logger_ );
161 
162  ARCamera *camera = new ARCamera ( camer_info, param_.undist_iterations, param_.distorted_input );
163  if ( !trackerSingleMarker_->init ( camera, 1.0f, 1000.0f ) ) {
164  ROS_ERROR ( "ERROR: init() failed" );
165  }
166 
167 }
168 
169 void ARToolKitPlusNode::updateParameterTrackerSingleMarker ( const sensor_msgs::CameraInfoConstPtr& camer_info ) {
170 
171  ARCamera * camera = ( ARCamera * ) trackerSingleMarker_->getCamera();
172  if ( camera->isInputDistorted() != param_.distorted_input ) {
173  delete camera;
174  camera = new ARCamera ( camer_info, param_.undist_iterations, param_.distorted_input );
175  trackerSingleMarker_->setCamera ( camera );
176  }
177 
178 // define size of the marker
179  trackerSingleMarker_->setPatternWidth ( param_.pattern_width );
180 
181 // the marker in the BCH test image has a thin border...
182  if ( param_.border_width > 0 ) {
183  trackerSingleMarker_->setBorderWidth ( param_.border_width );
184  } else {
185  trackerSingleMarker_->setBorderWidth ( param_.useBCH ? 0.125f : 0.250f );
186  }
187 
188 // set a threshold. alternatively we could also activate automatic thresholding
189  if ( param_.edge_threshold > 0 ) {
190  trackerSingleMarker_->activateAutoThreshold ( false );
191  trackerSingleMarker_->setThreshold ( param_.edge_threshold );
192  } else {
193  trackerSingleMarker_->activateAutoThreshold ( true );
194  }
195 // let's use lookup-table undistortion for high-speed
196 // note: LUT only works with images up to 1024x1024
197  trackerSingleMarker_->setUndistortionMode ( ( ARToolKitPlus::UNDIST_MODE ) param_.undist_mode );
198 
199 // RPP is more robust than ARToolKit's standard pose estimator
200  trackerSingleMarker_->setPoseEstimator ( ( ARToolKitPlus::POSE_ESTIMATOR ) param_.pose_estimation_mode );
201 
202 // switch to simple ID based markers
203 // use the tool in tools/IdPatGen to generate markers
205 
206 // do the OpenGL camera setup
207 //glMatrixMode(GL_PROJECTION)
208 //glLoadMatrixf(tracker->getProjectionMatrix());
209 }
210 
211 void ARToolKitPlusNode::updateParameterTrackerMultiMarker ( const sensor_msgs::CameraInfoConstPtr& camer_info ) {
212 
213  ARCamera * camera = ( ARCamera * ) trackerMultiMarker_->getCamera();
214  if ( camera->isInputDistorted() != param_.distorted_input ) {
215  delete camera;
216  camera = new ARCamera ( camer_info, param_.undist_iterations, param_.distorted_input );
217  trackerMultiMarker_->setCamera ( camera );
218  }
219 
220  trackerMultiMarker_->setUseDetectLite ( param_.use_multi_marker_lite_detection );
221 
222 // the marker in the BCH test image has a thin border...
223  if ( param_.border_width > 0 ) {
224  trackerMultiMarker_->setBorderWidth ( param_.border_width );
225  } else {
226  trackerMultiMarker_->setBorderWidth ( param_.useBCH ? 0.125f : 0.250f );
227  }
228 
229 // set a threshold. alternatively we could also activate automatic thresholding
230  if ( param_.edge_threshold > 0 ) {
231  trackerMultiMarker_->activateAutoThreshold ( false );
232  trackerMultiMarker_->setThreshold ( param_.edge_threshold );
233  } else {
234  trackerMultiMarker_->activateAutoThreshold ( true );
235  }
236 // let's use lookup-table undistortion for high-speed
237 // note: LUT only works with images up to 1024x1024
238  trackerMultiMarker_->setUndistortionMode ( ( ARToolKitPlus::UNDIST_MODE ) param_.undist_mode );
239 
240 // RPP is more robust than ARToolKit's standard pose estimator
241  trackerMultiMarker_->setPoseEstimator ( ( ARToolKitPlus::POSE_ESTIMATOR ) param_.pose_estimation_mode );
242 
243 // switch to simple ID based markers
244 // use the tool in tools/IdPatGen to generate markers
246 
247 // do the OpenGL camera setup
248 //glMatrixMode(GL_PROJECTION)
249 //glLoadMatrixf(tracker->getProjectionMatrix());
250 
251 }
252 
253 
254 void ARToolKitPlusNode::imageCallback ( const sensor_msgs::ImageConstPtr& image_msg, const sensor_msgs::CameraInfoConstPtr& camer_info_ ) {
256  if ( ( callback_counter_ % ( param_.skip_frames+1 ) ) != 0 ) {
257  return;
258  }
260  try {
262  } catch ( cv_bridge::Exception& e ) {
263  ROS_ERROR ( "cv_bridge exception: %s", e.what() );
264  return;
265  }
267  if ( trackerSingleMarker_ == NULL ) initTrackerSingleMarker ( camer_info_ );
268 
269  updateParameterTrackerSingleMarker ( camer_info_ );
270  ARToolKitPlus::ARMarkerInfo* arMarkerInfo;
271  int nNumMarkers;
272  int markerId = trackerSingleMarker_->calc ( img->image.data, param_.nPattern, param_.nUpdateMatrix, &arMarkerInfo, &nNumMarkers );
273  float conf = ( float ) trackerSingleMarker_->getConfidence();
274  arTags2D_.resize ( nNumMarkers );
275  for ( int i = 0; i < arTags2D_.size(); i++ ) {
276  arTags2D_[i] = arMarkerInfo[i];
277  }
278  }
280  if ( trackerMultiMarker_ == NULL ) initTrackerMultiMarker ( camer_info_ );
281  updateParameterTrackerMultiMarker ( camer_info_ );
282  int nNumMarkers = trackerMultiMarker_->calc ( img->image.data );
283 
284  arMultiMarkerInfo_ = trackerMultiMarker_->getMultiMarkerConfig();
285  arTags2D_.clear();
286  arTags2D_.reserve ( trackerMultiMarker_->getNumDetectedMarkers() );
288  for ( int i = 0; i < trackerMultiMarker_->getNumDetectedMarkers(); i++ ) {
289  const ARToolKitPlus::ARMarkerInfo &singleMarker = trackerMultiMarker_->getDetectedMarker ( i );
290  arTags2D_.push_back ( singleMarker );
291  arTags2D_.back().belongsToPattern = ARToolKitPlus::ARTag2D::NO_PATTERN;
292  for ( int j = 0; ( j < arMultiMarkerInfo_->marker_num ); j++ ) {
294  if ( singleMarker.id == multiMarker.patt_id ) {
295  arTags2D_.back().belongsToPattern = ARToolKitPlus::ARTag2D::PATTERN;
296  break;
297  }
298  }
299  }
300  }
301 
302  estimatePoses ( image_msg->header );
303 
304  if ( param_.publish_tf ) publishTf();
305  if ( param_.publish_markers ) publishMarkers( image_msg->header );
306 
307  if ( param_.show_camera_image ) {
308  cv::Mat img_debug;
309  cvtColor ( img->image, img_debug, CV_GRAY2BGR );
310  generateDebugImage ( img_debug );
311  cv::imshow ( param_.node_name + std::string ( " - debug" ), img_debug );
312  cv::waitKey ( 5 );
313  }
314 }
315 
316 void ARToolKitPlusNode::estimatePoses ( const std_msgs::Header &header ) {
317 
318  ARFloat center[2];
319  center[0] = 0;
320  center[1] = 0;
321  ARFloat pose[3][4];
322  tf::Transform trans;
324  char frame[0xFF];
325  markerTransforms_.clear();
326  markerTransformsID_.clear();
327 
328  if ( trackerMultiMarker_ ) {
329 
330  if ( arMultiMarkerInfo_->marker_num > 0 ) {
331  const ARFloat *p = trackerMultiMarker_->getModelViewMatrix();
332  for ( int r = 0; r < 3; r++ ) {
333  pose[r][0] = p[r+0];
334  pose[r][1] = p[r+4];
335  pose[r][2] = p[r+8];
336  pose[r][3] = p[r+12];
337  }
338  matrix2Tf ( pose, trans );
339  std::string child_frame = tf::resolve ( param_.tf_prefix, param_.pattern_frame );
340  st = tf::StampedTransform ( trans, header.stamp, header.frame_id, child_frame );
341  markerTransforms_.push_back ( st );
342  markerTransformsID_.push_back(-1);
343  }
344  }
345  for ( std::vector<ARToolKitPlus::ARTag2D>::iterator arTag = arTags2D_.begin(); arTag != arTags2D_.end(); arTag++ ) {
346  if ( arTag->id < 0 )
347  continue;
348  if ( arTag->belongsToPattern != ARToolKitPlus::ARTag2D::NO_PATTERN )
349  continue;
350  sprintf ( frame, "t%i", arTag->id );
351  if ( trackerMultiMarker_ ) trackerMultiMarker_->executeSingleMarkerPoseEstimator ( & ( *arTag ), center, param_.pattern_width, pose );
352  if ( trackerSingleMarker_ ) trackerSingleMarker_->executeSingleMarkerPoseEstimator ( & ( *arTag ), center, param_.pattern_width, pose );
353  sprintf ( frame, "t%i", arTag->id );
354  std::string child_frame = tf::resolve ( param_.tf_prefix, frame );
355 
356  if ( param_.plausibility_check ) {
357  double roll, pitch, yaw, z;
358  tf::Matrix3x3 R(pose[0][0], pose[0][1], pose[0][2],
359  pose[1][0], pose[1][1], pose[1][2],
360  pose[2][0], pose[2][1], pose[2][2]);
361 
362  R.getRPY(roll, pitch, yaw);
363  z = pose[2][3];
364 
365  if (std::isnan(roll) || std::isnan(pitch) || std::isnan(yaw))
366  continue;
367 
368  if ( z < 0.0001 ) {
369  if ( param_.plausibility_correction ) {
370  // TODO: add plausibility correction
371  } else continue;
372  }
373  }
374 
375  matrix2Tf ( pose, trans );
376  st = tf::StampedTransform ( trans, header.stamp, header.frame_id, child_frame );
377  markerTransforms_.push_back ( st );
378  markerTransformsID_.push_back(arTag->id);
379  }
380 }
381 
383  if ( param_.show_camera_image ) {
384  cv::namedWindow ( param_.node_name + std::string ( " - debug" ), 1 );
385  }
386 }
387 
388 
ARToolKitPlusNode(ros::NodeHandle &n)
std::vector< ARToolKitPlus::ARTag2D > arTags2D_
Definition: artoolkitplus.h:98
image_transport::ImageTransport imageTransport_
Definition: artoolkitplus.h:93
static const int PATTERN
Definition: artoolkitplus.h:47
ros::NodeHandle n_
Definition: artoolkitplus.h:90
void initTrackerSingleMarker(const sensor_msgs::CameraInfoConstPtr &camer_info_)
MyLogger * logger_
void publishMarkers(const std_msgs::Header &header)
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())
void updateParameterTrackerSingleMarker(const sensor_msgs::CameraInfoConstPtr &camer_info)
std::list< tf::StampedTransform > markerTransforms_
Definition: artoolkitplus.h:99
ARCamera(const sensor_msgs::CameraInfoConstPtr &_camer_info, int _undist_iterations, bool _input_distorted)
void imageCallback(const sensor_msgs::ImageConstPtr &image_msg, const sensor_msgs::CameraInfoConstPtr &info_msg)
void callbackParameters(tuw_artoolkitplus::ARParamConfig &config, uint32_t level)
TrackerSingleMarkerImpl implements the TrackerSingleMarker interface.
ARMultiEachMarkerInfoT * marker
Definition: arMulti.h:67
std::string resolve(const std::string &prefix, const std::string &frame_name)
dynamic_reconfigure::Server< tuw_artoolkitplus::ARParamConfig > reconfigureServer_
boost::shared_ptr< ARToolKitPlus::TrackerMultiMarker > trackerMultiMarker_
Definition: artoolkitplus.h:97
void artLog(const char *nStr)
Passes a simple string to the implementing instance.
CvImagePtr cvtColor(const CvImageConstPtr &source, const std::string &encoding)
virtual ~ARCamera()
void getRPY(tfScalar &roll, tfScalar &pitch, tfScalar &yaw, unsigned int solution_number=1) const
#define ROS_INFO(...)
ARFloat dist_factor[4]
std::vector< int > markerTransformsID_
TrackerMultiMarkerImpl implements the TrackerMultiMarker interface.
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
void updateParameterTrackerMultiMarker(const sensor_msgs::CameraInfoConstPtr &camer_info)
ARFileGrabber camera("dump_%02d.raw", CAM_W, CAM_H, 4)
ros::NodeHandle n_param_
Definition: artoolkitplus.h:91
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
boost::shared_ptr< ARToolKitPlus::TrackerSingleMarker > trackerSingleMarker_
Definition: artoolkitplus.h:96
ros::Publisher pub_markers_
static const int NO_PATTERN
Definition: artoolkitplus.h:46
image_transport::CameraSubscriber cameraSubscriber_
Definition: artoolkitplus.h:94
TFSIMD_FORCE_INLINE const tfScalar & z() const
void matrix2Tf(const ARFloat M[3][4], tf::Transform &transform)
void generateDebugImage(cv::Mat &img)
bool isInputDistorted()
ARToolKit::Logger specifies the interface for a logging application.
Definition: Logger.h:61
#define NULL
Definition: PocketKnife.h:38
void initTrackerMultiMarker(const sensor_msgs::CameraInfoConstPtr &camer_info_)
const ARToolKitPlus::ARMultiMarkerInfoT * arMultiMarkerInfo_
void estimatePoses(const std_msgs::Header &header)
dynamic_reconfigure::Server< tuw_artoolkitplus::ARParamConfig >::CallbackType reconfigureFnc_
float ARFloat
Definition: config.h:60
ARFloat mat[3][4]
#define ARTOOLKITPLUS_IMAGE_SRC
#define ROS_ERROR(...)


tuw_artoolkitplus
Author(s): Markus Bader
autogenerated on Sun Sep 4 2016 03:24:33