ROS与C++入门教程-actionlib-多线程的action客户端
ROS与C++入门教程-actionlib-多线程的action客户端
说明:
- 介绍如何编写多线程action客户端
- 介绍使用simple_action_client创建客户端
- 示例程序发起线程,创建操作客户端,并将goal发送到action服务器。
客户端
- 创建文件,actionlib_tutorials/src/averaging_client.cpp,参考代码
cd ~/catkin_ws/srcactionlib_tutorials/src/
touch averaging_client.cpp
vim averaging_client.cpp
- 代码如下:
#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include <actionlib/client/terminal_state.h>
#include <actionlib_tutorials/AveragingAction.h>
#include <boost/thread.hpp>
void spinThread()
{
ros::spin();
}
int main (int argc, char **argv)
{
ros::init(argc, argv, "test_averaging");
// create the action client
actionlib::SimpleActionClient<actionlib_tutorials::AveragingAction> ac("averaging");
boost::thread spin_thread(&spinThread);
ROS_INFO("Waiting for action server to start.");
ac.waitForServer();
ROS_INFO("Action server started, sending goal.");
// send a goal to the action
actionlib_tutorials::AveragingGoal goal;
goal.samples = 100;
ac.sendGoal(goal);
//wait for the action to return
bool finished_before_timeout = ac.waitForResult(ros::Duration(30.0));
if (finished_before_timeout)
{
actionlib::SimpleClientGoalState state = ac.getState();
ROS_INFO("Action finished: %s",state.toString().c_str());
}
else
ROS_INFO("Action did not finish before the time out.");
// shutdown the node and join the thread back before exiting
ros::shutdown();
spin_thread.join();
//exit
return 0;
}
代码解释:
- 代码:
#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include <actionlib/client/terminal_state.h>
解释:
- actionlib/server/simple_action_client.h是action库用于实现简单的action客户端
- actionlib/client/terminal_state.h定义goal的状态
代码:
#include <actionlib_tutorials/AveragingAction.h>
- 解释:Averaging.action文件自动生成的action消息头文件。
- 代码:
#include <boost/thread.hpp>
解释:
- boost thread库用于启动线程
代码:
void spinThread()
{
ros::spin();
}
解释:这里是一个简单的函数,用于发起线程,稍后将在代码中使用。这个线程将在后台启动ros节点。
代码:
int main (int argc, char **argv)
{
ros::init(argc, argv, "test_averaging");
// create the action client
actionlib::SimpleActionClient<actionlib_tutorials::AveragingAction> ac("averaging");
解释:
- action客户端是模板,指定与action服务器通信的消息类型。
- action客户端构造函数还接受两个参数,即要连接的服务器名称和一个布尔选项,用于自动发起线程。
- 这里,action客户端使用服务器名称和自动选项设置为false来构造,这意味着必须创建线程。
代码:
boost::thread spin_thread(&spinThread);
解释:
- 这里创建线程,并且ros节点在后台开始运行。
- 通过使用此方法,您可以根据需要为action客户端创建多个线程。
代码:
ROS_INFO("Waiting for action server to start.");
ac.waitForServer();
- 解释:由于action服务器可能未启动并运行,因此action客户端将在继续操作之前等待action服务器启动。
- 代码:
ROS_INFO("Action server started, sending goal.");
// send a goal to the action
actionlib_tutorials::AveragingGoal goal;
goal.samples = 100;
ac.sendGoal(goal);
- 解释:这里创建一个目标msg,设置目标值并发送到动作服务器。
- 代码:
//wait for the action to return
bool finished_before_timeout = ac.waitForResult(ros::Duration(30.0));
解释:
- action客户端现在等待目标完成,然后继续。
- 等待的超时设置为30秒,这意味着在30秒后,如果目标没有完成,函数将返回false。
代码:
if (finished_before_timeout)
{
actionlib::SimpleClientGoalState state = ac.getState();
ROS_INFO("Action finished: %s",state.toString().c_str());
}
else
ROS_INFO("Action did not finish before the time out.");
解释:如果目标在超时之前完成,则报告目标状态,否则通知用户目标没有在分配的时间内完成。
代码:
// shutdown the node and join the thread back before exiting
ros::shutdown();
spin_thread.join();
//exit
return 0;
}
- 解释:现在目标已经完成,我们已经报告了目标状态,我们需要关闭ros节点并退出之前加入我们的线程。
编译:
- 更改CMakeLists.txt ,增加:
add_executable(averaging_client src/averaging_client.cpp)
target_link_libraries(averaging_client ${catkin_LIBRARIES})
- 编译:
cd ~/catkin_ws
catkin_make
运行
- 新终端,执行:
$ roscore
- 新终端,客户端:
$ rosrun actionlib_tutorials averaging_client
- 结果:
[ INFO] 1250806286.804217000: Started node [/test_averaging], pid [9414], bound on [aqy], xmlrpc port [35466], tcpros port [55866], logging to [~/ros/ros/log/test_averaging_9414.log], using [real] time
[ INFO] 1250806287.828279000: Waiting for action server to start.
- 新终端,显示话题:
$ rostopic list -v
- 结果:
Published topics:
* /averaging/goal [actionlib_tutorials/AveragingActionGoal] 1 publisher
* /averaging/cancel [actionlib/GoalID] 1 publisher
* /rosout [roslib/Log] 1 publisher
* /rosout_agg [roslib/Log] 1 publisher
Subscribed topics:
* /time [unknown type] 2 subscribers
* /rosout [roslib/Log] 1 subscriber
* /averaging/feedback [unknown type] 1 subscriber
* /averaging/status [unknown type] 1 subscriber
* /averaging/result [unknown type] 1 subscriber
- 图形显示:
$ rosrun rqt_graph rqt_graph &
- 效果:
获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号