友情提示:380元/半年,儿童学编程,就上码丁实验室。
ROS2入门教程-管理节点
说明:
- 介绍ROS2中的节点的用途和如何使用和管理节点。
概要
-
ROS2引入了被管理节点的概念,也称为
LifecycleNode
。 -
在下面的教程中,其解释了这些节点的用途,是什么使它们与常规节点不同以及它们如何遵从生命周期管理。
-
Managed nodes are scoped within a state machine of a finite amount of states. These states can be changed by invoking a transition id which indicates the succeeding consecutive state. The state machine is implemented as described at the ROS2 design page.
-
状态可根据实现来区分为
Primary States
和Transition States
-
Primary States
是一个稳定的状态,任何节点都可以执行respected task。 另一方面,Transition States
是临时的中间状态,属于过渡时期。 这些中间状态的结果被用来表明两个主要状态之间的转换是否是成功的。 -
因此, 任何托管节点都可以位于下列状态之一:
-
Primary States (steady states):
-
unconfigured
-
inactive
-
active
-
shutdown
-
-
Transition States (intermediate states):
-
configuring
-
activating
-
deactivating
-
cleaningup
-
shuttingdown
-
-
可能的转换是:
-
configure
-
activate
-
deactivate
-
cleanup
-
shutdown
-
-
更多相关信息,请参阅:http://design.ros2.org/articles/node_lifecycle.html
Demo
-
该演示分为三部分:
-
lifecycle_talker
-
lifecycle_listener
-
lifecycle_service_client
-
-
lifecycle_talker
是一个托管节点, 并发布节点所在的状态。 -
talker节点分成四部分并按以下步骤执行:
-
configuring: 初始化发布者和计时器
-
activate: 激活发布者和计时器以进行发布
-
deactivate: 停止发布者和计时器
-
cleanup: 清除发布者和计时器
-
-
这个演示的原理是作为典型的talker/listener演示来实现的。
-
成像过程可能需要等待片刻,因为需要启动摄像头或者激光。可以在configuring状态时打开摄像头或激光设备,只启动和停止发布设备的数据,只有在cleanup/shutdown阶段才会关闭设备。
-
lifecycle_listener
是显示lifecycle_talker
特性的监听器。talker仅在activate状态下使得消息发布,从而使得listener只有在talker处于activate状态时才接收消息。 -
lifecycle_service_client
是一个脚本调用不同的转换lifecycle_talker
。这表明可以有外部用户来控制节点生命周期。
运行演示
- 运行演示前,需要设置ROS2的环境变量
lifecycle_talker | lifecycle_listener | lifecycle_service_client |
---|---|---|
$ ros2 run lifecycle lifecycle_talker |
$ ros2 run lifecycle lifecycle_listener |
$ ros2 run lifecycle lifecycle_service_client |
![]() |
![]() |
![]() |
-
If we look at the output of the
lifecycle_talker
, we notice that
nothing seems to happen. And this does make sense, since every node
starts asunconfigured
. Thelifecycle_talker
is not configured yet
and in our example, no publishers and timers are created yet. The
same behavior can be seen for thelifecycle_listener
, which is less
surprising given that no publishers are available at this moment. The
interesting part starts with the third terminal. In there we launch
ourlifecycle_service_client
which is responsible for changing the
states of thelifecycle_talker
. -
Triggering transition 1 (configure)
[lc_client] Transition 1 successfully triggered.
[lc_client] Node lc_talker has current state inactive.
- 让
lifecycle_talker
的状态改为inactive
,inactive
意味着将会创建和配置所有的发布者和定时器。但由于处于inactive
状态,故还未开始发布消息。
[lc_talker] on_configure() is called.
Lifecycle publisher is currently inactive. Messages are not published.
...
- 由于
lifecycle_listener
会监听lifecycle_talker
的状态变化,当lifecycle_talker
状态发生变化时,其会收到一个通知。而实际上,其会收到两个通知,一个用于从主要状态"unconfigured"变为"configured"的状态,另一个是从"configured"到"inactive"状态。
[lc_listener] notify callback: Transition from state unconfigured to configuring
[lc_listener] notify callback: Transition from state configuring to inactive
-
Triggering transition 2 (activate)
[lc_client] Transition 2 successfully triggered.
[lc_client] Node lc_talker has current state active. -
让
lifecycle_talker
的状态改为active
,active
意味着将会激活所有的发布者和定时器,同时会开始发布消息。
[lc_talker] on_activate() is called.
[lc_talker] Lifecycle publisher is active. Publishing: [Lifecycle HelloWorld #11]
[lc_talker] Lifecycle publisher is active. Publishing: [Lifecycle HelloWorld #12]
...
lifecycle_listener
接收到与之前相同的通知。lifecycle_talker
状态由"inactive" 变为"active"
[lc_listener] notify callback: Transition from state unconfigured to configuring
[lc_listener] notify callback: Transition from state configuring to inactive
- 与之前的转换事件不同,
lifecycle_listener
开始接收到实际发布的数据
[lc_listener] data_callback: Lifecycle HelloWorld #11
[lc_listener] data_callback: Lifecycle HelloWorld #12
...
-
可以看到此时消息的索引已经是11。这演示的目的是表明如果在生命周期的
lifecycle_listener
任一状态下进行发布消息,那么只有在"active"状态下,消息才实际发布出去。 -
For the rest of the demo, you will see similar output as we deactivate and activate the lifecycle talker and finally shut it down.
The demo code
-
lifecycle_talker,lifecycle_listener和lifecycle_service_client
-
和普通的talker的代码不同,lifecycle_talker不是继承
rclcpp::node::Node
而是继承自rclcpp_lifecycle::LifecycleNode
class LifecycleTalker : public rclcpp_lifecycle::LifecycleNode
-
Every child of LifecycleNodes have a set of callbacks provided. These callbacks go along with the applied state machine attached to it. These callbacks are:
-
rcl_lifecycle_ret_t on_configure(const rclcpp_lifecycle::State & previous_state)
-
rcl_lifecycle_ret_t on_activate(const rclcpp_lifecycle::State & previous_state)
-
rcl_lifecycle_ret_t on_deactivate(const rclcpp_lifecycle::State & previous_state)
-
rcl_lifecycle_ret_t on_cleanup(const rclcpp_lifecycle::State & previous_state)
-
rcl_lifecycle_ret_t on_shutdown(const rclcpp_lifecycle::State & previous_state)
-
-
这些回调都有一个正的默认返回值(
return RCL_LIFECYCLE_RET_OK
)。这允许生命周期节点改变其状态,即使没有显式的回调函数被覆盖。还有一个用于错误处理的回调函数。每当一个状态转换抛出一个未捕获的异常,就会调用on_error
。 -
这为执行自定义错误处理提供了空间。只有(!)在这个函数返回的情况下,
RCL_LIFECYCLE_RET_OK
状态机转换到状态unconfigured
。默认情况下,on_error
返回RCL_LIFECYCLE_RET_ERROR
和状态机转换到finalized
。 -
同时,每个生命周期节点默认具有5个不同的通信接口。
-
Publisher
<node_name>__transition_event
: publishes in case a transition is happening. This allows users to get notified of transition events within the network. -
Service
<node_name>__get_state
: 查询节点的当前状态。返回一个主要或转换状态 -
Service
<node_name>__change_state
: triggers a transition for the
current node. This service call takes a transition id. Only in the
case, that this transition ID is a valid transition of the current
state, the transition is fulfilled. All other cases are getting
ignored. -
Service <node_name>__get_available_states: 一个内省工具,其返回这个节点可能存在的所有状态的列表
-
Service <node_name>__get_available_transitions: 一个内省工具,其返回这个节点可以执行的所有可能转换的列表
-
lifecycle_service_client_py.py