actionlib_tutorials - ROS Wiki
一、说明
ROS有许多教程需要系统地拔除,才能最终渡过彼岸;现在需要对actionlib_tutorials下载和实验本教程。
二、工作空间环境
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
git clone https://ghproxy.com/https://github.com/ros/common_tutorials.git
三、生成Action消息
在编写动作之前,定义目标、结果和反馈是非常重要的。操作消息是从 .action 有关操作文件的更多信息,请参考文件自动生成 actionlib 文档。本文件定义了反馈主题的目标、结果和类型和格式。在您喜欢的编辑器中创建 actionlib_tutorials/action/Fibonacci.action,并将以下内容放入其中:
https://raw.githubusercontent.com/ros/common_tutorials/hydro-devel/actionlib_tutorials/action/Fibonacci.action
#goal definition int32 order --- #result definition int32[] sequence --- #feedback int32[] sequence
在制作过程中自动生成消息文件需要 CMakeLists.txt 添加一些内容。
-
像这样将 actionlib_msgs 包添加到 find_package 如果使用宏参数( catkin_create_package 生成 CMakeLists.txt,可以添加):
find_package(catkin REQUIRED COMPONENTS actionlib_msgs)
-
请注意,CMake 需要 find_package actionlib_msgs(message_generation 不需要显式列出,它是由 actionlib_msgs 隐式引用)。
-
使用 add_action_files 宏来声明要生成的操作:
add_action_files( DIRECTORY action FILES Fibonacci.action )
调用 generate_messages 宏,别忘了对 actionlib_msgs 以及其他消息包(如 std_msgs)的依赖:
generate_messages( DEPENDENCIES actionlib_msgs std_msgs # Or other packages containing msgs )
-
将 actionlib_msgs 添加到 catkin_package 宏,如下所示:
catkin_package( CATKIN_DEPENDS actionlib_msgs )
-
catkin_package 还仅将 CATKIN_DEPEND 指定到 actionlib_msgs。对 message_runtime 自动发生传输依赖。
-
注:有时你必须设置你 package.xml,由于我们正在生成信息,您必须在清单文件中声明您在运行时必须生成信息。您可以插入以下行程。
<exec_depend>message_generation</exec_depend>
现在通过以下操作自动生成您的操作文件 msg 并检查结果。
$ cd ../.. # Go back to the top level of your catkin workspace $ catkin_make $ ls devel/share/actionlib_tutorials/msg/ FibonacciActionFeedback.msg FibonacciAction.msg FibonacciFeedback.msg FibonacciResult.msg FibonacciActionGoal.msg FibonacciActionResult.msg FibonacciGoal.msg $ ls devel/include/actionlib_tutorials/ FibonacciActionFeedback.h FibonacciAction.h FibonacciFeedback.h FibonacciResult.h FibonacciActionGoal.h FibonacciActionResult.h FibonacciGoal.h
请使用此文件手动生成消息文件 actionlib_msgs 包中的脚本 genaction.py。
开始写服务器
首先,创建你喜欢的编辑器 actionlib_tutorials/src/fibonacci_server.cpp,并将以下内容放入其中:
#include <ros/ros.h> #include <actionlib/server/simple_action_server.h> #include <actionlib_tutorials/FibonacciAction.h> class FibonacciAction { protected: ros::NodeHandle nh_; actionlib::SimpleActionServer<actionlib_tutorials::FibonacciAction> as_; // NodeHandle instance must be created before this line. Otherwise strange error occurs. std::string action_name_; // create messages that are used to published feedback/result actionlib_tutorials::FibonacciFeedback feedback_; actionlib_tutorials::FibonacciResult result_; public: FibonacciAction(std::string name) : as_(nh_, name, boost::bind(&FibonacciAction::executeCB, this, _1), false), action_name_(name) { as_.start(); } ~FibonacciAction(void) { } void executeCB(const actionlib_tutorials::FibonacciGoalConstPtr &goal) { // helper variables ros::Rate r(1); bool success = true; // push_back the seeds for the fibonacci sequence feedback_.sequence.clear(); feedback_.sequence.push_back(0); feedback_.sequence.push_back(1); // publish info to the console for the user ROS_INFO("%s: Executing, creating fibonacci sequence of order %i with seeds %i, %i", action_name_.c_str(), goal->order, feedback_.sequence[0], feedback_.sequence[1]); // start executing the action for(int i=1; i<=goal->order; i ) { // check that preempt has not been requested by the client if (as_.isPreemptRequested() || !ros::ok()) { ROS_INFO("%s: Preempted", action_name_.c_str()); // set the action state to preempted as_.setPreempted()
success = false;
break;
}
feedback_.sequence.push_back(feedback_.sequence[i] + feedback_.sequence[i-1]);
// publish the feedback
as_.publishFeedback(feedback_);
// this sleep is not necessary, the sequence is computed at 1 Hz for demonstration purposes
r.sleep();
}
if(success)
{
result_.sequence = feedback_.sequence;
ROS_INFO("%s: Succeeded", action_name_.c_str());
// set the action state to succeeded
as_.setSucceeded(result_);
}
}
};
int main(int argc, char** argv)
{
ros::init(argc, argv, "fibonacci");
FibonacciAction fibonacci("fibonacci");
ros::spin();
return 0;
}
六、代码解释
现在,让我们逐段分解代码。
#include <ros/ros.h>
#include <actionlib/server/simple_action_server.h>
actionlib/server/simple_action_server.h 是用于实现简单动作的动作库。
#include <actionlib_tutorials/FibonacciAction.h>
这包括从上面显示的 Fibonacci.action 文件生成的操作消息。这是从 FibonacciAction.msg 文件自动生成的标头。有关消息定义的更多信息,请参阅消息页面。
protected:
ros::NodeHandle nh_;
actionlib::SimpleActionServer<actionlib_tutorials::FibonacciAction> as_; // NodeHandle instance must be created before this line. Otherwise strange error occurs.
std::string action_name_;
// create messages that are used to published feedback/result
actionlib_tutorials::FibonacciFeedback feedback_;
actionlib_tutorials::FibonacciResult result_;
这些是动作类的受保护变量。节点句柄在构造动作期间被构造并传递到动作服务器。动作服务器是在动作的构造函数中构造的,下面已经讨论过了。创建反馈和结果消息以在操作中发布。
FibonacciAction(std::string name) :
as_(nh_, name, boost::bind(&FibonacciAction::executeCB, this, _1), false),
action_name_(name)
{
as_.start();
}
在动作构造函数中,创建了动作服务器。动作服务器接受节点句柄、动作名称和可选的 executeCB 参数。在此示例中,操作服务器是使用 executeCB 的参数创建的。
void executeCB(const actionlib_tutorials::FibonacciGoalConstPtr &goal)
{
现在创建了构造函数中引用的 executeCB 函数。回调函数被传递一个指向目标消息的指针。注意:这是一个 boost 共享指针,通过将“ConstPtr”附加到目标消息类型的末尾来给出。
ros::Rate r(1);
bool success = true;
// push_back the seeds for the fibonacci sequence
feedback_.sequence.clear();
feedback_.sequence.push_back(0);
feedback_.sequence.push_back(1);
// publish info to the console for the user
ROS_INFO("%s: Executing, creating fibonacci sequence of order %i with seeds %i, %i", action_name_.c_str(), goal->order, feedback_.sequence[0], feedback_.sequence[1]);
这里创建了动作的内部。在此示例中,发布 ROS_INFO 以让用户知道该操作正在执行。
// start executing the action
for(int i=1; i<=goal->order; i++)
{
// check that preempt has not been requested by the client
if (as_.isPreemptRequested() || !ros::ok())
{
ROS_INFO("%s: Preempted", action_name_.c_str());
// set the action state to preempted
as_.setPreempted();
success = false;
break;
}
feedback_.sequence.push_back(feedback_.sequence[i] + feedback_.sequence[i-1]);
动作服务器的一个重要组成部分是允许动作客户端请求取消当前目标执行的能力。当客户端请求当前目标被抢占时,动作服务器应该取消目标,执行必要的清理,并调用函数 setPreempted(),这表明该动作已被用户请求抢占。设置动作服务器检查抢占请求的速率由服务器的实现者决定。
// publish the feedback
as_.publishFeedback(feedback_);
// this sleep is not necessary, the sequence is computed at 1 Hz for demonstration purposes
r.sleep();
}
这里将斐波那契数列放入反馈变量中,然后发布到动作服务器提供的反馈通道上。然后动作继续循环和发布反馈。
if(success)
{
result_.sequence = feedback_.sequence;
ROS_INFO("%s: Succeeded", action_name_.c_str());
// set the action state to succeeded
as_.setSucceeded(result_);
}
}
一旦动作完成了斐波那契数列的计算,动作就会通过设置成功通知动作客户端动作完成。
int main(int argc, char** argv)
{
ros::init(argc, argv, "fibonacci");
FibonacciAction fibonacci("fibonacci");
ros::spin();
return 0;
}
最后是 main 函数,创建动作并旋转节点。该操作将运行并等待接收目标。
七、编译
在 CMakeLists.txt文件追加:
add_executable(fibonacci_server src/fibonacci_server.cpp)
target_link_libraries(
fibonacci_server
${catkin_LIBRARIES}
)
add_dependencies(
fibonacci_server
${actionlib_tutorials_EXPORTED_TARGETS}
)
最小的整个 CMakeLists.txt 看起来像这样:
cmake_minimum_required(VERSION 2.8.3)
project(actionlib_tutorials)
find_package(catkin REQUIRED COMPONENTS roscpp actionlib actionlib_msgs)
find_package(Boost REQUIRED COMPONENTS system)
add_action_files(
DIRECTORY action
FILES Fibonacci.action
)
generate_messages(
DEPENDENCIES actionlib_msgs std_msgs
)
catkin_package(
CATKIN_DEPENDS actionlib_msgs
)
include_directories(include ${catkin_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
add_executable(fibonacci_server src/fibonacci_server.cpp)
target_link_libraries(
fibonacci_server
${catkin_LIBRARIES}
)
add_dependencies(
fibonacci_server
${actionlib_tutorials_EXPORTED_TARGETS}
)
八、运行服务器
在新终端中启动 roscore
$ roscore
然后运行动作服务器:
$ rosrun actionlib_tutorials fibonacci_server
您将看到类似于以下内容的内容:
-
[ INFO] 1250790662.410962000: Started node [/fibonacci], pid [29267], bound on [aqy], xmlrpc port [39746], tcpros port [49573], logging to [~/ros/ros/log/fibonacci_29267.log], using [real] time
要检查您的操作是否正常运行,请列出正在发布的主题:
$ rostopic list -v
您将看到类似于以下内容的内容:
-
Published topics: * /fibonacci/feedback [actionlib_tutorials/FibonacciActionFeedback] 1 publisher * /fibonacci/status [actionlib_msgs/GoalStatusArray] 1 publisher * /rosout [rosgraph_msgs/Log] 1 publisher * /fibonacci/result [actionlib_tutorials/FibonacciActionResult] 1 publisher * /rosout_agg [rosgraph_msgs/Log] 1 publisher Subscribed topics: * /fibonacci/goal [actionlib_tutorials/FibonacciActionGoal] 1 subscriber * /fibonacci/cancel [actionlib_msgs/GoalID] 1 subscriber * /rosout [rosgraph_msgs/Log] 1 subscriber
或者,您可以查看节点:
$ rqt_graph
这表明您的操作服务器正在按预期发布反馈、状态和结果通道,并按预期订阅目标和取消通道。操作服务器已启动并正常运行。
将目标发送到操作服务器 对于使用操作的下一步,您需要 Ctrl-C 操作服务器并编写一个简单的操作客户端。
请看【ROS知识:action_tutorials[2] 实现Action Client】