FF SDKAegis Docs v0.1.0a2
Quadruped Platform
Quadruped Platform · 四足

Aegis Quadruped Robot SDK

Aegis 四足机器人 SDK

Aegis (product codename D1) is FF's quadruped robot-dog lineup, covering point-foot, wheeled-foot, EDU, and Pro/Ultra variants. A single self-contained wheel controls walking, stunts, and the full telemetry suite — with no extra vendor software to install.

Aegis(产品代号 D1)是 FF 四足机器狗产品线,覆盖点足、轮足、EDU、Pro/Ultra 多个机型。 一个自包含 wheel 即可控制行走、特技和全套遥测 —— 不需要安装任何额外厂商软件。

target: D1-<sn> Python ≥ 3.10 aarch64 / x86_64 Includes C++ SDK含 C++ SDK

01Overview & capability matrix概览与能力矩阵

Every capability call follows the uniform form robot.<capability>.<action>(). A capability the platform doesn't support will raise CapabilityNotSupported — an explicit error, never a faked success.

所有能力调用都是 robot.<能力>.<动作>() 的统一形式。平台不支持的能力会 raise CapabilityNotSupported —— 明确报错,绝不假装成功。

Capability能力域 Method方法 Status状态 Notes说明
motioncmd_vel() Velocity control速度控制✅ liveForward / strafe / turn, hardware-verified前进 / 横移 / 转向,真机验证
stand() / damping()✅ liveStand / damping soft e-stop站立 / 阻尼软急停
do_preset() Stunt特技✅ liveShake hand / jump / backflip / two-leg stand, etc., see Stunt actions握手 / 跳跃 / 后空翻 / 双腿站立等,见 特技动作
stop()✅ liveStop moving停止移动
attitude_control() In-place attitude原地姿态✅ liveQuadruped-only: in-place pitch / yaw / roll / stance height, see Motion control四足专属:原地俯仰 / 转头 / 侧倾 / 站高,见 运动控制
statebattery() / status()✅ liveBattery, robot posture state machine电量、机器人姿态状态机
pose() Pose位姿✅ liveWorld-frame position + Euler angles世界系位置 + 欧拉角
joint_states() Joint telemetry关节遥测✅ live12 joints point-foot / 16 joints wheeled-foot, see variant differences点足 12 关节 / 轮足 16 关节,见 机型差异
get_imu()✅ liveFull IMU — quaternion + rpy + body angular velocity + body linear acceleration (via vendor SDK backend)完整 IMU —— 四元数 + rpy + 机体角速度 + 机体线加速度(经厂商 SDK 后端)
get_body_state()✅ liveCenter-of-mass position + rpy + body/world velocity (CoM position also via pose())重心位置 + rpy + 机体/世界速度(重心位置也可经 pose()
visionframe() Grab frame取帧🟡 partial🟡 部分Interface ready, coverage in progress接口就绪,覆盖完善中
displayset_led()🟡 partial🟡 部分LED effects; quadruped has no face screen, expression interfaces N/ALED 灯效;四足无面屏,表情类接口不适用
navigationgoto() etc.🟡 partial🟡 部分Patrol navigation stack integration in progress巡检导航栈对接中
audio⏳ planned⏳ 规划TTS / playback plannedTTS / 播放规划中
arm / checkinQuadruped has no arm; check-in N/A for this form factor四足无机械臂;考勤不适用本形态
Self-contained distribution The low-level motion library needed to control the robot is packaged inside the wheel. No separate vendor SDK to install, no extra configuration on the robot. Both the point-foot and wheeled-foot low-level bindings are built in and loaded automatically by variant.
自包含分发 机器人控制所需的底层运动库已打包在 wheel 内部,不需要单独安装任何厂商 SDK、 不需要在机器人上做任何额外配置。点足和轮足两套底层 binding 同时内置,按 variant 自动加载。

02Installation安装

The devkit's wheels/ directory ships Python 3.10 wheels for two architectures:

devkit 的 wheels/ 目录提供两个架构的 Python 3.10 wheel:

wheel Install on装在哪 Purpose用途
ff_sdk-0.1.0a2-cp310-cp310-linux_aarch64.whlThe robot itself机器人本体Program runs on the robot (recommended, lowest latency)程序跑在机器人上(推荐,延迟最低)
ff_sdk-0.1.0a2-cp310-cp310-linux_x86_64.whlLinux dev machineLinux 开发机Remote control / development & debugging远程控制 / 开发调试
shell — install
# On the robot (aarch64)
pip install wheels/ff_sdk-0.1.0a2-cp310-cp310-linux_aarch64.whl

# On the Linux dev machine (x86_64)
pip install wheels/ff_sdk-0.1.0a2-cp310-cp310-linux_x86_64.whl

# verify
python -c "import ff_sdk; print(ff_sdk.__version__)"
shell — 安装
# 在机器人上(aarch64)
pip install wheels/ff_sdk-0.1.0a2-cp310-cp310-linux_aarch64.whl

# 在 Linux 开发机上(x86_64)
pip install wheels/ff_sdk-0.1.0a2-cp310-cp310-linux_x86_64.whl

# 验证
python -c "import ff_sdk; print(ff_sdk.__version__)"
Windows / macOS The low-level motion library is a Linux library, so on Windows / macOS only dry-run mode is supported (learn the API, write code, run unit tests). For real-robot control, run on the robot itself or a Linux dev machine.
Windows / macOS 底层运动库为 Linux 库,Windows / macOS 上仅支持 dry-run 模式(学习 API、写代码、跑单测)。 真机控制请在机器人本体或 Linux 开发机上运行。

03Quickstart快速开始

Step 1 · No robot needed: dry-run

第 1 步 · 不需要真机:dry-run

With FF_SDK_DRY_RUN=1 set, the SDK skips all real low-level calls and every API returns a sensible placeholder result — useful for getting familiar with the API and validating your business logic:

设置 FF_SDK_DRY_RUN=1 后,SDK 跳过所有真实底层调用,每个 API 返回合理的占位结果 —— 用来熟悉 API、验证业务逻辑:

shell
FF_SDK_DRY_RUN=1 python examples/01_hello_connect.py

Step 2 · Connect to a real robot

第 2 步 · 连接真机

hello_aegis.py
import asyncio, ff_sdk

async def main():
    dog = await ff_sdk.connect("D1-DEMO")
    try:
        report = dog.diagnose()                      # health check first
        print(report)

        await dog.motion.stand()                     # stand up
        await asyncio.sleep(4)

        await dog.motion.cmd_vel(linear=0.3)         # move forward 0.3 m/s
        await asyncio.sleep(2)
        await dog.motion.stop()

        battery = await dog.state.battery()
        print(f"battery {battery.percent:.0%}")

        await dog.motion.do_preset("shake_hand")     # shake-hand stunt
        await asyncio.sleep(dog.motion.preset_timeout("shake_hand"))

        await dog.motion.damping()                   # finish: damping (soft e-stop)
    finally:
        await dog.close()

asyncio.run(main())
hello_aegis.py
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())
Safety notes For the first real run, place the robot on 1m of clear, flat, non-slip floor on all sides; stunts (especially backflip) require 2m clearance all around + a full battery. On any anomaly, immediately call await dog.e_stop() or physically press the e-stop. Make it a habit to finish with damping().
安全须知 首次跑真机请把机器人放在四周 1m 空旷、平整防滑的地面;特技(尤其 backflip 后空翻)要求四周 2m 空旷 + 满电。任何异常立即 await dog.e_stop() 或物理按下急停。收尾习惯性调用 damping()

04Connect & configure连接与配置

connect()

async ff_sdk.connect(target: str, *, config: Config | None = None, identity: Identity | None = None) -> Session

target identifies your robot in the form D1-<serial>; for simulation use mujoco://d1.

targetD1-<序列号> 形式标识你的机器人;仿真用 mujoco://d1

Network modes

网络模式

Mode模式 How to connect怎么连 What to put in hosthost 填什么
Hotspot direct热点直连 (default)(默认)Connect your computer to the robot's built-in WiFi hotspot电脑连机器人自带 WiFi 热点Leave blank (default hotspot gateway)不用填(默认热点网关)
Ethernet / LAN以太网 / 局域网Robot joins your router机器人接入你的路由器FF_SDK_D1_HOST=<robot-ip>

The hotspot name / password for each model is on the body label or in the included manual.

各型号热点名称 / 密码见机身标签或随机说明书。

Environment variables

环境变量

Variable变量 Default默认 Notes说明
FF_SDK_D1_HOSTHotspot gateway热点网关Robot IP (required in LAN mode)机器人 IP(局域网模式必填)
FF_SDK_D1_VARIANTzsl-1wVariant: zsl-1 point-foot / zsl-1w wheeled-foot, see Variant adaptation机型变体:zsl-1 点足 / zsl-1w 轮足,见 机型适配
FF_SDK_D1_FEEDBACK_PORT8080Telemetry feedback listen port遥测反馈监听端口
FF_SDK_DRY_RUNOffSet to 1 to enter dry-run mode1 进入干跑模式
FF_SDK_TRANSPORT_TIMEOUT5.0Per-operation timeout (seconds)单次操作超时(秒)
FF_SDK_LOG_DIR/var/log/ff_sdkLog directory日志目录

Config object

Config 对象

python — three ways to configure
import ff_sdk
from ff_sdk import Config

# Option 1: all defaults / env vars
dog = await ff_sdk.connect("D1-DEMO")

# Option 2: explicit Config (platform-specific items go in 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)

# Option 3: pure-code construction
cfg = Config(transport_timeout=5.0, dry_run=False,
             extra={"d1_variant": "zsl-1"})
dog = await ff_sdk.connect("D1-DEMO", config=cfg)
python — 三种配置方式
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 & lifecycleSession 与生命周期

The Session returned by connect() is your single entry point for all interaction with the robot:

connect() 返回的 Session 是你与机器人的全部交互入口:

Member成员 Type类型 Notes说明
session.motion / .state / …Capability accessor能力访问器Raises CapabilityNotSupported when unsupported不支持时 raise CapabilityNotSupported
session.capabilities()set[str]Set of capability-domain names this robot supports这台机器人支持的能力域名集合
session.diagnose()DiagnosticReportSynchronous health check: online status of each link同步健康体检:各链路在线状态
await session.e_stop(reason)Emergency stop; subsequent motion calls are rejected紧急停止,之后的动作调用会被拒绝
session.session_stateEnum枚举IDLE / CONNECTING / CONNECTED / DEGRADED / ESTOPPED / DISCONNECTED / FAULT
session.uptimefloatSeconds since the session was established会话建立以来的秒数
await session.close()Disconnect and release resources断开连接、释放资源

Recommended: async with

推荐写法:async with

python — context manager auto-cleanup
async with await ff_sdk.connect("D1-DEMO") as dog:
    await dog.motion.stand()
    ...
# leaving the with block auto-closes; exceptions won't leak the connection
python — 上下文管理器自动收尾
async with await ff_sdk.connect("D1-DEMO") as dog:
    await dog.motion.stand()
    ...
# 离开 with 块自动 close(),异常也不会泄漏连接
python — capability probing
print(dog.capabilities())
# {'motion', 'state', ...}

if "motion" in dog.capabilities():
    await dog.motion.stand()
python — 能力探测
print(dog.capabilities())
# {'motion', 'state', ...}

if "motion" in dog.capabilities():
    await dog.motion.stand()

06motion · Motion control运动控制

Velocity control

速度控制

async motion.cmd_vel(linear: float = 0.0, angular: float = 0.0, lateral: float = 0.0) -> MotionResult
Parameter参数 Unit单位 Meaning含义
linearm/sForward (negative = reverse)前进(负值后退)
angularrad/sYaw turn (positive = left)偏航转向(正值左转)
lateralm/sLateral movement横向移动
Continuous motion cmd_vel is a velocity command, not a displacement command. To keep the robot walking = resend the command periodically; to stop = await motion.stop(). For the safe approach, see the example cookbook/safety_watchdog.py.
持续运动 cmd_vel 是速度指令而不是位移指令。让机器人持续行走 = 周期性重发指令; 停下 = await motion.stop()。安全做法见示例 cookbook/safety_watchdog.py

Posture control

姿态控制

Method方法 Notes说明
await motion.stand()Stand (~4s)站立(约 4s)
await motion.damping()Damping mode — a limp-joint "soft e-stop"; recommended to always call at the end阻尼模式 —— 关节松软的“软急停”,推荐收尾必调
await motion.stop()Stop moving (stay standing)停止移动(保持站立)
await motion.cmd_twist(twist)The Twist dataclass form of cmd_velcmd_velTwist 数据类形式
await state.pose()Current pose (Pose) — read via state.pose(); motion.current_pose is not provided (raises CapabilityNotSupported)当前位姿(Pose)—— 走 state.pose() 读取;motion.current_pose 未提供(会 raise CapabilityNotSupported

In-place attitude control · D1-only

原地姿态控制 · 仅 D1

async motion.attitude_control(roll_vel: float = 0.0, pitch_vel: float = 0.0, yaw_vel: float = 0.0, height_vel: float = 0.0) -> MotionResult

Quadruped-only. Tilts / turns / raises the body in place without walking. All four terms are velocities (roll/pitch/yaw in rad/s, height in m/s), each clamped to ±0.5. Supported on both zsl-1 (point-foot) and zsl-1w (wheeled-foot).

四足专属。不走路、原地俯仰 / 转头 / 侧倾 / 升降身体。四个量都是速度(roll/pitch/yaw 单位 rad/s,height 单位 m/s),各自钳在 ±0.5。zsl-1(点足)与 zsl-1w(轮足)均支持。

Parameter参数 Unit单位 Meaning含义
pitch_velrad/sPitch — nod up / down俯仰 —— 抬头 / 低头
yaw_velrad/sYaw — turn head left / right转头 —— 左 / 右
roll_velrad/sRoll / peek — lean left / right侧倾 / 探头 —— 左 / 右
height_velm/sStance height — raise / lower站高 —— 升 / 降
Enter in-place (STAY) mode first The robot must be in the in-place (STAY) motion mode before these calls — otherwise the input is read as locomotion, not attitude. The aegis SDK backend enters it implicitly; on the dog_task UDP fallback, send the STAY mode command first. On the fallback, pitch/yaw are continuous but peek & stance height are discrete button pulses (approximated by direction, not magnitude).
先进原地(STAY)模式 调用前机器人必须先处于原地(STAY)运动模式 —— 否则输入会被当成行走而非姿态。aegis SDK 后端会隐式切入;走 dog_task UDP 兜底时需先发 STAY 模式指令。兜底路径下 pitch/yaw 连续,但 peek 与 stance 是离散按键脉冲(按方向近似,非按幅度)。
in-place attitude — D1 only
if not hasattr(robot.motion, "attitude_control"):
    print("attitude_control is D1 (quadruped) only")
    return

# enter in-place (STAY) mode first, then drive the 4 velocity terms
await robot.motion.attitude_control(pitch_vel=-0.3)               # nod down
await robot.motion.attitude_control(yaw_vel=0.3)                  # turn head left
await robot.motion.attitude_control(roll_vel=0.4, height_vel=0.3) # peek + raise
await robot.motion.attitude_control()                            # back to neutral
原地姿态 — 仅 D1
if not hasattr(robot.motion, "attitude_control"):
    print("attitude_control 仅 D1(四足)可用")
    return

# 先进原地(STAY)模式,再驱动 4 个速度量
await robot.motion.attitude_control(pitch_vel=-0.3)               # 低头
await robot.motion.attitude_control(yaw_vel=0.3)                  # 向左转头
await robot.motion.attitude_control(roll_vel=0.4, height_vel=0.3) # 探头 + 升高
await robot.motion.attitude_control()                            # 回到中立

Joint-level interface

关节级接口

Method方法 Notes说明
await state.joint_states()Read current joint position / velocity / effort dict — joint telemetry goes through state.joint_states(); motion.read_joint_state is not provided (raises CapabilityNotSupported)读取当前关节位置 / 速度 / 力矩字典 —— 关节遥测走 state.joint_states()motion.read_joint_state 未提供(会 raise CapabilityNotSupported
motion.joint_stream(q_func, rate_hz=50.0, …)High-frequency joint stream: send target joint positions per q_func(t) cycle (advanced, mind safety). ⏳ Planned — currently not available on Aegis (raises CapabilityNotSupported)高频关节流:按 q_func(t) 周期下发目标关节位置(进阶,注意安全)。⏳ 规划中,当前 Aegis 不可用(会 raise CapabilityNotSupported

07Stunt actions特技动作

Invoked via motion.do_preset(name); motion.known_presets() lists all actions supported by the current variant at runtime.

通过 motion.do_preset(name) 调用;motion.known_presets() 可在运行时列出当前机型支持的全部动作。

name Action动作 Est. time预计耗时 Notes注意
stand / stand_upStand站立~4s
lie_downLie down趴下~3s
damping / passiveDamping (soft e-stop)阻尼(软急停)~1sRecommended to always call at the end推荐收尾必调
shake_handShake hand握手~10sDon't interrupt mid-action全程别打断
jumpJump in place原地跳~4sLeave overhead space上方留空间
front_jumpForward jump前跳~4sLeave 1m ahead前方留 1m
backflipBackflip后空翻~5s⚠️ 2m clearance all around + full battery⚠️ 四周 2m 空旷 + 满电
two_leg_standTwo-leg stand双腿站立~4sUse cancel_two_leg_stand to recover配合 cancel_two_leg_stand 恢复
recoverFall recovery摔倒恢复~3s
python — stunt + wait for completion
res = await dog.motion.do_preset("shake_hand")
# wait the suggested duration for the action to finish before sending the next command
await asyncio.sleep(dog.motion.preset_timeout("shake_hand"))

print(dog.motion.known_presets())   # all action names supported by the current variant
python — 特技 + 等待动作完成
res = await dog.motion.do_preset("shake_hand")
# 用建议时长等动作做完,再发下一条指令
await asyncio.sleep(dog.motion.preset_timeout("shake_hand"))

print(dog.motion.known_presets())   # 当前机型支持的全部动作名

08state · State telemetry状态遥测

Method方法 Returns返回 Notes说明
await state.battery()BatteryStatepercent(0–1) / voltage / is_charging
await state.status()RobotStatusIDLE / STANDING / MOVING / LYING / DAMPING / CHARGING / ESTOPPED / FAULT …
await state.pose()PoseWorld-frame x,y,z (m) + roll,pitch,yaw (rad)世界系 x,y,z(米)+ roll,pitch,yaw(弧度)
await state.joint_states()JointStatesnames / positions / velocities / efforts; 12 joints point-foot, 16 joints wheeled-footnames / positions / velocities / efforts,点足 12 关节、轮足 16 关节
python — compatibility pattern for joint telemetry
from ff_sdk.core.exceptions import CapabilityNotSupported

try:
    joints = await dog.state.joint_states()
    print(f"{len(joints.names)} joints")
    for name, pos in zip(joints.names, joints.positions):
        print(f"  {name}: {pos:+.3f} rad")
except CapabilityNotSupported as e:
    # some wheeled-foot factory firmware doesn't support joint telemetry (motion control unaffected)
    print(f"this variant/firmware doesn't support joint telemetry: {e}")
python — 关节遥测的兼容写法
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}")

State polling cadence

状态轮询节奏

Polling frequency Telemetry reads are request-response. 1–5 Hz is plenty for routine monitoring; don't saturate the link with a tight while loop — see the throttled pattern in examples/state/watch_status.py.
轮询频率 遥测读取是请求-响应式。常规监控 1–5 Hz 足够;不要用密集 while 循环打满链路 —— 参考 examples/state/watch_status.py 的节流写法。

09Other capabilities其他能力

vision (🟡 partial)(🟡 部分)

async vision.frame(source: str = "default") -> CameraFrame vision.stream_camera(source: str = "default") -> AsyncIterator[CameraFrame]

Grab a single frame / continuously stream. CameraFrame contains data(bytes) / width / height / encoding. The interface is ready; variant coverage is being completed.

取单帧 / 持续取流。CameraFramedata(bytes) / width / height / encoding。接口就绪,机型覆盖完善中。

display (🟡 LED)(🟡 LED)

async display.set_led(*, color: str = "off", pattern: str = "solid") -> None

The quadruped has no face screen, so expression interfaces like show_expression raise CapabilityNotSupported on this platform.

四足无面屏,show_expression 等表情类接口在本平台 raise CapabilityNotSupported

navigation (🟡 partial)(🟡 部分)

async navigation.goto(pose: Pose, *, timeout_s: float | None = None) -> bool async navigation.cancel() -> None async navigation.list_waypoints() -> tuple[str, ...]

Patrol navigation stack integration is in progress; availability is governed by what session.capabilities() returns at runtime.

巡检导航栈对接中;可用性以 session.capabilities() 运行时返回为准。

10Variant adaptation机型适配(variant)

The Aegis lineup has several models, but to you as a developer the API is identical — you only need to pick the right variant parameter.

Aegis 产品线有多个型号,对开发者来说 API 完全一样,只需选对一个 variant 参数。

Which one do I have?

我手上是哪台?

What to check看什么 Point-foot点足 Wheeled-foot轮足 / 轮狗
Foot end足端4 rubber foot pads4 个橡胶脚垫4 drive wheels4 个驱动轮
Locomotion移动方式Stepping gait迈步行走Wheeled glide + stepping hybrid轮式滑行 + 迈步混合
Joint count关节数12 (3 per leg)12(每腿 3 个)16 (3 per leg + wheel)16(每腿 3 个 + 轮)
Model产品型号 Form形态 variant Adaptation status适配状态
Standard标准版 (point-foot batch)(点足批次)Point-foot点足zsl-1✅ hardware-verified✅ 真机验证 (stand / walk / stunt / full telemetry)(站立 / 行走 / 特技 / 全遥测)
Standard标准版 (wheeled-foot batch)(轮足批次)Wheeled-foot轮足zsl-1w✅ hardware-verified✅ 真机验证 (motion + state telemetry)(运动 + 状态遥测)
EDUEDU 版 (education)(教育版)Point-foot点足zsl-1🟡 adapted🟡 已适配, same control path as point-foot, pending regression testing,与点足同一控制路径,待回归测试
Pro / UltraPoint-foot点足zsl-1🟡 adapted🟡 已适配, pending regression testing,待回归测试

How to set variant (pick one of three)

variant 怎么填(三选一)

shell / python
# Option 1: env var (recommended, no code change)
export FF_SDK_D1_VARIANT=zsl-1      # point-foot / EDU / Ultra
export FF_SDK_D1_VARIANT=zsl-1w     # wheeled-foot (default when unset)
shell / python
# 方式 1:环境变量(推荐,不改代码)
export FF_SDK_D1_VARIANT=zsl-1      # 点足 / EDU / Ultra
export FF_SDK_D1_VARIANT=zsl-1w     # 轮足(不设时的默认值)
python — Config explicit override
cfg = Config.from_env()
cfg.extra["d1_variant"] = "zsl-1"
dog = await ff_sdk.connect("D1-DEMO", config=cfg)
python — Config 显式指定
cfg = Config.from_env()
cfg.extra["d1_variant"] = "zsl-1"
dog = await ff_sdk.connect("D1-DEMO", config=cfg)
What if I set it wrong? When the SDK can't load a matching motion library, it automatically falls back to the generic communication path, and session.diagnose() tells you exactly which link didn't come up — it won't damage the robot.
填错了会怎样? SDK 加载不到匹配的运动库时自动降级到通用通信路径,session.diagnose() 会明确告诉你哪条链路没起来 —— 不会损坏机器人。

11Deploy to robot部署到机器人

Deployment部署方式 Notes说明 Recommendation推荐度
Run on the robot跑在机器人上scp the program to the robot, loopback control, lowest latency程序 scp 到机器人,本机回环控制,延迟最低★★★ recommended★★★ 推荐
Run on a Linux dev machine跑在 Linux 开发机Dev machine joins the robot hotspot, remote control开发机连机器人热点,远程控制★★ (advanced setup, contact support)★★(进阶配置,联系支持)
Run on Windows / Mac跑在 Windows / MacDry-run only (the motion library is Linux-only)仅 dry-run(底层运动库是 Linux 库)★ for learning / writing code★ 学习 / 写代码用

For getting the program onto the robot, auto-start on boot (systemd), and the upgrade flow, see docs/deployment.md inside the devkit. C++ developers should look at the devkit's cpp/README.md (headers + dual-arch prebuilt libs + examples).

程序上机、开机自启(systemd)与升级流程详见 devkit 内 docs/deployment.md。 C++ 开发者请看 devkit 的 cpp/README.md(头文件 + 双架构预编译库 + 示例)。

12Cross-platform Skills跨平台 Skills

ff_sdk.skills.* are high-level actions you write once and run on every platform — internally they automatically pick the most suitable implementation per platform:

ff_sdk.skills.* 是写一次、所有平台都能跑的高层动作 —— 内部自动按平台选择最合适的实现:

python — skills
from ff_sdk import skills

result = await skills.wave(dog)              # auto-mapped to shake-hand on Aegis
result = await skills.bow(dog)               # auto-mapped to a nod
result = await skills.greet(dog, "friend")   # wave + (on platforms with audio) greeting
print(result)   # {"ok": True, "message": "...", "platform": "..."}
python — 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": "..."}

Cross-robot code should prefer skills; only drop down to motion.do_preset directly for platform-specific details.

跨机器人代码应优先用 skills;平台专属细节才直接调 motion.do_preset

13Errors & diagnostics异常与诊断

Exception hierarchy

异常层级

Exception异常 When it's raised什么时候抛
FfSdkErrorRoot class of all SDK exceptions所有 SDK 异常的根类
ConfigErrorConfig invalid or incomplete配置无效或不完整
ConnectionErrorCan't establish / lost connection无法建立 / 失去连接
TransportErrorWire-level failure (socket / RPC timeout)线路级故障(socket / RPC 超时)
TimeoutErrorOperation exceeded its deadline操作超过截止时间
PlatformErrorLow-level error translated by the platform adapter平台适配层翻译的底层错误
CapabilityNotSupportedThis platform / variant / firmware doesn't support this capability该平台 / 机型 / 固件不支持此能力
EStopActiveErrorEmergency stop active; motion rejected紧急停止激活中,动作被拒绝
StateErrorCurrent state disallows the operation (charging / OTA / fault)当前状态不允许该操作(充电 / OTA / 故障中)
python — recommended error-handling skeleton
import ff_sdk
from ff_sdk.core.exceptions import (
    CapabilityNotSupported, EStopActiveError, StateError)

try:
    await dog.motion.stand()
except CapabilityNotSupported as e:
    print(f"this variant doesn't support: {e}")
except EStopActiveError:
    print("e-stop active; clear the hazard before resetting")
except StateError as e:
    print(f"current state disallows: {e}")   # e.g. charging
python — 推荐的错误处理骨架
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(): check first, then act

diagnose():先体检,再动作

python
report = dog.diagnose()
print(report)
# online status of every link (control / telemetry / motion backend) at a glance
# always the first debugging step — look here, don't guess
python
report = dog.diagnose()
print(report)
# 各链路(控制通道 / 遥测通道 / 运动后端)在线状态一目了然
# 排错第一步永远是看这个,而不是猜

14Example index示例索引

All examples in the devkit's examples/ run as-is (dry-run first, then real robot):

devkit 的 examples/ 全部可直接运行(先 dry-run 后真机):

Example示例 Contents内容
01_hello_connect.pyFirst connection + diagnose + emergency stop第一次连接 + 诊断 + 紧急停止
02_diagnose.pyHealth report walkthrough体检报告详解
03_estop.pyEmergency stop + callback + reset紧急停止 + 回调 + 重置
d1/udp_walk.pyFull walking demo (stand → forward → turn → damping)完整行走演示(站立 → 前进 → 转向 → 阻尼)
d1/presets_and_telemetry.pyVariant selection + stunts + joint telemetry机型选择 + 特技 + 关节遥测
motion/cmd_vel.py / stand_damping.py / do_preset.pyMotion control trio运动控制三件套
state/read_battery.py / watch_status.pyBattery / status monitoring电量 / 状态监听
cookbook/safety_watchdog.pySafety watchdog (strongly recommended reading first)安全看门狗(强烈推荐先读)
cookbook/multi_robot.pyConcurrent multi-robot control多机器人并发控制
cookbook/record_trajectory.pyTrajectory recording轨迹记录
cookbook/sim_to_real.pySim-to-real migration仿真到真机迁移

15FAQ / TroubleshootingFAQ / 排错

Symptom现象 Likely cause可能原因 Fix解决
diagnose shows the motion backend offlinediagnose 显示运动后端 offlineWrong variant (point-foot robot set to wheeled-foot)variant 填错(点足机器填了轮足)Switch variant per the variant table and reconnect机型表 换 variant 重连
Stand command sent, no response站立指令发了没反应Robot still in damping / e-stop state机器人还在阻尼 / 急停状态Run do_preset("stand") first, check state.status()do_preset("stand"),看 state.status()
Wheeled-foot joint_states errors轮足 joint_states 报错Factory firmware limitation已出厂固件限制Use the try/except CapabilityNotSupported pattern用 try/except CapabilityNotSupported 兼容写法
Can't connect to the robot连不上机器人Not on the robot hotspot / wrong host没连到机器人热点 / host 填错Check WiFi; set FF_SDK_D1_HOST in LAN mode确认 WiFi;局域网模式设 FF_SDK_D1_HOST
Commands occasionally dropped指令偶尔丢WiFi link jitterWiFi 链路抖动Run the program on the robot itself (loopback is most stable)程序跑到机器人本体上(本机回环最稳)