Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
polygon.cpp
1 // Copyright (c) 2022 Samsung R&D Institute Russia
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "nav2_collision_monitor/polygon.hpp"
16 
17 #include <algorithm>
18 #include <exception>
19 #include <utility>
20 
21 #include "geometry_msgs/msg/point.hpp"
22 #include "geometry_msgs/msg/point32.hpp"
23 #include "tf2/transform_datatypes.hpp"
24 #include "nav2_ros_common/tf2_factories.hpp"
25 
26 #include "nav2_ros_common/node_utils.hpp"
27 #include "nav2_util/geometry_utils.hpp"
28 #include "nav2_util/robot_utils.hpp"
29 
30 #include "nav2_collision_monitor/kinematics.hpp"
31 #include "nav2_collision_monitor/polygon_utils.hpp"
32 
33 namespace nav2_collision_monitor
34 {
35 
37  const nav2::LifecycleNode::WeakPtr & node,
38  const std::string & polygon_name,
39  const nav2::TransformBuffer::SharedPtr tf_buffer,
40  const std::string & base_frame_id,
41  const tf2::Duration & transform_tolerance)
42 : node_(node), polygon_name_(polygon_name), action_type_(DO_NOTHING),
43  slowdown_ratio_(0.0), linear_limit_(0.0), angular_limit_(0.0),
44  footprint_sub_(nullptr), tf_buffer_(tf_buffer),
45  base_frame_id_(base_frame_id), transform_tolerance_(transform_tolerance),
46  node_clock_(nullptr)
47 {
48  RCLCPP_INFO(logger_, "[%s]: Creating Polygon", polygon_name_.c_str());
49 }
50 
52 {
53  RCLCPP_INFO(logger_, "[%s]: Destroying Polygon", polygon_name_.c_str());
54  polygon_sub_.reset();
55  polygon_pub_.reset();
56  poly_.clear();
57  node_clock_.reset();
58  auto node = node_.lock();
59  if (post_set_params_handler_ && node) {
60  node->remove_post_set_parameters_callback(post_set_params_handler_.get());
61  }
62  post_set_params_handler_.reset();
63  if (on_set_params_handler_ && node) {
64  node->remove_on_set_parameters_callback(on_set_params_handler_.get());
65  }
66  on_set_params_handler_.reset();
67 }
68 
70 {
71  auto node = node_.lock();
72  if (!node) {
73  throw std::runtime_error{"Failed to lock node"};
74  }
75 
76  node_clock_ = node->get_clock();
77  std::string polygon_sub_topic, polygon_pub_topic, footprint_topic;
78 
79  if (!getParameters(polygon_sub_topic, polygon_pub_topic, footprint_topic)) {
80  return false;
81  }
82 
83  createSubscription(polygon_sub_topic);
84 
85  if (!footprint_topic.empty()) {
86  RCLCPP_INFO(
87  logger_,
88  "[%s]: Making footprint subscriber on %s topic",
89  polygon_name_.c_str(), footprint_topic.c_str());
90  footprint_sub_ = std::make_unique<nav2_costmap_2d::FootprintSubscriber>(
91  node, footprint_topic, *tf_buffer_,
92  base_frame_id_, tf2::durationToSec(transform_tolerance_));
93  }
94 
95  if (visualize_) {
96  // Fill polygon_ for future usage
97  polygon_.header.frame_id = base_frame_id_;
98  std::vector<Point> poly;
99  getPolygon(poly);
100  for (const Point & p : poly) {
101  geometry_msgs::msg::Point32 p_s;
102  p_s.x = p.x;
103  p_s.y = p.y;
104  // p_s.z will remain 0.0
105  polygon_.polygon.points.push_back(p_s);
106  }
107 
108  polygon_pub_ = node->create_publisher<geometry_msgs::msg::PolygonStamped>(
109  polygon_pub_topic);
110  }
111 
112  // Add callback for dynamic parameters
113  post_set_params_handler_ = node->add_post_set_parameters_callback(
114  std::bind(
116  this, std::placeholders::_1));
117  on_set_params_handler_ = node->add_on_set_parameters_callback(
118  std::bind(
120  this, std::placeholders::_1));
121 
122  return true;
123 }
124 
126 {
128 
129  if (visualize_) {
130  polygon_pub_->on_activate();
131  }
132 }
133 
135 {
136  if (visualize_) {
137  polygon_pub_->on_deactivate();
138  }
139 }
140 
141 std::string Polygon::getName() const
142 {
143  return polygon_name_;
144 }
145 
146 ActionType Polygon::getActionType() const
147 {
148  return action_type_;
149 }
150 
152 {
153  std::lock_guard<std::mutex> lock_reinit(mutex_);
154  return enabled_;
155 }
156 
158 {
159  return min_points_;
160 }
161 
163  const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
164  std::vector<Point> & out_triggering_points)
165 {
166  const int points_inside = getPointsInside(sources_collision_points_map, out_triggering_points);
167  return isTriggeredInternal(points_inside);
168 }
169 
170 bool Polygon::isTriggeredInternal(int points_inside)
171 {
172  const bool hit_now = points_inside >= min_points_;
173 
175  trigger_active_ = hit_now;
176  return trigger_active_;
177  }
178 
179  if (hit_now) {
180  trigger_hits_ += 1;
181  release_hits_ = 0;
183  trigger_active_ = true;
184  }
185  } else {
186  release_hits_ += 1;
187  trigger_hits_ = 0;
189  trigger_active_ = false;
190  }
191  }
192 
193  return trigger_active_;
194 }
195 
197 {
198  trigger_hits_ = 0;
199  release_hits_ = 0;
200  trigger_active_ = false;
201 }
202 
204 {
205  return slowdown_ratio_;
206 }
207 
209 {
210  return linear_limit_;
211 }
212 
214 {
215  return angular_limit_;
216 }
217 
219 {
220  return time_before_collision_;
221 }
222 
223 std::vector<std::string> Polygon::getSourcesNames() const
224 {
225  return sources_names_;
226 }
227 
228 void Polygon::getPolygon(std::vector<Point> & poly) const
229 {
230  poly.clear();
231  if (poly_.empty()) {
232  return;
233  }
234  poly = poly_;
235 }
236 
238 {
239  if (poly_.empty()) {
240  RCLCPP_WARN(logger_, "[%s]: Polygon shape is not set yet", polygon_name_.c_str());
241  return false;
242  }
243  return true;
244 }
245 
246 void Polygon::updatePolygon(const Velocity & /*cmd_vel_in*/)
247 {
248  if (footprint_sub_ != nullptr) {
249  // Get latest robot footprint from footprint subscriber
250  std::vector<geometry_msgs::msg::Point> footprint_vec;
251  std_msgs::msg::Header footprint_header;
252  footprint_sub_->getFootprintInRobotFrame(footprint_vec, footprint_header);
253 
254  std::size_t new_size = footprint_vec.size();
255  poly_.resize(new_size);
256  polygon_.header.frame_id = base_frame_id_;
257  polygon_.polygon.points.resize(new_size);
258 
259  geometry_msgs::msg::Point32 p_s;
260  for (std::size_t i = 0; i < new_size; i++) {
261  poly_[i] = {footprint_vec[i].x, footprint_vec[i].y};
262  p_s.x = footprint_vec[i].x;
263  p_s.y = footprint_vec[i].y;
264  polygon_.polygon.points[i] = p_s;
265  }
266  } else if (!polygon_.header.frame_id.empty() && polygon_.header.frame_id != base_frame_id_) {
267  // Polygon is published in another frame: correct poly_ vertices to the latest frame state
268  std::size_t new_size = polygon_.polygon.points.size();
269 
270  // Get the transform from PolygonStamped frame to base_frame_id_
271  tf2::Stamped<tf2::Transform> tf_transform;
272  if (
273  !nav2_util::getTransform(
274  polygon_.header.frame_id, base_frame_id_,
275  transform_tolerance_, tf_buffer_, tf_transform))
276  {
277  return;
278  }
279 
280  // Correct main poly_ vertices
281  poly_.resize(new_size);
282  for (std::size_t i = 0; i < new_size; i++) {
283  // Transform point coordinates from PolygonStamped frame -> to base frame
284  tf2::Vector3 p_v3_s(polygon_.polygon.points[i].x, polygon_.polygon.points[i].y, 0.0);
285  tf2::Vector3 p_v3_b = tf_transform * p_v3_s;
286 
287  // Fill poly_ array
288  poly_[i] = {p_v3_b.x(), p_v3_b.y()};
289  }
290  }
291 }
292 
294  const std::vector<Point> & points,
295  std::vector<Point> & out_triggering_points) const
296 {
297  int num = 0;
298  for (const Point & point : points) {
299  if (nav2_util::geometry_utils::isPointInsidePolygon(point.x, point.y, poly_)) {
300  out_triggering_points.push_back(point);
301  num++;
302  }
303  }
304  return num;
305 }
306 
308  const std::vector<Point> & points,
309  std::vector<std::size_t> & out_triggering_indices) const
310 {
311  int num = 0;
312  for (std::size_t i = 0; i < points.size(); ++i) {
313  if (nav2_util::geometry_utils::isPointInsidePolygon(points[i].x, points[i].y, poly_)) {
314  out_triggering_indices.push_back(i);
315  num++;
316  }
317  }
318  return num;
319 }
320 
322  const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
323  std::vector<Point> & out_triggering_points) const
324 {
325  int num = 0;
326  std::vector<std::string> polygon_sources_names = getSourcesNames();
327 
328  // Sum the number of points from all sources associated with current polygon
329  for (const auto & source_name : polygon_sources_names) {
330  const auto & iter = sources_collision_points_map.find(source_name);
331  if (iter != sources_collision_points_map.end()) {
332  num += getPointsInside(iter->second, out_triggering_points);
333  }
334  }
335 
336  return num;
337 }
338 
340  const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
341  const Velocity & velocity,
342  std::vector<Point> & out_triggering_points) const
343 {
344  // Initial robot pose is {0,0} in base_footprint coordinates
345  Pose pose = {0.0, 0.0, 0.0};
346  Velocity vel = velocity;
347 
348  std::vector<std::string> polygon_sources_names = getSourcesNames();
349  std::vector<Point> collision_points;
350 
351  // Save all points coming from the sources associated with current polygon
352  for (const auto & source_name : polygon_sources_names) {
353  const auto & iter = sources_collision_points_map.find(source_name);
354  if (iter != sources_collision_points_map.end()) {
355  collision_points.insert(collision_points.end(), iter->second.begin(), iter->second.end());
356  }
357  }
358 
359  // Array of points transformed to the frame concerned with pose on each simulation step
360  std::vector<Point> points_transformed = collision_points;
361 
362  // Check static polygon
363  if (getPointsInside(collision_points, out_triggering_points) >= min_points_) {
364  return 0.0;
365  }
366 
367  // Robot movement simulation
368  for (double time = 0.0; time <= time_before_collision_; time += simulation_time_step_) {
369  // Shift the robot pose towards to the vel during simulation_time_step_ time interval
370  // NOTE: vel is changing during the simulation
371  projectState(simulation_time_step_, pose, vel);
372  // Transform collision_points to the frame concerned with current robot pose
373  points_transformed = collision_points;
374  transformPoints(pose, points_transformed);
375  // If the collision occurred on this stage, return the actual time before a collision
376  // as if robot was moved with given velocity
377  std::vector<std::size_t> triggering_indices;
378  if (getPointsInside(points_transformed, triggering_indices) >= min_points_) {
379  for (std::size_t i : triggering_indices) {
380  out_triggering_points.push_back(collision_points[i]);
381  }
382  return time;
383  }
384  }
385 
386  // There is no collision
387  return -1.0;
388 }
389 
391 {
392  if (!visualize_) {
393  return;
394  }
395 
396  auto node = node_.lock();
397  if (!node) {
398  throw std::runtime_error{"Failed to lock node"};
399  }
400 
401  // Actualize the time to current and publish the polygon
402  polygon_.header.stamp = node->now();
403  auto msg = std::make_unique<geometry_msgs::msg::PolygonStamped>(polygon_);
404  polygon_pub_->publish(std::move(msg));
405 }
406 
408  std::string & polygon_sub_topic,
409  std::string & polygon_pub_topic,
410  std::string & footprint_topic,
411  bool use_dynamic_sub_topic)
412 {
413  auto node = node_.lock();
414  if (!node) {
415  throw std::runtime_error{"Failed to lock node"};
416  }
417 
418  try {
419  // Get action type.
420  // Leave it not initialized: the will cause an error if it will not set.
421  const std::string at_str = node->declare_or_get_parameter<std::string>(
422  polygon_name_ + ".action_type");
423  if (at_str == "stop") {
424  action_type_ = STOP;
425  } else if (at_str == "slowdown") {
426  action_type_ = SLOWDOWN;
427  } else if (at_str == "limit") {
428  action_type_ = LIMIT;
429  } else if (at_str == "approach") {
430  action_type_ = APPROACH;
431  } else if (at_str == "none") {
432  action_type_ = DO_NOTHING;
433  } else { // Error if something else
434  RCLCPP_ERROR(logger_, "[%s]: Unknown action type: %s", polygon_name_.c_str(), at_str.c_str());
435  return false;
436  }
437 
438  enabled_ = node->declare_or_get_parameter(polygon_name_ + ".enabled", true);
439  min_points_ = node->declare_or_get_parameter(polygon_name_ + ".min_points", 4);
440  trigger_consecutive_points_ = node->declare_or_get_parameter(
441  polygon_name_ + ".trigger_consecutive_points", 1);
442  release_consecutive_points_ = node->declare_or_get_parameter(
443  polygon_name_ + ".release_consecutive_points", 1);
444 
446  RCLCPP_ERROR(
447  logger_,
448  "[%s]: trigger_consecutive_points and release_consecutive_points must be >= 1",
449  polygon_name_.c_str());
450  return false;
451  }
452 
454 
455  try {
456  min_points_ = node->declare_or_get_parameter<int>(polygon_name_ + ".max_points") + 1;
457  RCLCPP_WARN(
458  logger_,
459  "[%s]: \"max_points\" parameter was deprecated. Use \"min_points\" instead to specify "
460  "the minimum number of data readings within a zone to trigger the action",
461  polygon_name_.c_str());
462  } catch (const std::exception &) {
463  // This is normal situation: max_points parameter should not being declared
464  }
465 
466  if (action_type_ == SLOWDOWN) {
467  slowdown_ratio_ = node->declare_or_get_parameter(polygon_name_ + ".slowdown_ratio", 0.5);
468  }
469 
470  if (action_type_ == LIMIT) {
471  linear_limit_ = node->declare_or_get_parameter(polygon_name_ + ".linear_limit", 0.5);
472  angular_limit_ = node->declare_or_get_parameter(polygon_name_ + ".angular_limit", 0.5);
473  }
474 
475  if (action_type_ == APPROACH) {
476  time_before_collision_ = node->declare_or_get_parameter(
477  polygon_name_ + ".time_before_collision", 2.0);
478  simulation_time_step_ = node->declare_or_get_parameter(
479  polygon_name_ + ".simulation_time_step", 0.1);
480  }
481 
482  visualize_ = node->declare_or_get_parameter(polygon_name_ + ".visualize", false);
483  if (visualize_) {
484  // Get polygon topic parameter in case if it is going to be published
485  polygon_pub_topic = node->declare_or_get_parameter(
486  polygon_name_ + ".polygon_pub_topic", polygon_name_);
487  }
488 
489  polygon_subscribe_transient_local_ = node->declare_or_get_parameter(
490  polygon_name_ + ".polygon_subscribe_transient_local", false);
491 
492  if (use_dynamic_sub_topic) {
493  if (action_type_ != APPROACH) {
494  // Get polygon sub topic
495  polygon_sub_topic = node->declare_or_get_parameter<std::string>(
496  polygon_name_ + ".polygon_sub_topic");
497  } else {
498  // Obtain the footprint topic to make a footprint subscription for approach polygon
499  footprint_topic = node->declare_or_get_parameter(
500  polygon_name_ + ".footprint_topic",
501  std::string("local_costmap/published_footprint"));
502  }
503  }
504 
505  // By default, use all observation sources for polygon
506  const std::vector<std::string> observation_sources =
507  node->declare_or_get_parameter<std::vector<std::string>>("observation_sources");
508  sources_names_ = node->declare_or_get_parameter(
509  polygon_name_ + ".sources_names", observation_sources);
510 
511  // Check the observation sources configured for polygon are defined
512  for (auto source_name : sources_names_) {
513  if (std::find(observation_sources.begin(), observation_sources.end(), source_name) ==
514  observation_sources.end())
515  {
516  RCLCPP_ERROR_STREAM(
517  logger_,
518  "Observation source [" << source_name <<
519  "] configured for polygon [" << getName() <<
520  "] is not defined as one of the node's observation_source!");
521  return false;
522  }
523  }
524  } catch (const std::exception & ex) {
525  RCLCPP_ERROR(
526  logger_,
527  "[%s]: Error while getting common polygon parameters: %s",
528  polygon_name_.c_str(), ex.what());
529  return false;
530  }
531 
532  return true;
533 }
534 
536  std::string & polygon_sub_topic,
537  std::string & polygon_pub_topic,
538  std::string & footprint_topic)
539 {
540  auto node = node_.lock();
541  if (!node) {
542  throw std::runtime_error{"Failed to lock node"};
543  }
544 
545  // Clear the subscription topics. They will be set later, if necessary.
546  polygon_sub_topic.clear();
547  footprint_topic.clear();
548 
549  bool use_dynamic_sub = true; // if getting parameter points fails, use dynamic subscription
550  try {
551  // Leave it uninitialized: it will throw an inner exception if the parameter is not set
552  std::string poly_string = node->declare_or_get_parameter<std::string>(
553  polygon_name_ + ".points");
554 
555  use_dynamic_sub = !getPolygonFromString(poly_string, poly_);
556  } catch (const rclcpp::exceptions::InvalidParameterValueException &) {
557  RCLCPP_INFO(
558  logger_,
559  "[%s]: Polygon points are not defined. Using dynamic subscription instead.",
560  polygon_name_.c_str());
561  }
562 
563  if (!getCommonParameters(
564  polygon_sub_topic, polygon_pub_topic, footprint_topic, use_dynamic_sub))
565  {
566  if (use_dynamic_sub && polygon_sub_topic.empty() && footprint_topic.empty()) {
567  RCLCPP_ERROR(
568  logger_,
569  "[%s]: Error while getting polygon parameters:"
570  " static points and sub topic both not defined",
571  polygon_name_.c_str());
572  }
573  return false;
574  }
575 
576  return true;
577 }
578 
579 void Polygon::createSubscription(std::string & polygon_sub_topic)
580 {
581  auto node = node_.lock();
582  if (!node) {
583  throw std::runtime_error{"Failed to lock node"};
584  }
585 
586  if (!polygon_sub_topic.empty()) {
587  RCLCPP_INFO(
588  logger_,
589  "[%s]: Subscribing on %s topic for polygon",
590  polygon_name_.c_str(), polygon_sub_topic.c_str());
591  rclcpp::QoS polygon_qos = nav2::qos::StandardTopicQoS();
593  polygon_qos.transient_local();
594  }
595  polygon_sub_ = node->create_subscription<geometry_msgs::msg::PolygonStamped>(
596  polygon_sub_topic,
597  std::bind(&Polygon::polygonCallback, this, std::placeholders::_1),
598  polygon_qos);
599  }
600 }
601 
602 void Polygon::updatePolygon(geometry_msgs::msg::PolygonStamped::ConstSharedPtr msg)
603 {
604  std::size_t new_size = msg->polygon.points.size();
605 
606  if (new_size < 3) {
607  RCLCPP_ERROR(
608  logger_,
609  "[%s]: Polygon should have at least 3 points",
610  polygon_name_.c_str());
611  return;
612  }
613 
614  // Get the transform from PolygonStamped frame to base_frame_id_
615  tf2::Stamped<tf2::Transform> tf_transform;
616  if (
617  !nav2_util::getTransform(
618  msg->header.frame_id, base_frame_id_,
619  transform_tolerance_, tf_buffer_, tf_transform))
620  {
621  return;
622  }
623 
624  // Set main poly_ vertices first time
625  poly_.resize(new_size);
626  for (std::size_t i = 0; i < new_size; i++) {
627  // Transform point coordinates from PolygonStamped frame -> to base frame
628  tf2::Vector3 p_v3_s(msg->polygon.points[i].x, msg->polygon.points[i].y, 0.0);
629  tf2::Vector3 p_v3_b = tf_transform * p_v3_s;
630 
631  // Fill poly_ array
632  poly_[i] = {p_v3_b.x(), p_v3_b.y()};
633  }
634 
635  // Store incoming polygon for further (possible) poly_ vertices corrections
636  // from PolygonStamped frame -> to base frame
637  polygon_ = *msg;
638 
640 }
641 
642 rcl_interfaces::msg::SetParametersResult Polygon::validateParameterUpdatesCallback(
643  const std::vector<rclcpp::Parameter> & /*parameters*/)
644 {
645  rcl_interfaces::msg::SetParametersResult result;
646  result.successful = true;
647  return result;
648 }
649 
651  const std::vector<rclcpp::Parameter> & parameters)
652 {
653  std::lock_guard<std::mutex> lock_reinit(mutex_);
654 
655  for (const auto & parameter : parameters) {
656  const auto & param_type = parameter.get_type();
657  const auto & param_name = parameter.get_name();
658  if (param_name.find(polygon_name_ + ".") != 0) {
659  continue;
660  }
661  if (param_type == rcl_interfaces::msg::ParameterType::PARAMETER_BOOL) {
662  if (param_name == polygon_name_ + "." + "enabled") {
663  enabled_ = parameter.as_bool();
665  }
666  }
667 
668  if (param_type == rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER) {
669  if (param_name == polygon_name_ + "." + "min_points") {
670  min_points_ = std::max(1, static_cast<int>(parameter.as_int()));
672  } else if (param_name == polygon_name_ + "." + "trigger_consecutive_points") {
673  const auto value = static_cast<int>(parameter.as_int());
674  if (value < 1) {
675  throw rclcpp::exceptions::InvalidParameterValueException(
676  "Parameter 'trigger_consecutive_points' must be >= 1");
677  }
680  } else if (param_name == polygon_name_ + "." + "release_consecutive_points") {
681  const auto value = static_cast<int>(parameter.as_int());
682  if (value < 1) {
683  throw rclcpp::exceptions::InvalidParameterValueException(
684  "Parameter 'release_consecutive_points' must be >= 1");
685  }
688  }
689  }
690  }
691 }
692 
693 void Polygon::polygonCallback(geometry_msgs::msg::PolygonStamped::ConstSharedPtr msg)
694 {
695  RCLCPP_INFO_THROTTLE(
696  logger_,
697  *node_clock_,
698  2000,
699  "[%s]: Polygon shape update has arrived",
700  polygon_name_.c_str());
701  updatePolygon(msg);
702 }
703 
705  std::string & poly_string,
706  std::vector<Point> & polygon)
707 {
708  std::string error;
709  // Historically the collision-monitor polygon requires at least 4 vertices.
710  if (!parsePolygonPoints(poly_string, 4, polygon, error)) {
711  RCLCPP_ERROR(
712  logger_, "[%s]: %s", polygon_name_.c_str(), error.c_str());
713  return false;
714  }
715  return true;
716 }
717 
718 } // namespace nav2_collision_monitor
A QoS profile for standard reliable topics with a history of 10 messages.
virtual bool getParameters(std::string &polygon_sub_topic, std::string &polygon_pub_topic, std::string &footprint_topic)
Supporting routine obtaining polygon-specific ROS-parameters.
Definition: polygon.cpp:535
int release_consecutive_points_
Number of consecutive misses required to release action.
Definition: polygon.hpp:323
int trigger_consecutive_points_
Number of consecutive hits required to trigger action.
Definition: polygon.hpp:321
int getMinPoints() const
Obtains polygon minimum points to enter inside polygon causing the action.
Definition: polygon.cpp:157
nav2::Publisher< geometry_msgs::msg::PolygonStamped >::SharedPtr polygon_pub_
Polygon publisher for visualization purposes.
Definition: polygon.hpp:367
double getTimeBeforeCollision() const
Obtains required time before collision for current polygon. Applicable for APPROACH model.
Definition: polygon.cpp:218
rclcpp::Clock::SharedPtr node_clock_
Collision monitor node's clock.
Definition: polygon.hpp:359
virtual void updatePolygon(const Velocity &)
Updates polygon from footprint subscriber (if any)
Definition: polygon.cpp:246
bool getCommonParameters(std::string &polygon_sub_topic, std::string &polygon_pub_topic, std::string &footprint_topic, bool use_dynamic_sub=false)
Supporting routine obtaining ROS-parameters common for all shapes.
Definition: polygon.cpp:407
std::mutex mutex_
Dynamic parameters handler.
Definition: polygon.hpp:309
double time_before_collision_
Time before collision in seconds.
Definition: polygon.hpp:337
double getCollisionTime(const std::unordered_map< std::string, std::vector< Point >> &sources_collision_points_map, const Velocity &velocity, std::vector< Point > &out_triggering_points) const
Obtains estimated (simulated) time before a collision. Applicable for APPROACH model.
Definition: polygon.cpp:339
bool enabled_
Whether polygon is enabled.
Definition: polygon.hpp:341
rcl_interfaces::msg::SetParametersResult validateParameterUpdatesCallback(const std::vector< rclcpp::Parameter > &parameters)
Validate incoming parameter updates before applying them. This callback is triggered when one or more...
Definition: polygon.cpp:642
rclcpp::Logger logger_
Collision monitor node logger stored for further usage.
Definition: polygon.hpp:307
ActionType action_type_
Action type for the polygon.
Definition: polygon.hpp:317
geometry_msgs::msg::PolygonStamped polygon_
Polygon, used for: 1. visualization; 2. storing latest dynamic polygon message.
Definition: polygon.hpp:365
int trigger_hits_
Current consecutive hit counter.
Definition: polygon.hpp:325
virtual void createSubscription(std::string &polygon_sub_topic)
Creates polygon or radius topic subscription.
Definition: polygon.cpp:579
nav2::Subscription< geometry_msgs::msg::PolygonStamped >::SharedPtr polygon_sub_
Polygon subscription.
Definition: polygon.hpp:345
bool polygon_subscribe_transient_local_
Whether the subscription to polygon topic has transient local QoS durability.
Definition: polygon.hpp:343
virtual bool isShapeSet()
Returns true if polygon points were set. Otherwise, prints a warning and returns false.
Definition: polygon.cpp:237
double simulation_time_step_
Time step for robot movement simulation.
Definition: polygon.hpp:339
bool trigger_active_
Latched trigger state after temporal debounce.
Definition: polygon.hpp:329
void activate()
Activates polygon lifecycle publisher.
Definition: polygon.cpp:125
bool configure()
Shape configuration routine. Obtains ROS-parameters related to shape object and creates polygon lifec...
Definition: polygon.cpp:69
double getLinearLimit() const
Obtains speed linear limit for current polygon. Applicable for LIMIT model.
Definition: polygon.cpp:208
std::string getName() const
Returns the name of polygon.
Definition: polygon.cpp:141
bool isTriggered(const std::unordered_map< std::string, std::vector< Point >> &sources_collision_points_map, std::vector< Point > &out_triggering_points)
Temporal debounce for min_points trigger.
Definition: polygon.cpp:162
virtual void getPolygon(std::vector< Point > &poly) const
Gets polygon points.
Definition: polygon.cpp:228
tf2::Duration transform_tolerance_
Transform tolerance.
Definition: polygon.hpp:357
void resetTriggerState()
Reset temporal debounce state.
Definition: polygon.cpp:196
ActionType getActionType() const
Obtains polygon action type.
Definition: polygon.cpp:146
int min_points_
Minimum number of data readings within a zone to trigger the action.
Definition: polygon.hpp:319
std::vector< Point > poly_
Polygon points (vertices) in a base_frame_id_.
Definition: polygon.hpp:370
std::vector< std::string > sources_names_
Name of the observation sources to check for polygon.
Definition: polygon.hpp:349
void deactivate()
Deactivates polygon lifecycle publisher.
Definition: polygon.cpp:134
std::unique_ptr< nav2_costmap_2d::FootprintSubscriber > footprint_sub_
Footprint subscriber.
Definition: polygon.hpp:347
void polygonCallback(geometry_msgs::msg::PolygonStamped::ConstSharedPtr msg)
Dynamic polygon callback.
Definition: polygon.cpp:693
double getSlowdownRatio() const
Obtains speed slowdown ratio for current polygon. Applicable for SLOWDOWN model.
Definition: polygon.cpp:203
double getAngularLimit() const
Obtains speed angular z limit for current polygon. Applicable for LIMIT model.
Definition: polygon.cpp:213
void updateParametersCallback(const std::vector< rclcpp::Parameter > &parameters)
Apply parameter updates after validation This callback is executed when parameters have been successf...
Definition: polygon.cpp:650
std::string polygon_name_
Name of polygon.
Definition: polygon.hpp:315
nav2::LifecycleNode::WeakPtr node_
Collision Monitor node.
Definition: polygon.hpp:305
virtual int getPointsInside(const std::vector< Point > &points, std::vector< Point > &out_triggering_points) const
Gets number of points inside given polygon.
Definition: polygon.cpp:293
double linear_limit_
Robot linear limit.
Definition: polygon.hpp:333
virtual ~Polygon()
Polygon destructor.
Definition: polygon.cpp:51
int release_hits_
Current consecutive miss counter.
Definition: polygon.hpp:327
bool getEnabled() const
Obtains polygon enabled state.
Definition: polygon.cpp:151
double angular_limit_
Robot angular limit.
Definition: polygon.hpp:335
bool getPolygonFromString(std::string &poly_string, std::vector< Point > &polygon)
Extracts Polygon points from a string with of the form [[x1,y1],[x2,y2],[x3,y3]......
Definition: polygon.cpp:704
bool visualize_
Whether to publish the polygon.
Definition: polygon.hpp:363
std::vector< std::string > getSourcesNames() const
Obtains the name of the observation sources for current polygon.
Definition: polygon.cpp:223
nav2::TransformBuffer::SharedPtr tf_buffer_
TF buffer.
Definition: polygon.hpp:353
std::string base_frame_id_
Base frame ID.
Definition: polygon.hpp:355
Polygon(const nav2::LifecycleNode::WeakPtr &node, const std::string &polygon_name, const nav2::TransformBuffer::SharedPtr tf_buffer, const std::string &base_frame_id, const tf2::Duration &transform_tolerance)
Polygon constructor.
Definition: polygon.cpp:36
double slowdown_ratio_
Robot slowdown (share of its actual speed)
Definition: polygon.hpp:331
void publish()
Publishes polygon message into a its own topic.
Definition: polygon.cpp:390
Point with 2D collision-check coordinates and optional z from the source.
Definition: types.hpp:52
Velocity for 2D model of motion.
Definition: types.hpp:26