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

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.

   1 #!/usr/bin/env ruby                                                             
   2 require 'ros'
   3 ROS::load_manifest('rb_tutorials')
   4 require 'roscpp_tutorials/TwoInts'

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.

   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

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.

  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

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.

Wiki: rosruby/Tutorials/WritingServiceClient (last edited 2012-06-09 12:14:14 by Takashi Ogura)