45 #include <dynamic_reconfigure/server.h>
46 #include <laser_filters/PolygonFilterConfig.h>
47 #include <geometry_msgs/PolygonStamped.h>
56 return x < 0.0 ? -1.0 : (x > 0.0 ? 1.0 : 0.0);
59 void padPolygon(geometry_msgs::Polygon& polygon,
double padding)
62 for (
unsigned int i = 0; i < polygon.points.size(); i++)
64 geometry_msgs::Point32& pt = polygon.points[ i ];
65 pt.x +=
sign0(pt.x) * padding;
66 pt.y +=
sign0(pt.y) * padding;
75 std::string& value_string = value;
76 ROS_FATAL(
"Values in the polygon specification (param %s) must be numbers. Found value %s.",
77 full_param_name.c_str(), value_string.c_str());
78 throw std::runtime_error(
"Values in the polygon specification must be numbers");
84 const std::string& full_param_name)
88 polygon_xmlrpc.
size() > 0 && polygon_xmlrpc.
size() < 3)
90 ROS_FATAL(
"The polygon (parameter %s) must be specified as nested list on the parameter server with at least "
91 "3 points eg: [[x1, y1], [x2, y2], ..., [xn, yn]]",
92 full_param_name.c_str());
94 throw std::runtime_error(
"The polygon must be specified as nested list on the parameter server with at least "
95 "3 points eg: [[x1, y1], [x2, y2], ..., [xn, yn]]");
97 geometry_msgs::Polygon polygon;
98 geometry_msgs::Point32 pt;
100 for (
int i = 0; i < polygon_xmlrpc.
size(); ++i)
106 ROS_FATAL(
"The polygon (parameter %s) must be specified as list of lists on the parameter server eg: "
107 "[[x1, y1], [x2, y2], ..., [xn, yn]], but this spec is not of that form.",
108 full_param_name.c_str());
109 throw std::runtime_error(
"The polygon must be specified as list of lists on the parameter server eg: "
110 "[[x1, y1], [x2, y2], ..., [xn, yn]], but this spec is not of that form");
116 polygon.points.push_back(pt);
121 std::vector<std::vector<float> >
parseVVF(
const std::string& input, std::string& error_return)
123 std::vector<std::vector<float> > result;
125 std::stringstream input_ss(input);
127 std::vector<float> current_vector;
128 while (!!input_ss && !input_ss.eof())
130 switch (input_ss.peek())
138 error_return =
"Array depth greater than 2";
142 current_vector.clear();
148 error_return =
"More close ] than open [";
154 result.push_back(current_vector);
165 std::stringstream err_ss;
166 err_ss <<
"Numbers at depth other than 2. Char was '" << char(input_ss.peek()) <<
"'.";
167 error_return = err_ss.str();
174 current_vector.push_back(value);
182 error_return =
"Unterminated vector string.";
192 geometry_msgs::Polygon
makePolygonFromString(
const std::string& polygon_string,
const geometry_msgs::Polygon& last_polygon)
195 std::vector<std::vector<float> > vvf =
parseVVF(polygon_string, error);
199 ROS_ERROR(
"Error parsing polygon parameter: '%s'", error.c_str());
200 ROS_ERROR(
" Polygon string was '%s'.", polygon_string.c_str());
204 geometry_msgs::Polygon polygon;
205 geometry_msgs::Point32 point;
208 if (vvf.size() < 3 && vvf.size() > 0)
210 ROS_WARN(
"You must specify at least three points for the robot polygon");
214 for (
unsigned int i = 0; i < vvf.size(); i++)
216 if (vvf[ i ].size() == 2)
218 point.x = vvf[ i ][ 0 ];
219 point.y = vvf[ i ][ 1 ];
221 polygon.points.push_back(point);
225 ROS_ERROR(
"Points in the polygon specification must be pairs of numbers. Found a point with %d numbers.",
226 int(vvf[ i ].size()));
236 std::string polygon_string =
"[";
238 for (
auto point : polygon.points) {
240 polygon_string +=
", ";
243 polygon_string +=
"[" + std::to_string(point.x) +
", " + std::to_string(point.y) +
"]";
245 polygon_string +=
"]";
246 return polygon_string;
254 std::string polygon_string;
255 PolygonFilterConfig param_config;
258 dyn_server_.reset(
new dynamic_reconfigure::Server<laser_filters::PolygonFilterConfig>(
own_mutex_, private_nh));
259 dynamic_reconfigure::Server<laser_filters::PolygonFilterConfig>::CallbackType
f;
260 f = [
this](
auto& config,
auto level){
reconfigureCB(config, level); };
263 bool polygon_set =
getParam(
"polygon", polygon_xmlrpc);
268 double polygon_padding = 0;
269 getParam(
"polygon_padding", polygon_padding);
272 param_config.polygon = polygon_string;
273 param_config.polygon_padding = polygon_padding;
280 if (!polygon_frame_set)
290 ROS_INFO(
"invert filter not set, assuming false");
294 return polygon_frame_set && polygon_set;
302 for (i = 0, j =
polygon_.points.size() - 1; i <
polygon_.points.size(); j = i++)
304 if ((
polygon_.points.at(i).y > point.y() != (
polygon_.points.at(j).y > point.y()) &&
317 geometry_msgs::PolygonStamped polygon_stamped;
335 sensor_msgs::LaserScan& output_scan)
337 boost::recursive_mutex::scoped_lock lock(
own_mutex_);
341 output_scan = input_scan;
343 sensor_msgs::PointCloud2 laser_cloud;
345 std::string error_msg;
349 input_scan.header.stamp +
ros::Duration().
fromSec(input_scan.ranges.size() * input_scan.time_increment),
353 ROS_WARN(
"Could not get transform, ignoring laser scan! %s", error_msg.c_str());
371 if (i_idx_c == -1 || x_idx_c == -1 || y_idx_c == -1 || z_idx_c == -1)
376 const int i_idx_offset = laser_cloud.fields[i_idx_c].offset;
377 const int x_idx_offset = laser_cloud.fields[x_idx_c].offset;
378 const int y_idx_offset = laser_cloud.fields[y_idx_c].offset;
379 const int z_idx_offset = laser_cloud.fields[z_idx_c].offset;
381 const int pstep = laser_cloud.point_step;
382 const long int pcount = laser_cloud.width * laser_cloud.height;
383 const long int limit = pstep * pcount;
385 int i_idx, x_idx, y_idx, z_idx;
386 for (i_idx = i_idx_offset, x_idx = x_idx_offset, y_idx = y_idx_offset, z_idx = z_idx_offset;
390 i_idx += pstep, x_idx += pstep, y_idx += pstep, z_idx += pstep)
394 float x = *((
float*)(&laser_cloud.data[x_idx]));
395 float y = *((
float*)(&laser_cloud.data[y_idx]));
396 float z = *((
float*)(&laser_cloud.data[z_idx]));
397 int index = *((
int*)(&laser_cloud.data[i_idx]));
405 output_scan.ranges[index] = std::numeric_limits<float>::quiet_NaN();
412 output_scan.ranges[index] = std::numeric_limits<float>::quiet_NaN();
432 size_t n_pts = scan_in.ranges.size();
439 ROS_DEBUG_NAMED(
"StaticLaserScanPolygonFilter",
"No precomputed map given. Computing one.");
445 for (
size_t i = 0; i < n_pts; ++i)
447 co_sine_map_(i, 0) = cos(scan_in.angle_min + (
double) i * scan_in.angle_increment);
448 co_sine_map_(i, 1) = sin(scan_in.angle_min + (
double) i * scan_in.angle_increment);
460 sensor_msgs::LaserScan& output_scan)
462 boost::recursive_mutex::scoped_lock lock(
own_mutex_);
469 std::string error_msg;
471 "StaticLaserScanPolygonFilter",
"waitForTransform %s -> %s",
485 1,
"StaticLaserScanPolygonFilter",
486 "Could not get transform, ignoring laser scan! %s", error_msg.c_str()
492 ROS_INFO_NAMED(
"StaticLaserScanPolygonFilter",
"Obtained transform");
498 for (
int i = 0; i <
polygon_.points.size(); ++i)
503 transform_listener.
transformPoint(input_scan.header.frame_id, point_stamped, point_stamped_new);
504 geometry_msgs::PointStamped result_point;
506 polygon_.points[i].x = result_point.point.x;
507 polygon_.points[i].y = result_point.point.y;
519 output_scan = input_scan;
523 size_t i_max = input_scan.ranges.size();
527 float range = input_scan.ranges[i];
535 output_scan.ranges[i] = std::numeric_limits<float>::quiet_NaN();