Ros Action Client with Feedback using Classes

Hi, i was wondering how to create ros action client with feedback and active Cbs using classes.

I have successfully to create ros action client with feedback and active Callbacks without using classes.
But i want to create the code using classes. There’s tutorial on actionlib wiki ros using boost:bind. But there’s only doneCb on the tutorials. Can you guys help me?

Thanks in advance

on actionlib wiki ros:

  ac.sendGoal(goal,
              boost::bind(&MyNode::doneCb, this, _1, _2),
              Client::SimpleActiveCallback(),
              Client::SimpleFeedbackCallback());
1 Like

Hi, can you give us a little more context on your question? Can you share the code you want to convert to a class structure?

Hi, I have the same question as @xbillynugraha.
I think it’s just about how to append a custom function in the sendgoal call.
In other words, what must Client::SimpleActiveCallback() and Client::SimpleFeedbackCallback() be replaced with?
And how to define which parameters are passed to the activeCb or feedbackCb function?

Here is my minimal example that does not work:

#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include <actionlib_tutorials/FibonacciAction.h>

using namespace actionlib_tutorials;
typedef actionlib::SimpleActionClient<FibonacciAction> Client;

class MyNode
{
public:
  MyNode() : ac("fibonacci", true)
  {
    ROS_INFO("Waiting for action server to start.");
    ac.waitForServer();
    ROS_INFO("Action server started, sending goal.");
  }

  void doStuff(int order)
  {
    FibonacciGoal goal;
    goal.order = order;

    ac.sendGoal(goal,
                boost::bind(&MyNode::doneCb, this, _1, _2),
                boost::bind(&MyNode::activeCb, this, _1, _2),
                boost::bind(&MyNode::feedbackCb, this, _1, _2));
  }

  void doneCb(const actionlib::SimpleClientGoalState& state,
              const FibonacciResultConstPtr& result)
  {
    ROS_INFO("Finished in state [%s]", state.toString().c_str());
    ROS_INFO("Answer: %i", result->sequence.back());
    ros::shutdown();
  }

void activeCb()
{
  ROS_INFO("Goal just went active");
}

void feedbackCb(const FibonacciFeedbackConstPtr& feedback)
{
  ROS_INFO("Got Feedback of length %lu", feedback->sequence.size());
}

private:
  Client ac;
};

int main (int argc, char **argv)
{
  ros::init(argc, argv, "test_fibonacci_class_client");
  MyNode my_node;
  my_node.doStuff(10);
  ros::spin();
  return 0;
}

Hi,
I just figured it out myself. This should work:

#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include <actionlib_tutorials/FibonacciAction.h>

using namespace actionlib_tutorials;
typedef actionlib::SimpleActionClient<FibonacciAction> Client;

class MyNode
{
public:
  MyNode() : ac("fibonacci", true)
  {
    ROS_INFO("Waiting for action server to start.");
    ac.waitForServer();
    ROS_INFO("Action server started, sending goal.");
  }

  void doStuff(int order)
  {
    FibonacciGoal goal;
    goal.order = order;

    ac.sendGoal(goal,
                boost::bind(&MyNode::doneCb, this, _1, _2),
                boost::bind(&MyNode::activeCb, this),
                boost::bind(&MyNode::feedbackCb, this, _1)); 
  }

  void doneCb(const actionlib::SimpleClientGoalState& state,
              const FibonacciResultConstPtr& result)
  {
    ROS_INFO("Finished in state [%s]", state.toString().c_str());
    ROS_INFO("Answer: %i", result->sequence.back());
    ros::shutdown();
  }

void activeCb()
{
  ROS_INFO("Goal just went active");
}

void feedbackCb(const FibonacciFeedbackConstPtr& feedback)
{
  ROS_INFO("Got Feedback of length %lu", feedback->sequence.size());
}

private:
  Client ac;
};

int main (int argc, char **argv)
{
  ros::init(argc, argv, "test_fibonacci_class_client");
  MyNode my_node;
  my_node.doStuff(10);
  ros::spin();
  return 0;
}
1 Like

I am trying to do something similar but in python but no tutorials exist in python. I have the following code and my response is as follows. This shows clearly that it never executed the callback_cb function

#! /usr/bin/env python

import rospy
import actionlib
import turtle2.msg
from turtle2.msg import turtlemvmtAction, turtlemvmtGoal, turtlemvmtResult, turtlemvmtFeedback
import rospy
import sensor_msgs.msg
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
from std_msgs.msg import String

class ActionClient():
def init(self, dist):
self. dist = dist
self.sub = rospy.Subscriber(‘/scan’, LaserScan, self.callback)

def callback(self,msg):
    dist = (msg.ranges[180])
    self.call_server()        
    print (dist)
            
def feedback_cb(self,msg1):
    print (msg1, "sent")


def call_server(self):
    print ("server called")

    client = actionlib.SimpleActionClient('sharedspace', turtlemvmtAction)

    client.wait_for_server()
    
    goal = turtlemvmtGoal()
    
    goal.ranges = self.dist
    
    client.send_goal(goal, feedback_cb = self.feedback_cb)

    client.wait_for_result()

    result = client.get_result()

    return result

if name == ‘main’:
try:
rospy.init_node(‘action_client’)
j = ActionClient(dist=)
print (‘The result is:’,)
rospy.spin()
except rospy.ROSInterruptException as e:
print (‘Something went wrong:’, e)

output:
The result is:
server called
0.9700070023536682

Any thoughs from those previously involved in the post? Any thoughts from previously amazing moderators @_RM @marco.nc.arruda @duckfrost @u1802520 @bayodesegun ?

Hi, what does turtlemvmtGoal() contain? I found this implementation of a callback-based actionlib client in python that might help you…
https://answers.ros.org/question/292061/how-do-i-create-a-callback-based-actionlib-client-in-python/?answer=292069#post-id-292069