监测参数变化 (C++)

目标 学习使用 ParameterEventHandler 类监控和响应参数变化。

辅导水平: 中级

时间 20 分钟

背景介绍

通常情况下,节点需要对自身参数或其他节点参数的变化做出响应。ParameterEventHandler 类可轻松监听参数变化,以便您的代码能对其做出响应。本教程将向您展示如何使用 C++ 版本的 ParameterEventHandler 类来监听节点自身参数的变化以及其他节点参数的变化。

先决条件

在开始本教程之前,您应首先完成以下教程:

任务

在本教程中,您将创建一个包含一些示例代码的新包,编写一些使用 ParameterEventHandler 类的 C++ 代码,并测试生成的代码。

1 创建软件包

首先,打开一个新终端,然后 为您的 ROS 2 安装提供源代码 以便 玫瑰2 命令即可运行。

跟进 本说明 创建一个名为 ros2_ws.

回顾一下,软件包应在 来源 目录,而不是工作区的根目录。因此,导航到 ros2_ws/src 然后在那里创建一个新软件包:

ros2 pkg create --build-type ament_cmake --license Apache-2.0 cpp_parameter_event_handler --ependencies rclcpp

您的终端将返回一条信息,验证是否创建了软件包 cpp_parameter_event_handler 及其所有必要的文件和文件夹。

"(《世界人权宣言》) --依赖 参数会自动在 package.xmlCMakeLists.txt.

1.1 更新 package.xml

因为您使用了 --依赖 选项,就不必在创建软件包时手动将依赖关系添加到 package.xmlCMakeLists.txt.不过,请务必一如既往地将说明、维护者电子邮件和姓名以及许可证信息添加到 package.xml.

<描述>;C++ 规范 活动 客户 教程</description>;
维护者 电子邮件="[email protected]";>;您的 名称维护人员</maintainer>;
许可证Apache-2.0</license>;

2 编写 C++ 节点

内部 ros2_ws/src/cpp_parameter_event_handler/src 目录下,新建一个名为 parameter_event_handler.cpp 并粘贴以下代码:

#include <内存>;

#include "rclcpp/rclcpp.hpp";

 带参数的样本节点 :  rclcpp::节点
{
:
  带参数的样本节点()
  : 节点("node_with_parameters";)
  {
    ->;declare_parameter("an_int_param";, 0);

    // 创建一个参数订阅者,用于监控参数变化
    // (用于此节点参数和其他节点参数)
    参数订阅者 = 标准::共享<;rclcpp::参数事件处理程序>;();

    // 为该节点的整数参数 "an_int_param" 设置回调;
    汽车 cb = []( rclcpp::参数 及样品; p) {
        RCLCPP_INFO(
          ->;get_logger(), "cb:收到参数更新 \";%s\"; 的 %s 类型: \";%ld\";";,
          p.获取名称().c_str(),
          p.get_type_name().c_str(),
          p.as_int());
      };
    cb_handle_ = 参数订阅者->;添加参数回调("an_int_param";, cb);
  }

私人:
  标准::共享_ptr<;rclcpp::参数事件处理程序>; 参数订阅者;
  标准::共享_ptr<;rclcpp::参数回调柄>; cb_handle_;
};

int 主要(int 参数, 烧焦 ** 参数)
{
  rclcpp::启动(参数, 参数);
  rclcpp::后旋(标准::共享<;带参数的样本节点>;());
  rclcpp::关闭();

  返回 0;
}

2.1 检查代码

第一项声明、 #include <内存>; 包含在内,以便代码可以使用 std::make_shared 模板。下一个 #include "rclcpp/rclcpp.hpp"; 允许代码引用 rclcpp 接口提供的各种功能,包括 ParameterEventHandler 类。

在类声明之后,代码定义了一个类、 带参数的样本节点.类的构造函数声明了一个整数参数 参数的默认值为 0。 接下来,代码会创建一个 参数事件处理程序 用于监控参数的变化。最后,代码创建了一个 lambda 函数,并将其设置为每当 参数 已更新。

备注

保存由 添加参数回调否则,将无法正确注册回调。

带参数的样本节点()
: 节点("node_with_parameters";)
{
  ->;declare_parameter("an_int_param";, 0);

  // 创建一个参数订阅者,用于监控参数变化
  // (用于此节点参数和其他节点参数)
  参数订阅者 = 标准::共享<;rclcpp::参数事件处理程序>;();

  // 为该节点的整数参数 "an_int_param" 设置回调;
  汽车 cb = []( rclcpp::参数 及样品; p) {
      RCLCPP_INFO(
        ->;get_logger(), "cb:收到参数更新 \";%s\"; 的 %s 类型: \";%ld\";";,
        p.获取名称().c_str(),
        p.get_type_name().c_str(),
        p.as_int());
    };
  cb_handle_ = 参数订阅者->;添加参数回调("an_int_param";, cb);
}

带参数的样本节点 是一个典型的 主要 函数初始化 ROS,启动样本节点使其可以发送和接收信息,然后在用户在控制台输入 ^C 后关闭。

int 主要(int 参数, 烧焦 ** 参数)
{
  rclcpp::启动(参数, 参数);
  rclcpp::后旋(标准::共享<;带参数的样本节点>;());
  rclcpp::关闭();

  返回 0;
}

2.2 添加可执行文件

要编译这段代码,首先打开 CMakeLists.txt 文件,并在依赖关系下面添加以下代码行 find_package(rclcpp 必填)

add_executable(parameter_event_handler src/parameter_event_handler.cpp)
ament_target_dependencies(parameter_event_handler rclcpp)

install(TARGETS
  参数事件处理程序
  目的地 lib/${PROJECT_NAME}
)

3 构建和运行

运行 rosdep 在工作区的根目录 (ros2_ws) 在构建前检查是否缺少依赖项:

rosdep install -i --from-path src --rosdistro $ROS_DISTRO -y

返回工作区的根目录、 ros2_ws然后创建新软件包:

colcon build --packages-select cpp_parameter_event_handler

打开一个新终端,导航至 ros2_ws并获取设置文件:

install/setup.bash

现在运行节点:

ros2 运行 cpp_parameter_event_handler 参数事件处理程序

节点现在处于活动状态,只有一个参数,每当该参数更新时就会打印一条信息。要测试这一点,请打开另一个终端,像以前一样输入 ROS 设置文件(.install/setup.bash),然后执行以下命令:

ros2 param set node_with_parameters an_int_param 43

运行节点的终端将显示类似下面的信息:

[INFO] [1606950498.422461764] [node_with_parameters]: cb:收到对整数类型参数 "an_int_param" 的更新:"43";

我们之前在节点中设置的回调已被调用,并显示了新的更新值。现在,您可以在终端中使用 ^C 终止正在运行的 parameter_event_handler 示例。

3.1 监控另一节点参数的变化

您还可以使用 ParameterEventHandler 监控另一个节点的参数变化。让我们更新 SampleNodeWithParameters 类,以便同时监控另一个节点中参数的变化。我们将使用 parameter_blackboard 演示应用程序来托管一个双参数,并对其更新进行监控。

首先更新构造函数,在现有代码后添加以下代码:

// 现在,添加一个回调以监控远程节点参数的任何变化。在此
// 情况下,我们提供远程节点名称。
汽车 cb2 = []( rclcpp::参数 及样品; p) {
    RCLCPP_INFO(
      ->;get_logger(), "cb2:收到参数更新 \";%s\"; 的类型:%s: \";%.02lf\";";,
      p.获取名称().c_str(),
      p.get_type_name().c_str(),
      p.as_double());
  };
汽车 远程节点名称 = 标准::字符串("parameter_blackboard";);
汽车 远程参数名 = 标准::字符串("a_double_param";);
cb_handle2_ = 参数订阅者->;添加参数回调(远程参数名, cb2, 远程节点名称);

然后再添加一个成员变量、 cb_handle2 的附加回调句柄:

私人:
  标准::共享_ptr<;rclcpp::参数事件处理程序>; 参数订阅者;
  标准::共享_ptr<;rclcpp::参数回调柄>; cb_handle_;
  标准::共享_ptr<;rclcpp::参数回调柄>; cb_handle2_;  // 添加以下内容
};

在终端中,返回工作区的根目录、 ros2_ws然后像以前一样编译更新的软件包:

colcon build --packages-select cpp_parameter_event_handler

然后获取设置文件:

install/setup.bash

现在,要测试对远程参数的监控,首先运行新建的 parameter_event_handler 代码:

ros2 运行 cpp_parameter_event_handler 参数事件处理程序

接下来,从另一个模板(ROS 已初始化)运行 parameter_blackboard 演示程序,如下所示:

ros2 run demo_nodes_cpp parameter_blackboard

最后,让我们从第三个终端(ROS 已初始化)在 parameter_blackboard 节点上设置一个参数:

ros2 参数设置参数_黑板 a_double_param 3.45

执行该命令后,您应该会在 parameter_event_handler 窗口中看到输出,表明参数更新时调用了回调函数:

[INFO] [1606952588.237531933] [node_with_parameters]: cb2: 收到对参数"a_double_param"的更新,参数类型:double: "3.45";

摘要

您创建了一个带有参数的节点,并使用 ParameterEventHandler 类设置了一个回调,以监控该参数的变化。您还使用了相同的类来监控远程节点的变化。ParameterEventHandler 是一种监控参数变化的便捷方法,这样您就可以对更新值作出响应。