ROS:动态参数

news2025/1/7 18:12:51

目录

  • 一、前言
  • 二、概念
  • 三、作用
  • 四、实际用例
    • 4.1需求
    • 4.2客户端
      • 4.2.1流程
      • 4.2.2新建功能包
      • 4.2.3添加.cfg文件
      • 4.2.4配置 CMakeLists.txt
      • 4.2.5编译
    • 4.3服务端(C++)
      • 4.3.1流程
      • 4.3.2vscode配置
      • 4.3.3服务器代码实现
      • 4.3.4编译配置文件
      • 4.3.5执行
    • 4.4服务端(Python)
      • 4.4.1流程
      • 4.4.2vscode配置
      • 4.4.3服务器代码实现
      • 4.4.4编辑配置文件
      • 4.4.5执行

一、前言

参数服务器的数据被修改时,如果节点不重新访问,那么就不能获取修改后的数据,例如在乌龟背景色修改的案例中,先启动乌龟显示节点,然后再修改参数服务器中关于背景色设置的参数,那么窗体的背景色是不会修改的,必须要重启乌龟显示节点才能生效。而一些特殊场景下,是要求要能做到动态获取的,也即,参数一旦修改,能够通知节点参数已经修改并读取修改后的数据,比如:
机器人调试时,需要修改机器人轮廓信息(长宽高)、传感器位姿信息…,如果这些信息存储在参数服务器中,那么意味着需要重启节点,才能使更新设置生效,但是希望修改完毕之后,某些节点能够即时更新这些参数信息。

在ROS中针对这种场景已经给出的解决方案: dynamic reconfigure 动态配置参数。

动态配置参数,之所以能够实现即时更新,因为被设计成 CS 架构,客户端修改参数就是向服务器发送请求,服务器接收到请求之后,读取修改后的是参数。

二、概念

一种可以在运行时更新参数而无需重启节点的参数配置策略。

三、作用

主要应用于需要动态更新参数的场景,比如参数调试、功能切换等。典型应用:导航时参数的动态调试。

四、实际用例

4.1需求

编写两个节点,一个节点可以动态修改参数,另一个节点时时解析修改后的数据。

4.2客户端

4.2.1流程

1.新建并编辑 .cfg 文件;
2.编辑CMakeLists.txt;
3.编译。

4.2.2新建功能包

新建功能包,添加依赖:roscpp rospy std_msgs dynamic_reconfigure

4.2.3添加.cfg文件

新建 cfg 文件夹,添加 xxx.cfg 文件(并添加可执行权限),cfg 文件其实就是一个 python 文件,用于生成参数修改的客户端(GUI)。

#! /usr/bin/env python
"""
 4生成动态参数 int,double,bool,string,列表
 5实现流程:
 6    1.导包
 7    2.创建生成器
 8    3.向生成器添加若干参数
 9    4.生成中间文件并退出
10
"""
# 1.导包
from dynamic_reconfigure.parameter_generator_catkin import *
PACKAGE = "demo02_dr"
# 2.创建生成器
gen = ParameterGenerator()

# 3.向生成器添加若干参数
#add(name, paramtype, level, description, default=None, min=None, max=None, edit_method="")
gen.add("int_param",int_t,0,"整型参数",50,0,100)
gen.add("double_param",double_t,0,"浮点参数",1.57,0,3.14)
gen.add("string_param",str_t,0,"字符串参数","hello world ")
gen.add("bool_param",bool_t,0,"bool参数",True)

many_enum = gen.enum([gen.const("small",int_t,0,"a small size"),
                gen.const("mediun",int_t,1,"a medium size"),
                gen.const("big",int_t,2,"a big size")
                ],"a car size set")

gen.add("list_param",int_t,0,"列表参数",0,0,2, edit_method=many_enum)

# 4.生成中间文件并退出
exit(gen.generate(PACKAGE,"dr_node","dr"))

chmod +x xxx.cfg添加权限

4.2.4配置 CMakeLists.txt

generate_dynamic_reconfigure_options(
  cfg/mycar.cfg
)

4.2.5编译

编译后会生成中间文件

C++ 需要调用的头文件:
在这里插入图片描述
Python需要调用的文件:
在这里插入图片描述

4.3服务端(C++)

4.3.1流程

1.新建并编辑 c++ 文件;
2.编辑CMakeLists.txt;
3.编译并执行。

4.3.2vscode配置

需要像之前自定义 msg 实现一样配置settings.json 文件,如果以前已经配置且没有变更工作空间,可以忽略,如果需要配置,配置方式与之前相同:

{
    "configurations": [
        {
            "browse": {
                "databaseFilename": "",
                "limitSymbolsToIncludedHeaders": true
            },
            "includePath": [
                "/opt/ros/noetic/include/**",
                "/usr/include/**",
                "/xxx/yyy工作空间/devel/include/**" //配置 head 文件的路径 
            ],
            "name": "ROS",
            "intelliSenseMode": "gcc-x64",
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++17"
        }
    ],
    "version": 4
}

4.3.3服务器代码实现

新建cpp文件,内容如下:

#include "ros/ros.h"
#include "dynamic_reconfigure/server.h"
#include "demo02_dr/drConfig.h"
 /*  
    动态参数服务端: 参数被修改时直接打印
    实现流程:
        1.包含头文件
        2.初始化 ros 节点
        3.创建服务器对象
        4.创建回调对象(使用回调函数,打印修改后的参数)
        5.服务器对象调用回调对象
        6.spin()
*/

void cb(demo02_dr::drConfig& config, uint32_t level){
    ROS_INFO("动态参数解析数据:%d,%.2f,%d,%s,%d",
        config.int_param,
        config.double_param,
        config.bool_param,
        config.string_param.c_str(),
        config.list_param
    );
}

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    // 2.初始化 ros 节点
    ros::init(argc,argv,"dr");
    // 3.创建服务器对象
    dynamic_reconfigure::Server<demo02_dr::drConfig> server;
    // 4.创建回调对象(使用回调函数,打印修改后的参数)
    dynamic_reconfigure::Server<demo02_dr::drConfig>::CallbackType cbType;
    cbType = boost::bind(&cb,_1,_2);
    // 5.服务器对象调用回调对象
    server.setCallback(cbType);
    // 6.spin()
    ros::spin();
    return 0;
}

4.3.4编译配置文件

add_executable(demo01_dr_server src/demo01_dr_server.cpp)
...

add_dependencies(demo01_dr_server ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
...

target_link_libraries(demo01_dr_server
  ${catkin_LIBRARIES}
)

4.3.5执行

先启动roscore

启动服务端:rosrun 功能包 xxxx

启动客户端:rosrun rqt_gui rqt_gui -s rqt_reconfigurerosrun rqt_reconfigure rqt_reconfigure

最终可以通过客户端提供的界面修改数据,并且修改完毕后,服务端会即时输出修改后的结果,最终运行结果与示例类似。

注:ROS版本较新时,可能没有提供客户端相关的功能包导致rosrun rqt_reconfigure rqt_reconfigure调用会抛出异常。

4.4服务端(Python)

4.4.1流程

1.新建并编辑 Python 文件;
2.编辑CMakeLists.txt;
3.编译并执行。

4.4.2vscode配置

需要像之前自定义 msg 实现一样配置settings.json 文件,如果以前已经配置且没有变更工作空间,可以忽略,如果需要配置,配置方式与之前相同:

{
    "python.autoComplete.extraPaths": [
        "/opt/ros/noetic/lib/python3/dist-packages",
        "/xxx/yyy工作空间/devel/lib/python3/dist-packages"
    ]
}

4.4.3服务器代码实现

新建python文件,内容如下:

#! /usr/bin/env python
import rospy
from dynamic_reconfigure.server import Server
from demo02_dr.cfg import drConfig

"""
    动态参数服务端: 参数被修改时直接打印
    实现流程:
        1.导包
        2.初始化 ros 节点
        3.创建服务对象
        4.回调函数处理
        5.spin
"""
# 回调函数
def cb(config,level):
    rospy.loginfo("python 动态参数服务解析:%d,%.2f,%d,%s,%d",
            config.int_param,
            config.double_param,
            config.bool_param,
            config.string_param,
            config.list_param
    )
    return config

if __name__ == "__main__":
    # 2.初始化 ros 节点
    rospy.init_node("dr_p")
    # 3.创建服务对象
    server = Server(drConfig,cb)
    # 4.回调函数处理
    # 5.spin
    rospy.spin()

添加可执行权限:chmod +x *.py

4.4.4编辑配置文件

catkin_install_python(PROGRAMS
  scripts/demo01_dr_server_p.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

4.4.5执行

先启动roscore

启动服务端:rosrun 功能包 xxxx.py

启动客户端:rosrun rqt_gui rqt_gui -s rqt_reconfigurerosrun rqt_reconfigure rqt_reconfigure

最终可以通过客户端提供的界面修改数据,并且修改完毕后,服务端会即时输出修改后的结果,最终运行结果与示例类似。

注:ROS版本较新时,可能没有提供客户端相关的功能包导致rosrun rqt_reconfigure rqt_reconfigure调用会抛出异常。

参考视屏:赵虚左ros入门
在这里插入图片描述

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

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

相关文章

Spring核心问题解答

1.谈谈对Spring的理解 Spring是Java EE编程领域的一个轻量级开源框架&#xff0c;该框架由一个叫Rod Johnson的程序员在 2002 年最早提出并随后创建&#xff0c;是为了解决企业级编程开发中的复杂性&#xff0c;实现敏捷开发的应用型框架 。 Spring是一个开源容器框架&#x…

Python+Qt窗体或Django网页支付宝收款码-扫码付款实例

程序示例精选 PythonQt窗体或Django网页支付宝收款码-扫码付款实例 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<PythonQt窗体或Django网页支付宝收款码-扫码付款实例>>编写代…

智安网络|保护数据资产:不同行业下的数据安全建设策略

在当今数字化时代&#xff0c;数据安全已经成为各行各业无法忽视的重要议题。保持良好网络卫生习惯并及时了解不断变化的网络威胁是企业中每个人的责任。企业、政府机构、医疗机构、金融机构以及其他组织和行业都面临着日益复杂和频繁的网络安全威胁。为了有效应对这些威胁&…

22.代理模式

代理模式 二十三种设计模式中的一种&#xff0c;属于结构型模式。它的作用就是通过提供一个代理类&#xff0c;在调用目标方法的时候&#xff0c;不再是直接对目标方法进行调用&#xff0c;而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦…

自定义表单设计:办公协同效率提高新工具!

为了提高工作效率和表格制作效率&#xff0c;低代码开发平台成为广大用户喜爱的主流平台。因为它包含了非常多的功能内容&#xff0c;在快节奏发展的社会环境中可以满足日益增长的业务需求&#xff0c;是助力通信业、医疗、高校、物流等众多行业办公效率提质增效的得力助手。其…

解决MySQL中分页查询时多页有重复数据,实际只有一条数据的问题

0 前言 有一个离奇的BUG&#xff0c;在查询时&#xff0c;第一页跟第二页有一个共同的数据。有的数据却不显示。 后来发现是在SQL排序时没用主键排序。 解决&#xff1a;使用主键排序 以下是我准备的举例&#xff0c;可以自己试试。 1 数据准备 SET NAMES utf8mb4; SET FORE…

JVM系列(7)——java内存模型

一、什么是JMM 一种抽象的规范。每个JVM 的实现都要遵守这样的规范&#xff0c;这样才能保证Java程序能够“一次编写&#xff0c;到处运行”。 内存模型描述了程序中各个变量&#xff08;实例域、静态域和数组元素&#xff09;之间的关系&#xff0c;以及在实际计算机系统中将…

华为产品测评官-开发者之声 - ModelArts 真实体验感想

华为产品测评官&#xff0d;开发者之声 - ModelArts 真实体验感想 我先是在6月17日参加了华为在深圳举办的开发者大会&#xff0c;后面看到群里发的"2023华为产品测评官&#xff0d;开发者之声"活动&#xff0c;简单看了一下体验活动的具体事情&#xff0c;感觉好玩…

mysql 第六章

目录 1.子查询 2.exists 3.as 别名 4.视图 5.null 6.连接查询 7.总结 1.子查询 2.exists 3.as 别名 4.视图 5.null 6.连接查询 7.总结 对 mysql 数据库的查询&#xff0c;除了基本的查询外&#xff0c;有时候需要对查询的结果集进行处理。

【Policy】使用 InitializingBean 实现策略时如何避免AOP失效

使用InitializingBean实现策略模式 参考策略模式示例中的第一种实现方式.代码demo项目 不同的注入方式对AOP注解的影响 部分策略代码及测试代码 public interface TraditionOrderService extends InitializingBean {// ... } Service public class TraditionOrderServiceIm…

原生信息流广告APP应用内增收及计费模式

比起传统的广告宣传&#xff0c;信息流最大的优势就在于流量的庞大。与此同时&#xff0c;多样化的信息流广告形式和精准的定向&#xff0c;还可以帮助广告主准确获取意向流量。此外&#xff0c;它的广告形式不强迫推送&#xff0c;因此也受到了广泛用户的支持和青睐。 原生信…

Java:输入与输出

目录 输入输出args 输入Scanner 输入格式化输出文件输入与输出 输入输出 args 输入 利用main函数中的参数args&#xff0c;当然也可以起别的名字。其他语言也是一样的。输入时空格分隔。 args的作用&#xff1a;在程序启动时可以用来指定外部参数 Scanner 输入 需要import j…

26.JavaWeb-SpringSecurity安全框架

1.SpringSecurity安全框架 Spring Security是一个功能强大且灵活的安全框架&#xff0c;它专注于为Java应用程序提供身份验证&#xff08;Authentication&#xff09;、授权&#xff08;Authorization&#xff09;和其他安全功能。Spring Security可以轻松地集成到Spring框架中…

Docker高级——网络配置

Docker网络 默认网络 安装 Docker 以后&#xff0c;会默认创建三种网络&#xff0c;可以通过 docker network ls 查看 [roottest ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 6f24f7cbfa10 bridge bridge local 2dc34a1c0f04 host host…

微信号长期没有使用或被回收?

7月17日&#xff0c;有网友表示自己之前申请了一个辅助账号作为树洞使用&#xff0c;如今登录的时候&#xff0c;弹出文字提示称“该微信号由于长期没有使用已被回收”。 腾讯客服回应表示&#xff0c;正常登录使用的微信号不会被系统回收&#xff0c;但对于长时间未登录的微信…

简用前后端的JSON格式注解:@DateTimeFormat、@JsonFormat、@JsonProperty

JsonFormat 【后端到前端】 在实体类属性上面使用JsonFormat注解了&#xff0c;要注意的是&#xff0c;它只会在声明返回类型为json时&#xff0c;比如使用ResponseBody返回json数据的时候&#xff0c;才会返回格式化的yyyy-MM-dd HH:mm:ss时间&#xff0c;如果直接使用Syste…

【分布式系统案例课】查询服务设计、计数栈选型、总结

查询服务设计 数据获取路径 两个问题考虑&#xff1a; 1、老数据归档的问题。 如果所有分钟小时级的数据一直存在这个DB当中&#xff0c;那么DB的存储空间会被不断的消耗&#xff0c;性能也会不断的下降。所以一旦小时天月的数据聚合完成&#xff0c;我们就可以将一些老的原始…

java: 错误: 不支持发行版本 5 java: 错误: 不支持发行版本8 java: 错误: 不支持发行版本17

&#x1f353;&#x1f353;原因 该错误表示你使用的Java编译器不支持Java 5版本的发行。Java版本的发行是根据不同的功能和语言变化来区分的。 要解决这个问题&#xff0c;你可以尝试以下几种方法&#xff1a; 检查编译器配置&#xff1a;确保你的IDE或编译器已正确配置为使…

Segment Tree 线段树算法(java)

线段树算法 Segment Tree 线段树算法代码演示 蓄水池算法 Segment Tree 线段树算法 什么是线段树算法&#xff1a; 线段树&#xff08;Segment Tree&#xff09;是一种基于树结构的数据结构&#xff0c;用于解决区间查询问题&#xff0c;例如区间最大值、最小值、区间和等。线段…

【数据结构】图解八大排序(下)

文章目录 一、前言二、快速排序1. hoare 版2. 挖坑法3. 前后指针法4. 快排的非递归实现5. 时空复杂度分析 三、归并排序1. 递归实现2. 非递归实现 四、计数排序 一、前言 在上一篇文章中&#xff0c;我们已经学习了五种排序算法&#xff0c;还没看过的小伙伴可以去看一下&…