4. 生命周期状态详解
ROS2 的生命周期节点(Lifecycle Node)把节点的运行过程拆分为一组可管理的状态,使自动驾驶系统中的感知、定位、规划、控制等模块能够被启动器、健康管理器和诊断系统统一编排。理解每个状态的含义、进入与退出条件,以及各状态下资源的持有策略,是编写可靠生命周期节点的核心。
一、四个主状态与两个过渡状态
ROS2 标准生命周期状态机包含四个稳定状态和若干过渡状态。稳定状态是节点可以停留并被外部观察的状态,过渡状态则是状态迁移过程中的中间态,通常由回调函数执行期间短暂存在。
- Unconfigured(未配置):节点已创建,但尚未分配任何运行时资源。此时节点只持有节点句柄和参数声明,不创建发布者、订阅者、定时器或硬件句柄。
- Inactive(非活跃):节点已完成配置,资源已分配,但数据流被暂停。发布者、订阅者、服务、动作服务器均已创建,但不参与实际的数据处理与输出。
- Active(活跃):节点处于正常工作状态,订阅回调被触发,定时器运行,发布者向外发送数据,是自动驾驶节点真正参与系统闭环的状态。
- Finalized(已终结):节点已释放全部资源,进入不可恢复的终态,只能通过销毁节点来退出。
过渡状态包括 Configuring、CleaningUp、Activating、Deactivating、ShuttingDown、ErrorProcessing 等,它们分别对应 on_configure、on_cleanup、on_activate、on_deactivate、on_shutdown、on_error 回调的执行过程。
二、各状态的进入条件与退出条件
状态迁移由外部服务调用或内部错误触发。ROS2 为每个生命周期节点提供标准服务接口,如 change_state、get_state、get_available_states、get_available_transitions。外部管理器通过 change_state 请求迁移,节点在对应回调中完成资源操作。
| 状态 | 进入条件 | 退出条件 | 资源策略 |
|---|---|---|---|
| Unconfigured | 节点创建完成,或 cleanup 成功,或 configure 失败 | 收到 configure 请求,或 shutdown 请求 | 不创建发布者、订阅者、定时器、硬件句柄 |
| Inactive | on_configure 成功返回 | 收到 activate、cleanup 或 shutdown 请求 | 创建并持有全部通信资源与硬件资源,但不处理数据 |
| Active | on_activate 成功返回 | 收到 deactivate 或 shutdown 请求 | 资源处于使用中,回调、定时器、发布全部生效 |
| Finalized | on_shutdown 成功返回,或不可恢复错误 | 无退出路径,只能销毁节点 | 全部资源已释放,节点不再响应任何状态迁移 |
三、回调函数中的资源管理策略
生命周期节点的资源管理遵循“配置时分配、清理时释放、激活时启用、去激活时暂停”的原则。下面是一个典型的感知节点实现片段:
class PerceptionNode : public rclcpp_lifecycle::LifecycleNode
{
public:
PerceptionNode() : LifecycleNode("perception_node") {}
CallbackReturn on_configure(const State &) override
{
// 分配资源:创建订阅、发布、参数、模型句柄
sub_ = create_subscription<sensor_msgs::msg::PointCloud2>(
"/lidar/points", 10, std::bind(&PerceptionNode::onCloud, this, _1));
pub_ = create_publisher<vision_msgs::msg::Detection2DArray>("/detections", 10);
detector_.loadModel(declare_parameter("model_path", ""));
return CallbackReturn::SUCCESS;
}
CallbackReturn on_activate(const State &) override
{
pub_->on_activate(); // 启用发布者
active_ = true; // 允许回调处理数据
return CallbackReturn::SUCCESS;
}
CallbackReturn on_deactivate(const State &) override
{
active_ = false; // 暂停数据处理
pub_->on_deactivate();
return CallbackReturn::SUCCESS;
}
CallbackReturn on_cleanup(const State &) override
{
sub_.reset();
pub_.reset();
detector_.release();
return CallbackReturn::SUCCESS;
}
CallbackReturn on_shutdown(const State &) override
{
active_ = false;
sub_.reset();
pub_.reset();
detector_.release();
return CallbackReturn::SUCCESS;
}
private:
void onCloud(const sensor_msgs::msg::PointCloud2::SharedPtr msg)
{
if (!active_) return; // 非活跃状态直接丢弃数据
// ... 推理与发布
}
rclcpp::Subscription<sensor_msgs::msg::PointCloud2>::SharedPtr sub_;
rclcpp_lifecycle::LifecyclePublisher<vision_msgs::msg::Detection2DArray>::SharedPtr pub_;
Detector detector_;
bool active_{false};
};
四、典型场景:自动驾驶启动流程中的状态编排
在一个自动驾驶系统中,启动器通常按以下顺序编排生命周期节点:
- 系统上电后,所有节点处于 Unconfigured,启动器调用 configure 服务,节点加载模型、打开传感器、创建通信接口。
- 配置完成后,节点进入 Inactive,此时数据流尚未打通,但资源已就绪,可以进行自检和参数校验。
- 启动器确认所有节点配置成功后,统一调用 activate,节点进入 Active,感知、定位、规划、控制开始闭环运行。
- 当车辆进入人工接管或停车状态时,启动器调用 deactivate,节点暂停数据处理但保留资源,便于快速恢复。
- 系统下电或节点需要升级时,调用 shutdown,节点释放资源进入 Finalized,随后销毁。
五、错误处理与状态恢复
当 on_configure、on_activate 等回调返回 FAILURE 或抛出异常时,节点会进入 ErrorProcessing 过渡状态,并执行 on_error 回调。on_error 的返回值决定后续去向:返回 SUCCESS 时节点回到 Unconfigured,返回 FAILURE 时进入 Finalized。因此,on_error 中应尽量释放已分配的资源,避免资源泄漏。
CallbackReturn on_error(const State &) override
{
RCLCPP_ERROR(get_logger(), "进入错误处理,释放资源");
sub_.reset();
pub_.reset();
detector_.release();
return CallbackReturn::SUCCESS; // 回到 Unconfigured,允许重新配置
}
在自动驾驶场景中,建议将可恢复错误(如模型加载失败、传感器暂时不可用)通过 on_error 回到 Unconfigured,由启动器重试 configure;将不可恢复错误(如硬件损坏、内存耗尽)直接进入 Finalized,并通知健康管理模块。通过合理设计各状态的进入条件、退出条件和资源策略,生命周期节点才能成为自动驾驶系统中可编排、可诊断、可恢复的可靠构件。