ROS中action的使用

本文详细介绍了在ROS中如何实现Action通信机制,包括服务端与客户端的设置、回调函数的定义、目标状态的发送与接收,以及如何在CMakeLists.txt中配置Action相关依赖。

例如说:
我的Action的文件为BBB.action,它在CCC的包里面
客户端和服务端:

  1. action的类型:CCC::BBBAction
  2. action的头文件: CCC/BBBAction.h,服务端和客户端都要include一下

服务端:

  1. action的服务端都要加上 #include<actionlib/server/simple_action_server.h>
  2. 声明服务器对象:
    actionlib::SimpleActionServer <CCC::BBBAction> action_server_
  3. 回调函数为:
    void EEE::ServerCallBack(const actionlib::SimpleActionServer<CCC::BBBAction>::GoalConstPtr& goal);
  4. 在类中使用初始化列表初始化:
    action_server_(nh, “/DDD”,boost::bind(&EEE::ServerCallBack,this, _1),false)
    其中nh为ros::NodeHandle
    EEE为类名
    DDD为标识action的字符串,服务端和客户端要一致
    "false”的意思是暂时不启动这个server(在这个构造函数中的后面会启动server)
  5. 启动server
    action_server_.start()
  6. 需要返回东西的时候,调用
    action_server_.setSucceeded(result, “”);
    其中action_server_是类型的对象
    result是CCC::BBBResult类型的对象
    注意不是CCC::BBBActionResult这个类型,CCC::BBBActionResult这个类型是存在的,但是这个setSucceeded的参数需要的是CCC::BBBResult

客户端:

  1. action的客户端都要加上#include <actionlib/client/simple_action_client.h>
  2. 声明客户端对象actionlib::SimpleActionClient<CCC::BBBAction> action_client_;
  3. 在类中使用初始化列表初始化:action_client_("/DDD", true)
    DDD为标识action的字符串,服务端和客户端要一致
    参数“true”是为了说明新的client将作为一个单线程运行
  4. bool server_exists = action_client_.waitForServer(ros::Duration(3.0));
    在三秒时间内查看是否存在对应服务端,这个一般返回得很快,一瞬间就可以了
  5. 回调函数为:
    void FFF::ClientCallBack(const actionlib::SimpleClientGoalState& state, const CCC::BBBResultConstPtr& result)
    actionlib::SimpleClientGoalState表示处理的状态,源文件为http://docs.ros.org/hydro/api/actionlib/html/simple__client__goal__state_8h_source.html
  6. 发送goal且指定回调函数action_client_.sendGoal(goal_,boost::bind(&FFF::ClientCallBack,this,_1,_2));

BBB包的CMakeLists.txt:

  1. find_package加上actionlib和actionlib_msgs
  2. add_action_files及上 BBB.action
  3. generate_messages 加上 actionlib_msgs
  4. catkin_package 的 CATKIN_DEPENDS加上 actionlib

服务端和客户端的包的CMakeLists.txt:

  1. find_package 加上 BBB

参考博客:
https://blog.youkuaiyun.com/will_ye/article/details/79589319

<think>好的,我现在需要帮助用户理解ROS中的Action通信机制,特别是ActionResult和ActionFeedback。首先,我需要回顾之前提供的引用内容,确保准确引用相关信息。 用户的问题主要集中在Action通信的机制和实现方式上,特别是ActionResult和ActionFeedback。根据引用[4],Action采用客户端/服务器模式,通过定义好的协议进行通信,涉及goal、cancel、status、feedback、result这几个部分。引用[2]提到ActionResult必须包含目标ID,并且在任何终端状态时发送,即使结果是空的。引用[3]则展示了ActionServer的实现,包括发布result和feedback的话题。 首先,我需要解释Action的基本结构,包括三个核心文件:*.action文件,生成对应的Goal、Result、Feedback消息。然后,描述通信流程,客户端发送goal,服务器处理并返回feedback和result。要特别强调ActionResult的作用,如引用[2]所说,必须发送,即使结果为空,并且客户端需要处理可能的结果状态(如Succeeded、Aborted等)。 接下来,关于ActionFeedback,引用[4]提到它是周期性的反馈数据,比如进度或中间结果,服务器通过feedback话题发布,客户端订阅以获取实时信息。引用[3]中的代码示例展示了如何发布feedback和result,这有助于说明实现方式。 然后,我需要讨论实现机制,比如如何创建ActionServer和ActionClient,如何定义消息类型,以及通信协议如何基于ROS的话题和服务。引用[3]中的代码片段显示,服务器需要订阅goal和cancel,发布status、result、feedback,这些都需要在实现时正确设置。 可能用户的实际需求是理解如何在项目中实现Action通信,或者调试相关的问题。因此,我需要强调关键实现细节,比如消息的正确使用、状态机的处理、结果和反馈的及时发送。同时,结合之前的引用,指出常见错误,比如忘记发送result,或者feedback频率不当影响性能。 最后,生成相关问题需要考虑用户可能进一步的问题,比如如何定义自定义的Action消息,如何处理多个并发的goal,或者如何调试Action通信中的问题。确保问题覆盖用户可能感兴趣的扩展方向,帮助他们深入学习。</think>### ROS Action通信机制深度解析 ROS Action通信机制是基于**客户端-服务器模型**的异步通信方式,结合了**目标驱动**和**实时反馈**的特性。其核心机制通过`*.action`文件定义接口,包含`Goal`、`Result`、`Feedback`三部分数据(引用[1][4])。以下从**通信流程**和**实现机制**两方面展开说明: --- #### 一、Action通信核心流程 1. **目标发起阶段** - 客户端通过`goal`话题发送`ActionGoal`消息(包含唯一`goal_id`) - 服务器接收目标后返回`status`状态码(如`ACTIVE`、`PREEMPTED`) ```cpp // 客户端发送目标示例 actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> client("move_base"); move_base_msgs::MoveBaseGoal goal; goal.target_pose.header.frame_id = "map"; client.sendGoal(goal); ``` 2. **执行反馈阶段** - 服务器通过`feedback`话题周期发送`ActionFeedback`消息(引用[3][4]) - 反馈数据可包含进度百分比、中间计算结果等实时信息 ```cpp // 服务器发送反馈示例 void executeCallback(const my_action::MyGoalConstPtr &goal) { my_action::MyFeedback feedback; feedback.progress = 50; server.publishFeedback(feedback); // 通过feedback_pub_发布(引用[3]) } ``` 3. **结果返回阶段** - 服务器通过`result`话题发送`ActionResult`消息(引用[2][4]) - **必须**在所有终止状态(`SUCCEEDED`/`ABORTED`等)时发送结果 ```cpp // 服务器发送结果示例 my_action::MyResult result; result.final_value = 100; server.setSucceeded(result); // 触发result_pub_发布(引用[3]) ``` --- #### 二、ActionResult与ActionFeedback实现机制 1. **ActionResult核心特性** - **强制发送原则**:即使结果为空,也必须发送(引用[2]) ```cpp // 空结果示例 actionlib_msgs::GoalStatus status; status.status = actionlib_msgs::GoalStatus::SUCCEEDED; server.setSucceeded(status); // 必须调用setSucceeded等终止方法 ``` - **状态机管理**:包含以下终止状态: - `SUCCEEDED`:目标成功完成 - `ABORTED`:内部错误导致失败 - `PREEMPTED`:被新目标抢占 - `REJECTED`:目标参数非法(引用[2][4]) 2. **ActionFeedback设计要点** - **非阻塞特性**:反馈消息与主线程异步发送(引用[3]) - **频率控制**:建议通过`ros::Rate`控制反馈周期(防止网络拥塞) ```cpp ros::Rate rate(10); // 10Hz反馈频率 while (ros::ok()) { publishFeedback(...); rate.sleep(); } ``` --- #### 三、底层通信协议实现 1. **消息通道架构**(引用[3][4]) | 通道类型 | 消息方向 | 消息格式 | 作用 | |---|---|---|---| | `goal` | Client → Server | `ActionGoal` | 发起任务请求 | | `cancel` | Client → Server | `GoalID` | 取消当前任务 | | `status` | Server → Client | `GoalStatusArray` | 广播任务状态 | | `feedback` | Server → Client | `ActionFeedback` | 周期性进度反馈 | | `result` | Server → Client | `ActionResult` | 最终执行结果 | 2. **状态同步机制** - 服务器通过`status_timer_`定时广播状态(引用[3]) - 客户端通过`SimpleActionClient`自动维护状态机: ```cpp actionlib::SimpleClientGoalState state = client.getState(); if (state == actionlib::SimpleClientGoalState::SUCCEEDED) { ROS_INFO("Action completed"); } ``` --- ### 关键问题解析 1. **为何ActionResult必须发送?** - 确保客户端能明确获知任务终止状态,避免无限等待(引用[2]) - 提供事务完整性保证(类似TCP协议的ACK机制) 2. **如何处理多目标冲突?** - 通过`goal_id`标识唯一性(引用[2]) - 使用`cancel`话题发送取消请求: ```cpp client.cancelAllGoals(); // 取消所有目标 client.cancelGoal(goal_id); // 取消特定目标 ``` --- ### 实现建议 1. **消息定义规范** - 在`*.action`文件中明确划分`Goal`、`Result`、`Feedback`字段 ```text # MyAction.action int32 target_value # Goal定义 --- int32 final_result # Result定义 --- float32 progress # Feedback定义 ``` 2. **异常处理要点** - 在`preemptCallback`中处理抢占请求 - 使用`try-catch`块包裹执行逻辑以确保发送结果 ```cpp try { executeGoal(goal); } catch (const std::exception& e) { server.setAborted(); // 异常时强制终止 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值