Ros
30 May 2023

ROS Service Data Type and Definition

ROS Learning Notes

ROS Learning Notes 07

image

Keypoints

  • Define srv file
  • Add package dependency in package.xml
  • Add srv file in CMakeLists.txt
  • Compile the package
  • Test client and server

Define srv file

  • srv file is a file that defines the service data type.
  • srv file is similar to msg file, but it has two parts: request and response.

  • Example: Person.srv
      string name
      uint8 age
      uint8 sex
    
      uint8 unknown = 0
      uint8 male    = 1
      uint8 female  = 2
      --- # three dashes is a separator to separate request(up) and response(down)
      string result
    

Add package dependency in package.xml

  • package.xml defines properties such as package name, version, author, maintainer, dependencies on other packages.
  • Example: add dependency in package.xml
      <build_depend>message_generation</build_depend>
      <exec_depend>message_runtime</exec_depend>
    

Add srv file in CMakeLists.txt

  • CMakelists.txt is the input to the CMake build system for building ROS packages. It describes how to build the code and where to install it.
  • Example: add srv file in CMakeLists.txt
      find_package(catkin REQUIRED COMPONENTS
          roscpp
          rospy
          std_msgs
          message_generation
      )
    
      add_service_files(FILES Person.srv)
      generate_messages(DEPENDENCIES std_msgs)
    
      catkin_package(
          CATKIN_DEPENDS geometry_msgs roscpp rospy turtlesim message_runtime
      )
    

Compile the package

  • Compile the package to generate the service data type.
      catkin_make
    
  • Three file will be generated in devel/include/learning_service:
    • Person.h
    • PersonRequest.h
    • PersonResponse.h

Test client and server

  • Test client:
      #include <ros/ros.h>
      #include "learning_service/Person.h"
    
      int main(int argc, char** argv){
          ros::init(argc, argv, "person_client");
          ros::NodeHandle nh;
    
          // wait for service to start
          ros::service::waitForService("/show_person");
          // create client. Data type is learning_service::Person, service name is /show_person, client name is person_client
          ros::ServiceClient person_client = nh.serviceClient<learning_service::Person>("/show_person");
    
          learning_service::Person srv;
          srv.request.name = "Tom";
          srv.request.age = 18;
          srv.request.sex = learning_service::Person::Request::male;
    
          ROS_INFO("Call service to show person [name:%s, age:%d, sex:%d]", srv.request.name.c_str(), srv.request.age, srv.request.sex);
    
          // call service
          person_client.call(srv);
    
          ROS_INFO("Show person result: %s", srv.response.result.c_str());
      }
    
      #!/usr/bin/env python
      # -*- coding: utf-8 -*-
    
      import rospy
      import sys
      from learning_service.srv import Person, PersonRequest
    
      def person_client():
          rospy.init_node('person_client')
    
          # wait for service to start
          rospy.wait_for_service('/show_person')
          try:
              person_client = rospy.ServiceProxy('/show_person', Person)
              response = person_client("Tom", 20, PersonRequest.male)
              return response.result
          except rospy.ServiceException as e:
              print("Service call failed: %s" % e)
    
      if __name__ == "__main__":
          print("Show person result: %s" % person_client())
    
  • Test server:
      #include <ros/ros.h>
      #include "learning_service/Person.h"
    
      // parameters are request: req, response: res
      bool personCallback(learning_service::Person::Request &req, learning_service::Person::Response &res){
          ROS_INFO("Person: name:%s age:%d sex:%d", req.name.c_str(), req.age, req.sex);
          res.result = "OK";
          return true;
      }
    
      int main(int argc, char** argv){
          ros::init(argc, argv, "person_server");
          ros::NodeHandle nh;
    
          // create server. service name is /show_person, server name is person_server
          ros::ServiceServer person_service = nh.advertiseService("/show_person", personCallback);
    
          ROS_INFO("Ready to show person information.");
          ros::spin();
      }
    
    
      #!/usr/bin/env python
      # -*- coding: utf-8 -*-
    
      import rospy
      from learning_service.srv import Person, PersonResponse
    
      def personCallback(req):
          rospy.loginfo("Person: name:%s age:%d sex:%d", req.name, req.age, req.sex)
          return PersonResponse("OK")
    
      def person_server():
          rospy.init_node('person_server')
          s = rospy.Service('/show_person', Person, personCallback)
          rospy.loginfo("Ready to show person information.")
          rospy.spin()
    
      if __name__ == "__main__":
          person_server()
    
  • Compile:
    add_executable(person_server src/person_server.cpp)
    target_link_libraries(person_server ${catkin_LIBRARIES})
    ## add_dependencies is used to add dependency on other packages. Here is to add dependency for our dynamic head file.
    add_dependencies(person_server ${PROJECT_NAME}_gencpp) 
    
    add_executable(person_client src/person_client.cpp)
    target_link_libraries(person_client ${catkin_LIBRARIES})
    add_dependencies(person_client ${PROJECT_NAME}_gencpp)
    
    catkin_make
    
  • Run:
    roscore
    rosrun learning_service person_server
    rosrun learning_service person_client
    

Tags:
0 comments