您正在阅读的是旧版本但仍受支持的 ROS 2 文档。 Jazzy.

配置服务自省

目标 为服务客户端和服务器配置服务自省。

辅导水平: 高级

时间 15 分钟

概述

ROS 2 应用程序通常由在远程节点执行特定程序的服务组成。通过服务自省功能可以对服务数据通信进行自省。

在本演示中,我们将重点介绍如何为服务客户端和服务器配置服务自省状态,并使用 玫瑰2 服务 回响.

安装演示版

参见 安装说明 了解安装 ROS 2 的详情。

如果安装了 ROS 2 二进制软件包,请确保有 ros-iron-demo-nodes-cpp 已安装。如果您下载了压缩包或从源代码构建了 ROS 2,那么它已经是安装的一部分了。

自省配置状态

服务自省有 3 种配置状态。

服务自省配置状态

rcl_service_introspection_off

残疾

rcl_service_introspection_metadata

只有元数据,没有任何用户数据内容

rcl_service_introspection_contents

带元数据的用户数据内容

自省演示

该演示展示了如何管理服务自省和监控服务数据通信。 玫瑰2 服务 回响.

IntrospectionServiceNode:

https://github.com/ros2/demos/blob/iron/demo_nodes_cpp/src/services/introspection_service.cpp

命名空间 演示节点
{

 自省服务节点 :  rclcpp::节点
{
:
  demo_nodes_cpp_public
  不含糊 自省服务节点( rclcpp::节点选项 及样品; 选项)
  : 节点("introspection_service";, 选项)
  {
    汽车 handle_add_twoo_ints =
      []( 标准::共享_ptr<;rmw_request_id_t>; 请求标题,
         标准::共享_ptr<;接口示例::服务::添加两个字符::要求>; 要求,
        标准::共享_ptr<;接口示例::服务::添加两个字符::回应>; 回应) ->; 空白
      {
        (空白)请求标题;
        RCLCPP_INFO(
          ->;get_logger(), 接收请求\na: %"; PRId64 " b: %"; PRId64,
          要求->;a, 要求->;b);
        回应->;数额 = 要求->;a + 要求->;b;
      };
    // 创建一个服务,使用回调函数来处理请求。
    srv_ = 创建服务<;接口示例::服务::添加两个字符>;("add_twoo_ints";, handle_add_twoo_ints);

    汽车 参数设置回调 =
      [](标准::病媒<;rclcpp::参数>; 参数) {
        rcl_interfaces::信息::设置参数结果 结果;
        结果.成功的 = ;
        对于 ( rclcpp::参数 及样品; 停止 : 参数) {
          如果 (停止.获取名称() != "service_configure_introspection";) {
            继续;
          }

          如果 (停止.get_type() != rclcpp::参数类型::参数字符串) {
            结果.成功的 = 错误;
            结果.理由 = 必须是字符串";;
            断裂;
          }

          如果 (停止.as_string() != "disabled"; &&; 停止.as_string() != "元数据"; &&;
            停止.as_string() != "内容";)
          {
            结果.成功的 = 错误;
            结果.理由 = "必须是 'disabled'、'metadata'或 'contents'";;
            断裂;
          }
        }

        返回 结果;
      };

    汽车 post_set_parameter_callback =
      []( 标准::病媒<;rclcpp::参数>; 及样品; 参数) {
        对于 ( rclcpp::参数 及样品; 停止 : 参数) {
          如果 (停止.获取名称() != "service_configure_introspection";) {
            继续;
          }

          rcl_service_introspection_state_t 反省状态 = rcl_service_introspection_off;

          如果 (停止.as_string() == "disabled";) {
            反省状态 = rcl_service_introspection_off;
          } 不然 如果 (停止.as_string() == "元数据";) {
            反省状态 = rcl_service_introspection_metadata;
          } 不然 如果 (停止.as_string() == "内容";) {
            反省状态 = rcl_service_introspection_contents;
          }

          ->;srv_->;配置自省(
            ->;获取时钟(), rclcpp::系统默认值QoS(), 反省状态);
          断裂;
        }
      };

    on_set_parameters_callback_handle_ = ->;add_on_set_parameters_callback(
      参数设置回调);
    post_set_parameters_callback_handle_ = ->;add_post_set_parameters_callback(
      post_set_parameter_callback);

    ->;declare_parameter("service_configure_introspection";, "disabled";);
  }

私人:
  rclcpp::服务<;接口示例::服务::添加两个字符>::SharedPtr srv_;
  rclcpp::节点接口::OnSetParametersCallbackHandle::SharedPtr
    on_set_parameters_callback_handle_;
  rclcpp::节点接口::PostSetParametersCallbackHandle::SharedPtr
    post_set_parameters_callback_handle_;
};

}  // 名称空间 demo_nodes_cpp

服务自省默认为禁用,因此用户需要启用它才能调用 配置自省 在服务服务器上。在该演示中 自省服务节点 使用名为 服务配置检查 来配置服务自省状态。

首先,我们需要开始 自省服务节点.

$ 玫瑰2 运行 演示节点 反省服务

要更改服务自省状态,我们需要设置 配置自省 参数如下

### 带元数据的用户数据内容
$ 玫瑰2 停止 设置 /introspection_service 服务配置自检 内容
#### 或者只有元数据
$ 玫瑰2 停止 设置 /introspection_service 服务配置自检 元数据
### 要禁用
$ 玫瑰2 停止 设置 /introspection_service 服务配置自检 

IntrospectionClientNode:

https://github.com/ros2/demos/blob/iron/demo_nodes_cpp/src/services/introspection_client.cpp

命名空间 演示节点
{
 自省客户端节点 :  rclcpp::节点
{
:
  demo_nodes_cpp_public
  不含糊 自省客户端节点( rclcpp::节点选项 及样品; 选项)
  : 节点("introspection_client";, 选项)
  {
    客户_ = 创建客户端<;接口示例::服务::添加两个字符>;("add_twoo_ints";);

    汽车 参数设置回调 =
      [](标准::病媒<;rclcpp::参数>; 参数) {
        rcl_interfaces::信息::设置参数结果 结果;
        结果.成功的 = ;
        对于 ( rclcpp::参数 及样品; 停止 : 参数) {
          如果 (停止.获取名称() != "client_configure_introspection";) {
            继续;
          }

          如果 (停止.get_type() != rclcpp::参数类型::参数字符串) {
            结果.成功的 = 错误;
            结果.理由 = 必须是字符串";;
            断裂;
          }

          如果 (停止.as_string() != "disabled"; &&; 停止.as_string() != "元数据"; &&;
            停止.as_string() != "内容";)
          {
            结果.成功的 = 错误;
            结果.理由 = "必须是 'disabled'、'metadata'或 'contents'";;
            断裂;
          }
        }

        返回 结果;
      };

    汽车 post_set_parameter_callback =
      []( 标准::病媒<;rclcpp::参数>; 及样品; 参数) {
        对于 ( rclcpp::参数 及样品; 停止 : 参数) {
          如果 (停止.获取名称() != "client_configure_introspection";) {
            继续;
          }

          rcl_service_introspection_state_t 反省状态 = rcl_service_introspection_off;

          如果 (停止.as_string() == "disabled";) {
            反省状态 = rcl_service_introspection_off;
          } 不然 如果 (停止.as_string() == "元数据";) {
            反省状态 = rcl_service_introspection_metadata;
          } 不然 如果 (停止.as_string() == "内容";) {
            反省状态 = rcl_service_introspection_contents;
          }

          ->;客户_->;配置自省(
            ->;获取时钟(), rclcpp::系统默认值QoS(), 反省状态);
          断裂;
        }
      };

    on_set_parameters_callback_handle_ = ->;add_on_set_parameters_callback(
      参数设置回调);
    post_set_parameters_callback_handle_ = ->;add_post_set_parameters_callback(
      post_set_parameter_callback);

    ->;declare_parameter("client_configure_introspection";, "disabled";);

    定时器 = ->;创建隔离墙计时器(
      标准::计时器::毫秒数(500),
      []() {
        如果 (!客户_->;服务已就绪()) {
          返回;
        }

        如果 (!正在执行的请求) {
          汽车 要求 = 标准::共享<;接口示例::服务::添加两个字符::要求>;();
          要求->;a = 2;
          要求->;b = 3;
          正在执行的请求 = ;
          客户_->;异步发送请求(
            要求,
            [](rclcpp::客户<;接口示例::服务::添加两个字符>::共享未来 cb_f)
            {
              正在执行的请求 = 错误;
              RCLCPP_INFO(get_logger(), "add_two_ints 的结果: %ld";, cb_f.获取()->;数额);
            }
          );
          返回;
        }
      });
  }

私人:
  rclcpp::客户<;接口示例::服务::添加两个字符>::SharedPtr 客户_;
  rclcpp::定时器基数::SharedPtr 定时器;
  rclcpp::节点接口::OnSetParametersCallbackHandle::SharedPtr
    on_set_parameters_callback_handle_;
  rclcpp::节点接口::PostSetParametersCallbackHandle::SharedPtr
    post_set_parameters_callback_handle_;
  bool 正在执行的请求{错误};
};

}  // 名称空间 demo_nodes_cpp

然后,我们启动并配置 自省客户端节点 以同样的方式。

$ 玫瑰2 运行 演示节点 反省客户端

将服务自省状态更改为设置 配置自省 参数如下

### 带元数据的用户数据内容
$ 玫瑰2 停止 设置 /introspection_client 客户端配置自检 内容
#### 或者只有元数据
$ 玫瑰2 停止 设置 /introspection_client 客户端配置自检 元数据
### 要禁用
$ 玫瑰2 停止 设置 /introspection_client 客户端配置自检 

在本教程中,服务自省状态的输出示例如下 目 录 关于 自省服务节点元数据 关于 自省客户端节点.要监控 自省客户端节点自省服务节点, 让我们运行它:

$ 玫瑰2 服务 回响 --流程式 /add_twoo_ints info:
  事件类型: 请求发送
  盖章:
    sec: 1709432402
    nanosec: 680094264
  client_gid: [1, 15, 0, 18, 86, 208, 115, 86, 0, 0, 0, 0, 0, 0, 21, 3]
  序列号: 247
要求: []
回应: []
--- 信息:
  事件类型: 已收到请求
  盖章:
    sec: 1709432402
    nanosec: 680459568
  client_gid: [1, 15, 0, 18, 86, 208, 115, 86, 0, 0, 0, 0, 0, 0, 20, 4]
  序列号: 247
要求: [{a: 2, b: 3}]
回应: []
--- 信息:
  事件类型: 发送回复
  盖章:
    sec: 1709432402
    nanosec: 680765280
  client_gid: [1, 15, 0, 18, 86, 208, 115, 86, 0, 0, 0, 0, 0, 0, 20, 4]
  序列号: 247
要求: []
回应: [{和: 5}]
--- 信息:
  事件类型: 已收到响应
  盖章:
    sec: 1709432402
    nanosec: 681027998
  client_gid: [1, 15, 0, 18, 86, 208, 115, 86, 0, 0, 0, 0, 0, 0, 21, 3]
  序列号: 247
要求: []
回应: []
--- ...

您可以看到 事件类型: 请求发送事件类型: 已收到响应这些反省服务活动发生在 自省客户端节点.这些事件不包括 要求回应 字段,这是因为 自省客户端节点的服务自省状态设置为 元数据.另一方面、 事件类型: 已收到请求事件类型: 发送回复 事件从 自省服务节点 包括 要求: [{a: 2, b: 3}]回应: {sum: 5}] 作为反省状态设置为 目 录.