Skip to content

Week 4 Move Service-Server Python Example

Copy all the code below into your move_server.py file and review the annotations to understand how it all works.

Remember

Don't forget the shebang!

#!/usr/bin/env python3
move_server.py
#!/usr/bin/env python3 

import rospy
from {BLANK}.msg import Twist # (1)!
from tuos_msgs.srv import SetBool, SetBoolResponse # (2)!

service_name = "move_service"

pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1) # (3)!

def callback_function(service_request): # (4)!

    vel = Twist()

    service_response = SetBoolResponse() # (5)!

    if service_request.request_signal == True: # (6)!
        print(f"The '{service_name}' Server received a 'true' request and the robot will now move for 5 seconds...") # (7)!

        StartTime = rospy.get_rostime() # (8)!

        vel.linear.x = 0.1
        pub.publish(vel) # (9)!

        rospy.loginfo('Published the velocity command to /cmd_vel')
        while (rospy.get_rostime().secs - StartTime.secs) < 5: # (10)!
            continue

        rospy.loginfo('5 seconds have elapsed, stopping the robot...')

        vel.linear.x = 0.0
        pub.publish(vel) # (11)!

        service_response.response_signal = True # (12)!
        service_response.response_message = "Request complete."
    else: # (13)!
        service_response.response_signal = False
        service_response.response_message = "Nothing happened, set request_signal to 'true' next time."
    return service_response

rospy.init_node(f"{service_name}_server") # (14)!
my_service = rospy.Service(service_name, SetBool, callback_function) # (15)!
rospy.loginfo(f"the '{service_name}' Server is ready to be called...") # (16)!
rospy.spin() # (17)!
  1. As you should know by now, in order to develop any ROS node in Python we first need to import the rospy library so that we can interact with ROS. We're also going to be issuing velocity commands to the robot, so we need to import the Twist message from the correct message package as well.

  2. We also need to import the Service Message that we want to use for the service that we will set up. This service will use the SetBool service message from a custom tuos_msgs package that we've created for you.

    Here, we import two different things from the tuos_msgs package:

    1. A definition of the full service message: SetBool, which we need to use when we create the service later.
    2. The Response portion of the service message: SetBoolResponse, which we will use to issue a response to the service caller.
  3. Next, we set up a publisher to the /cmd_vel topic, so that we can publish velocity commands to the robot (using Twist messages). Hopefully this part is starting to become familiar to you by now!

  4. Here we define a callback_function. Any code within this function will be executed whenever the service is called.

    The function can take one input argument only, in this case we are calling it service_request. This is where the rospy.Service instance that we set up earlier will put the data that it obtains from a /move_service call, whenever a Request is made.

  5. We create an instance of the Response portion of the SetBool service message, which we will populate with data later on (based on the outcome of the actions that the service server performs).

  6. We then analyse the service Request data (this is the data that is passed to the Server node, whenever a call to the service is made by a caller, or client). We know how to access the data within the service request from using the rossrv info command, which provides us with the following information:

    rossrv info tuos_msgs/SetBool:
    
    bool request_signal
    ---
    bool response_signal
    string response_message
    

    The Request message will therefore contain a boolean value called request_signal, so we can call this value from the input to our callback function (which we called service_request). Using an if statement, we check if this value is True or False, and then define some actions for each situation accordingly...

  7. Print a status message to tell the Service caller that a True value has been received.

  8. Get the current ROS time.

  9. Set a linear velocity for the robot, publish this to the /cmd_vel topic using the publisher that we set up earlier (pub).

  10. Here, we use a while loop to act as a 5-second timer (by keeping an eye on the current ROS time using get_rostime()). Once 5 seconds have elapsed, this while loop will end.

  11. Once the time has elapsed, we publish another velocity command to make the robot stop.

  12. Finally, we can format a service Response using the SetBoolResponse instance that we set up earlier (service_response). Again, we know the names of the attributes in the service response from the rossrv info command:

    rossrv info tuos_msgs/SetBool:
    
    bool request_signal
    ---
    bool response_signal
    string response_message
    
  13. If, the value of the service_request.request_signal was actually found to be False by our if statement earlier, then we do nothing other than send a service response, to indicate that nothing has happened!

  14. This part of the code will execute before anything in the callback function above. First, we initialise our new ROS Node with a name ("move_service_server").

  15. Then, we create a rospy.Service instance where we define:

    1. The name of the service that this node will launch (service_name = "move_service" at the beginning of the code).
    2. The full service message format that the service will use, in this case: SetBool, which we imported earlier.
    3. A callback function, in this case called callback_function, which will define what we want this service Server to do once the service is called.
  16. Send some information to the terminal to indicate that the node has been launched successfully, and that the Service is ready to be called.

  17. The rospy.spin() function keeps our node running indefinitely (so that the callback function can continue to execute, whenever the service is called).

Fill in the Blank!

Which message package does the Twist message belong to?

← Back to Week 4 - Exercise 1