-
Notifications
You must be signed in to change notification settings - Fork 0
Week 4 Move Server
Copy all of the code below into your move_server.py file. Then, review the explainer below to understand how this all works.
#!/usr/bin/env python3
import rospy
from {BLANK}.msg import Twist
from com2009_msgs.srv import SetBool, SetBoolResponse
service_name = "move_service"
pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1)
vel = Twist()
def callback_function(service_request):
service_response = SetBoolResponse()
if service_request.request_signal == True:
print(f"The '{service_name}' Server received a 'true' request and the robot will now move for 5 seconds...")
StartTime = rospy.get_rostime()
vel.linear.x = 0.1
pub.publish(vel)
rospy.loginfo('Published the velocity command to /cmd_vel')
while (rospy.get_rostime().secs - StartTime.secs) < 5:
continue
rospy.loginfo('5 seconds have elapsed, stopping the robot...')
vel.linear.x = 0.0
pub.publish(vel)
service_response.response_signal = True
service_response.response_message = "Request complete."
else:
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")
my_service = rospy.Service(service_name, SetBool, callback_function)
rospy.loginfo(f"the '{service_name}' Server is ready to be called...")
rospy.spin()FILL IN THE {BLANK}! Which message package does the
Twistmessage belong to?
Firstly, don't forget the shebang:
#!/usr/bin/env python3As 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.
Then, we also 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 com2009_msgs package that we have created for you:
from com2009_msgs.srv import SetBool, SetBoolResponseHere, we import two different things from the com2009_msgs package:
- A definition of the full service message:
SetBool, which we need to use when we create the service later. - The Response portion of the service message:
SetBoolResponse, which we will use to issue a response to the service caller.
Then, we set up a publisher to the /cmd_vel topic, so that we can publish velocity commands to the robot (using Twist messages). By now you should be familiar with this from the work you have done so far on this course.
pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1)
vel = Twist()Next, we define a callback_function:
def callback_function(service_request):We'll come back to this in more detail in a bit and first jump to the part of the code after the callback_function(), since this next bit will actually execute first:
rospy.init_node(f"{service_name}_server")
my_service = rospy.Service(service_name, SetBool, callback_function)
rospy.loginfo(f"the '{service_name}' Server is ready to be called...")
rospy.spin()Here, we initialise a new ROS Node and call it "move_service_server" (via the service_name = "move_service" variable inside an f-string). Then, we create a rospy.Service instance where we define:
- The name of the service that this node will launch (
service_name = "move_service"at the beginning of the code). - The full service message format that the service will use, in this case:
SetBool, which we imported earlier. - 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.
After this, we send some information to the terminal using rospy.loginfo to indicate that the node has been launched successfully and is ready to be called. Finally, we use the rospy.spin() tool to make sure that our node keeps running indefinitely.
Now let's return to the definition of the callback_function(). This contains the code that will be executed by this node when 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 the /move_service whenever it is called (the service Request). Then, 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).
def callback_function(service_request):
service_response = SetBoolResponse()We then analyse the service Request data, which is passed to this node whenever a call to the service is made. 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 com2009_msgs/SetBool:
bool request_signal
---
bool response_signal
string response_message
The Request message will contain a boolean value called request_signal, so we can call this value by name from the input variable to our callback function, which we called service_request. We will check if this value is True or False using an if statement, and then define some actions for each situation accordingly:
if service_request.request_signal == True:If the service_request.request_signal value is True, then we perform the following actions:
-
Print a status message to tell the Service caller that a
Truevalue has been received:print(f"The '{service_name}' Server received a 'true' request and the robot will now move for 5 seconds...")
-
Get the current ROS time using the
rospy.get_rostime()function:StartTime = rospy.get_rostime()
-
Set a linear velocity for the robot, publish this to the
/cmd_veltopic using the publisher that we set up earlier and then issue another status message to indicate that this has been done:vel.linear.x = 0.1 pub.publish(vel) rospy.loginfo('Published the velocity command to /cmd_vel')
-
Setup a while loop to act as a timer, and wait until 5 seconds has elapsed before doing anything else:
while (rospy.get_rostime().secs - StartTime.secs) < 5: continue
-
Once the time has elapsed, issue another status message to indicate this, then publish another velocity command to make the robot stop:
rospy.loginfo('5 seconds have elapsed, stopping the robot...') vel.linear.x = 0.0 pub.publish(vel)
-
Finally, we can format a service Response using the
SetBoolResponseinstance that we set up earlier (calledservice_response). Again, we know how to access the fields within the service response from therossrv infocommand as shown earlier, and thus we know that our Response should be constructed as follows:service_response.response_signal = True service_response.response_message = "Request complete."
If, however, the value of the
service_request.request_signalwas actually found to beFalseby ourifstatement earlier then we format our service response differently:else: service_response.response_signal = False service_response.response_message = "Nothing happened, set request_signal to 'true' next time."
COM2009/3009 Robotics Lab Course
Updated for the 2021-22 Academic Year
Dr Tom Howard | Multidisciplinary Engineering Education (MEE) | The University of Sheffield
The documentation within this Wiki is licensed under Creative Commons License CC BY-NC:
You are free to distribute, remix, adapt, and build upon this work (for non-commercial purposes only) as long as credit is given to the original author.