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 就行,头文件是最准确的文档。

相关推荐
Lynne30910 小时前
工业网络,到底该集中还是自治?
网络·架构·数据
光电笑映13 小时前
网络通信基础:从协议分层到 Socket 编程预备
linux·运维·服务器·网络
mengge.cloud14 小时前
0917Docker 小白实验教程(理论+实操)
linux·服务器·网络·docker
Thomas.Sir16 小时前
第13课:PyTorch|经典CNN网络模型从零复现【从LeNet到VGG的逐行实现】
网络·pytorch·cnn
en.en..16 小时前
网络分层封装 与 TCP粘包的因果关系
网络·单片机·嵌入式硬件
IMPYLH17 小时前
HTML 的 <slot> 元素
前端·网络·html
星恒讯工业路由器18 小时前
“铸链计划”第三批启动,工业5G产品从“有”到“优”的淘汰赛开始了
网络·物联网·智能路由器·工业物联网·铸链计划·工业5g·工业路由器选型
2601_9494999419 小时前
工业 POF 器件国产化新思路:芯瑞科技DT‑2532Z 解决安华高 HFBR‑2532Z 供应链卡点
运维·网络·人工智能·科技·光模块
Doris__HE20 小时前
【元脑服务器NF8260G7-NF8260M7技术规格分享】
运维·服务器·网络·数据库·性能优化
白猫不黑20 小时前
CTF是什么?从零理解一场攻防竞赛
网络·web安全·计算机·网络安全·信息安全·ctf·红蓝对抗