0 官方例程文档
ros2 humble lifecycle demo github repo
1 引言
ROS2引入了受管理节点的概念,受管理的节点又被称为是生命周期节点(LifecycleNode)。在接下来的教程中,我们会解释这些节点的作用,是什么使得它们和普通节点不一样,以及它们是怎样受到生命周期的管理的。受管理的节点内有一个状态机,状态机里有一系列预定义的状态。这些状态可以通过调用transition id改变,从transition id可以知道接下来的状态。这个状态机的实现可以参见受管理的节点-ROS2设计文档。
主要状态(Primary States)也即稳定状态,在这一状态下任何节点都可以执行相应的任务。而转换状态(Transition States)是瞬间存在的中间状态,只在切换时存在。这些状态的结果被用于显示转换是否成功。这样,任何一个受管理的节点可以处于如下状态之一:
主要状态(稳定状态):
- Unconfigured
- Inactive
- active
- Shutdown(Finalized)
转换状态(中间状态):
- Configuring
- Activating
- Deactivating
- Cleaningup
- Shuttingdown
Transition id:
- Configure
- Activate
- Deactivate
- Cleanup(可以理解为清除配置configuration)
- Shutdown
更详细的信息可参见受管理的节点-ROS2设计文档。
2 The demo
本demo可分为三个application:
- lifecycle_talker
- lifecycle_listener
- lifecycle_service_client
lifecycle_talker
代表一个受管理的节点,并且会根据所处的状态有不同的发布行为。我们将talker node的任务分解成如下几个部分:
- configure:初始化publisher和timer
- activate:激活publisher和定时器,从而使能发布
- deactivate:停止publisher和timer
- cleanup:销毁publisher和timer
本demo展示了一对典型的talker/listener节点。然而,可以想象这样一个场景:你所用的硬件也许会有一段相当长时间的启动阶段(booting phase),比如laser和camera。我们或许可以在configurating state 中 bring up 设备驱动,在active/deactive state中仅开启或停止节点的发布行为,并且仅在clearn up/shutdown状态来shutdown 设备。
lifecycle_listener
是一个简单的listener,用于展示lifecycle talker的特性。因为talker仅仅在active state的时候才会发布消息,所以listener只能在talker处于active state的时候接收到消息。
lifecycle_service_client
是一个脚本,会调用不同的transition,这个可以被当作是外部用户在控制节点的生命周期。
3 运行demo
因为ROS2自带了lifecycle这个package,然后如果已经将ROS2环境变量加入bashrc的话,这里就不用再配置了,如果没有,则需要source一下。
两种方式:
-
一种是在三个终端里分别启动三个节点:
ros2 run lifecycle lifecycle_talker
ros2 run lifecycle lifecycle_listener
ros2 run lifecycle lifecycle_service_client
-
另一种是通过launch文件同时启动
ros2 launch lifecycle lifecycle_demo.launch.py
在第三个service节点启动之前,talker节点是没有发布任何消息的,因为它还处于unconfigured的状态。
3 The demo code
我们看了代码就会发现,相比于普通的talker节点,生命周期talker有一个明显的不同,那就是:我们的节点并不继承自常规的rclcpp::node::Node
,而是rclcpp_lifecycle::LifesycleNode
。
class LifecycleTalker : public rclcpp_lifecycle::LifecycleNode
每个继承自LifecycleNode的子类都有一套回调函数。这些回调函数对应了生命周期节点的状态机。
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
on_configure(const rclcpp_lifecycle::State & previous_state)
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
on_activate(const rclcpp_lifecycle::State & previous_state)
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
on_deactivate(const rclcpp_lifecycle::State & previous_state)
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
on_cleanup(const rclcpp_lifecycle::State & previous_state)
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
on_shutdown(const rclcpp_lifecycle::State & previous_state)
4 命令行控制
查看当前的生命周期节点:ros2 lifecycle nodes
查看某个生命周期节点所处的状态:ros2 lifecycle get <lifecycle_node>
列出某个生命周期节点仍可切换的状态:ros2 lifecycle list <lifecycle_node>
切换某个生命周期节点的状态:
ros2 lifecycle set <lifecycle_node> configure/activate/cleanup/deactivate/shutdown
(切换成功会显示transition successful字样)
其他部分暂时没时间写了,未完待续。