measurement_buffer.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement
4  *
5  * Copyright (c) 2018, Simbe Robotics, Inc.
6  * All rights reserved.
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 Simbe Robotics, Inc. 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  * Author: Steve Macenski (steven.macenski@simberobotics.com)
36  *********************************************************************/
37 
40 
41 namespace buffer
42 {
43 
44 /*****************************************************************************/
45 MeasurementBuffer::MeasurementBuffer(const std::string& topic_name, \
46  const double& observation_keep_time, \
47  const double& expected_update_rate, \
48  const double& min_obstacle_height, \
49  const double& max_obstacle_height, \
50  const double& obstacle_range, \
52  const std::string& global_frame, \
53  const std::string& sensor_frame, \
54  const double& tf_tolerance, \
55  const double& min_d, \
56  const double& max_d, \
57  const double& vFOV, \
58  const double& vFOVPadding, \
59  const double& hFOV, \
60  const double& decay_acceleration, \
61  const bool& marking, \
62  const bool& clearing, \
63  const double& voxel_size, \
64  const bool& voxel_filter, \
65  const int& voxel_min_points, \
66  const bool& enabled, \
67  const bool& clear_buffer_after_reading, \
68  const ModelType& model_type) :
69 /*****************************************************************************/
70  _buffer(tf), _observation_keep_time(observation_keep_time),
71  _expected_update_rate(expected_update_rate),_last_updated(ros::Time::now()),
72  _global_frame(global_frame), _sensor_frame(sensor_frame),
73  _topic_name(topic_name), _min_obstacle_height(min_obstacle_height),
74  _max_obstacle_height(max_obstacle_height), _obstacle_range(obstacle_range),
75  _tf_tolerance(tf_tolerance), _min_z(min_d), _max_z(max_d),
76  _vertical_fov(vFOV), _vertical_fov_padding(vFOVPadding),
77  _horizontal_fov(hFOV), _decay_acceleration(decay_acceleration),
78  _marking(marking), _clearing(clearing), _voxel_size(voxel_size),
79  _voxel_filter(voxel_filter), _voxel_min_points(voxel_min_points),
80  _enabled(enabled), _clear_buffer_after_reading(clear_buffer_after_reading),
81  _model_type(model_type)
82 {
83 }
84 
85 /*****************************************************************************/
87 /*****************************************************************************/
88 {
89 }
90 
91 /*****************************************************************************/
92 void MeasurementBuffer::BufferROSCloud(const sensor_msgs::PointCloud2& cloud)
93 /*****************************************************************************/
94 {
95  // add a new measurement to be populated
97 
98  const std::string origin_frame = \
99  _sensor_frame == "" ? cloud.header.frame_id : _sensor_frame;
100 
101  try
102  {
103  // transform into global frame
104  geometry_msgs::PoseStamped local_pose, global_pose;
105  local_pose.pose.position.x=0;
106  local_pose.pose.position.y=0;
107  local_pose.pose.position.z=0;
108  local_pose.pose.orientation.x=0;
109  local_pose.pose.orientation.y=0;
110  local_pose.pose.orientation.z=0;
111  local_pose.pose.orientation.w=1;
112  local_pose.header.stamp = cloud.header.stamp;
113  local_pose.header.frame_id = origin_frame;
114 
115  _buffer.canTransform(_global_frame, local_pose.header.frame_id , \
116  local_pose.header.stamp, ros::Duration(0.5));
117  _buffer.transform(local_pose, global_pose, _global_frame);
118 
119  _observation_list.front()._origin.x = global_pose.pose.position.x;
120  _observation_list.front()._origin.y = global_pose.pose.position.y;
121  _observation_list.front()._origin.z = global_pose.pose.position.z;
122 
123  _observation_list.front()._orientation = global_pose.pose.orientation;
124  _observation_list.front()._obstacle_range_in_m = _obstacle_range;
125  _observation_list.front()._min_z_in_m = _min_z;
126  _observation_list.front()._max_z_in_m = _max_z;
127  _observation_list.front()._vertical_fov_in_rad = _vertical_fov;
128  _observation_list.front()._vertical_fov_padding_in_m = _vertical_fov_padding;
129  _observation_list.front()._horizontal_fov_in_rad = _horizontal_fov;
130  _observation_list.front()._decay_acceleration = _decay_acceleration;
131  _observation_list.front()._clearing = _clearing;
132  _observation_list.front()._marking = _marking;
133  _observation_list.front()._model_type = _model_type;
134 
135  if (_clearing && !_marking)
136  {
137  // no need to buffer points
138  return;
139  }
140 
141  // transform the cloud in the global frame
142  point_cloud_ptr cld_global(new sensor_msgs::PointCloud2());
143  geometry_msgs::TransformStamped tf_stamped = _buffer.lookupTransform( \
144  _global_frame, cloud.header.frame_id, cloud.header.stamp);
145  tf2::doTransform (cloud, *cld_global, tf_stamped);
146 
147  pcl::PCLPointCloud2::Ptr cloud_pcl (new pcl::PCLPointCloud2 ());
148  pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2 ());
149 
150  pcl_conversions::toPCL(*cld_global, *cloud_pcl);
151 
152  // remove points that are below or above our height restrictions, and
153  // in the same time, remove NaNs and if user wants to use it, combine with a
154  if ( _voxel_filter )
155  {
156  pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
157  sor.setInputCloud (cloud_pcl);
158  sor.setFilterFieldName("z");
159  sor.setFilterLimits(_min_obstacle_height,_max_obstacle_height);
160  sor.setDownsampleAllData(false);
161  sor.setLeafSize ((float)_voxel_size,
162  (float)_voxel_size,
163  (float)_voxel_size);
164  sor.setMinimumPointsNumberPerVoxel(static_cast<unsigned int>(_voxel_min_points));
165  sor.filter(*cloud_filtered);
166  }
167  else
168  {
169  pcl::PassThrough<pcl::PCLPointCloud2> pass_through_filter;
170  pass_through_filter.setInputCloud(cloud_pcl);
171  pass_through_filter.setKeepOrganized(false);
172  pass_through_filter.setFilterFieldName("z");
173  pass_through_filter.setFilterLimits( \
175  pass_through_filter.filter(*cloud_filtered);
176  }
177 
178  pcl_conversions::fromPCL(*cloud_filtered, *cld_global);
179  _observation_list.front()._cloud = cld_global;
180  }
181  catch (tf::TransformException& ex)
182  {
183  // if fails, remove the empty observation
184  _observation_list.pop_front();
185  ROS_ERROR( \
186  "TF Exception for sensor frame: %s, cloud frame: %s, %s", \
187  _sensor_frame.c_str(), cloud.header.frame_id.c_str(), ex.what());
188  return;
189  }
190 
193 }
194 
195 /*****************************************************************************/
197  std::vector<observation::MeasurementReading>& observations)
198 /*****************************************************************************/
199 {
201 
202  for (readings_iter it = _observation_list.begin(); \
203  it != _observation_list.end(); ++it)
204  {
205  observations.push_back(*it);
206  }
207 }
208 
209 /*****************************************************************************/
211 /*****************************************************************************/
212 {
213  if (_observation_list.empty())
214  {
215  return;
216  }
217 
218  readings_iter it = _observation_list.begin();
220  {
221  _observation_list.erase(++it, _observation_list.end());
222  return;
223  }
224 
225  for (it = _observation_list.begin(); it != _observation_list.end(); ++it)
226  {
228  const ros::Duration time_diff = _last_updated - obs._cloud->header.stamp;
229 
230  if (time_diff > _observation_keep_time)
231  {
232  _observation_list.erase(it, _observation_list.end());
233  return;
234  }
235  }
236 }
237 
238 /*****************************************************************************/
240 /*****************************************************************************/
241 {
242  _observation_list.clear();
243 }
244 
245 /*****************************************************************************/
247 /*****************************************************************************/
248 {
250 }
251 
252 /*****************************************************************************/
254 /*****************************************************************************/
255 {
257  {
258  return true;
259  }
260 
261  const ros::Duration update_time = ros::Time::now() - _last_updated;
262  const bool current = update_time.toSec() <= _expected_update_rate.toSec();
263  if (!current)
264  {
265  ROS_WARN_THROTTLE(10.,
266  "%s buffer updated in %.2fs, it should be updated every %.2fs.",
267  _topic_name.c_str(), update_time.toSec(), _expected_update_rate.toSec());
268  }
269  return current;
270 }
271 
272 /*****************************************************************************/
274 /*****************************************************************************/
275 {
276  return _enabled;
277 }
278 
279 /*****************************************************************************/
280 void MeasurementBuffer::SetEnabled(const bool& enabled)
281 /*****************************************************************************/
282 {
283  _enabled = enabled;
284 }
285 
286 /*****************************************************************************/
288 /*****************************************************************************/
289 {
291 }
292 
293 /*****************************************************************************/
295 /*****************************************************************************/
296 {
297  _lock.lock();
298 }
299 
300 /*****************************************************************************/
302 /*****************************************************************************/
303 {
304  _lock.unlock();
305 }
306 
307 } // namespace buffer
308 
void GetReadings(std::vector< observation::MeasurementReading > &observations)
T & transform(const T &in, T &out, const std::string &target_frame, ros::Duration timeout=ros::Duration(0.0)) const
void SetEnabled(const bool &enabled)
const ros::Duration _observation_keep_time
void doTransform(const T &data_in, T &data_out, const geometry_msgs::TransformStamped &transform)
std::list< observation::MeasurementReading > _observation_list
bool UpdatedAtExpectedRate(void) const
sensor_msgs::PointCloud2::Ptr point_cloud_ptr
virtual bool canTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &target_time, const ros::Duration timeout, std::string *errstr=NULL) const
MeasurementBuffer(const std::string &topic_name, const double &observation_keep_time, const double &expected_update_rate, const double &min_obstacle_height, const double &max_obstacle_height, const double &obstacle_range, tf2_ros::Buffer &tf, const std::string &global_frame, const std::string &sensor_frame, const double &tf_tolerance, const double &min_d, const double &max_d, const double &vFOV, const double &vFOVPadding, const double &hFOV, const double &decay_acceleration, const bool &marking, const bool &clearing, const double &voxel_size, const bool &voxel_filter, const int &voxel_min_points, const bool &enabled, const bool &clear_buffer_after_reading, const ModelType &model_type)
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
#define ROS_WARN_THROTTLE(period,...)
boost::recursive_mutex _lock
void toPCL(const ros::Time &stamp, std::uint64_t &pcl_stamp)
sensor_msgs::PointCloud2::Ptr _cloud
const ros::Duration _expected_update_rate
static Time now()
void fromPCL(const std::uint64_t &pcl_stamp, ros::Time &stamp)
void BufferROSCloud(const sensor_msgs::PointCloud2 &cloud)
#define ROS_ERROR(...)
std::list< observation::MeasurementReading >::iterator readings_iter


spatio_temporal_voxel_layer
Author(s):
autogenerated on Wed May 3 2023 03:05:44