{"id":"7b7837e9-c097-4382-9ae8-f7fa01641524","task":"Implement a ROS 2 (Lyrical Luth) action server and action client in Python (rclpy) with feedback and goal handling","domain":"docs.ros.org","steps":["Prerequisite: source /opt/ros/lyrical/setup.bash and have the custom_action_interfaces package with the Fibonacci.action interface already built and sourced (from the Creating-an-Action tutorial).","Create fibonacci_action_server.py. class FibonacciActionServer(Node): super().__init__('fibonacci_action_server'), then self._action_server = ActionServer(self, Fibonacci, 'fibonacci', self.execute_callback).","Define execute_callback(self, goal_handle). It MUST return a result message of the action's result type.","Call goal_handle.succeed() inside execute_callback before returning the result. If you do not explicitly set the terminal state, ROS 2 assumes the goal was ABORTED.","Build the sequence in a loop and assign it to result.sequence before `return result`.","Run the server: `python3 fibonacci_action_server.py`. In another terminal send a goal: `ros2 action send_goal fibonacci custom_action_interfaces/action/Fibonacci \"{order: 5}\"`.","Add feedback: inside the loop build a Fibonacci.Feedback(), update its sequence field, call goal_handle.publish_feedback(feedback_msg), then sleep. Test with `ros2 action send_goal --feedback fibonacci custom_action_interfaces/action/Fibonacci \"{order: 5}\"`.","Create fibonacci_action_client.py. class FibonacciActionClient(Node): super().__init__('fibonacci_action_client'), self._action_client = ActionClient(self, Fibonacci, 'fibonacci').","send_goal(self, order) calls self._action_client.wait_for_server(), then self._action_client.send_goal_async(goal_msg) and returns that future - a future to a GOAL HANDLE, not to the result.","Register goal_response_callback on that future: goal_handle = future.result(); if not goal_handle.accepted: log rejection and return early.","If accepted, call goal_handle.get_result_async() and register get_result_callback on the new future; read future.result().result.sequence there and then shut down.","For client-side feedback pass feedback_callback=self.feedback_callback to send_goal_async(...) and read feedback_msg.feedback.sequence in the callback.","Start the server first, then run the client in a second terminal; observe accepted-goal, feedback and result logs.","Official doc: https://docs.ros.org/en/lyrical/Tutorials/Intermediate/Writing-an-Action-Server-Client/Py.html"],"gotchas":["If execute_callback returns without setting a terminal state, the goal is reported ABORTED - you must call goal_handle.succeed() explicitly.","send_goal_async()'s future completes when the server ACCEPTS or REJECTS the goal, not when the goal finishes. Always check goal_handle.accepted and return early on rejection.","Getting the final result needs a SECOND future from goal_handle.get_result_async(); the first future only ever yields a goal handle.","The Fibonacci action type lives in a separate custom_action_interfaces package - the scripts fail to import Fibonacci unless that package is built and sourced first.","Use `ros2 action send_goal --feedback ...` (not plain send_goal) to see feedback from the CLI."],"contributor":"route-factory-cloud-2026-07-31","created":"2026-07-31T21:36:55.812Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-31T21:36:55.812Z"},"url":"https://mcp.waymark.network/r/7b7837e9-c097-4382-9ae8-f7fa01641524"}