ROS2 LifecycleNode讲解及实例

LifecycleNode讲解及实例

文章目录

  • 前言
  • LifecycleNode是什么
    • 背景
    • 生命周期
    • 状态定义
      • Unconfigured
      • Inactive
      • Active
      • Finalized
    • 转换逻辑图示
    • 标准接口
  • 代码实现&测试
    • 代码
    • 测试
  • 总结

前言

本文用来记录什么是LifecycleNode,做背景介绍及基本原理的介绍及分析如何使用。1

LifecycleNode是什么

背景

节点的托管生命周期允许更好地控制ROS系统的状态。它将允许roslaunch在允许任何组件开始执行其行为之前确保所有组件都已正确实例化。它还允许重新启动或在线更换节点。

本文档最重要的概念是,受管节点提供已知接口,根据已知的生命周期状态机执行,否则可被视为黑盒。这使得节点开发人员可以自由决定如何提供托管生命周期功能,同时还确保为管理节点而创建的任何工具都可以与任何兼容的节点一起使用。

生命周期

有四个主要状态:

  • Unconfigured
  • Inactive
  • Active
  • Finalized

还存在6个过渡状态,它们是在所请求的过渡期间的中间状态。

  • Configuring
  • CleaningUp
  • ShuttingDown
  • Activating
  • Deactivating
  • ErrorProcessing

在转换状态中,将执行逻辑以确定转换是否成功。成功或失败应通过生命周期管理界面传达给生命周期管理软件。

有7个过渡暴露于监督流程,它们是:

  • create
  • configure
  • cleanup
  • activate
  • deactivate
  • shutdown
  • destroy

状态定义

Unconfigured

这是节点在实例化后立即处于的生命周期状态。这也是节点在发生错误后可能返回的状态。

  • 节点可以经由 configure 转换转换到 Inactive 状态
  • 节点可以经由 shutdown 转换转换到 Finalized 状态

Inactive

此状态表示当前未执行任何处理的节点。

此状态的主要目的是允许节点在运行时进行配置(更改配置参数、添加和删除主题发布/订阅等),而不更改其行为。

当处于这种状态时,节点将不会接收任何执行时间来读取主题、执行数据处理、响应功能服务请求等。

在非活动状态下,将不会读取和/或处理到达托管主题的任何数据。数据保留将受为主题配置的QoS策略的约束。

对处于非活动状态的节点的任何托管服务请求都不会被应答(对于调用者来说,它们将立即失败)。

  • 节点可以经由 shutdown 转换转换到 Finalized 状态
  • 节点可以经由 cleanup 转换转换到 Unconfigured 状态
  • 节点可以经由 activate 转换转换到 Active 状态

Active

这是节点生命周期的主要状态。在这种状态下,节点执行任何处理,响应服务请求,读取和处理数据,产生输出等。

如果在此状态下发生节点/系统无法处理的错误,则节点将转换到 ErrorProcessing

  • 节点可以经由 deactivate 转换转换到 Inactive 状态
  • 节点可以经由 shutdown 转换转换到 Finalized 状态

Finalized

Finalized 状态是节点在被销毁之前立即结束的状态。这个状态总是终结的,从这里开始的唯一转变就是被摧毁。

转换逻辑图示

下边这张图用来说明状态切换之间的关系,如果看不懂也没关系,可以根据后续的测试代码切换一遍流程即可理解。2

请添加图片描述

标准接口

服务(Service):3

  • /change_state - 调用触发合法转换

  • /get_available_transitions - 显示合法的转换

  • /get_state - 显示当前状态

  • /get_available_states - 列出所有状态

  • /get_transition_graph - 显示完整状态机

主题(Topic):

  • /transition_event - 发布正在进行的转换

代码实现&测试

代码

# CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(my_lifecycle_node)if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic)
endif()# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_lifecycle REQUIRED)
find_package(lifecycle_msgs REQUIRED)
find_package(std_msgs REQUIRED)add_executable(my_lifecycle_nodesrc/my_lifecycle_node.cpp)
ament_target_dependencies(my_lifecycle_node rclcpp rclcpp_lifecycle lifecycle_msgs std_msgs)install(TARGETSmy_lifecycle_nodeDESTINATION lib/${PROJECT_NAME}
)if(BUILD_TESTING)find_package(ament_lint_auto REQUIRED)# the following line skips the linter which checks for copyrights# comment the line when a copyright and license is added to all source filesset(ament_cmake_copyright_FOUND TRUE)# the following line skips cpplint (only works in a git repo)# comment the line when this package is in a git repo and when# a copyright and license is added to all source filesset(ament_cmake_cpplint_FOUND TRUE)ament_lint_auto_find_test_dependencies()
endif()ament_package()
# package.xml<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3"><name>my_lifecycle_node</name><version>0.0.0</version><description>TODO: Package description</description><maintainer email="https://blog.csdn.net/Bing_Lee">dev</maintainer><license>TODO: License declaration</license><buildtool_depend>ament_cmake</buildtool_depend><depend>rclcpp</depend><depend>rclcpp_lifecycle</depend><depend>lifecycle_msgs</depend><depend>std_msgs</depend><test_depend>ament_lint_auto</test_depend><test_depend>ament_lint_common</test_depend><export><build_type>ament_cmake</build_type></export>
</package>
#include <iostream>
#include <rclcpp/rclcpp.hpp>
#include <rclcpp_lifecycle/lifecycle_node.hpp>#include "lifecycle_msgs/msg/transition.hpp"
#include "std_msgs/msg/string.hpp"using namespace std::chrono_literals;class my_lifecycle_node : public rclcpp_lifecycle::LifecycleNode
{
public:explicit my_lifecycle_node(const std::string& node_name, bool intra_process_comms = false): rclcpp_lifecycle::LifecycleNode(node_name, rclcpp::NodeOptions().use_intra_process_comms(intra_process_comms)) {}rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_configure(const rclcpp_lifecycle::State&){RCLCPP_INFO(get_logger(), "on_configure() is called.");return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;}rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_activate(const rclcpp_lifecycle::State&){RCUTILS_LOG_INFO_NAMED(get_name(), "on_activate() is called.");std::this_thread::sleep_for(2s);return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;}rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_deactivate(const rclcpp_lifecycle::State&){RCUTILS_LOG_INFO_NAMED(get_name(), "on_deactivate() is called.");return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;}rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_cleanup(const rclcpp_lifecycle::State&){RCUTILS_LOG_INFO_NAMED(get_name(), "on cleanup() is called.");return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;}rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_shutdown(const rclcpp_lifecycle::State& state){RCUTILS_LOG_INFO_NAMED(get_name(), "on shutdown() is called from state %s.", state.label().c_str());return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;}
};int main(int argc, char** argv)
{rclcpp::init(argc, argv);auto node = std::make_shared<my_lifecycle_node>("my_lifecycle_node");rclcpp::spin(node->get_node_base_interface());rclcpp::shutdown();return 0;
}
# 文件结构
$ tree my_lifecycle_node/
my_lifecycle_node/
├── CMakeLists.txt
├── include
│   └── my_lifecycle_node
├── package.xml
└── src└── my_lifecycle_node.cpp

测试

# 编译
$ colcon build --packages-up-to my_lifecycle_node
# bash 安装配置
$ source install/setup.bash
# 运行
$ ros2 run my_lifecycle_node my_lifecycle_node

新开一个窗口

$ ros2 service list
/my_lifecycle_node/change_state
/my_lifecycle_node/describe_parameters
/my_lifecycle_node/get_available_states
/my_lifecycle_node/get_available_transitions
/my_lifecycle_node/get_parameter_types
/my_lifecycle_node/get_parameters
/my_lifecycle_node/get_state
/my_lifecycle_node/get_transition_graph
/my_lifecycle_node/list_parameters
/my_lifecycle_node/set_parameters
/my_lifecycle_node/set_parameters_atomically$ ros2 topic list
/my_lifecycle_node/transition_event
/parameter_events
/rosout

状态切换

# 当前状态
$ ros2 lifecycle get /my_lifecycle_node 
unconfigured [1]
# 配置节点
$ ros2 lifecycle set /my_lifecycle_node configure
Transitioning successful$ ros2 lifecycle get /my_lifecycle_node 
inactive [2]
# 激活节点
$ ros2 lifecycle set /my_lifecycle_node activate
Transitioning successful$ ros2 lifecycle get /my_lifecycle_node 
active [3]
# 停止节点
$ ros2 lifecycle set /my_lifecycle_node deactivate
Transitioning successful$ ros2 lifecycle get /my_lifecycle_node 
inactive [2]
# 获取当前节点可转换的状态
$ ros2 lifecycle list /my_lifecycle_node 
- cleanup [2]Start: inactiveGoal: cleaningup
- activate [3]Start: inactiveGoal: activating
- shutdown [6]Start: inactiveGoal: shuttingdown
# 杀掉节点
$ ros2 lifecycle set /my_lifecycle_node shutdown
Transitioning successful$ ros2 lifecycle get /my_lifecycle_node 
finalized [4]
# 尝试切换杀掉的(状态为finalized)节点,失败
$ ros2 lifecycle set /my_lifecycle_node configure
Unknown transition requested, available ones are:

总结

本文对于LifecycleNode做了整体的说明和测试,说明了中间的变换关系,方便大家理解和用于实际使用中。


  1. ros.rog Class LifecycleNode ↩︎

  2. Managed nodes (ros2.org) ↩︎

  3. ROS2----LifecycleNode生命周期节点总结 ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/217455.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【大数据】Doris 架构

Doris 架构 Doris 的架构很简洁&#xff0c;只设 FE&#xff08;Frontend&#xff09;、BE&#xff08;Backend&#xff09;两种角色、两个进程&#xff0c;不依赖于外部组件&#xff0c;方便部署和运维&#xff0c;FE、BE 都可线性扩展。 ✅ Frontend&#xff08;FE&#xff0…

十六 动手学深度学习v2计算机视觉 ——样式迁移

文章目录 基于CNN的样式迁移 基于CNN的样式迁移 我们通过前向传播&#xff08;实线箭头方向&#xff09;计算风格迁移的损失函数&#xff0c;并通过反向传播&#xff08;虚线箭头方向&#xff09;迭代模型参数&#xff0c;即不断更新合成图像。 风格迁移常用的损失函数由3部分组…

Linux - 进程间通信(中)- 管道的应用场景

前言 在上篇博客当中&#xff0c;对Linux 当中的进程通信&#xff0c;做了详细阐述&#xff0c;主要是针对父子进程的通信来阐述的同时&#xff0c;也进行了模拟实现。 对于管道也有了初步了解&#xff0c;但是这仅仅是 进程间通信的一部分&#xff0c;Linux 当中关于进程间通…

golang 操作Jenkins

1.創建Agent/Node func CreateAgent(username string, password string, nodeName string, nodeDescription string, numExecutors string, remoteFS string, labelString string, host string) {var obj stringobj "{name:" nodeName ",nodeDescription:&q…

YOLOv4 学习笔记

文章目录 前言一、YOLOv4贡献和改进二、YOLOv4核心概念三、YOLOv4网络架构四、YOLOv4数据增强五、YOLOv4的损失函数总结 前言 在近年来的目标检测领域&#xff0c;YOLOv4的出现标志着一个重要的技术突破。YOLOv4不仅继承了YOLO系列快速、高效的特点&#xff0c;还引入了一系列…

【启扬方案】启扬储能管理平板助力储能电站实现智能且高效化运行

在储能领域&#xff0c;储能电站扮演着重要角色&#xff0c;储能电站技术的应用贯穿于电力系统发电、输电、配电、用电的各个环节。实现电力系统削峰填谷、可再生能源发电波动平滑与跟踪计划处理、高效系统调频&#xff0c;增加供电的可靠性。 但随着储能电⼒系统建设发展得越来…

Java网络编程,使用UDP实现TCP(三), 基本实现四次挥手

简介 四次挥手示意图 在四次挥手过程中&#xff0c;第一次挥手中的Seq为本次挥手的ISN&#xff0c; ACK为 上一次挥手的 Seq1&#xff0c;即最后一次数据传输的Seq1。挥手信息由客户端首先发起。 实现步骤&#xff1a; 下面是TCP四次挥手的步骤&#xff1a; 第一次挥手&…

记录一下如何使用python生成二维码 并简单练习命令行参数供初学者参考

主代码main.py 后面是演示效果图&#xff1a; import argparse import sysimport qrcode import os qr qrcode.QRCode(version1,error_correctionqrcode.constants.ERROR_CORRECT_L,box_size10,border4, ) fileList[] fileName[]parserargparse.ArgumentParser(description生…

Ubuntu20.04降低linux版本到5.4.0-26-generic

前言 试用ubuntu20.04安装昇腾的驱动和cann的时&#xff0c;出现如下问题&#xff1a; (base) rootubuntu:/home/work# ./Ascend-hdk-910-npu-driver_23.0.rc3_linux-aarch64.run --full Verifying archive integrity... 100% SHA256 checksums are OK. All good. Uncompr…

基于Python+WaveNet+MFCC+Tensorflow智能方言分类—深度学习算法应用(含全部工程源码)(三)

目录 前言引言总体设计系统整体结构图系统流程图 运行环境模块实现1. 数据预处理2. 模型构建1&#xff09;定义模型结构2&#xff09;优化损失函数 3. 模型训练及保存1&#xff09;模型训练2&#xff09;模型保存3&#xff09;映射保存 相关其它博客工程源代码下载其它资料下载…

“百里挑一”AI原生应用亮相,百度智能云千帆AI加速器首个Demo Day来了!

作者简介&#xff1a; 辭七七&#xff0c;目前大二&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f…

亚马逊云科技:向量数据存储在生成式人工智能应用程序中的作用

生成式人工智能深受大众喜爱&#xff0c;并且由于具备回答问题、写故事、创作艺术品甚至生成代码的功能&#xff0c;推动了行业的转变&#xff0c;那么如何才能在自己的企业中充分地利用生成式人工智能等应运而生问题。许多客户已经积累了大量特定领域的数据&#xff08;财务记…

LangChain学习二:提示-实战(下半部分)

文章目录 上一节内容&#xff1a;LangChain学习二&#xff1a;提示-实战&#xff08;上半部分&#xff09;学习目标&#xff1a;提示词中的示例选择器和输出解释器学习内容一&#xff1a;示例选择器1.1 LangChain自定义示例选择器1.2 实现自定义示例选择器1.2.1实战&#xff1a…

静态路由的原理和配置

一.路由器的工作原理 首先我们知道路由器是工作在网络层的&#xff0c;那就是三层设备。网络层的功能主要为&#xff1a;不同网段之间通信、最佳路径选择也就是逻辑地址&#xff08;ip地址&#xff09;寻址、转发数据。 1.路由器是什么 路由器是能将数据包转发到正确的目的地…

【QT 5 调试软件+(Linux下验证>>>>串口相关初试串口)+Windows下qt代码在Linux下运行+参考win下历程+基础样例】

【QT 5 调试软件Linux下验证>>>>串口相关初试串口参考win下历程基础样例】 1、前言2、实验环境3、先行了解4、自我总结-win下工程切到Linux下1、平台无关的代码&#xff1a;2、依赖的库&#xff1a;3、文件路径和换行符&#xff1a;4、编译器差异&#xff1a;5、构…

什么是防抖与节流?应用场景举例

防抖节流如何处理防抖与节流 防抖节流防抖例子节流例子Vue Axios全局接口防抖、节流封装实现 小结 防抖 防抖&#xff1a;触发高频事件后n秒内函数只会执行一次&#xff0c;如果n秒内高频事件再次被触发&#xff0c;则重新计算时间 应用场景&#xff1a; 提交按钮、用户注册…

QEMU源码全解析 —— virtio(2)

接前一篇文章&#xff1a; 本文内容参考&#xff1a; 《趣谈Linux操作系统》 —— 刘超&#xff0c;极客时间 《QEMU/KVM》源码解析与应用 —— 李强&#xff0c;机械工业出版社 特此致谢&#xff01; 上一回对于virtio进行了简介&#xff0c;并说明了其基本原理以及框架。对…

【JVM入门到实战】(三) 查看字节码文件的工具

一、 javap -v命令 javap是JDK自带的反编译工具&#xff0c;可以通过控制台查看字节码文件的内容。适合在服务器上查看字节码文件内容。直接输入javap查看所有参数。输入javap -v 字节码文件名称 查看具体的字节码信息。&#xff08;如果jar包需要先使用 jar –xvf 命令解压&a…

mmyolo的bbox_loss和检测bbox都是空

最近用mmyolo训练自己的数据集的时候发现训练的时候loss_bbox0&#xff0c;测试和eval的时候结果也全是空的&#xff0c;排除了数据集读取的问题&#xff0c;最后发现是config中自定义了自己的类别但是没有传给dataset。。。 简而言之&#xff0c;在自定义了数据集里的metainf…

【C语言】一个RDMACM、Verbs API与epoll一起使用的例子

一、epoll介绍 epoll是Linux内核为处理大批量文件描述符而作了改进的poll&#xff0c;是Linux下多路复用IO接口select/poll的增强版本&#xff0c;它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。 以下是epoll的主要使用方法和优点&#xff1a; epo…