aruco_map.cpp
Go to the documentation of this file.
1 /*
2  * Detecting and pose estimation of ArUco markers maps
3  * Copyright (C) 2018 Copter Express Technologies
4  *
5  * Author: Oleg Kalachev <okalachev@gmail.com>
6  *
7  * Distributed under MIT License (available at https://opensource.org/licenses/MIT).
8  * The above copyright notice and this permission notice shall be included in all
9  * copies or substantial portions of the Software.
10  */
11 
12 /*
13  * Code is based on https://github.com/UbiquityRobotics/fiducials, which is distributed
14  * under the BSD license.
15  */
16 
17 #include <math.h>
18 #include <string>
19 #include <vector>
20 #include <fstream>
21 #include <algorithm>
22 #include <ros/ros.h>
23 #include <nodelet/nodelet.h>
26 #include <cv_bridge/cv_bridge.h>
27 #include <tf/transform_datatypes.h>
28 #include <tf2_ros/buffer.h>
36 #include <geometry_msgs/TransformStamped.h>
37 #include <geometry_msgs/PoseWithCovarianceStamped.h>
38 #include <sensor_msgs/Image.h>
39 #include <visualization_msgs/Marker.h>
40 #include <visualization_msgs/MarkerArray.h>
41 
42 #include <aruco_pose/MarkerArray.h>
43 #include <aruco_pose/Marker.h>
44 
45 #include <opencv2/opencv.hpp>
46 #include <opencv2/aruco.hpp>
47 
48 #include "draw.h"
49 #include "utils.h"
50 
51 using std::vector;
52 using cv::Mat;
53 using sensor_msgs::Image;
54 using sensor_msgs::CameraInfo;
55 using aruco_pose::MarkerArray;
56 
58 
59 class ArucoMap : public nodelet::Nodelet {
60 private:
67  cv::Ptr<cv::aruco::Board> board_;
69  geometry_msgs::TransformStamped transform_;
70  geometry_msgs::PoseWithCovarianceStamped pose_;
71  vector<geometry_msgs::TransformStamped> markers_transforms_;
72  aruco_pose::MarkerArray markers_;
77  visualization_msgs::MarkerArray vis_array_;
81 
82 public:
83  virtual void onInit()
84  {
87 
88  image_transport::ImageTransport it_priv(nh_priv_);
89 
90  // TODO: why image_transport doesn't work here?
91  img_pub_ = nh_priv_.advertise<sensor_msgs::Image>("image", 1, true);
92  markers_pub_ = nh_priv_.advertise<aruco_pose::MarkerArray>("markers", 1, true);
93 
94  board_ = cv::makePtr<cv::aruco::Board>();
95  board_->dictionary = cv::aruco::getPredefinedDictionary(
96  static_cast<cv::aruco::PREDEFINED_DICTIONARY_NAME>(nh_priv_.param("dictionary", 2)));
97  camera_matrix_ = cv::Mat::zeros(3, 3, CV_64F);
98 
99  std::string type, map;
100  type = nh_priv_.param<std::string>("type", "map");
101  transform_.child_frame_id = nh_priv_.param<std::string>("frame_id", "aruco_map");
102  known_tilt_ = nh_priv_.param<std::string>("known_tilt", "");
103  auto_flip_ = nh_priv_.param("auto_flip", false);
104  image_width_ = nh_priv_.param("image_width" , 2000);
105  image_height_ = nh_priv_.param("image_height", 2000);
106  image_margin_ = nh_priv_.param("image_margin", 200);
107  image_axis_ = nh_priv_.param("image_axis", true);
108  markers_parent_frame_ = nh_priv_.param<std::string>("markers/frame_id", transform_.child_frame_id);
109  markers_frame_ = nh_priv_.param<std::string>("markers/child_frame_id_prefix", "");
110 
111  // createStripLine();
112 
113  if (type == "map") {
114  param(nh_priv_, "map", map);
115  loadMap(map);
116  } else if (type == "gridboard") {
117  createGridBoard(nh_priv_);
118  } else {
119  NODELET_FATAL("unknown type: %s", type.c_str());
120  ros::shutdown();
121  }
122 
123  pose_pub_ = nh_priv_.advertise<geometry_msgs::PoseWithCovarianceStamped>("pose", 1);
124  vis_markers_pub_ = nh_priv_.advertise<visualization_msgs::MarkerArray>("visualization", 1, true);
125  debug_pub_ = it_priv.advertise("debug", 1);
126 
127  image_sub_.subscribe(nh_, "image_raw", 1);
128  info_sub_.subscribe(nh_, "camera_info", 1);
129  markers_sub_.subscribe(nh_, "markers", 1);
130 
131  sync_.reset(new message_filters::Synchronizer<SyncPolicy>(SyncPolicy(10), image_sub_, info_sub_, markers_sub_));
132  sync_->registerCallback(boost::bind(&ArucoMap::callback, this, _1, _2, _3));
133 
135  publishMarkers();
136  publishMapImage();
137  vis_markers_pub_.publish(vis_array_);
138 
139  NODELET_INFO("ready");
140  }
141 
142  void callback(const sensor_msgs::ImageConstPtr& image,
143  const sensor_msgs::CameraInfoConstPtr& cinfo,
144  const aruco_pose::MarkerArrayConstPtr& markers)
145  {
146  int valid = 0;
147  int count = markers->markers.size();
148  std::vector<int> ids;
149  std::vector<std::vector<cv::Point2f>> corners;
150  cv::Vec3d rvec, tvec;
151 
152  parseCameraInfo(cinfo, camera_matrix_, dist_coeffs_);
153  if (markers->markers.empty()) goto publish_debug;
154 
155  ids.reserve(count);
156  corners.reserve(count);
157 
158  for(auto const &marker : markers->markers) {
159  ids.push_back(marker.id);
160  std::vector<cv::Point2f> marker_corners = {
161  cv::Point2f(marker.c1.x, marker.c1.y),
162  cv::Point2f(marker.c2.x, marker.c2.y),
163  cv::Point2f(marker.c3.x, marker.c3.y),
164  cv::Point2f(marker.c4.x, marker.c4.y)
165  };
166  corners.push_back(marker_corners);
167  }
168 
169  if (known_tilt_.empty()) {
170  // simple estimation
171  valid = cv::aruco::estimatePoseBoard(corners, ids, board_, camera_matrix_, dist_coeffs_,
172  rvec, tvec, false);
173  if (!valid) goto publish_debug;
174 
175  transform_.header.stamp = markers->header.stamp;
176  transform_.header.frame_id = markers->header.frame_id;
177  pose_.header = transform_.header;
178  fillPose(pose_.pose.pose, rvec, tvec);
179  fillTransform(transform_.transform, rvec, tvec);
180 
181  } else {
182  Mat obj_points, img_points;
183  // estimation with "snapping"
184  cv::aruco::getBoardObjectAndImagePoints(board_, corners, ids, obj_points, img_points);
185  if (obj_points.empty()) goto publish_debug;
186 
187  double center_x = 0, center_y = 0, center_z = 0;
188  alignObjPointsToCenter(obj_points, center_x, center_y, center_z);
189 
190  valid = solvePnP(obj_points, img_points, camera_matrix_, dist_coeffs_, rvec, tvec, false);
191  if (!valid) goto publish_debug;
192 
193  fillTransform(transform_.transform, rvec, tvec);
194  try {
195  geometry_msgs::TransformStamped snap_to = tf_buffer_.lookupTransform(markers->header.frame_id,
196  known_tilt_, markers->header.stamp, ros::Duration(0.02));
197  snapOrientation(transform_.transform.rotation, snap_to.transform.rotation, auto_flip_);
198  } catch (const tf2::TransformException& e) {
199  NODELET_WARN_THROTTLE(1, "can't snap: %s", e.what());
200  }
201 
202  geometry_msgs::TransformStamped shift;
203  shift.transform.translation.x = -center_x;
204  shift.transform.translation.y = -center_y;
205  shift.transform.translation.z = -center_z;
206  shift.transform.rotation.w = 1;
207  tf2::doTransform(shift, transform_, transform_);
208 
209  // for debug topic
210  tvec[0] = transform_.transform.translation.x;
211  tvec[1] = transform_.transform.translation.y;
212  tvec[2] = transform_.transform.translation.z;
213 
214  transform_.header.stamp = markers->header.stamp;
215  transform_.header.frame_id = markers->header.frame_id;
216  pose_.header = transform_.header;
217  transformToPose(transform_.transform, pose_.pose.pose);
218  }
219 
220  if (!transform_.child_frame_id.empty()) {
221  br_.sendTransform(transform_);
222  }
223  pose_pub_.publish(pose_);
224 
225 publish_debug:
226  // publish debug image (even if no map detected)
227  if (debug_pub_.getNumSubscribers() > 0) {
228  Mat mat = cv_bridge::toCvCopy(image, "bgr8")->image; // copy image as we're planning to modify it
229  cv::aruco::drawDetectedMarkers(mat, corners, ids); // draw detected markers
230  if (valid) {
231  _drawAxis(mat, camera_matrix_, dist_coeffs_, rvec, tvec, 1.0); // draw board axis
232  }
233  cv_bridge::CvImage out_msg;
234  out_msg.header.frame_id = image->header.frame_id;
235  out_msg.header.stamp = image->header.stamp;
237  out_msg.image = mat;
238  debug_pub_.publish(out_msg.toImageMsg());
239  }
240  }
241 
242  void alignObjPointsToCenter(Mat &obj_points, double &center_x, double &center_y, double &center_z) const
243  {
244  // Align object points to the center of mass
245  double sum_x = 0;
246  double sum_y = 0;
247  double sum_z = 0;
248 
249  for (int i = 0; i < obj_points.rows; i++) {
250  sum_x += obj_points.at<float>(i, 0);
251  sum_y += obj_points.at<float>(i, 1);
252  sum_z += obj_points.at<float>(i, 2);
253  }
254 
255  center_x = sum_x / obj_points.rows;
256  center_y = sum_y / obj_points.rows;
257  center_z = sum_z / obj_points.rows;
258 
259  for (int i = 0; i < obj_points.rows; i++) {
260  obj_points.at<float>(i, 0) -= center_x;
261  obj_points.at<float>(i, 1) -= center_y;
262  obj_points.at<float>(i, 2) -= center_z;
263  }
264  }
265 
266  void loadMap(std::string filename)
267  {
268  std::ifstream f(filename);
269  std::string line;
270 
271  if (!f.good()) {
272  NODELET_FATAL("%s - %s", strerror(errno), filename.c_str());
273  ros::shutdown();
274  }
275 
276  while (std::getline(f, line)) {
277  int id;
278  double length, x, y, z, yaw, pitch, roll;
279 
280  std::istringstream s(line);
281 
282  // Read first character to see whether it's a comment
283  char first = 0;
284  if (!(s >> first)) {
285  // No non-whitespace characters, must be a blank line
286  continue;
287  }
288 
289  if (first == '#') {
290  NODELET_DEBUG("Skipping line as a comment: %s", line.c_str());
291  continue;
292  } else if (isdigit(first)) {
293  // Put the digit back into the stream
294  // Note that this is a non-modifying putback, so this should work with istreams
295  // (see https://en.cppreference.com/w/cpp/io/basic_istream/putback)
296  s.putback(first);
297  } else {
298  // Probably garbage data; inform user and throw an exception, possibly killing nodelet
299  NODELET_FATAL("Malformed input: %s", line.c_str());
300  ros::shutdown();
301  throw std::runtime_error("Malformed input");
302  }
303 
304  if (!(s >> id >> length >> x >> y)) {
305  NODELET_ERROR("Not enough data in line: %s; "
306  "Each marker must have at least id, length, x, y fields", line.c_str());
307  continue;
308  }
309  // Be less strict about z, yaw, pitch roll
310  if (!(s >> z)) {
311  NODELET_DEBUG("No z coordinate provided for marker %d, assuming 0", id);
312  z = 0;
313  }
314  if (!(s >> yaw)) {
315  NODELET_DEBUG("No yaw provided for marker %d, assuming 0", id);
316  yaw = 0;
317  }
318  if (!(s >> pitch)) {
319  NODELET_DEBUG("No pitch provided for marker %d, assuming 0", id);
320  pitch = 0;
321  }
322  if (!(s >> roll)) {
323  NODELET_DEBUG("No roll provided for marker %d, assuming 0", id);
324  roll = 0;
325  }
326  addMarker(id, length, x, y, z, yaw, pitch, roll);
327  }
328 
329  NODELET_INFO("loading %s complete (%d markers)", filename.c_str(), static_cast<int>(board_->ids.size()));
330  }
331 
333  {
334  NODELET_INFO("generate gridboard");
335  NODELET_WARN("gridboard maps are deprecated");
336 
337  int markers_x, markers_y, first_marker;
338  double markers_side, markers_sep_x, markers_sep_y;
339  std::vector<int> marker_ids;
340  markers_x = nh.param("markers_x", 10);
341  markers_y = nh.param("markers_y", 10);
342  first_marker = nh.param("first_marker", 0);
343 
344  param(nh, "markers_side", markers_side);
345  param(nh, "markers_sep_x", markers_sep_x);
346  param(nh, "markers_sep_y", markers_sep_y);
347 
348  if (nh.getParam("marker_ids", marker_ids)) {
349  if ((unsigned int)(markers_x * markers_y) != marker_ids.size()) {
350  NODELET_FATAL("~marker_ids length should be equal to ~markers_x * ~markers_y");
351  ros::shutdown();
352  }
353  } else {
354  // Fill marker_ids automatically
355  marker_ids.resize(markers_x * markers_y);
356  for (int i = 0; i < markers_x * markers_y; i++)
357  {
358  marker_ids.at(i) = first_marker++;
359  }
360  }
361 
362  double max_y = markers_y * markers_side + (markers_y - 1) * markers_sep_y;
363  for(int y = 0; y < markers_y; y++) {
364  for(int x = 0; x < markers_x; x++) {
365  double x_pos = x * (markers_side + markers_sep_x);
366  double y_pos = max_y - y * (markers_side + markers_sep_y) - markers_side;
367  NODELET_INFO("add marker %d %g %g", marker_ids[y * markers_y + x], x_pos, y_pos);
368  addMarker(marker_ids[y * markers_y + x], markers_side, x_pos, y_pos, 0, 0, 0, 0);
369  }
370  }
371  }
372 
373  // void createStripLine()
374  // {
375  // visualization_msgs::Marker marker;
376  // marker.header.frame_id = transform_.child_frame_id;
377  // marker.action = visualization_msgs::Marker::ADD;
378  // marker.ns = "aruco_map_link";
379  // marker.type = visualization_msgs::Marker::LINE_STRIP;
380  // marker.scale.x = 0.02;
381  // marker.color.g = 1;
382  // marker.color.a = 0.8;
383  // marker.frame_locked = true;
384  // marker.pose.orientation.w = 1;
385  // vis_array_.markers.push_back(marker);
386  // }
387 
388  void addMarker(int id, double length, double x, double y, double z,
389  double yaw, double pitch, double roll)
390  {
391  // Check whether the id is in range for current dictionary
392  int num_markers = board_->dictionary->bytesList.rows;
393  if (num_markers <= id) {
394  NODELET_ERROR("Marker id %d is not in dictionary; current dictionary contains %d markers. "
395  "Please see https://github.com/CopterExpress/clover/blob/master/aruco_pose/README.md#parameters for details",
396  id, num_markers);
397  return;
398  }
399  // Check if marker is already in the board
400  if (std::count(board_->ids.begin(), board_->ids.end(), id) > 0) {
401  NODELET_ERROR("Marker id %d is already in the map", id);
402  return;
403  }
404  // Create transform
405  tf::Quaternion q;
406  q.setRPY(roll, pitch, yaw);
407  tf::Transform transform(q, tf::Vector3(x, y, z));
408 
409  /* marker's corners:
410  0 1
411  3 2
412  */
413  double halflen = length / 2;
414  tf::Point p0(-halflen, halflen, 0);
415  tf::Point p1(halflen, halflen, 0);
416  tf::Point p2(halflen, -halflen, 0);
417  tf::Point p3(-halflen, -halflen, 0);
418  p0 = transform * p0;
419  p1 = transform * p1;
420  p2 = transform * p2;
421  p3 = transform * p3;
422 
423  vector<cv::Point3f> obj_points = {
424  cv::Point3f(p0.x(), p0.y(), p0.z()),
425  cv::Point3f(p1.x(), p1.y(), p1.z()),
426  cv::Point3f(p2.x(), p2.y(), p2.z()),
427  cv::Point3f(p3.x(), p3.y(), p3.z())
428  };
429 
430  board_->ids.push_back(id);
431  board_->objPoints.push_back(obj_points);
432 
433  // Add marker's static transform
434  if (!markers_frame_.empty()) {
435  geometry_msgs::TransformStamped marker_transform;
436  marker_transform.header.frame_id = markers_parent_frame_;
437  marker_transform.child_frame_id = markers_frame_ + std::to_string(id);
438  tf::transformTFToMsg(transform, marker_transform.transform);
439  markers_transforms_.push_back(marker_transform);
440  }
441 
442  // Add marker to array
443  aruco_pose::Marker marker;
444  marker.id = id;
445  marker.length = length;
446  marker.pose.position.x = x;
447  marker.pose.position.y = y;
448  marker.pose.position.z = z;
449  tf::quaternionTFToMsg(q, marker.pose.orientation);
450  markers_.markers.push_back(marker);
451 
452  // Add visualization marker
453  visualization_msgs::Marker vis_marker;
454  vis_marker.header.frame_id = transform_.child_frame_id;
455  vis_marker.action = visualization_msgs::Marker::ADD;
456  vis_marker.id = vis_array_.markers.size();
457  vis_marker.ns = "aruco_map_marker";
458  vis_marker.type = visualization_msgs::Marker::CUBE;
459  vis_marker.scale.x = length;
460  vis_marker.scale.y = length;
461  vis_marker.scale.z = 0.001;
462  vis_marker.color.r = 1;
463  vis_marker.color.g = 0.5;
464  vis_marker.color.b = 0.5;
465  vis_marker.color.a = 0.8;
466  vis_marker.pose.position.x = x;
467  vis_marker.pose.position.y = y;
468  vis_marker.pose.position.z = z;
469  tf::quaternionTFToMsg(q, marker.pose.orientation);
470  vis_marker.frame_locked = true;
471  vis_array_.markers.push_back(vis_marker);
472 
473  // Add linking line
474  // geometry_msgs::Point p;
475  // p.x = x;
476  // p.y = y;
477  // p.z = z;
478  // vis_array_.markers.at(0).points.push_back(p);
479  }
480 
482  {
483  if (!markers_transforms_.empty()) {
484  static_br_.sendTransform(markers_transforms_);
485  }
486  }
487 
489  {
490  markers_pub_.publish(markers_);
491  }
492 
494  {
495  cv::Size size(image_width_, image_height_);
496  cv::Mat image;
497  cv_bridge::CvImage msg;
498 
499  if (!board_->ids.empty()) {
500  _drawPlanarBoard(board_, size, image, image_margin_, 1, image_axis_);
502  } else {
503  // empty map
504  image.create(size, CV_8UC1);
505  image.setTo(cv::Scalar::all(255));
507  }
508 
509  msg.image = image;
510  img_pub_.publish(msg.toImageMsg());
511  }
512 };
513 
void publishMarkers()
Definition: aruco_map.cpp:488
void loadMap(std::string filename)
Definition: aruco_map.cpp:266
CV_EXPORTS_W void getBoardObjectAndImagePoints(const Ptr< Board > &board, InputArrayOfArrays detectedCorners, InputArray detectedIds, OutputArray objPoints, OutputArray imgPoints)
Given a board configuration and a set of detected markers, returns the corresponding image points and...
Definition: aruco.cpp:1253
ros::Publisher img_pub_
Definition: aruco_map.cpp:61
void snapOrientation(geometry_msgs::Quaternion &to, const geometry_msgs::Quaternion &from, bool auto_flip=false)
Definition: utils.h:110
Mat camera_matrix_
Definition: aruco_map.cpp:68
#define NODELET_ERROR(...)
aruco_pose::MarkerArray markers_
Definition: aruco_map.cpp:72
void createGridBoard(ros::NodeHandle &nh)
Definition: aruco_map.cpp:332
#define NODELET_WARN(...)
static void param(ros::NodeHandle nh, const std::string &param_name, T &param_val)
Definition: utils.h:25
markers_x
Definition: genmap.py:46
bool auto_flip_
Definition: aruco_map.cpp:80
f
uint32_t getNumSubscribers() const
void callback(const sensor_msgs::ImageConstPtr &image, const sensor_msgs::CameraInfoConstPtr &cinfo, const aruco_pose::MarkerArrayConstPtr &markers)
Definition: aruco_map.cpp:142
ros::NodeHandle & getNodeHandle() const
std::string known_tilt_
Definition: aruco_map.cpp:78
void fillPose(geometry_msgs::Pose &pose, const cv::Vec3d &rvec, const cv::Vec3d &tvec)
Definition: utils.h:59
XmlRpcServer s
void addMarker(int id, double length, double x, double y, double z, double yaw, double pitch, double roll)
Definition: aruco_map.cpp:388
std::string encoding
Publisher advertise(const std::string &base_topic, uint32_t queue_size, bool latch=false)
bool image_axis_
Definition: aruco_map.cpp:80
message_filters::Subscriber< Image > image_sub_
Definition: aruco_map.cpp:63
virtual void onInit()
Definition: aruco_map.cpp:83
int image_margin_
Definition: aruco_map.cpp:79
ros::NodeHandle & getPrivateNodeHandle() const
tf::Vector3 Point
void doTransform(const T &data_in, T &data_out, const geometry_msgs::TransformStamped &transform)
static void parseCameraInfo(const sensor_msgs::CameraInfoConstPtr &cinfo, cv::Mat &matrix, cv::Mat &dist)
Definition: utils.h:33
length
Definition: genmap.py:42
ros::Publisher pose_pub_
Definition: aruco_map.cpp:61
max_y
Definition: genmap.py:52
void publishMapImage()
Definition: aruco_map.cpp:493
tf2_ros::Buffer tf_buffer_
Definition: aruco_map.cpp:75
CV_EXPORTS Ptr< Dictionary > getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME name)
Returns one of the predefined dictionaries defined in PREDEFINED_DICTIONARY_NAME. ...
Definition: dictionary.cpp:301
sensor_msgs::ImagePtr toImageMsg() const
bool param(const std::string &param_name, T &param_val, const T &default_val) const
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
void publish(const boost::shared_ptr< M > &message) const
void _drawAxis(InputOutputArray _image, InputArray _cameraMatrix, InputArray _distCoeffs, InputArray _rvec, InputArray _tvec, float length)
Definition: draw.cpp:176
#define NODELET_WARN_THROTTLE(rate,...)
markers_y
Definition: genmap.py:47
void setRPY(const tfScalar &roll, const tfScalar &pitch, const tfScalar &yaw)
bool getParam(const std::string &key, std::string &s) const
int image_height_
Definition: aruco_map.cpp:79
tf2_ros::TransformBroadcaster br_
Definition: aruco_map.cpp:73
static void quaternionTFToMsg(const Quaternion &bt, geometry_msgs::Quaternion &msg)
int image_width_
Definition: aruco_map.cpp:79
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
geometry_msgs::TransformStamped transform_
Definition: aruco_map.cpp:69
image_transport::Publisher debug_pub_
Definition: aruco_map.cpp:62
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
Mat dist_coeffs_
Definition: aruco_map.cpp:68
void sendTransform(const geometry_msgs::TransformStamped &transform)
void publish(const sensor_msgs::Image &message) const
vector< geometry_msgs::TransformStamped > markers_transforms_
Definition: aruco_map.cpp:71
std::string markers_parent_frame_
Definition: aruco_map.cpp:78
#define NODELET_INFO(...)
void transformToPose(const geometry_msgs::Transform &transform, geometry_msgs::Pose &pose)
Definition: utils.h:131
cv::Ptr< cv::aruco::Board > board_
Definition: aruco_map.cpp:67
CV_EXPORTS_W void drawDetectedMarkers(InputOutputArray image, InputArrayOfArrays corners, InputArray ids=noArray(), Scalar borderColor=Scalar(0, 255, 0))
Draw detected markers in image.
Definition: aruco.cpp:1702
boost::shared_ptr< message_filters::Synchronizer< SyncPolicy > > sync_
Definition: aruco_map.cpp:66
void subscribe(ros::NodeHandle &nh, const std::string &topic, uint32_t queue_size, const ros::TransportHints &transport_hints=ros::TransportHints(), ros::CallbackQueueInterface *callback_queue=0)
ros::Publisher markers_pub_
Definition: aruco_map.cpp:61
message_filters::Subscriber< MarkerArray > markers_sub_
Definition: aruco_map.cpp:65
CV_EXPORTS_W int estimatePoseBoard(InputArrayOfArrays corners, InputArray ids, const Ptr< Board > &board, InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec, bool useExtrinsicGuess=false)
Pose estimation for a board of markers.
Definition: aruco.cpp:1596
InputArray ids
Definition: aruco.hpp:569
message_filters::Subscriber< CameraInfo > info_sub_
Definition: aruco_map.cpp:64
ROSCPP_DECL void shutdown()
geometry_msgs::PoseWithCovarianceStamped pose_
Definition: aruco_map.cpp:70
void publishMarkersFrames()
Definition: aruco_map.cpp:481
void _drawPlanarBoard(Board *_board, Size outSize, OutputArray _img, int marginSize, int borderBits, bool drawAxis)
Definition: draw.cpp:26
#define NODELET_FATAL(...)
void sendTransform(const geometry_msgs::TransformStamped &transform)
tf2_ros::TransformListener tf_listener_
Definition: aruco_map.cpp:76
std::string markers_frame_
Definition: aruco_map.cpp:78
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
std::string map_
Definition: aruco_map.cpp:78
#define NODELET_DEBUG(...)
static void transformTFToMsg(const Transform &bt, geometry_msgs::Transform &msg)
NodeHandlePtr nh_
tf2_ros::StaticTransformBroadcaster static_br_
Definition: aruco_map.cpp:74
void fillTransform(geometry_msgs::Transform &transform, const cv::Vec3d &rvec, const cv::Vec3d &tvec)
Definition: utils.h:77
void alignObjPointsToCenter(Mat &obj_points, double &center_x, double &center_y, double &center_z) const
Definition: aruco_map.cpp:242
std_msgs::Header header
message_filters::sync_policies::ExactTime< Image, CameraInfo, MarkerArray > SyncPolicy
Definition: aruco_map.cpp:57
visualization_msgs::MarkerArray vis_array_
Definition: aruco_map.cpp:77
first
Definition: genmap.py:43
ros::Publisher vis_markers_pub_
Definition: aruco_map.cpp:61


aruco_pose
Author(s): Oleg Kalachev
autogenerated on Mon Feb 28 2022 22:08:24