把大疆 M3E 无人机接进 RoboNIX:目前的进展
一、背景与目标
RoboNIX 是 syswonder 社区的一个面向具身智能的机器人操作系统,目前主要接入了机械臂、灵巧手这类设备。我最近在做的一件事,是把大疆 Mavic 3 Enterprise(M3E)无人机作为「首个无人机本体」接进去,让它成为 RoboNIX 能调度、能编程控制的一个执行单元。
最终想要的效果是:在 RoboNIX 里能对无人机做到——
- 程序化飞控:起飞 / 降落 / 巡航 / 手动操控
- 实时遥测:高度、GPS、飞行状态
- 实时画面:网页端看 MJPEG 视频流
- 自然语言控制:对着
rbnx chat说「飞过去拍张照」
这篇先记一下目前走到哪了、踩了哪些坑。
二、硬件与路线选择
硬件是 M3E 飞机 + DJI RC Pro(RM510B)遥控器,RoboNIX 跑在一台 Linux(WSL2 Ubuntu 22.04)上。
大疆给开发者开了两条路:
| 路线 | 跑在哪 | 特点 |
|---|---|---|
| MSDK | RC Pro 的 Android 上 | 用 App 控制飞机,开发快、适合先打通链路 |
| PSDK | 机载计算 + E-port | 能力更强,但需要机载设备和扩展口 |
我选择先走 MSDK:自己写一个 Android APK 装到 RC Pro 上,把飞控能力用 HTTP 接口暴露出来;RoboNIX 侧再写一个桥接原语去调这些接口。这样先把「RoboNIX → 无人机」的链路整体跑通,PSDK 可以以后再说。
三、整体架构
1 | ┌────────────────────────────────────────────┐ |
数据流四个方向:
| 方向 | 路径 | 协议 |
|---|---|---|
| PC → 无人机 | RoboNIX → drone_bridge → HTTP → RC Pro → MSDK → M3E | HTTP/JSON |
| 无人机 → PC | M3E → MSDK → RC Pro → HTTP → drone_bridge → Atlas | HTTP/JSON |
| 视频流 | M3E → RC Pro → /api/video MJPEG → 浏览器 |
HTTP MJPEG |
| 对话控制 | 用户 → rbnx chat → Executor → drone_bridge → … |
MCP + HTTP |
四、两个软件主体
4.1 RC Pro 端:自研 APK
APK 跑在 RC Pro 上,负责跟飞机通信。核心能力:
- 飞控三模式:待命 / 巡航 / 手动
- 内置 WebServer(:8080):HTTP REST API + 网页仪表盘 + MJPEG 视频流
- 视频帧采集:NV21 → JPEG,640px,约 12fps
最新版是同事交付的 v4.0(包名 com.dji.wang.aircraft),统一了相机、云台、GPS 拍照等接口,动作串和 Python 侧完全对齐。
4.2 RoboNIX 端:drone_bridge 原语
这是一个 Python 包,结构大致是:
1 | drone_bridge/ |
一个关键点:这些原语声明为 MCP(@drone.mcp(...))而不是 gRPC。原因是 RoboNIX 的 executor 在分发外部能力时硬编码走了 Transport::Mcp,rbnx call 只认 MCP 声明的能力。这个坑后面会细说。
五、11 个原语详解(核心)
经过多轮精简和与真实 API 对齐,最终确定了 11 个原语,命名空间统一为 robonix/primitive/drone/*。
5.1 无人机本体
| 原语 | 输入 | 对应 HTTP | 说明 |
|---|---|---|---|
takeoff |
altitude(m, 默认 3.0) |
POST /api/start |
起飞爬升至指定高度;前置 IDLE + SDK 已激活 |
land |
无 | ⚠️ 无端点 | API v4.0 没有 /api/land,当前固定返回失败 |
move_velocity |
vy/vz/wz/vx/wx/wy/duration |
POST /api/manual |
机体系 6DOF 速度向量;只映射左右/上下/旋转,vx/wx/wy 忽略 |
rotate_velocity |
direction/angular_velocity/duration |
POST /api/manual(rotate) |
独立旋转;direction=1 右转 / -1 左转 |
hover |
无 | POST /api/stop |
紧急悬停 |
rth |
无 | POST /api/gohome |
智能返航并降落;依赖 GPS |
state |
无 | GET /api/status + /api/capture_gps |
完整状态,含 GPS 坐标 |
5.2 云台
| 原语 | 输入 | 对应 HTTP | 说明 |
|---|---|---|---|
gimbal_velocity |
vpitch/vyaw/vroll/duration |
POST /api/gimbal {action,step} |
3DOF 角速度向量;vroll 忽略 |
gimbal_reset |
无 | POST /api/gimbal {action:"level"} |
云台回中 |
5.3 相机
| 原语 | 输入 | 对应 HTTP | 说明 |
|---|---|---|---|
camera_capture |
无 | POST /api/camera {action:"photo"} |
拍照 |
camera_video |
无 | GET /api/video |
返回视频流 URL(MJPEG,640px,12fps),调用方自行拉流 |
云台 / 相机接口仅巡航进行中可用(
cruiseActive == true)。
一个诚实的说明
move_velocity 和 gimbal_velocity 目前是「速度 → 位移/角度」的离散近似:算出 位移 = 速度 × 持续时间,再一次性下发,并不是真正的连续速度控制。真连续需要 APK 端补 /api/velocity(MSDK 虚拟摇杆 VirtualStickController)和 /api/gimbal/velocity(KeyGimbalSpeed),这是下一步的重点。
六、使用方式
打通之后,控制无人机有四种入口:
1. 网页控制台 —— 浏览器打开 RC Pro 内置仪表盘(http://<RC_Pro_IP>:8080)或项目里的增强版 dashboard.html,实时视频 + 遥测 + 三模式切换 + 航点巡航。
2. rbnx chat 对话控制 —— 理想形态:
1 | 你: 起飞 |
目前 drone_bridge 提供的是底层能力 API,把自然语言映射到能力调用的 skill 层还需要另行开发。
3. Python 脚本直接调 HTTP —— 最直接:
1 | import requests |
4. rbnx call 直接调原语 —— 我给 RoboNIX 加的子命令,绕开 LLM 直接命中一个原语,方便调试:
1 | rbnx call robonix/primitive/drone/takeoff --args '{"altitude":3.0}' |
七、部署流程(简述)
- RC Pro 开机连 WiFi,打开 APK,记下 Web 控制地址。
- WSL2 里确认
rbnx已装好。 - 把
drone_bridge拷到~/my-robot/primitives/。 - 在 manifest 里配置 RC Pro 的 IP。
bash scripts/build.sh(codegen 生成 MCP dataclass)+ 装依赖。cd ~/my-robot && rbnx boot,看到atlas / executor / soma / drone_bridge都起来。
八、端到端验证现状
rbnx call robonix/primitive/drone/state→ 返回[✓ state],链路 rbnx → executor → MCP → driver → HTTP 全通。rbnx call .../camera_video→ 返回{"success":true,"video_url":...},不依赖飞机连接也能正常返回。- 测试时
state内部出现过HTTP 502,是因为当时 RC Pro 没开机、连不上——属于硬件连通性,不是 RoboNIX 链路问题。
如实说:目前所有验证都还停留在软件 / 链路层面,还没有真正让飞机动起来。 实飞是下一步的关键验证。
九、踩过的坑
- executor 硬编码走 MCP:外部能力分发写死了
Transport::Mcp,所以原语必须@provider.mcp声明,否则rbnx call调不到。 mcp包版本要< 2:mcp 2.0 把fastmcp移掉了,装了 2.x 直接 import 报错,start.sh里固定成了mcp>=1.0,<2。- Windows 改代码要手动同步到 WSL:WSL 里的
~/my-robot/primitives/drone_bridge/不会自动更新,这个漏过好几次,导致 WSL 里跑的还是旧代码。 - 进程名是
robonix-*:只杀rbnx boot会留下孤儿组件占着 50051/50091 端口,重新 boot 就报「Address already in use」。 - WSL2 默认 NAT 网络:可能访问不到 RC Pro,最简单是从 Windows 侧跑 bridge(standalone 模式)。
十、待办与下一步
| 待办 | 说明 |
|---|---|
/api/land 端点 |
APK 侧还没实现原地降落,land 原语目前固定返回失败 |
/api/velocity |
真连续速度控制,升级 move_velocity |
/api/gimbal/velocity |
真连续云台,升级 gimbal_velocity |
| 电池/电压/航向遥测 | 当前 v4.0 /api/status 不返回这些字段 |
| 自然语言 Skill | 让 rbnx chat 能一句话控制 |
| 实飞验证 | 让飞机真正动起来 |
这条路的骨架已经搭起来了:RC Pro APK ✅ → HTTP API ✅ → MJPEG 视频 ✅ → drone_bridge ✅ → rbnx call ✅。剩下的是把「离散近似」换成「真连续控制」,以及走出软件层、做一次真正的实飞。后续每前进一点,我就回来记一笔。
