<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki.hshl.de/wiki/index.php?action=history&amp;feed=atom&amp;title=ROS2%3A_Template_to_program_an_Action_Server</id>
	<title>ROS2: Template to program an Action Server - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.hshl.de/wiki/index.php?action=history&amp;feed=atom&amp;title=ROS2%3A_Template_to_program_an_Action_Server"/>
	<link rel="alternate" type="text/html" href="https://wiki.hshl.de/wiki/index.php?title=ROS2:_Template_to_program_an_Action_Server&amp;action=history"/>
	<updated>2026-06-03T23:51:23Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in HSHL Mechatronik</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://wiki.hshl.de/wiki/index.php?title=ROS2:_Template_to_program_an_Action_Server&amp;diff=147549&amp;oldid=prev</id>
		<title>Mirekgoebel am 26. März 2026 um 16:03 Uhr</title>
		<link rel="alternate" type="text/html" href="https://wiki.hshl.de/wiki/index.php?title=ROS2:_Template_to_program_an_Action_Server&amp;diff=147549&amp;oldid=prev"/>
		<updated>2026-03-26T16:03:04Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;de&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Nächstältere Version&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Version vom 26. März 2026, 16:03 Uhr&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l55&quot;&gt;Zeile 55:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Zeile 55:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         # This creates an action endpoint (similar to a service, but asynchronous)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         # This creates an action endpoint (similar to a service, but asynchronous)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         # Parameters:&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         # Parameters:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         # &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  &lt;/del&gt;self              -&amp;gt; current node&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         # &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;1) &lt;/ins&gt;self              -&amp;gt; current node&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         # &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  &lt;/del&gt;Fibonacci         -&amp;gt; action type (Goal, Result, Feedback definition)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         # &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;2) &lt;/ins&gt;Fibonacci         -&amp;gt; action type (Goal, Result, Feedback definition)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         # &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  &lt;/del&gt;&#039;example_action&#039;  -&amp;gt; name of the action topic&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         # &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;3) &lt;/ins&gt;&#039;example_action&#039;  -&amp;gt; name of the action topic&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         #   self.execute_callback -&amp;gt; function that is executed when a goal is received&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         #   self.execute_callback -&amp;gt; function that is executed when a goal is received&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;        # !! 1)-3) must be the same in ActionClient and ActionServer&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         self.action_server = ActionServer(&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         self.action_server = ActionServer(&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;             self,&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;             self,&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key mtrwiki:diff:1.41:old-147548:rev-147549:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>Mirekgoebel</name></author>
	</entry>
	<entry>
		<id>https://wiki.hshl.de/wiki/index.php?title=ROS2:_Template_to_program_an_Action_Server&amp;diff=147548&amp;oldid=prev</id>
		<title>Mirekgoebel: Die Seite wurde neu angelegt: „Kategorie:ROS2  zurück zum Hauptartikel  &lt;source line lang=&quot;python&quot; style=&quot;font-size:small&quot;&gt; #!/usr/bin/env python # this specifies the interpreter of this script  &quot;&quot;&quot; Generic ROS 2 Action Server Example (Python)  This example shows in detail: - How an Action Server is created - How goals are received and processed - How feedback is sent to a client - How another Action Server can be called - How i…“</title>
		<link rel="alternate" type="text/html" href="https://wiki.hshl.de/wiki/index.php?title=ROS2:_Template_to_program_an_Action_Server&amp;diff=147548&amp;oldid=prev"/>
		<updated>2026-03-26T15:59:51Z</updated>

		<summary type="html">&lt;p&gt;Die Seite wurde neu angelegt: „&lt;a href=&quot;/wiki/index.php/Kategorie:ROS2&quot; title=&quot;Kategorie:ROS2&quot;&gt;Kategorie:ROS2&lt;/a&gt;  &lt;a href=&quot;/wiki/index.php/Overview_and_the_most_important_commands_of_ROS2&quot; title=&quot;Overview and the most important commands of ROS2&quot;&gt;zurück zum Hauptartikel&lt;/a&gt;  &amp;lt;source line lang=&amp;quot;python&amp;quot; style=&amp;quot;font-size:small&amp;quot;&amp;gt; #!/usr/bin/env python # this specifies the interpreter of this script  &amp;quot;&amp;quot;&amp;quot; Generic ROS 2 Action Server Example (Python)  This example shows in detail: - How an Action Server is created - How goals are received and processed - How feedback is sent to a client - How another Action Server can be called - How i…“&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;[[Kategorie:ROS2]]&lt;br /&gt;
&lt;br /&gt;
[[Overview_and_the_most_important_commands_of_ROS2|zurück zum Hauptartikel]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source line lang=&amp;quot;python&amp;quot; style=&amp;quot;font-size:small&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python # this specifies the interpreter of this script&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
Generic ROS 2 Action Server Example (Python)&lt;br /&gt;
&lt;br /&gt;
This example shows in detail:&lt;br /&gt;
- How an Action Server is created&lt;br /&gt;
- How goals are received and processed&lt;br /&gt;
- How feedback is sent to a client&lt;br /&gt;
- How another Action Server can be called&lt;br /&gt;
- How internal state (e.g. odometry) can be used&lt;br /&gt;
&lt;br /&gt;
IMPORTANT:&lt;br /&gt;
Replace &amp;quot;Fibonacci&amp;quot; with your own custom action type.&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
&lt;br /&gt;
# --- Standard Python libraries ---&lt;br /&gt;
import time  # Provides basic time functions (e.g., sleep).&lt;br /&gt;
from math import sqrt  # Used for distance calculations.&lt;br /&gt;
&lt;br /&gt;
# --- ROS 2 core libraries ---&lt;br /&gt;
import rclpy  # Main ROS 2 Python client library.&lt;br /&gt;
from rclpy.node import Node  # Base class for all ROS 2 nodes.&lt;br /&gt;
from rclpy.action import ActionServer, ActionClient  # Enables action server/client functionality.&lt;br /&gt;
&lt;br /&gt;
# --- ROS 2 message and action types ---&lt;br /&gt;
from action_msgs.msg import GoalStatus  # Contains action result status constants.&lt;br /&gt;
from nav_msgs.msg import Odometry  # Provides robot position and velocity data.&lt;br /&gt;
from example_interfaces.action import Fibonacci  # Example action definition (replace in real use).&lt;br /&gt;
&lt;br /&gt;
# Main class&lt;br /&gt;
class GenericActionServer(Node):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    A reusable template for a ROS 2 Action Server node.&lt;br /&gt;
&lt;br /&gt;
    This node:&lt;br /&gt;
    - Accepts incoming action goals&lt;br /&gt;
    - Processes them asynchronously&lt;br /&gt;
    - Optionally calls another action server&lt;br /&gt;
    - Publishes feedback during execution&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        # Initialize the ROS 2 node with a unique name&lt;br /&gt;
        super().__init__(&amp;#039;generic_action_server&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
        # --- Action Server (handles incoming goals from clients) ---&lt;br /&gt;
        # This creates an action endpoint (similar to a service, but asynchronous)&lt;br /&gt;
        # Parameters:&lt;br /&gt;
        #   self              -&amp;gt; current node&lt;br /&gt;
        #   Fibonacci         -&amp;gt; action type (Goal, Result, Feedback definition)&lt;br /&gt;
        #   &amp;#039;example_action&amp;#039;  -&amp;gt; name of the action topic&lt;br /&gt;
        #   self.execute_callback -&amp;gt; function that is executed when a goal is received&lt;br /&gt;
        self.action_server = ActionServer(&lt;br /&gt;
            self,&lt;br /&gt;
            Fibonacci,&lt;br /&gt;
            &amp;#039;example_action&amp;#039;,&lt;br /&gt;
            self.execute_callback&lt;br /&gt;
        )&lt;br /&gt;
&lt;br /&gt;
        # --- Action Client (used to call another Action Server) ---&lt;br /&gt;
        # This allows this node to act as a client to another action&lt;br /&gt;
        self.external_action_client = ActionClient(&lt;br /&gt;
            self,&lt;br /&gt;
            Fibonacci,&lt;br /&gt;
            &amp;#039;external_action&amp;#039;&lt;br /&gt;
        )&lt;br /&gt;
&lt;br /&gt;
        # --- Subscriber (example: listen to odometry data) ---&lt;br /&gt;
        # This demonstrates how sensor/state data can be integrated&lt;br /&gt;
        # into your action logic&lt;br /&gt;
        self.create_subscription(&lt;br /&gt;
            Odometry,          # message type&lt;br /&gt;
            &amp;#039;/odom&amp;#039;,           # topic name&lt;br /&gt;
            self.odom_callback,# callback function&lt;br /&gt;
            10                 # queue size&lt;br /&gt;
        )&lt;br /&gt;
&lt;br /&gt;
        # --- Internal state variables ---&lt;br /&gt;
        # Store the current robot position (updated via odometry)&lt;br /&gt;
        self.current_position = None&lt;br /&gt;
&lt;br /&gt;
        # Store the previous position to calculate distance increments&lt;br /&gt;
        self.previous_position = None&lt;br /&gt;
&lt;br /&gt;
        # Accumulated traveled distance&lt;br /&gt;
        self.total_distance = 0.0&lt;br /&gt;
&lt;br /&gt;
        # Store current goal handle (needed to send feedback)&lt;br /&gt;
        self.goal_handle = None&lt;br /&gt;
&lt;br /&gt;
        self.get_logger().info(&amp;quot;Generic Action Server is ready.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # --- Subscriber callback ---&lt;br /&gt;
    def odom_callback(self, msg):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        This function is called every time a new Odometry message arrives.&lt;br /&gt;
&lt;br /&gt;
        Purpose:&lt;br /&gt;
        - Track the robot&amp;#039;s movement&lt;br /&gt;
        - Compute the traveled distance over time&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        # Extract current position from odometry message&lt;br /&gt;
        position = msg.pose.pose.position&lt;br /&gt;
        self.current_position = position&lt;br /&gt;
&lt;br /&gt;
        # If we already have a previous position, compute distance delta&lt;br /&gt;
        if self.previous_position is not None:&lt;br /&gt;
            distance_step = sqrt(&lt;br /&gt;
                (position.x - self.previous_position.x) ** 2 +&lt;br /&gt;
                (position.y - self.previous_position.y) ** 2&lt;br /&gt;
            )&lt;br /&gt;
&lt;br /&gt;
            # Add incremental distance to total distance&lt;br /&gt;
            self.total_distance += distance_step&lt;br /&gt;
&lt;br /&gt;
        # Update previous position for next iteration&lt;br /&gt;
        self.previous_position = position&lt;br /&gt;
&lt;br /&gt;
    # --- Action execution ---&lt;br /&gt;
    async def execute_callback(self, goal_handle):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        This function is automatically called when a client sends a goal.&lt;br /&gt;
&lt;br /&gt;
        Workflow:&lt;br /&gt;
        1. Accept goal&lt;br /&gt;
        2. Initialize/reset state&lt;br /&gt;
        3. Perform the task (optionally calling other systems)&lt;br /&gt;
        4. Return a result&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        self.get_logger().info(&amp;quot;Received new goal&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Store goal handle so we can send feedback later&lt;br /&gt;
        self.goal_handle = goal_handle&lt;br /&gt;
&lt;br /&gt;
        # Reset tracking variables for this new goal&lt;br /&gt;
        self.total_distance = 0.0&lt;br /&gt;
        self.previous_position = None&lt;br /&gt;
&lt;br /&gt;
        # Extract goal parameters from request&lt;br /&gt;
        # (depends on your custom action definition)&lt;br /&gt;
        target_value = goal_handle.request.order&lt;br /&gt;
&lt;br /&gt;
        self.get_logger().info(f&amp;quot;Processing goal: {target_value}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Call another Action Server (optional, example use case)&lt;br /&gt;
        success = await self.call_external_action(target_value)&lt;br /&gt;
&lt;br /&gt;
        # --- Prepare result message ---&lt;br /&gt;
        result = Fibonacci.Result()&lt;br /&gt;
&lt;br /&gt;
        if success:&lt;br /&gt;
            # Mark goal as successfully completed&lt;br /&gt;
            goal_handle.succeed()&lt;br /&gt;
&lt;br /&gt;
            # Fill result message with meaningful data&lt;br /&gt;
            result.sequence = [0, 1, 2]  # Replace with real result&lt;br /&gt;
&lt;br /&gt;
            self.get_logger().info(&amp;quot;Goal succeeded&amp;quot;)&lt;br /&gt;
        else:&lt;br /&gt;
            # Mark goal as failed&lt;br /&gt;
            goal_handle.abort()&lt;br /&gt;
&lt;br /&gt;
            result.sequence = []&lt;br /&gt;
&lt;br /&gt;
            self.get_logger().info(&amp;quot;Goal failed&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Return result to client&lt;br /&gt;
        return result&lt;br /&gt;
&lt;br /&gt;
    # --- Call another Action Server ---&lt;br /&gt;
    async def call_external_action(self, value):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        Sends a goal to another Action Server and waits for the result.&lt;br /&gt;
&lt;br /&gt;
        This demonstrates how to chain actions together.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        # Create goal message for external action&lt;br /&gt;
        goal_msg = Fibonacci.Goal()&lt;br /&gt;
        goal_msg.order = value&lt;br /&gt;
&lt;br /&gt;
        # Wait until the external server is available&lt;br /&gt;
        self.get_logger().info(&amp;quot;Waiting for external server...&amp;quot;)&lt;br /&gt;
        self.external_action_client.wait_for_server()&lt;br /&gt;
&lt;br /&gt;
        # Send goal asynchronously (non-blocking)&lt;br /&gt;
        send_goal_future = self.external_action_client.send_goal_async(goal_msg)&lt;br /&gt;
&lt;br /&gt;
        # Wait until the goal is accepted/rejected&lt;br /&gt;
        goal_handle = await send_goal_future&lt;br /&gt;
&lt;br /&gt;
        if not goal_handle.accepted:&lt;br /&gt;
            self.get_logger().warn(&amp;quot;External goal rejected&amp;quot;)&lt;br /&gt;
            return False&lt;br /&gt;
&lt;br /&gt;
        self.get_logger().info(&amp;quot;External goal accepted&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Start a timer to periodically send feedback to the client&lt;br /&gt;
        self.feedback_timer = self.create_timer(1.0, self.publish_feedback)&lt;br /&gt;
&lt;br /&gt;
        # Wait for the external action result&lt;br /&gt;
        result_future = goal_handle.get_result_async()&lt;br /&gt;
        result = await result_future&lt;br /&gt;
&lt;br /&gt;
        # Stop feedback timer (task finished)&lt;br /&gt;
        self.feedback_timer.cancel()&lt;br /&gt;
&lt;br /&gt;
        # Check result status&lt;br /&gt;
        if result.status == GoalStatus.STATUS_SUCCEEDED:&lt;br /&gt;
            self.get_logger().info(&amp;quot;External action succeeded&amp;quot;)&lt;br /&gt;
            return True&lt;br /&gt;
        else:&lt;br /&gt;
            self.get_logger().warn(f&amp;quot;External action failed: {result.status}&amp;quot;)&lt;br /&gt;
            return False&lt;br /&gt;
&lt;br /&gt;
    # --- Feedback publishing ---&lt;br /&gt;
    def publish_feedback(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        Sends periodic feedback to the Action Client.&lt;br /&gt;
&lt;br /&gt;
        Feedback is useful to:&lt;br /&gt;
        - Show progress&lt;br /&gt;
        - Provide intermediate results&lt;br /&gt;
        - Keep long-running tasks observable&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        # If no active goal exists, do nothing&lt;br /&gt;
        if self.goal_handle is None:&lt;br /&gt;
            return&lt;br /&gt;
&lt;br /&gt;
        # Create feedback message&lt;br /&gt;
        feedback_msg = Fibonacci.Feedback()&lt;br /&gt;
&lt;br /&gt;
        # Fill with example data (replace with meaningful values)&lt;br /&gt;
        feedback_msg.partial_sequence = [1, 2, 3]&lt;br /&gt;
&lt;br /&gt;
        # Publish feedback to client&lt;br /&gt;
        self.goal_handle.publish_feedback(feedback_msg)&lt;br /&gt;
&lt;br /&gt;
        self.get_logger().info(&amp;quot;Feedback sent&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # --- Cleanup ---&lt;br /&gt;
    def destroy_node(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        Called when the node is shutting down.&lt;br /&gt;
        Used for cleanup if needed.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        super().destroy_node()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --- Main entry point ---&lt;br /&gt;
def main(args=None):&lt;br /&gt;
    # Initialize ROS 2 Python client library&lt;br /&gt;
    rclpy.init(args=args)&lt;br /&gt;
&lt;br /&gt;
    # Create node instance&lt;br /&gt;
    node = GenericActionServer()&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        # Keep node alive and processing callbacks&lt;br /&gt;
        rclpy.spin(node)&lt;br /&gt;
    except KeyboardInterrupt:&lt;br /&gt;
        # Graceful shutdown on CTRL+C&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
    # Destroy node explicitly&lt;br /&gt;
    node.destroy_node()&lt;br /&gt;
&lt;br /&gt;
    # Shutdown ROS 2&lt;br /&gt;
    rclpy.shutdown()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;#039;__main__&amp;#039;:&lt;br /&gt;
    main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mirekgoebel</name></author>
	</entry>
</feed>