Note: This tutorial assumes that you have completed the previous tutorials: examining the simple publisher and subscriber. |
Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags. |
Writing a Simple Service and Client
Description: This tutorial covers how to write a service and client node in ruby.Tutorial Level: BEGINNER
Contents
Writing a Service Node
Here we'll create the service ("add_two_ints_server") node which will receive two ints and return the sum.
Change directory into the rb_tutorials package, you created in the earlier tutorial, Writing a simple pub/sub:
roscd rb_tutorials
Please make sure you have followed the directions in the previous tutorial for creating the service needed in this tutorial, creating the AddTwoInts.srv.
The Code
Create the nodes/add_two_ints_server.rb file within the rb_tutorials package and paste the following inside it:
1 #!/usr/bin/env ruby
2 require 'ros'
3 ROS::load_manifest('rb_tutorials')
4 require 'roscpp_tutorials/TwoInts'
5
6 node = ROS::Node.new('sample_service_server')
7 node.advertise_service('/add_two_ints',
8 Roscpp_tutorials::TwoInts) do |req, res|
9 res.sum = req.a + req.b
10 node.loginfo("a=#{req.a}, b=#{req.b}")
11 node.loginfo(" sum = #{res.sum}")
12 true # return for success
13 end
14 node.spin
Don't forget to make the node executable:
chmod +x nodes/add_two_ints_server.rb
The Code Explained
Now, let's break the code down.
At first you have to require 'ros' and load_manifest as same as Pub/Sub samples. Then require service type, this time roscpp_tutorials/AddTwo.
<
6 node = ROS::Node.new('sample_service_server')
rosruby always needs Node instace. This creates a node that has 'sample_service_server' name.
This declares a new service named add_two_ints with the TwoInts service type. All requests are passed to the following block. The block is called with instances of TwoIntsRequest and TwoIntsResponse. If the service call succeeded, it should return true.
Just like with the subscriber example, node.spin deals callback functions until the service is shutdown.
Writing the Client Node
The Code
Create the nodes/add_two_ints_client.rb file within the rb_tutorials package and paste the following inside it:
1 #!/usr/bin/env ruby
2 require 'ros'
3 ROS::load_manifest('rb_tutorials')
4 require 'roscpp_tutorials/TwoInts'
5
6 if ARGV.length < 2
7 puts "usage: #{$0} X Y"
8 return
9 end
10
11 node = ROS::Node.new('sample_service_client')
12
13 if node.wait_for_service('/add_two_ints', 1)
14 service = node.service('/add_two_ints', Roscpp_tutorials::TwoInts)
15 req = Roscpp_tutorials::TwoIntsRequest.new
16 res = Roscpp_tutorials::TwoIntsResponse.new
17 req.a = ARGV[0].to_i
18 req.b = ARGV[1].to_i
19 if service.call(req, res)
20 p res.sum
21 end
22 end
Don't forget to make the node executable:
chmod +x nodes/add_two_ints_client.rb
The Code Explained
Now, let's break the code down.
13 if node.wait_for_service('/add_two_ints', 1)
This is a convenience method that blocks until the service named add_two_ints is available.
14 service = node.service('/add_two_ints', Roscpp_tutorials::TwoInts)
Next we create a handle for calling the service.
Because we've declared the type of the service to be TwoInts, it does the work of generating the TwoIntsRequest object for you (you're free to pass in your own instead). The return value is an TwoIntsResponse object.