Ask Your Question
2

How to handle exceptions in the user-defined-callback in service-server and how to inform service-client about the failed-service-call in ros2 rclcpp ?

asked 2020-07-07 01:32:41 -0500

Prabeen gravatar image

I am facing an issue in ros2 rclcpp services. I have a service-server in one machine and service-client in other machine. Now if the service-server callback throws any exception, how service-client will be informed that some issue occurred and the service call failed.

I cannot send a default response and I cannot add any extra field also in the response in my case. Please help me if there is any way to handle it in rclcpp apis and framework .

Earlier I was working on ros1(roscpp) and ros1 service-server-callback returns a bool(we can return true if success and false if fails). In service-client accordingly we can get true/false from call(). If call() returns false, that means service-call failed. How can I do similar things in ros2 rclcpp ?

Please help me on this. Thanks in advance :)

edit retag flag offensive close merge delete

Comments

I'd like to know how to do this too (in Python). Is the best solution to include an is_ok boolean field in the service response?

SmallJoeMan gravatar image SmallJoeMan  ( 2020-12-11 07:05:06 -0500 )edit

@SmallJoeMan I think it is currently the most elegant solution... (Most of ROS2 services use the name success for the boolean field)

afrixs gravatar image afrixs  ( 2022-03-02 09:01:45 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
0

answered 2022-03-02 08:57:20 -0500

afrixs gravatar image

updated 2022-03-08 05:51:28 -0500

Hi, I just faced the same problem and investigated the rclcpp code a bit, it seems like making the service fail is not currently possible (although the docs recommend to throw exceptions but that doesn't work).

The only workaround in your case is to add a timeout on the client side and make the server not return a response. Here is an example of the migration from ROS1:

// ROS 1 style is in comments, ROS 2 follows, uncommented.
// #include "nav_msgs/GetMap.h"
#include "nav_msgs/srv/get_map.hpp"

// bool service_callback(
//   nav_msgs::GetMap::Request & request,
//   nav_msgs::GetMap::Response & response)
void service_callback(
  const std::shared_ptr<rmw_request_id_t> request_header,
  const std::shared_ptr<nav_msgs::srv::GetMap::Request> request)
{
  auto response = std::make_shared<nav_msgs::srv::GetMap::Response>();
  // ...
  if (!has_map_) {
    // return false;
    return;
  }
  // return true;
  map_server_->send_response(*request_header, *response);
}

On the client side you just add a timeout:

auto result = client->async_send_request(request);
// Wait for the result.
if (sync_response_executor->spin_until_future_complete(result, 800ms) != rclcpp::FutureReturnCode::SUCCESS) {
    RCLCPP_ERROR(get_logger(), "Service failed");
    return;
}
edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

Asked: 2020-07-07 01:32:41 -0500

Seen: 245 times

Last updated: Mar 08