ROS1&&ROS2中间件机制——源码级别梳理与总结

Case1

ROS2如下代码,经常出现客户端发送异步请求没有收到回调的情况:

    std::unordered_map<std::string, NodeInf> TaskManager::getAllNodes() {
        if (!get_cur_host_nodes_status_cli_->wait_for_service(std::chrono::duration<double>(1))) {
            MOGO_WARN("cannot call service to get cur host nodes because of [/ssm/query_agent_state] is not available");
            return {};
        }

        get_cur_host_nodes_status_cli_->prune_pending_requests(); // 加上这一行解决问题
        auto request = std::make_shared<autopilot_msgs::srv::BinarySrv::Request>();
        auto response = std::make_shared<autopilot_msgs::srv::BinarySrv::Response>();
        std::vector<uint8_t> bytes(hostname_.begin(), hostname_.end());

	    request->req = bytes;

        bool hasCallBack = false;
	    using ServiceResponseFuture = mogo::Client<autopilot_msgs::srv::BinarySrv>::SharedFuture;
        auto response_received_callback = [this, &hasCallBack](ServiceResponseFuture future) {
            system_master::AgentInf agent_info;
            auto response = future.get();

            common::DeserializeProto(agent_info, response->resp);
            if (response->resp.size() == 1 && response->resp[0] == '0') {
                MOGO_WARN("the request host of req does not exist in the domain host maintained by ssm, the resp returned by ssm is [0]");
                return;
            }

            if (agent_info.agent_state() == system_master::AgentState::DISCONNECT) {
                MOGO_WARN("the node status of the agent may be changing and is unreliable");
                return;
            }

            auto nodes = agent_info.node();
            for (int i = 0; i < nodes.size(); i++) {
                auto node = nodes.Get(i);
                NodeInf node_inf;
                node_inf.node_name_ = node.node_name();
                node_inf.node_state_ = static_cast<NodeState>(node.state());
                nodes_mp_[node_inf.node_name_] = node_inf;
            }

            hasCallBack = true;
        };
        
        auto future_result = get_cur_host_nodes_status_cli_->async_send_request(request, response_received_callback); 
        
        // mogo::spin_until_future_complete(node_handle_.get_node(), future_result) == mogo::FutureReturnCode::SUCCESS) {
        //     MOGO_INFO("Received response: %s", response->data.c_str());
        // } else {
        //     MOGO_ERROR("Failed to get response within the timeout.");
        // }

        int count = 0;
        while (!hasCallBack) {
            usleep(10000);
            count++;
            if (!hasCallBack && count >= 100) {
                MOGO_ERROR("asynchronous callback timeout, the threshold of timeout is 1s, the time slice is 10ms");
                break;
            }
        }

	    return nodes_mp_;
    }

        在 ROS 2 中,prune_pending_requests() 是一个用于清理挂起请求的函数。它是 rclcpp::Client 类的成员函数,用于清理尚未完成的请求,以避免请求队列中的挂起请求堆积。

        在 ROS 2 中,客户端(Client)与服务端(Server)之间进行通信时,客户端可能会向服务端发送请求并等待响应。如果客户端发送的请求在一定时间内没有得到响应,这些请求就会被视为挂起请求。这可能发生在网络延迟、服务端故障或其他原因导致请求无法完成的情况下。

   prune_pending_requests() 函数的作用是清理这些挂起请求,以确保请求队列不会无限增长。当调用这个函数时,它会检查每个挂起请求的状态,并将超时的请求从队列中移除。

以下是一个示例代码,演示了如何使用 prune_pending_requests() 函数:

#include <rclcpp/rclcpp.hpp>

int main(int argc, char** argv) {
  rclcpp::init(argc, argv);
  auto node = std::make_shared<rclcpp::Node>("client_node");

  // 创建客户端
  auto client = node->create_client<example_interfaces::srv::AddTwoInts>("add_two_ints");

  // 发送请求(未得到响应)
  auto request = std::make_shared<example_interfaces::srv::AddTwoInts::Request>();
  request->a = 10;
  request->b = 20;
  auto future_result = client->async_send_request(request);

  // 在发送请求后,等待一段时间
  std::this_thread::sleep_for(std::chrono::seconds(5));

  // 清理挂起的请求
  client->prune_pending_requests();

  // 检查请求是否已完成
  if (future_result.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
    auto response = future_result.get();
    RCLCPP_INFO(node->get_logger(), "Result: %ld", response->sum);
  } else {
    RCLCPP_WARN(node->get_logger(), "Request timed out.");
  }

  rclcpp::shutdown();
  return 0;
}

        在上面的示例中,我们创建了一个客户端,向服务端发送请求,并在请求发送后等待一段时间。然后,我们调用 prune_pending_requests() 函数来清理挂起请求。最后,我们检查请求是否已完成,并根据结果进行相应的处理。

        请注意,prune_pending_requests() 函数需要运行在客户端的上下文中,因此需要在适当的地方调用该函数,例如在等待请求完成之前或之后。

        这个函数对于管理挂起请求队列很有用,可以防止队列无限增长,并确保及时处理请求超时的情况。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值