Bird
Raised Fist0
ROSframework~30 mins

Action server implementation in ROS - Mini Project: Build & Apply

Choose your learning style10 modes available
Action server implementation
📖 Scenario: You are building a simple ROS action server that counts numbers up to a goal value. This server will receive a goal number, count up to it step by step, and send feedback during the counting process.
🎯 Goal: Create a ROS action server node that accepts a goal number, counts from 0 up to that number, sends feedback at each step, and finally returns the result when done.
📋 What You'll Learn
Create a ROS node named count_action_server
Define an action server using the actionlib.SimpleActionServer class
Use the Count.action file with goal, feedback, and result fields
Send feedback messages during counting
Send a result message when counting completes
💡 Why This Matters
🌍 Real World
Action servers in ROS are used to perform tasks that take time and provide feedback, such as moving a robot arm or navigating to a location.
💼 Career
Understanding ROS action servers is essential for robotics software engineers working on complex robot behaviors and asynchronous task management.
Progress0 / 4 steps
1
Create the initial ROS node and import necessary modules
Write the first lines of code to import rospy, actionlib, and the CountAction, CountFeedback, and CountResult messages from the your_package.msg module. Then initialize a ROS node called count_action_server.
ROS
Hint

Use import statements for modules and rospy.init_node() to start the node.

2
Create the action server object with a callback function
Define a callback function named execute_cb that takes a goal parameter. Then create an actionlib.SimpleActionServer object called server with the name 'count', the action type CountAction, and the execute callback execute_cb. Start the server with server.start().
ROS
Hint

Define a function with def execute_cb(goal): and create the server with SimpleActionServer.

3
Implement the counting logic with feedback in the callback
Inside the execute_cb function, create feedback and result objects of types CountFeedback and CountResult. Use a for loop from 0 to goal.target inclusive. In each iteration, set feedback.current_number to the loop index, publish feedback with server.publish_feedback(feedback), and sleep for 0.5 seconds. After the loop, set result.final_number to goal.target and call server.set_succeeded(result).
ROS
Hint

Use a for loop and call server.publish_feedback(feedback) inside it. Use server.set_succeeded(result) after the loop.

4
Keep the node running to process action requests
Add rospy.spin() at the end of the script to keep the node alive and processing incoming action goals.
ROS
Hint

Use rospy.spin() to keep the node alive.

Practice

(1/5)
1. What is the main role of an action server in ROS?
easy
A. To handle long-running tasks and provide feedback during execution
B. To send simple messages without feedback
C. To only receive goals without processing them
D. To replace the ROS parameter server

Solution

  1. Step 1: Understand the purpose of an action server

    An action server is designed to manage tasks that take time and can provide updates while working.
  2. Step 2: Compare options with the role

    Only To handle long-running tasks and provide feedback during execution correctly describes handling long tasks and sending feedback, unlike others which describe unrelated roles.
  3. Final Answer:

    To handle long-running tasks and provide feedback during execution -> Option A
  4. Quick Check:

    Action server = long tasks + feedback [OK]
Hint: Remember: action servers manage long tasks with feedback [OK]
Common Mistakes:
  • Confusing action server with simple message publishers
  • Thinking action server only receives goals without processing
  • Mixing action server with parameter server functionality
2. Which of the following is the correct way to define the execute callback function in a ROS action server using Python?
easy
A. def execute(goal, self):
B. def executeCallback(goal):
C. def callback_execute(goal, self):
D. def execute_callback(self, goal):

Solution

  1. Step 1: Recall the standard signature for execute callback

    In ROS Python action servers, the execute callback is a method with 'self' and 'goal' parameters.
  2. Step 2: Match options to this signature

    Only def execute_callback(self, goal): correctly uses 'def execute_callback(self, goal):' matching the expected pattern.
  3. Final Answer:

    def execute_callback(self, goal): -> Option D
  4. Quick Check:

    Method signature = self first, then goal [OK]
Hint: Method callbacks in classes always have self first [OK]
Common Mistakes:
  • Omitting 'self' parameter in method definition
  • Swapping parameter order incorrectly
  • Using camelCase instead of snake_case for method name
3. Given this snippet inside an action server's execute callback:
for i in range(3):
    feedback.percent_complete = (i + 1) * 33
    self._action_server.publish_feedback(feedback)
    rospy.sleep(1)
result.success = True
self._action_server.set_succeeded(result)

What will the client receive?
medium
A. No feedback updates, only success result
B. Three feedback updates at 33%, 66%, and 99%, then success result
C. Only one feedback update at 99%, then success result
D. Feedback updates but the result will be failure

Solution

  1. Step 1: Analyze the loop sending feedback

    The loop runs 3 times, each time publishing feedback with percent_complete increasing by 33.
  2. Step 2: Check the result setting after loop

    After feedback, the result.success is set to True and the goal is marked succeeded.
  3. Final Answer:

    Three feedback updates at 33%, 66%, and 99%, then success result -> Option B
  4. Quick Check:

    Loop feedback + success result = Three feedback updates at 33%, 66%, and 99%, then success result [OK]
Hint: Loop sends multiple feedbacks before final success [OK]
Common Mistakes:
  • Assuming feedback is sent only once after loop
  • Confusing success with failure result
  • Ignoring the sleep delay between feedbacks
4. Identify the error in this action server execute callback snippet:
def execute_callback(self, goal):
    if goal.order < 0:
        self._action_server.set_aborted()
    result = Result()
    result.output = goal.order * 2
    self._action_server.set_succeeded(result)
medium
A. set_aborted() is called without a result argument
B. Result() is not imported or defined
C. The goal attribute 'order' does not exist
D. set_succeeded() should be called before set_aborted()

Solution

  1. Step 1: Check set_aborted() usage

    set_aborted() requires a result argument to inform the client about failure details.
  2. Step 2: Verify other parts

    Result() usage is typical; goal.order is assumed valid; set_succeeded() after set_aborted() is not called sequentially here.
  3. Final Answer:

    set_aborted() is called without a result argument -> Option A
  4. Quick Check:

    set_aborted needs result argument [OK]
Hint: Always pass a result when aborting goals [OK]
Common Mistakes:
  • Calling set_aborted() without result causes runtime error
  • Assuming set_aborted() can be called without parameters
  • Ignoring the need to inform client on abort
5. You want to implement an action server that cancels the goal if a certain condition is met during execution. Which approach correctly handles goal cancellation in the execute callback?
hard
A. Call set_aborted() immediately when the goal is received without checking cancellation
B. Ignore cancellation requests and always call set_succeeded() at the end
C. Check self._action_server.is_preempt_requested() inside the loop, then call self._action_server.set_preempted() and return
D. Use rospy.sleep() to delay cancellation handling until after completion

Solution

  1. Step 1: Understand cancellation handling in action servers

    Cancellation requests are detected by checking is_preempt_requested() during execution.
  2. Step 2: Proper response to cancellation

    When cancellation is requested, call set_preempted() to notify client and stop processing.
  3. Final Answer:

    Check self._action_server.is_preempt_requested() inside the loop, then call self._action_server.set_preempted() and return -> Option C
  4. Quick Check:

    Cancellation check + set_preempted = Check self._action_server.is_preempt_requested() inside the loop, then call self._action_server.set_preempted() and return [OK]
Hint: Use is_preempt_requested() to detect and handle cancellations [OK]
Common Mistakes:
  • Ignoring cancellation requests during execution
  • Calling set_aborted() instead of set_preempted() on cancel
  • Delaying cancellation handling until after task finishes
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard