-
Notifications
You must be signed in to change notification settings - Fork 0
Week 5 Action Client
Copy all of the code below into your action_client.py
file. Then, review the explainer below to understand how this all works.
#!/usr/bin/env python3
import rospy
import actionlib
from com2009_msgs.msg import CameraSweepAction, CameraSweepGoal, CameraSweepFeedback
node_name = "camera_sweep_action_client"
action_server_name = "/camera_sweep_action_server"
captured_images = 0
def feedback_callback(feedback_data: CameraSweepFeedback):
global captured_images
captured_images = feedback_data.{BLANK}
print(f"FEEDBACK: Current yaw: {feedback_data.current_angle:.1f} degrees. "
f"Image(s) captured so far: {captured_images}...")
rospy.init_node(node_name)
client = actionlib.SimpleActionClient(action_server_name,
CameraSweepAction)
client.wait_for_server()
goal = CameraSweepGoal()
goal.sweep_angle = 90
goal.image_count = 10
client.send_goal(goal, feedback_cb=feedback_callback)
client.wait_for_result()
print(f"RESULT: Action State = {client.get_state()}")
print(f"RESULT: {captured_images} images saved to {client.get_result()}")
FILL IN THE {BLANK}! Which attribute of the
feedback_data
object tells us how many images have been captured over the course of the Camera Sweep Action? (We discussed this in the "What is a ROS Action?" Section, but you could also runrosmsg info com2009_msgs/CameraSweepFeedback
in a terminal to help you with this).
As you know by now, in order to develop ROS nodes using Python we need to use the rospy
library. If we want to work with ROS Actions, we also need to import actionlib
. We already know the type of messages that we need to use to interact with the /camera_sweep_action_server
, so we import that message type too (from the com2009_msgs
package where that message type is defined). We need to import the full message definition: CameraSweepAction
as well as the Goal
message (which we use to actually make a call to the server). In addition to this, we'll also import the Feedback
portion of the message too, which helps when building the feedback callback function:
import rospy
import actionlib
from com2009_msgs.msg import CameraSweepAction, CameraSweepGoal, CameraSweepFeedback
ROS Actions provide feedback, so we also imported the Feedback
portion of the CameraSweepAction
message into our node in the above as well. We then define a callback function for when we call the server, which will process that feedback data as it is published:
captured_images = 0
def feedback_callback(feedback_data: CameraSweepFeedback):
global captured_images
captured_images = feedback_data.{BLANK}
print(f"FEEDBACK: Current yaw: {feedback_data.current_angle:.1f} degrees. "
f"Image(s) captured so far: {captured_images}...")
Here we are using Python's "Type Annotations" feature:
def feedback_callback(feedback_data: CameraSweepFeedback):
...
Which informs the interpreter that the feedback_data
that is received by the feedback_callback
function will be of the CameraSweepFeedback
type. All this really does is allow autocomplete functionality to work with in our editor (VS Code), whenever we want to pull an attribute from the feedback_data
object. So, moving on...
As is standard practice when we construct ROS nodes, we must initialise them with a node name:
rospy.init_node(node_name)
Where the node_name
variable was assigned earlier on in the code as:
node_name = "camera_sweep_action_client"
Then, we connect to the action server using the actionlib
SimpleActionClient()
method, provide this with the name of the server that we wish to connect to and the type of messages that are used on the server (in this case CameraSweepAction
messages):
client = actionlib.SimpleActionClient(action_server_name,
CameraSweepAction)
Where the action_server_name
variable was also assigned earlier on in the code too:
action_server_name = "/camera_sweep_action_server"
After that, the node simply waits until the action server is activated (if it isn't already):
client.wait_for_server()
Once the server is available, we construct a goal message and send this to the action server, whilst also pointing it to the callback function that we defined earlier, which will be used to process the feedback messages:
goal = CameraSweepGoal()
goal.sweep_angle = 90
goal.image_count = 10
client.send_goal(goal, feedback_cb=feedback_callback)
Then, we simply wait for the action to complete, by using the wait_for_result()
method. Once it has completed, the server provides us with a result, so we simply print that (as well as the current state of the action) to the terminal:
client.wait_for_result()
print(f"RESULT: Action State = {client.get_state()}")
print(f"RESULT: {captured_images} images saved to {client.get_result()}")
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.