box_filter.cpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Robot Operating System code by the University of Osnabrück
5  * Copyright (c) 2015, University of Osnabrück
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  * 1. Redistributions of source code must retain the above
13  * copyright notice, this list of conditions and the following
14  * disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  *
21  * 3. Neither the name of the copyright holder nor the names of its
22  * contributors may be used to endorse or promote products derived
23  * from this software without specific prior written permission.
24  *
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
30  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
33  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
35  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  *
38  *
39  *
40  * box_filter.cpp
41  *
42  * author: Sebastian Pütz <spuetz@uni-osnabrueck.de>
43  */
44 
46 #include <ros/ros.h>
47 
49 
50 }
51 
53  up_and_running_ = true;
54  double min_x = 0, min_y = 0, min_z = 0, max_x = 0, max_y = 0, max_z = 0;
55  bool box_frame_set = getParam("box_frame", box_frame_);
56  bool x_max_set = getParam("max_x", max_x);
57  bool y_max_set = getParam("max_y", max_y);
58  bool z_max_set = getParam("max_z", max_z);
59  bool x_min_set = getParam("min_x", min_x);
60  bool y_min_set = getParam("min_y", min_y);
61  bool z_min_set = getParam("min_z", min_z);
62  bool invert_set = getParam("invert", invert_filter);
63 
64  ROS_INFO("BOX filter started");
65 
66  max_.setX(max_x);
67  max_.setY(max_y);
68  max_.setZ(max_z);
69  min_.setX(min_x);
70  min_.setY(min_y);
71  min_.setZ(min_z);
72 
73  if(!box_frame_set){
74  ROS_ERROR("box_frame is not set!");
75  }
76  if(!x_max_set){
77  ROS_ERROR("max_x is not set!");
78  }
79  if(!y_max_set){
80  ROS_ERROR("max_y is not set!");
81  }
82  if(!z_max_set){
83  ROS_ERROR("max_z is not set!");
84  }
85  if(!x_min_set){
86  ROS_ERROR("min_x is not set!");
87  }
88  if(!y_min_set){
89  ROS_ERROR("min_y is not set!");
90  }
91  if(!z_min_set){
92  ROS_ERROR("min_z is not set!");
93  }
94  if(!invert_set){
95  ROS_INFO("invert filter not set, assuming false");
96  invert_filter=false;
97  }
98 
99 
100  return box_frame_set && x_max_set && y_max_set && z_max_set &&
101  x_min_set && y_min_set && z_min_set;
102 
103 }
104 
106  const sensor_msgs::LaserScan& input_scan,
107  sensor_msgs::LaserScan &output_scan)
108 {
109  output_scan = input_scan;
110  sensor_msgs::PointCloud2 laser_cloud;
111 
112  std::string error_msg;
113 
114  bool success = tf_.waitForTransform(
115  box_frame_,
116  input_scan.header.frame_id,
117  input_scan.header.stamp + ros::Duration().fromSec(input_scan.ranges.size()*input_scan.time_increment),
118  ros::Duration(1.0),
119  ros::Duration(0.01),
120  &error_msg
121  );
122  if(!success){
123  ROS_WARN("Could not get transform, irgnoring laser scan! %s", error_msg.c_str());
124  return false;
125  }
126 
127  try{
128  projector_.transformLaserScanToPointCloud(box_frame_, input_scan, laser_cloud, tf_);
129  }
130  catch(tf::TransformException& ex){
131  if(up_and_running_){
132  ROS_WARN_THROTTLE(1, "Dropping Scan: Tansform unavailable %s", ex.what());
133  return true;
134  }
135  else
136  {
137  ROS_INFO_THROTTLE(.3, "Ignoring Scan: Waiting for TF");
138  }
139  return false;
140  }
141  const int i_idx_c = sensor_msgs::getPointCloud2FieldIndex(laser_cloud, "index");
142  const int x_idx_c = sensor_msgs::getPointCloud2FieldIndex(laser_cloud, "x");
143  const int y_idx_c = sensor_msgs::getPointCloud2FieldIndex(laser_cloud, "y");
144  const int z_idx_c = sensor_msgs::getPointCloud2FieldIndex(laser_cloud, "z");
145 
146  if(i_idx_c == -1 || x_idx_c == -1 || y_idx_c == -1 || z_idx_c == -1){
147  ROS_INFO_THROTTLE(.3, "x, y, z and index fields are required, skipping scan");
148 
149  }
150 
151 
152  const int i_idx_offset = laser_cloud.fields[i_idx_c].offset;
153  const int x_idx_offset = laser_cloud.fields[x_idx_c].offset;
154  const int y_idx_offset = laser_cloud.fields[y_idx_c].offset;
155  const int z_idx_offset = laser_cloud.fields[z_idx_c].offset;
156 
157  const int pstep = laser_cloud.point_step;
158  const long int pcount = laser_cloud.width * laser_cloud.height;
159  const long int limit = pstep * pcount;
160 
161  int i_idx, x_idx, y_idx, z_idx;
162  for(
163  i_idx = i_idx_offset,
164  x_idx = x_idx_offset,
165  y_idx = y_idx_offset,
166  z_idx = z_idx_offset;
167 
168  x_idx < limit;
169 
170  i_idx += pstep,
171  x_idx += pstep,
172  y_idx += pstep,
173  z_idx += pstep)
174  {
175 
176  // TODO works only for float data types and with an index field
177  // I'm working on it, see https://github.com/ros/common_msgs/pull/78
178  float x = *((float*)(&laser_cloud.data[x_idx]));
179  float y = *((float*)(&laser_cloud.data[y_idx]));
180  float z = *((float*)(&laser_cloud.data[z_idx]));
181  int index = *((int*)(&laser_cloud.data[i_idx]));
182 
183  tf::Point point(x, y, z);
184 
185  if(!invert_filter){
186  if(inBox(point)){
187  output_scan.ranges[index] = std::numeric_limits<float>::quiet_NaN();
188  }
189  }
190  else{
191  if(!inBox(point)){
192  output_scan.ranges[index] = std::numeric_limits<float>::quiet_NaN();
193  }
194  }
195 
196  }
197  up_and_running_ = true;
198  return true;
199 }
200 
202  return
203  point.x() < max_.x() && point.x() > min_.x() &&
204  point.y() < max_.y() && point.y() > min_.y() &&
205  point.z() < max_.z() && point.z() > min_.z();
206 }
207 
static int getPointCloud2FieldIndex(const sensor_msgs::PointCloud2 &cloud, const std::string &field_name)
TFSIMD_FORCE_INLINE void setX(tfScalar x)
TFSIMD_FORCE_INLINE void setY(tfScalar y)
TFSIMD_FORCE_INLINE void setZ(tfScalar z)
laser_geometry::LaserProjection projector_
Definition: box_filter.h:78
TFSIMD_FORCE_INLINE const tfScalar & y() const
#define ROS_WARN(...)
tf::TransformListener tf_
Definition: box_filter.h:81
bool getParam(const std::string &name, std::string &value)
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
TFSIMD_FORCE_INLINE const tfScalar & x() const
#define ROS_INFO_THROTTLE(period,...)
TFSIMD_FORCE_INLINE const tfScalar & z() const
#define ROS_WARN_THROTTLE(period,...)
Duration & fromSec(double t)
#define ROS_INFO(...)
bool inBox(tf::Point &point)
Definition: box_filter.cpp:201
TFSIMD_FORCE_INLINE const tfScalar & y() const
TFSIMD_FORCE_INLINE const tfScalar & x() const
TFSIMD_FORCE_INLINE const tfScalar & z() const
bool update(const sensor_msgs::LaserScan &input_scan, sensor_msgs::LaserScan &filtered_scan)
Definition: box_filter.cpp:105
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)
#define ROS_ERROR(...)


laser_filters
Author(s): Tully Foote
autogenerated on Wed Jul 3 2019 19:33:47