apriltag_detector.cpp
Go to the documentation of this file.
00001 #include <apriltags_ros/apriltag_detector.h>
00002 #include <cv_bridge/cv_bridge.h>
00003 #include <sensor_msgs/image_encodings.h>
00004 #include <boost/foreach.hpp>
00005 #include <geometry_msgs/PoseStamped.h>
00006 #include <geometry_msgs/PoseArray.h>
00007 #include <apriltags_ros/AprilTagDetection.h>
00008 #include <apriltags_ros/AprilTagDetectionArray.h>
00009 #include <AprilTags/Tag16h5.h>
00010 #include <AprilTags/Tag25h7.h>
00011 #include <AprilTags/Tag25h9.h>
00012 #include <AprilTags/Tag36h9.h>
00013 #include <AprilTags/Tag36h11.h>
00014 #include <XmlRpcException.h>
00015 
00016 namespace apriltags_ros{
00017 
00018 AprilTagDetector::AprilTagDetector(ros::NodeHandle& nh, ros::NodeHandle& pnh): it_(nh){
00019   XmlRpc::XmlRpcValue april_tag_descriptions;
00020   if(!pnh.getParam("tag_descriptions", april_tag_descriptions)){
00021     ROS_WARN("No april tags specified");
00022   }
00023   else{
00024     try{
00025       descriptions_ = parse_tag_descriptions(april_tag_descriptions);
00026     } catch(XmlRpc::XmlRpcException e){
00027       ROS_ERROR_STREAM("Error loading tag descriptions: "<<e.getMessage());
00028     }
00029   }
00030 
00031   if(!pnh.getParam("sensor_frame_id", sensor_frame_id_)){
00032     sensor_frame_id_ = "";
00033   }
00034 
00035   std::string tag_family;
00036   pnh.param<std::string>("tag_family", tag_family, "36h11");
00037 
00038   pnh.param<bool>("projected_optics", projected_optics_, false);
00039 
00040   const AprilTags::TagCodes* tag_codes;
00041   if(tag_family == "16h5"){
00042     tag_codes = &AprilTags::tagCodes16h5;
00043   }
00044   else if(tag_family == "25h7"){
00045     tag_codes = &AprilTags::tagCodes25h7;
00046   }
00047   else if(tag_family == "25h9"){
00048     tag_codes = &AprilTags::tagCodes25h9;
00049   }
00050   else if(tag_family == "36h9"){
00051     tag_codes = &AprilTags::tagCodes36h9;
00052   }
00053   else if(tag_family == "36h11"){
00054     tag_codes = &AprilTags::tagCodes36h11;
00055   }
00056   else{
00057     ROS_WARN("Invalid tag family specified; defaulting to 36h11");
00058     tag_codes = &AprilTags::tagCodes36h11;
00059   }
00060 
00061   tag_detector_= boost::shared_ptr<AprilTags::TagDetector>(new AprilTags::TagDetector(*tag_codes));
00062   image_sub_ = it_.subscribeCamera("image_rect", 1, &AprilTagDetector::imageCb, this);
00063   image_pub_ = it_.advertise("tag_detections_image", 1);
00064   detections_pub_ = nh.advertise<AprilTagDetectionArray>("tag_detections", 1);
00065   pose_pub_ = nh.advertise<geometry_msgs::PoseArray>("tag_detections_pose", 1);
00066 }
00067 AprilTagDetector::~AprilTagDetector(){
00068   image_sub_.shutdown();
00069 }
00070 
00071 void AprilTagDetector::imageCb(const sensor_msgs::ImageConstPtr& msg, const sensor_msgs::CameraInfoConstPtr& cam_info){
00072   cv_bridge::CvImagePtr cv_ptr;
00073   try{
00074     cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
00075   }
00076   catch (cv_bridge::Exception& e){
00077     ROS_ERROR("cv_bridge exception: %s", e.what());
00078     return;
00079   }
00080   cv::Mat gray;
00081   cv::cvtColor(cv_ptr->image, gray, CV_BGR2GRAY);
00082   std::vector<AprilTags::TagDetection>  detections = tag_detector_->extractTags(gray);
00083   ROS_DEBUG("%d tag detected", (int)detections.size());
00084 
00085   double fx;
00086   double fy;
00087   double px;
00088   double py;
00089   if (projected_optics_) {
00090     // use projected focal length and principal point
00091     // these are the correct values
00092     fx = cam_info->P[0];
00093     fy = cam_info->P[5];
00094     px = cam_info->P[2];
00095     py = cam_info->P[6];
00096   } else {
00097     // use camera intrinsic focal length and principal point
00098     // for backwards compatability
00099     fx = cam_info->K[0];
00100     fy = cam_info->K[4];
00101     px = cam_info->K[2];
00102     py = cam_info->K[5];
00103   }
00104 
00105   if(!sensor_frame_id_.empty())
00106     cv_ptr->header.frame_id = sensor_frame_id_;
00107 
00108   AprilTagDetectionArray tag_detection_array;
00109   geometry_msgs::PoseArray tag_pose_array;
00110   tag_pose_array.header = cv_ptr->header;
00111 
00112   BOOST_FOREACH(AprilTags::TagDetection detection, detections){
00113     std::map<int, AprilTagDescription>::const_iterator description_itr = descriptions_.find(detection.id);
00114     if(description_itr == descriptions_.end()){
00115       ROS_WARN_THROTTLE(10.0, "Found tag: %d, but no description was found for it", detection.id);
00116       continue;
00117     }
00118     AprilTagDescription description = description_itr->second;
00119     double tag_size = description.size();
00120 
00121     detection.draw(cv_ptr->image);
00122     Eigen::Matrix4d transform = detection.getRelativeTransform(tag_size, fx, fy, px, py);
00123     Eigen::Matrix3d rot = transform.block(0, 0, 3, 3);
00124     Eigen::Quaternion<double> rot_quaternion = Eigen::Quaternion<double>(rot);
00125 
00126     geometry_msgs::PoseStamped tag_pose;
00127     tag_pose.pose.position.x = transform(0, 3);
00128     tag_pose.pose.position.y = transform(1, 3);
00129     tag_pose.pose.position.z = transform(2, 3);
00130     tag_pose.pose.orientation.x = rot_quaternion.x();
00131     tag_pose.pose.orientation.y = rot_quaternion.y();
00132     tag_pose.pose.orientation.z = rot_quaternion.z();
00133     tag_pose.pose.orientation.w = rot_quaternion.w();
00134     tag_pose.header = cv_ptr->header;
00135 
00136     AprilTagDetection tag_detection;
00137     tag_detection.pose = tag_pose;
00138     tag_detection.id = detection.id;
00139     tag_detection.size = tag_size;
00140     tag_detection_array.detections.push_back(tag_detection);
00141     tag_pose_array.poses.push_back(tag_pose.pose);
00142 
00143     tf::Stamped<tf::Transform> tag_transform;
00144     tf::poseStampedMsgToTF(tag_pose, tag_transform);
00145     tf_pub_.sendTransform(tf::StampedTransform(tag_transform, tag_transform.stamp_, tag_transform.frame_id_, description.frame_name()));
00146   }
00147   detections_pub_.publish(tag_detection_array);
00148   pose_pub_.publish(tag_pose_array);
00149   image_pub_.publish(cv_ptr->toImageMsg());
00150 }
00151 
00152 
00153 std::map<int, AprilTagDescription> AprilTagDetector::parse_tag_descriptions(XmlRpc::XmlRpcValue& tag_descriptions){
00154   std::map<int, AprilTagDescription> descriptions;
00155   ROS_ASSERT(tag_descriptions.getType() == XmlRpc::XmlRpcValue::TypeArray);
00156   for (int32_t i = 0; i < tag_descriptions.size(); ++i) {
00157     XmlRpc::XmlRpcValue& tag_description = tag_descriptions[i];
00158     ROS_ASSERT(tag_description.getType() == XmlRpc::XmlRpcValue::TypeStruct);
00159     ROS_ASSERT(tag_description["id"].getType() == XmlRpc::XmlRpcValue::TypeInt);
00160     ROS_ASSERT(tag_description["size"].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00161 
00162     int id = (int)tag_description["id"];
00163     double size = (double)tag_description["size"];
00164 
00165     std::string frame_name;
00166     if(tag_description.hasMember("frame_id")){
00167       ROS_ASSERT(tag_description["frame_id"].getType() == XmlRpc::XmlRpcValue::TypeString);
00168       frame_name = (std::string)tag_description["frame_id"];
00169     }
00170     else{
00171       std::stringstream frame_name_stream;
00172       frame_name_stream << "tag_" << id;
00173       frame_name = frame_name_stream.str();
00174     }
00175     AprilTagDescription description(id, size, frame_name);
00176     ROS_INFO_STREAM("Loaded tag config: "<<id<<", size: "<<size<<", frame_name: "<<frame_name);
00177     descriptions.insert(std::make_pair(id, description));
00178   }
00179   return descriptions;
00180 }
00181 
00182 
00183 }


apriltags_ros
Author(s): Mitchell Wills
autogenerated on Thu Jun 6 2019 20:53:29