34 #ifndef ARUCO_MAPPING_CPP 35 #define ARUCO_MAPPING_CPP 38 #include "lidar_camera_calibration/marker_6dof.h" 44 listener_ (new
tf::TransformListener),
47 calib_filename_(
"empty"),
48 space_type_ (
"plane"),
50 first_marker_detected_(false),
51 lowest_marker_id_(-1),
53 closest_camera_index_(0)
56 double temp_marker_size;
60 nh->
getParam(
"/aruco_mapping/marker_size", temp_marker_size);
73 ROS_WARN(
"Calibration filename empty! Check the launch file paths");
96 cv::namedWindow(
"Mono8", cv::WINDOW_AUTOSIZE);
104 markers_[i].previous_marker_id = -1;
118 sensor_msgs::CameraInfo camera_calibration_data;
119 std::string camera_name =
"camera";
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);
128 image_size->width = camera_calibration_data.width;
129 image_size->height = camera_calibration_data.height;
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);
135 for(
size_t i = 0; i < 5; i++)
136 distortion_coeff->at<
double>(i,0) = camera_calibration_data.D.at(i);
148 if ((intrinsics->at<
double>(2,2) == 1) && (distortion_coeff->at<
double>(0,4) == 0))
155 ROS_WARN(
"Wrong calibration data, check calibration file and filepath");
171 ROS_ERROR(
"Not able to convert sensor_msgs::Image to OpenCV::Mat format %s", e.what());
176 cv::Mat I = cv_ptr->image;
186 cv::imshow(
"Mono8", I);
197 std::vector<aruco::Marker> temp_markers;
210 if(temp_markers.size() == 0)
223 for(
size_t i = 0; i < temp_markers.size();i++)
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;
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;
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;
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;
266 markers_[0].tf_to_previous.setOrigin(position);
267 markers_[0].tf_to_previous.setRotation(rotation);
288 std::ofstream outfile(pkg_loc.c_str(), std::ios_base::trunc);
290 lidar_camera_calibration::marker_6dof marker_r_and_t;
293 marker_r_and_t.dof.data.clear();
295 marker_r_and_t.num_of_markers = temp_markers.size();
297 for(
size_t i = 0; i < temp_markers.size();i++)
300 int current_marker_id = temp_markers[i].id;
303 temp_markers[i].draw(output_image, cv::Scalar(0,0,255),2);
308 bool existing =
false;
309 int temp_counter = 0;
313 if(
markers_[temp_counter].marker_id == current_marker_id)
315 index = temp_counter;
317 ROS_DEBUG_STREAM(
"Existing marker with ID: " << current_marker_id <<
"found");
323 if(existing ==
false)
326 markers_[index].marker_id = current_marker_id;
334 for(
size_t k = 0;k < temp_markers.size(); k++)
336 if(
markers_[j].marker_id == temp_markers[k].
id)
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] );
356 markers_[index].current_camera_tf =
markers_[index].current_camera_tf.inverse();
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();
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();
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] );
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();
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();
398 std::stringstream camera_tf_id;
399 std::stringstream camera_tf_id_old;
400 std::stringstream marker_tf_id_old;
402 camera_tf_id <<
"camera_" << index;
405 bool any_known_marker_visible =
false;
411 for(
int k = 0; k < index; k++)
413 if((
markers_[k].visible ==
true) && (any_known_marker_visible ==
false))
415 if(
markers_[k].previous_marker_id != -1)
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;
427 if(any_known_marker_visible ==
true)
430 for(
char k = 0; k < 10; k++)
434 marker_tf_id_old.str(),camera_tf_id_old.str()));
438 camera_tf_id_old.str(),camera_tf_id.str()));
449 marker_tf_id_old.str(),camera_tf_id_old.str()));
452 camera_tf_id_old.str(),camera_tf_id.str()));
459 ROS_ERROR(
"Not able to lookup transform");
463 marker_origin =
markers_[index].tf_to_previous.getOrigin();
464 marker_quaternion =
markers_[index].tf_to_previous.getRotation();
469 double roll, pitch, yaw;
473 marker_origin.
setZ(0);
474 marker_quaternion.
setRPY(pitch,roll,yaw);
477 markers_[index].tf_to_previous.setRotation(marker_quaternion);
478 markers_[index].tf_to_previous.setOrigin(marker_origin);
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();
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();
495 markers_[index].current_camera_tf =
markers_[index].current_camera_tf.inverse();
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();
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();
519 for(
char k = 0; k < 5; k++)
522 std::stringstream marker_tf_name;
523 marker_tf_name <<
"marker_" << index;
534 ROS_ERROR(
"Not able to lookup transform");
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();
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();
552 marker_r_and_t.dof.data.clear();
556 bool any_markers_visible=
false;
557 int num_of_visible_markers=0;
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)
575 minimal_distance = size;
579 any_markers_visible =
true;
580 num_of_visible_markers++;
596 std::stringstream closest_camera_tf_name;
608 ROS_ERROR(
"Not able to lookup transform");
633 aruco_mapping::ArucoMarker marker_msg;
635 if((any_markers_visible ==
true))
638 marker_msg.header.frame_id =
"world";
639 marker_msg.marker_visibile =
true;
640 marker_msg.num_of_visible_markers = num_of_visible_markers;
642 marker_msg.marker_ids.clear();
643 marker_msg.global_marker_poses.clear();
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);
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();
677 std::stringstream marker_tf_id;
678 marker_tf_id <<
"marker_" << i;
680 std::stringstream marker_tf_id_old;
682 marker_tf_id_old <<
"world";
684 marker_tf_id_old <<
"marker_" <<
markers_[i].previous_marker_id;
688 std::stringstream camera_tf_id;
689 camera_tf_id <<
"camera_" << i;
692 if(world_option ==
true)
695 std::stringstream marker_globe;
696 marker_globe <<
"marker_globe_" << i;
705 if(world_option ==
true)
714 visualization_msgs::Marker vis_marker;
717 vis_marker.header.frame_id =
"world";
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();
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;
731 vis_marker.pose = marker_pose;
751 cv::Mat marker_rotation(3,3, CV_32FC1);
752 cv::Rodrigues(marker.
Rvec, marker_rotation);
753 cv::Mat marker_translation = marker.
Tvec;
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;
766 marker_rotation = marker_rotation * rotate_to_ros.t();
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));
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));
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
tf::Transform arucoMarker2Tf(const aruco::Marker &marker)
Compute TF from marker detector result.
TFSIMD_FORCE_INLINE void setZ(tfScalar z)
int marker_counter_previous_
TFSIMD_FORCE_INLINE const tfScalar & getY() const
TFSIMD_FORCE_INLINE const tfScalar & getW() const
tf::TransformBroadcaster broadcaster_
int closest_camera_index_
TFSIMD_FORCE_INLINE const tfScalar & getZ() 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's origin.
std::string calib_filename_
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())
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)
aruco::CameraParameters aruco_calib_params_
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's origin.
#define ROS_INFO_STREAM(args)
bool first_marker_detected_
static constexpr double RVIZ_MARKER_LIFETIME
bool getParam(const std::string &key, std::string &s) const
TFSIMD_FORCE_INLINE const tfScalar & getX() const
static constexpr double RVIZ_MARKER_COLOR_R
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.
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)