point_cloud_publisher.cpp
Go to the documentation of this file.
1 #include <sensor_msgs/PointCloud2.h>
3 
4 #include "pf_driver/PFR2300Header.h"
6 
7 PointcloudPublisher::PointcloudPublisher(std::shared_ptr<ScanConfig> config, std::shared_ptr<ScanParameters> params,
8  const std::string& scan_topic, const std::string& frame_id,
9  const uint16_t num_layers, const std::string& part)
10  : PFDataPublisher(config, params), layer_prev_(-1)
11 {
12  ros::NodeHandle p_nh("~/");
13 
14  XmlRpc::XmlRpcValue angles_param;
15  p_nh.getParam("correction_params", angles_param);
16 
17  angles_.resize(num_layers);
18 
19  for (size_t i = 0; i < angles_param.size(); i++)
20  {
21  angles_[i] = angles_param[i]["ang"];
22  auto coeff_param = angles_param[i]["coeff"];
23  std::vector<double> coeffs;
24  for (size_t j = 0; j < coeff_param.size(); j++)
25  {
26  coeffs.push_back(coeff_param[j]);
27  }
28 
29  correction_params_[angles_[i]] = coeffs;
30  }
31 
32  for (int i = 0; i < angles_param.size(); i++)
33  {
34  std::string topic = scan_topic + "_" + std::to_string(i + 1);
35  std::string id = frame_id + "_" + std::to_string(i + 1);
36 
37  // init frames for each layer
38  publish_static_transform(frame_id, id, angles_[i]);
39 
40  scan_publishers_.push_back(p_nh.advertise<sensor_msgs::LaserScan>(topic.c_str(), 100));
41  frame_ids_.push_back(id);
42  }
43 
44  cloud_.reset(new sensor_msgs::PointCloud2());
45  pcl_publisher_ = nh_.advertise<sensor_msgs::PointCloud2>(scan_topic, 1);
46  header_publisher_ = nh_.advertise<pf_driver::PFR2300Header>("/r2300_header", 1);
47  frame_id_.assign(frame_id);
48 }
49 
51 {
52  cloud_.reset(new sensor_msgs::PointCloud2());
53  layer_prev_ = -1;
54 }
55 
56 void PointcloudPublisher::publish_static_transform(const std::string& parent, const std::string& child,
57  int inclination_angle)
58 {
59  geometry_msgs::TransformStamped transform;
60 
61  transform.header.stamp = ros::Time::now();
62  transform.header.frame_id = parent.c_str();
63  transform.child_frame_id = child.c_str();
64  transform.transform.translation.x = 0;
65  transform.transform.translation.y = 0;
66  transform.transform.translation.z = 0;
67 
68  tf2::Quaternion quat;
69  double ang = inclination_angle / 10000.0 * M_PI / 180.0;
70  quat.setRPY(0, ang, 0);
71  transform.transform.rotation.x = quat.x();
72  transform.transform.rotation.y = quat.y();
73  transform.transform.rotation.z = quat.z();
74  transform.transform.rotation.w = quat.w();
75 
77 }
78 
79 void PointcloudPublisher::publish_scan(sensor_msgs::LaserScanPtr msg, uint16_t idx)
80 {
81  msg->header.frame_id = frame_ids_.at(idx);
82  scan_publishers_.at(idx).publish(msg);
83 }
84 
85 void PointcloudPublisher::handle_scan(sensor_msgs::LaserScanPtr msg, uint16_t layer_idx, int layer_inclination,
86  bool apply_correction)
87 {
88  publish_scan(msg, layer_idx);
89 
90  sensor_msgs::PointCloud2 c;
91  int channelOptions = laser_geometry::channel_option::Intensity;
92  if (apply_correction)
93  {
94  // since 'apply_correction' calculates the point cloud from laser scan message,
95  // 'transformLaserScanToPointCloud' is not be needed anymore
96  // just 'projectLaser' is enough just so that it initializes the pointcloud message correctly
97  projector_.projectLaser(*msg, c);
98  project_laser(c, msg, layer_inclination);
99  }
100  else
101  {
102  projector_.transformLaserScanToPointCloud(frame_id_, *msg, c, tfListener_, -1.0, channelOptions);
103  }
104 
105  if (layer_idx <= layer_prev_)
106  {
107  if (!cloud_->data.empty())
108  {
109  cloud_->header.frame_id = frame_id_;
111  cloud_.reset(new sensor_msgs::PointCloud2());
112  }
113  copy_pointcloud(*cloud_, c);
114  }
115  else
116  {
117  add_pointcloud(*cloud_, c);
118  }
119  layer_prev_ = layer_idx;
120 }
121 
122 void PointcloudPublisher::copy_pointcloud(sensor_msgs::PointCloud2& c1, sensor_msgs::PointCloud2 c2)
123 {
124  c1.header.frame_id = c2.header.frame_id;
125  c1.height = c2.height;
126  c1.width = c2.width;
127  c1.is_bigendian = c2.is_bigendian;
128  c1.point_step = c2.point_step;
129  c1.row_step = c2.row_step;
130 
131  c1.fields = std::move(c2.fields);
132  c1.data = std::move(c2.data);
133 }
134 
135 void PointcloudPublisher::add_pointcloud(sensor_msgs::PointCloud2& c1, sensor_msgs::PointCloud2 c2)
136 {
137  pcl::PCLPointCloud2 p1, p2;
138  pcl_conversions::toPCL(c1, p1);
139  pcl::PointCloud<pcl::PointXYZI>::Ptr p1_cloud(new pcl::PointCloud<pcl::PointXYZI>);
140 
141  // handle when point cloud is empty
142  pcl::fromPCLPointCloud2(p1, *p1_cloud);
143 
144  pcl_conversions::toPCL(c2, p2);
145  pcl::PointCloud<pcl::PointXYZI>::Ptr p2_cloud(new pcl::PointCloud<pcl::PointXYZI>);
146  pcl::fromPCLPointCloud2(p2, *p2_cloud);
147 
148  *p1_cloud += *p2_cloud;
149  pcl::toROSMsg(*p1_cloud.get(), c1);
150 }
151 
152 void PointcloudPublisher::project_laser(sensor_msgs::PointCloud2& c, sensor_msgs::LaserScanPtr msg,
153  const int layer_inclination)
154 {
155  pcl::PCLPointCloud2 p;
157  pcl::PointCloud<pcl::PointXYZI>::Ptr p_cloud(new pcl::PointCloud<pcl::PointXYZI>);
158 
159  // handle when point cloud is empty
160  pcl::fromPCLPointCloud2(p, *p_cloud);
161 
162  size_t cl_idx = 0;
163 
164  double angle_v_deg = layer_inclination / 10000.0;
165  double angle_v = (M_PI / 180.0) * angle_v_deg;
166 
167  for (size_t i = 0; i < msg->ranges.size(); i++)
168  {
169  // num of points in cloud is sometimes less than that in laser scan because of
170  // https://github.com/ros-perception/laser_geometry/blob/indigo-devel/src/laser_geometry.cpp#L110
171  if (msg->ranges[i] < msg->range_min || msg->ranges[i] >= msg->range_max)
172  {
173  continue;
174  }
175  double angle_h = msg->angle_min + msg->angle_increment * (double)i;
176 
177  angle_v = correction_params_[layer_inclination][0] * angle_h * angle_h +
178  correction_params_[layer_inclination][1] * angle_h + correction_params_[layer_inclination][2];
179 
180  p_cloud->points[cl_idx].x = cos(angle_h) * cos(angle_v) * msg->ranges[i];
181  p_cloud->points[cl_idx].y = sin(angle_h) * cos(angle_v) * msg->ranges[i];
182  p_cloud->points[cl_idx].z = sin(angle_v) * msg->ranges[i];
183 
184  cl_idx++;
185  }
186 
187  pcl::toROSMsg(*p_cloud.get(), c);
188 }
virtual void resetCurrentScans()
void projectLaser(const sensor_msgs::LaserScan &scan_in, sensor_msgs::PointCloud &cloud_out, double range_cutoff=-1.0, int channel_options=channel_option::Default)
virtual void handle_scan(sensor_msgs::LaserScanPtr msg, uint16_t layer_idx, int layer_inclination, bool apply_correction)
std::string frame_id_
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
ros::Publisher pcl_publisher_
void publish_static_transform(const std::string &parent, const std::string &child, int inclination_angle)
std::vector< ros::Publisher > scan_publishers_
void publish_scan(sensor_msgs::LaserScanPtr msg, uint16_t idx)
tf2_ros::StaticTransformBroadcaster static_broadcaster_
ros::Publisher header_publisher_
std::vector< std::string > frame_ids_
void publish(const boost::shared_ptr< M > &message) const
bool getParam(const std::string &key, std::string &s) const
void copy_pointcloud(sensor_msgs::PointCloud2 &c1, sensor_msgs::PointCloud2 c2)
void toPCL(const ros::Time &stamp, std::uint64_t &pcl_stamp)
ros::NodeHandle nh_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
std::map< int, std::vector< double > > correction_params_
std::vector< int > angles_
void add_pointcloud(sensor_msgs::PointCloud2 &c1, sensor_msgs::PointCloud2 c2)
sensor_msgs::PointCloud2Ptr cloud_
laser_geometry::LaserProjection projector_
tf::TransformListener tfListener_
void toROSMsg(const sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
static Time now()
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
void transformLaserScanToPointCloud(const std::string &target_frame, const sensor_msgs::LaserScan &scan_in, sensor_msgs::PointCloud &cloud_out, tf::Transformer &tf, double range_cutoff, int channel_options=channel_option::Default)
void sendTransform(const geometry_msgs::TransformStamped &transform)
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
PointcloudPublisher(std::shared_ptr< ScanConfig > config, std::shared_ptr< ScanParameters > params, const std::string &scan_topic, const std::string &frame_id, const uint16_t num_layers, const std::string &part)
void project_laser(sensor_msgs::PointCloud2 &c, sensor_msgs::LaserScanPtr msg, const int layer_inclination)


pf_driver
Author(s): Harsh Deshpande
autogenerated on Fri Feb 24 2023 03:59:35