WHY_Blog

why的小窝

0%

ROS2 服务


是什么?

ROS2平台上的一种 通信机制 ,
组成: 生产端(producer)消费端(consumer)
作用: 消费端(consumer) 提出 请求(request) , 生产端(producer) 返回 回复(response)
特点在于消费端


代码快速开发

代码逻辑

创建生产端对象 -> 创建服务 -> 编写服务回调函数(收到 请求(request) 做什么,返回怎么样的 回复(response))

创建消费端对象 -> 关联服务 -> 编写 请求(request) (根据消息格式定义 请求(request) 内容) -> 编写服务端返回结果回调函数(收到 回复(response),做什么)

代码框架

  1. 生产端(producer)

    1. 创建生产端

      1
      2
      3
      4
      5
      /* srv1.创建生产端服务 */
      srv_producer_temp_ = this->create_service<SrvInterface>(
      "srv_temp",
      std::bind(&SrvProducerTemp::srv_producer_temp_callback, this, std::placeholders::_1, std::placeholders::_2));
      // 指定服务名称,(未知参数),回调函数
    2. 编写服务回调函数

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      /* srv2.服务回调函数 */
      void srv_producer_temp_callback(const std::shared_ptr<SrvInterface::Request> request, const std::shared_ptr<SrvInterface::Response> response)
      {
      /* srv2.1 处理服务端响应 */
      int8_t length = request->test_request_data;
      RCLCPP_INFO(this->get_logger(), "SrvProducerTemp received request with length %d", length);
      /* srv2.2 返回响应结果 */
      response->test_response_data = SrvInterface::Response::SUCCESS; // 调用常量,返回响应结果

      // 数组操作示例/参数调用示例
      if (param_name2_ > 0 && length > param_name2_)
      {
      response->test_response_data = SrvInterface::Response::SUCCESS;

      response->test_array_data.resize(length); // 确保数组有足够的空间
      for (int i = 0; i < param_name2_; i++)
      {
      response->test_array_data[i] = i;
      }
      }
      else
      {
      response->test_response_data = SrvInterface::Response::FAILURE;
      }
      }
    3. *声明和获取参数

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      /* srv3.声明和获取参数*/
      this->declare_parameter("param_name1", 1.0);
      this->declare_parameter("param_name2", 1);

      this->get_parameter("param_name1", param_name1_);
      this->get_parameter("param_name2", param_name2_);

      // 添加参数设置回调
      parameters_callback_handle_ = this->add_on_set_parameters_callback(
      [&](const std::vector<rclcpp::Parameter> &params)
      -> rcl_interfaces::msg::SetParametersResult
      {
      // 遍历参数
      for (auto param : params)
      {
      if (param.get_name() == "param_name1")
      {
      RCLCPP_INFO(this->get_logger(), "更新参数 %s 值为:%f", param.get_name().c_str(), param.as_double());
      param_name1_ = param.as_double();
      }
      else if (param.get_name() == "param_name2")
      {
      RCLCPP_INFO(this->get_logger(), "更新参数 %s 值为:%ld", param.get_name().c_str(), param.as_int());
      param_name2_ = param.as_int();
      }
      }
      auto result = rcl_interfaces::msg::SetParametersResult();
      result.successful = true;
      return result;
      });
  2. 消费端(consumer)代码框架

    1. 创建消费端(consumer)

      1
      2
      srv_consumer_temp_ = this->create_client<SrvInterface>("srv_temp"); // 请求服务的名称

    2. 编写发送请求逻辑

      1. 等待服务端上线

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        /* cli2.1等待服务端上线 */
        while (!srv_consumer_temp_->wait_for_service(1s))
        {
        // 等待时检测rclcpp的状态
        if (!rclcpp::ok())
        {
        RCLCPP_ERROR(this->get_logger(), "等待服务的过程中被打断...");
        return;
        }
        RCLCPP_INFO(this->get_logger(), "等待服务端上线中");
        }
      2. 构造请求

        1
        2
        3
        /* cli2.2构造请求*/
        auto request = std::make_shared<SrvInterface::Request>();
        request->test_request_data = 10;
      3. 发送请求

        1
        2
        3
        /* cli2.3发送异步请求,然后等待返回,返回时调用回调函数*/
        // 回调函数见 SrvConsumerTemp::srv_consumer_temp_callback()
        srv_consumer_temp_->async_send_request(request, std::bind(&SrvConsumerTemp::srv_consumer_temp_callback, this, std::placeholders::_1));
      4. 编写服务端返回结果回调函数

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        /* 服务端返回结果回调函数 */
        void srv_consumer_temp_callback(std::shared_future<typename SrvInterface::Response::SharedPtr> result_future)
        {
        /* cli2.4获取和处理服务端返回的结果 */
        auto response = result_future.get();

        /* cli2.4处理服务端返回的结果 */
        if (response->test_response_data == SrvInterface::Response::SUCCESS)
        {
        RCLCPP_INFO(this->get_logger(), "处理成功");
        }
        else if (response->test_response_data == SrvInterface::Response::FAILURE)
        {
        RCLCPP_INFO(this->get_logger(), "处理失败");
        }
        }
    3. *编写参数修改请求函数(服务请求另一种实现方式)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      /* 参数修改请求函数*/
      void param_modify_request(int new_value)
      {
      /* par1.创建参数修改请求 */
      auto param = rcl_interfaces::msg::Parameter();
      param.name = "param_name2"; // 参数名称

      auto param_value = rcl_interfaces::msg::ParameterValue(); // 参数值对象
      param_value.type = rclcpp::ParameterType::PARAMETER_INTEGER; // 参数类型
      param_value.integer_value = new_value; // 参数值
      param.value = param_value;
      /* par2.发送请求函数 */
      // 见 SrvConsumerTemp::param_modify_request_send()
      auto response = param_modify_request_send(param);
      /* par3.处理返回结果 */
      if (response == nullptr)
      {
      RCLCPP_WARN(this->get_logger(), "参数修改失败");
      return;
      }
      else
      {
      for (auto result : response->results)
      {
      if (result.successful)
      {
      RCLCPP_INFO(this->get_logger(), "参数 已修改为:%d", new_value);
      }
      else
      {
      RCLCPP_WARN(this->get_logger(), "参数 修改失败, 失败原因:%s", result.reason.c_str());
      }
      }
      }
      };

      /* 参数修改请求发送函数 */
      std::shared_ptr<rcl_interfaces::srv::SetParameters::Response> param_modify_request_send(rcl_interfaces::msg::Parameter param)
      {
      /* par2.1创建客户端 */
      auto param_client = this->create_client<rcl_interfaces::srv::SetParameters>(
      "/srv_producer_temp_node/set_parameters");
      /* par2.2等待服务端上线 */
      while (!param_client->wait_for_service(1s))
      {
      // 等待时检测rclcpp的状态
      if (!rclcpp::ok())
      {
      RCLCPP_ERROR(this->get_logger(), "等待服务的过程中被打断...");
      return nullptr;
      }
      RCLCPP_INFO(this->get_logger(), "等待参数修改服务端上线中");
      }
      /* par2.3构造请求 */
      auto request = std::make_shared<rcl_interfaces::srv::SetParameters::Request>();
      request->parameters.push_back(param);
      /* par2.4发送请求 */
      auto response_future = param_client->async_send_request(request);
      /* par2.5等待返回结果 */
      rclcpp::spin_until_future_complete(this->get_node_base_interface(), response_future);
      /* par2.6获取返回结果 */
      auto response = response_future.get();
      return response;
      }

庆祝我的第一篇博文诞生

以此记录我学习、探索机器人学的每一步

让我们开始吧!! ^^_^^

如果你是跳转过来的,那说明那部分尚在开发

markdown语法

文字

==高亮显示==
斜体显示

分割线


加粗显示 不加粗

代码

代码
sudo rm -rf

代码块

1
2
3
## 你好
__加粗显示__
_斜体显示_

其他

引用

嵌套引用

  • 无序列表
  • 111
    • tab缩进进入下一级
  • 下一个
  1. 有序列表
  2. 你好
    1. tab缩进进入下一级

数学公式上下标
2^5^ 上标
53 下标
100/12

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment