cpp对齐官方

This commit is contained in:
cyy_mac
2026-07-30 15:25:48 +08:00
parent dbfcb95566
commit f8b849397d
36 changed files with 2561 additions and 122 deletions

View File

@@ -14,6 +14,10 @@
导入和主要调用流程,同时底层会使用 Go1 PRO 所需的 Blowfish 加密和 616 字节
私有 `LowCmd` 协议。
反过来,要让本项目编写的程序直接在官方 SDK 上复现,应用必须导入
`robot_interface`,并限制在官方 wrapper 真正导出的公共子集内。应用不应直接导入
`go1_pro_sdk`
## 接口矩阵
| 官方接口 | 本项目原接口 | 当前兼容状态 |
@@ -29,8 +33,8 @@
| `Safety.PowerProtect` | `power_protect` | 调用兼容,算法不是官方闭源实现 |
| `Safety.PositionProtect` | `position_protect` | 调用兼容,保护动作更保守 |
| `HighCmd/HighState` | MQTT `Go1/Go1MQTT` | 类型已提供UDP 传输不支持 |
| `Loop/LoopFunc` | 无 | 官方 Python wrapper 本身未导出 |
| C++ headers/static library | 无 | 不兼容 C++ 源码 ABI |
| `Loop/LoopFunc` | 无 | C++ 已提供;官方 Python wrapper 本身未导出 |
| C++ headers/static library | 无 | 低层 C++ 源码兼容;不承诺二进制 ABI |
## 关键协议差异
@@ -49,7 +53,10 @@ EDU SDK 相同。
```python
import robot_interface as sdk
udp = sdk.UDP(sdk.LOWLEVEL, 8080, "192.168.123.10", 8007)
LOWLEVEL = 0xff
FR_1 = 1
udp = sdk.UDP(LOWLEVEL, 8080, "192.168.123.10", 8007)
safe = sdk.Safety(sdk.LeggedType.Go1)
cmd = sdk.LowCmd()
state = sdk.LowState()
@@ -58,16 +65,84 @@ udp.InitCmdData(cmd)
udp.Recv()
udp.GetRecv(state)
cmd.motorCmd[sdk.FR_1].q = 1.2
cmd.motorCmd[sdk.FR_1].dq = 0.0
cmd.motorCmd[sdk.FR_1].Kp = 5.0
cmd.motorCmd[sdk.FR_1].Kd = 1.0
cmd.motorCmd[FR_1].q = 1.2
cmd.motorCmd[FR_1].dq = 0.0
cmd.motorCmd[FR_1].Kp = 5.0
cmd.motorCmd[FR_1].Kd = 1.0
safe.PositionLimit(cmd)
safe.PowerProtect(cmd, state, 1)
udp.SetSend(cmd)
udp.Send()
```
这里故意不使用 `sdk.LOWLEVEL``sdk.FR_1`、上下文管理器或 `close()`:这些是本项目
提供的便利能力,但不属于官方 Python wrapper 的导出契约。
## C++ 同源码用法
C++ 公共入口、命名空间、结构字段和低层方法签名与官方 v3.8.6 对齐:
```cpp
#include "unitree_legged_sdk/unitree_legged_sdk.h"
using namespace UNITREE_LEGGED_SDK;
UDP udp(LOWLEVEL, 8090, "192.168.123.10", 8007);
Safety safe(LeggedType::Go1);
LowCmd cmd{};
LowState state{};
udp.InitCmdData(cmd);
```
业务源码和 `#include` 不变只切换链接库。PRO 端用本项目 CMake 目标
`unitree_legged_sdk`,官方 Go1 端用官方仓库的 `libunitree_legged_sdk.a`。本项目已经用
官方头文件反向编译可移植示例,并用本项目头文件编译官方仓库的五个 C++ 示例。
本项目构建方法:
```bash
cmake -S . -B build-cpp -DCMAKE_BUILD_TYPE=Release
cmake --build build-cpp
ctest --test-dir build-cpp --output-on-failure
```
标准四参数 `UDP(LOWLEVEL, ...)` 会在库内部完成 PRO 编解码。默认从安装数据目录读取
Blowfish state需要覆盖时设置 `GO1_PRO_BLOWFISH_STATE=/path/to/blowfish_state.bin`
## 可移植程序规则
要求同一份源码直接运行时,主控制流程只使用:
- `import robot_interface as sdk`
- `sdk.UDP``sdk.Safety``sdk.LeggedType`
- `sdk.LowCmd/LowState``MotorCmd/MotorState``IMU/BmsState`
- `InitCmdData/Recv/GetRecv/SetSend/Send`
- 官方结构中公开的字段,例如 `motorCmd[i].q``motorState[i].q`
所有官方结构对象都应先无参构造,再逐字段赋值。例如使用
`motor = sdk.MotorCmd(); motor.q = 1.0`,不要写 `sdk.MotorCmd(q=1.0)`。后者是 Python
dataclass 常见写法,但官方 pybind wrapper 不接受构造参数。
枚举也按官方对象使用,例如 `sdk.Safety(sdk.LeggedType.Go1)`。不要把枚举当作整数比较
或直接写 `sdk.Safety(2)`;本项目的严格兼容入口会和官方一样拒绝后一种写法。
以下接口属于 PRO 扩展,使用后程序不再能在只安装官方 SDK 的环境中直接运行:
- `from go1_pro_sdk import ...`
- `MCUClient``Go1``Go1MQTT`
- `LowCmd.set_motor()``all_damping()`
- `LowState.remote``apply_safety()`
- `wake_mcu()``safe_stop()`、Blowfish 和快速 C++ builder。
推荐把程序分为“官方公共控制核心”和“可选 PRO 增强”两个模块。公共核心不能导入
增强模块;增强模块可以包装公共核心,但必须允许在官方环境中完全不加载。
`Send()``Recv()``SetSend()` 的具体正整数来自线协议和底层 socket不属于跨
SDK 稳定契约。初始化时可以用 `Recv() > 0` 判断是否收到包,但不应比较具体字节数。
首次进入 PRO 低层通道前,应先反复发送 `InitCmdData()` 产生的 stop sentinel并在
收到第一帧 `LowState` 后再写入有效位置目标。可移植示例已采用这一时序,避免在状态
仍为全零默认值时直接驱动关节。
`UDP(HIGHLEVEL, ..., "192.168.123.161", 8082)` 不会被静默映射到 MQTT。两种通道
状态模型和时序不同,兼容层会明确抛出 `NotImplementedError`。高层控制继续使用
`Go1``Go1MQTT`
@@ -85,5 +160,10 @@ udp.Send()
类型不保证完全相同。
- 本项目 `LowState` 是 PRO 抓包格式的解释,不应按官方 `#pragma pack(1)` 结构大小
直接做内存映射。
- 官方 C++ 用户需要单独的 C++ facade 和库链接方案Python 兼容模块不能让现有
C++ 程序直接重编译通过。
- C++ 类型布局和公开符号用于源码重编译兼容,不保证本项目库与官方预编译对象之间
的 ABI 互换;切换实现时应重新编译应用。
- 两个自定义包长 C++ `UDP` 构造函数和 `SetSend(char*)` 提供原始 UDP 透传,但不会
自动把任意自定义结构转换为 PRO 私有协议;主动断连时间和 accessible 时间参数
仅保留调用形状。Python 兼容入口仍只保证标准四参数 `LOWLEVEL` 通道。
- 官方 SDK 和本项目都提供顶层 `robot_interface`,同一个 Python 环境不要同时安装
两种实现。应在 PRO 环境安装本项目,在官方机器人环境安装官方 SDK。