aruco_marker_recognition.cpp
Go to the documentation of this file.
1 
19 #include <cv_bridge/cv_bridge.h>
21 #include <ros_uri/ros_uri.hpp>
22 #include <Tracking/ICP.h>
23 
24 #include "opencv2/imgproc/imgproc.hpp"
25 #include "opencv2/highgui/highgui.hpp"
26 
27 
28 namespace aruco_marker_recognition {
29 
30 typedef boost::array< ::geometry_msgs::Point_<std::allocator<void> > , 8> BoundingBox;
31 
32 ArucoMarkerRecognition::ArucoMarkerRecognition() : nh_(NODE_NAME), marker_size_(DEFAULT_MARKER_SIZE), recognition_paused_(true)
33 {
34  ROS_DEBUG("Initializing recognition system");
35  nh_.getParam("use_stereo", use_stereo_);
36 
37  nh_.getParam("image_left_topic", image_left_topic_);
38  nh_.getParam("image_right_topic", image_right_topic_);
39  nh_.getParam("image_left_cam_info_topic", image_left_cam_info_topic_);
40  nh_.getParam("image_right_cam_info_topic", image_right_cam_info_topic_);
41 
42  // Set up dynamic reconfigure
43  reconfigure_server_.setCallback(boost::bind(&ArucoMarkerRecognition::configCallback, this, _1, _2));
44 
45  nh_.getParam("marker_size", marker_size_);
47 
48  ROS_DEBUG("Subscribe to image topics");
51 
52  if (use_stereo_) {
55  } else {
58  }
59 
61  sync_policy_->registerCallback(boost::bind(&ArucoMarkerRecognition::imageCallback, this, _1, _2, _3, _4));
62 
63  ROS_DEBUG("Advertise services");
66 
67  object_mesh_service_client_ = nh_.serviceClient<asr_object_database::ObjectMetaData>(OBJECT_DB_SERVICE_META_DATA);
68 
69  std::string left_markers_img_topic;
70  std::string right_markers_img_topic;
71  std::string asr_objects_topic;
72  nh_.getParam("left_markers_img_topic", left_markers_img_topic);
73  nh_.getParam("right_markers_img_topic", right_markers_img_topic);
74  nh_.getParam("asr_objects_topic", asr_objects_topic);
75  left_markers_img_pub_ = nh_.advertise<sensor_msgs::Image> (left_markers_img_topic, 10);
76  if (use_stereo_) {
77  right_markers_img_pub_ = nh_.advertise<sensor_msgs::Image> (right_markers_img_topic, 10);
78  }
79  asr_objects_pub_ = nh_.advertise<asr_msgs::AsrObject> (asr_objects_topic, 10);
80 
81  std::string vis_markers_topic;
82  nh_.getParam("vis_markers_topic", vis_markers_topic);
83  vis_markers_pub_ = nh_.advertise<visualization_msgs::Marker> (vis_markers_topic, 10);
84 
85  nh_.getParam("recognizer_name", recognizer_name_);
86 
87  ROS_DEBUG("Initializing completed");
88 
89  ROS_DEBUG("Recognition is paused");
90 
91 }
92 
93 bool ArucoMarkerRecognition::processGetRecognizerRequest(GetRecognizer::Request &req, GetRecognizer::Response &res) {
94  ROS_DEBUG("Process get recognizer request");
95  recognition_paused_ = false;
96  ROS_DEBUG("Recognition is running");
97  return true;
98 }
99 
100 bool ArucoMarkerRecognition::processReleaseRecognizerRequest(ReleaseRecognizer::Request &req, ReleaseRecognizer::Response &res) {
101  ROS_DEBUG("Process release recognizer request");
102  recognition_paused_ = true;
103  ROS_DEBUG("Recognition is paused");
104  return true;
105 }
106 
107 void ArucoMarkerRecognition::imageCallback(const sensor_msgs::ImageConstPtr& input_img_left, const sensor_msgs::ImageConstPtr& input_img_right, const sensor_msgs::CameraInfoConstPtr& cam_info_left, const sensor_msgs::CameraInfoConstPtr& cam_info_right) {
108  if (!recognition_paused_) {
109  ROS_DEBUG("Images received");
110  cv_bridge::CvImagePtr cv_left;
111  cv_bridge::CvImagePtr cv_right;
112  try {
113  cv_left = cv_bridge::toCvCopy(input_img_left, sensor_msgs::image_encodings::BGR8);
114  cv_right = cv_bridge::toCvCopy(input_img_right, sensor_msgs::image_encodings::BGR8);
115  } catch (cv_bridge::Exception& e) {
116  ROS_ERROR("Cv_bridge exception: %s", e.what());
117  return;
118  }
119  cv::Mat img;
120  cv::GaussianBlur(cv_left->image, img, cv::Size(0, 0), config_.gaussianBlurSigma);
121  cv::addWeighted(cv_left->image, config_.sharpenWeightImage, img, config_.sharpenWeightBlur, 0, cv_left->image);
122 
123  cv::GaussianBlur(cv_right->image, img, cv::Size(0, 0), config_.gaussianBlurSigma);
124  cv::addWeighted(cv_right->image, config_.sharpenWeightImage, img, config_.sharpenWeightBlur, 0, cv_right->image);
125 
126  detector_.setCameraParameters(*cam_info_left, *cam_info_right);
127 
128  std::vector<aruco::Marker> left_markers = detector_.detect(cv_left->image, MarkerDetection::CameraId::cam_left, config_);
129  std::vector<aruco::Marker> right_markers;
130  std::map<int, geometry_msgs::Pose> idPoseMap;
131  if (use_stereo_) {
132  right_markers = detector_.detect(cv_right->image, MarkerDetection::CameraId::cam_right, config_);
133 
134  ivt_bridge::IvtStereoCalibration ivtCalib;
135  ivtCalib.fromCameraInfo(cam_info_left, cam_info_right);
136 
137  idPoseMap = getMarkerPoses(left_markers, right_markers, ivtCalib);
138  } else {
139  idPoseMap = getMarkerPoses(left_markers);
140  }
141  std::string cam_left_frame_id = "/" + cam_info_left->header.frame_id;
142 
143  //publish marker visualizations
144  int marker_id = 1;
145  for (auto it = idPoseMap.begin(); it != idPoseMap.end(); ++it) {
146  vis_markers_pub_.publish(createSquareMarker(marker_id, it->second, cam_left_frame_id));
147  vis_markers_pub_.publish(createArrowMarker(marker_id, it->second, cam_left_frame_id));
148  vis_markers_pub_.publish(createArrowMarker(marker_id, it->second, cam_left_frame_id, true));
149  ++marker_id;
150  }
151 
152  //publish marker mesh visualizations & asr-objects
153  int id = 0;
154  for (auto idPosePair : idPoseMap) {
155  std::string object_type = "marker_" + std::to_string(idPosePair.first);
156  asr_object_database::ObjectMetaData objectMetaData;
157  objectMetaData.request.object_type = object_type;
158  objectMetaData.request.recognizer = recognizer_name_;
159  object_mesh_service_client_.call(objectMetaData);
160 
161  if (objectMetaData.response.is_valid) {
162  vis_markers_pub_.publish(createMeshMarker(id, idPosePair.second, objectMetaData.response.object_mesh_resource, cam_left_frame_id));
163  asr_objects_pub_.publish(createAsrObject(idPosePair.second, object_type, cam_left_frame_id, objectMetaData.response.object_mesh_resource));
164  id++;
165  } else {
166  asr_objects_pub_.publish(createAsrObject(idPosePair.second, object_type, cam_left_frame_id));
167  }
168  }
169 
170 
171  //publish images with marker overlay
172  cv_left->image = drawMarkers(cv_left->image, left_markers);
173  left_markers_img_pub_.publish(cv_left->toImageMsg());
174 
175  if (use_stereo_) {
176  cv_right->image = drawMarkers(cv_right->image, right_markers);
177  right_markers_img_pub_.publish(cv_right->toImageMsg());
178  }
179  ROS_DEBUG("--------------\n");
180  }
181 }
182 
183 void ArucoMarkerRecognition::configCallback(ArucoMarkerRecognitionConfig &config, uint32_t level) {
184  this->config_ = config;
185 }
186 
187 cv::Mat ArucoMarkerRecognition::drawMarkers(const cv::Mat &image, const std::vector<aruco::Marker> &markers) {
188  cv::Mat output = image;
189  for (unsigned int i = 0; i < markers.size(); i++) {
190  markers[i].draw(output, cv::Scalar(0, 0, 255), 2);
191  }
192  return output;
193 }
194 
195 std::map<int, geometry_msgs::Pose> ArucoMarkerRecognition::getMarkerPoses(const std::vector<aruco::Marker> &left_markers) {
196  std::map<int, geometry_msgs::Pose> idPoseMap;
197  for (aruco::Marker marker : left_markers) {
198  geometry_msgs::Pose pose;
199  pose.position.x = marker.Tvec.at<float>(0,0);
200  pose.position.y = marker.Tvec.at<float>(1,0);
201  pose.position.z = marker.Tvec.at<float>(2,0);
202 
203  cv::Mat rot_cv(3, 3, CV_32FC1);
204  cv::Rodrigues(marker.Rvec, rot_cv);
205 
206  cv::Mat rotate_to_ros(3, 3, CV_32FC1);
207  // 0 1 0
208  // 0 0 -1
209  // -1 0 0
210  rotate_to_ros.at<float>(0,0) = 0.0;
211  rotate_to_ros.at<float>(0,1) = 1.0;
212  rotate_to_ros.at<float>(0,2) = 0.0;
213  rotate_to_ros.at<float>(1,0) = 0.0;
214  rotate_to_ros.at<float>(1,1) = 0.0;
215  rotate_to_ros.at<float>(1,2) = -1.0;
216  rotate_to_ros.at<float>(2,0) = -1.0;
217  rotate_to_ros.at<float>(2,1) = 0.0;
218  rotate_to_ros.at<float>(2,2) = 0.0;
219  rot_cv = rot_cv*rotate_to_ros.t();
220 
221  float q4 = 0.5f * sqrt(1.0f + rot_cv.at<float>(0,0) + rot_cv.at<float>(1,1) + rot_cv.at<float>(2,2));
222  float t = (1.0f / (4.0f * q4));
223  float q1 = t * (rot_cv.at<float>(2,1) - rot_cv.at<float>(1,2));
224  float q2 = t * (rot_cv.at<float>(0,2) - rot_cv.at<float>(2,0));
225  float q3 = t * (rot_cv.at<float>(1,0) - rot_cv.at<float>(0,1));
226 
227  pose.orientation.x = q1;
228  pose.orientation.y = q2;
229  pose.orientation.z = q3;
230  pose.orientation.w = q4;
231 
232  idPoseMap.insert(std::make_pair(marker.id, pose));
233  }
234  return idPoseMap;
235 }
236 
237 std::map<int, geometry_msgs::Pose> ArucoMarkerRecognition::getMarkerPoses(const std::vector<aruco::Marker> &left_markers, const std::vector<aruco::Marker> &right_markers, const ivt_bridge::IvtStereoCalibration &ivtCalib) {
238  std::map<int, geometry_msgs::Pose> idPoseMap;
239  boost::shared_ptr<CStereoCalibration> stereoCalibPtr = ivtCalib.getStereoCalibration();
240 
241  for (unsigned int i = 0; i < left_markers.size(); i++) {
242  int left_id = left_markers.at(i).id;
243  for (unsigned int j = 0; j < right_markers.size(); j++) {
244  if (right_markers.at(j).id == left_id) {
245  CVec3dArray world_marker_corners(4);
246  CVec2dArray image_marker_corners_left(4);
247  CVec3dArray camera_marker_corners_left(4);
248 
249  for (int k = 0; k < 4; ++k) {
250  Vec2d img_point_left;
251  Vec3d world_point = {0.0f};
252  Vec2d left_point = { left_markers.at(i)[k].x, left_markers.at(i)[k].y };
253  Vec2d right_point = { right_markers.at(j)[k].x, right_markers.at(j)[k].y };
254  stereoCalibPtr->Calculate3DPoint(left_point, right_point, world_point, false, false);
255  world_marker_corners.AddElement(world_point);
256 
257  stereoCalibPtr->GetLeftCalibration()->WorldToImageCoordinates(world_point, img_point_left);
258  image_marker_corners_left.AddElement(img_point_left);
259  }
260 
261  Vec3d m0 = {0.0, 0.0, 0.0};
262  Vec3d m1 = {static_cast<float>(marker_size_ * 1000), 0.0, 0.0};
263  Vec3d m2 = {static_cast<float>(marker_size_ * 1000),static_cast<float>(marker_size_ * 1000), 0.0};
264  Vec3d m3 = {0.0, static_cast<float>(marker_size_ * 1000), 0.0};
265  for (int k = 0; k < 4; ++k) {
266  stereoCalibPtr->GetLeftCalibration()->WorldToCameraCoordinates(world_marker_corners[k], camera_marker_corners_left[k]);
267 
268  }
269  Vec3d sourcePoints[4] = {m0, m1, m2, m3};
270  Vec3d targetPointsLeft[4] = {camera_marker_corners_left[0],camera_marker_corners_left[1],camera_marker_corners_left[2],camera_marker_corners_left[3]};
271 
272  Mat3d rotation_left;
273  Vec3d translation_left;
274  CICP::CalculateOptimalTransformation(sourcePoints, targetPointsLeft, 4, rotation_left, translation_left);
275 
276  //translate marker position from corner to center
277  const Vec3d x = { static_cast<float>(marker_size_ * 1000) / 2.0f, 0.0f, 0.0f };
278  Vec3d x2;
279  const Vec3d y = { 0.0f, static_cast<float>(marker_size_ * 1000) / 2.0f, 0.0f };
280  Vec3d y2;
281 
282  Math3d::MulMatVec(rotation_left, x, x2);
283  Math3d::MulMatVec(rotation_left, y, y2);
284 
285  Math3d::AddToVec(translation_left, x2);
286  Math3d::AddToVec(translation_left, y2);
287 
288  //rotate marker in xz-plane, normal direction == -y
289  Mat3d B;
290  Vec3d axis;
291  axis.x = 1.0;
292  axis.y = 0.0;
293  axis.z = 0.0;
294  float theta = 0.5 * M_PI;
295  Math3d::SetRotationMat(B, axis, theta);
296 
297  Mat3d C;
298  Math3d::MulMatMat(rotation_left, B, C);
299 
300  geometry_msgs::Pose pose;
301  pose.position.x = translation_left.x / 1000;
302  pose.position.y = translation_left.y / 1000;
303  pose.position.z = translation_left.z / 1000;
304 
305  float q4 = 0.5f * sqrt(1.0f + C.r1 + C.r5 + C.r9);
306  float t = (1.0f / (4.0f * q4));
307  float q1 = t * (C.r8 - C.r6);
308  float q2 = t * (C.r3 - C.r7);
309  float q3 = t * (C.r4 - C.r2);
310 
311  pose.orientation.x = q1;
312  pose.orientation.y = q2;
313  pose.orientation.z = q3;
314  pose.orientation.w = q4;
315 
316  idPoseMap.insert(std::make_pair(left_id, pose));
317  break;
318  }
319  }
320  }
321 
322  return idPoseMap;
323 }
324 
325 visualization_msgs::Marker ArucoMarkerRecognition::createSquareMarker(int id, const geometry_msgs::Pose &pose, const string &frame_id) {
326  visualization_msgs::Marker square_marker;
327  square_marker.header.frame_id = frame_id;
328  square_marker.ns = "Found markers";
329  square_marker.id = id;
330  square_marker.action = visualization_msgs::Marker::ADD;
331  square_marker.pose.position = pose.position;
332  square_marker.pose.orientation = pose.orientation;
333  square_marker.color.a = 1;
334  square_marker.color.r = 1;
335  square_marker.color.g = 0;
336  square_marker.color.b = 0;
337  square_marker.scale.x = marker_size_;
338  square_marker.scale.y = 0.001;
339  square_marker.scale.z = marker_size_;
340  square_marker.type = visualization_msgs::Marker::CUBE;
341  square_marker.lifetime = ros::Duration(2);
342 
343  return square_marker;
344 }
345 
346 visualization_msgs::Marker ArucoMarkerRecognition::createArrowMarker(int id, const geometry_msgs::Pose &pose, const string &frame_id, bool isNsX) {
347  visualization_msgs::Marker arrow_marker;
348  arrow_marker.header.frame_id = frame_id;
349  arrow_marker.ns = isNsX ? "Found markers (orientation x)" : "Found markers (orientation)";
350  arrow_marker.id = id;
351  arrow_marker.action = visualization_msgs::Marker::ADD;
352  arrow_marker.pose.position = pose.position;
353  arrow_marker.pose.orientation = pose.orientation;
354  geometry_msgs::Point p0;
355  p0.x = 0;
356  p0.y = 0;
357  p0.z = 0;
358  geometry_msgs::Point p1;
359  p1.x = isNsX ? 0.05 : 0;
360  p1.y = isNsX ? 0 : -0.05;
361  p1.z = 0;
362  arrow_marker.points.push_back(p0);
363  arrow_marker.points.push_back(p1);
364  arrow_marker.color.a = 1;
365  arrow_marker.color.r = isNsX ? 1 : 0; // marker color is red if ns = x
366  arrow_marker.color.g = 0;
367  arrow_marker.color.b = isNsX ? 0 : 1; // marker color is blue if ns != x
368  arrow_marker.scale.x = 0.01;
369  arrow_marker.scale.y = 0.02;
370  arrow_marker.scale.z = 0.02;
371  arrow_marker.type = visualization_msgs::Marker::ARROW;
372  arrow_marker.lifetime = ros::Duration(2);
373 
374  return arrow_marker;
375 }
376 
377 visualization_msgs::Marker ArucoMarkerRecognition::createMeshMarker(int id, const geometry_msgs::Pose &pose, const std::string &mesh_res, const string &frame_id) {
378 
379  visualization_msgs::Marker marker;
380  marker.header.frame_id = frame_id;
381  marker.ns = "Found markers (meshes)";
382  marker.id = id;
383  marker.action = visualization_msgs::Marker::ADD;
384  marker.pose.position = pose.position;
385  marker.pose.orientation = pose.orientation;
386 
387  marker.scale.x = marker.scale.y = marker.scale.z = 0.001;
388  marker.color.r = marker.color.g = marker.color.b = 130.0f / 255.0f;
389  marker.color.a = 1.0;
390 
391  marker.mesh_resource = mesh_res;
392  marker.mesh_use_embedded_materials = false;
393 
394  marker.type = visualization_msgs::Marker::MESH_RESOURCE;
395  marker.lifetime = ros::Duration(2);
396 
397  return marker;
398 }
399 
400 asr_msgs::AsrObject ArucoMarkerRecognition::createAsrObject(const geometry_msgs::Pose &pose, const std::string &object_type, const string &frame_id, const std::string &mesh_res) {
401  asr_msgs::AsrObject o;
402 
403  o.header.frame_id = frame_id;
404  o.header.stamp = ros::Time::now();
405  o.providedBy = recognizer_name_;
406  geometry_msgs::PoseWithCovariance current_pose_with_c;
407  current_pose_with_c.pose = pose;
408  o.sampledPoses.push_back(current_pose_with_c);
409 
410  //Set bounding box as planar rectangle
411  BoundingBox bounding_box;
412 
413  Vec3d minPoint;
414  minPoint.x = minPoint.y = minPoint.z = 0.0;
415  Vec3d maxPoint;
416  maxPoint.x = maxPoint.z = marker_size_;
417  maxPoint.y = 0.0;
418 
419  for (unsigned int z = 0; z < 2; z++) {
420  for (unsigned int y = 0; y < 2; y++) {
421  for (unsigned int x = 0; x < 2; x++) {
422  bounding_box[4*z+2*y+x].x = (1 - x) * minPoint.x + x * maxPoint.x;
423  bounding_box[4*z+2*y+x].y = (1 - y) * minPoint.y + y * maxPoint.y;
424  bounding_box[4*z+2*y+x].z = (1 - z) * minPoint.z + z * maxPoint.z;
425  }
426  }
427  }
428 
429  o.boundingBox = bounding_box;
430 
431  o.color.r = o.color.g = o.color.b = 130.0f / 255.0f;
432  o.color.a = 1.0;
433  o.type = object_type;
434  o.typeConfidence = 1.0f;
435  o.identifier = "052052051100";
436  o.meshResourcePath = mesh_res;
437 
438  return o;
439 }
440 
441 
442 }
443 
444 int main(int argc, char** argv) {
445  ros::init(argc, argv, "asr_aruco_marker_recognition");
446  ROS_INFO("Starting up ArucoMarkerRecognition.\n");
448  ROS_DEBUG("ArucoMarkerRecognition is started up.\n");
449  //Here we set the frame rate with which marker recognition shall work.
450  unsigned int hertz = 5;
451  ROS_DEBUG_STREAM("ArucoMarkerRecognition runs at " << hertz << " hertz.\n");
452  ros::Rate r(hertz);
453 
454  while (ros::ok()) {
455  ros::spinOnce();
456  r.sleep();
457  }
458  return 0;
459 }
visualization_msgs::Marker createMeshMarker(int id, const geometry_msgs::Pose &pose, const std::string &mesh_res, const string &frame_id)
Create a ros marker from a given pose of a found marker.
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
cv::Mat drawMarkers(const cv::Mat &image, const std::vector< aruco::Marker > &markers)
Draws recognized markers and their id into an image.
void publish(const boost::shared_ptr< M > &message) const
void setCameraParameters(const sensor_msgs::CameraInfo &cam_params_left, const sensor_msgs::CameraInfo &cam_params_right)
Set the camera parameters of the two cameras.
message_filters::Subscriber< sensor_msgs::Image > image_left_sub_
f
This is the base class of the marker recognition system used for creating the ros environment and con...
visualization_msgs::Marker createArrowMarker(int id, const geometry_msgs::Pose &pose, const string &frame_id, bool isNsX=false)
Create a ros marker from a given pose of a found marker.
bool processGetRecognizerRequest(GetRecognizer::Request &req, GetRecognizer::Response &res)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
message_filters::Subscriber< sensor_msgs::CameraInfo > image_left_param_sub_
bool call(MReq &req, MRes &res)
This class is used to detect markers in an image using the aruco-library.
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
message_filters::Subscriber< sensor_msgs::CameraInfo > image_right_param_sub_
static const std::string NODE_NAME("asr_aruco_marker_recognition")
int main(int argc, char **argv)
#define ROS_INFO(...)
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
ROSCPP_DECL bool ok()
asr_msgs::AsrObject createAsrObject(const geometry_msgs::Pose &pose, const std::string &object_type, const string &frame_id, const std::string &mesh_res="")
Create a asr_object from a given marker pose.
message_filters::Subscriber< sensor_msgs::Image > image_right_sub_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
boost::array< ::geometry_msgs::Point_< std::allocator< void > >, 8 > BoundingBox
This class represents a marker. It is a vector of the fours corners ot the marker.
Definition: marker.h:41
std::map< int, geometry_msgs::Pose > getMarkerPoses(const std::vector< aruco::Marker > &left_markers)
#define ROS_DEBUG_STREAM(args)
bool sleep()
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)
void imageCallback(const sensor_msgs::ImageConstPtr &input_img_left, const sensor_msgs::ImageConstPtr &input_img_right, const sensor_msgs::CameraInfoConstPtr &cam_info_left, const sensor_msgs::CameraInfoConstPtr &cam_info_right)
The ros callback which is called when new images are received.
static const std::string GET_RECOGNIZER_SERVICE_NAME("get_recognizer")
bool getParam(const std::string &key, std::string &s) const
static const std::string OBJECT_DB_SERVICE_META_DATA("/asr_object_database/object_meta_data")
static Time now()
dynamic_reconfigure::Server< ArucoMarkerRecognitionConfig > reconfigure_server_
visualization_msgs::Marker createSquareMarker(int id, const geometry_msgs::Pose &pose, const string &frame_id)
Create a ros marker from a given pose of a found marker.
bool processReleaseRecognizerRequest(ReleaseRecognizer::Request &req, ReleaseRecognizer::Response &res)
std::vector< aruco::Marker > detect(const cv::Mat &image, CameraId id, const ArucoMarkerRecognitionConfig &config)
Detects markers in the given image with the camera parameters of the camera with the given id...
void configCallback(ArucoMarkerRecognitionConfig &config_, uint32_t level)
The callback function which is called when the configuration file has changed.
ROSCPP_DECL void spinOnce()
#define ROS_ERROR(...)
static const std::string RELEASE_RECOGNIZER_SERVICE_NAME("release_recognizer")
message_filters::Synchronizer< ApproximatePolicy > ApproximateSync
message_filters::sync_policies::ApproximateTime< sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo > ApproximatePolicy
#define ROS_DEBUG(...)
static const double DEFAULT_MARKER_SIZE(0.05)


asr_aruco_marker_recognition
Author(s): Allgeyer Tobias, Meißner Pascal, Qattan Mohamad
autogenerated on Mon Jun 10 2019 12:40:21