Skip to content

Commit fc27b4c

Browse files
committed
collision_monitor: fix linter and address issues in the comment
Signed-off-by: lotusymt <[email protected]>
1 parent 4203283 commit fc27b4c

File tree

8 files changed

+92
-43
lines changed

8 files changed

+92
-43
lines changed

nav2_collision_monitor/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ find_package(nav2_common REQUIRED)
88
find_package(nav2_costmap_2d REQUIRED)
99
find_package(nav2_msgs REQUIRED)
1010
find_package(nav2_util REQUIRED)
11-
find_package(rosgraph_msgs REQUIRED)
1211
find_package(rclcpp REQUIRED)
1312
find_package(rclcpp_components REQUIRED)
1413
find_package(rclcpp_lifecycle REQUIRED)
@@ -150,6 +149,7 @@ install(DIRECTORY params DESTINATION share/${PROJECT_NAME})
150149
if(BUILD_TESTING)
151150
find_package(ament_lint_auto REQUIRED)
152151
find_package(launch_testing_ament_cmake REQUIRED)
152+
find_package(rosgraph_msgs REQUIRED)
153153
# the following line skips the linter which checks for copyrights
154154
set(ament_cmake_copyright_FOUND TRUE)
155155
set(ament_cmake_cpplint_FOUND TRUE)

nav2_collision_monitor/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ The data may be obtained from different data sources:
4848

4949
> **⚠️ when using CostmapSource**
5050
> Collision Monitor normally **bypasses the costmap** to minimize reaction latency using fresh sensor data.
51-
51+
> Use at your own caution or when using external costmap sources from derived sources.
5252
5353

5454
### Design

nav2_collision_monitor/include/nav2_collision_monitor/costmap.hpp

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,54 @@
1212
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
// See the License for the specific language governing permissions and
1414
// limitations under the License.
15+
1516
#ifndef NAV2_COLLISION_MONITOR__COSTMAP_HPP_
1617
#define NAV2_COLLISION_MONITOR__COSTMAP_HPP_
1718

19+
/**
20+
* @file costmap.hpp
21+
* @brief Observation source that converts a Nav2 costmap topic into 2D points for Collision Monitor.
22+
*/
23+
1824
#include <memory>
1925
#include <string>
2026
#include <vector>
27+
2128
#include "nav2_collision_monitor/source.hpp"
2229
#include "nav2_msgs/msg/costmap.hpp"
2330
#include <nav2_ros_common/lifecycle_node.hpp>
24-
#include <nav2_ros_common/node_utils.hpp>
31+
#include <nav2_ros_common/subscription.hpp>
2532

2633
namespace nav2_collision_monitor
2734
{
2835

36+
/**
37+
* @class CostmapSource
38+
* @brief Reads nav2_msgs::msg::Costmap and produces obstacle points for Collision Monitor.
39+
*
40+
* Cells with cost >= @ref cost_threshold_ are exported as points. Optionally, NO_INFORMATION (255)
41+
* can be treated as obstacles via @ref treat_unknown_as_obstacle_.
42+
*
43+
* Parameters (declared/queried in @ref getParameters):
44+
* - `topic` (std::string): costmap topic name (relative is recommended).
45+
* - `cost_threshold` (int, 0..255): minimum cost to consider a cell occupied.
46+
* - `treat_unknown_as_obstacle` (bool): whether cost 255 should be treated as occupied.
47+
*/
2948
class CostmapSource : public Source
3049
{
3150
public:
51+
/**
52+
* @brief Construct a CostmapSource.
53+
* @param node Weak pointer to the lifecycle node.
54+
* @param source_name Logical name of this source instance (for params/logs).
55+
* @param tf_buffer Shared TF buffer for frame transforms.
56+
* @param base_frame_id Robot base frame (e.g., "base_footprint").
57+
* @param global_frame_id Global frame of the costmap (e.g., "odom" or "map").
58+
* @param transform_tolerance Allowed TF age for transforms.
59+
* @param source_timeout Max age of data before it is considered stale.
60+
* @param base_shift_correction Whether to compensate robot motion during simulation checks.
61+
*/
3262
CostmapSource(
33-
3463
const nav2::LifecycleNode::WeakPtr & node,
3564
const std::string & source_name,
3665
const std::shared_ptr<tf2_ros::Buffer> tf_buffer,
@@ -40,31 +69,63 @@ class CostmapSource : public Source
4069
const rclcpp::Duration & source_timeout,
4170
const bool base_shift_correction);
4271

72+
/// @brief Destructor.
4373
~CostmapSource();
4474

75+
/**
76+
* @brief Declare and get parameters; create the subscription.
77+
*
78+
* Must be called during the node’s configuration phase (after construction, before use).
79+
* Reads `topic`, `cost_threshold`, and `treat_unknown_as_obstacle`.
80+
*/
4581
void configure();
4682

83+
/**
84+
* @brief Produce current obstacle points from the latest costmap.
85+
* @param curr_time Current time used for staleness checks and TF queries.
86+
* @param[out] data Output vector of points in the base frame.
87+
* @return true if valid, non-stale data were produced; false otherwise.
88+
*
89+
* @details
90+
* - Returns false if no message has arrived or data are older than @ref source_timeout_.
91+
* - Transforms points from costmap frame to @ref base_frame_id using @ref tf_buffer_.
92+
* - Applies @ref cost_threshold_ and @ref treat_unknown_as_obstacle_.
93+
*/
4794
bool getData(
4895
const rclcpp::Time & curr_time,
4996
std::vector<Point> & data) override;
5097

98+
/**
99+
* @brief Read parameters specific to the costmap source.
100+
* @param[out] source_topic Resolved topic name to subscribe to.
101+
*
102+
* Declares/gets: `topic`, `cost_threshold`, `treat_unknown_as_obstacle`.
103+
*/
51104
void getParameters(std::string & source_topic);
52105

53106
private:
107+
/**
108+
* @brief Subscription callback to store the latest costmap message.
109+
* @param msg Incoming costmap.
110+
*/
54111
void dataCallback(nav2_msgs::msg::Costmap::ConstSharedPtr msg);
55-
// ↑ Store the latest Costmap message; we’ll read it in getData()
56112

57-
nav2_msgs::msg::Costmap::ConstSharedPtr data_; // Latest costmap message (thread-safe shared ptr)
58-
rclcpp::Subscription<nav2_msgs::msg::Costmap>::SharedPtr data_sub_;
113+
/// @brief Latest costmap message.
114+
nav2_msgs::msg::Costmap::ConstSharedPtr data_;
59115

60-
// Threshold for considering a cell as an obstacle. Valid range: 0..255.
61-
// Typical choices: 253 (inscribed), 254 (lethal). Inflation = 1..252.
116+
/// @brief Subscription handle for the costmap topic.
117+
nav2::Subscription<nav2_msgs::msg::Costmap>::SharedPtr data_sub_;
118+
119+
/**
120+
* @brief Minimum cost (0..255) considered as an obstacle.
121+
* @note Typical values: 253 (inscribed), 254 (lethal). Inflation = 1..252.
122+
*/
62123
int cost_threshold_{253};
63124

64-
// Whether 255 (NO_INFORMATION) should be treated as an obstacle.
125+
/**
126+
* @brief Whether cost 255 (NO_INFORMATION) is treated as an obstacle.
127+
*/
65128
bool treat_unknown_as_obstacle_{true};
66-
67-
68129
};
69130

70131
} // namespace nav2_collision_monitor

nav2_collision_monitor/package.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
<depend>nav2_ros_common</depend>
2828
<depend>point_cloud_transport</depend>
2929
<depend>point_cloud_transport_plugins</depend>
30-
<!-- <depend>nav2_common</depend> -->
3130

3231
<test_depend>ament_cmake_gtest</test_depend>
3332
<test_depend>ament_lint_common</test_depend>

nav2_collision_monitor/params/collision_monitor_params.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ collision_monitor:
102102
max_height: 0.5
103103
use_global_height: False
104104
enabled: True
105-
costmap:
106-
type: "costmap"
107-
topic: "/local_costmap/costmap"
108-
cost_threshold: 254
109-
enabled: True
110-
treat_unknown_as_obstacle: True
105+
# costmap:
106+
# type: "costmap"
107+
# topic: "local_costmap/costmap" # relative, respects namespaces
108+
# cost_threshold: 254
109+
# enabled: True
110+
# treat_unknown_as_obstacle: True

nav2_collision_monitor/src/costmap.cpp

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,16 @@
1414
// limitations under the License.
1515
#include "nav2_msgs/msg/costmap.hpp"
1616
#include "nav2_collision_monitor/costmap.hpp"
17-
#include <functional>
1817
#include <cmath>
1918
#include <tf2/time.hpp>
2019
#include <tf2_ros/buffer.hpp>
2120
#include <tf2_ros/transform_listener.hpp>
22-
#include <nav2_ros_common/lifecycle_node.hpp>
2321
#include <nav2_ros_common/node_utils.hpp>
22+
#include <nav2_ros_common/qos_profiles.hpp>
23+
#include <nav2_costmap_2d/cost_values.hpp>
2424

2525
namespace nav2_collision_monitor
2626
{
27-
28-
2927
CostmapSource::CostmapSource(
3028
const nav2::LifecycleNode::WeakPtr & node,
3129
const std::string & source_name,
@@ -43,7 +41,6 @@ CostmapSource::CostmapSource(
4341
RCLCPP_INFO(logger_, "[%s]: Creating CostmapSource", source_name_.c_str());
4442
}
4543

46-
4744
CostmapSource::~CostmapSource()
4845
{
4946
RCLCPP_INFO(logger_, "[%s]: Destroying CostmapSource", source_name_.c_str());
@@ -59,19 +56,17 @@ void CostmapSource::configure()
5956
}
6057
std::string source_topic;
6158
getParameters(source_topic);
62-
rclcpp::QoS qos = rclcpp::SystemDefaultsQoS();
63-
64-
6559
data_sub_ = node->create_subscription<nav2_msgs::msg::Costmap>(
6660
source_topic,
6761
std::bind(&CostmapSource::dataCallback, this, std::placeholders::_1),
68-
qos);
62+
nav2::qos::StandardTopicQoS());
6963
}
7064

7165
bool CostmapSource::getData(
7266
const rclcpp::Time & curr_time,
7367
std::vector<Point> & data)
7468
{
69+
auto node = node_.lock();
7570
if (data_ == nullptr) {
7671
return false;
7772
}
@@ -89,7 +84,6 @@ bool CostmapSource::getData(
8984
}
9085
}
9186

92-
9387
// Extract lethal/inscribed cells and transform to base frame
9488
const auto & cm = *data_;
9589
const auto & meta = cm.metadata;
@@ -98,17 +92,18 @@ bool CostmapSource::getData(
9892
for (unsigned int x = 0; x < meta.size_x; ++x) {
9993
const int idx = y * meta.size_x + x;
10094

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);
95+
const uint8_t cell_cost = cm.data[idx];
96+
const bool is_obstacle =
97+
(cell_cost >= cost_threshold_ && cell_cost < nav2_costmap_2d::NO_INFORMATION) ||
98+
(treat_unknown_as_obstacle_ && cell_cost == nav2_costmap_2d::NO_INFORMATION);
10499
if (is_obstacle) {
105100
const double wx = meta.origin.position.x + (x + 0.5) * meta.resolution;
106101
const double wy = meta.origin.position.y + (y + 0.5) * meta.resolution;
107102
tf2::Vector3 p_v3_s(wx, wy, 0.0);
108103
tf2::Vector3 p_v3_b = tf_transform * p_v3_s;
109104
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);
105+
RCLCPP_DEBUG_THROTTLE(logger_, *node->get_clock(), 2000 /*ms*/,
106+
"[%s] Found obstacles in costmap", source_name_.c_str());
112107
}
113108
}
114109
}
@@ -125,9 +120,8 @@ void CostmapSource::getParameters(std::string & source_topic)
125120

126121
// Cost threshold (0–255). 253 = inscribed 254 = lethal; 255 = NO_INFORMATION.
127122
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();
123+
// Minimal change (no range descriptor)
124+
int v = node->declare_or_get_parameter<int>(thresh_name, 253); // declare if missing, else get
131125
v = std::max(0, std::min(255, v)); // clamp
132126
if (v != node->get_parameter(thresh_name).as_int()) {
133127
RCLCPP_WARN(node->get_logger(), "Clamping %s to %d", thresh_name.c_str(), v);
@@ -136,9 +130,7 @@ void CostmapSource::getParameters(std::string & source_topic)
136130

137131
// Whether 255 (NO_INFORMATION) should be treated as an obstacle.
138132
const auto unk_name = source_name_ + ".treat_unknown_as_obstacle";
139-
nav2::declare_parameter_if_not_declared(
140-
node, unk_name, rclcpp::ParameterValue(true));
141-
treat_unknown_as_obstacle_ = node->get_parameter(unk_name).as_bool();
133+
treat_unknown_as_obstacle_ = node->declare_or_get_parameter<bool>(unk_name, true);
142134
}
143135

144136
void CostmapSource::dataCallback(nav2_msgs::msg::Costmap::ConstSharedPtr msg)

nav2_collision_monitor/test/bags/cm_moving_obstacle/fake_cm_bag_source.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ class FakeCMSource(Node):
3737

3838
def __init__(self):
3939
super().__init__('fake_cm_bag_source')
40-
# Use sim time so /clock drives timestamps
41-
# self.set_parameters([Parameter('use_sim_time', value=True)])
4240

4341
# Publishers
4442
self.clock_pub = self.create_publisher(ClockMsg, '/clock', 10)

nav2_collision_monitor/test/collision_monitor_node_bag.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ class MetricsCatcher : public rclcpp::Node {
5252
stop_window_start_ = this->declare_parameter<double>("stop_window_start", 3.0);
5353
stop_window_end_ = this->declare_parameter<double>("stop_window_end", 8.0);
5454

55-
5655
// Velocity classification thresholds (on the topic we evaluate)
5756
stop_thresh_ = this->declare_parameter<double>("stop_thresh", 0.02); // |vx| <= stop => stopped
5857
resume_thresh_ = this->declare_parameter<double>("resume_thresh", 0.10); // vx >= resume => resumed

0 commit comments

Comments
 (0)