Robot Operating System——Parameter设置的预处理、校验和成功回调

大纲

  • 预处理
  • 校验
  • 成功回调
  • 完整代码
  • 测试
  • 总结

在《Robot Operating System——对Parameter设置进行校验》一文中,我们通过Node的add_on_set_parameters_callback方法,设置了一个回调函数,用于校验传递过来的Parameter参数。但是这个方法并不能对传递过来的内容做预处理,只能做校验。

当我们需要干涉传入的Parameters时,比如填入一些默认值或者做某些计算,则需要使用预处理程序。

如果Parameters设置成功,我们还可以通过成功回调函数来做对应值变更后的逻辑计算。

本文我们将使用demo_nodes_cpp/src/parameters/set_parameters_callback.cpp来讲解这三个功能。

首先我们声明两个Parameters,pararm1和param2。后续我们会对这两个Parameters进行操作。

class SetParametersCallback : public rclcpp::Node
{
public:DEMO_NODES_CPP_PUBLICexplicit SetParametersCallback(const rclcpp::NodeOptions & options): Node("set_param_callback_node", options){// Declare a parameter named "param1" in this node, with default value 1.0:this->declare_parameter("param1", 1.0);// Retrieve the value of 'param1' into a member variable 'value_1_'.value_1_ = this->get_parameter("param1").as_double();// Following statement does the same for 'param2' and 'value_2_', but in a more concise way:value_2_ = this->declare_parameter("param2", 2.0);……private:rclcpp::node_interfaces::PreSetParametersCallbackHandle::SharedPtrpre_set_parameters_callback_handle_;rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtron_set_parameters_callback_handle_;rclcpp::node_interfaces::PostSetParametersCallbackHandle::SharedPtrpost_set_parameters_callback_handle_;double value_1_;double value_2_;
};

预处理

预处理的回调函数的参数是std::vector<rclcpp::Parameter> & parameters。这意味着我们可以对其中的内容做修改、增加、和删除。

如下面的代码,它会在传入参数有param1时,往vector的末尾插入关于param2新值的rclcpp::Parameter(“param2”, 4.0)。这样修改param1时,param2的值也被改动。如果只是修改param2,则不会受到这个逻辑的影响。

    // Define a callback function that will be registered as the 'pre_set_parameters_callback'://   This callback is passed the list of the Parameter objects that are intended to be changed,//   and returns nothing.//   Through this callback it is possible to modify the upcoming changes by changing,//   adding or removing entries of the Parameter list.////   This callback should not change the state of the node (i.e. in this example//   the callback should not change 'value_1_' and 'value_2_').//auto modify_upcoming_parameters_callback =[](std::vector<rclcpp::Parameter> & parameters) {// As an example: whenever "param1" is changed, "param2" is set to 4.0:for (auto & param : parameters) {if (param.get_name() == "param1") {parameters.push_back(rclcpp::Parameter("param2", 4.0));}}};pre_set_parameters_callback_handle_ = this->add_pre_set_parameters_callback(modify_upcoming_parameters_callback);

预处理的回调是使用Node::add_pre_set_parameters_callback来注册的。

校验

校验相关的内容我们在《Robot Operating System——对Parameter设置进行校验》已经有过介绍。此处不再赘述。

只是我们拿它和“预处理”的回调对比下入参,可以发现“校验”的回调入参是std::vector<rclcpp::Parameter> parameters。它是只读的。这就意味着它只能做读取和校验,而不能做其他干涉行为。

    // Define a callback function that will be registered as the 'on_set_parameters_callback'://   The purpose of this callback is to allow the node to inspect the upcoming change//   to the parameters and explicitly approve or reject the change.//   If the change is rejected, no parameters are changed.////   This callback should not change the state of the node (i.e. in this example//   the callback should not change 'value_1_' and 'value_2_').//auto validate_upcoming_parameters_callback =[](std::vector<rclcpp::Parameter> parameters) {rcl_interfaces::msg::SetParametersResult result;result.successful = true;for (const auto & param : parameters) {// As an example: no parameters are changed if a value > 5.0 is specified for 'param1',// or a value < -5.0 for 'param2'.if (param.get_name() == "param1") {if (param.get_value<double>() > 5.0) {result.successful = false;result.reason = "cannot set 'param1' > 5.0";break;}} else if (param.get_name() == "param2") {if (param.get_value<double>() < -5.0) {result.successful = false;result.reason = "cannot set 'param2' < -5.0";break;}}}return result;};on_set_parameters_callback_handle_ = this->add_on_set_parameters_callback(validate_upcoming_parameters_callback);

成功回调

成功回调是指Parameters在Node被设置成功后,ROS2会回调的函数。

如果我们逻辑中有涉及Parameters修改后的行为控制,则可以通过这个回调来进行。

比如这个例子中,当param1和param2被设置成功后,我们会打印出相关的新值。

    // Define a callback function that will be registered as the 'post_set_parameters_callback'://   This callback is passed a list of immutable Parameter objects, and returns nothing.//   The purpose of this callback is to react to changes from parameters//   that have successfully been accepted.////   This callback can change the internal state of the node. E.g.://     - In this example the callback updates the local copies 'value_1_' and 'value_2_',//     - Another example could be to trigger recalculation of a kinematic model due to//       the change of link length parameters,//     - Yet another example could be to emit a signal for an HMI update,//     - Etc.//auto react_to_updated_parameters_callback =[this](const std::vector<rclcpp::Parameter> & parameters) {for (const auto & param : parameters) {if (param.get_name() == "param1") {value_1_ = param.get_value<double>();RCLCPP_INFO(get_logger(), "Member variable 'value_1_' set to: %f.", value_1_);}if (param.get_name() == "param2") {value_2_ = param.get_value<double>();RCLCPP_INFO(get_logger(), "Member variable 'value_2_' set to: %f.", value_2_);}}};post_set_parameters_callback_handle_ = this->add_post_set_parameters_callback(react_to_updated_parameters_callback);

完整代码

// Copyright 2022 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License./*** Example usage: changing 'param1' successfully will result in setting of 'param2'.* ros2 service call /set_param_callback_node/set_parameters rcl_interfaces/srv/SetParameters"{parameters: [{name: "param1", value: {type: 3, double_value: 1.0}}]}"*/#include <string>#include "rclcpp/rclcpp.hpp"
#include "rcl_interfaces/msg/set_parameters_result.hpp"
#include "rclcpp_components/register_node_macro.hpp"#include "demo_nodes_cpp/visibility_control.h"/*** This example node demonstrates the usage of pre_set, on_set* and post_set parameter callbacks*/
namespace demo_nodes_cpp
{
class SetParametersCallback : public rclcpp::Node
{
public:DEMO_NODES_CPP_PUBLICexplicit SetParametersCallback(const rclcpp::NodeOptions & options): Node("set_param_callback_node", options){// Declare a parameter named "param1" in this node, with default value 1.0:this->declare_parameter("param1", 1.0);// Retrieve the value of 'param1' into a member variable 'value_1_'.value_1_ = this->get_parameter("param1").as_double();// Following statement does the same for 'param2' and 'value_2_', but in a more concise way:value_2_ = this->declare_parameter("param2", 2.0);// Define a callback function that will be registered as the 'pre_set_parameters_callback'://   This callback is passed the list of the Parameter objects that are intended to be changed,//   and returns nothing.//   Through this callback it is possible to modify the upcoming changes by changing,//   adding or removing entries of the Parameter list.////   This callback should not change the state of the node (i.e. in this example//   the callback should not change 'value_1_' and 'value_2_').//auto modify_upcoming_parameters_callback =[](std::vector<rclcpp::Parameter> & parameters) {// As an example: whenever "param1" is changed, "param2" is set to 4.0:for (auto & param : parameters) {if (param.get_name() == "param1") {parameters.push_back(rclcpp::Parameter("param2", 4.0));}}};// Define a callback function that will be registered as the 'on_set_parameters_callback'://   The purpose of this callback is to allow the node to inspect the upcoming change//   to the parameters and explicitly approve or reject the change.//   If the change is rejected, no parameters are changed.////   This callback should not change the state of the node (i.e. in this example//   the callback should not change 'value_1_' and 'value_2_').//auto validate_upcoming_parameters_callback =[](std::vector<rclcpp::Parameter> parameters) {rcl_interfaces::msg::SetParametersResult result;result.successful = true;for (const auto & param : parameters) {// As an example: no parameters are changed if a value > 5.0 is specified for 'param1',// or a value < -5.0 for 'param2'.if (param.get_name() == "param1") {if (param.get_value<double>() > 5.0) {result.successful = false;result.reason = "cannot set 'param1' > 5.0";break;}} else if (param.get_name() == "param2") {if (param.get_value<double>() < -5.0) {result.successful = false;result.reason = "cannot set 'param2' < -5.0";break;}}}return result;};// Define a callback function that will be registered as the 'post_set_parameters_callback'://   This callback is passed a list of immutable Parameter objects, and returns nothing.//   The purpose of this callback is to react to changes from parameters//   that have successfully been accepted.////   This callback can change the internal state of the node. E.g.://     - In this example the callback updates the local copies 'value_1_' and 'value_2_',//     - Another example could be to trigger recalculation of a kinematic model due to//       the change of link length parameters,//     - Yet another example could be to emit a signal for an HMI update,//     - Etc.//auto react_to_updated_parameters_callback =[this](const std::vector<rclcpp::Parameter> & parameters) {for (const auto & param : parameters) {if (param.get_name() == "param1") {value_1_ = param.get_value<double>();RCLCPP_INFO(get_logger(), "Member variable 'value_1_' set to: %f.", value_1_);}if (param.get_name() == "param2") {value_2_ = param.get_value<double>();RCLCPP_INFO(get_logger(), "Member variable 'value_2_' set to: %f.", value_2_);}}};// Register the callbacks:// In this example all three callbacks are registered, but this is not mandatory// The handles (i.e. the returned shared pointers) must be kept, as the callback// is only registered as long as the shared pointer is alive.pre_set_parameters_callback_handle_ = this->add_pre_set_parameters_callback(modify_upcoming_parameters_callback);on_set_parameters_callback_handle_ = this->add_on_set_parameters_callback(validate_upcoming_parameters_callback);post_set_parameters_callback_handle_ = this->add_post_set_parameters_callback(react_to_updated_parameters_callback);// Output some info:RCLCPP_INFO(get_logger(), "This node demonstrates the use of parameter callbacks.");RCLCPP_INFO(get_logger(), "As an example, it exhibits the following behavior:");RCLCPP_INFO(get_logger()," * Two parameters of type double are declared in the node: 'param1' and 'param2'");RCLCPP_INFO(get_logger(), " * 'param1' cannot be set to a value > 5.0");RCLCPP_INFO(get_logger(), " * 'param2' cannot be set to a value < -5.0");RCLCPP_INFO(get_logger(), " * Each time 'param1' is set, 'param2' is automatically set to 4.0");RCLCPP_INFO(get_logger()," * Member variables 'value_1_' and 'value_2_' are updated upon change of the parameters.");RCLCPP_INFO(get_logger(), "To try it out set a parameter, e.g.:");RCLCPP_INFO(get_logger(), "  ros2 param set set_param_callback_node param1 10.0");RCLCPP_INFO(get_logger(), "  ros2 param set set_param_callback_node param1 3.0");RCLCPP_INFO(get_logger(), "The first command will fail.");RCLCPP_INFO(get_logger(), "The 2nd command will set 'param1' to 3.0 and 'param2' to 4.0.");}private:rclcpp::node_interfaces::PreSetParametersCallbackHandle::SharedPtrpre_set_parameters_callback_handle_;rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtron_set_parameters_callback_handle_;rclcpp::node_interfaces::PostSetParametersCallbackHandle::SharedPtrpost_set_parameters_callback_handle_;double value_1_;double value_2_;
};}  // namespace demo_nodes_cppRCLCPP_COMPONENTS_REGISTER_NODE(demo_nodes_cpp::SetParametersCallback)

测试

./build/demo_nodes_cpp/set_parameters_callback 

在这里插入图片描述

ros2 param set set_param_callback_node param1 10.0

在这里插入图片描述
下面的命令会要求在一个命令中设置param1和param2。这样我们的回调函数参数中的vector就会收到两个Parameter。虽然vector中已经有param2,而又因为param1的存在,导致param2的新值会被插入到vector的尾部。这样ROS2 在内部会先将param2设置为20.0,然后又设置成预处理函数中的4.0。

ros2 service call /set_param_callback_node/set_parameters_atomically rcl_interfaces/srv/SetParametersAtomically \
"{parameters: [{name: 'param1', value: {type: 3, double_value: 1.0}}, {name: 'param2', value: {type: 3, double_value: 20.0}}]}"

在这里插入图片描述
在这里插入图片描述
下面“成功回调”的打印印证了上述分析
在这里插入图片描述

总结

通过Node::add_pre_set_parameters_callback可以设置Parameters的预处理函数。这个函数可以对Parameters进行增删改操作。
通过Node::add_on_set_parameters_callback可以设置Parameter的校验函数。
通过Node::add_post_set_parameters_callback可以设置Parameters设置成功后的回调函数。

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

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

相关文章

go程序在windows服务中优雅开启和关闭

本篇主要是讲述一个go程序&#xff0c;如何在windows服务中优雅开启和关闭&#xff0c;废话不多说&#xff0c;开搞&#xff01;&#xff01;&#xff01;   使用方式&#xff1a;go程序 net服务启动 Ⅰ 开篇不利 Windows go进程编译后&#xff0c;为一个.exe文件,直接执行即…

[Vulnhub] Raven WordPress+SUDO-Python权限提升+MSQP自动化Mysql权限提升

信息收集 IP AddressOpening Ports192.168.101.159TCP: $ nmap -p- 192.168.101.159 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 6.7p1 Debian 5deb8u4 (protocol 2.0) | ssh-hostkey: | 1024 26:81:c1:f3:5e:01:ef:93:4…

【Java版数据结构】初识泛型

看到这句话的时候证明&#xff1a;此刻你我都在努力 加油陌生人 br />个人主页&#xff1a;Gu Gu Study专栏&#xff1a;Java版数据结构 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者&#xff1…

指针数组模拟二维数组

有任何不懂的问题可以评论区留言&#xff0c;能力范围内都会一一回答 指针数组&#xff0c;是数组&#xff0c;但是它的元素都是指针。 #define _CRT_SECURE_NO_WARNING #include <stdio.h> int main(void) {int a 3;int b 4;int c 5;int* arr[3] { &a,&b,…

STM32的外部中断详解

一、什么是中断&#xff1f; 想象一下你正在家里做饭&#xff0c;突然门铃响了&#xff0c;你听到门铃声后&#xff0c;会暂时放下手中的事情&#xff08;比如炒菜&#xff09;&#xff0c;去开门看看是谁。在这个例子中&#xff0c;门铃声就是一个“中断”&#xff0c;它打断…

【C语言】 二叉树创建(结构体,先序遍历,中序遍历,后续遍历)

二叉树的创建&#xff1a;首先先定义一个结构体&#xff0c;里面包含数据&#xff08;data&#xff09;&#xff0c;指向左子树的指针&#xff08;L&#xff09;&#xff0c;指向右子树的指针&#xff08;R&#xff09;三个部分 在创建树的函数中&#xff0c;首先先输入…

HCIP作业3——MGRE综合实验

一、实验及拓扑 二、实验步骤 1、配置IP R1 [R1]int g0/0/0 [R1-GigabitEthernet0/0/0]ip add 192.168.1.254 24 [R1-GigabitEthernet0/0/0]int s4/0/0 [R1-Serial4/0/0]ip add 15.1.1.1 24 [R1-Serial4/0/0]quitR2 [R2]int g0/0/0 [R2-GigabitEthernet0/0/0]ip add 192.16…

qt国际化

1.pro文件里添加那个…ts. 2.开始-qt-qtxxxfor mingw.然后切换到pro所在的目录。 3.输入lupdate testguojihua.pro,会发现生成一个.ts的文件 4.开始–qt–Linguist,然后打开那个文件。 5.选择文件-发布&#xff0c;就能找到.qm文件了 6.使用这个qm文件

SpringBoot 使用easypoi.excel实现导入解析数据,并结合数据字典实现对数据的校验

在日常开发工作中避免不了的功能需求&#xff1a;导入Excel文件&#xff0c;然而导入文件流操作、对数据的校验有是件麻烦事&#xff0c;自从接触了easypoi后&#xff0c;觉得封装的很好&#xff0c;很简洁。 使用的主要依赖如下&#xff1a; <dependency><groupId&…

Spring -- 使用XML开发MyBatis

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 今天你敲代码了吗 文章目录 MyBatis XML配置文件开发配置连接字符串和MyBatis写Mapper层代码添加mapper接口添加UserInfoXmLMapper.xml 操作数据库INSERTDELETE & UPDATE MyBatis XML配置文件开发 实际上,除…

谷粒商城实战笔记-64-商品服务-API-品牌管理-OSS前后联调测试上传

文章目录 1&#xff0c;拷贝文件到前端工程2&#xff0c;局部修改3&#xff0c;在品牌编辑界面使用上传组件4&#xff0c;OSS配置允许跨域5&#xff0c;测试multiUpload.vue完整代码singleUpload.vue完整代码policy.js代码 在Web应用开发中&#xff0c;文件上传是一项非常常见的…

USB描述符实例和介绍

具体的描述符每个字节的含义可参考USB2.0协议 一个标注的描述符集合 /*********************************/ 设备描述符[18]{0x12, //固定 bLength字段。设备描述符的长度为18(0x12)字节0x01, //固定 bDescriptorType字段。设备描述符的编号为0x010x10,0x01, //bcdUSB字…

uniapp中@click或者@tap多层嵌套的问题解决方法

我们在开发页面的过程中。例如要设计一个九宫格的相册&#xff0c;并且加上删除上传图片和点击图片后预览图片大图的功能例如下图的演示功能。 点击图片后显示大图预览图片&#xff0c;点击x号后要删除掉当前的图片&#xff0c;那么我们设计的时候如果我们代码写成如下的格式 …

【C语言】栈的实现(数据结构)

前言&#xff1a; 还是举一个生活中的例子&#xff0c;大家都玩过积木&#xff0c;当我们把积木叠起来的时候&#xff0c;如果要拿到最底部的积木&#xff0c;我们必须从顶端一个一个打出&#xff0c;最后才能拿到底部的积木&#xff0c;也就是后进先出&#xff08;先进后出&a…

硬件厂家行业进销存系统开发之门票预约,源码解析css样式

采用技术未来之窗web行业应用弹窗对话框artDialog 未来之窗web行业应用弹窗对话框artDialog: 网页弹窗&#xff0c;独立使用单文件版本&#xff0c;可指定位置&#xff0c;左上&#xff0c;左下&#xff0c;中间&#xff0c;右侧&#xff0c;下册&#xff0c;左侧&#xff0c;…

音乐曲谱软件Guitar Pro 8.2 for Mac 中文破解版

Guitar Pro 8.2 for Mac 中文破解版是一款功能强大的音乐曲谱软件&#xff0c;非常适合学习如何玩&#xff0c;改进技巧&#xff0c;重现喜爱的歌曲或陪伴自己。 Guitar Pro for Mac 是一款功能强大的音乐曲谱软件&#xff0c;非常适合学习如何玩&#xff0c;改进技巧&#xf…

做一个能和你互动玩耍的智能机器人之一

2024年被很多人称为AI元年&#xff0c;其实AI元年的叫法由来以久&#xff0c;近年来每一次AI技术的进步&#xff0c;都有很多圈内人大呼AI元年&#xff0c;但不仅一直风声不大&#xff0c;雨点也偏小&#xff0c;都是小范围交流。 得益于软硬件的进步&#xff0c;AI今年开始侵…

深度学习系列70:模型部署torchserve

1. 流程说明 ts文件夹下&#xff0c; 从launcher.py进入&#xff0c;执行jar文件。 入口为model_server.py的start()函数。内容包含&#xff1a; 读取args&#xff0c;创建pid文件 找到java&#xff0c;启动model-server.jar程序&#xff0c;同时读取log-config文件&#xff…

数据库表结构创建

一、原型图 二、分析 1、天气&#xff0c;值字段只有实测值&#xff0c;可用一个字段表示&#xff08;单位、来源同上&#xff09; 2、气温有默认值与实测值两个选项&#xff0c;一个字段无法表示默认值与实测值&#xff08;单位&#xff0c;来源同上&#xff09; 3、因为有…

【Kettle实现神通(数据库)MPP增量、全量数据ETL,同步任务Linux运行(通用)】

1、背景介绍 具体Kettle操作步骤不做过多介绍&#xff0c;主要技术方案说明&#xff0c;Kettle8.2版本放在底部链接提取&#xff0c;本次采用Kettle实现源端&#xff1a;神通数据通用库、目标端&#xff1a;神通MPP增量数据同步&#xff0c;并在服务器端运行Job。 2、windows…