16 #include "nav2_collision_monitor/collision_detector_node.hpp"
22 #include "tf2_ros/create_timer_ros.hpp"
24 #include "nav2_ros_common/node_utils.hpp"
26 using namespace std::chrono_literals;
28 namespace nav2_collision_monitor
31 CollisionDetector::CollisionDetector(
const rclcpp::NodeOptions & options)
32 : nav2::LifecycleNode(
"collision_detector", options)
45 RCLCPP_INFO(get_logger(),
"Configuring");
48 tf_buffer_ = std::make_shared<tf2_ros::Buffer>(this->get_clock());
49 auto timer_interface = std::make_shared<tf2_ros::CreateTimerROS>(
50 this->get_node_base_interface(),
51 this->get_node_timers_interface());
52 tf_buffer_->setCreateTimerInterface(timer_interface);
55 state_pub_ = this->create_publisher<nav2_msgs::msg::CollisionDetectorState>(
56 "collision_detector_state");
59 "~/collision_points_marker");
64 return nav2::CallbackReturn::FAILURE;
67 return nav2::CallbackReturn::SUCCESS;
73 RCLCPP_INFO(get_logger(),
"Activating");
80 for (std::shared_ptr<Polygon> polygon :
polygons_) {
85 timer_ = this->create_timer(
86 std::chrono::duration<double>{1.0 /
frequency_},
92 return nav2::CallbackReturn::SUCCESS;
98 RCLCPP_INFO(get_logger(),
"Deactivating");
108 for (std::shared_ptr<Polygon> polygon :
polygons_) {
109 polygon->deactivate();
115 return nav2::CallbackReturn::SUCCESS;
121 RCLCPP_INFO(get_logger(),
"Cleaning up");
132 return nav2::CallbackReturn::SUCCESS;
138 RCLCPP_INFO(get_logger(),
"Shutting down");
139 return nav2::CallbackReturn::SUCCESS;
144 std::string base_frame_id, odom_frame_id;
145 tf2::Duration transform_tolerance;
146 rclcpp::Duration source_timeout(2.0, 0.0);
150 frequency_ = node->declare_or_get_parameter(
"frequency", 10.0);
151 base_frame_id = node->declare_or_get_parameter(
"base_frame_id", std::string(
"base_footprint"));
152 odom_frame_id = node->declare_or_get_parameter(
"odom_frame_id", std::string(
"odom"));
153 transform_tolerance = tf2::durationFromSec(
154 node->declare_or_get_parameter(
"transform_tolerance", 0.1));
155 source_timeout = rclcpp::Duration::from_seconds(
156 node->declare_or_get_parameter(
"source_timeout", 2.0));
157 const bool base_shift_correction = node->declare_or_get_parameter(
"base_shift_correction",
true);
160 base_frame_id, odom_frame_id, transform_tolerance, source_timeout,
161 base_shift_correction))
174 const std::string & base_frame_id,
175 const tf2::Duration & transform_tolerance)
181 std::vector<std::string> polygon_names =
182 node->declare_or_get_parameter<std::vector<std::string>>(
"polygons");
183 for (std::string polygon_name : polygon_names) {
185 const std::string polygon_type =
186 node->declare_or_get_parameter<std::string>(polygon_name +
".type");
188 if (polygon_type ==
"polygon") {
190 std::make_shared<Polygon>(
191 node, polygon_name,
tf_buffer_, base_frame_id, transform_tolerance));
192 }
else if (polygon_type ==
"circle") {
194 std::make_shared<Circle>(
195 node, polygon_name,
tf_buffer_, base_frame_id, transform_tolerance));
196 }
else if (polygon_type ==
"velocity_polygon") {
198 std::make_shared<VelocityPolygon>(
199 node, polygon_name,
tf_buffer_, base_frame_id, transform_tolerance));
203 "[%s]: Unknown polygon type: %s",
204 polygon_name.c_str(), polygon_type.c_str());
214 auto action_type =
polygons_.back()->getActionType();
215 if (action_type != DO_NOTHING) {
218 "[%s]: The action_type of the polygon is different than \"none\" which is "
219 "not supported in the collision detector.",
220 polygon_name.c_str());
224 }
catch (
const std::exception & ex) {
225 RCLCPP_ERROR(get_logger(),
"Error while getting parameters: %s", ex.what());
233 const std::string & base_frame_id,
234 const std::string & odom_frame_id,
235 const tf2::Duration & transform_tolerance,
236 const rclcpp::Duration & source_timeout,
237 const bool base_shift_correction)
243 std::vector<std::string> source_names =
244 node->declare_or_get_parameter<std::vector<std::string>>(
"observation_sources");
245 for (std::string source_name : source_names) {
246 const std::string source_type = node->declare_or_get_parameter(
247 source_name +
".type", std::string(
"scan"));
249 if (source_type ==
"scan") {
250 std::shared_ptr<Scan> s = std::make_shared<Scan>(
251 node, source_name,
tf_buffer_, base_frame_id, odom_frame_id,
252 transform_tolerance, source_timeout, base_shift_correction);
257 }
else if (source_type ==
"pointcloud") {
258 std::shared_ptr<PointCloud> p = std::make_shared<PointCloud>(
259 node, source_name,
tf_buffer_, base_frame_id, odom_frame_id,
260 transform_tolerance, source_timeout, base_shift_correction);
265 }
else if (source_type ==
"range") {
266 std::shared_ptr<Range> r = std::make_shared<Range>(
267 node, source_name,
tf_buffer_, base_frame_id, odom_frame_id,
268 transform_tolerance, source_timeout, base_shift_correction);
273 }
else if (source_type ==
"polygon") {
274 std::shared_ptr<PolygonSource> ps = std::make_shared<PolygonSource>(
275 node, source_name,
tf_buffer_, base_frame_id, odom_frame_id,
276 transform_tolerance, source_timeout, base_shift_correction);
283 "[%s]: Unknown source type: %s",
284 source_name.c_str(), source_type.c_str());
288 }
catch (
const std::exception & ex) {
289 RCLCPP_ERROR(get_logger(),
"Error while getting parameters: %s", ex.what());
299 rclcpp::Time curr_time = this->now();
302 std::vector<Point> collision_points;
304 std::unique_ptr<nav2_msgs::msg::CollisionDetectorState> state_msg =
305 std::make_unique<nav2_msgs::msg::CollisionDetectorState>();
308 for (std::shared_ptr<Source> source :
sources_) {
309 if (source->getEnabled()) {
310 if (!source->getData(curr_time, collision_points) &&
311 source->getSourceTimeout().seconds() != 0.0)
315 "Invalid source %s detected."
316 " Either due to data not published yet, or to lack of new data received within the"
317 " sensor timeout, or if impossible to transform data to base frame",
318 source->getSourceName().c_str());
325 auto marker_array = std::make_unique<visualization_msgs::msg::MarkerArray>();
326 visualization_msgs::msg::Marker marker;
327 marker.header.frame_id = get_parameter(
"base_frame_id").as_string();
328 marker.header.stamp = rclcpp::Time(0, 0);
329 marker.ns =
"collision_points";
331 marker.type = visualization_msgs::msg::Marker::POINTS;
332 marker.action = visualization_msgs::msg::Marker::ADD;
333 marker.scale.x = 0.02;
334 marker.scale.y = 0.02;
335 marker.color.r = 1.0;
336 marker.color.a = 1.0;
337 marker.lifetime = rclcpp::Duration(0, 0);
338 marker.frame_locked =
true;
340 for (
const auto & point : collision_points) {
341 geometry_msgs::msg::Point p;
345 marker.points.push_back(p);
347 marker_array->markers.push_back(marker);
351 for (std::shared_ptr<Polygon> polygon :
polygons_) {
352 if (!polygon->getEnabled()) {
355 state_msg->polygons.push_back(polygon->getName());
356 state_msg->detections.push_back(
357 polygon->getPointsInside(
358 collision_points) >= polygon->getMinPoints());
369 for (std::shared_ptr<Polygon> polygon :
polygons_) {
370 if (polygon->getEnabled()) {
378 #include "rclcpp_components/register_node_macro.hpp"
void destroyBond()
Destroy bond connection to lifecycle manager.
nav2::LifecycleNode::SharedPtr shared_from_this()
Get a shared pointer of this.
void createBond()
Create bond connection to lifecycle manager.
Collision Monitor ROS2 node.
nav2::CallbackReturn on_activate(const rclcpp_lifecycle::State &state) override
: Activates LifecyclePublishers, polygons and main processor, creates bond connection
nav2::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr collision_points_marker_pub_
Collision points marker publisher.
bool getParameters()
Supporting routine obtaining all ROS-parameters.
bool configureSources(const std::string &base_frame_id, const std::string &odom_frame_id, const tf2::Duration &transform_tolerance, const rclcpp::Duration &source_timeout, const bool base_shift_correction)
Supporting routine creating and configuring all data sources.
void process()
Main processing routine.
void publishPolygons() const
Polygons publishing routine. Made for visualization.
nav2::CallbackReturn on_shutdown(const rclcpp_lifecycle::State &state) override
Called in shutdown state.
nav2::Publisher< nav2_msgs::msg::CollisionDetectorState >::SharedPtr state_pub_
collision monitor state publisher
~CollisionDetector()
Destructor for the nav2_collision_monitor::CollisionDetector.
nav2::CallbackReturn on_cleanup(const rclcpp_lifecycle::State &state) override
: Resets all subscribers/publishers, polygons/data sources arrays
std::vector< std::shared_ptr< Source > > sources_
Data sources array.
std::shared_ptr< tf2_ros::Buffer > tf_buffer_
TF buffer.
std::shared_ptr< tf2_ros::TransformListener > tf_listener_
TF listener.
bool configurePolygons(const std::string &base_frame_id, const tf2::Duration &transform_tolerance)
Supporting routine creating and configuring all polygons.
rclcpp::TimerBase::SharedPtr timer_
timer that runs actions
nav2::CallbackReturn on_deactivate(const rclcpp_lifecycle::State &state) override
: Deactivates LifecyclePublishers, polygons and main processor, destroys bond connection
double frequency_
main loop frequency
nav2::CallbackReturn on_configure(const rclcpp_lifecycle::State &state) override
: Initializes and obtains ROS-parameters, creates main subscribers and publishers,...
std::vector< std::shared_ptr< Polygon > > polygons_
Polygons array.