54 个接口、5 层结构、30 条拒绝理由:从 aimdk_msgs 倒推启元机器人 Q1 的软件架构
上一篇我们读了 Q1 的「身体说明书」——那份藏在官方 URDF 里的骨架档案,26 段骨架、22 个关节、16.9 公斤。这次往里走一层:身体之上,是让这具身体能听、能说、能动、也能拒绝你的软件系统。
研究一个 ROS2 机器人系统的架构,有条公开的捷径:不用拆机、不用搞到源码,读它对外暴露的接口定义就够了。分布式系统里,接口就是「宪法」——哪些能力开放、以什么方式开放、谁优先谁排队、什么情况下拒绝你,全部写死在消息定义文件里,一行都赖不掉。
Q1 的 SDK(q1-sdk v1.0.0.0)里有个 aimdk_msgs 包,装着机器人对外的全部接口定义。这篇文章带你把它们盘完。读法和上一篇一样:所有数字来自接口文件原文,出处随文标注。
一、先盘家底:54 个文件、两种类型、五层目录
接前两篇的环境(Windows 11 + WSL2 Ubuntu 22.04 + ROS2 Humble + q1-sdk v1.0.0.0),两条命令就能验明家底:
source ~/workspace/sdk_q1/install/setup.bash
ros2 interface list | grep aimdk | wc -l
输出:54。
54 个接口全部可被 ros2 工具链识别。实测环境:WSL2 Ubuntu 22.04 + ROS2 Humble + q1-sdk v1.0.0.0(与前两篇同一环境)。
这 54 个接口文件分两种类型,类型即通信方式(这是 ROS2 的基本法,也是读架构的第一把钥匙):
- 36 个 .msg(消息)——走 topic,「广播流」。发布者只管往外发,谁爱听谁订阅,典型如传感器状态:机器人每秒广播一次触摸事件,你不听它也照发。
- 18 个 .srv(服务)——走 service,「请求-响应」。你必须收到答复才算数,典型如下命令:让机器人播一段语音,它会告诉你成没成、预计播多久。
再看目录结构,54 个文件分成五层(数字为 msg + srv,来源:aimdk_msgs 包目录清点):

| 层 | 接口数 | 管什么 |
|---|---|---|
| common | 7 msg | 地基:统一的消息头、状态码、拒绝理由 |
| hal | 13 msg + 9 srv | 硬件抽象:电池、关节、触摸、音频、相机、灯 |
| mc | 11 msg + 6 srv | 运动控制:动作档位、预设动作、输入源 |
| interaction | 4 msg + 3 srv | 交互:语音合成播报、表情、关机 |
| agent | 1 msg | 智能体:语音识别结果 |
目录即架构图。 不用看一行实现代码,五层目录已经把这台机器人的「部门编制」交代清楚了:管硬件的、管运动的、管说话的、管思考的,还有一层给全员立规矩的。下面逐层拆。

二、common 层:先立规矩,再干活
7 个文件,全是「格式合同」:RequestHeader / ResponseHeader / MessageHeader 三种消息头,加上 CommonRequest / CommonResponse / CommonTaskResponse 三种通用信封。任何一层发消息,都得套这个信封。
最有意思的是 CommonState——统一的任务状态码。它先定义了 10 个状态(成功 / 失败 / 中止 / 超时 / 无效 / 手动 / 未就绪 / 等待中 / 已创建 / 运行中),然后紧跟一个 reason 字段和 30 条拒绝理由码。机器人拒绝执行你的指令时,不是沉默,而是给你一个编号。原文精选(来源:aimdk_msgs/msg/CommonState.msg):
| 编号 | 拒绝理由 |
|---|---|
| 1 | 开箱状态中 |
| 2 | 开机自检中 |
| 5 | 低电量限制 |
| 6 | 正在充电中 |
| 7 | 动作不在白名单 |
| 10~14 | 前方 / 后方 / 左方 / 右方 / 上方有障碍物 |
| 15 | 其他任务正在运行 |
| 19 | 无法执行任务,机器人需要处于双足站立状态 |
| 24 | 室内模式下暂不支持该动作 |
| 26 | 当前机型不支持该功能 |
| 28 | 当前动画不可打断 |
| 30 | 当前状态不满足变形/动作执行条件 |
细读这张表能看出产品形态:连「上方有障碍物」都单独给了编号(机器人要跳跃、要起身),「正在充电中」会拒绝你(充电时不出工),「室内模式」有单独的动作白名单(客厅里不许撒欢)。

更重要是设计态度:拒绝也要给出可查的理由。消费电子产品拒绝你的时候往往只有一声「叮」,而这里拒绝是一门 30 条的词典——排障时查表就行,不用猜。这是把「可调试性」写进了协议层。
三、hal 层:把每块硬件翻译成标准词
hal(Hardware Abstraction Layer,硬件抽象层)是接口最多的层,13 个 msg + 9 个 srv,每块硬件一份「字典词条」。挑四个有讲头的:
Bms(电池管理):一个字段 status,是个 32 位整数,0~28 每一位都是一个状态开关——充电过流、放电过流、电池短路、电芯过压/欠压、总电压过压/欠压、温感开路、充放电温度超限、最大压差超限、MOSFET 禁止充/放电、均衡线电阻超限、电池充满……外加循环次数、总充放电累计(mAh)、均衡线电阻(mΩ)、电池温度。一条消息就是电池包的完整体检报告,精确到电阻单位。
TouchState(触摸):定义了 10 种触摸事件——单击、双击、三击、四击、五击、六击,超过六次归为「多击」,再加向左滑、向右滑。对,六连击是协议里明文存在的。注释还写明传感器位置因机型而异:Q1 在头部,T1 在背部和胸部。这正是第一篇里我们双终端实测链路用的那条消息——当时它还只是屏幕上每秒刷新的 event_type: 1,现在你知道那只是它十种表情之一。
JointCommand / JointState(关节):命令里除了常规的位置/速度/力矩,还有 stiffness(刚度)和 damping(阻尼)——这是阻抗控制的标志性参数:不但能命令关节「到哪儿」,还能命令它「多硬」。手臂被外力推开时是硬顶还是顺从回弹,就调这两个数。而状态回传里除了位置,还有 coil_temp(线圈温度)和 motor_temp(电机温度)——电机烧毁前会有先兆,协议层已经把体温计插好了。
SetServo(舵机):一个看似平淡的舵机服务,注释里藏着结构性信息——位置范围 0~90 度,0 度是四足形态的位置,90 度是双足形态的位置,速度按「步」计,1 步 0.225 度。Q1 的四足↔双足变形不止是软件里的动作指令,底下还有一套物理舵机机构在锁形态。硬件的「户口」骗不了人。
四、mc 层:61 个动作档位,和 5 个被删掉的动作
mc(Motion Control,运动控制)层是考古富矿。核心是 McAction 这一个文件:61 个有效动作档位,按编号分段,像一座规划好的城市(来源:aimdk_msgs/mc/action/McAction.msg,逐项清点):
| 编号段 | 数量 | 内容 |
|---|---|---|
| 1~3 | 3 | 急停类:被动模式、阻尼模式(断力卸能,安全优先) |
| 10~22 | 6 | 形态切换:四足↔双足,常规/带旋转/前空翻三种翻法 |
| 100~121 | 22 | 四足动作:握手、坐下、跳舞、前空翻、后空翻、俯卧撑、跳跃、伸展、模仿…… |
| 200~303 | 11 | 双足动作:越障、太空步(206)、奔跑、模仿、全身控制、上肢录制 |
| 1001~1019 | 19 | Q 系列专属:折叠收储、站起、入座/离座、室内轻柔步态、室外越障、超能跑步模式 |
而这座城里还有 5 块「拆掉的楼」——官方注释原文标注「(删除)」的动作:
- 204 双足原地旋转
- 205 双足下腰
- 209 双足羽生结弦
- 210 双足劈叉
- 400 双足转圈舞
「羽生结弦」大概率指花滑运动员的标志性动作编排。为什么删?接口文件不会说,但「删」这个动作本身说明:这些动作被实现过、评估过,然后出于稳定性或安全考虑下了架。接口文件的注释区,就是产品决策的施工现场——上一篇 URDF 里被注释掉的 mesh 碰撞,这一篇被注释掉的羽生结弦,同一个考古乐趣。
这一层还有三样东西值得停一下:
- McPresetMotion:37 个预置动作档(含恢复默认姿态),从挥手、握手、碰拳、比心、拥抱、拒绝、加油,到四个拍照姿势和一个「三连拍」——演示和互动场景的动作库。
- McTaskSource:9 种动作触发源——APP、云端、遥控器、SDK、agent、自动任务引擎、MC 内部自动切换、Insta360 相机、其他。一台机器人身上有九个「可能下指令的角色」,这为下一节埋下伏笔。
- SetMcMotion 服务:模仿动作的参数里有 onnx 模型路径——模仿动作是神经网络模型驱动的,文件里还留着 MIMIC_QY / MIMIC_LC(灵创)/ 开源模仿等多套模型入口。AI 不只在大脑板上,也长在运动控制层。
五、interaction 层:连「说话」都要排队
如果说过往的印象里机器人说话是「播放一段音频」,这一层会刷新认知。PlayTts(语音播报服务)的请求里有个 priority_level 字段,定义了六级播报优先级(来源:aimdk_msgs/interaction/msg/TtsPriorityLevel.msg,以下注释为官方原文):
| 级别 | 常量名 | 场景 |
|---|---|---|
| L1 | BACKGROUND | 后台 |
| L2 | SERVICE | 主动服务 |
| L4 | MISSION | 任务 |
| L6 | INTERACTION | 交互(默认档) |
| L8 | WARNING | 危险预警 |
| L10 | SAFETY | 生命安全 |
六级之外还能用 priority_weight 在同级内微调权重。

配套细节一层扣一层:音频播放(AudioFile)另有 media_role 体系——系统告警 100、提示音 80、对话语音 60、音乐 40,任何非音乐角色开播,音乐会自动压低音量(ducking),和手机导航播报压低音乐是同一套哲学。
请求里还必带 domain(调用方标识)和 trace_id(调用链追踪 ID),响应里除了成败,还有预估播报时长——方便上层编排「说完这句话就做下一个动作」。
这层还有个「特权通道」的例子:ShutdownTask(关机服务)不走 CommonRequest,走 TokenCommon——必填 source(来源标识)和 token(令牌)。关机是要令牌的。让机器人闭嘴可以排队,让机器人躺下必须出示证件——权限的松紧,全在接口设计里。
回头看 mc 层那 9 种触发源,再配上运动输入源的 priority(0~100)和 timeout(默认 1000ms,来源:McInputSource.msg,注释列出的输入源为 rc / vr / app_proxy / interaction / pnc),架构意图就完整了:手机 APP、语音、云端、遥控器、VR 可能同时指挥一台机器人,「谁先谁后」必须写成协议,而不是靠社交默契。

六、agent 层:只有一个文件的顶层
五层里最小的层:agent(智能体层)只有一个 AsrResult——语音识别结果(识别文本、置信度、是否最终结果、语言)。topic 名 /aima/agent/asr_result。
怎么读这个「1」?先说清边界:这不是说机器人的大脑只有语音识别——官方指南 §1 写明大脑板上跑着核心算法与供应商程序。接口数量刻画的是** v1.0.0.0 版本对第三方开发者开放的边界**:大脑侧目前只把语音识别结果这条「感官流」放了出来。
和上一篇 URDF 里那个焊死的腕关节对照着看,是同一个设计哲学的两面:腕关节是结构上的预留车位,agent 层是协议上的预留楼层——目录建好了、命名规范立好了(topic 前缀 /aima/agent/ 与其他四层完全一致),后续版本往上加接口时,接入方一行代码都不用改结构。
七、三机一体:你的电脑和机器人是「平等节点」
最后把视角拉高。这套接口跑在什么硬件上?官方指南 §1 给出了架构:三台设备,同一条消息总线——
- 开发 PC(Ubuntu 22.04):跑你的 SDK 程序
- 运控板(10.1.1.100):HAL / MC / 交互基础服务——第三、四、五节拆的那些接口,家在这里
- 大脑板(10.1.1.101):核心算法、供应商程序——agent 层的来处
关键在连接方式:三者经局域网 FastDDS 总线互联,是对等节点,没有主从。你的电脑和机器人内部的两块板,说同一种语言、订同一套宪法——这正是第一篇里「无真机验证」能成立的原理:当时我们在两个终端里自发自收 TouchState,那其实就是这套三机架构的微缩沙盘,把终端 A 换成真机器人,链路一字不变。
顺带一个命名彩蛋:接口注释里的 topic 名有清晰规律——/aima/agent/asr_result、/aima/hal/touch/state……/aima/<层>/<模块>/<对象>,看到 topic 名就能反推它属于哪一层。总线上的门牌号,本身就是一张架构索引。


八、亲手盘一遍:五条命令
本文开头用过的盘点命令,完整版在这(环境同前两篇,全部实测):
source /opt/ros/humble/setup.bash
source ~/workspace/sdk_q1/install/setup.bash
# 1. 接口总数(期望输出 54)
ros2 interface list | grep aimdk | wc -l
# 2. 触摸的十种事件(第三节的 TouchState 原文)
ros2 interface show aimdk_msgs/msg/TouchState
# 3. 六级播报优先级(第五节的原文,官方中文注释直接可见)
ros2 interface show aimdk_msgs/srv/PlayTts
# 4. 30 条拒绝理由(第二节的原文)
ros2 interface show aimdk_msgs/msg/CommonState
# 5. 61 档动作清单 + 5 个被删动作(第四节的原文,搜"删除")
ros2 interface show aimdk_msgs/msg/McAction

没有真机也能跑——这些命令读的是编译后的接口定义,不连机器人。跑一遍,本文的每个数字你都能在屏幕上亲手验证。
结语:接口即架构
54 个文件盘完,Q1 的软件骨架立起来了:
- 五层目录是部门编制:common 立规矩、hal 管硬件、mc 管运动、interaction 管表达、agent 留着思考;
- 30 条拒绝理由是可调试性的态度:拒绝不给编号的系统,排障全靠猜;
- 六级播报优先级 + 输入源 0~100 优先级是多主仲裁的方案:九个触发源抢一台机器人,规则写进协议;
- 令牌关机、白名单动作、室内模式是安全边界:越是「躺下」这种大动作,门禁越严;
- 一个文件的 agent 层是版本边界,也是预留楼层。
下一篇,我们让这些接口真正跑起来——SDK 的 examples 目录里躺着 19 个 Python + 19 个 C++ 示例程序,挑几个接上仿真环境实跑。纸面架构到运行代码,就差这一步。
互动一题:McAction 里被官方删掉的 5 个动作——原地旋转、下腰、羽生结弦、劈叉、转圈舞——你最希望哪个在后续版本回来?(我投羽生结弦一票。)评论区聊聊,另外本文所有数字都可以用第八节的命令亲手验证,欢迎跑完回来抓 bug。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)