在一些情况下,阻塞直到一个目标完成不会提供足够的灵活。相反的,基于事件运行或许需要更多场景。在以下例程中,提供如何使用回调来避免调用waitForResult()来阻塞用于目标完成。
/*fibonacci_callback_client.cpp*/
#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;
// Called once when the goal completes
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();
}
// Called once when the goal becomes active
void activeCb()
{
ROS_INFO("Goal just went active");
}
// Called every time feedback is received for the goal
void feedbackCb(const FibonacciFeedbackConstPtr& feedback)
{
ROS_INFO("Got Feedback of length %lu", feedback->sequence.size());
}
int main (int argc, char **argv)
{
ros::init(argc, argv, "test_fibonacci_callback");
// Create the action client
Client ac("fibonacci", true);
ROS_INFO("Waiting for action server to start.");
ac.waitForServer();
ROS_INFO("Action server started, sending goal.");
// Send Goal
FibonacciGoal goal;
goal.order = 20;
ac.sendGoal(goal, &doneCb, &activeCb, &feedbackCb);
ros::spin();
return 0;
}
当尝试注册类方法时,注册目标、活跃和反馈回调的语法并不是很方便。然而,这已经完成了,通过”超级有用但有时很难得到正确的语法” boost::bind
/*fibonacci_class_client.cpp*/
#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;
// Need boost::bind to pass in the 'this' pointer
ac.sendGoal(goal,
boost::bind(&MyNode::doneCb, this, _1, _2),
Client::SimpleActiveCallback(),
Client::SimpleFeedbackCallback());
}
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();
}
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;
}
这个示例的关键所在是调用sendGoal ,该函数使用boost::bind
/*fibonacci_class_client.cpp*/
#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;
// Need boost::bind to pass in the 'this' pointer
ac.sendGoal(goal,
boost::bind(&MyNode::doneCb, this, _1, _2),
Client::SimpleActiveCallback(),
Client::SimpleFeedbackCallback());
}
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();
}
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;
}
我们不注册活跃或反馈回调函数,因此我们可以使用传递null函数指针来代替。我们也可以通过设置两个参数为空来使用,因为默认的回调函数为null。