Building a Fibonacci Sequence with ROS Action Server-Client Node

Building a Fibonacci Sequence with ROS Action Server-Client Node

ยท

3 min read

In this blog post, we will learn how to create a simple ROS action code. We will create an action that generates a Fibonacci sequence and sends it to the action client. Before we dive into this tutorial, it is always recommended that you create a separate package for the ROS action file.

Also Read: ROS Action

Creating the Fibonacci Action Message

First, we need to create a custom action message for our Fibonacci action. Open a terminal and create a new ROS package with the following command:

catkin_create_pkg fibonacci_msgs actionlib_msgs rospy

This creates a new package named fibonacci_msgs that depends on actionlib_msgs and rospy.

Next, create a new folder named action inside the fibonacci_msgs package with the following command:

mkdir -p fibonacci_msgs/action

Inside the action folder, create a new file named Fibonacci.action and paste the following code:

#goal
int32 order
---
#result
int32[] sequence
---
#feedback
int32[] sequence

This code defines the structure of the Fibonacci action messages, which include a goal message, a result message, and a feedback message. The goal message contains the "order" of the Fibonacci sequence to generate, and the result message contains the generated sequence. The feedback message contains the intermediate sequence generated during the Fibonacci computation.

Once you have created the message, you need to build your workspace using the following command in your terminal:

cd ~/catkin_ws
catkin_make

Creating the Fibonacci Action Server Node

Next, we will create the Fibonacci action server node that generates the Fibonacci sequence. We will create a file named fibonacci_server.py in the scripts directory of our ROS package. The fibonacci_server.py file should contain the following code:

#!/usr/bin/env python

import rospy
import actionlib
from my_ros_package.msg import FibonacciAction, FibonacciGoal, FibonacciResult, FibonacciFeedback

class FibonacciServer(object):

  _feedback = FibonacciFeedback()
  _result = FibonacciResult()

  def __init__(self):
    self._as = actionlib.SimpleActionServer("fibonacci", FibonacciAction, self.execute, False)
    self._as.start()

  def execute(self, goal):
    r = rospy.Rate(1)
    success = True

    # Fibonacci sequence generation
    fibonacci_sequence = [0, 1]
    for i in range(1, goal.order):
      if self._as.is_preempt_requested():
        rospy.loginfo('Preempted')
        self._as.set_preempted()
        success = False
        break
      fibonacci_sequence.append(fibonacci_sequence[i] + fibonacci_sequence[i-1])
      self._feedback.sequence = fibonacci_sequence
      self._as.publish_feedback(self._feedback)
      r.sleep()

    if success:
      self._result.sequence = fibonacci_sequence
      rospy.loginfo('Succeeded')
      self._as.set_succeeded(self._result)

if __name__ == '__main__':
  rospy.init_node('fibonacci_server')
  FibonacciServer()
  rospy.spin()

This code creates a FibonacciServer class that implements the Fibonacci action server. The FibonacciServer class creates a SimpleActionServer object that listens to the Fibonacci action topic and calls the execute method when a goal is received. The execute method generates the Fibonacci sequence and sends feedback to the action client. If the execution is successful, it sets the result and marks the goal as successful.

Creating the Fibonacci Action Client Node

Finally, we will create the Fibonacci action client node that sends the goal and receives the result. We will create a file named fibonacci_client.py in the scripts directory of our ROS package. The fibonacci_client.py file should contain the following code:

#!/usr/bin/env python

import rospy
import actionlib
from actionlib_msgs.msg import GoalStatus
from fibonacci_msgs.msg import FibonacciAction, FibonacciGoal

def fibonacci_client(n):
    client = actionlib.SimpleActionClient('fibonacci', FibonacciAction)
    client.wait_for_server()

    goal = FibonacciGoal(order=n)
    client.send_goal(goal)

    while True:
        status = client.get_state()
        if status == GoalStatus.SUCCEEDED:
            return client.get_result().sequence
        elif status in [GoalStatus.PREEMPTED, GoalStatus.REJECTED, GoalStatus.ABORTED]:
            return None
        rospy.sleep(0.1)

if __name__ == '__main__':
    rospy.init_node('fibonacci_client')

    sequence = fibonacci_client(10)
    if sequence is not None:
        print('Fibonacci sequence:', sequence)
    else:
        print('Failed to generate Fibonacci sequence')

This code defines a Fibonacci action client node in Python. It imports the necessary packages, defines the Fibonacci client function which creates an action client for the Fibonacci action, waits for the server to be available, sends a goal to the server, and then waits for the server to complete the goal. Once the goal has been completed, the function returns the generated Fibonacci sequence or none if the goal failed.

In the next blog post, we will discuss accessing the created Fibonacci ROS action code via the ROS action command line tool.

ย