Sometimes you do not know what type of message a service takes. To find the right type use the ros2 service type command:
ros2servicetype/service_topic
Programming a Service
ROS 2, services enable synchronous communication between nodes. A service consists of a request and response model: one node (client) sends a request, and another node (service server) processes it and returns a response.
Here is the code for making a simple ROS 2 Service
#!/usr/bin/env pythonimportrclpyfromrclpy.nodeimportNodefromexample_interfaces.srvimportAddTwoIntsclassAddTwoIntsServerNode(Node):def__init__(self):super().__init__("add_two_ints_server")self.server_=self.create_service(AddTwoInts,"add_two_ints",self.callback_add_two_ints);self.get_logger().info("Add Two Ints Server has been started.")defcallback_add_two_ints(self,request,response):response.sum=request.a+request.bself.get_logger().info(str(request.a)+" + "+str(request.b)+" = "+str(response.sum))returnresponsedefmain(args=None):rclpy.init(args=args)node=AddTwoIntsServerNode()rclpy.spin(node)rclpy.shutdown()if__name__=='__main__':main()
#include"rclcpp/rclcpp.hpp"#include"example_interfaces/srv/add_two_ints.hpp"usingstd::placeholders::_1;usingstd::placeholders::_2;classAddTwoIntServerNode:publicrclcpp::Node{public:AddTwoIntServerNode():Node("add_two_ints_server"){server_=this->create_service<example_interfaces::srv::AddTwoInts>("add_two_ints",std::bind(&AddTwoIntServerNode::callbackAddTwoInts,this,_1,_2));RCLCPP_INFO(this->get_logger(),"Service server has been started.");}private:voidcallbackAddTwoInts(constexample_interfaces::srv::AddTwoInts::Request::SharedPtrrequest,constexample_interfaces::srv::AddTwoInts::Response::SharedPtrresponse){response->sum=request->a+request->b;RCLCPP_INFO(this->get_logger(),"%d + %d = %d",(int)request->a,(int)request->b,(int)response->sum);}rclcpp::Service<example_interfaces::srv::AddTwoInts>::SharedPtrserver_;};intmain(intargc,char**argv){rclcpp::init(argc,argv);autonode=std::make_shared<AddTwoIntServerNode>();rclcpp::spin(node);rclcpp::shutdown();return0;}
Programming a Client
ROS 2, Clients are nodes or components that initiate the service call, while the service itself is implemented by the server node. This interaction is commonly used for tasks requiring immediate feedback, such as retrieving or setting specific values.
Manual Making A Service Call
Sometime it is handy to make a ROS 2 service call manually. To do this use the ros2 service call command:
#!/usr/bin/env python3importrclpyfromrclpy.nodeimportNodefromexample_interfaces.srvimportAddTwoIntsdefmain(args=None):rclpy.init(args=args)node=Node("add_two_ints_client_no_oop")client=node.create_client(AddTwoInts,"add_two_ints")whilenotclient.wait_for_service(1.0):node.get_logger().warn("Waiting for Server Add Two Ints...")request=AddTwoInts.Request()request.a=3request.b=8future=client.call_async(request)rclpy.spin_until_future_complete(node,future)try:response=future.result()node.get_logger().info(str(request.a)+" + "+str(request.b)+" = "+str(response.sum))exceptExceptionase:node.get_Togger().error("Service call failed %r"%(e,))rclpy.shutdown()if__name__=="__main__":main()
#include"rclcpp/rclcpp.hpp"#include"example_interfaces/srv/add_two_ints.hpp"intmain(intargc,char**argv){rclcpp::init(argc,argv);autonode=std::make_shared<rclcpp::Node>("add_two_ints_client_no_oop");autoclient=node->create_client<example_interfaces::srv::AddTwoInts>("add_two_ints");while(!client->wait_for_service(std::chrono::seconds(1))){RCLCPP_WARN(node->get_logger(),"Waiting for the server to be up");}autorequest=std::make_shared<example_interfaces::srv::AddTwoInts::Request>();request->a=3;request->b=8;autofuture=client->async_send_request(request);if(rclcpp::spin_until_future_complete(node,future)==rclcpp::FutureReturnCode::SUCCESS){RCLCPP_INFO(node->get_logger(),"%d + %d = %d",(int)request->a,(int)request->b,(int)future.get()->sum);}else{RCLCPP_ERROR(node->get_logger(),"Error while calling service");}rclcpp::shutdown();return0;}
With Object Orientated Programming
This program creates a client with object orientated programming.
#include"rclcpp/rclcpp.hpp"#include"example_interfaces/srv/add_two_ints.hpp"classAddTwoIntsClientNode:publicrclcpp::Node{public:AddTwoIntsClientNode():Node("add_two_ints_client"){thread1_=std::thread(std::bind(&AddTwoIntsClientNode::callAddTwoIntsService,this,10,4));}voidcallAddTwoIntsService(inta,intb){autoclient=this->create_client<example_interfaces::srv::AddTwoInts>("add_two_ints");while(!client->wait_for_service(std::chrono::seconds(1))){RCLCPP_WARN(this->get_logger(),"Waiting for the server to be up");}autorequest=std::make_shared<example_interfaces::srv::AddTwoInts::Request>();request->a=a;request->b=b;autofuture=client->async_send_request(request);try{autoresponse=future.get();RCLCPP_INFO(this->get_logger(),"%d + %d = %d",a,b,(int)response->sum);}catch(conststd::exception&e){RCLCPP_ERROR(this->get_logger(),"Service call failed");}}private:std::threadthread1_;};intmain(intargc,char**argv){rclcpp::init(argc,argv);autonode=std::make_shared<AddTwoIntsClientNode>();rclcpp::spin(node);rclcpp::shutdown();return0;}