# 包结构与数据流 ## 仓库分层 本仓库同时提供 Python SDK 和独立 C++ SDK,两者按构建系统和公共入口区分: | 层 | Python | C++ | |---|---|---| | 公共 API | `go1_pro_sdk/`、`robot_interface.py` | `include/unitree_legged_sdk/` | | 私有实现 | Python package 子模块 | `src/` | | 构建入口 | `pyproject.toml` | `CMakeLists.txt` | | 示例 | `examples/*.py` | `examples/cpp/*.cpp` | | 测试 | `tests/*.py` | `tests/cpp/` | `fast_lowcmd_cpp/` 属于 Python 侧:它生成 CPython extension,用来加速 Python 的命令 编解码和状态解析。它不提供 C++ 公共头文件,也不应被 C++ 应用直接链接。 ## Python 架构 ### 模块依赖图 ``` ┌──────────────────────┐ │ MCUClient │ ← 用户主要 API │ (connection/) │ └──────┬───────────────┘ │ ┌──────────────┼──────────────┐ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ codec/ │ │ types/ │ │ safety/ │ │ Blowfish │ │ LowCmd │ │ apply_ │ │ build_* │ │ LowState │ │ safety │ │ parse_* │ │ MotorCmd │ │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │ │ └────────────────┼────────────────┘ ▼ ┌─────────────┐ │ utils/ │ │ common.py │ ← CRC, float_hex │ constants │ ← 关节限位, 默认地址 └─────────────┘ ``` ### 数据流: 收一帧 → 用户处理 → 发命令 ``` UDP 858B 密文 UDP 616B 密文 ▲ │ │ ▼ MCU :8007 MCU :8007 │ ▲ ▼ │ ┌─────────────────────────────────────────────────┐ │ MCUClient.recv_latest() │ │ socket.recvfrom() │ │ bf.decrypt_ecb(data[:856]) → 856B 明文 │ │ parse_low_state(...) → LowState 结构 │ └─────────────────────────────────────────────────┘ │ ▼ ┌──────────┐ 用户逻辑 ┌──────────┐ │ LowState │ ──────────► │ LowCmd │ └──────────┘ qDes, Kp, └──────────┘ Kd, tau... │ ▼ ┌─────────────────────────────────────────────────┐ │ apply_safety(cmd, state, power_factor=1) │ │ position_limit(cmd) │ │ power_protect(cmd, state, factor) │ │ position_protect(cmd, state, limit_rad) │ └─────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────┐ │ MCUClient.send(cmd) │ │ build_low_cmd_plain(cmd) → 616B 明文 │ │ bf.encrypt_ecb(plain) → 616B 密文 │ │ sock.sendto(cipher, ...) │ └─────────────────────────────────────────────────┘ ``` ### 各包职责 #### utils/ 最底层。纯函数, 无副作用, 无依赖其他模块。 - `common.py`: CRC, float↔hex, tau↔2B, Kp↔2B, Kd↔2B, decode_sn/version - `constants.py`: MCU 地址, 关节命名, 限位, TAU_MAX, DAMPING_POSE #### types/ 数据结构 (dataclass)。依赖 utils, 不依赖 codec/safety/connection。 - `motor.py`: MotorCmd, MotorState, MotorMode - `imu.py`: IMU - `bms.py`: BMS - `remote.py`: RemoteState, parse_remote - `low_cmd.py`: LowCmd (12 motorCmd + 元数据) - `low_state.py`: LowState (12 motorState + IMU + BMS + remote 等) #### codec/ 加解密和序列化。依赖 types + utils。 - `blowfish.py`: 标准 Blowfish ECB (LE 字节序), 接受预生成 state - `lowcmd_builder.py`: LowCmd → 616B 明文 → 加密后 616B - `lowstate_parser.py`: 解密后 807B → LowState 结构 #### safety/ 控制保护层。依赖 types + utils。 - `safety.py`: PositionLimit/PowerProtect/PositionProtect 三个保护 + 统一入口 apply_safety #### connection/ UDP 高层抽象。依赖前面所有。 - `mcu_client.py`: MCUClient (socket + Blowfish + 序列化 + safe_stop) ### 用户三种用法 #### Level 1: 高层 (推荐) ```python from go1_pro_sdk import MCUClient, LowCmd, MotorCmd, MotorMode with MCUClient() as client: client.wake_mcu() state = client.recv_state() cmd = LowCmd() cmd.set_motor('FR_1', MotorCmd(mode=MotorMode.Servo, q=1.2, Kp=5, Kd=1)) client.send(cmd) client.safe_stop() ``` #### Level 2: 中层 (自己管 socket, 用编解码) ```python from go1_pro_sdk import Blowfish, build_low_cmd_encrypted, parse_low_state, LowCmd import socket bf = Blowfish.from_state_file('go1_pro_sdk/_data/blowfish_state.bin') sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(('', 0)) cmd = LowCmd() sock.sendto(build_low_cmd_encrypted(cmd, bf), ('192.168.123.10', 8007)) data, _ = sock.recvfrom(2048) state = parse_low_state(bf.decrypt_ecb(data[:856])) ``` #### Level 3: 底层 (诊断/逆向) 直接用 `Blowfish.encrypt_block(b8)` / `Blowfish.decrypt_block(b8)`, 自己处理 8B 块。 适合协议研究或字节级 diff。 ## C++ 架构 ```text 应用源码 #include │ ▼ include/unitree_legged_sdk/ 公共、官方兼容声明 comm.h / udp.h / safety.h / loop.h / quadruped.h │ ▼ src/ udp.cpp POSIX UDP、线程安全收发、官方方法适配 safety.cpp PositionLimit/PowerProtect/PositionProtect loop.cpp Loop/LoopFunc 调度和 Linux CPU affinity pro_codec.cpp 616B LowCmd、858B LowState、CRC、Blowfish quadruped.cpp 版本、长度常量和 InitEnvironment ``` `src/pro_codec.h` 是库内部头文件,不安装给用户。C++ 应用只能包含 `include/unitree_legged_sdk/` 下的头文件,这保证业务源码切换到官方 SDK 时不依赖 PRO 专有声明。PRO 的加密和私有线协议全部封装在 `UDP` 实现内部。 CMake 对外提供: - 构建树目标:`unitree_legged_sdk`; - namespaced alias:`unitree_legged_sdk::unitree_legged_sdk`; - 安装后的 `find_package(unitree_legged_sdk CONFIG REQUIRED)`; - 安装目录中的公共头文件、静态库、CMake config 和 Blowfish state。 ## 共享边界 Python 与 C++ 没有运行时语言绑定关系,也不会互相调用。它们共享的是协议规格、实机 抓包回归基准和 Blowfish state。修改协议实现时必须同时运行: ```bash conda run -n free_dog_sdk python -m pytest -q tests fast_lowcmd_cpp/test_fast_lowcmd.py cmake -S . -B build-cpp -DCMAKE_BUILD_TYPE=Release cmake --build build-cpp ctest --test-dir build-cpp --output-on-failure ```