diff --git a/CMakeLists.txt b/CMakeLists.txt index 0712c2f74b6cc6d5db0d2bf8be0ce1ddb1bef213..10afb732c6d70345e0c5ea739020b05283557f7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ find_package(catkin REQUIRED) # ******************************************************************** # Add catkin additional components here # ******************************************************************** -find_package(catkin REQUIRED COMPONENTS iri_base_algorithm nav_msgs iri_blob_detector sensor_msgs geometry_msgs dynamic_reconfigure message_generation tf) +find_package(catkin REQUIRED COMPONENTS iri_base_algorithm visualization_msgs nav_msgs iri_blob_detector sensor_msgs geometry_msgs dynamic_reconfigure message_generation tf) ## System dependencies are found with CMake's conventions # find_package(Boost REQUIRED COMPONENTS system) @@ -62,7 +62,7 @@ catkin_package( # ******************************************************************** # Add ROS and IRI ROS run time dependencies # ******************************************************************** - CATKIN_DEPENDS iri_base_algorithm nav_msgs iri_blob_detector sensor_msgs geometry_msgs dynamic_reconfigure message_runtime tf + CATKIN_DEPENDS iri_base_algorithm visualization_msgs nav_msgs iri_blob_detector sensor_msgs geometry_msgs dynamic_reconfigure message_runtime tf # ******************************************************************** # Add system and labrobotica run time dependencies here # ******************************************************************** @@ -99,6 +99,8 @@ target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBRARIES}) # Add message headers dependencies # ******************************************************************** # add_dependencies(${PROJECT_NAME} <msg_package_name>_generate_messages_cpp) +add_dependencies(${PROJECT_NAME} geometry_msgs_generate_messages_cpp) +add_dependencies(${PROJECT_NAME} visualization_msgs_generate_messages_cpp) add_dependencies(${PROJECT_NAME} nav_msgs_generate_messages_cpp) add_dependencies(${PROJECT_NAME} iri_blob_detector_generate_messages_cpp) # ******************************************************************** diff --git a/cfg/VisualGps.cfg b/cfg/VisualGps.cfg index c79ca2dfd0416205340472c0990284504ec494c6..03c5dee496c6b1d132841ed3d47737327d914ae8 100755 --- a/cfg/VisualGps.cfg +++ b/cfg/VisualGps.cfg @@ -39,8 +39,12 @@ gen = ParameterGenerator() # Name Type Reconfiguration level Description Default Min Max #gen.add("velocity_scale_factor", double_t, 0, "Maximum velocity scale factor", 0.5, 0.0, 1.0) -gen.add("world_frame" , str_t, 0, "Wolrd reference frame", "map") +gen.add("world_frame" , str_t, 0, "World reference frame", "map") gen.add("odom_gps_frame" , str_t, 0, "GPS odometry reference frame", "gps_odom") +gen.add("base_frame" , str_t, 0, "Base frame id", "base_link") +gen.add("camera_frame" , str_t, 0, "Camera frame id", "top_camera_optical") +gen.add("undistort_points" , bool_t, 0, "Enable point undistorsion", True) +gen.add("publish_markers" , bool_t, 0, "Enable marker publishing", True) gen.add("color1_id" , str_t, 0, "Color 1 identifier", "color1") gen.add("color1_x" , double_t, 0, "Color 1 X position", 0.5, -100.0,100.0) gen.add("color1_y" , double_t, 0, "Color 1 Y position", 0.5, -100.0,100.0) @@ -58,4 +62,7 @@ gen.add("color4_x" , double_t, 0, " gen.add("color4_y" , double_t, 0, "Color 4 Y position", 0.5, -100.0,100.0) gen.add("color4_z" , double_t, 0, "Color 4 Z position", 0.5, -100.0,100.0) + + + exit(gen.generate(PACKAGE, "VisualGpsAlgorithm", "VisualGps")) diff --git a/config/params.yaml b/config/params.yaml new file mode 100644 index 0000000000000000000000000000000000000000..aada361b7425e5a354a639a45c978000e2b847e6 --- /dev/null +++ b/config/params.yaml @@ -0,0 +1,4 @@ +world_frame: map +odom_gps_frame: gps_odom +base_frame: base_link +camera_frame: top_camera_optical \ No newline at end of file diff --git a/include/visual_gps_alg.h b/include/visual_gps_alg.h index 569155e8191c5e8679535709188ed211cce472a5..0528d13bc886d088e79a0d98a6a6dd055dbc0431 100644 --- a/include/visual_gps_alg.h +++ b/include/visual_gps_alg.h @@ -29,10 +29,14 @@ #include <iri_blob_detector/blob.h> #include <geometry_msgs/Pose.h> +#include <tf/transform_listener.h> + //include visual_gps_alg main library #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/calib3d/calib3d.hpp> +#include <Eigen/Eigen> + /** * \brief IRI ROS Specific Driver Class * @@ -52,8 +56,19 @@ class VisualGpsAlgorithm // private attributes and methods cv::Mat K,D,R,P; geometry_msgs::Pose pose; + tf::StampedTransform transform_base_to_camera; + + Eigen::Vector3d t_base_2_camera; + Eigen::Matrix3d R_base_camera; + Eigen::Vector2d t_world_2_base; + double yaw_world_2_base; + + std::vector<std::string> points_ids; + std::vector<cv::Point3f> map_points; + std::vector<cv::Point3f> img_points; - void update_points(std::vector<iri_blob_detector::blob> &blobs, std::vector<cv::Point3f> &points_3d,std::vector<cv::Point2f> &points_img); + void update_points(std::vector<iri_blob_detector::blob> &blobs, std::vector<cv::Point3f> &points_3d,std::vector<cv::Point2f> &pixels_img, std::vector<cv::Point3f> &points_img_3d, std::vector<std::string> &ids); + void OptimalRigidTransformation(std::vector<cv::Point3f> pw, std::vector<cv::Point3f> pc, geometry_msgs::Pose &pose); public: /** * \brief define config type @@ -128,6 +143,8 @@ class VisualGpsAlgorithm void set_camera_params(cv::Mat &K,cv::Mat &D,cv::Mat &R,cv::Mat &P,unsigned int width,unsigned int height); bool compute_pos(std::vector<iri_blob_detector::blob> &blobs1,std::vector<iri_blob_detector::blob> &blobs2,std::vector<iri_blob_detector::blob> &blobs3,std::vector<iri_blob_detector::blob> &blobs4); void get_pose(geometry_msgs::Pose &pose); + void get_points(std::vector<cv::Point3f> &map_points, std::vector<cv::Point3f> &img_points, std::vector<std::string> &ids); + void set_transform_base_to_camera(tf::StampedTransform t); /** * \brief Destructor diff --git a/include/visual_gps_alg_node.h b/include/visual_gps_alg_node.h index 9ae8336cd502f60c1c49e27b3984ad7834d5dcc9..fa3e5a63854d26b7257ac0be5618f36046c2aec5 100644 --- a/include/visual_gps_alg_node.h +++ b/include/visual_gps_alg_node.h @@ -29,7 +29,10 @@ #include "visual_gps_alg.h" #include <tf/transform_broadcaster.h> + // [publisher subscriber headers] +#include <geometry_msgs/PoseStamped.h> +#include <visualization_msgs/MarkerArray.h> #include <nav_msgs/Odometry.h> #include <iri_blob_detector/blob_array.h> #include <sensor_msgs/CameraInfo.h> @@ -47,6 +50,12 @@ class VisualGpsAlgNode : public algorithm_base::IriBaseAlgorithm<VisualGpsAlgori { private: // [publisher attributes] + ros::Publisher pose_publisher_; + geometry_msgs::PoseStamped pose_PoseStamped_msg_; + + ros::Publisher markers_publisher_; + visualization_msgs::MarkerArray markers_MarkerArray_msg_; + ros::Publisher odom_publisher_; nav_msgs::Odometry odom_Odometry_msg_; @@ -103,6 +112,11 @@ class VisualGpsAlgNode : public algorithm_base::IriBaseAlgorithm<VisualGpsAlgori // [action client attributes] tf::TransformBroadcaster odom_broadcaster; + tf::TransformListener tf_listener; + + bool loaded_static_tf; + bool load_static_tf(); + void publish_markers(std::vector<cv::Point3f> map_points, std::vector<cv::Point3f> img_points, std::vector<std::string> ids); /** * \brief config variable diff --git a/launch/visual_gps.launch b/launch/visual_gps.launch index 1830b443d2baacb599014503d7ca0ee5bc360ad1..572559f84d5bdf28bb015ccbc9f84fb4ba92d07f 100644 --- a/launch/visual_gps.launch +++ b/launch/visual_gps.launch @@ -58,5 +58,6 @@ <remap from="~/camera/camera_info" to="/usb_cam/camera_info"/> <remap from="~/set_camera_params" to="/usb_cam/set_parameters"/> <rosparam file="$(arg positions_path)/$(arg positions_file)" command="load" /> + <rosparam file="$(arg positions_path)/params.yaml" command="load" /> </node> </launch> diff --git a/launch/visual_gps_sim.launch b/launch/visual_gps_sim.launch index 7d599c2c4fe291430c1d186128f4cd5c8da270cc..8560430d7a757c985997fe234dc3cccb62fddb1d 100644 --- a/launch/visual_gps_sim.launch +++ b/launch/visual_gps_sim.launch @@ -58,5 +58,6 @@ <remap from="~/camera/camera_info" to="/usb_cam/camera_info"/> <remap from="~/set_camera_params" to="/usb_cam/set_parameters"/> <rosparam file="$(arg positions_path)/$(arg positions_file)" command="load" /> + <rosparam file="$(arg positions_path)/params.yaml" command="load" /> </node> </launch> diff --git a/package.xml b/package.xml index 50856018412988e2769a497ee18699bf33d55478..68fb9493b3a70f44652642a247ff33e461380c9f 100644 --- a/package.xml +++ b/package.xml @@ -51,6 +51,8 @@ <!-- <doc_depend>doxygen</doc_depend> --> <buildtool_depend>catkin</buildtool_depend> <build_depend>iri_base_algorithm</build_depend> + <run_depend>visualization_msgs</run_depend> + <build_depend>visualization_msgs</build_depend> <build_depend>nav_msgs</build_depend> <build_depend>iri_blob_detector</build_depend> <build_depend>sensor_msgs</build_depend> diff --git a/src/visual_gps_alg.cpp b/src/visual_gps_alg.cpp index 9a8eea0a6bf05e486415b5b7350af2f16d3cfc9f..96216c7bb3f1d46e7307046c9f8f11437d1e2e39 100644 --- a/src/visual_gps_alg.cpp +++ b/src/visual_gps_alg.cpp @@ -23,12 +23,12 @@ void VisualGpsAlgorithm::config_update(Config& config, uint32_t level) } // VisualGpsAlgorithm Public API -void VisualGpsAlgorithm::update_points(std::vector<iri_blob_detector::blob> &blobs, std::vector<cv::Point3f> &points_3d,std::vector<cv::Point2f> &points_img) +void VisualGpsAlgorithm::update_points(std::vector<iri_blob_detector::blob> &blobs, std::vector<cv::Point3f> &points_3d,std::vector<cv::Point2f> &pixels_img, std::vector<cv::Point3f> &points_img_3d, std::vector<std::string> &ids) { unsigned int max_index=0; double max_size=0; - if(blobs.size()!=0)// some blobs detected for color1 + if(blobs.size()!=0)// some blobs detected { if(blobs[0].id.find(this->config_.color1_id)!=std::string::npos)// blob 1 matches with color1 points_3d.push_back(cv::Point3f(this->config_.color1_x,this->config_.color1_y,this->config_.color1_z)); @@ -40,12 +40,35 @@ void VisualGpsAlgorithm::update_points(std::vector<iri_blob_detector::blob> &blo points_3d.push_back(cv::Point3f(this->config_.color4_x,this->config_.color4_y,this->config_.color4_z)); // get the biggest blob for(unsigned int i=0;i<blobs.size();i++) + { if(blobs[i].size>max_size) { max_size=blobs[i].size; max_index=i; } - points_img.push_back(cv::Point2f(blobs[max_index].center_x-this->K.at<double>(0,2),blobs[max_index].center_y-this->K.at<double>(1,2))); + } + + if(this->config_.undistort_points) + { + // rectify points + std::vector<cv::Point2f> pixels_img_undist; + cv::fisheye::undistortPoints(pixels_img,pixels_img_undist,this->K,this->D,this->R,this->P); + pixels_img = pixels_img_undist; + } + + pixels_img.push_back(cv::Point2f(blobs[max_index].center_x-this->K.at<double>(0,2),blobs[max_index].center_y-this->K.at<double>(1,2))); + + Eigen::Vector3d p_projected; + static double z_i = points_3d[0].z - this->t_base_2_camera(2); // map height + + p_projected(0) = pixels_img.back().x / this->K.at<double>(0,0) * z_i; // x projected to the map height + p_projected(1) = pixels_img.back().y / this->K.at<double>(1,1) * z_i; // y projected to the map height + p_projected(2) = z_i; // z is the map height + + // move to baselink frame + Eigen::Vector3d p_base_link = this->R_base_camera * p_projected + this->t_base_2_camera; + points_img_3d.push_back(cv::Point3f( p_base_link(0),p_base_link(1), p_base_link(2))); + ids.push_back(blobs[0].id); } } @@ -60,9 +83,12 @@ void VisualGpsAlgorithm::set_camera_params(cv::Mat &K,cv::Mat &D,cv::Mat &R,cv:: bool VisualGpsAlgorithm::compute_pos(std::vector<iri_blob_detector::blob> &blobs1,std::vector<iri_blob_detector::blob> &blobs2,std::vector<iri_blob_detector::blob> &blobs3,std::vector<iri_blob_detector::blob> &blobs4) { bool ok=false; - std::vector<cv::Point3f> points_3d; - std::vector<cv::Point2f> points_img; - std::vector<cv::Point2f> points_img_undist; + std::vector<std::string> ids; + std::vector<cv::Point3f> map_points; + std::vector<cv::Point2f> pixels_img; + std::vector<cv::Point3f> img_points; + std::vector<cv::Point3f> img_points_undist; + Eigen::Vector2d point_a,point_b,ab_vector,center_world,tmp_vector; std::vector<Eigen::Vector2d> circle_center; std::vector<double> circle_radius; @@ -72,113 +98,74 @@ bool VisualGpsAlgorithm::compute_pos(std::vector<iri_blob_detector::blob> &blobs double num=0.0,den=0.0; // find point correspondence - this->update_points(blobs1,points_3d,points_img); - this->update_points(blobs2,points_3d,points_img); - this->update_points(blobs4,points_3d,points_img); - this->update_points(blobs3,points_3d,points_img); - // rectify points - cv::fisheye::undistortPoints(points_img,points_img_undist,this->K,this->D,this->R,this->P); - //points_img = points_img_undist; - if(points_3d.size()>3 && points_img.size()>3) - { - ROS_DEBUG("VisualGpsAlgorithm: using 4 detections"); - for(unsigned int i=0;i<points_3d.size();i++) - { - for(unsigned int j=i+1;j<points_3d.size();j++) - { - point_a << points_3d[i].x , points_3d[i].y; - point_b << points_3d[j].x , points_3d[j].y; - ab_vector=point_b-point_a; - angle_a=atan2(-points_img[i].y,points_img[i].x); - if(angle_a<0.0) - angle_a+=2*3.14159; - angle_b=atan2(-points_img[j].y,points_img[j].x); - if(angle_b<0.0) - angle_b+=2*3.14159; - angle=angle_a-angle_b; - if(fabs(cos(angle))<0.9) - { - angle=3.14159/2.0-angle; - radius=ab_vector.norm()/(2.0*fabs(cos(angle))); - circle_radius.push_back(radius); - tmp_vector << -ab_vector(1) , ab_vector(0); - center_world=point_a+(ab_vector+tan(angle)*tmp_vector)/2.0; - circle_center.push_back(center_world); - } - } - } - Eigen::MatrixXd A(circle_center.size()-1,2); - Eigen::VectorXd B(circle_center.size()-1); - Eigen::Vector2d sol; - for(unsigned int i=0;i<circle_center.size()-1;i++) - { - A(i,0)=circle_center[i+1](0)-circle_center[0](0); - A(i,1)=circle_center[i+1](1)-circle_center[0](1); - B(i)=pow(circle_center[i+1](0),2)-pow(circle_center[0](0),2)+(pow(circle_center[i+1](1),2)-pow(circle_center[0](1),2)+pow(circle_radius[0],2)-pow(circle_radius[i+1],2))/2.0; - } - sol=(A.transpose()*A).inverse()*A.transpose()*B; - this->pose.position.x=sol(0); - this->pose.position.y=sol(1); - this->pose.position.z=0.0; + this->update_points(blobs1,map_points,pixels_img, img_points, ids); + this->update_points(blobs2,map_points,pixels_img, img_points, ids); + this->update_points(blobs4,map_points,pixels_img, img_points, ids); + this->update_points(blobs3,map_points,pixels_img, img_points, ids); - // estimate orientation - for(unsigned int i=0;i<points_3d.size();i++) - { - camera_x_avg+=points_img[i].x; - camera_y_avg+=points_img[i].y; - world_x_avg+=points_3d[i].x; - world_y_avg+=points_3d[i].y; - } - camera_x_avg/=points_3d.size(); - camera_y_avg/=points_3d.size(); - world_x_avg/=points_3d.size(); - world_y_avg/=points_3d.size(); - for(unsigned int i=0;i<points_3d.size();i++) - { - num+=(points_img[i].x-camera_x_avg)*(points_3d[i].y-world_y_avg)-(points_img[i].y-camera_y_avg)*(points_3d[i].x-world_x_avg); - den+=(points_img[i].x-camera_x_avg)*(points_3d[i].x-world_x_avg)-(points_img[i].y-camera_y_avg)*(points_3d[i].y-world_y_avg); - } - yaw=atan2(num,den); - this->pose.orientation=tf::createQuaternionMsgFromYaw(yaw); - ROS_INFO("VisualGpsAlgorithm:compute_pos: pose x,y,yaw=%f,%f,%f",this->pose.position.x, this->pose.position.y, yaw ); - ok = true; - } - else if(points_3d.size()>2 && points_img.size()>2) + if(map_points.size()>1 && img_points.size()>1) { - ROS_DEBUG("VisualGpsAlgorithm: using 3 detections"); - for(unsigned int i=0;i<points_3d.size();i++) - { - //ROS_INFO("VisualGpsAlgorithm:compute_pos: ________cx,cy= %f, %f ________ wx,wy= %f, %f", points_img[i].x, points_img[i].y, points_3d[i].x, points_3d[i].y ); - camera_x_avg+=points_img[i].x; - camera_y_avg+=points_img[i].y; - world_x_avg+=points_3d[i].x; - world_y_avg+=points_3d[i].y; - //ROS_INFO("VisualGpsAlgorithm:compute_pos: ---"); - } - camera_x_avg/=points_3d.size(); - camera_y_avg/=points_3d.size(); - world_x_avg/=points_3d.size(); - world_y_avg/=points_3d.size(); - for(unsigned int i=0;i<points_3d.size();i++) - { - num+=(points_img[i].x-camera_x_avg)*(points_3d[i].y-world_y_avg)-(points_img[i].y-camera_y_avg)*(points_3d[i].x-world_x_avg); - den+=(points_img[i].x-camera_x_avg)*(points_3d[i].x-world_x_avg)-(points_img[i].y-camera_y_avg)*(points_3d[i].y-world_y_avg); - } - yaw=atan2(num,den); - this->pose.orientation=tf::createQuaternionMsgFromYaw(yaw); - this->pose.position.x=world_x_avg-cos(yaw)*camera_x_avg+sin(yaw)*camera_y_avg; - this->pose.position.y=world_y_avg-sin(yaw)*camera_x_avg-cos(yaw)*camera_y_avg; - this->pose.position.z=0.0; - ROS_INFO("VisualGpsAlgorithm:compute_pos: pose x,y,yaw=%f,%f,%f",this->pose.position.x, this->pose.position.y, yaw ); + this->OptimalRigidTransformation(map_points, img_points, this->pose); ok = true; } else + { + ROS_WARN("VisualGpsAlgorithm:compute_pos: not enough blobs found: %lu", img_points.size()); ok = false; + } + this->map_points = map_points; + this->img_points = img_points; + this->points_ids = ids; + return ok; } +void VisualGpsAlgorithm::OptimalRigidTransformation(std::vector<cv::Point3f> pw, std::vector<cv::Point3f> pc, geometry_msgs::Pose &pose) +{ + double camera_x_avg=0.0,camera_y_avg=0.0,world_x_avg=0.0,world_y_avg=0.0; + + double num=0.0,den=0.0; + for(unsigned int i=0;i<pw.size();i++) + { + camera_x_avg+=pc[i].x; + camera_y_avg+=pc[i].y; + world_x_avg+=pw[i].x; + world_y_avg+=pw[i].y; + } + camera_x_avg/=pw.size(); + camera_y_avg/=pw.size(); + world_x_avg/=pw.size(); + world_y_avg/=pw.size(); + for(unsigned int i=0;i<pw.size();i++) + { + num+=(pc[i].x-camera_x_avg)*(pw[i].y-world_y_avg)-(pc[i].y-camera_y_avg)*(pw[i].x-world_x_avg); + den+=(pc[i].x-camera_x_avg)*(pw[i].x-world_x_avg)+(pc[i].y-camera_y_avg)*(pw[i].y-world_y_avg); + } + this->yaw_world_2_base=atan2(num,den); + pose.orientation=tf::createQuaternionMsgFromYaw(this->yaw_world_2_base); + pose.position.x=world_x_avg-cos(this->yaw_world_2_base)*camera_x_avg+sin(this->yaw_world_2_base)*camera_y_avg; + pose.position.y=world_y_avg-sin(this->yaw_world_2_base)*camera_x_avg-cos(this->yaw_world_2_base)*camera_y_avg; + pose.position.z=0.0; +} + void VisualGpsAlgorithm::get_pose(geometry_msgs::Pose &pose) { pose=this->pose; } + +void VisualGpsAlgorithm::get_points(std::vector<cv::Point3f> &map_points, std::vector<cv::Point3f> &img_points, std::vector<std::string> &ids) +{ + map_points = this->map_points; + img_points = this->img_points; + ids = this->points_ids; +} + +void VisualGpsAlgorithm::set_transform_base_to_camera(tf::StampedTransform t) +{ + this->transform_base_to_camera = t; + this->t_base_2_camera << t.getOrigin().x(), t.getOrigin().y(), t.getOrigin().z(); + double yaw_base_2_camera = tf::getYaw(t.getRotation()); + this->R_base_camera = Eigen::Matrix3d::Identity(); + this->R_base_camera.topLeftCorner<2,2>() = Eigen::Rotation2D<double>(yaw_base_2_camera).matrix(); +} \ No newline at end of file diff --git a/src/visual_gps_alg_node.cpp b/src/visual_gps_alg_node.cpp index 232e3da3b63454f2fbe4c55c70632ff89edd13ee..2cf7f06b4aad343f821473e8f0db6b7ee1771f7b 100644 --- a/src/visual_gps_alg_node.cpp +++ b/src/visual_gps_alg_node.cpp @@ -2,12 +2,15 @@ #include <dynamic_reconfigure/Reconfigure.h> VisualGpsAlgNode::VisualGpsAlgNode(void) : - algorithm_base::IriBaseAlgorithm<VisualGpsAlgorithm>() + algorithm_base::IriBaseAlgorithm<VisualGpsAlgorithm>(), + tf_listener(ros::Duration(10.f)) { //init class attributes if necessary this->loop_rate_ = 10;//in [Hz] // [init publishers] + this->pose_publisher_ = this->private_node_handle_.advertise<geometry_msgs::PoseStamped>("pose", 1); + this->markers_publisher_ = this->private_node_handle_.advertise<visualization_msgs::MarkerArray>("markers", 1); this->odom_publisher_ = this->public_node_handle_.advertise<nav_msgs::Odometry>("odom", 1); // [init subscribers] @@ -37,6 +40,8 @@ VisualGpsAlgNode::VisualGpsAlgNode(void) : // [init action servers] // [init action clients] + + this->loaded_static_tf=false; } VisualGpsAlgNode::~VisualGpsAlgNode(void) @@ -55,12 +60,27 @@ void VisualGpsAlgNode::mainNodeThread(void) tf::Quaternion tf_quat; geometry_msgs::TransformStamped odom_trans; // [fill msg structures] + // Initialize the topic message structure + //this->pose_PoseStamped_msg_.data = my_var; + + // Initialize the topic message structure + //this->markers_MarkerArray_msg_.data = my_var; + // [fill srv structure and make request to the server] // [fill action structure and make request to the action server] // [publish messages] + // Uncomment the following line to publish the topic message + //this->pose_publisher_.publish(this->pose_PoseStamped_msg_); + + // Uncomment the following line to publish the topic message + //this->markers_publisher_.publish(this->markers_MarkerArray_msg_); + + + if(!this->loaded_static_tf) + this->loaded_static_tf = this->load_static_tf(); if(this->cam_info_received) { @@ -81,6 +101,20 @@ void VisualGpsAlgNode::mainNodeThread(void) odom_trans.transform.translation.z = this->odom_Odometry_msg_.pose.pose.position.z; odom_trans.transform.rotation=this->odom_Odometry_msg_.pose.pose.orientation; this->odom_broadcaster.sendTransform(odom_trans); + + this->pose_PoseStamped_msg_.pose = this->odom_Odometry_msg_.pose.pose; + this->pose_PoseStamped_msg_.header = this->odom_Odometry_msg_.header; + this->pose_PoseStamped_msg_.header.frame_id = this->config_.world_frame; + this->pose_publisher_.publish(this->pose_PoseStamped_msg_); + + if(this->config_.publish_markers) + { + std::vector<cv::Point3f> map_points; + std::vector<cv::Point3f> img_points; + std::vector<std::string> points_ids; + this->alg_.get_points(map_points, img_points, points_ids); + this->publish_markers(map_points, img_points, points_ids); + } } this->alg_.unlock(); } @@ -107,6 +141,8 @@ void VisualGpsAlgNode::camera_info_callback(const sensor_msgs::CameraInfo::Const } } + + void VisualGpsAlgNode::camera_info_mutex_enter(void) { pthread_mutex_lock(&this->camera_info_mutex_); @@ -264,3 +300,153 @@ int main(int argc,char *argv[]) { return algorithm_base::main<VisualGpsAlgNode>(argc, argv, "visual_gps_alg_node"); } + +bool VisualGpsAlgNode::load_static_tf() +{ + bool ok=false; + std::string target_frame = this->config_.camera_frame; + std::string source_frame = this->config_.base_frame; + ros::Time target_time = ros::Time::now(); + try + { + while ( !this->tf_listener.waitForTransform(source_frame, target_frame, target_time, ros::Duration(1.)) ) + { + ROS_WARN("VisualGpsAlgNode: load_static_tf: tf not received!"); + ros::Duration(0.1).sleep(); + } + tf::StampedTransform transform_base_2_camera; + + this->tf_listener.lookupTransform(source_frame, target_frame, target_time, transform_base_2_camera); + + ROS_INFO("VisualGpsAlgNode:load_static_tf: read camera-base transform: x,y,z=%f,%f,%f, yaw=%f", transform_base_2_camera.getOrigin().x(), transform_base_2_camera.getOrigin().y(), transform_base_2_camera.getOrigin().z(), tf::getYaw(transform_base_2_camera.getRotation())); + + this->alg_.set_transform_base_to_camera(transform_base_2_camera); + ok=true; + } + catch (tf::TransformException &ex) + { + ROS_ERROR("VisualGpsAlgNode:load_static_tf: %s",ex.what()); + } + + return ok; +} + +void VisualGpsAlgNode::publish_markers(std::vector<cv::Point3f> map_points, std::vector<cv::Point3f> img_points, std::vector<std::string> ids) +{ + this->markers_MarkerArray_msg_.markers.clear(); + for(uint i=0; i<map_points.size(); i++) + { + visualization_msgs::Marker marker; + marker.header.frame_id = this->config_.base_frame; + marker.ns = "map"; + marker.id = i; + marker.header.stamp = ros::Time::now(); + marker.type = visualization_msgs::Marker::CUBE; + marker.action = visualization_msgs::Marker::ADD; + marker.scale.x = 0.6; + marker.scale.y = 0.6; + marker.scale.z = 0.1; + marker.pose.position.x = img_points[i].x; + marker.pose.position.y = img_points[i].y; + marker.pose.position.z = img_points[i].z; + marker.pose.orientation.x = 0.0; + marker.pose.orientation.y = 0.0; + marker.pose.orientation.z = 0.0; + marker.pose.orientation.w = 1.0; + + if (ids[i].find("green")!=std::string::npos) + { + marker.color.r = 0.0; + marker.color.g = 1.0; + marker.color.b = 0.0; + } + else if (ids[i].find("red")!=std::string::npos) + { + marker.color.r = 1.0; + marker.color.g = 0.0; + marker.color.b = 0.0; + } + else if (ids[i].find("yellow")!=std::string::npos) + { + marker.color.r = 1.0; + marker.color.g = 1.0; + marker.color.b = 0.0; + } + else if (ids[i].find("blue")!=std::string::npos) + { + marker.color.r = 0.0; + marker.color.g = 0.0; + marker.color.b = 1.0; + } + else + { + ROS_WARN("VisualGpsAlgNode::publish_markers: unrecognized point id: %s", ids[i].c_str()); + marker.color.r = 1.0; + marker.color.g = 1.0; + marker.color.b = 1.0; + } + marker.color.a = 1.0; + marker.lifetime = ros::Duration(1.0f); + + this->markers_MarkerArray_msg_.markers.push_back(marker); + } + for(uint i=0; i<img_points.size(); i++) + { + visualization_msgs::Marker marker; + marker.header.frame_id = this->config_.base_frame; + marker.ns = "img"; + marker.id = i+img_points.size(); + marker.header.stamp = ros::Time::now(); + marker.type = visualization_msgs::Marker::SPHERE; + marker.action = visualization_msgs::Marker::ADD; + marker.scale.x = 0.5; + marker.scale.y = 0.5; + marker.scale.z = 0.5; + marker.pose.position.x = img_points[i].x; + marker.pose.position.y = img_points[i].y; + marker.pose.position.z = img_points[i].z; + marker.pose.orientation.x = 0.0; + marker.pose.orientation.y = 0.0; + marker.pose.orientation.z = 0.0; + marker.pose.orientation.w = 1.0; + + if (ids[i].find("green")!=std::string::npos) + { + marker.color.r = 0.0; + marker.color.g = 1.0; + marker.color.b = 0.0; + } + else if (ids[i].find("red")!=std::string::npos) + { + marker.color.r = 1.0; + marker.color.g = 0.0; + marker.color.b = 0.0; + } + else if (ids[i].find("yellow")!=std::string::npos) + { + marker.color.r = 1.0; + marker.color.g = 1.0; + marker.color.b = 0.0; + } + else if (ids[i].find("blue")!=std::string::npos) + { + marker.color.r = 0.0; + marker.color.g = 0.0; + marker.color.b = 1.0; + } + else + { + ROS_WARN("VisualGpsAlgNode::publish_markers: unrecognized point id: %s", ids[i].c_str()); + marker.color.r = 1.0; + marker.color.g = 1.0; + marker.color.b = 1.0; + } + marker.color.a = 1.0; + marker.lifetime = ros::Duration(1.0f); + + this->markers_MarkerArray_msg_.markers.push_back(marker); + } + + this->markers_publisher_.publish(this->markers_MarkerArray_msg_); +} +