1- #include " nav2_msgs/msg/costmap.hpp"
2- #include " nav2_collision_monitor/costmap.hpp"
1+ // Copyright (c) 2025 Angsa Robotics
2+ // Copyright (c) 2025 lotusymt
3+ //
4+ // Licensed under the Apache License, Version 2.0 (the "License");
5+ // you may not use this file except in compliance with the License.
6+ // You may obtain a copy of the License at
7+ //
8+ // http://www.apache.org/licenses/LICENSE-2.0
9+ //
10+ // Unless required by applicable law or agreed to in writing, software
11+ // distributed under the License is distributed on an "AS IS" BASIS,
12+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ // See the License for the specific language governing permissions and
14+ // limitations under the License.
15+ #include " nav2_msgs/msg/costmap.hpp"
16+ #include " nav2_collision_monitor/costmap.hpp"
317#include < functional>
418#include < cmath>
5- #include < tf2/time.hpp> // tf2::Duration, tf2::TimePoint, durationFromSec()
6- #include < tf2_ros/buffer.hpp> // tf2_ros::Buffer (you already use it)
19+ #include < tf2/time.hpp>
20+ #include < tf2_ros/buffer.hpp>
721#include < tf2_ros/transform_listener.hpp>
8- #include < nav2_ros_common/lifecycle_node.hpp> // nav2::LifecycleNode
22+ #include < nav2_ros_common/lifecycle_node.hpp>
923#include < nav2_ros_common/node_utils.hpp>
1024
1125namespace nav2_collision_monitor
1226{
1327
1428
15- CostmapSource::CostmapSource (
16- // const nav2_util::LifecycleNode::WeakPtr & node,
29+ CostmapSource::CostmapSource (
1730 const nav2::LifecycleNode::WeakPtr & node,
1831 const std::string & source_name,
1932 const std::shared_ptr<tf2_ros::Buffer> tf_buffer,
@@ -27,17 +40,17 @@ CostmapSource::CostmapSource(
2740 transform_tolerance, source_timeout, base_shift_correction),
2841 data_ (nullptr )
2942{
30- RCLCPP_INFO (logger_, " [%s]: Creating CostmapSource" , source_name_.c_str ());
43+ RCLCPP_INFO (logger_, " [%s]: Creating CostmapSource" , source_name_.c_str ());
3144}
3245
3346
34- CostmapSource::~CostmapSource ()
47+ CostmapSource::~CostmapSource ()
3548{
36- RCLCPP_INFO (logger_, " [%s]: Destroying CostmapSource" , source_name_.c_str ());
49+ RCLCPP_INFO (logger_, " [%s]: Destroying CostmapSource" , source_name_.c_str ());
3750 data_sub_.reset ();
3851}
3952
40- void CostmapSource::configure ()
53+ void CostmapSource::configure ()
4154{
4255 Source::configure ();
4356 auto node = node_.lock ();
@@ -48,14 +61,14 @@ void CostmapSource::configure()
4861 getParameters (source_topic);
4962 rclcpp::QoS qos = rclcpp::SystemDefaultsQoS ();
5063
51-
64+
5265 data_sub_ = node->create_subscription <nav2_msgs::msg::Costmap>(
5366 source_topic,
5467 std::bind (&CostmapSource::dataCallback, this , std::placeholders::_1),
5568 qos);
5669}
5770
58- bool CostmapSource::getData (
71+ bool CostmapSource::getData (
5972 const rclcpp::Time & curr_time,
6073 std::vector<Point> & data)
6174{
@@ -66,51 +79,71 @@ bool CostmapSource::getData(
6679 if (!sourceValid (data_->header .stamp , curr_time)) {
6780 return false ;
6881 }
69- tf2::Transform tf_transform;
70- if (!getTransform (curr_time, data_->header , tf_transform)) {
71- return false ;
82+ tf2::Transform tf_transform; tf_transform.setIdentity ();
83+ const std::string src = data_->header .frame_id ;
84+ if (src != base_frame_id_) {
85+ if (!getTransform (curr_time, data_->header , tf_transform)) {
86+ RCLCPP_WARN (logger_, " [%s] TF %s->%s unavailable at t=%.3f" ,
87+ source_name_.c_str (), src.c_str (), base_frame_id_.c_str (), curr_time.seconds ());
88+ return false ;
89+ }
7290 }
7391
92+
7493 // Extract lethal/inscribed cells and transform to base frame
75- const auto & cm = *data_;
76- const auto & meta = cm.metadata ;
77-
78- for (unsigned int y = 0 ; y < meta.size_y ; ++y) {
79- for (unsigned int x = 0 ; x < meta.size_x ; ++x) {
80- const int idx = y * meta.size_x + x;
81-
82- // CHANGE: Costmap costs are 0..255 (0 free, 253 inscribed, 254 lethal, 255 unknown)
83- if (cm.data [idx] >= cost_threshold_) {
84- const double wx = meta.origin .position .x + (x + 0.5 ) * meta.resolution ;
85- const double wy = meta.origin .position .y + (y + 0.5 ) * meta.resolution ;
94+ const auto & cm = *data_;
95+ const auto & meta = cm.metadata ;
96+
97+ for (unsigned int y = 0 ; y < meta.size_y ; ++y) {
98+ for (unsigned int x = 0 ; x < meta.size_x ; ++x) {
99+ const int idx = y * meta.size_x + x;
100+
101+ const uint8_t c = cm.data [idx];
102+ const bool is_obstacle = (c >= cost_threshold_ && c < 255 ) ||
103+ (treat_unknown_as_obstacle_ && c == 255 );
104+ if (is_obstacle) {
105+ const double wx = meta.origin .position .x + (x + 0.5 ) * meta.resolution ;
106+ const double wy = meta.origin .position .y + (y + 0.5 ) * meta.resolution ;
86107 tf2::Vector3 p_v3_s (wx, wy, 0.0 );
87108 tf2::Vector3 p_v3_b = tf_transform * p_v3_s;
88109 data.push_back ({p_v3_b.x (), p_v3_b.y ()});
110+ RCLCPP_INFO (logger_, " [%s] Lethal cell at (%f, %f)" ,
111+ source_name_.c_str (), wx, wy);
89112 }
90113 }
91114 }
92115 return true ;
93116}
94117
95- void CostmapSource::getParameters (std::string & source_topic)
118+ void CostmapSource::getParameters (std::string & source_topic)
96119{
97120 auto node = node_.lock ();
98121 if (!node) {
99122 throw std::runtime_error{" Failed to lock node" };
100123 }
101124 getCommonParameters (source_topic);
102125
126+ // Cost threshold (0–255). 253 = inscribed 254 = lethal; 255 = NO_INFORMATION.
127+ const auto thresh_name = source_name_ + " .cost_threshold" ;
128+ nav2::declare_parameter_if_not_declared (
129+ node, thresh_name, rclcpp::ParameterValue (253 ));
130+ int v = node->get_parameter (thresh_name).as_int ();
131+ v = std::max (0 , std::min (255 , v)); // clamp
132+ if (v != node->get_parameter (thresh_name).as_int ()) {
133+ RCLCPP_WARN (node->get_logger (), " Clamping %s to %d" , thresh_name.c_str (), v);
134+ }
135+ cost_threshold_ = v;
103136
104-
105- // Todo: use a cost threshold suitable for Nav2 costmaps; default 254 (lethal)
137+ // Whether 255 (NO_INFORMATION) should be treated as an obstacle.
138+ const auto unk_name = source_name_ + " .treat_unknown_as_obstacle " ;
106139 nav2::declare_parameter_if_not_declared (
107- node, source_name_ + " .cost_threshold " , rclcpp::ParameterValue (254 ));
108- cost_threshold_ = node->get_parameter (source_name_ + " .cost_threshold " ). as_int ();
140+ node, unk_name , rclcpp::ParameterValue (true ));
141+ treat_unknown_as_obstacle_ = node->get_parameter (unk_name). as_bool ();
109142}
110143
111- void CostmapSource::dataCallback (nav2_msgs::msg::Costmap::ConstSharedPtr msg)
144+ void CostmapSource::dataCallback (nav2_msgs::msg::Costmap::ConstSharedPtr msg)
112145{
113146 data_ = msg;
114147}
115148
116- } // namespace nav2_collision_monitor
149+ }
0 commit comments