Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
circle.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/circle.hpp"
16 
17 #include <math.h>
18 #include <cmath>
19 #include <exception>
20 
21 #include "nav2_ros_common/node_utils.hpp"
22 #include "nav2_ros_common/tf2_factories.hpp"
23 
24 #include "nav2_collision_monitor/polygon_utils.hpp"
25 
26 namespace nav2_collision_monitor
27 {
28 
30  const nav2::LifecycleNode::WeakPtr & node,
31  const std::string & polygon_name,
32  const nav2::TransformBuffer::SharedPtr tf_buffer,
33  const std::string & base_frame_id,
34  const tf2::Duration & transform_tolerance)
35 : Polygon::Polygon(node, polygon_name, tf_buffer, base_frame_id, transform_tolerance)
36 {
37  RCLCPP_INFO(logger_, "[%s]: Creating Circle", polygon_name_.c_str());
38 }
39 
41 {
42  RCLCPP_INFO(logger_, "[%s]: Destroying Circle", polygon_name_.c_str());
43 }
44 
45 void Circle::getPolygon(std::vector<Point> & poly) const
46 {
47  // Number of polygon points. More edges means better approximation.
48  constexpr int polygon_edges = 16;
49  poly = circleToPolygon(radius_, polygon_edges);
50 }
51 
53  const std::vector<Point> & points,
54  std::vector<Point> & out_triggering_points) const
55 {
56  int num = 0;
57  for (Point point : points) {
58  if (point.x * point.x + point.y * point.y < radius_squared_) {
59  out_triggering_points.push_back(point);
60  num++;
61  }
62  }
63 
64  return num;
65 }
66 
68  const std::vector<Point> & points,
69  std::vector<std::size_t> & out_triggering_indices) const
70 {
71  int num = 0;
72  for (std::size_t i = 0; i < points.size(); ++i) {
73  const Point & point = points[i];
74  if (point.x * point.x + point.y * point.y < radius_squared_) {
75  out_triggering_indices.push_back(i);
76  num++;
77  }
78  }
79  return num;
80 }
81 
83 {
84  if (radius_squared_ == -1.0) {
85  RCLCPP_WARN(logger_, "[%s]: Circle radius is not set yet", polygon_name_.c_str());
86  return false;
87  }
88  return true;
89 }
90 
92  std::string & polygon_sub_topic,
93  std::string & polygon_pub_topic,
94  std::string & footprint_topic)
95 {
96  auto node = node_.lock();
97  if (!node) {
98  throw std::runtime_error{"Failed to lock node"};
99  }
100 
101  // Clear the polygon subscription topic. It will be set later, if necessary.
102  polygon_sub_topic.clear();
103 
104  bool use_dynamic_sub = true; // if getting parameter radius fails, use dynamic subscription
105  try {
106  // Leave it not initialized: the will cause an error if it will not set
107  radius_ = node->declare_or_get_parameter<double>(polygon_name_ + ".radius");
109  use_dynamic_sub = false;
110  } catch (const rclcpp::exceptions::InvalidParameterValueException &) {
111  RCLCPP_INFO(
112  logger_,
113  "[%s]: Polygon circle radius is not defined. Using dynamic subscription instead.",
114  polygon_name_.c_str());
115  }
116 
117  bool ret = true;
118  if (!getCommonParameters(
119  polygon_sub_topic, polygon_pub_topic, footprint_topic, use_dynamic_sub))
120  {
121  if (use_dynamic_sub && polygon_sub_topic.empty()) {
122  RCLCPP_ERROR(
123  logger_,
124  "[%s]: Error while getting circle parameters: static radius and sub topic both not defined",
125  polygon_name_.c_str());
126  }
127  ret = false;
128  }
129 
130  // There is no footprint subscription for the Circle. Thus, set string as empty.
131  footprint_topic.clear();
132 
133  return ret;
134 }
135 
136 void Circle::createSubscription(std::string & polygon_sub_topic)
137 {
138  auto node = node_.lock();
139  if (!node) {
140  throw std::runtime_error{"Failed to lock node"};
141  }
142 
143  if (!polygon_sub_topic.empty()) {
144  RCLCPP_INFO(
145  logger_,
146  "[%s]: Subscribing on %s topic for polygon",
147  polygon_name_.c_str(), polygon_sub_topic.c_str());
148  rclcpp::QoS polygon_qos = nav2::qos::StandardTopicQoS(); // set to default
150  polygon_qos.transient_local();
151  }
152  radius_sub_ = node->create_subscription<std_msgs::msg::Float32>(
153  polygon_sub_topic,
154  std::bind(&Circle::radiusCallback, this, std::placeholders::_1),
155  polygon_qos);
156  }
157 }
158 
160 {
161  // Update circle radius
162  radius_ = radius;
164 
165  // Create a polygon from radius and store it
166  std::vector<Point> poly;
167  getPolygon(poly);
168  polygon_.polygon.points.clear(); // clear polygon points
169  for (const Point & p : poly) {
170  geometry_msgs::msg::Point32 p_s;
171  p_s.x = p.x;
172  p_s.y = p.y;
173  // p_s.z will remain 0.0
174  polygon_.polygon.points.push_back(p_s); // add new points
175  }
176 }
177 
178 void Circle::radiusCallback(std_msgs::msg::Float32::ConstSharedPtr msg)
179 {
180  RCLCPP_INFO(
181  logger_,
182  "[%s]: Polygon circle radius update has been arrived",
183  polygon_name_.c_str());
184  updatePolygonFromRadius(msg->data);
185 }
186 
187 } // namespace nav2_collision_monitor
A QoS profile for standard reliable topics with a history of 10 messages.
void updatePolygonFromRadius(double radius)
Updates polygon from radius value.
Definition: circle.cpp:159
int getPointsInside(const std::vector< Point > &points, std::vector< Point > &out_triggering_points) const override
Gets number of points inside circle.
Definition: circle.cpp:52
bool getParameters(std::string &polygon_sub_topic, std::string &polygon_pub_topic, std::string &footprint_topic) override
Supporting routine obtaining polygon-specific ROS-parameters.
Definition: circle.cpp:91
void getPolygon(std::vector< Point > &poly) const override
Gets polygon points, approximated to the circle. To be used in visualization purposes.
Definition: circle.cpp:45
double radius_squared_
(radius * radius) value. Stored for optimization.
Definition: circle.hpp:131
void radiusCallback(std_msgs::msg::Float32::ConstSharedPtr msg)
Dynamic circle radius callback.
Definition: circle.cpp:178
bool isShapeSet() override
Returns true if circle radius is set. Otherwise, prints a warning and returns false.
Definition: circle.cpp:82
nav2::Subscription< std_msgs::msg::Float32 >::SharedPtr radius_sub_
Radius subscription.
Definition: circle.hpp:133
~Circle()
Circle class destructor.
Definition: circle.cpp:40
double radius_
Radius of the circle.
Definition: circle.hpp:129
void createSubscription(std::string &polygon_sub_topic) override
Creates polygon or radius topic subscription.
Definition: circle.cpp:136
Circle(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)
Circle class constructor.
Definition: circle.cpp:29
Basic polygon shape class. For STOP/SLOWDOWN/LIMIT model it represents zone around the robot while fo...
Definition: polygon.hpp:45
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
rclcpp::Logger logger_
Collision monitor node logger stored for further usage.
Definition: polygon.hpp:307
geometry_msgs::msg::PolygonStamped polygon_
Polygon, used for: 1. visualization; 2. storing latest dynamic polygon message.
Definition: polygon.hpp:365
bool polygon_subscribe_transient_local_
Whether the subscription to polygon topic has transient local QoS durability.
Definition: polygon.hpp:343
std::string polygon_name_
Name of polygon.
Definition: polygon.hpp:315
nav2::LifecycleNode::WeakPtr node_
Collision Monitor node.
Definition: polygon.hpp:305
Point with 2D collision-check coordinates and optional z from the source.
Definition: types.hpp:52