为什么需要

在机器人开发中,会有很多参数和设置可以后期需要调整的,如果都放到源码里很难实现动态修改和管理,ROS2为了解决这一问题,提出了参数这一通信机制。

是什么

如何理解“参数”?

  • ROS2的参数就是节点的设置
  • 参数类似于ROS中的全局变量,由ROS Master进行管理,其通信机制较为简单,不涉及TCP/UDP的通信。

参数服务器是一种特殊的“通信方式”。特殊点在于参数服务器是节点存储参数的地方、用于配置参数、全局共享参数。

  • 参数服务器使用互联网传输,在节点管理器中运行,实现整个通信过程
  • 参数服务器,作为ROS中另外一种数据传输方式,有别于topic和service,它更加静态。
  • 参数服务器维护者一个数据字典,字典里存储着各种参数和配置
    • 参数服务器在ROS中主要用于实现不同节点之间的数据共享。一般用于存储一些多节点共享的数据,类似于全局变量。
    • 参数服务器相当于是独立于所有节点的一个公共容器,可以将数据存储在该容器中,被不同的节点调用,当然不同的节点也可以往其中存储数据。

维护方式

参数服务器的维护方式非常的简单灵活,总的来讲有三种方式:

  • 命令行维护
  • launch文件内读写
  • node源码

命令行维护

使用命令行来维护参数服务器,主要使用rosparam语句来进行操作的各种命令,如下表:

ROS1:rosparam 命令 作用
rosparam set param_key param_value 设置参数
rosparam get param_key 显示参数
rosparam load file_name 从文件加载参数
rosparam dump file_name 保存参数到文件
rosparam delete 删除参数
rosparam list 列出参数名称

load&&dump文件

load和dump文件需要遵守YAML格式,一般格式如下:

key : value

具体示例如下:

name:'Zhangsan'
age:20
gender:'M'
score{Chinese:80,Math:90}
score_history:[85,82,88,90]

一般格式如下:

launch文件内读写

launch文件中有很多标签,而与参数服务器相关的标签只有两个,一个是< param>,另一个是< rosparam>

node源码

除了上述最常用的两种读写参数服务器的方法,还有一种就是修改ROS的源码,也就是利用API来对参数服务器进行操作。具体内容我们学习完后面章节再进行介绍。

ROS2:体验一下

(1)运行小乌龟模拟器节点和小乌龟控制节点

# 终端一
ros2 run turtlesim turtlesim_node# 终端二
ros2 run turtlesim turtle_teleop_key

(2)查看参数

  • 查看节点有哪些参数(设置)
ros2 param list

  • 看参数的详情信息:参数的名字,参数的描述,参数的类型,还有对参数的约束,最大值最小值等。
# ---- 语法--------
ros2 param describe <node_name> <param_name># ------ 举例 ---
ros2 param describe /turtlesim background_b

  • 获取参数名
param list
  • 获取参数值
ros2 param get /turtlesim background_b

  • 设置参数值:注意这里只是临时修改
# ------------语法
ros2 param set <node_name> <parameter_name> <value># ---------- 举个例子
ros2 param set /turtlesim background_r 44
ros2 param set /turtlesim background_g 156
ros2 param set /turtlesim background_b 10
  • 把参数存起来:相当去把当前的参数值拍一张快照,然后保存下来,后面可以用于恢复参数到当前的数值。
# ------------语法
ros2 param dump <node_name># ---------- 举个例子
ros2 param dump /turtlesim
# 文件被保存成了yaml格式,用cat指令看一看
文件被保存成了yaml格式,用cat指令看一看# 恢复参数:# 方法一:# 我们Ctrl+C关闭乌龟模拟器,然后再重新运行。ros2 run turtlesim turtlesim_node# 着通过param的load的方法把参数值恢复成我们之前存储的。ros2 param load  /turtlesim ./turtlesim.yaml# 方法二:启动节点时加载参数快照# 语法:ros2 run <package_name> <executable_name> --ros-args --params-file <file_name># 先关闭乌龟,然后重新运行ros2 run turtlesim turtlesim_node --ros-args --params-file ./turtlesim.yaml

三个角色

  • ROS Master (管理者):管理者作为一个公共的容器保存数据
  • Talker (参数设置者):参数设置者往容器中存储数据
  • Listener (参数调用者): 参数调用者读取容器中所需的数据

建立流程

  • step1:

    • 参数设置者使用RPC向参数服务器发送参数(包括参数名与参数值)
    • ROS Master 将参数保存到参数列表中。
  • step2:
    • 参数调用者使用RPC向参数服务器发送参数查找请求,请求中包含要查找的参数名。
  • step3:
    • ROS Master 根据步骤2请求提供的参数名查找参数值,并使用RPC将查询结果发送给参数调用者。

参数组成成分

ROS2参数是由键值对组成的.

  • 名字的数据类型是字符串
  • 值的数据类型可以是:
    • bool 和bool[],布尔类型用来表示开关,比如我们可以控制雷达控制节点,开始扫描和停止扫描。
    • int64 和int64[],整形表示一个数字,含义可以自己来定义
    • float64 和float64[],浮点型,可以表示小数类型的参数值
    • string 和string[],字符串,可以用来表示雷达控制节点中真实雷达的ip地址
    • byte[],字节数组,这个可以用来表示图片,点云数据等信息

代码实现

ROS2将日志分为五个级别,在RCLCPP中通过不同的宏可以实现不同日志级别日志的打印,例程如下

RCLCPP_DEBUG(this->get_logger(), "我是DEBUG级别的日志,我被打印出来了!");
RCLCPP_INFO(this->get_logger(), "我是INFO级别的日志,我被打印出来了!");
RCLCPP_WARN(this->get_logger(), "我是WARN级别的日志,我被打印出来了!");
RCLCPP_ERROR(this->get_logger(), "我是ERROR级别的日志,我被打印出来了!");
RCLCPP_FATAL(this->get_logger(), "我是FATAL级别的日志,我被打印出来了!");

有时候日志太多,会让人眼花缭乱找不到重要信息,所以我们需要对日志的级别进行过滤,比如只看INFO以上级别的,ROS2中可以通过已有的API设置日志的级别,RCLCPP中API如下:

this->get_logger().set_level(log_level);

目标:声明参数并实现动态修改打印的日志级别功能

RCLCPP实现

创建功能包和节点

mkdir -p chapt4/chapt4_ws/
ros2 pkg create example_parameters_rclcpp --build-type ament_cmake --dependencies rclcpp --destination-directory src --node-name parameters_basic --maintainer-name "fishros" --maintainer-email "fishros@foxmail.com"

parameters_basic.cpp

#include <chrono>
#include "rclcpp/rclcpp.hpp"class ParametersBasicNode : public rclcpp::Node {public:explicit ParametersBasicNode(std::string name) : Node(name) {RCLCPP_INFO(this->get_logger(), "节点已启动:%s.", name.c_str());}private:
};int main(int argc, char** argv) {rclcpp::init(argc, argv);/*产生一个的节点*/auto node = std::make_shared<ParametersBasicNode>("parameters_basic");/* 运行节点,并检测退出信号*/rclcpp::spin(node);rclcpp::shutdown();return 0;
}

构建测试:

colcon build  --packages-select example_parameters_rclcpp
source install/setup.bash
ros2 run example_parameters_rclcpp parameters_basic

参数API

在RCLCPP的API中,关于参数相关的函数比较多些,但都是围绕参数获取、参数设置、参数描述、列出参数、添加和移除参数回调事件。

使用参数控制节点日志级别

#include <chrono>
#include "rclcpp/rclcpp.hpp"
/*# declare_parameter            声明和初始化一个参数# describe_parameter(name)  通过参数名字获取参数的描述# get_parameter                通过参数名字获取一个参数# set_parameter                设置参数的值
*/
class ParametersBasicNode : public rclcpp::Node {public:// 构造函数,有一个参数为节点名称explicit ParametersBasicNode(std::string name) : Node(name) {RCLCPP_INFO(this->get_logger(), "节点已启动:%s.", name.c_str());this->declare_parameter("rcl_log_level", 0);     /*声明参数*/this->get_parameter("rcl_log_level", log_level); /*获取参数*//*设置日志级别*/this->get_logger().set_level((rclcpp::Logger::Level)log_level);using namespace std::literals::chrono_literals;timer_ = this->create_wall_timer(500ms, std::bind(&ParametersBasicNode::timer_callback, this));}private:int log_level;rclcpp::TimerBase::SharedPtr timer_;void timer_callback() {this->get_parameter("rcl_log_level", log_level); /*获取参数*//*设置日志级别*/this->get_logger().set_level((rclcpp::Logger::Level)log_level);std::cout<<"======================================================"<<std::endl;RCLCPP_DEBUG(this->get_logger(), "我是DEBUG级别的日志,我被打印出来了!");RCLCPP_INFO(this->get_logger(), "我是INFO级别的日志,我被打印出来了!");RCLCPP_WARN(this->get_logger(), "我是WARN级别的日志,我被打印出来了!");RCLCPP_ERROR(this->get_logger(), "我是ERROR级别的日志,我被打印出来了!");RCLCPP_FATAL(this->get_logger(), "我是FATAL级别的日志,我被打印出来了!");}
};int main(int argc, char** argv) {rclcpp::init(argc, argv);/*产生一个的节点*/auto node = std::make_shared<ParametersBasicNode>("parameters_basic");/* 运行节点,并检测退出信号*/rclcpp::spin(node);rclcpp::shutdown();return 0;
}

上面set_level,设置日志级别,ROS2的日志级别定义在文件/opt/ros/humble/include/rcutils/rcutils/logging.h的167-175行

/// The severity levels of log messages / loggers.
enum RCUTILS_LOG_SEVERITY
{RCUTILS_LOG_SEVERITY_UNSET = 0,  ///< The unset log levelRCUTILS_LOG_SEVERITY_DEBUG = 10,  ///< The debug log levelRCUTILS_LOG_SEVERITY_INFO = 20,  ///< The info log levelRCUTILS_LOG_SEVERITY_WARN = 30,  ///< The warn log levelRCUTILS_LOG_SEVERITY_ERROR = 40,  ///< The error log levelRCUTILS_LOG_SEVERITY_FATAL = 50,  ///< The fatal log level
};

编译测试

colcon build --packages-select example_parameters_rclcpp
source install/setup.bash
ros2 run example_parameters_rclcpp parameters_basic

运行后你会发现DEBUG级别的日志并没有被打印出来,原因在于我们将节点的日志级别设置为了0,0对应的日志级别为RCUTILS_LOG_SEVERITY_UNSET即未设置使用默认级别,节点默认的日志级别就是INFO级别的,所以只能打印INFO以上的日志信息。

运行节点的时候可以指定参数的值,我们尝试将log_level的值改成10即DEBUG级别。

ros2 run example_parameters_rclcpp parameters_basic --ros-args -p rcl_log_level:=10

除了在节点运行前通过CLI传递参数,在运动的过程中也可以动态的修改参数

#查看参数列表
ros2 param list
#设置参数级别
ros2 param set /parameters_basic rcl_log_level 10

补充

上面我们通过参数实现了动态控制节点日志级别的功能,其实像这样的功能ROS2早已为我们准备好了,在运行任意节点时候可以通过CLI传递日志级别配置。

ros2 run package-name node-name --ros-args --log-level debug

除了命令行设置参数和查看日志,通过rqt也可以可视化设置和查看

ROS:参数服务器通信相关推荐

  1. rosparam和ROS参数服务器的使用(C++ Python)

    1. Prob. 在一个项目里经常会处理很多不同的参数,同时有很多参数是共用的,每个节点都分别定义的话,某一次修改容易造成不同步的问题.为了方便统一和同步,可以使用ROS的参数服务器来完成上述的事情, ...

  2. ROS参数服务器(参数使用详细介绍)

    参数服务器是可通过网络访问的共享的多变量字典.它是节点存储参数的地方.用于配置参数.全局共享参数.参数服务器使用互联网传输,在节点管理器中运行,实现整个通信过程.它使用XMLRPC数据类型为参数赋值, ...

  3. [ROS](12)ROS通信 —— 参数服务器(Parameter Server)通信

      文章只是个人学习过程中学习笔记,主要参考ROS教程1 2 . [ROS](01)创建ROS工作空间 [ROS](02)创建&编译ROS软件包Package [ROS](03)CMakeLi ...

  4. Linux Ubuntu 16.04 安装 yaml-cpp ROS 下参数服务器及yaml-cpp实现参数读写

    Linux Ubuntu 16.04 安装 yaml-cpp & ROS 下使用.yaml文件实现参数读写 0. 准备工作 1. 安装yaml-cpp 2. ROS中使用.yaml文件实现参数 ...

  5. param参数服务器

    声明:本文主要内容来自: MOOC 机器人操作系统入门.仅仅是为了查阅方便,做了个小结,侵权必删! Table of Contents 零.param介绍 0.0 param有什么用 0.1参数类型 ...

  6. 参数服务器——分布式机器学习的新杀器

    转自:微信公众号 数据极客 在大规模数据上跑机器学习任务是过去十多年内系统架构师面临的主要挑战之一,许多模型和抽象先后用于这一任务.从早期的MPI,到后来的Hadoop,乃至于目前使用较多的Spark ...

  7. rosparam和ROS参数服务

    机器人工作时,我们有需要对机器人的参数(如传感器参数.算法的参数)进行设置. 有些参数(如机器人的轮廓.传感器的高度)在机器人启动时就设定好就行了: 有些参数则需要动态改变(特别是在调试的时候). R ...

  8. ROS学习小笔记(Topic通信 ,service通信,参数服务器)

    (菜鸡整理的学习笔记,原文链接已经挂上,不小心过来的朋友建议去博主那边学习,谢谢) 原文链接:https://blog.csdn.net/LoongEmbedded/article/details/1 ...

  9. ROS系列(四):ROS通信机制系列(3):参数服务器

    参数服务器在ROS中主要用于实现不同节点之间的数据共享.参数服务器相当于是独立于所有节点的一个公共容器,可以将数据存储在该容器中,被不同的节点调用,当然不同的节点也可以往其中存储数据,关于参数服务器的 ...

最新文章

  1. 200万?程序员刚拿下华为Offer,这些技巧你必须知道!
  2. c# poi写入e_C# 使用 NPOI 库读写 Excel 文件(转载)
  3. python毕业设计有哪些方向-Python毕业选题档案管理系统 开题报告
  4. 有空时深入阅读这两篇文章
  5. python接口测试面试题及答案_100道接口测试面试题收好了!【建议收藏】
  6. 矩阵元素求积及其矩阵元素的差分
  7. 32命令模式(Command Pattern)
  8. flask笔记3-模板
  9. 摄影测量--后方交会
  10. 【多题合集】线段覆盖1、2、3
  11. 数字接口系列文章:SPI 总线
  12. Oracle match_recognize
  13. python测试代码怎么写_python unittest编写测试代码
  14. BZOJ3083: 遥远的国度
  15. 被后台杀死后,Android应用如何重新走闪屏逻辑
  16. 《穿越计算机的迷雾》读书笔记五
  17. mysql环境变量配置还是不行_为什么要配置mysql环境变量
  18. 机器学习算法入门介绍
  19. 攻略 | 教你拿下梦寐以求的Offer(多资源)
  20. 开发一个类似美团的外卖小程序多少钱

热门文章

  1. 向前欧拉公式 matlab_史上最完美的数学公式,你知道是什么吗
  2. 免费的CRM软件都有哪些功能?
  3. 【推荐】PHP-集成函数总结
  4. Flink批处理metaspace内存溢出问题
  5. 爱启航2020考研数学真题大串讲讲义
  6. 朗沃软件测试班开班了
  7. VC调用C#的COM组件(DLL)
  8. OPPO 4G发布会今召开:OPPO N1 mini来了
  9. 编程知识体系(Java为主)
  10. MySql导出表结构到Word文档