本文以 ROS 2 Humble 与 C++ rclcpp_lifecycle::LifecycleNode 为例,说明生命周期节点的状态模型,以及节点内部直调、命令行、ROS 服务和生命周期管理器四种调用方式。重点区分“节点进程已启动”与“节点已经投入业务运行”。

前言

普通 ROS 2 节点通常在进程启动后就立即开始发布、订阅或执行控制逻辑。对于传感器驱动、底盘驱动和导航等模块,这种模式不利于控制初始化顺序和故障恢复。

生命周期节点(LifecycleNode)将节点的工作过程拆分为多个可控阶段:先创建节点、再初始化资源、确认准备完成后激活业务;需要停机或恢复时,也可以先停止业务再释放资源。

这套机制适合 IMU、雷达、底盘、定位、导航等有明确启动依赖的机器人模块。


一、生命周期节点的状态模型

最常用的状态转换如下:

Unconfigured --configure--> Inactive --activate--> Active
Active --deactivate--> Inactive --cleanup--> Unconfigured
任一主状态 --shutdown--> Finalized

各主状态的含义如下。

状态 含义
Unconfigured 节点对象已创建,但尚未初始化业务资源。
Inactive 初始化已完成,但业务尚未运行,例如不发布传感器数据。
Active 节点正式工作,可发布消息、启动定时器、处理控制任务。
Finalized 节点已关闭,不能继续恢复工作。

典型的生命周期回调包括:

CallbackReturn on_configure(const rclcpp_lifecycle::State & state);
CallbackReturn on_activate(const rclcpp_lifecycle::State & state);
CallbackReturn on_deactivate(const rclcpp_lifecycle::State & state);
CallbackReturn on_cleanup(const rclcpp_lifecycle::State & state);
CallbackReturn on_shutdown(const rclcpp_lifecycle::State & state);

业务代码不应自行调用 on_configure()on_activate()。这些是状态机回调,应通过状态转换接口触发。

例如,一个姿态角测试发布器可以在 on_configure() 中创建生命周期发布器和定时器,在 on_activate() 中激活发布器、启动定时器;在 on_deactivate() 中停止定时器,在 on_cleanup() 中释放资源。


二、方式一:在节点内部直接调用

这是最适合测试节点或“默认启动即运行”场景的方式。

main() 中创建节点后,依次调用 configure()activate()

#include <memory>

#include "lifecycle_msgs/msg/state.hpp"
#include "rclcpp/executors/single_threaded_executor.hpp"

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);

  auto node = std::make_shared<YawAnglePublisher>();

  if (node->configure().id() !=
      lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE)
  {
    rclcpp::shutdown();
    return 1;
  }

  if (node->activate().id() !=
      lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE)
  {
    rclcpp::shutdown();
    return 1;
  }

  rclcpp::executors::SingleThreadedExecutor executor;
  executor.add_node(node->get_node_base_interface());
  executor.spin();

  rclcpp::shutdown();
  return 0;
}

调用链为:

main()
  ↓
configure()
  ↓
on_configure()
  ↓
activate()
  ↓
on_activate()
  ↓
节点进入 Active 状态

rclcpp_lifecycle::LifecycleNode 还提供通用的 trigger_transition() 接口,可按 transition ID 触发状态转换。但对常见流程而言,configure()activate()deactivate()cleanup() 可读性更好。

在 ROS 2 Humble 中,生命周期节点建议使用执行器并加入节点基础接口:

rclcpp::executors::SingleThreadedExecutor executor;
executor.add_node(node->get_node_base_interface());
executor.spin();

不要将它当作普通 rclcpp::Node,直接写成 rclcpp::spin(node)

适用场景:

  • 单独运行的测试发布器或订阅器;
  • 无需人工确认即可工作的固定功能节点;
  • 希望执行 ros2 run 后立即开始工作的节点。

三、方式二:使用命令行调用

ROS 2 提供了 ros2 lifecycle 命令,适合开发调试和人工运维。

查看节点当前状态:

ros2 lifecycle get /yaw_angle_publisher

执行配置和激活:

ros2 lifecycle set /yaw_angle_publisher configure
ros2 lifecycle set /yaw_angle_publisher activate

停用、清理和关闭:

ros2 lifecycle set /yaw_angle_publisher deactivate
ros2 lifecycle set /yaw_angle_publisher cleanup
ros2 lifecycle set /yaw_angle_publisher shutdown

这种方式尤其适合硬件调试:先让节点停在 Unconfigured,确认参数正确后执行 configure;确认串口、网络或设备初始化成功后,再执行 activate


四、方式三:通过 ROS 服务调用

生命周期节点会对外提供状态控制服务。最核心的是:

/节点名/change_state

其服务类型为:

lifecycle_msgs/srv/ChangeState

例如,手工调用服务让节点进入配置状态:

ros2 service call /yaw_angle_publisher/change_state \
  lifecycle_msgs/srv/ChangeState \
  "{transition: {id: 1, label: ''}}"

常用状态转换 ID:

操作 Transition ID
configure 1
cleanup 2
activate 3
deactivate 4
shutdown 5、6、7

节点还会提供状态查询服务,包括:

/节点名/get_state
/节点名/get_available_states
/节点名/get_available_transitions
/节点名/get_transition_graph

其他 C++ 节点可创建 ChangeState client,由程序主动控制目标节点:

auto client = this->create_client<lifecycle_msgs::srv::ChangeState>(
  "/yaw_angle_publisher/change_state");

auto request = std::make_shared<lifecycle_msgs::srv::ChangeState::Request>();
request->transition.id =
  lifecycle_msgs::msg::Transition::TRANSITION_ACTIVATE;

client->async_send_request(request);

这种方式适合上位机控制、故障恢复逻辑、机器人启动脚本,以及多节点之间的状态联动。


五、方式四:使用生命周期管理器统一调度

当系统中存在多个相互依赖的生命周期节点时,更适合由生命周期管理器统一控制。

例如一台 AMR 的启动顺序可能为:

IMU 驱动
  ↓
雷达驱动
  ↓
底盘驱动
  ↓
定位节点
  ↓
导航节点

管理器一般完成以下流程:

等待目标节点服务就绪
  ↓
逐个 configure
  ↓
检查是否均进入 Inactive
  ↓
逐个 activate
  ↓
检查是否均进入 Active

如果某一节点初始化失败,管理器可以停止后续激活,执行清理或进行故障告警。导航系统中常见的生命周期管理器也是通过节点的生命周期服务进行控制,并不是跨进程直接调用目标节点的 C++ 成员函数。

适用场景:

  • IMU、雷达、底盘、定位和导航等多个模块协同启动;
  • 存在明确初始化依赖关系;
  • 需要统一启停、状态监控和故障恢复。

六、ros2 launch 不等于节点已激活

这是生命周期节点中最常见的误区。

ros2 launch:负责启动节点进程
生命周期转换:负责决定节点是否初始化、是否真正工作

因此,单独执行:

ros2 launch my_package my_launch.py

通常只会启动生命周期节点进程。节点是否会自动进入 Active,取决于项目的设计:

  1. 节点在 main() 中主动执行 configure()activate()
  2. 用户通过 ros2 lifecycle set 手工切换;
  3. 其他节点通过 /change_state 服务切换;
  4. 生命周期管理器统一切换。

七、不同场景的推荐方案

场景 推荐方式
单个测试发布器、订阅器 节点内部自动 configure -> activate
驱动参数与硬件连通性调试 ros2 lifecycle 命令行
上位机或业务节点控制驱动 /change_state 服务客户端
多传感器、多驱动和导航协同启动 生命周期管理器

对于简单测试程序,自动激活能够减少重复操作;对于真实机器人系统,建议保留标准生命周期服务,并由统一管理器协调启动顺序与异常恢复。

总结

生命周期节点的核心价值,是把“节点已创建”和“节点正在工作”明确拆开:

创建节点 → 初始化资源 → 激活业务 → 停用业务 → 清理资源 → 关闭节点

ROS 2 中常见的四种调用方式分别是:

  1. 节点内部调用 configure()activate()
  2. 使用 ros2 lifecycle set 命令;
  3. 调用 /change_state 服务;
  4. 使用生命周期管理器统一调度。

选择哪一种方式,取决于系统规模和控制需求:测试节点适合自动启动,真实机器人系统则更适合可观测、可控、可恢复的统一生命周期管理。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐