最新消息:

ROS2入门示例-管理节点

ROS2/二代机器人系统 少儿编程 2464浏览 0评论
ROS2入门示例

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 StatesTransition 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
ROS2入门示例-管理节点 ROS2入门示例-管理节点 ROS2入门示例-管理节点
  • 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 as unconfigured. The lifecycle_talker is not configured yet
    and in our example, no publishers and timers are created yet. The
    same behavior can be seen for the lifecycle_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
    our lifecycle_service_client which is responsible for changing the
    states of the lifecycle_talker.

  • Triggering transition 1 (configure)

[lc_client] Transition 1 successfully triggered.
[lc_client] Node lc_talker has current state inactive.
  • lifecycle_talker的状态改为inactiveinactive意味着将会创建和配置所有的发布者和定时器。但由于处于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的状态改为activeactive意味着将会激活所有的发布者和定时器,同时会开始发布消息。

[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

您必须 登录 才能发表评论!