15 #include "nav2_collision_monitor/source.hpp"
22 #include "geometry_msgs/msg/transform_stamped.hpp"
24 #include "nav2_ros_common/node_utils.hpp"
25 #include "nav2_util/robot_utils.hpp"
26 #include "nav2_ros_common/tf2_factories.hpp"
28 namespace nav2_collision_monitor
32 const nav2::LifecycleNode::WeakPtr & node,
33 const std::string & source_name,
34 const nav2::TransformBuffer::SharedPtr tf_buffer,
35 const std::string & base_frame_id,
36 const std::string & global_frame_id,
37 const tf2::Duration & transform_tolerance,
38 const rclcpp::Duration & source_timeout,
39 const bool base_shift_correction)
40 : node_(node), source_name_(source_name), tf_buffer_(tf_buffer),
41 base_frame_id_(base_frame_id), global_frame_id_(global_frame_id),
42 transform_tolerance_(transform_tolerance), source_timeout_(source_timeout),
43 base_shift_correction_(base_shift_correction)
51 auto node =
node_.lock();
52 if (post_set_params_handler_ && node) {
53 node->remove_post_set_parameters_callback(post_set_params_handler_.get());
55 post_set_params_handler_.reset();
56 if (on_set_params_handler_ && node) {
57 node->remove_on_set_parameters_callback(on_set_params_handler_.get());
59 on_set_params_handler_.reset();
64 auto node =
node_.lock();
66 throw std::runtime_error{
"Failed to lock node"};
70 const std::vector<std::string> zone_names =
71 node->declare_or_get_parameter<std::vector<std::string>>(
72 source_name_ +
".exclusion_zones", std::vector<std::string>());
74 for (
const std::string & zone_name : zone_names) {
75 auto zone = std::make_shared<ExclusionZone>(
78 if (!zone->configure()) {
80 logger_,
"[%s]: Failed to configure exclusion zone '%s'",
88 post_set_params_handler_ = node->add_post_set_parameters_callback(
91 this, std::placeholders::_1));
92 on_set_params_handler_ = node->add_on_set_parameters_callback(
95 this, std::placeholders::_1));
98 add_ez_service_ = node->create_service<nav2_msgs::srv::AddExclusionZone>(
102 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
107 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
113 const rclcpp::Time & curr_time,
114 std::vector<Point> & data)
118 std::vector<Point> source_data;
126 zone->apply(curr_time, source_data);
133 std::make_move_iterator(source_data.begin()),
134 std::make_move_iterator(source_data.end()));
162 auto node =
node_.lock();
164 throw std::runtime_error{
"Failed to lock node"};
167 source_topic = node->declare_or_get_parameter(
170 enabled_ = node->declare_or_get_parameter(
174 node->declare_or_get_parameter(
180 const rclcpp::Time & source_time,
181 const rclcpp::Time & curr_time)
const
185 const rclcpp::Duration dt = curr_time - source_time;
189 "[%s]: Latest source and current collision monitor node timestamps differ on %f seconds. "
190 "Ignoring the source.",
200 std::lock_guard<std::mutex> lock_reinit(
mutex_);
215 const std::vector<rclcpp::Parameter> & )
217 rcl_interfaces::msg::SetParametersResult result;
218 result.successful =
true;
223 const std::vector<rclcpp::Parameter> & parameters)
225 std::lock_guard<std::mutex> lock_reinit(
mutex_);
227 for (
auto parameter : parameters) {
228 const auto & param_type = parameter.get_type();
229 const auto & param_name = parameter.get_name();
233 if (param_type == rcl_interfaces::msg::ParameterType::PARAMETER_BOOL) {
242 const std::shared_ptr<rmw_request_id_t>,
243 const std::shared_ptr<nav2_msgs::srv::AddExclusionZone::Request> request,
244 std::shared_ptr<nav2_msgs::srv::AddExclusionZone::Response> response)
246 const auto & desc = request->zone;
249 bool duplicate = std::any_of(
251 [&](
const auto & z) {return z->getName() == desc.zone_name;});
252 if (desc.zone_name.empty() || duplicate ||
253 (desc.type !=
"polygon" && desc.type !=
"circle") ||
254 (desc.type ==
"circle" && desc.radius <= 0.0) ||
255 (desc.type ==
"polygon" && desc.points.size() < 3))
257 response->success =
false;
258 response->message =
"Invalid exclusion zone description for '" + desc.zone_name +
263 auto node =
node_.lock();
264 auto zone = std::make_shared<ExclusionZone>(
267 if (!zone->configure(desc)) {
268 response->success =
false;
269 response->message =
"Failed to configure zone '" + desc.zone_name +
"'";
275 response->success =
true;
276 response->message =
"Added zone '" + desc.zone_name +
"' to source '" +
source_name_ +
"'";
277 RCLCPP_INFO(
logger_,
"%s", response->message.c_str());
281 const std::shared_ptr<rmw_request_id_t>,
282 const std::shared_ptr<nav2_msgs::srv::RemoveExclusionZone::Request> request,
283 std::shared_ptr<nav2_msgs::srv::RemoveExclusionZone::Response> response)
285 if (request->remove_all) {
290 response->success =
true;
291 response->message = std::string(
"Removed all zone(s) from source '") +
293 RCLCPP_INFO(
logger_,
"%s", response->message.c_str());
297 if (request->zone_name.empty()) {
298 response->success =
false;
299 response->message =
"Zone name must not be empty";
303 auto it = std::find_if(
305 [&](
const std::shared_ptr<ExclusionZone> & z) {
306 return z->getName() == request->zone_name;
310 response->success =
false;
311 response->message =
"Zone '" + request->zone_name +
319 response->success =
true;
320 response->message =
"Removed zone '" + request->zone_name +
322 RCLCPP_INFO(
logger_,
"%s", response->message.c_str());
326 const rclcpp::Time & curr_time,
327 const std_msgs::msg::Header & data_header,
328 tf2::Transform & tf_transform)
const
332 !nav2_util::getTransform(
333 data_header.frame_id, data_header.stamp,
341 !nav2_util::getTransform(
nav2::LifecycleNode::WeakPtr node_
Collision Monitor node.
rclcpp::Logger logger_
Collision monitor node logger stored for further usage.
std::vector< std::shared_ptr< ExclusionZone > > exclusion_zones_
Exclusion zones masking out points from this source.
void removeExclusionZoneCallback(const std::shared_ptr< rmw_request_id_t > request_header, const std::shared_ptr< nav2_msgs::srv::RemoveExclusionZone::Request > request, std::shared_ptr< nav2_msgs::srv::RemoveExclusionZone::Response > response)
Service callback to remove an exclusion zone at runtime.
void activate()
Activates the exclusion zone visualization publishers (if any)
std::string base_frame_id_
Robot base frame ID.
virtual ~Source()
Source destructor.
bool getTransform(const rclcpp::Time &curr_time, const std_msgs::msg::Header &data_header, tf2::Transform &tf_transform) const
Obtain the transform to get data from source frame and time where it was received to the base frame a...
void addExclusionZoneCallback(const std::shared_ptr< rmw_request_id_t > request_header, const std::shared_ptr< nav2_msgs::srv::AddExclusionZone::Request > request, std::shared_ptr< nav2_msgs::srv::AddExclusionZone::Response > response)
Service callback to add an exclusion zone at runtime.
bool enabled_
Whether source is enabled.
virtual bool getSourceData(const rclcpp::Time &curr_time, std::vector< Point > &data)=0
Adds latest data from source to the data array. Pure virtual method implemented by each concrete sour...
bool getEnabled() const
Obtains source enabled state.
std::string getSourceName() const
Obtains the name of the data source.
Source(const nav2::LifecycleNode::WeakPtr &node, const std::string &source_name, const nav2::TransformBuffer::SharedPtr tf_buffer, const std::string &base_frame_id, const std::string &global_frame_id, const tf2::Duration &transform_tolerance, const rclcpp::Duration &source_timeout, const bool base_shift_correction)
Source constructor.
nav2::ServiceServer< nav2_msgs::srv::AddExclusionZone >::SharedPtr add_ez_service_
Service to add an exclusion zone at runtime.
tf2::Duration transform_tolerance_
Transform tolerance.
void getCommonParameters(std::string &source_topic)
Supporting routine obtaining ROS-parameters common for all data sources.
bool getData(const rclcpp::Time &curr_time, std::vector< Point > &data)
Adds latest data from source to the data array, then removes any points falling inside an enabled exc...
bool configure()
Source configuration routine.
void updateParametersCallback(const std::vector< rclcpp::Parameter > ¶meters)
Apply parameter updates after validation This callback is executed when parameters have been successf...
void publishExclusionZones() const
Publishes the source's exclusion zones for visualization.
std::string global_frame_id_
Global frame ID for correct transform calculation.
void deactivate()
Deactivates the exclusion zone visualization publishers (if any)
std::string source_name_
Name of data source.
nav2::ServiceServer< nav2_msgs::srv::RemoveExclusionZone >::SharedPtr remove_ez_service_
Service to remove an exclusion zone at runtime.
bool sourceValid(const rclcpp::Time &source_time, const rclcpp::Time &curr_time) const
Checks whether the source data might be considered as valid.
bool base_shift_correction_
Whether to correct source data towards to base frame movement, considering the difference between cur...
std::mutex mutex_
Dynamic parameters handler.
rcl_interfaces::msg::SetParametersResult validateParameterUpdatesCallback(const std::vector< rclcpp::Parameter > ¶meters)
Validate incoming parameter updates before applying them. This callback is triggered when one or more...
rclcpp::Duration source_timeout_
Maximum time interval in which data is considered valid.
nav2::TransformBuffer::SharedPtr tf_buffer_
TF buffer.
rclcpp::Duration getSourceTimeout() const
Obtains the source_timeout parameter of the data source.