< >
Home » ROS与C++入门教程 » ROS与C++入门教程-actionlib-多线程的action客户端

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 &
  • 效果:

请输入图片描述

纠错,疑问,交流: 请进入讨论区点击加入Q群

获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号


标签: ROS与C++入门教程