ros入门(六)actionlib学习笔记

大G霸 大G霸     2022-10-14     527

关键词:

在读move_base的代码的时候,遇到了actionlib,于是记录下学习笔记。

首先说,actionlib是一个完善service的功能包,当一个功能需要执行一段时间,但是你需要实时察看执行的状态和阶段的时候,service就无法满足了。

于是出现了actionlib。而actionlib中主要是由一个server和一个client的部分。

两个关系这样子的。

 

Actionlib 源码:

http://docs.ros.org/api/actionlib/html/namespaceactionlib.html

 

Actionlib的server和client部分符合这样的状态转移图。

Serve的状态转移图是这样的,

 

Server的方法记录如下:

http://docs.ros.org/api/actionlib/html/classactionlib_1_1simple__action__server_1_1SimpleActionServer.html

这里各种状态代表的不同的意思:

服务端状态
中间状态

(前面说了,simple的状态有三个,就是等待执行挂起)

  • Pending - goal还没有被ActionServer处理

  • Active - goal正在被AS处理

  • Recalling - goal没有被处理并且从客户端已发送取消它的命令,但AS还不确定goal已经被取消了(时差导致的?)

  • Preempting - goal正被处理呢,从AC端收到了取消请求,但AS还不确定goal已经被取消了

终点状态
  • Rejected - AC没有发cancle请求,goal被AS不处理直接拒绝了The goal was rejected by the action server without being processed and without a request from the action client to cancel
  • Succeeded - goal被AS成功实现 was achieved successfully by the action server
  • Aborted - goal被AS终止没有AC的cancle请求
  • Recalled - 在AS开始执行之前这个goal被另一个goal或者cancle请求取消了
  • Preempted - 处理中的goal被另一个goal或者AC的取消请求给取消了

 

 

 

而Client的状态转移图是这样的,

 

而client的所有方法记录在:

http://docs.ros.org/api/actionlib/html/classactionlib_1_1SimpleActionClient.html#ae6a2e6904495e7c20c59e96af0d86801

 

下面我们就写一个最简单的Actionlib的server和client,这里我们使用的是采用Goal返回函数。

首先我们还原官方例程使用的一个例子,洗盘子。而我们这个时候需要首先在包目录下加入action文件夹。在./action/DoDished.action文件中定义。

#goal definition
int32 samples
---
#result definition
float32 mean
float32 std_dev
---
#feedback
int32 sample
float32 data
float32 mean
float32 std_dev

   下面在catkin_ws/src目录下创建一个测试package:

catkin_create_pkg actionlib_bing roscpp std_msgs actionlib actionlib_msgs message_generation rospy

  在package的CMakeLists.txt文件中加入下面这几行:

#find_package(catkin REQUIRED genmsg actionlib_msgs actionlib)
add_action_files(DIRECTORY action FILES DoDishes.action)
generate_messages(DEPENDENCIES actionlib_msgs)

  注意如果使用catkin_create_pkg创建包时没有添加actionlib相关的依赖项,要将上面CMakeLists中第一行的注释去掉,另外还要在package.xml文件中加入下面几行。因为我们在创建包时就添加好了相关依赖,所以这一步骤可以省略。

<build_depend>actionlib</build_depend>
<build_depend>actionlib_msgs</build_depend>
<run_depend>actionlib</run_depend>
<run_depend>actionlib_msgs</run_depend>

  

 使用catkin_make编译即可查看生成的消息文件,这些消息之后将会用于ActionClient 和 ActionServer间的通信。

  另外可以看到,在devel/include/actionlib_test/中生成了相关的头文件:

 

C++ SimpleActionServer    

我们首先要创建一个server,例程如下:

#include <actionlib_bing/DoDishesAction.h>
#include <actionlib/server/simple_action_server.h>
typedef actionlib::SimpleActionServer<actionlib_bing::DoDishesAction> Server;

void execute(const actionlib_bing::DoDishesGoalConstPtr& goal, Server* as)
{
  // Do lots of awesome groundbreaking robot stuff here
  ros::Duration(2).sleep();
  as->setSucceeded();
}


int main(int argc, char** argv)
{
  ros::init(argc, argv, "do_dishes_server");
  ros::NodeHandle n;
  Server server(n, "do_dishes", boost::bind(&execute, _1, &server), false);
  server.start();
  ros::spin();
  return 0;
}

#include <actionlib_bing/DoDishesAction.h>

#include <actionlib/server/simple_action_server.h>

第一个就是引入DoDishes类的消息,而他的位置则是在你的devel/include/你的包的名字/中。

首先我们要定义一个SimpleActionServer,后面的则是消息类型。

 typedef actionlib::SimpleActionServer<actionlib_bing::DoDishesAction> Server;

 

进入main函数。

主要的是server的构造,http://docs.ros.org/api/actionlib/html/classactionlib_1_1SimpleActionServer.html

 

server(n, "do_dishes", boost::bind(&execute, _1, &server), false);

其中的参数n,就是NodeHandle。而“do_dishes”,是你给server起的名字。boost::bind(&execute, _1, &server)是当收到新的goal时候需要的返回函数。其中boost::bind用法可以参见http://www.cnblogs.com/TIANHUAHUA/p/8418818.html

我们的回调函数功能就是延时两秒后,发送完成信息。

server.start();开启server

 

一个简单的server就完成了。

 

C++ SimpleActionClient    

我们简单改写一个Client,同样是基于官方例程。

#include <actionlib_bing/DoDishesAction.h>
#include <actionlib/client/simple_action_client.h>


typedef actionlib::SimpleActionClient<actionlib_bing::DoDishesAction> Client;

int main(int argc, char** argv)
{
  ros::init(argc, argv, "DoDishes_Client");

  Client client("do_dishes", true); // true -> don't need ros::spin()
  client.waitForServer(); // Waits for the ActionServer to connect to this client
  actionlib_bing::DoDishesGoal goal;
  // Fill in goal here
  client.sendGoal(goal); // Sends a goal to the ActionServer
  client.waitForResult(ros::Duration(5.0)); // Blocks until this goal finishes
  ros::Rate loop_rate(1);
  while (ros::ok()){
    // if (client.getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
    //   printf("Yay! The dishes are now clean\n");
    printf("Current State: %s\n", client.getState().toString().c_str());
    loop_rate.sleep();
  }

typedef actionlib::SimpleActionClient<actionlib_bing::DoDishesAction> Client;

首先定义一个Client变量,

Client client("do_dishes", true);然后接入“do_dishes”的sever。True代表无需使用ros::spin(), 而false为需要自己添加ros::spin()。默认为true。

client需要发布goal之后,等待结果,最后就可以查询server的程序运行的当前状态了。

 

在CMakeLists文件中加入下面这几行:

add_executable(client   src/client.cpp)
add_executable(server   src/server.cpp)
target_link_libraries( client ${catkin_LIBRARIES})
target_link_libraries( server ${catkin_LIBRARIES})

首先运行server,在运行client

运行之后,我们会得到Active的等待goal完成,直到goal完成,状态变为succeeded。

 

C++ Move_base的client编写    

#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <move_base_msgs/MoveBaseGoal.h>
#include <geometry_msgs/PoseStamped.h>

typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> Client;
int main(int argc, char** argv)
{
  ros::init(argc, argv, "move_base_actionlib_bing");

  Client client("move_base", true); // true -> don't need ros::spin()
  client.waitForServer(); // Waits for the ActionServer to connect to this client
  // Fill in goal here (0.813, 2.349, 0.000)
  printf("Server connected. \r\n");
  move_base_msgs::MoveBaseGoal action_goal;
  action_goal.target_pose.header.stamp = ros::Time::now();
  action_goal.target_pose.header.frame_id = "map";

  action_goal.target_pose.pose.position.x =0.813;
  action_goal.target_pose.pose.position.y =2.349;
  action_goal.target_pose.pose.position.z =0;

  action_goal.target_pose.pose.orientation.x =0;
  action_goal.target_pose.pose.orientation.y =0;
  action_goal.target_pose.pose.orientation.z =0;
  action_goal.target_pose.pose.orientation.w =1;

  client.sendGoal(action_goal); // Sends a goal to the ActionServer
  client.waitForResult(ros::Duration(05.0)); // Blocks until this goal finishes
  ros::Rate loop_rate(1);
  while (ros::ok()){
    printf("Current State: %s\n", client.getState().toString().c_str());
    loop_rate.sleep();
  }
  return 0;
}

其中,跑起来navigation的仿真包。我们再运行这个节点,就会通过move_base的server。

之后程序会发送一个目标点,我们一直打印着move_base运行状态。

注意,当我们不发送goal就直接读取返回状态的话,会出现

Trying to getState() when no goal is running. You are incorrectly using SimpleActionClient

并且返回Current State:LOST

 

参考资料:    

actionlib

ROS actionlib学习(一)

actionlib的身世之谜

Actionlib doc:

http://docs.ros.org/api/actionlib/html/classactionlib_1_1SimpleActionClient.html#ae6a2e6904495e7c20c59e96af0d86801

http://docs.ros.org/api/actionlib/html/classactionlib_1_1SimpleActionServer.html

 

ros从入门到放弃(学习笔记1)

最近在想着做机器人,机缘巧合接触到了ROS,在这里分享一下我学习ROS的经历。首先就是安装ROS,安装ROS网上有很多资料可以查到,但是我在安装的时候初始化一直出问题,基本网上什么方法都尝试了,总... 查看详情

ros知识(12)----actionlib的使用

 1.原理1.1功能 1.2框架 2.例子 3.源码the_first_actionlib_sample 查看详情

rosactionlib学习

  actionlib是ROS中一个很重要的功能包集合,尽管在ROS中已经提供了srevice机制来满足请求—响应式的使用场景,但是假如某个请求执行时间很长,在此期间用户想查看执行的进度或者取消这个请求的话,service机制就不能满足了... 查看详情

《ros理论与实践》学习笔记机器视觉处理(代码片段)

《ROS理论与实践》学习笔记(六)机器视觉处理课程内容1.ROS摄像头驱动及数据接口2.摄像头参数标定3.ROS+OpenCV图像处理方法及案例4.ROS+Tensorflow物体识别方法及案例本讲作业1.通过人脸识别方式,发布速度控制指... 查看详情

ros学习笔记之——remark

此博文用于本人备忘一些资料~Real-TimePanoramicTrackingforEventCamerashttps://github.com/VLOGroup/dvs-panotrackinghttps://github.com/VLOGroup/dvs-reconstructionCeresSolver一文助你Ceres入门——CeresSolver新手向全攻略_福尔摩睿的工作站-CSDN 查看详情

第十二课actionlib

一Actionlib概念在ROS系统中,有时需发送请求给某个节点完成相应的任务,同时获得一个一个响应,这种情况下可以通过ROS服务来完成;然而,在某些情况下,服务需要很长时间才能执行完,如让机器人到达一个指定的地点,用户想要取消或... 查看详情

ros实验笔记之——px4仿真

 之前博文《ROS学习笔记之——PX4开发初入门》《ROS学习笔记之——PX4生态系统》已经对PX4做了一些基本的学习,并且在mac上搭建了px4开发环境。本博文在ubuntu下对PX4进行一些基本的仿真学习~之前在做无人机仿真开发时... 查看详情

集成电路模拟版图入门-版图基础学习笔记

今日接着给大家分享模拟版图入门学习笔(六),前几期的学习笔记如下:集成电路模拟版图入门-版图基础学习笔记(一)集成电路模拟版图入门-版图基础学习笔记(二)集成电路模拟版图入门-... 查看详情

ros学习笔记之——px4生态系统

之前博客已经初步学习了PX4《ROS学习笔记之——PX4开发初入门》,本博文进一步的学习PX4的相关知识,部分资料来源于购买的阿木实验室的课程《PX4智能无人机二次开发》与《Prometheus自主无人机二次开发课程》目录 PX4... 查看详情

ros实验笔记之——slam无人驾驶初入门(代码片段)

最近想学习一下无人驾驶SLAM方面的内容代码测试这里先基于kitti数据集,进行测试。之前博客中已经介绍过kitti数据集了。本博文就用这个数据集来进行各种经典方法的复现TheKITTIVisionBenchmarkSuitehttp://www.cvlibs.net/datasets/kitti/eva... 查看详情

ros学习笔记之——vicon的使用(代码片段)

...近要测量定位算法的精度,打算用vicon来提供groundtruth入门vicon其实就相当于一个传感器,在机载电脑上安装VICON-ROS包,这个包就相当于驱动接收来自VICON的数据在机载电脑上编译(需要用cm编译)编译完了之后&... 查看详情

c语言进阶学习笔记六详解文件操作(看完这篇,你的文件操作就入门了!)(代码片段)

前言在之前的学习过程中,我们所编写的程序在执行过程中所产生的数据及结果都只是临时存放在内存区域,一旦程序运行结束,该程序所涉及的内存空间全部返回给操作系统。这时候如果我们想要去查看这些数据和... 查看详情

ros学习笔记02:ros基础

文章目录一、ROS架构一、ROS架构ROS架构分为三个层次:OS层⟹\\Longrightarrow⟹中间层⟹\\Longrightarrow⟹应用层 查看详情

ros进二阶学习笔记-rosandmultithread

ROS进二阶学习笔记(4)-ROSandMultithreadI'lldiscussabouttheconceptofthread,multithread,andtheapplicationofmultithreadcodinginROSenv.1.What'smultithread?-Basicsofoperatingsystemref:http:// 查看详情

ros进二阶学习笔记--metapackage

ROS进阶学习笔记(24)--MetapackageMetapackage是ROSFileSystem概念层中的一个概念:2.CreateandConfigureaMetapackage:url:http://wiki.ros.org/catkin/package.xml#MetapackagesUsuallytheparentfolder,namedli 查看详情

ros-4:ros节点和主题(代码片段)

...在起src下创建功能包ros_demo_pkg,依赖项为roscpp、std_msgs、actionlib、actionlib_msgs,并构建该空功能包。ROS中节点间的基本通讯方式是topic,即publish/subscribe模式。以下介绍如何创建两个两个节点分别发布和订阅一个主题。一、创建 查看详情

ros学习笔记三(理解ros节点)

要求已经在Linux系统中安装一个学习用的ros软件包例子:sudoapt-getinstallros-indigo-ros-tutorialsROS图形概念概述nodes:节点,一个节点即为一个可执行文件,可以通过ROS和其他节点进行通信;messages:消息,当订阅或者发布一个topic时使... 查看详情

ros学习笔记——debug

NEW1$roscoreNEW2$rosrunrqt_consolerqt_console  $rosrunrqt_logger_levelrqt_logger_levelNEW3$rosrunturtlesimturtlesim_node 查看详情