Aegis 四足机器人 SDK
Aegis(产品代号 D1)是 FF 四足机器狗产品线,覆盖点足、轮足、EDU、Pro/Ultra 多个机型。 一个自包含 wheel 即可控制行走、特技和全套遥测 —— 不需要安装任何额外厂商软件。
01概览与能力矩阵
所有能力调用都是 robot.<能力>.<动作>() 的统一形式。平台不支持的能力会
raise CapabilityNotSupported —— 明确报错,绝不假装成功。
| 能力域 | 方法 | 状态 | 说明 |
|---|---|---|---|
motion | cmd_vel() 速度控制 | ✅ live | 前进 / 横移 / 转向,真机验证 |
stand() / damping() | ✅ live | 站立 / 阻尼软急停 | |
do_preset() 特技 | ✅ live | 握手 / 跳跃 / 后空翻 / 双腿站立等,见 特技动作 | |
stop() | ✅ live | 停止移动 | |
state | battery() / status() | ✅ live | 电量、机器人姿态状态机 |
pose() 位姿 | ✅ live | 世界系位置 + 欧拉角 | |
joint_states() 关节遥测 | ✅ live | 点足 12 关节 / 轮足 16 关节,见 机型差异 | |
vision | frame() 取帧 | 🟡 部分 | 接口就绪,覆盖完善中 |
display | set_led() | 🟡 部分 | LED 灯效;四足无面屏,表情类接口不适用 |
navigation | goto() 等 | 🟡 部分 | 巡检导航栈对接中 |
audio | — | ⏳ 规划 | TTS / 播放规划中 |
arm / checkin | — | ❌ | 四足无机械臂;考勤不适用本形态 |
variant 自动加载。
02安装
devkit 的 wheels/ 目录提供两个架构的 Python 3.10 wheel:
| wheel | 装在哪 | 用途 |
|---|---|---|
ff_sdk-0.1.0a0-cp310-cp310-linux_aarch64.whl | 机器人本体 | 程序跑在机器人上(推荐,延迟最低) |
ff_sdk-0.1.0a0-cp310-cp310-linux_x86_64.whl | Linux 开发机 | 远程控制 / 开发调试 |
# 在机器人上(aarch64)
pip install wheels/ff_sdk-0.1.0a0-cp310-cp310-linux_aarch64.whl
# 在 Linux 开发机上(x86_64)
pip install wheels/ff_sdk-0.1.0a0-cp310-cp310-linux_x86_64.whl
# 验证
python -c "import ff_sdk; print(ff_sdk.__version__)"
03快速开始
第 1 步 · 不需要真机:dry-run
设置 FF_SDK_DRY_RUN=1 后,SDK 跳过所有真实底层调用,每个 API 返回合理的占位结果 ——
用来熟悉 API、验证业务逻辑:
FF_SDK_DRY_RUN=1 python examples/01_hello_connect.py
第 2 步 · 连接真机
import asyncio, ff_sdk
async def main():
dog = await ff_sdk.connect("D1-DEMO")
try:
report = dog.diagnose() # 先体检
print(report)
await dog.motion.stand() # 站立
await asyncio.sleep(4)
await dog.motion.cmd_vel(linear=0.3) # 前进 0.3 m/s
await asyncio.sleep(2)
await dog.motion.stop()
battery = await dog.state.battery()
print(f"电量 {battery.percent:.0%}")
await dog.motion.do_preset("shake_hand") # 握手特技
await asyncio.sleep(dog.motion.preset_timeout("shake_hand"))
await dog.motion.damping() # 收尾:阻尼(软急停)
finally:
await dog.close()
asyncio.run(main())
backflip 后空翻)要求四周 2m 空旷 + 满电。任何异常立即
await dog.e_stop() 或物理按下急停。收尾习惯性调用 damping()。
04连接与配置
connect()
target 用 D1-<序列号> 形式标识你的机器人;仿真用 mujoco://d1。
网络模式
| 模式 | 怎么连 | host 填什么 |
|---|---|---|
| 热点直连(默认) | 电脑连机器人自带 WiFi 热点 | 不用填(默认热点网关) |
| 以太网 / 局域网 | 机器人接入你的路由器 | FF_SDK_D1_HOST=<robot-ip> |
各型号热点名称 / 密码见机身标签或随机说明书。
环境变量
| 变量 | 默认 | 说明 |
|---|---|---|
FF_SDK_D1_HOST | 热点网关 | 机器人 IP(局域网模式必填) |
FF_SDK_D1_VARIANT | zsl-1w | 机型变体:zsl-1 点足 / zsl-1w 轮足,见 机型适配 |
FF_SDK_D1_FEEDBACK_PORT | 8080 | 遥测反馈监听端口 |
FF_SDK_DRY_RUN | 关 | 设 1 进入干跑模式 |
FF_SDK_TRANSPORT_TIMEOUT | 5.0 | 单次操作超时(秒) |
FF_SDK_LOG_DIR | /var/log/ff_sdk | 日志目录 |
Config 对象
import ff_sdk
from ff_sdk import Config
# 方式 1:全用默认 / 环境变量
dog = await ff_sdk.connect("D1-DEMO")
# 方式 2:显式 Config(平台特定项放 extra)
cfg = Config.from_env()
cfg.extra["d1_host"] = "192.168.1.100"
cfg.extra["d1_variant"] = "zsl-1"
dog = await ff_sdk.connect("D1-DEMO", config=cfg)
# 方式 3:纯代码构造
cfg = Config(transport_timeout=5.0, dry_run=False,
extra={"d1_variant": "zsl-1"})
dog = await ff_sdk.connect("D1-DEMO", config=cfg)
05Session 与生命周期
connect() 返回的 Session 是你与机器人的全部交互入口:
| 成员 | 类型 | 说明 |
|---|---|---|
session.motion / .state / … | 能力访问器 | 不支持时 raise CapabilityNotSupported |
session.capabilities() | set[str] | 这台机器人支持的能力域名集合 |
session.diagnose() | DiagnosticReport | 同步健康体检:各链路在线状态 |
await session.e_stop(reason) | — | 紧急停止,之后的动作调用会被拒绝 |
session.session_state | 枚举 | IDLE / CONNECTING / CONNECTED / DEGRADED / ESTOPPED / DISCONNECTED / FAULT |
session.uptime | float | 会话建立以来的秒数 |
await session.close() | — | 断开连接、释放资源 |
推荐写法:async with
async with await ff_sdk.connect("D1-DEMO") as dog:
await dog.motion.stand()
...
# 离开 with 块自动 close(),异常也不会泄漏连接
print(dog.capabilities())
# {'motion', 'state', ...}
if "motion" in dog.capabilities():
await dog.motion.stand()
06motion · 运动控制
速度控制
| 参数 | 单位 | 含义 |
|---|---|---|
linear | m/s | 前进(负值后退) |
angular | rad/s | 偏航转向(正值左转) |
lateral | m/s | 横向移动 |
cmd_vel 是速度指令而不是位移指令。让机器人持续行走 = 周期性重发指令;
停下 = await motion.stop()。安全做法见示例 cookbook/safety_watchdog.py。
姿态控制
| 方法 | 说明 |
|---|---|
await motion.stand() | 站立(约 4s) |
await motion.damping() | 阻尼模式 —— 关节松软的“软急停”,推荐收尾必调 |
await motion.stop() | 停止移动(保持站立) |
await motion.cmd_twist(twist) | cmd_vel 的 Twist 数据类形式 |
await motion.current_pose() | 当前位姿(Pose) |
关节级接口
| 方法 | 说明 |
|---|---|
await motion.read_joint_state() | 读取当前关节位置 / 速度 / 力矩字典 |
motion.joint_stream(q_func, rate_hz=50.0, …) | 高频关节流:按 q_func(t) 周期下发目标关节位置(进阶,注意安全) |
07特技动作
通过 motion.do_preset(name) 调用;motion.known_presets()
可在运行时列出当前机型支持的全部动作。
| name | 动作 | 预计耗时 | 注意 |
|---|---|---|---|
stand / stand_up | 站立 | ~4s | |
lie_down | 趴下 | ~3s | |
damping / passive | 阻尼(软急停) | ~1s | 推荐收尾必调 |
shake_hand | 握手 | ~10s | 全程别打断 |
jump | 原地跳 | ~4s | 上方留空间 |
front_jump | 前跳 | ~4s | 前方留 1m |
backflip | 后空翻 | ~5s | ⚠️ 四周 2m 空旷 + 满电 |
two_leg_stand | 双腿站立 | ~4s | 配合 cancel_two_leg_stand 恢复 |
recover | 摔倒恢复 | ~3s |
res = await dog.motion.do_preset("shake_hand")
# 用建议时长等动作做完,再发下一条指令
await asyncio.sleep(dog.motion.preset_timeout("shake_hand"))
print(dog.motion.known_presets()) # 当前机型支持的全部动作名
08state · 状态遥测
| 方法 | 返回 | 说明 |
|---|---|---|
await state.battery() | BatteryState | percent(0–1) / voltage / is_charging |
await state.status() | RobotStatus | IDLE / STANDING / MOVING / LYING / DAMPING / CHARGING / ESTOPPED / FAULT … |
await state.pose() | Pose | 世界系 x,y,z(米)+ roll,pitch,yaw(弧度) |
await state.joint_states() | JointStates | names / positions / velocities / efforts,点足 12 关节、轮足 16 关节 |
from ff_sdk.core.exceptions import CapabilityNotSupported
try:
joints = await dog.state.joint_states()
print(f"{len(joints.names)} 个关节")
for name, pos in zip(joints.names, joints.positions):
print(f" {name}: {pos:+.3f} rad")
except CapabilityNotSupported as e:
# 部分轮足已出厂固件不支持关节遥测(运动控制不受影响)
print(f"该机型/固件不支持关节遥测: {e}")
状态轮询节奏
examples/state/watch_status.py 的节流写法。
09其他能力
vision(🟡 部分)
取单帧 / 持续取流。CameraFrame 含 data(bytes) / width / height / encoding。接口就绪,机型覆盖完善中。
display(🟡 LED)
四足无面屏,show_expression 等表情类接口在本平台 raise CapabilityNotSupported。
navigation(🟡 部分)
巡检导航栈对接中;可用性以 session.capabilities() 运行时返回为准。
10机型适配(variant)
Aegis 产品线有多个型号,对开发者来说 API 完全一样,只需选对一个
variant 参数。
我手上是哪台?
| 看什么 | 点足 | 轮足 / 轮狗 |
|---|---|---|
| 足端 | 4 个橡胶脚垫 | 4 个驱动轮 |
| 移动方式 | 迈步行走 | 轮式滑行 + 迈步混合 |
| 关节数 | 12(每腿 3 个) | 16(每腿 3 个 + 轮) |
| 产品型号 | 形态 | variant | 适配状态 |
|---|---|---|---|
| 标准版(点足批次) | 点足 | zsl-1 | ✅ 真机验证(站立 / 行走 / 特技 / 全遥测) |
| 标准版(轮足批次) | 轮足 | zsl-1w | ✅ 真机验证(运动 + 状态遥测) |
| EDU 版(教育版) | 点足 | zsl-1 | 🟡 已适配,与点足同一控制路径,待回归测试 |
| Pro / Ultra | 点足 | zsl-1 | 🟡 已适配,待回归测试 |
variant 怎么填(三选一)
# 方式 1:环境变量(推荐,不改代码)
export FF_SDK_D1_VARIANT=zsl-1 # 点足 / EDU / Ultra
export FF_SDK_D1_VARIANT=zsl-1w # 轮足(不设时的默认值)
cfg = Config.from_env()
cfg.extra["d1_variant"] = "zsl-1"
dog = await ff_sdk.connect("D1-DEMO", config=cfg)
session.diagnose()
会明确告诉你哪条链路没起来 —— 不会损坏机器人。
11部署到机器人
| 部署方式 | 说明 | 推荐度 |
|---|---|---|
| 跑在机器人上 | 程序 scp 到机器人,本机回环控制,延迟最低 | ★★★ 推荐 |
| 跑在 Linux 开发机 | 开发机连机器人热点,远程控制 | ★★(进阶配置,联系支持) |
| 跑在 Windows / Mac | 仅 dry-run(底层运动库是 Linux 库) | ★ 学习 / 写代码用 |
程序上机、开机自启(systemd)与升级流程详见 devkit 内 docs/deployment.md。
C++ 开发者请看 devkit 的 cpp/README.md(头文件 + 双架构预编译库 + 示例)。
12跨平台 Skills
ff_sdk.skills.* 是写一次、所有平台都能跑的高层动作 ——
内部自动按平台选择最合适的实现:
from ff_sdk import skills
result = await skills.wave(dog) # Aegis 上自动映射为握手
result = await skills.bow(dog) # 自动映射为点头
result = await skills.greet(dog, "朋友") # 招手 + (支持语音的平台)打招呼
print(result) # {"ok": True, "message": "...", "platform": "..."}
跨机器人代码应优先用 skills;平台专属细节才直接调 motion.do_preset。
13异常与诊断
异常层级
| 异常 | 什么时候抛 |
|---|---|
FfSdkError | 所有 SDK 异常的根类 |
ConfigError | 配置无效或不完整 |
ConnectionError | 无法建立 / 失去连接 |
TransportError | 线路级故障(socket / RPC 超时) |
TimeoutError | 操作超过截止时间 |
PlatformError | 平台适配层翻译的底层错误 |
CapabilityNotSupported | 该平台 / 机型 / 固件不支持此能力 |
EStopActiveError | 紧急停止激活中,动作被拒绝 |
StateError | 当前状态不允许该操作(充电 / OTA / 故障中) |
import ff_sdk
from ff_sdk.core.exceptions import (
CapabilityNotSupported, EStopActiveError, StateError)
try:
await dog.motion.stand()
except CapabilityNotSupported as e:
print(f"此机型不支持: {e}")
except EStopActiveError:
print("急停激活中,请先排除险情再复位")
except StateError as e:
print(f"当前状态不允许: {e}") # 例如正在充电
diagnose():先体检,再动作
report = dog.diagnose()
print(report)
# 各链路(控制通道 / 遥测通道 / 运动后端)在线状态一目了然
# 排错第一步永远是看这个,而不是猜
14示例索引
devkit 的 examples/ 全部可直接运行(先 dry-run 后真机):
| 示例 | 内容 |
|---|---|
01_hello_connect.py | 第一次连接 + 诊断 + 紧急停止 |
02_diagnose.py | 体检报告详解 |
03_estop.py | 紧急停止 + 回调 + 重置 |
d1/udp_walk.py | 完整行走演示(站立 → 前进 → 转向 → 阻尼) |
d1/presets_and_telemetry.py | 机型选择 + 特技 + 关节遥测 |
motion/cmd_vel.py / stand_damping.py / do_preset.py | 运动控制三件套 |
state/read_battery.py / watch_status.py | 电量 / 状态监听 |
cookbook/safety_watchdog.py | 安全看门狗(强烈推荐先读) |
cookbook/multi_robot.py | 多机器人并发控制 |
cookbook/record_trajectory.py | 轨迹记录 |
cookbook/sim_to_real.py | 仿真到真机迁移 |
15FAQ / 排错
| 现象 | 可能原因 | 解决 |
|---|---|---|
diagnose 显示运动后端 offline | variant 填错(点足机器填了轮足) | 按 机型表 换 variant 重连 |
| 站立指令发了没反应 | 机器人还在阻尼 / 急停状态 | 先 do_preset("stand"),看 state.status() |
轮足 joint_states 报错 | 已出厂固件限制 | 用 try/except CapabilityNotSupported 兼容写法 |
| 连不上机器人 | 没连到机器人热点 / host 填错 | 确认 WiFi;局域网模式设 FF_SDK_D1_HOST |
| 指令偶尔丢 | WiFi 链路抖动 | 程序跑到机器人本体上(本机回环最稳) |