ROS2 动作通信从零开始理解


一、先看 .action 文件写了什么

learning_interface/action/MoveCircle.action 中:

复制代码
bool enable     ← 目标:客户端说"我要启动"还是"我不要启动"
---
bool finish     ← 结果:服务端最后说"完成了"还是"没完成"
---
int32 state     ← 反馈:服务端过程中说"我现在转到 30°了""我现在转到 60°了"...

三段分别叫 Goal(目标)、Result(结果)、Feedback(反馈),这是动作通信的三要素。


二、colcon build 之后发生了什么

.action 文件被 ROS2 的编译工具自动翻译成 C++ 代码,生成一个名叫 MoveCircle 的类,里面装了三个小结构体:

复制代码
类名: learning_interface::action::MoveCircle
  内部包含:
      MoveCircle::Goal       →  结构体 { bool enable }
      MoveCircle::Result     →  结构体 { bool finish }
      MoveCircle::Feedback   →  结构体 { int32 state }

代码里写的 using Action = learning_interface::action::MoveCircle; 就是给这个长名字起个短名。之后:

cpp 复制代码
Action::Goal       →  MoveCircle::Goal       →  有 .enable 字段
Action::Result     →  MoveCircle::Result     →  有 .finish 字段
Action::Feedback   →  MoveCircle::Feedback   →  有 .state  字段

三、rclcpp_action 是什么

rclcpp_action 是一个命名空间 (可以理解为一个装相关功能的文件夹),里面放着 ROS2 动作通信需要的所有东西。通过 #include "rclcpp_action/rclcpp_action.hpp" 引入。

它里面装了这些:

复制代码
rclcpp_action (命名空间)
├── create_server<Action>()    →  创建一个动作服务端,返回智能指针
├── create_client<Action>()    →  创建一个动作客户端,返回智能指针
├── Server<Action>             →  服务端类(你创建出来的就是它)
├── Client<Action>             →  客户端类
├── ServerGoalHandle<Action>   →  服务端用来管理"一个具体目标"的句柄
├── ClientGoalHandle<Action>   →  客户端用来管理"一个具体目标"的句柄
├── GoalResponse               →  枚举:ACCEPT_AND_EXECUTE(接受)/ REJECT(拒绝)
├── CancelResponse             →  枚举:ACCEPT / REJECT
├── ResultCode                 →  枚举:SUCCEEDED / ABORTED / CANCELED
└── GoalUUID                   →  本质是 std::array<uint8_t, 16>(16字节唯一ID)

四、create_server 怎么创建服务端

cpp 复制代码
action_server_ = rclcpp_action::create_server<Action>(
    this,                // 我是哪个节点
    "move_circle",       // 动作名叫什么(客户端通过这个名字找到我)
    回调1,               // 收到目标时调用
    回调2,               // 收到取消请求时调用
    回调3                // 目标被接受后调用
);
  • create_server 是一个函数模板<Action> 告诉它要用哪个动作接口类型
  • 返回值是 Server<Action>::SharedPtr,也就是 std::shared_ptr<Server<Action>>(智能指针,自动管理内存)
  • create_publishercreate_subscription 是同一个模式

五、ServerGoalHandle<Action> 是什么?里面有什么?

using GoalHandle = rclcpp_action::ServerGoalHandle<Action>; 定义了一个别名。

ServerGoalHandle<Action> 是一个类模板,"句柄"的意思就是"抓手"------每次客户端发来一个目标,服务端就拿到一个句柄,通过这个句柄来控制和反馈这个具体目标。好比你去餐厅点餐,服务员给你一个号码牌,通过这个号码牌你可以查进度、取餐、取消。

它有哪些方法:

方法 什么时候用 作用
get_goal() 执行时想知道客户端发了什么 返回 shared_ptr<Action::Goal>,包含 .enable 字段
get_goal_id() 想知道是哪个目标 返回目标 UUID
is_canceling() 每轮循环检查一次 客户端是否请求取消?返回 true/false
is_active() 查目标还在不在 是否还没到达终态
is_executing() 查是否正在执行 是否处于执行状态
publish_feedback(feedback) 有进展就发 向客户端发送进度反馈
succeed(result) 任务完成了 通知客户端"成功了"(终态,调完不能再调别的)
abort(result) 任务没法完成了 通知客户端"中止了"(终态)
canceled(result) 响应客户端的取消 通知客户端"已取消"(终态)
execute() 开始执行时 标记进入执行状态

六、完整流程串起来

复制代码
客户端                                    服务端
  │                                         │
  │── 发送 Goal (enable=true) ──────────→  │  触发 handle_goal
  │                                         │     ↓ 返回 ACCEPT_AND_EXECUTE
  │                                         │  触发 handle_accepted
  │                                         │     ↓ 开新线程 → execute()
  │   ←── Feedback (state=0°) ──────────    │     publish_feedback(0°)
  │   ←── Feedback (state=30°) ─────────    │     publish_feedback(30°)
  │   ←── Feedback (state=60°) ─────────    │     publish_feedback(60°)
  │           ...                            │         ...
  │   ←── Feedback (state=360°) ────────    │     publish_feedback(360°)
  │   ←── Result (finish=true) ─────────    │     succeed(result)
  │                                         │
  └─ 收到最终结果,关闭                     └─ 执行完毕

七、怎么自己看头文件学习

ROS2 的头文件就在系统目录里,可以直接打开看源码:

bash 复制代码
ls /opt/ros/foxy/include/rclcpp_action/

核心文件就几个:

复制代码
client.hpp              →  Client<T> 类的完整定义
server.hpp              →  Server<T> 类的完整定义
create_client.hpp       →  create_client<T>() 函数声明
create_server.hpp       →  create_server<T>() 函数声明
client_goal_handle.hpp  →  ClientGoalHandle<T> 的所有方法
server_goal_handle.hpp  →  ServerGoalHandle<T> 的所有方法
types.hpp               →  GoalUUID、GoalStatus 等基础类型

想看哪个直接 cat 就行,头文件是最准确的文档。

相关推荐
三川6981 小时前
深入浅出SSD 09:NVMe介绍
网络
超级赛博搬砖工2 小时前
并发、多线程和HTTP连接之间有什么关系?
网络·网络协议·http
兰_博3 小时前
ensp配置-无线局域网配置
网络
许彰午3 小时前
17-22-运维与高级主题
运维·网络
万联WANFLOW3 小时前
外贸独立站:服务器放海外国内后台卡,放国内海外客户打不开——这道两头难怎么破?
运维·网络·数据库·经验分享
Kari114 小时前
连锁门店开业网络验收怎么做:把 PDF 清单改造成可回放的 Skill
网络·人工智能·pdf·php
玖玥拾4 小时前
Unity 3D 笔记(十二)Unity/C# Socket 网络笔记1
网络·unity·c#
2401_891957314 小时前
简单了解传输层协议UDP
网络·网络协议·udp
AvatarAI_Walker4 小时前
2026年7月安徽本地健康IP孵化行业观察:不同需求下的服务方向梳理
大数据·网络·tcp/ip·搜索引擎·精选