Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
a0d374f
nav2_ros_common: add lifecycle-managed Subscription wrapper
Lotusymt Jan 3, 2026
0a73e71
modify alias
Lotusymt Jan 3, 2026
9f5f9eb
fix bugs
Lotusymt Jan 4, 2026
7953c21
Fix lifecycle subscription tests and add header guard
Lotusymt Jan 5, 2026
5e5f949
WIP: draft subscription factory lifecycle handling (design not final)
Lotusymt Jan 12, 2026
ccd57ee
fix rviz
Lotusymt Jan 12, 2026
eff1f93
fix cpp linter
Lotusymt Jan 12, 2026
84b8b45
subsscription2.0, imitating publisher
Lotusymt Jan 14, 2026
216d394
fix cpp linter
Lotusymt Jan 14, 2026
020eab4
cleanup
Lotusymt Jan 14, 2026
7a7e7ab
Restore files to upstream/main
Lotusymt Jan 14, 2026
9dd1d1b
Ignore CTest Testing/ artifacts
Lotusymt Jan 14, 2026
8cb1594
revert unintended testfile changes
Lotusymt Jan 14, 2026
a9c12e9
update subscription
Lotusymt Jan 15, 2026
7ecc46c
Clean up CMakeLists.txt by removing unused lines
Lotusymt Jan 20, 2026
d3839fe
Update nav2_ros_common/include/nav2_ros_common/interface_factories.hpp
Lotusymt Jan 20, 2026
b897c7b
Update nav2_ros_common/include/nav2_ros_common/interface_factories.hpp
Lotusymt Jan 20, 2026
ba3f245
Update nav2_ros_common/include/nav2_ros_common/subscription.hpp
Lotusymt Jan 21, 2026
91640b9
fixes
Lotusymt Jan 22, 2026
1e55192
fix param order
Lotusymt Jan 22, 2026
0013d84
fix linter
Lotusymt Jan 22, 2026
fa7eb4c
safe logic for templated node's subscription
Lotusymt Jan 31, 2026
6c01742
use handle message, bypass latched message, tests passed
Lotusymt Mar 4, 2026
d504958
make cloud points compatible
Lotusymt Mar 4, 2026
6d54181
fix bug
Lotusymt Mar 4, 2026
d09c3fa
fix generate result error
Lotusymt Mar 5, 2026
344fc94
nav2_ros_common: create subscription on activate, destroy on deactivate
Lotusymt Apr 28, 2026
75848e8
nav2_costmap_2d, nav2_map_server: align with create-on-activate subs
Lotusymt Apr 28, 2026
7e73798
nav2_costmap_2d, nav2_map_server: activate test subs after PR #5834
Lotusymt Apr 28, 2026
990927f
nav2_util: break LifecycleServiceClient ctor wait loop on shutdown
Lotusymt Apr 28, 2026
2e3f88b
Re-trigger CI
Lotusymt May 3, 2026
7b91f99
Re-trigger CI (round 2)
Lotusymt May 3, 2026
73f7ff0
Re-trigger CI (round 3)
Lotusymt May 3, 2026
d77b3c7
nav2_ros_common, nav2_costmap_2d, nav2_route: activate subs created d…
Lotusymt May 3, 2026
36462f4
nav2_behaviors, nav2_route: activate plugin-owned and behavior Costma…
Lotusymt May 3, 2026
25826b2
nav2_route: expand for-loop bodies to satisfy uncrustify
Lotusymt May 3, 2026
deedeee
nav2_loopback_sim: activate lifecycle subscriptions and fix unit-test…
Lotusymt May 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,6 @@ Session.vim

# Vim Temporary
.netrwhist

# CTest
Testing/
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ repos:
entry: ament_uncrustify
- id: ament_xmllint
name: ament_xmllint
description: Check XML markup using xmllint.
description: Check XML markup using xmllint (well-formedness only, no schema fetch).
language: system
types: [xml]
entry: ament_xmllint
entry: python3 tools/xmllint_wellformed_only
- id: ament_flake8
name: ament_flake8
description: Check Python code style using flake8.
Expand Down
4 changes: 2 additions & 2 deletions nav2_amcl/include/nav2_amcl/amcl_node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class AmclNode : public nav2::LifecycleNode
std::atomic<bool> first_map_received_{false};
amcl_hyp_t * initial_pose_hyp_;
std::recursive_mutex mutex_;
nav2::Subscription<nav_msgs::msg::OccupancyGrid>::ConstSharedPtr map_sub_;
nav2::Subscription<nav_msgs::msg::OccupancyGrid>::SharedPtr map_sub_;
#if NEW_UNIFORM_SAMPLING
struct Point2D { int32_t x; int32_t y; };
static std::vector<Point2D> free_space_indices;
Expand Down Expand Up @@ -204,7 +204,7 @@ class AmclNode : public nav2::LifecycleNode
* @brief Initialize pub subs of AMCL
*/
void initPubSub();
nav2::Subscription<geometry_msgs::msg::PoseWithCovarianceStamped>::ConstSharedPtr
nav2::Subscription<geometry_msgs::msg::PoseWithCovarianceStamped>::SharedPtr
initial_pose_sub_;
nav2::Publisher<geometry_msgs::msg::PoseWithCovarianceStamped>::SharedPtr
pose_pub_;
Expand Down
4 changes: 4 additions & 0 deletions nav2_amcl/src/amcl_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ AmclNode::on_activate(const rclcpp_lifecycle::State & /*state*/)
RCLCPP_INFO(get_logger(), "Activating");

// Lifecycle publishers must be explicitly activated
map_sub_->on_activate();
initial_pose_sub_->on_activate();
pose_pub_->on_activate();
particle_cloud_pub_->on_activate();

Expand Down Expand Up @@ -178,6 +180,8 @@ AmclNode::on_deactivate(const rclcpp_lifecycle::State & /*state*/)
active_ = false;

// Lifecycle publishers must be explicitly deactivated
map_sub_->on_deactivate();
initial_pose_sub_->on_deactivate();
pose_pub_->on_deactivate();
particle_cloud_pub_->on_deactivate();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class CheckStopStatusTestFixture : public nav2_behavior_tree::BehaviorTreeTestFi
std::chrono::milliseconds duration = 100ms;
config_->input_ports["duration_stopped"] = std::to_string(duration.count()) + "ms";
bt_node_ = std::make_shared<nav2_behavior_tree::CheckStopStatus>("check_stop_status", *config_);
odom_smoother_->on_activate();
}

void TearDown()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class IsBatteryChargingConditionTestFixture : public ::testing::Test
static void SetUpTestCase()
{
node_ = std::make_shared<nav2::LifecycleNode>("test_is_battery_charging");
node_->configure();
node_->activate();
executor_ = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
executor_->add_node(node_->get_node_base_interface());
factory_ = std::make_shared<BT::BehaviorTreeFactory>();
Expand Down Expand Up @@ -58,6 +60,10 @@ class IsBatteryChargingConditionTestFixture : public ::testing::Test
delete config_;
config_ = nullptr;
battery_pub_.reset();
if (node_) {
node_->deactivate();
node_->cleanup();
}
node_.reset();
factory_.reset();
executor_.reset();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class IsBatteryLowConditionTestFixture : public ::testing::Test
static void SetUpTestCase()
{
node_ = std::make_shared<nav2::LifecycleNode>("test_is_battery_low");
node_->configure();
node_->activate();
executor_ = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
executor_->add_node(node_->get_node_base_interface());
factory_ = std::make_shared<BT::BehaviorTreeFactory>();
Expand Down Expand Up @@ -59,6 +61,10 @@ class IsBatteryLowConditionTestFixture : public ::testing::Test
delete config_;
config_ = nullptr;
battery_pub_.reset();
if (node_) {
node_->deactivate();
node_->cleanup();
}
node_.reset();
factory_.reset();
executor_.reset();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ class GoalUpdaterTestFixture : public ::testing::Test
static void SetUpTestCase()
{
node_ = std::make_shared<nav2::LifecycleNode>("goal_updater_test_fixture");
node_->configure();
node_->activate();
factory_ = std::make_shared<BT::BehaviorTreeFactory>();

config_ = new BT::NodeConfiguration();
Expand Down Expand Up @@ -62,6 +64,10 @@ class GoalUpdaterTestFixture : public ::testing::Test
{
delete config_;
config_ = nullptr;
if (node_) {
node_->deactivate();
node_->cleanup();
}
node_.reset();
factory_.reset();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class SpeedControllerTestFixture : public nav2_behavior_tree::BehaviorTreeTestFi
bt_node_ = std::make_shared<nav2_behavior_tree::SpeedController>("speed_controller", *config_);
dummy_node_ = std::make_shared<nav2_behavior_tree::DummyNode>();
bt_node_->setChild(dummy_node_.get());
odom_smoother_->on_activate();
}

void TearDown()
Expand Down
10 changes: 10 additions & 0 deletions nav2_behaviors/include/nav2_behaviors/plugins/assisted_teleop.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ class AssistedTeleop : public TimedBehavior<AssistedTeleopAction>
*/
CostmapInfoType getResourceInfo() override {return CostmapInfoType::LOCAL;}

/**
* @brief Activate behavior (and lifecycle-managed subscriptions e.g. preempt_teleop)
*/
void activate() override;

/**
* @brief Deactivate behavior (and lifecycle-managed subscriptions)
*/
void deactivate() override;

protected:
/**
* @brief Configuration of behavior action
Expand Down
14 changes: 14 additions & 0 deletions nav2_behaviors/plugins/assisted_teleop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ void AssistedTeleop::onConfigure()
this, std::placeholders::_1));
}

void AssistedTeleop::activate()
{
TimedBehavior<AssistedTeleopAction>::activate();
vel_sub_->on_activate();
preempt_teleop_sub_->on_activate();
}

void AssistedTeleop::deactivate()
{
preempt_teleop_sub_->on_deactivate();
vel_sub_->on_deactivate();
TimedBehavior<AssistedTeleopAction>::deactivate();
}

ResultStatus AssistedTeleop::onRun(const std::shared_ptr<const AssistedTeleopAction::Goal> command)
{
preempt_teleop_ = false;
Expand Down
33 changes: 30 additions & 3 deletions nav2_behaviors/src/behavior_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,14 +172,28 @@ nav2::CallbackReturn
BehaviorServer::on_activate(const rclcpp_lifecycle::State & /*state*/)
{
RCLCPP_INFO(get_logger(), "Activating");

// Activate lifecycle-managed subscriptions so they receive /local_costmap/published_footprint
// and /global_costmap/published_footprint (and costmaps). Without this, footprint is never
// received and behaviors like AssistedTeleop wait forever for the collision checker.
if (local_costmap_sub_) {
local_costmap_sub_->on_activate();
}
if (global_costmap_sub_) {
global_costmap_sub_->on_activate();
}
if (local_footprint_sub_) {
local_footprint_sub_->on_activate();
}
if (global_footprint_sub_) {
global_footprint_sub_->on_activate();
}

std::vector<pluginlib::UniquePtr<nav2_core::Behavior>>::iterator iter;
for (iter = behaviors_.begin(); iter != behaviors_.end(); ++iter) {
(*iter)->activate();
}

// create bond connection
createBond();

return nav2::CallbackReturn::SUCCESS;
}

Expand All @@ -193,6 +207,19 @@ BehaviorServer::on_deactivate(const rclcpp_lifecycle::State & /*state*/)
(*iter)->deactivate();
}

if (local_costmap_sub_) {
local_costmap_sub_->on_deactivate();
}
if (global_costmap_sub_) {
global_costmap_sub_->on_deactivate();
}
if (local_footprint_sub_) {
local_footprint_sub_->on_deactivate();
}
if (global_footprint_sub_) {
global_footprint_sub_->on_deactivate();
}

// destroy bond connection
destroyBond();

Expand Down
4 changes: 4 additions & 0 deletions nav2_bt_navigator/src/bt_navigator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ nav2::CallbackReturn
BtNavigator::on_activate(const rclcpp_lifecycle::State & state)
{
RCLCPP_INFO(get_logger(), "Activating");

odom_smoother_->on_activate();
for (size_t i = 0; i != navigators_.size(); i++) {
if (!navigators_[i]->on_activate()) {
on_deactivate(state);
Expand All @@ -156,6 +158,8 @@ BtNavigator::on_deactivate(const rclcpp_lifecycle::State & /*state*/)
}
}

odom_smoother_->on_deactivate();

// destroy bond connection
destroyBond();

Expand Down
7 changes: 7 additions & 0 deletions nav2_collision_monitor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ find_package(visualization_msgs REQUIRED)
find_package(nav2_ros_common REQUIRED)
find_package(point_cloud_transport REQUIRED)

# Rolling point_cloud_transport prefers subscribe(..., rclcpp::QoS, ...); Jazzy/Kilted use rmw_qos_profile_t
if(DEFINED ENV{ROS_DISTRO} AND "$ENV{ROS_DISTRO}" STREQUAL "rolling")
add_compile_definitions(POINT_CLOUD_TRANSPORT_SUBSCRIBE_USE_QOS)
endif()

nav2_package()

set(monitor_executable_name collision_monitor)
Expand All @@ -33,6 +38,7 @@ add_library(${monitor_library_name} SHARED
src/circle.cpp
src/source.cpp
src/scan.cpp
src/lifecycle_point_cloud_subscription.cpp
src/pointcloud.cpp
src/polygon_source.cpp
src/range.cpp
Expand Down Expand Up @@ -70,6 +76,7 @@ add_library(${detector_library_name} SHARED
src/circle.cpp
src/source.cpp
src/scan.cpp
src/lifecycle_point_cloud_subscription.cpp
src/pointcloud.cpp
src/polygon_source.cpp
src/costmap.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ class Circle : public Polygon
*/
bool isShapeSet() override;

/**
* @brief Activates circle subscription(s)
*/
void activate() override;
/**
* @brief Deactivates circle subscription(s)
*/
void deactivate() override;

protected:
/**
* @brief Supporting routine obtaining polygon-specific ROS-parameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ class CostmapSource : public Source
*/
void configure();

void activate() override;
void deactivate() override;

/**
* @brief Produce current obstacle points from the latest costmap.
* @param curr_time Current time used for staleness checks and TF queries.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) 2025 Angsa Robotics
// Copyright (c) 2025 lotusymt
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef NAV2_COLLISION_MONITOR__LIFECYCLE_POINT_CLOUD_SUBSCRIPTION_HPP_
#define NAV2_COLLISION_MONITOR__LIFECYCLE_POINT_CLOUD_SUBSCRIPTION_HPP_

#include <functional>
#include <memory>
#include <string>

#include "rclcpp_lifecycle/lifecycle_node.hpp"
#include "sensor_msgs/msg/point_cloud2.hpp"
#include "point_cloud_transport/point_cloud_transport.hpp"

namespace nav2_collision_monitor
{

/**
* @brief Lifecycle-managed subscription that wraps point_cloud_transport::Subscriber.
*
* Gates message delivery on activation state (on_activate/on_deactivate), so it can be
* used like nav2::Subscription when using point_cloud_transport for transport hints.
*/
class LifecyclePointCloudSubscription : public rclcpp_lifecycle::SimpleManagedEntity
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this specialization?

{
public:
RCLCPP_SMART_PTR_DEFINITIONS(LifecyclePointCloudSubscription)

using Callback = std::function<void(sensor_msgs::msg::PointCloud2::ConstSharedPtr)>;

/**
* @brief Construct and create the PointCloudTransport.
* @param node Lifecycle node shared pointer (PointCloudTransport requires Node::SharedPtr on ROS 2 Jazzy).
*/
explicit LifecyclePointCloudSubscription(
rclcpp_lifecycle::LifecycleNode::SharedPtr node);

~LifecyclePointCloudSubscription();

/**
* @brief Subscribe to a topic with transport hints; callback is only invoked when activated.
* @param topic Topic name
* @param qos QoS profile
* @param callback User callback (invoked only when this entity is activated)
* @param transport_hints Transport hints for point_cloud_transport
*/
void subscribe(
const std::string & topic,
const rclcpp::QoS & qos,
Callback callback,
const point_cloud_transport::TransportHints & transport_hints);

void on_activate() override;
void on_deactivate() override;

/** @brief Unsubscribe and release the underlying subscriber. */
void shutdown();

private:
std::shared_ptr<rclcpp_lifecycle::LifecycleNode> node_;
std::shared_ptr<point_cloud_transport::PointCloudTransport> pct_;
point_cloud_transport::Subscriber data_sub_;
};

} // namespace nav2_collision_monitor

#endif // NAV2_COLLISION_MONITOR__LIFECYCLE_POINT_CLOUD_SUBSCRIPTION_HPP_
Loading
Loading