datacontainerbase.h
Go to the documentation of this file.
1 #ifndef VELODYNE_POINTCLOUD_DATACONTAINERBASE_H
2 #define VELODYNE_POINTCLOUD_DATACONTAINERBASE_H
3 // Copyright (C) 2012, 2019 Austin Robot Technology, Jack O'Quin, Joshua Whitley, Sebastian Pütz
4 // All rights reserved.
5 //
6 // Software License Agreement (BSD License 2.0)
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
10 // are met:
11 //
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above
15 // copyright notice, this list of conditions and the following
16 // disclaimer in the documentation and/or other materials provided
17 // with the distribution.
18 // * Neither the name of {copyright_holder} nor the names of its
19 // contributors may be used to endorse or promote products derived
20 // from this software without specific prior written permission.
21 //
22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 // POSSIBILITY OF SUCH DAMAGE.
34 
35 #include <tf/transform_listener.h>
36 #include <velodyne_msgs/VelodyneScan.h>
38 #include <Eigen/Dense>
39 #include <string>
40 #include <algorithm>
41 #include <cstdarg>
42 
44 {
46 {
47 public:
48  DataContainerBase(const double max_range, const double min_range, const std::string& target_frame,
49  const std::string& fixed_frame, const unsigned int init_width, const unsigned int init_height,
50  const bool is_dense, const unsigned int scans_per_packet,
52  : config_(max_range, min_range, target_frame, fixed_frame, init_width, init_height, is_dense, scans_per_packet)
53  , tf_ptr(tf_ptr)
54  {
55  va_list vl;
56  cloud.fields.clear();
57  cloud.fields.reserve(fields);
58  va_start(vl, fields);
59  int offset = 0;
60  for (int i = 0; i < fields; ++i)
61  {
62  // Create the corresponding PointField
63  std::string name(va_arg(vl, char*));
64  int count(va_arg(vl, int));
65  int datatype(va_arg(vl, int));
66  offset = addPointField(cloud, name, count, datatype, offset);
67  }
68  va_end(vl);
69  cloud.point_step = offset;
70  cloud.row_step = init_width * cloud.point_step;
71  if (config_.transform && !tf_ptr)
72  {
74  }
75  }
76 
77  struct Config
78  {
79  double max_range;
80  double min_range;
81  std::string target_frame;
82  std::string fixed_frame;
83  unsigned int init_width;
84  unsigned int init_height;
85  bool is_dense;
86  unsigned int scans_per_packet;
87  bool transform;
88 
89  Config(double max_range, double min_range, std::string target_frame, std::string fixed_frame,
90  unsigned int init_width, unsigned int init_height, bool is_dense, unsigned int scans_per_packet)
91  : max_range(max_range)
92  , min_range(min_range)
93  , target_frame(target_frame)
94  , fixed_frame(fixed_frame)
95  , transform(fixed_frame != target_frame)
96  , init_width(init_width)
97  , init_height(init_height)
98  , is_dense(is_dense)
99  , scans_per_packet(scans_per_packet)
100  {
101  ROS_INFO_STREAM("Initialized container with "
102  << "min_range: " << min_range << ", max_range: " << max_range
103  << ", target_frame: " << target_frame << ", fixed_frame: " << fixed_frame
104  << ", init_width: " << init_width << ", init_height: " << init_height
105  << ", is_dense: " << is_dense << ", scans_per_packet: " << scans_per_packet);
106  }
107  };
108 
109  virtual void setup(const velodyne_msgs::VelodyneScan::ConstPtr& scan_msg)
110  {
111  cloud.header = scan_msg->header;
112  cloud.data.resize(scan_msg->packets.size() * config_.scans_per_packet * cloud.point_step);
113  cloud.width = config_.init_width;
114  cloud.height = config_.init_height;
115  cloud.is_dense = static_cast<uint8_t>(config_.is_dense);
116  }
117 
118  virtual void addPoint(float x, float y, float z, const uint16_t ring, const uint16_t azimuth, const float distance,
119  const float intensity, const float time) = 0;
120  virtual void newLine() = 0;
121 
122  const sensor_msgs::PointCloud2& finishCloud()
123  {
124  cloud.data.resize(cloud.point_step * cloud.width * cloud.height);
125 
126  if (!config_.target_frame.empty())
127  {
128  cloud.header.frame_id = config_.target_frame;
129  }
130 
131  ROS_DEBUG_STREAM("Prepared cloud width" << cloud.height * cloud.width
132  << " Velodyne points, time: " << cloud.header.stamp);
133  return cloud;
134  }
135 
136  void configure(const double max_range, const double min_range, const std::string fixed_frame,
137  const std::string target_frame)
138  {
143 
144  config_.transform = fixed_frame.compare(target_frame) != 0;
145  if (config_.transform && !tf_ptr)
146  {
148  }
149  }
150 
151  sensor_msgs::PointCloud2 cloud;
152 
153  inline void vectorTfToEigen(tf::Vector3& tf_vec, Eigen::Vector3f& eigen_vec)
154  {
155  eigen_vec(0) = tf_vec[0];
156  eigen_vec(1) = tf_vec[1];
157  eigen_vec(2) = tf_vec[2];
158  }
159 
160  inline bool computeTransformation(const ros::Time& time)
161  {
163  try
164  {
165  tf_ptr->lookupTransform(config_.target_frame, cloud.header.frame_id, time, transform);
166  }
167  catch (tf::LookupException& e)
168  {
169  ROS_ERROR("%s", e.what());
170  return false;
171  }
172  catch (tf::ExtrapolationException& e)
173  {
174  ROS_ERROR("%s", e.what());
175  return false;
176  }
177 
178  tf::Quaternion quaternion = transform.getRotation();
179  Eigen::Quaternionf rotation(quaternion.w(), quaternion.x(), quaternion.y(), quaternion.z());
180 
181  Eigen::Vector3f eigen_origin;
182  vectorTfToEigen(transform.getOrigin(), eigen_origin);
183  Eigen::Translation3f translation(eigen_origin);
184  transformation = translation * rotation;
185  return true;
186  }
187 
188  inline void transformPoint(float& x, float& y, float& z)
189  {
190  Eigen::Vector3f p = transformation * Eigen::Vector3f(x, y, z);
191  x = p.x();
192  y = p.y();
193  z = p.z();
194  }
195 
196  inline bool pointInRange(float range)
197  {
198  return (range >= config_.min_range && range <= config_.max_range);
199  }
200 
201 protected:
204  Eigen::Affine3f transformation;
205 };
206 } /* namespace velodyne_rawdata */
207 #endif // VELODYNE_POINTCLOUD_DATACONTAINERBASE_H
const sensor_msgs::PointCloud2 & finishCloud()
double min_range
minimum range to publish
virtual void addPoint(float x, float y, float z, const uint16_t ring, const uint16_t azimuth, const float distance, const float intensity, const float time)=0
TFSIMD_FORCE_INLINE tfScalar distance(const Vector3 &v) const
double max_range
maximum range to publish
TFSIMD_FORCE_INLINE const tfScalar & y() const
bool computeTransformation(const ros::Time &time)
void vectorTfToEigen(tf::Vector3 &tf_vec, Eigen::Vector3f &eigen_vec)
std::string fixed_frame
fixed frame used for transform
boost::shared_ptr< tf::TransformListener > tf_ptr
transform listener
TFSIMD_FORCE_INLINE const tfScalar & x() const
void transformPoint(float &x, float &y, float &z)
#define ROS_DEBUG_STREAM(args)
TFSIMD_FORCE_INLINE Vector3 & getOrigin()
TFSIMD_FORCE_INLINE const tfScalar & z() const
bool transform
enable / disable transform points
#define ROS_INFO_STREAM(args)
Quaternion getRotation() const
DataContainerBase(const double max_range, const double min_range, const std::string &target_frame, const std::string &fixed_frame, const unsigned int init_width, const unsigned int init_height, const bool is_dense, const unsigned int scans_per_packet, boost::shared_ptr< tf::TransformListener > &tf_ptr, int fields,...)
Config(double max_range, double min_range, std::string target_frame, std::string fixed_frame, unsigned int init_width, unsigned int init_height, bool is_dense, unsigned int scans_per_packet)
void configure(const double max_range, const double min_range, const std::string fixed_frame, const std::string target_frame)
std::string target_frame
target frame to transform a point
virtual void setup(const velodyne_msgs::VelodyneScan::ConstPtr &scan_msg)
#define ROS_ERROR(...)


velodyne_pointcloud
Author(s): Jack O'Quin, Piyush Khandelwal, Jesse Vera, Sebastian Pütz
autogenerated on Sun Sep 6 2020 03:25:30