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

news2024/9/28 23:34:44

大纲

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

在《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_PUBLIC
  explicit 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::SharedPtr
    pre_set_parameters_callback_handle_;
  rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr
    on_set_parameters_callback_handle_;
  rclcpp::node_interfaces::PostSetParametersCallbackHandle::SharedPtr
    post_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_PUBLIC
  explicit 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::SharedPtr
    pre_set_parameters_callback_handle_;
  rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr
    on_set_parameters_callback_handle_;
  rclcpp::node_interfaces::PostSetParametersCallbackHandle::SharedPtr
    post_set_parameters_callback_handle_;

  double value_1_;
  double value_2_;
};

}  // namespace demo_nodes_cpp

RCLCPP_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.coloradmin.cn/o/1948879.html

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

相关文章

【UbuntuDebian安装Nginx】在线安装Nginx

云计算&#xff1a;腾讯云轻量服务器 操作系统&#xff1a;Ubuntu-v22 1.更新系统软件包列表 打开终端并运行以下命令来确保你的系统软件包列表是最新的&#xff1a; sudo apt update2.安装 Nginx 使用以下命令安装 Nginx&#xff1a; sudo apt install nginx3.启动 Nginx…

基于python的BP神经网络回归模型

1 导入必要的库 import pandas as pd from sklearn.model_selection import train_test_split, cross_val_score, KFold import xgboost as xgb from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score …

电脑如何进行录屏?电脑录屏无压力!

在数字时代&#xff0c;屏幕录制已成为我们日常生活和工作中不可或缺的一部分。无论你是想要制作教程、记录游戏过程&#xff0c;还是捕捉在线会议的精彩瞬间&#xff0c;掌握屏幕录制的方法都显得尤为重要。本文将为你详细介绍电脑如何进行录屏&#xff0c;帮助你轻松捕捉屏幕…

音视频入门基础:H.264专题(17)——FFmpeg源码获取H.264裸流文件信息(视频压缩编码格式、色彩格式、视频分辨率、帧率)的总流程

音视频入门基础&#xff1a;H.264专题系列文章&#xff1a; 音视频入门基础&#xff1a;H.264专题&#xff08;1&#xff09;——H.264官方文档下载 音视频入门基础&#xff1a;H.264专题&#xff08;2&#xff09;——使用FFmpeg命令生成H.264裸流文件 音视频入门基础&…

科技核心 电力方向

【电力投资】电力体制改革***电量投资风险控制研究 【配电网管理】基于***配电网线损数据精细化管理研究 【电价优化】基于***能源系统电价优化模型研究 【电力营销】基于***电力营销业务数据***

用python程序发送文件(python实例二十六)

目录 1.认识Python 2.环境与工具 2.1 python环境 2.2 Visual Studio Code编译 3.文件上传 3.1 代码构思 3.2 服务端代码 3.3 客户端代码 3.4 运行结果 4.总结 1.认识Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具…

SqlSugar删除没有定义主键的实体类对应的数据库表数据

一般而言&#xff0c;使用SqlSugar的DbFirst功能创建数据库表实体类时&#xff0c;如果数据库表有主键&#xff0c;生成的实体类对应属性也会标识为主键&#xff0c;如下图所示。   但有时候生成的实体类没有自动配置主键&#xff0c;这时可以通过以下方式进行删除操作&…

littlefs文件系统的移植和测试

简介 LittleFS 由ARM官方发布&#xff0c;ARM mbedOS的官方推荐文件系统&#xff0c;具有轻量级&#xff0c;掉电安全的特性。主要用在微控制器和flash上 掉电恢复&#xff0c;在写入时即使复位或者掉电也可以恢复到上一个正确的状态。 擦写均衡&#xff0c;有效延长flash的使…

微软蓝屏事件:网络安全的多维挑战与应对策略

一、引言 1. 事件概述&#xff1a;微软蓝屏事件的影响与范围 微软蓝屏事件&#xff0c;这一近期震动全球科技界的重大事件&#xff0c;起因于一次看似平常的软件更新。美国电脑安全技术公司“众击”发布的更新包中隐藏着一个致命的“缺陷”&#xff0c;这个缺陷如同潜伏的病毒…

goland设置Gin框架中tmpl模板的语法提示的方法

goland设置Gin框架中tmpl模板的语法提示的方法 前言 在Gin中&#xff0c;我们要使用 .tmpl 结尾的模板文件&#xff0c;但是我们在new的时候&#xff0c;发现没有对应的文件&#xff0c;所以它就会被当成普通的文件来进行解析&#xff0c;因此也没有提示&#xff0c;这对我们…

MySQL --- 表的操作

在对表进行操作时&#xff0c;需要先选定操作的表所在的数据库&#xff0c;即先执行 use 数据库名; 一、创建表 create table 表名( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎 ; 说明&#xff1a…

个性化音频生成GPT-SoVits部署使用和API调用

一、训练自己的音色模型步骤 1、准备好要训练的数据&#xff0c;放在Data文件夹中&#xff0c;按照文件模板中的结构进行存放数据 2、双击打开go-webui.bat文件&#xff0c;等待页面跳转 3、页面打开后&#xff0c;开始训练自己的模型 &#xff08;1&#xff09;、人声伴奏分…

Mac文件拷贝到移动硬盘怎么做Mac拷贝之后Win电脑里看不到

在日常使用mac电脑的过程中&#xff0c;我们经常需要将一些重要的文件备份到外部硬盘上&#xff0c;以防止数据丢失或电脑故障。传输文件到硬盘可以通过多种方法实现&#xff0c;比如拖拽或者复制至移动硬盘&#xff0c;但有时也会遇到移动硬盘无法粘贴&#xff0c;或拷贝后无法…

FastAPI(七十五)实战开发《在线课程学习系统》接口开发-- 创建课程

源码见&#xff1a;"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 上次我们分享了&#xff0c;FastAPI&#xff08;七十四&#xff09;实战开发《在线课程学习系统》接口开发-- 删除留言 从本篇文章开始&#xff0c;…

DVWA中命令执行漏洞细说

在攻击中&#xff0c;命令注入是比较常见的方式&#xff0c;今天我们细说在软件开发中如何避免命令执行漏洞 我们通过DVWA中不同的安全等级来细说命令执行漏洞 1、先调整DVWA的安全等级为Lower,调整等级在DVWA Security页面调整 2、在Command Injection页面输入127.0.0.1&…

Gitlab以及分支管理

一、概述 Git 是一个分布式版本控制系统&#xff0c;用于跟踪文件的变化&#xff0c;尤其是源代码的变化。它由 Linus Torvalds 于 2005 年开发&#xff0c;旨在帮助管理大型软件项目的开发过程。 二、Git 的功能特性 Git 是关注于文件数据整体的变化&#xff0c;直接会将文件…

视频去水印免费电脑版 pdf压缩在线免费网页版 pdf压缩在线免费 简单工具软件详细方法步骤分享

消除视频中的恼人水印&#xff0c;是许多视频编辑爱好者的常见需求。在这篇文章中&#xff0c;我们将探讨几种视频去水印的技巧&#xff0c;在数字化时代&#xff0c;视频和图片的传播越来越方便&#xff0c;但随之而来的水印问题也让人头疼。本文将为您详细介绍视频剪辑去水印…

CTF-Web习题:[GXYCTF2019]Ping Ping Ping

题目链接&#xff1a;[GXYCTF2019]Ping Ping Ping 解题思路 访问靶机&#xff0c;得到如下页面&#xff0c;类似于URL参数 尝试用HackBar构造url传输过去看看 发现返回了ping命令的执行结果&#xff0c;可以猜测php脚本命令是ping -c 4 $ip&#xff0c;暂时不知道执行的函数…

JavaScript(15)——操作表单元素属性和自定义属性

操作表单元素属性 表单很多情况&#xff0c;也需要修改属性&#xff0c;比如点击眼睛可以看到密码&#xff0c;本质是把表单类型转换为文本框正常的有属性有取值的&#xff0c;跟其他的标签属性没有任何区别 获取&#xff1a;DOM对象.属性名 设置&#xff1a;DOM对象.属性名…

【OpenCV C++20 学习笔记】操作图片

操作图片 概述图片的导入和保存对导入的图片的操作获取像素值Point类型和图片像素 内存管理和引用计数一些简便操作图片可视化更精确的类型转换 概述 在本专栏的第一篇文章中就介绍了一个用OpenCV处理图片的实例&#xff08;《图片处理基础》&#xff09;&#xff0c;这篇文章…