ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange |
1 | initial version |
Hi,
I recently came across this issue. In ROS 1, services are clearly different from action as they are synchronous. Porting code from ROS 1 to 2 usually requires service calls to keep synchronous, or induces a change in the architecture.
Here is a simple wrapper to handle this:
template <class ServiceT>
class ServiceNodeSync
{
typedef typename ServiceT::Request RequestT;
typedef typename ServiceT::Response ResponseT;
public:
ServiceNodeSync(std::string name): node(std::make_shared<rclcpp::Node>(name))
{ }
void init(std::string service)
{
client = node->create_client<ServiceT>(service);
client->wait_for_service();
}
ResponseT sendRequest(const RequestT &req)
{
return sendRequest(std::make_shared<RequestT>(req));
}
ResponseT sendRequest(const std::shared_ptr<RequestT> &req_ptr)
{
auto result = client->async_send_request(req_ptr);
rclcpp::spin_until_future_complete(node, result);
return *result.get();
}
protected:
rclcpp::Node::SharedPtr node;
typename rclcpp::Client<ServiceT>::SharedPtr client;
};
It can be used as a member variable (say service_node_sync) of your base node Then the synchronous service call boils down to:
auto response = service_node_sync.sendRequest(request);
I guess this can be adapted for particular uses, but for now that is basically how I can teach/introduce ROS 2 services as being more or less the same as in ROS 1.