FF SDKFuturist Docs v0.1.0a0
Humanoid Platform人形机器人平台

Futurist Humanoid Robot SDK

Futurist 人形机器人 SDK

Futurist (product code A2) is FF's full-size humanoid robot, and the platform with the broadest capability coverage: motion, state, audio TTS, camera frame capture and facial expressions are all available, while arm, navigation and face check-in keep maturing. A great fit for interactive demos, reception/greeting, and multi-modal application development.

Futurist(产品代号 A2)是 FF 全尺寸人形机器人,也是能力覆盖最全的平台: 运动、状态、语音 TTS、相机取帧、面部表情全部可用,机械臂、导航与人脸考勤持续完善。 适合做交互演示、迎宾接待、多模态应用开发。

target: A2-<sn> Python ≥ 3.10 aarch64 / x86_64 8 capability domains8 大能力域

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

Futurist is the platform with the broadest coverage across the 8 capability domains. Every call follows the uniform form robot.<capability>.<action>(); unsupported capabilities explicitly raise CapabilityNotSupported.

Futurist 是 8 个能力域覆盖最全的平台。所有调用统一为 robot.<能力>.<动作>(),不支持的能力明确抛 CapabilityNotSupported

Capability能力域 Method方法 Status状态 Notes说明
motionstand() / damping() / stop()✅ liveBasic posture control (stop() pending cmd_vel integration)基础姿态控制(stop() 随 cmd_vel 待接入)
cmd_vel() velocity control速度控制🟡 Partial部分API available; speed envelope still being calibrated接口可用,速度包络持续标定
do_preset() preset actions预置动作🟡 Partial部分wave / bow / nod, etc.招手 / 鞠躬 / 点头等
statebattery() / status() / joint_states()✅ liveFull telemetry全套遥测
pose() pose位姿✅ liveOdometry-based基于里程计
audiosay() TTS✅ liveText-to-speech playback文本转语音播报
play_wav() / volume()🟡 Partial部分Audio playback / volume音频播放 / 音量
visionframe() frame capture取帧✅ liveHead camera JPEG frame capture头部相机 JPEG 取帧
displayshow_expression() expression表情✅ liveFace-screen expression library (incl. list_expressions())面屏表情库(含 list_expressions()
armpose_arm() / grasp()🟡 Partial部分Arm joint pose / grasp机械臂关节位姿 / 抓取
checkinenroll() / recognize()🟡 Partial部分Face enroll / recognize / check-in人脸注册 / 识别 / 考勤
navigationgoto() etc.🟡 Partial部分Waypoint navigation integration in progress定点导航对接中

02Installation安装

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

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

shell — install
# On the robot (aarch64) — recommended, broadest capability coverage
pip install wheels/ff_sdk-0.1.0a0-cp310-cp310-linux_aarch64.whl

# On a Linux dev machine (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__)"
shell — 安装
# 在机器人上(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__)"
Where your program runs Futurist's audio / vision / expression capabilities depend on on-board robot services, so we recommend deploying your program onto the robot to run (the SDK auto-detects the on-board environment). During development, dry-run on any computer with FF_SDK_DRY_RUN=1.
程序跑在哪 Futurist 的语音 / 视觉 / 表情等能力依赖机器人本体服务,推荐把程序部署到机器人上运行 (SDK 会自动检测本体环境)。开发阶段在任意电脑用 FF_SDK_DRY_RUN=1 干跑。

03Quickstart快速开始

hello_futurist.py — exercise five capability domains in one run
import asyncio, ff_sdk

async def main():
    async with await ff_sdk.connect("A2-DEMO") as robot:
        print(robot.diagnose())                       # health check first
        print(robot.capabilities())                   # see which capabilities are supported

        await robot.motion.stand()                    # stand up
        await robot.display.show_expression("smile")  # smile expression
        await robot.audio.say("Hello, I'm Futurist")  # TTS playback

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

        frame = await robot.vision.frame()            # grab one frame from the head camera
        with open("snapshot.jpg", "wb") as f:
            f.write(frame.data)

        await robot.motion.do_preset("stand_up")      # preset action (only stand_up / damping are live; wave is dry-run-only)

asyncio.run(main())
hello_futurist.py — 一次跑通五个能力域
import asyncio, ff_sdk

async def main():
    async with await ff_sdk.connect("A2-DEMO") as robot:
        print(robot.diagnose())                       # 先体检
        print(robot.capabilities())                   # 看支持哪些能力

        await robot.motion.stand()                    # 站立
        await robot.display.show_expression("smile")  # 微笑表情
        await robot.audio.say("你好,我是 Futurist")   # TTS 播报

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

        frame = await robot.vision.frame()            # 头部相机取一帧
        with open("snapshot.jpg", "wb") as f:
            f.write(frame.data)

        await robot.motion.do_preset("stand_up")      # 预置动作(仅 stand_up / damping live;wave 当前 dry-run-only)

asyncio.run(main())
Safety notice Humanoid robots have a high center of gravity. Keep 1.5 m of clearance all around during motion tests; keep an emergency stop within reach while debugging; on any anomaly, immediately call await robot.e_stop(). Do not test walking near stairwells, table edges or other hazardous spots.
安全须知 人形机器人重心高。运动测试保持四周 1.5m 空旷;调试期间手边常备急停; 任何异常立刻 await robot.e_stop()。请勿在楼梯口、桌沿等危险位置测试行走。

04Connect & configure连接与配置

connect()

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

target uses the A2-<serial> form; for simulation use mujoco://a2.

targetA2-<序列号> 形式;仿真用 mujoco://a2

Automatic environment detection

环境自动检测

When your program runs on the robot itself, the SDK auto-detects the on-board runtime environment (communication domain, service endpoints), and usually no manual configuration is needed. Remote connection from a dev machine is an advanced usage — contact support for network configuration guidance.

程序跑在机器人本体上时,SDK 自动检测本体运行环境(通信域、各服务端点), 通常不需要任何手工配置。开发机远程连接为进阶用法,请联系支持获取网络配置指引。

Environment variables

环境变量

Variable变量 Default默认 Notes说明
FF_SDK_DRY_RUNoffSet 1 to enter dry-run mode (development without a real robot)1 进入干跑模式(无真机开发)
FF_SDK_TRANSPORT_TIMEOUT5.0Per-operation timeout (seconds)单次操作超时(秒)
FF_SDK_DISCOVERY_TIMEOUT3.0Service discovery deadline (seconds)服务发现截止(秒)
FF_SDK_LOG_DIR/var/log/ff_sdkLog directory日志目录
python — Config
from ff_sdk import Config

cfg = Config.from_env()          # read from environment variables
cfg.transport_timeout = 8.0      # or change it in code
robot = await ff_sdk.connect("A2-DEMO", config=cfg)
python — Config
from ff_sdk import Config

cfg = Config.from_env()          # 从环境变量读取
cfg.transport_timeout = 8.0      # 也可以代码里改
robot = await ff_sdk.connect("A2-DEMO", config=cfg)

05Session & lifecycleSession 与生命周期

Member成员 Type类型 Notes说明
session.motion / .state / .audio / .vision / .display / .arm / .checkin / .navigationCapability accessors能力访问器Raises CapabilityNotSupported when unsupported不支持时 raise CapabilityNotSupported
session.capabilities()set[str]Set of supported capability domains支持的能力域集合
session.diagnose()DiagnosticReportSynchronous health check同步健康体检
await session.e_stop(reason)Emergency stop紧急停止
session.session_stateenum枚举IDLE / CONNECTING / CONNECTED / DEGRADED / ESTOPPED / DISCONNECTED / FAULT
await session.close()Disconnect断开连接
python — async with auto-cleanup
async with await ff_sdk.connect("A2-DEMO") as robot:
    await robot.motion.stand()
# leaving the with block auto-calls close(); the connection won't leak even on exceptions
python — async with 自动收尾
async with await ff_sdk.connect("A2-DEMO") as robot:
    await robot.motion.stand()
# 离开 with 自动 close(),异常也不会泄漏连接

06motion · Motion control运动控制

Method方法 Status状态 Notes说明
await motion.stand()Stand up / enter walk-ready state站立 / 进入可行走状态
await motion.damping()Damped soft e-stop (recommended for cleanup)阻尼软急停(收尾推荐)
await motion.stop()🟡Stop moving (= cmd_vel(0)) — ⚠️ live raises NotImplementedError, dry-run only (pending cmd_vel integration)停止移动(= cmd_vel(0))—— ⚠️ live 抛 NotImplementedError,仅 dry-run(随 cmd_vel 待接入)
await motion.cmd_vel(linear, angular, lateral)🟡Velocity control (m/s, rad/s)速度控制(m/s, rad/s)
await motion.do_preset(name)🟡Preset actions: wave / bow / nod, etc.预置动作:wave 招手 / bow 鞠躬 / nod 点头等
await motion.current_pose()⚠️ Not available on A2 (raises CapabilityNotSupported) — use state.pose() instead⚠️ A2 不可用(raise CapabilityNotSupported)—— 请改用 state.pose()

High-rate joint stream (advanced) — ⚠️ research-only, not yet implemented on A2

高频关节流(进阶)—— ⚠️ 研究型,A2 尚未接入

Not yet on A2 joint_stream is not yet implemented on A2 — calling it currently raises CapabilityNotSupported. The example below is experimental and cannot be run live as-is.
A2 尚未接入 joint_stream 在 A2 上尚未实现 —— 当前调用会 CapabilityNotSupported。下方示例为实验性,无法直接 live 运行。
motion.joint_stream(q_func: Callable[[float], list[float]], *, rate_hz: float = 50.0, duration_s: float | None = None, joint_names: list[str] | None = None) -> AsyncIterator[dict]

Streams the target joint positions given by q_func(t) at a fixed rate — for custom motions / trajectory playback and other research scenarios.

以固定频率把 q_func(t) 给出的目标关节位置流式下发 —— 用于自定义动作 / 轨迹回放等研究型场景。

joint_stream safety joint_stream drives joints directly. Please fully validate the trajectory in simulation (mujoco://a2) first, confirm the amplitude and speed are safe before going to the real robot, and run the first pass at low amplitude and low speed.
关节流安全 joint_stream 直接驱动关节,请先在仿真(mujoco://a2)里完整验证轨迹, 确认幅度与速度安全后再上真机,且首次以小幅度低速跑。
python — 50Hz sinusoidal arm swing example (simulate first!)
import math

def q_func(t: float) -> list[float]:
    # return the target joint position array (radians); t is seconds since the stream started
    return [0.3 * math.sin(2 * math.pi * 0.5 * t)]

async for tick in robot.motion.joint_stream(
        q_func, rate_hz=50.0, duration_s=5.0,
        joint_names=["right_shoulder_pitch"]):
    pass   # tick holds the per-frame dispatch receipt
python — 50Hz 正弦摆臂示例(先仿真!)
import math

def q_func(t: float) -> list[float]:
    # 返回目标关节位置数组(弧度),t 为流开始后的秒数
    return [0.3 * math.sin(2 * math.pi * 0.5 * t)]

async for tick in robot.motion.joint_stream(
        q_func, rate_hz=50.0, duration_s=5.0,
        joint_names=["right_shoulder_pitch"]):
    pass   # tick 含每帧下发回执

07state · State telemetry状态遥测

Method方法 Returns返回 Notes说明
await state.battery()BatteryStatepercent(0–1) / voltage / is_charging
await state.status()RobotStatusIDLE / STANDING / MOVING / CHARGING / ESTOPPED / FAULT …
await state.pose()PoseOdometry pose: x,y,z (m) + roll,pitch,yaw (rad)里程计位姿:x,y,z(米)+ roll,pitch,yaw(弧度)
await state.joint_states()JointStatesWhole-body joints names / positions / velocities / efforts全身关节 names / positions / velocities / efforts
python — charging-state guard
from ff_sdk.core.exceptions import StateError

status = await robot.state.status()
battery = await robot.state.battery()

if battery.is_charging:
    print("charging — motion commands will be rejected with StateError; leave the dock first")
else:
    await robot.motion.stand()
python — 充电状态保护
from ff_sdk.core.exceptions import StateError

status = await robot.state.status()
battery = await robot.state.battery()

if battery.is_charging:
    print("充电中 —— 运动指令会被 StateError 拒绝,先脱离充电桩")
else:
    await robot.motion.stand()

08audio · Audio语音

Method方法 Status状态 Notes说明
await audio.say(text, *, engine=…)TTS text playback (Chinese & English supported)TTS 文本播报(支持中英文)
await audio.play_wav(wav_bytes)🟡Play WAV audio data — ⚠️ not yet integrated on A2; both live and dry-run raise CapabilityNotSupported播放 WAV 音频数据 —— ⚠️ A2 未接入;live 与 dry-run 均抛 CapabilityNotSupported
await audio.volume(level)🟡Set volume 0.0–1.0 — ⚠️ not yet integrated on A2; both live and dry-run raise CapabilityNotSupported设置音量 0.0–1.0 —— ⚠️ A2 未接入;live 与 dry-run 均抛 CapabilityNotSupported
audio.stream_mic(source="default")🟡Microphone audio stream (AudioChunk 16kHz mono iterator)麦克风音频流(AudioChunk 16kHz mono 迭代器)
python — speak + play a sound effect
await robot.audio.say("Welcome, I'm Futurist")   # ✅ live

# volume() / play_wav() are not yet integrated on A2 (raise CapabilityNotSupported):
# await robot.audio.volume(0.7)
# with open("chime.wav", "rb") as f:
#     await robot.audio.play_wav(f.read())
python — 语音播报 + 播放音效
await robot.audio.say("欢迎光临,我是 Futurist")   # ✅ live

# volume() / play_wav() 在 A2 上尚未接入(会抛 CapabilityNotSupported):
# await robot.audio.volume(0.7)
# with open("chime.wav", "rb") as f:
#     await robot.audio.play_wav(f.read())

09vision · Vision视觉

async vision.frame(source: str = "head_front") -> CameraFrame vision.stream_camera(source: str = "default") -> AsyncIterator[CameraFrame]
CameraFrame fieldCameraFrame 字段 Notes说明
data: bytesImage data (JPEG)图像数据(JPEG)
width / heightResolution分辨率
encodingEncoding format编码格式
timestampCapture timestamp采集时间戳
sourceCamera identifier (default head front camera head_front)相机标识(默认头部前向相机 head_front
python — snapshot + feed your own vision model
frame = await robot.vision.frame()
with open("snap.jpg", "wb") as f:
    f.write(frame.data)

# data is standard JPEG — feed it straight to OpenCV / PIL / your detection model
# import cv2, numpy as np
# img = cv2.imdecode(np.frombuffer(frame.data, np.uint8), cv2.IMREAD_COLOR)
python — 抓拍 + 接入你自己的视觉模型
frame = await robot.vision.frame()
with open("snap.jpg", "wb") as f:
    f.write(frame.data)

# data 是标准 JPEG,可直接喂给 OpenCV / PIL / 你的检测模型
# import cv2, numpy as np
# img = cv2.imdecode(np.frombuffer(frame.data, np.uint8), cv2.IMREAD_COLOR)

10display · Expressions & display表情与显示

Method方法 Status状态 Notes说明
await display.show_expression(preset)Play a face-screen expression (by name)播放面屏表情(按名称)
await display.list_expressions()List all available expression names in the library列出表情库全部可用表情名
await display.show_text(text)🟡Show text on the face screen面屏显示文字
await display.set_led(color=…, pattern=…)LED lighting effectsLED 灯效
python — explore the expression library
names = await robot.display.list_expressions()
print(names)            # ('smile', 'blink', 'thinking', ...)

await robot.display.show_expression("smile")
python — 表情库探索
names = await robot.display.list_expressions()
print(names)            # ('smile', 'blink', 'thinking', ...)

await robot.display.show_expression("smile")
Expression names are runtime-authoritative The expression library updates with firmware. Before writing code, call list_expressions() to get the real list for this specific robot — don't hardcode assumptions.
表情名以运行时为准 表情库随固件版本更新,写代码前先 list_expressions() 拿当前这台机器的真实清单, 不要硬编码假设。

11arm · Arm机械臂 🟡 Partial部分

Method方法 Notes说明
await arm.pose_arm(joints, duration_s=2.0)Move to a target pose by joint-angle group (ArmJointAngles)按关节角组(ArmJointAngles)运动到目标位姿
await arm.current_tcp(arm="right")Read end-effector TCP pose (TcpPose)读末端 TCP 位姿(TcpPose
await arm.grasp(arm="right") / release()Hand grasp / release手部抓取 / 松开
arm.joint_servo_stream(…)Arm joint servo stream (advanced; same safety requirements as joint_stream)手臂关节伺服流(进阶,同 joint_stream 安全要求)
await arm.read_arm_state()Read arm joint state读手臂关节状态
python — raise the right arm + grasp
from ff_sdk.capabilities.arm import ArmJointAngles

await robot.arm.pose_arm(
    ArmJointAngles(angles=(0.0, -0.4, 0.0, 1.2, 0.0, 0.0, 0.0), arm="right"),
    duration_s=2.0,
)
await robot.arm.grasp(arm="right")
await asyncio.sleep(1)
await robot.arm.release(arm="right")
python — 抬右臂 + 抓取
from ff_sdk.capabilities.arm import ArmJointAngles

await robot.arm.pose_arm(
    ArmJointAngles(angles=(0.0, -0.4, 0.0, 1.2, 0.0, 0.0, 0.0), arm="right"),
    duration_s=2.0,
)
await robot.arm.grasp(arm="right")
await asyncio.sleep(1)
await robot.arm.release(arm="right")

12checkin · Face check-in人脸考勤 🟡 Partial部分

Method方法 Notes说明
await checkin.enroll(name, employee_id=…, department=…)Enroll a face → EnrollResult (with job_id)注册人脸 → EnrollResult(含 job_id
await checkin.enroll_status(job_id)Query enroll-job progress查注册任务进度
await checkin.recognize(jpg)Recognize a JPEG → RecognitionResult (name / score / bbox)识别一张 JPEG → RecognitionResultname / score / bbox
await checkin.list_faces()List enrolled faces列出已注册人脸
await checkin.set_auto_greet(enabled)Toggle "auto-greet on recognizing a known person"开关“识别到熟人自动打招呼”
python — take a shot and recognize
frame = await robot.vision.frame()
result = await robot.checkin.recognize(frame.data)

if result.name:
    await robot.audio.say(f"Hello, {result.name}")
    await robot.display.show_expression("smile")
else:
    await robot.audio.say("Nice to meet you, may I have your name?")
python — 拍一张并识别
frame = await robot.vision.frame()
result = await robot.checkin.recognize(frame.data)

if result.name:
    await robot.audio.say(f"你好,{result.name}")
    await robot.display.show_expression("smile")
else:
    await robot.audio.say("初次见面,请问怎么称呼?")

14Cross-platform Skills跨平台 Skills

python — write once, run on every platform
from ff_sdk import skills

await skills.wave(robot)                  # on Futurist → do_preset("wave")
await skills.bow(robot)                   # → do_preset("bow")
await skills.greet(robot, "Mr. Wang", language="zh")
# greet = wave + TTS greeting (Futurist supports both, for the most complete effect)
python — 写一次,全平台运行
from ff_sdk import skills

await skills.wave(robot)                  # Futurist 上 → do_preset("wave")
await skills.bow(robot)                   # → do_preset("bow")
await skills.greet(robot, "王先生", language="zh")
# greet = 招手 + TTS 打招呼(Futurist 两者都支持,效果最完整)

15Exceptions & diagnostics异常与诊断

Exception异常 When it's raised什么时候抛
FfSdkErrorRoot class of all SDK exceptions所有 SDK 异常的根类
ConfigError / AuthenticationErrorConfiguration / identity issues配置 / 身份问题
ConnectionError / TransportError / TimeoutErrorConnection / link / timeout连接 / 线路 / 超时
PlatformErrorLow-level error translated by the platform adapter layer平台适配层翻译的底层错误
CapabilityNotSupportedCapability not available on this platform能力在该平台不可用
EStopActiveErrorEmergency stop is active紧急停止激活中
StateErrorState doesn't allow it (charging / OTA / in fault)状态不允许(充电 / OTA / 故障中)
python — diagnose first
report = robot.diagnose()
print(report)
# whether control / telemetry / audio / vision links are online — always check the health report first when troubleshooting
python — diagnose 先行
report = robot.diagnose()
print(report)
# 控制 / 遥测 / 语音 / 视觉各链路是否在线,排错第一步永远先看体检

16Example index示例索引

Example示例 Content内容
01_hello_connect.pyFirst connection + diagnostics + emergency stop第一次连接 + 诊断 + 紧急停止
02_diagnose.pyHealth report walkthrough体检报告详解
03_estop.pyEmergency stop + callback + reset紧急停止 + 回调 + 重置
cookbook/context_manager.pyasync with context managementasync with 上下文管理
cookbook/safety_watchdog.pySafety watchdog安全看门狗
cookbook/graceful_shutdown.pyGraceful shutdown优雅关闭
cookbook/multi_robot.pyMulti-robot concurrent control多机器人并发控制
cookbook/sim_to_real.pySim-to-real migration (mujoco://a2 → A2-<sn>)仿真到真机迁移(mujoco://a2 → A2-<sn>)
cookbook/diagnose_report.pyDiagnostic report export诊断报告导出

17FAQ / troubleshooting排错

Symptom现象 Possible cause可能原因 Fix解决
Motion commands rejected运动指令被拒绝Charging / e-stop active正在充电 / 急停激活Check state.battery().is_charging and session_state; retry after leaving the dock / resettingstate.battery().is_chargingsession_state;脱桩 / 复位后重试
say() no soundsay() 没声音Volume is 0 / audio service not ready音量为 0 / 音频服务未就绪First audio.volume(0.7); check the audio link in diagnose()audio.volume(0.7);看 diagnose() 音频链路
Expression didn't play表情没播放Expression name misspelled表情名拼错Use list_expressions() to get the real listlist_expressions() 拿真实清单
vision.frame() times outvision.frame() 超时Camera service not ready相机服务未就绪diagnose() to check the vision link; wait for the service to finish startingdiagnose() 查视觉链路;稍等服务启动完成
Capability CapabilityNotSupported能力 CapabilityNotSupportedProgram isn't running on the robot itself程序没跑在机器人本体上Some capabilities depend on on-board services; deploy the program onto the robot部分能力依赖本体服务;把程序部署上机