ROS之actionlib

1,什么是action

   用过toplic的同学们都知道,两个节点之间可以通过发布或者订阅来单向通信。但是如果我们在发布信息到指定的节点的同时,我们需要知道订阅的节点是否接收到消息,执行状态如何,那么问题来了,我是否可以通过节点中同时发布和订阅主题的执行状态呢?答案当然是可以的,action就解决了这一痛点;

  action机制从原理上看的话,其实是基于topic实现的,相当于制定了一套由目标话题,反馈话题,结果话题组成的高级协议。action实现了一种类似于service的请求/响应通讯机制,区别在于action带有反馈机制,用来不断向客户端反馈任务的进度,并且还支持在任务中途中止运行。
操作起来就像这样子,客户端给服务端抛出一个目标,然后客户端就可以去干别的事情了,在任务执行期间,客户端会以消息的形式,周期性地接收到来自服务端的进度反馈,如果没有终止任务的话这个过程会一直延续到收到最终的结果。当然也可以随时终止当前的操作,开始一个全新的操作;

1,创建功能包

catkin_create_pkg action_demo roscpp actionlib actionlib_msgs  //创建功能包
cd action_demo/
mkdir action  //新建action文件夹来存放.action文件

2,action文件

action文件格式

#part1: the goal, to be sent by the client 
--- 
#part2: the result, to be sent by the server upon completion 
--- 
#part3: the feedback, to be sent by server during execution
---
cd action/&&gedit action_demo.action   //新建.action文件

加入如下内容

# Goal
int32 goal
---
# Result
bool result
---
# Feedback message
int32 feedback_msg

打开CMakeList.txt,加入下面语句


## Generate actions in the 'action' folder
add_action_files(
  FILES
  action_demo.action
)

## Generate added messages and services with any dependencies listed here
generate_messages(
  DEPENDENCIES
  actionlib_msgs
)
catkin_package(
  CATKIN_DEPENDS actionlib_msgs
)

接下来,编译!!

编译成功后,会生产.msg文件,如下

banker@banker:~$ ls catkin_ws/devel/share/action_demo/msg/
action_demoActionFeedback.msg  action_demoFeedback.msg
action_demoActionGoal.msg      action_demoGoal.msg
action_demoAction.msg          action_demoResult.msg
action_demoActionResult.msg
banker@banker:~$ ls catkin_ws/devel/include/action_demo/
action_demoActionFeedback.h  action_demoActionResult.h  action_demoResult.h
action_demoActionGoal.h      action_demoFeedback.h
action_demoAction.h          action_demoGoal.h

2,开始编写代码测试

server代码

#include <ros/ros.h>
#include <actionlib/server/simple_action_server.h>
#include <action_demo/action_demoAction.h>

class action_demoAction
{
protected:

  ros::NodeHandle nh_;
  actionlib::SimpleActionServer<action_demo::action_demoAction> 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
  action_demo::action_demoFeedback feedback_;
  action_demo::action_demoResult result_;

public:

  action_demoAction(std::string name) :
    as_(nh_, name, boost::bind(&action_demoAction::executeCB, this, _1), false),
    action_name_(name)
  {
    as_.start();
  }

  ~action_demoAction(void)
  {
  }

  void executeCB(const action_demo::action_demoGoalConstPtr &goal)
  {
    ros::Rate r(10);
    bool success = true;

    // publish info to the console for the user
    ROS_INFO("%s: Executing, creating actiondemo  order %i with feedback_msg %i", action_name_.c_str(), goal->goal, feedback_.feedback_msg);
    feedback_.feedback_msg = 0;
    result_.result = 0;
    // start executing the action
    for(int i=1; i<=goal->goal; i++)
    {

      feedback_.feedback_msg = i;
      result_.result += i;
      ROS_INFO("%i: feedback_.feedback_msg", feedback_.feedback_msg);
      // publish the feedback
      as_.publishFeedback(feedback_);

      r.sleep();
    }

    if(success)
    {
      //result_.result = feedback_.feedback_msg;
      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, "action_demo");
  ROS_INFO(" action server start.");
  action_demoAction action_demo("action_demo");
  ros::spin();

  return 0;
}

client代码

#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include <actionlib/client/terminal_state.h>
#include <action_demo/action_demoAction.h>

// 当action完成后会调用次回调函数一次
void doneCb(const actionlib::SimpleClientGoalState& state,const action_demo::action_demoResultConstPtr& result)
{
    ROS_INFO("doneCb ,action finsh , result = %i",result->result);
    ros::shutdown();
}

 

// 当action激活后会调用次回调函数一次
void activeCb()
{

    ROS_INFO("Goal just went active");

}
// 收到feedback后调用的回调函数
void feedbackCb(const action_demo::action_demoFeedbackConstPtr& feedback)
{

    ROS_INFO(" feedback_msg : %i ", feedback->feedback_msg);

}

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

  // create the action client
  // true causes the client to spin its own thread
  actionlib::SimpleActionClient<action_demo::action_demoAction> ac("action_demo", true);

  ROS_INFO("Waiting for action server to start.");
  // wait for the action server to start
  ac.waitForServer(); //will wait for infinite time

  ROS_INFO("Action server started, sending goal.");
  // send a goal to the action
  action_demo::action_demoGoal goal;
  goal.goal = 5;
  //ac.sendGoal(goal);
  ac.sendGoal(goal,  &doneCb, &activeCb, &feedbackCb);
  //wait for the action to return
  bool finished_before_timeout = ac.waitForResult(ros::Duration(10.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.");

  //exit
  return 0;
}

修改CMakeLists,加入如下代码:

add_executable(action_demo_server src/action_demo_server.cpp)

add_executable(action_demo_client src/action_demo_client.cpp)

target_link_libraries(
  action_demo_client
  ${catkin_LIBRARIES}
)

target_link_libraries(
  action_demo_server
  ${catkin_LIBRARIES}
)

编译运行

^Cbanker@banker:~$ rosrun action_demo action_demo_server 
[ INFO] [1565945494.394334604]:  action server start.
[ INFO] [1565945497.440212600]: action_demo: Executing, creating actiondemo  order 5 with feedback_msg 0
[ INFO] [1565945497.440259549]: 1: feedback_.feedback_msg
[ INFO] [1565945498.440326674]: 2: feedback_.feedback_msg
[ INFO] [1565945499.440314090]: 3: feedback_.feedback_msg
[ INFO] [1565945500.440317296]: 4: feedback_.feedback_msg
[ INFO] [1565945501.440296284]: 5: feedback_.feedback_msg
[ INFO] [1565945502.440289997]: action_demo: Succeeded







banker@banker:~$ rosrun action_demo action_demo_client 
[ INFO] [1565945497.254264243]: Waiting for action server to start.
[ INFO] [1565945497.439740210]: Action server started, sending goal.
[ INFO] [1565945497.440392219]: Goal just went active
[ INFO] [1565945497.440531685]:  feedback_msg : 1 
[ INFO] [1565945498.440599365]:  feedback_msg : 2 
[ INFO] [1565945499.440703451]:  feedback_msg : 3 
[ INFO] [1565945500.440653442]:  feedback_msg : 4 
[ INFO] [1565945501.440654238]:  feedback_msg : 5 
[ INFO] [1565945502.440648618]: doneCb ,action finsh , result = 15

代码主要是客户端给服务器发送一个值(goal),服务端接收到后把1到这个值累加,每次累加会给客户端返回一个feedback_msg,完成后result的值就是累加的值

finshed!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ROS actionlib is a library that provides a way to define and execute long-running, asynchronous tasks in a modular way. It is used to manage and monitor the progress of tasks that have multiple stages or that require feedback during execution. The library provides a flexible and efficient communication protocol that allows nodes to interact with each other in a structured and reliable way. Actionlib is commonly used in robotics applications to control complex behaviors such as navigation, manipulation, or perception. It allows developers to define and execute complex actions as a series of smaller, self-contained tasks. These tasks can be executed in parallel, and the overall progress of the action can be tracked and monitored. Actionlib consists of two main components: the action server and the action client. The action server is responsible for executing the action, while the action client sends requests to the server and monitors the progress of the action. The action server receives requests from the action client and executes the requested action. During execution, the server provides feedback to the client, keeping it informed of the progress of the action. Once the action is complete, the server sends a result message back to the client. The action client sends requests to the server and monitors the progress of the action. It can also cancel the action if necessary. The client receives feedback from the server, allowing it to provide real-time feedback to the user or to adjust its behavior based on the progress of the action. Overall, ROS actionlib provides a powerful and flexible framework for managing and executing complex, asynchronous tasks in ROS-based robotics applications.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值