pcl_coloring.cpp
Go to the documentation of this file.
1 /*
2  velo2cam_calibration - Automatic calibration algorithm for extrinsic parameters of a stereo camera and a velodyne
3  Copyright (C) 2017-2018 Jorge Beltran, Carlos Guindel
4 
5  This file is part of velo2cam_calibration.
6 
7  velo2cam_calibration is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 2 of the License, or
10  (at your option) any later version.
11 
12  velo2cam_calibration is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with velo2cam_calibration. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 /*
22  pcl_coloring: Color the point cloud using the RGB values from the image
23 */
24 
25 #define DEBUG 1
26 
27 #include <ros/ros.h>
28 #include "ros/package.h"
29 #include <tf/tf.h>
30 #include <tf/transform_listener.h>
31 #include <pcl/point_cloud.h>
33 #include <pcl/common/transforms.h>
34 #include <pcl_ros/transforms.h>
35 #include <opencv2/opencv.hpp>
36 #include <cv_bridge/cv_bridge.h>
38 #include <sensor_msgs/CameraInfo.h>
42 
43 using namespace std;
44 using namespace sensor_msgs;
45 
46 typedef pcl::PointCloud<pcl::PointXYZRGB> PointCloudXYZRGB;
49 
50 void callback(const PointCloud2::ConstPtr& pcl_msg, const CameraInfoConstPtr& cinfo_msg, const ImageConstPtr& image_msg){
51  if(DEBUG) ROS_INFO("\n\nColouring VELODYNE CLOUD!!");;
52  // Conversion
53  cv_bridge::CvImageConstPtr cv_img_ptr;
54  cv::Mat image;
55  try{
56  image = cv_bridge::toCvShare(image_msg, "bgr8")->image;
57  }catch (cv_bridge::Exception& e){
58  ROS_ERROR("cv_bridge exception: %s", e.what());
59  return;
60  }
61 
63  cam_model_.fromCameraInfo(cinfo_msg);
64 
65  pcl::PointCloud<pcl::PointXYZ>::Ptr pcl_cloud(new pcl::PointCloud<pcl::PointXYZ>); // From ROS Msg
66  pcl::PointCloud<pcl::PointXYZ>::Ptr trans_cloud(new pcl::PointCloud<pcl::PointXYZ>); // After transformation
67  PointCloudXYZRGB::Ptr coloured = PointCloudXYZRGB::Ptr(new PointCloudXYZRGB); // For coloring purposes
68  fromROSMsg(*pcl_msg, *pcl_cloud);
69 
70  tf::TransformListener listener;
71  tf::StampedTransform transform;
72  if(DEBUG) cout << "FRAME ID "<< pcl_cloud->header.frame_id << endl;
73 
74  try{
75  listener.waitForTransform(target_frame.c_str(), source_frame.c_str(), ros::Time(0), ros::Duration(20.0));
76  listener.lookupTransform (target_frame.c_str(), source_frame.c_str(), ros::Time(0), transform);
77  }catch (tf::TransformException& ex) {
78  ROS_WARN("[draw_frames] TF exception:\n%s", ex.what());
79  return;
80  }
81  pcl_ros::transformPointCloud (*pcl_cloud, *trans_cloud, transform);
82  trans_cloud->header.frame_id = target_frame;
83 
84  pcl::copyPointCloud(*trans_cloud, *coloured);
85 
86  for (pcl::PointCloud<pcl::PointXYZRGB>::iterator pt = coloured->points.begin(); pt < coloured->points.end(); ++pt)
87  {
88  cv::Point3d pt_cv((*pt).x, (*pt).y, (*pt).z);
89  cv::Point2d uv;
90  uv = cam_model_.project3dToPixel(pt_cv);
91 
92  if(uv.x>0 && uv.x < image.cols && uv.y > 0 && uv.y < image.rows){
93  // Copy colour to laser pointcloud
94  (*pt).b = image.at<cv::Vec3b>(uv)[0];
95  (*pt).g = image.at<cv::Vec3b>(uv)[1];
96  (*pt).r = image.at<cv::Vec3b>(uv)[2];
97  }
98 
99  }
100  if(DEBUG) ROS_INFO("Publish coloured PC");
101 
102  // Publish coloured PointCloud
103  sensor_msgs::PointCloud2 pcl_colour_ros;
104  pcl::toROSMsg(*coloured, pcl_colour_ros);
105  pcl_colour_ros.header.stamp = pcl_msg->header.stamp ;
106  pcl_pub.publish(pcl_colour_ros);
107 }
108 
109 int main(int argc, char **argv){
110  ros::init(argc, argv, "pcl_coloring");
111  ros::NodeHandle nh_("~"); // LOCAL
112  // Parameters
113  nh_.param<std::string>("target_frame", target_frame, "/stereo_camera");
114  nh_.param<std::string>("source_frame", source_frame, "/velodyne");
115 
116  // Subscribers
117  message_filters::Subscriber<PointCloud2> pc_sub(nh_, "pointcloud", 1);
118  message_filters::Subscriber<CameraInfo> cinfo_sub(nh_, "camera_info", 1);
119  message_filters::Subscriber<Image> image_sub(nh_, "image", 1);
120 
121  pcl_pub = nh_.advertise<PointCloud2> ("velodyne_coloured", 1);
122 
124  // ExactTime takes a queue size as its constructor argument, hence MySyncPolicy(10)
125  message_filters::Synchronizer<MySyncPolicy> sync(MySyncPolicy(10), pc_sub, cinfo_sub, image_sub);
126  sync.registerCallback(boost::bind(&callback, _1, _2, _3));
127 
128  ros::spin();
129  return 0;
130 }
CvImageConstPtr toCvShare(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
void publish(const boost::shared_ptr< M > &message) const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
string source_frame
#define ROS_WARN(...)
ROSCPP_DECL void spin(Spinner &spinner)
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
void callback(const PointCloud2::ConstPtr &pcl_msg, const CameraInfoConstPtr &cinfo_msg, const ImageConstPtr &image_msg)
Connection registerCallback(C &callback)
pcl::PointCloud< pcl::PointXYZRGB > PointCloudXYZRGB
#define ROS_INFO(...)
bool fromCameraInfo(const sensor_msgs::CameraInfo &msg)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
#define DEBUG
int main(int argc, char **argv)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const
void transformPointCloud(const pcl::PointCloud< PointT > &cloud_in, pcl::PointCloud< PointT > &cloud_out, const tf::Transform &transform)
void toROSMsg(const sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
cv::Point2d project3dToPixel(const cv::Point3d &xyz) const
#define ROS_ERROR(...)
string target_frame
ros::Publisher pcl_pub


velo2cam_calibration
Author(s): Jorge Beltran , Carlos Guindel
autogenerated on Thu Feb 28 2019 03:24:25