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说明 |
motion | stand() / damping() / stop() | ✅ live | Basic 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.招手 / 鞠躬 / 点头等 |
state | battery() / status() / joint_states() | ✅ live | Full telemetry全套遥测 |
pose() pose位姿 | ✅ live | Odometry-based基于里程计 |
audio | say() TTS | ✅ live | Text-to-speech playback文本转语音播报 |
play_wav() / volume() | 🟡 Partial部分 | Audio playback / volume音频播放 / 音量 |
vision | frame() frame capture取帧 | ✅ live | Head camera JPEG frame capture头部相机 JPEG 取帧 |
display | show_expression() expression表情 | ✅ live | Face-screen expression library (incl. list_expressions())面屏表情库(含 list_expressions()) |
arm | pose_arm() / grasp() … | 🟡 Partial部分 | Arm joint pose / grasp机械臂关节位姿 / 抓取 |
checkin | enroll() / recognize() … | 🟡 Partial部分 | Face enroll / recognize / check-in人脸注册 / 识别 / 考勤 |
navigation | goto() 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.
target 用 A2-<序列号> 形式;仿真用 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_RUN | off关 | Set 1 to enter dry-run mode (development without a real robot)设 1 进入干跑模式(无真机开发) |
FF_SDK_TRANSPORT_TIMEOUT | 5.0 | Per-operation timeout (seconds)单次操作超时(秒) |
FF_SDK_DISCOVERY_TIMEOUT | 3.0 | Service discovery deadline (seconds)服务发现截止(秒) |
FF_SDK_LOG_DIR | /var/log/ff_sdk | Log 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 / .navigation | Capability accessors能力访问器 | Raises CapabilityNotSupported when unsupported不支持时 raise CapabilityNotSupported |
session.capabilities() | set[str] | Set of supported capability domains支持的能力域集合 |
session.diagnose() | DiagnosticReport | Synchronous health check同步健康体检 |
await session.e_stop(reason) | — | Emergency stop紧急停止 |
session.session_state | enum枚举 | 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() | BatteryState | percent(0–1) / voltage / is_charging |
await state.status() | RobotStatus | IDLE / STANDING / MOVING / CHARGING / ESTOPPED / FAULT … |
await state.pose() | Pose | Odometry pose: x,y,z (m) + roll,pitch,yaw (rad)里程计位姿:x,y,z(米)+ roll,pitch,yaw(弧度) |
await state.joint_states() | JointStates | Whole-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: bytes | Image data (JPEG)图像数据(JPEG) |
width / height | Resolution分辨率 |
encoding | Encoding format编码格式 |
timestamp | Capture timestamp采集时间戳 |
source | Camera 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 → RecognitionResult(name / 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("初次见面,请问怎么称呼?")
13navigation · Navigation导航 🟡 Partial部分
async navigation.goto(pose: Pose, *, timeout_s: float | None = None) -> bool
async navigation.cancel() -> None
async navigation.list_waypoints() -> tuple[str, ...]
async navigation.current_waypoint() -> str | None
Waypoint navigation integration is in progress; availability follows the runtime results of session.capabilities() and diagnose().
定点导航对接中,可用性以 session.capabilities() 与 diagnose() 运行时结果为准。
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什么时候抛 |
FfSdkError | Root class of all SDK exceptions所有 SDK 异常的根类 |
ConfigError / AuthenticationError | Configuration / identity issues配置 / 身份问题 |
ConnectionError / TransportError / TimeoutError | Connection / link / timeout连接 / 线路 / 超时 |
PlatformError | Low-level error translated by the platform adapter layer平台适配层翻译的底层错误 |
CapabilityNotSupported | Capability not available on this platform能力在该平台不可用 |
EStopActiveError | Emergency stop is active紧急停止激活中 |
StateError | State 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.py | First connection + diagnostics + emergency stop第一次连接 + 诊断 + 紧急停止 |
02_diagnose.py | Health report walkthrough体检报告详解 |
03_estop.py | Emergency stop + callback + reset紧急停止 + 回调 + 重置 |
cookbook/context_manager.py | async with context managementasync with 上下文管理 |
cookbook/safety_watchdog.py | Safety watchdog安全看门狗 |
cookbook/graceful_shutdown.py | Graceful shutdown优雅关闭 |
cookbook/multi_robot.py | Multi-robot concurrent control多机器人并发控制 |
cookbook/sim_to_real.py | Sim-to-real migration (mujoco://a2 → A2-<sn>)仿真到真机迁移(mujoco://a2 → A2-<sn>) |
cookbook/diagnose_report.py | Diagnostic 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 / resetting看 state.battery().is_charging 与 session_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 list用 list_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能力 CapabilityNotSupported | Program isn't running on the robot itself程序没跑在机器人本体上 | Some capabilities depend on on-board services; deploy the program onto the robot部分能力依赖本体服务;把程序部署上机 |