aruco_mapping.cpp
Go to the documentation of this file.
1 /*********************************************************************************************/
32 /* Author: Jan Bacik */
33 
34 #ifndef ARUCO_MAPPING_CPP
35 #define ARUCO_MAPPING_CPP
36 
37 #include <aruco_mapping.h>
38 #include "lidar_camera_calibration/marker_6dof.h"
39 
40 namespace aruco_mapping
41 {
42 
44  listener_ (new tf::TransformListener), // Initialize TF Listener
45  num_of_markers_ (10), // Number of used markers
46  marker_size_(0.1), // Marker size in m
47  calib_filename_("empty"), // Calibration filepath
48  space_type_ ("plane"), // Space type - 2D plane
49  roi_allowed_ (false), // ROI not allowed by default
50  first_marker_detected_(false), // First marker not detected by defualt
51  lowest_marker_id_(-1), // Lowest marker ID
52  marker_counter_(0), // Reset marker counter
53  closest_camera_index_(0) // Reset closest camera index
54 
55 {
56  double temp_marker_size;
57 
58  //Parse params from launch file
59  nh->getParam("/aruco_mapping/calibration_file", calib_filename_);
60  nh->getParam("/aruco_mapping/marker_size", temp_marker_size);
61  nh->getParam("/aruco_mapping/num_of_markers", num_of_markers_);
62  nh->getParam("/aruco_maping/space_type",space_type_);
63  nh->getParam("/aruco_mapping/roi_allowed",roi_allowed_);
64  nh->getParam("/aruco_mapping/roi_x",roi_x_);
65  nh->getParam("/aruco_mapping/roi_y",roi_y_);
66  nh->getParam("/aruco_mapping/roi_w",roi_w_);
67  nh->getParam("/aruco_mapping/roi_h",roi_h_);
68 
69  // Double to float conversion
70  marker_size_ = float(temp_marker_size);
71 
72  if(calib_filename_ == "empty")
73  ROS_WARN("Calibration filename empty! Check the launch file paths");
74  else
75  {
76  ROS_INFO_STREAM("Calibration file path: " << calib_filename_ );
77  ROS_INFO_STREAM("Number of markers: " << num_of_markers_);
78  ROS_INFO_STREAM("Marker Size: " << marker_size_);
79  ROS_INFO_STREAM("Type of space: " << space_type_);
80  ROS_INFO_STREAM("ROI allowed: " << roi_allowed_);
81  ROS_INFO_STREAM("ROI x-coor: " << roi_x_);
82  ROS_INFO_STREAM("ROI y-coor: " << roi_x_);
83  ROS_INFO_STREAM("ROI width: " << roi_w_);
84  ROS_INFO_STREAM("ROI height: " << roi_h_);
85  }
86 
87  //ROS publishers
88  marker_msg_pub_ = nh->advertise<aruco_mapping::ArucoMarker>("aruco_poses",1);
89  marker_visualization_pub_ = nh->advertise<visualization_msgs::Marker>("aruco_markers",1);
90  lidar_camera_calibration_rt = nh->advertise< lidar_camera_calibration::marker_6dof >("lidar_camera_calibration_rt",1);
91 
92  //Parse data from calibration file
94 
95  //Initialize OpenCV window
96  cv::namedWindow("Mono8", cv::WINDOW_AUTOSIZE);
97 
98  //Resize marker container
99  markers_.resize(num_of_markers_);
100 
101  // Default markers_ initialization
102  for(size_t i = 0; i < num_of_markers_;i++)
103  {
104  markers_[i].previous_marker_id = -1;
105  markers_[i].visible = false;
106  markers_[i].marker_id = -1;
107  }
108 }
109 
111 {
112  delete listener_;
113 }
114 
115 bool
116 ArucoMapping::parseCalibrationFile(std::string calib_filename)
117 {
118  sensor_msgs::CameraInfo camera_calibration_data;
119  std::string camera_name = "camera";
120 
121  camera_calibration_parsers::readCalibrationIni(calib_filename, camera_name, camera_calibration_data);
122 
123  // Alocation of memory for calibration data
124  cv::Mat *intrinsics = new(cv::Mat)(3, 3, CV_64F);
125  cv::Mat *distortion_coeff = new(cv::Mat)(5, 1, CV_64F);
126  cv::Size *image_size = new(cv::Size);
127 
128  image_size->width = camera_calibration_data.width;
129  image_size->height = camera_calibration_data.height;
130 
131  for(size_t i = 0; i < 3; i++)
132  for(size_t j = 0; j < 3; j++)
133  intrinsics->at<double>(i,j) = camera_calibration_data.K.at(3*i+j);
134 
135  for(size_t i = 0; i < 5; i++)
136  distortion_coeff->at<double>(i,0) = camera_calibration_data.D.at(i);
137 
138  ROS_DEBUG_STREAM("Image width: " << image_size->width);
139  ROS_DEBUG_STREAM("Image height: " << image_size->height);
140  ROS_DEBUG_STREAM("Intrinsics:" << std::endl << *intrinsics);
141  ROS_DEBUG_STREAM("Distortion: " << *distortion_coeff);
142 
143 
144  //Load parameters to aruco_calib_param_ for aruco detection
145  aruco_calib_params_.setParams(*intrinsics, *distortion_coeff, *image_size);
146 
147  //Simple check if calibration data meets expected values
148  if ((intrinsics->at<double>(2,2) == 1) && (distortion_coeff->at<double>(0,4) == 0))
149  {
150  ROS_INFO_STREAM("Calibration data loaded successfully");
151  return true;
152  }
153  else
154  {
155  ROS_WARN("Wrong calibration data, check calibration file and filepath");
156  return false;
157  }
158 }
159 
160 void
161 ArucoMapping::imageCallback(const sensor_msgs::ImageConstPtr &original_image)
162 {
163  //Create cv_brigde instance
164  cv_bridge::CvImagePtr cv_ptr;
165  try
166  {
168  }
169  catch (cv_bridge::Exception& e)
170  {
171  ROS_ERROR("Not able to convert sensor_msgs::Image to OpenCV::Mat format %s", e.what());
172  return;
173  }
174 
175  // sensor_msgs::Image to OpenCV Mat structure
176  cv::Mat I = cv_ptr->image;
177 
178  // region of interest
179  if(roi_allowed_==true)
180  I = cv_ptr->image(cv::Rect(roi_x_,roi_y_,roi_w_,roi_h_));
181 
182  //Marker detection
183  processImage(I,I);
184 
185  // Show image
186  cv::imshow("Mono8", I);
187  cv::waitKey(10);
188  /*cv::waitKey(2000);
189  ros::shutdown();*/
190 }
191 
192 
193 bool
194 ArucoMapping::processImage(cv::Mat input_image,cv::Mat output_image)
195 {
196  aruco::MarkerDetector Detector;
197  std::vector<aruco::Marker> temp_markers;
198 
199  //Set visibility flag to false for all markers
200  for(size_t i = 0; i < num_of_markers_; i++)
201  markers_[i].visible = false;
202 
203  // Save previous marker count
205 
206  // Detect markers
207  Detector.detect(input_image,temp_markers,aruco_calib_params_,marker_size_);
208 
209  // If no marker found, print statement
210  if(temp_markers.size() == 0)
211  ROS_DEBUG("No marker found!");
212 
213  //------------------------------------------------------
214  // FIRST MARKER DETECTED
215  //------------------------------------------------------
216  if((temp_markers.size() > 0) && (first_marker_detected_ == false))
217  {
218  //Set flag
220 
221  // Detect lowest marker ID
222  lowest_marker_id_ = temp_markers[0].id;
223  for(size_t i = 0; i < temp_markers.size();i++)
224  {
225  if(temp_markers[i].id < lowest_marker_id_)
226  lowest_marker_id_ = temp_markers[i].id;
227  }
228 
229 
230  ROS_DEBUG_STREAM("The lowest Id marker " << lowest_marker_id_ );
231 
232  // Identify lowest marker ID with world's origin
233  markers_[0].marker_id = lowest_marker_id_;
234 
235  markers_[0].geometry_msg_to_world.position.x = 0;
236  markers_[0].geometry_msg_to_world.position.y = 0;
237  markers_[0].geometry_msg_to_world.position.z = 0;
238 
239  markers_[0].geometry_msg_to_world.orientation.x = 0;
240  markers_[0].geometry_msg_to_world.orientation.y = 0;
241  markers_[0].geometry_msg_to_world.orientation.z = 0;
242  markers_[0].geometry_msg_to_world.orientation.w = 1;
243 
244  // Relative position and Global position
245  markers_[0].geometry_msg_to_previous.position.x = 0;
246  markers_[0].geometry_msg_to_previous.position.y = 0;
247  markers_[0].geometry_msg_to_previous.position.z = 0;
248 
249  markers_[0].geometry_msg_to_previous.orientation.x = 0;
250  markers_[0].geometry_msg_to_previous.orientation.y = 0;
251  markers_[0].geometry_msg_to_previous.orientation.z = 0;
252  markers_[0].geometry_msg_to_previous.orientation.w = 1;
253 
254  // Transformation Pose to TF
255  tf::Vector3 position;
256  position.setX(0);
257  position.setY(0);
258  position.setZ(0);
259 
260  tf::Quaternion rotation;
261  rotation.setX(0);
262  rotation.setY(0);
263  rotation.setZ(0);
264  rotation.setW(1);
265 
266  markers_[0].tf_to_previous.setOrigin(position);
267  markers_[0].tf_to_previous.setRotation(rotation);
268 
269  // Relative position of first marker equals Global position
270  markers_[0].tf_to_world=markers_[0].tf_to_previous;
271 
272  // Increase count
273  marker_counter_++;
274 
275  // Set sign of visibility of first marker
276  markers_[0].visible=true;
277 
278  ROS_INFO_STREAM("First marker with ID: " << markers_[0].marker_id << " detected");
279 
280  //First marker does not have any previous marker
281  markers_[0].previous_marker_id = THIS_IS_FIRST_MARKER;
282  }
283 
284  //------------------------------------------------------
285  // FOR EVERY MARKER DO
286  //------------------------------------------------------
287  std::string pkg_loc = ros::package::getPath("lidar_camera_calibration") + "/conf/transform.txt";
288  std::ofstream outfile(pkg_loc.c_str(), std::ios_base::trunc);
289 
290  lidar_camera_calibration::marker_6dof marker_r_and_t;
291 
292  marker_r_and_t.header.stamp = ros::Time::now();
293  marker_r_and_t.dof.data.clear();
294 
295  marker_r_and_t.num_of_markers = temp_markers.size();
296 
297  for(size_t i = 0; i < temp_markers.size();i++)
298  {
299  int index;
300  int current_marker_id = temp_markers[i].id;
301 
302  //Draw marker convex, ID, cube and axis
303  temp_markers[i].draw(output_image, cv::Scalar(0,0,255),2);
304  aruco::CvDrawingUtils::draw3dCube(output_image,temp_markers[i], aruco_calib_params_);
305  aruco::CvDrawingUtils::draw3dAxis(output_image,temp_markers[i], aruco_calib_params_);
306 
307  // Existing marker ?
308  bool existing = false;
309  int temp_counter = 0;
310 
311  while((existing == false) && (temp_counter < marker_counter_))
312  {
313  if(markers_[temp_counter].marker_id == current_marker_id)
314  {
315  index = temp_counter;
316  existing = true;
317  ROS_DEBUG_STREAM("Existing marker with ID: " << current_marker_id << "found");
318  }
319  temp_counter++;
320  }
321 
322  //New marker ?
323  if(existing == false)
324  {
325  index = marker_counter_;
326  markers_[index].marker_id = current_marker_id;
327  existing = true;
328  ROS_DEBUG_STREAM("New marker with ID: " << current_marker_id << " found");
329  }
330 
331  // Change visibility flag of new marker
332  for(size_t j = 0;j < marker_counter_; j++)
333  {
334  for(size_t k = 0;k < temp_markers.size(); k++)
335  {
336  if(markers_[j].marker_id == temp_markers[k].id)
337  markers_[j].visible = true;
338  }
339  }
340 
341  //------------------------------------------------------
342  // For existing marker do
343  //------------------------------------------------------
344  if((index < marker_counter_) && (first_marker_detected_ == true))
345  {
346  outfile << temp_markers[i] << "\n";
347  marker_r_and_t.dof.data.push_back( temp_markers[i].id );
348  marker_r_and_t.dof.data.push_back( temp_markers[i].Tvec.ptr<float>(0)[0] );
349  marker_r_and_t.dof.data.push_back( temp_markers[i].Tvec.ptr<float>(0)[1] );
350  marker_r_and_t.dof.data.push_back( temp_markers[i].Tvec.ptr<float>(0)[2] );
351  marker_r_and_t.dof.data.push_back( temp_markers[i].Rvec.ptr<float>(0)[0] );
352  marker_r_and_t.dof.data.push_back( temp_markers[i].Rvec.ptr<float>(0)[1] );
353  marker_r_and_t.dof.data.push_back( temp_markers[i].Rvec.ptr<float>(0)[2] );
354 
355  markers_[index].current_camera_tf = arucoMarker2Tf(temp_markers[i]);
356  markers_[index].current_camera_tf = markers_[index].current_camera_tf.inverse();
357 
358  const tf::Vector3 marker_origin = markers_[index].current_camera_tf.getOrigin();
359  markers_[index].current_camera_pose.position.x = marker_origin.getX();
360  markers_[index].current_camera_pose.position.y = marker_origin.getY();
361  markers_[index].current_camera_pose.position.z = marker_origin.getZ();
362 
363  const tf::Quaternion marker_quaternion = markers_[index].current_camera_tf.getRotation();
364  markers_[index].current_camera_pose.orientation.x = marker_quaternion.getX();
365  markers_[index].current_camera_pose.orientation.y = marker_quaternion.getY();
366  markers_[index].current_camera_pose.orientation.z = marker_quaternion.getZ();
367  markers_[index].current_camera_pose.orientation.w = marker_quaternion.getW();
368  }
369 
370  //------------------------------------------------------
371  // For new marker do
372  //------------------------------------------------------
373  if((index == marker_counter_) && (first_marker_detected_ == true))
374  {
375  outfile << temp_markers[i] << "\n";
376  marker_r_and_t.dof.data.push_back( temp_markers[i].id );
377  marker_r_and_t.dof.data.push_back( temp_markers[i].Tvec.ptr<float>(0)[0] );
378  marker_r_and_t.dof.data.push_back( temp_markers[i].Tvec.ptr<float>(0)[1] );
379  marker_r_and_t.dof.data.push_back( temp_markers[i].Tvec.ptr<float>(0)[2] );
380  marker_r_and_t.dof.data.push_back( temp_markers[i].Rvec.ptr<float>(0)[0] );
381  marker_r_and_t.dof.data.push_back( temp_markers[i].Rvec.ptr<float>(0)[1] );
382  marker_r_and_t.dof.data.push_back( temp_markers[i].Rvec.ptr<float>(0)[2] );
383 
384  markers_[index].current_camera_tf=arucoMarker2Tf(temp_markers[i]);
385 
386  tf::Vector3 marker_origin = markers_[index].current_camera_tf.getOrigin();
387  markers_[index].current_camera_pose.position.x = marker_origin.getX();
388  markers_[index].current_camera_pose.position.y = marker_origin.getY();
389  markers_[index].current_camera_pose.position.z = marker_origin.getZ();
390 
391  tf::Quaternion marker_quaternion = markers_[index].current_camera_tf.getRotation();
392  markers_[index].current_camera_pose.orientation.x = marker_quaternion.getX();
393  markers_[index].current_camera_pose.orientation.y = marker_quaternion.getY();
394  markers_[index].current_camera_pose.orientation.z = marker_quaternion.getZ();
395  markers_[index].current_camera_pose.orientation.w = marker_quaternion.getW();
396 
397  // Naming - TFs
398  std::stringstream camera_tf_id;
399  std::stringstream camera_tf_id_old;
400  std::stringstream marker_tf_id_old;
401 
402  camera_tf_id << "camera_" << index;
403 
404  // Flag to keep info if any_known marker_visible in actual image
405  bool any_known_marker_visible = false;
406 
407  // Array ID of markers, which position of new marker is calculated
408  int last_marker_id;
409 
410  // Testing, if is possible calculate position of a new marker to old known marker
411  for(int k = 0; k < index; k++)
412  {
413  if((markers_[k].visible == true) && (any_known_marker_visible == false))
414  {
415  if(markers_[k].previous_marker_id != -1)
416  {
417  any_known_marker_visible = true;
418  camera_tf_id_old << "camera_" << k;
419  marker_tf_id_old << "marker_" << k;
420  markers_[index].previous_marker_id = k;
421  last_marker_id = k;
422  }
423  }
424  }
425 
426  // New position can be calculated
427  if(any_known_marker_visible == true)
428  {
429  // Generating TFs for listener
430  for(char k = 0; k < 10; k++)
431  {
432  // TF from old marker and its camera
433  broadcaster_.sendTransform(tf::StampedTransform(markers_[last_marker_id].current_camera_tf,ros::Time::now(),
434  marker_tf_id_old.str(),camera_tf_id_old.str()));
435 
436  // TF from old camera to new camera
438  camera_tf_id_old.str(),camera_tf_id.str()));
439 
441  }
442 
443  // Calculate TF between two markers
444  listener_->waitForTransform(marker_tf_id_old.str(),camera_tf_id.str(),ros::Time(0),
446  try
447  {
448  broadcaster_.sendTransform(tf::StampedTransform(markers_[last_marker_id].current_camera_tf,ros::Time::now(),
449  marker_tf_id_old.str(),camera_tf_id_old.str()));
450 
452  camera_tf_id_old.str(),camera_tf_id.str()));
453 
454  listener_->lookupTransform(marker_tf_id_old.str(),camera_tf_id.str(),ros::Time(0),
455  markers_[index].tf_to_previous);
456  }
457  catch(tf::TransformException &e)
458  {
459  ROS_ERROR("Not able to lookup transform");
460  }
461 
462  // Save origin and quaternion of calculated TF
463  marker_origin = markers_[index].tf_to_previous.getOrigin();
464  marker_quaternion = markers_[index].tf_to_previous.getRotation();
465 
466  // If plane type selected roll, pitch and Z axis are zero
467  if(space_type_ == "plane")
468  {
469  double roll, pitch, yaw;
470  tf::Matrix3x3(marker_quaternion).getRPY(roll,pitch,yaw);
471  roll = 0;
472  pitch = 0;
473  marker_origin.setZ(0);
474  marker_quaternion.setRPY(pitch,roll,yaw);
475  }
476 
477  markers_[index].tf_to_previous.setRotation(marker_quaternion);
478  markers_[index].tf_to_previous.setOrigin(marker_origin);
479 
480  marker_origin = markers_[index].tf_to_previous.getOrigin();
481  markers_[index].geometry_msg_to_previous.position.x = marker_origin.getX();
482  markers_[index].geometry_msg_to_previous.position.y = marker_origin.getY();
483  markers_[index].geometry_msg_to_previous.position.z = marker_origin.getZ();
484 
485  marker_quaternion = markers_[index].tf_to_previous.getRotation();
486  markers_[index].geometry_msg_to_previous.orientation.x = marker_quaternion.getX();
487  markers_[index].geometry_msg_to_previous.orientation.y = marker_quaternion.getY();
488  markers_[index].geometry_msg_to_previous.orientation.z = marker_quaternion.getZ();
489  markers_[index].geometry_msg_to_previous.orientation.w = marker_quaternion.getW();
490 
491  // increase marker count
492  marker_counter_++;
493 
494  // Invert and position of new marker to compute camera pose above it
495  markers_[index].current_camera_tf = markers_[index].current_camera_tf.inverse();
496 
497  marker_origin = markers_[index].current_camera_tf.getOrigin();
498  markers_[index].current_camera_pose.position.x = marker_origin.getX();
499  markers_[index].current_camera_pose.position.y = marker_origin.getY();
500  markers_[index].current_camera_pose.position.z = marker_origin.getZ();
501 
502  marker_quaternion = markers_[index].current_camera_tf.getRotation();
503  markers_[index].current_camera_pose.orientation.x = marker_quaternion.getX();
504  markers_[index].current_camera_pose.orientation.y = marker_quaternion.getY();
505  markers_[index].current_camera_pose.orientation.z = marker_quaternion.getZ();
506  markers_[index].current_camera_pose.orientation.w = marker_quaternion.getW();
507 
508  // Publish all TFs and markers
509  publishTfs(false);
510  }
511  }
512 
513  //------------------------------------------------------
514  // Compute global position of new marker
515  //------------------------------------------------------
516  if((marker_counter_previous_ < marker_counter_) && (first_marker_detected_ == true))
517  {
518  // Publish all TF five times for listener
519  for(char k = 0; k < 5; k++)
520  publishTfs(false);
521 
522  std::stringstream marker_tf_name;
523  marker_tf_name << "marker_" << index;
524 
525  listener_->waitForTransform("world",marker_tf_name.str(),ros::Time(0),
527  try
528  {
529  listener_->lookupTransform("world",marker_tf_name.str(),ros::Time(0),
530  markers_[index].tf_to_world);
531  }
532  catch(tf::TransformException &e)
533  {
534  ROS_ERROR("Not able to lookup transform");
535  }
536 
537  // Saving TF to Pose
538  const tf::Vector3 marker_origin = markers_[index].tf_to_world.getOrigin();
539  markers_[index].geometry_msg_to_world.position.x = marker_origin.getX();
540  markers_[index].geometry_msg_to_world.position.y = marker_origin.getY();
541  markers_[index].geometry_msg_to_world.position.z = marker_origin.getZ();
542 
543  tf::Quaternion marker_quaternion=markers_[index].tf_to_world.getRotation();
544  markers_[index].geometry_msg_to_world.orientation.x = marker_quaternion.getX();
545  markers_[index].geometry_msg_to_world.orientation.y = marker_quaternion.getY();
546  markers_[index].geometry_msg_to_world.orientation.z = marker_quaternion.getZ();
547  markers_[index].geometry_msg_to_world.orientation.w = marker_quaternion.getW();
548  }
549  }
550  outfile.close();
551  lidar_camera_calibration_rt.publish(marker_r_and_t);
552  marker_r_and_t.dof.data.clear();
553  //------------------------------------------------------
554  // Compute which of visible markers is the closest to the camera
555  //------------------------------------------------------
556  bool any_markers_visible=false;
557  int num_of_visible_markers=0;
558 
559  if(first_marker_detected_ == true)
560  {
561  double minimal_distance = INIT_MIN_SIZE_VALUE;
562  for(int k = 0; k < num_of_markers_; k++)
563  {
564  double a,b,c,size;
565 
566  // If marker is visible, distance is calculated
567  if(markers_[k].visible==true)
568  {
569  a = markers_[k].current_camera_pose.position.x;
570  b = markers_[k].current_camera_pose.position.y;
571  c = markers_[k].current_camera_pose.position.z;
572  size = std::sqrt((a * a) + (b * b) + (c * c));
573  if(size < minimal_distance)
574  {
575  minimal_distance = size;
577  }
578 
579  any_markers_visible = true;
580  num_of_visible_markers++;
581  }
582  }
583  }
584 
585  //------------------------------------------------------
586  // Publish all known markers
587  //------------------------------------------------------
588  if(first_marker_detected_ == true)
589  publishTfs(true);
590 
591  //------------------------------------------------------
592  // Compute global camera pose
593  //------------------------------------------------------
594  if((first_marker_detected_ == true) && (any_markers_visible == true))
595  {
596  std::stringstream closest_camera_tf_name;
597  closest_camera_tf_name << "camera_" << closest_camera_index_;
598 
599  listener_->waitForTransform("world",closest_camera_tf_name.str(),ros::Time(0),
601  try
602  {
603  listener_->lookupTransform("world",closest_camera_tf_name.str(),ros::Time(0),
605  }
606  catch(tf::TransformException &ex)
607  {
608  ROS_ERROR("Not able to lookup transform");
609  }
610 
611  // Saving TF to Pose
612  const tf::Vector3 marker_origin = world_position_transform_.getOrigin();
613  world_position_geometry_msg_.position.x = marker_origin.getX();
614  world_position_geometry_msg_.position.y = marker_origin.getY();
615  world_position_geometry_msg_.position.z = marker_origin.getZ();
616 
618  world_position_geometry_msg_.orientation.x = marker_quaternion.getX();
619  world_position_geometry_msg_.orientation.y = marker_quaternion.getY();
620  world_position_geometry_msg_.orientation.z = marker_quaternion.getZ();
621  world_position_geometry_msg_.orientation.w = marker_quaternion.getW();
622  }
623 
624  //------------------------------------------------------
625  // Publish all known markers
626  //------------------------------------------------------
627  if(first_marker_detected_ == true)
628  publishTfs(true);
629 
630  //------------------------------------------------------
631  // Publish custom marker message
632  //------------------------------------------------------
633  aruco_mapping::ArucoMarker marker_msg;
634 
635  if((any_markers_visible == true))
636  {
637  marker_msg.header.stamp = ros::Time::now();
638  marker_msg.header.frame_id = "world";
639  marker_msg.marker_visibile = true;
640  marker_msg.num_of_visible_markers = num_of_visible_markers;
641  marker_msg.global_camera_pose = world_position_geometry_msg_;
642  marker_msg.marker_ids.clear();
643  marker_msg.global_marker_poses.clear();
644  for(size_t j = 0; j < marker_counter_; j++)
645  {
646  if(markers_[j].visible == true)
647  {
648  marker_msg.marker_ids.push_back(markers_[j].marker_id);
649  marker_msg.global_marker_poses.push_back(markers_[j].geometry_msg_to_world);
650  }
651  }
652  }
653  else
654  {
655  marker_msg.header.stamp = ros::Time::now();
656  marker_msg.header.frame_id = "world";
657  marker_msg.num_of_visible_markers = num_of_visible_markers;
658  marker_msg.marker_visibile = false;
659  marker_msg.marker_ids.clear();
660  marker_msg.global_marker_poses.clear();
661  }
662 
663  // Publish custom marker msg
664  marker_msg_pub_.publish(marker_msg);
665 
666  return true;
667 }
668 
670 
671 void
672 ArucoMapping::publishTfs(bool world_option)
673 {
674  for(int i = 0; i < marker_counter_; i++)
675  {
676  // Actual Marker
677  std::stringstream marker_tf_id;
678  marker_tf_id << "marker_" << i;
679  // Older marker - or World
680  std::stringstream marker_tf_id_old;
681  if(i == 0)
682  marker_tf_id_old << "world";
683  else
684  marker_tf_id_old << "marker_" << markers_[i].previous_marker_id;
685  broadcaster_.sendTransform(tf::StampedTransform(markers_[i].tf_to_previous,ros::Time::now(),marker_tf_id_old.str(),marker_tf_id.str()));
686 
687  // Position of camera to its marker
688  std::stringstream camera_tf_id;
689  camera_tf_id << "camera_" << i;
690  broadcaster_.sendTransform(tf::StampedTransform(markers_[i].current_camera_tf,ros::Time::now(),marker_tf_id.str(),camera_tf_id.str()));
691 
692  if(world_option == true)
693  {
694  // Global position of marker TF
695  std::stringstream marker_globe;
696  marker_globe << "marker_globe_" << i;
697  broadcaster_.sendTransform(tf::StampedTransform(markers_[i].tf_to_world,ros::Time::now(),"world",marker_globe.str()));
698  }
699 
700  // Cubes for RVIZ - markers
701  publishMarker(markers_[i].geometry_msg_to_previous,markers_[i].marker_id,i);
702  }
703 
704  // Global Position of object
705  if(world_option == true)
707 }
708 
710 
711 void
712 ArucoMapping::publishMarker(geometry_msgs::Pose marker_pose, int marker_id, int index)
713 {
714  visualization_msgs::Marker vis_marker;
715 
716  if(index == 0)
717  vis_marker.header.frame_id = "world";
718  else
719  {
720  std::stringstream marker_tf_id_old;
721  marker_tf_id_old << "marker_" << markers_[index].previous_marker_id;
722  vis_marker.header.frame_id = marker_tf_id_old.str();
723  }
724 
725  vis_marker.header.stamp = ros::Time::now();
726  vis_marker.ns = "basic_shapes";
727  vis_marker.id = marker_id;
728  vis_marker.type = visualization_msgs::Marker::CUBE;
729  vis_marker.action = visualization_msgs::Marker::ADD;
730 
731  vis_marker.pose = marker_pose;
732  vis_marker.scale.x = marker_size_;
733  vis_marker.scale.y = marker_size_;
734  vis_marker.scale.z = RVIZ_MARKER_HEIGHT;
735 
736  vis_marker.color.r = RVIZ_MARKER_COLOR_R;
737  vis_marker.color.g = RVIZ_MARKER_COLOR_G;
738  vis_marker.color.b = RVIZ_MARKER_COLOR_B;
739  vis_marker.color.a = RVIZ_MARKER_COLOR_A;
740 
741  vis_marker.lifetime = ros::Duration(RVIZ_MARKER_LIFETIME);
742 
744 }
745 
747 
750 {
751  cv::Mat marker_rotation(3,3, CV_32FC1);
752  cv::Rodrigues(marker.Rvec, marker_rotation);
753  cv::Mat marker_translation = marker.Tvec;
754 
755  cv::Mat rotate_to_ros(3,3,CV_32FC1);
756  rotate_to_ros.at<float>(0,0) = -1.0;
757  rotate_to_ros.at<float>(0,1) = 0;
758  rotate_to_ros.at<float>(0,2) = 0;
759  rotate_to_ros.at<float>(1,0) = 0;
760  rotate_to_ros.at<float>(1,1) = 0;
761  rotate_to_ros.at<float>(1,2) = 1.0;
762  rotate_to_ros.at<float>(2,0) = 0.0;
763  rotate_to_ros.at<float>(2,1) = 1.0;
764  rotate_to_ros.at<float>(2,2) = 0.0;
765 
766  marker_rotation = marker_rotation * rotate_to_ros.t();
767 
768  // Origin solution
769  tf::Matrix3x3 marker_tf_rot(marker_rotation.at<float>(0,0),marker_rotation.at<float>(0,1),marker_rotation.at<float>(0,2),
770  marker_rotation.at<float>(1,0),marker_rotation.at<float>(1,1),marker_rotation.at<float>(1,2),
771  marker_rotation.at<float>(2,0),marker_rotation.at<float>(2,1),marker_rotation.at<float>(2,2));
772 
773  tf::Vector3 marker_tf_tran(marker_translation.at<float>(0,0),
774  marker_translation.at<float>(1,0),
775  marker_translation.at<float>(2,0));
776 
777  /*ROS_INFO_STREAM("in aruco mapping: \n" << marker << "\n");
778  ROS_INFO_STREAM("Edited: \n" << marker_tf_tran[0] << "\n");*/
779  return tf::Transform(marker_tf_rot, marker_tf_tran);
780 
781 
782 }
783 
784 
785 
786 } //aruco_mapping
787 
788 #endif //ARUCO_MAPPING_CPP
static constexpr double RVIZ_MARKER_COLOR_A
static void draw3dCube(cv::Mat &Image, Marker &m, const CameraParameters &CP)
ros::Publisher marker_visualization_pub_
Publisher of visualization_msgs::Marker message to "aruco_markers" topic.
void detect(const cv::Mat &input, std::vector< Marker > &detectedMarkers, cv::Mat camMatrix=cv::Mat(), cv::Mat distCoeff=cv::Mat(), float markerSizeMeters=-1, bool setYPerpendicular=true)
ros::Publisher marker_msg_pub_
Publisher of aruco_mapping::ArucoMarker custom message.
static constexpr double WAIT_FOR_TRANSFORM_INTERVAL
void publish(const boost::shared_ptr< M > &message) const
TFSIMD_FORCE_INLINE void setX(tfScalar x)
tf::TransformListener * listener_
TFSIMD_FORCE_INLINE void setY(tfScalar y)
static constexpr double THIS_IS_FIRST_MARKER
static constexpr double INIT_MIN_SIZE_VALUE
void publishMarker(geometry_msgs::Pose markerPose, int MarkerID, int rank)
Function to publish all known markers for visualization purposes.
static constexpr double RVIZ_MARKER_COLOR_G
int index
tf::Transform arucoMarker2Tf(const aruco::Marker &marker)
Compute TF from marker detector result.
bool sleep() const
TFSIMD_FORCE_INLINE void setZ(tfScalar z)
TFSIMD_FORCE_INLINE const tfScalar & getY() const
TFSIMD_FORCE_INLINE const tfScalar & getW() const
tf::TransformBroadcaster broadcaster_
TFSIMD_FORCE_INLINE const tfScalar & getZ() const
#define ROS_WARN(...)
bool waitForTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration &timeout, const ros::Duration &polling_sleep_duration=ros::Duration(0.01), std::string *error_msg=NULL) const
ArucoMapping(ros::NodeHandle *nh)
Construct a client for EZN64 USB control.
ros::Publisher lidar_camera_calibration_rt
Publisher of std::vector<double> message for tvec and rvec for lidar_camera_calibration.
tf::StampedTransform world_position_transform_
Actual TF of camera with respect to world&#39;s origin.
void setRPY(const tfScalar &roll, const tfScalar &pitch, const tfScalar &yaw)
void getRPY(tfScalar &roll, tfScalar &pitch, tfScalar &yaw, unsigned int solution_number=1) const
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
void sendTransform(const StampedTransform &transform)
static void draw3dAxis(cv::Mat &Image, Marker &m, const CameraParameters &CP)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
This class represents a marker. It is a vector of the fours corners ot the marker.
Main class for marker detection.
bool parseCalibrationFile(std::string filename)
Function to parse data from calibration file.
#define ROS_DEBUG_STREAM(args)
void setParams(cv::Mat cameraMatrix, cv::Mat distorsionCoeff, cv::Size size)
TFSIMD_FORCE_INLINE Vector3 & getOrigin()
aruco::CameraParameters aruco_calib_params_
void lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const
ROSLIB_DECL std::string getPath(const std::string &package_name)
static constexpr double RVIZ_MARKER_COLOR_B
std::vector< MarkerInfo > markers_
Container holding MarkerInfo data about all detected markers.
static constexpr double RVIZ_MARKER_HEIGHT
geometry_msgs::Pose world_position_geometry_msg_
Actual Pose of camera with respect to world&#39;s origin.
#define ROS_INFO_STREAM(args)
Quaternion getRotation() const
static constexpr double RVIZ_MARKER_LIFETIME
bool getParam(const std::string &key, std::string &s) const
TFSIMD_FORCE_INLINE const tfScalar & getX() const
static Time now()
static constexpr double RVIZ_MARKER_COLOR_R
Aruco mapping namespace.
Definition: aruco_mapping.h:66
void imageCallback(const sensor_msgs::ImageConstPtr &original_image)
Callback function to handle image processing.
bool processImage(cv::Mat input_image, cv::Mat output_image)
Process actual image, detect markers and compute poses.
#define ROS_ERROR(...)
void publishTfs(bool world_option)
Function to publish all known TFs.
static constexpr double BROADCAST_WAIT_INTERVAL
bool readCalibrationIni(std::istream &in, std::string &camera_name, sensor_msgs::CameraInfo &cam_info)
std::string pkg_loc
Definition: Find_RT.h:17
#define ROS_DEBUG(...)


lidar_camera_calibration
Author(s):
autogenerated on Sat Feb 6 2021 03:39:37