Humanoid Platform · 人形
Futurist 人形机器人 SDK
Futurist(产品代号 A2)是 FF 全尺寸人形机器人,也是能力覆盖最全的平台: 运动、状态、语音 TTS、相机取帧、面部表情全部可用,机械臂、导航与人脸考勤持续完善。 适合做交互演示、迎宾接待、多模态应用开发。
01概览与能力矩阵
Futurist 是 8 个能力域覆盖最全的平台。所有调用统一为
robot.<能力>.<动作>(),不支持的能力明确抛
CapabilityNotSupported。
| 能力域 | 方法 | 状态 | 说明 |
|---|---|---|---|
motion | stand() / damping() / stop() | ✅ live | 基础姿态控制 |
cmd_vel() 速度控制 | 🟡 部分 | 接口可用,速度包络持续标定 | |
do_preset() 预置动作 | 🟡 部分 | 招手 / 鞠躬 / 点头等 | |
state | battery() / status() / joint_states() | ✅ live | 全套遥测 |
pose() 位姿 | ✅ live | 基于里程计 | |
audio | say() TTS | ✅ live | 文本转语音播报 |
play_wav() / volume() | 🟡 部分 | 音频播放 / 音量 | |
vision | frame() 取帧 | ✅ live | 头部相机 JPEG 取帧 |
display | show_expression() 表情 | ✅ live | 面屏表情库(含 list_expressions()) |
arm | pose_arm() / grasp() … | 🟡 部分 | 机械臂关节位姿 / 抓取 |
checkin | enroll() / recognize() … | 🟡 部分 | 人脸注册 / 识别 / 考勤 |
navigation | goto() 等 | 🟡 部分 | 定点导航对接中 |
02安装
devkit 的 wheels/ 目录提供两个架构的 Python 3.10 wheel:
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__)"
程序跑在哪
Futurist 的语音 / 视觉 / 表情等能力依赖机器人本体服务,推荐把程序部署到机器人上运行
(SDK 会自动检测本体环境)。开发阶段在任意电脑用
FF_SDK_DRY_RUN=1 干跑。
03快速开始
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("wave") # 招手
asyncio.run(main())
安全须知
人形机器人重心高。运动测试保持四周 1.5m 空旷;调试期间手边常备急停;
任何异常立刻
await robot.e_stop()。请勿在楼梯口、桌沿等危险位置测试行走。
04连接与配置
connect()
async ff_sdk.connect(target: str, *, config: Config | None = None,
identity: Identity | None = None) -> Session
target 用 A2-<序列号> 形式;仿真用 mujoco://a2。
环境自动检测
程序跑在机器人本体上时,SDK 自动检测本体运行环境(通信域、各服务端点), 通常不需要任何手工配置。开发机远程连接为进阶用法,请联系支持获取网络配置指引。
环境变量
| 变量 | 默认 | 说明 |
|---|---|---|
FF_SDK_DRY_RUN | 关 | 设 1 进入干跑模式(无真机开发) |
FF_SDK_TRANSPORT_TIMEOUT | 5.0 | 单次操作超时(秒) |
FF_SDK_DISCOVERY_TIMEOUT | 3.0 | 服务发现截止(秒) |
FF_SDK_LOG_DIR | /var/log/ff_sdk | 日志目录 |
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 与生命周期
| 成员 | 类型 | 说明 |
|---|---|---|
session.motion / .state / .audio / .vision / .display / .arm / .checkin / .navigation | 能力访问器 | 不支持时 raise CapabilityNotSupported |
session.capabilities() | set[str] | 支持的能力域集合 |
session.diagnose() | DiagnosticReport | 同步健康体检 |
await session.e_stop(reason) | — | 紧急停止 |
session.session_state | 枚举 | IDLE / CONNECTING / CONNECTED / DEGRADED / ESTOPPED / DISCONNECTED / FAULT |
await session.close() | — | 断开连接 |
python — async with 自动收尾
async with await ff_sdk.connect("A2-DEMO") as robot:
await robot.motion.stand()
# 离开 with 自动 close(),异常也不会泄漏连接
06motion · 运动控制
| 方法 | 状态 | 说明 |
|---|---|---|
await motion.stand() | ✅ | 站立 / 进入可行走状态 |
await motion.damping() | ✅ | 阻尼软急停(收尾推荐) |
await motion.stop() | ✅ | 停止移动 |
await motion.cmd_vel(linear, angular, lateral) | 🟡 | 速度控制(m/s, rad/s) |
await motion.do_preset(name) | 🟡 | 预置动作:wave 招手 / bow 鞠躬 / nod 点头等 |
await motion.current_pose() | ✅ | 当前位姿 |
高频关节流(进阶)
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]
以固定频率把 q_func(t) 给出的目标关节位置流式下发 ——
用于自定义动作 / 轨迹回放等研究型场景。
关节流安全
joint_stream 直接驱动关节,请先在仿真(mujoco://a2)里完整验证轨迹,
确认幅度与速度安全后再上真机,且首次以小幅度低速跑。
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 · 状态遥测
| 方法 | 返回 | 说明 |
|---|---|---|
await state.battery() | BatteryState | percent(0–1) / voltage / is_charging |
await state.status() | RobotStatus | IDLE / STANDING / MOVING / CHARGING / ESTOPPED / FAULT … |
await state.pose() | Pose | 里程计位姿:x,y,z(米)+ roll,pitch,yaw(弧度) |
await state.joint_states() | JointStates | 全身关节 names / positions / velocities / efforts |
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 · 语音
| 方法 | 状态 | 说明 |
|---|---|---|
await audio.say(text, *, engine=…) | ✅ | TTS 文本播报(支持中英文) |
await audio.play_wav(wav_bytes) | 🟡 | 播放 WAV 音频数据 |
await audio.volume(level) | 🟡 | 设置音量 0.0–1.0 |
audio.stream_mic(source="default") | 🟡 | 麦克风音频流(AudioChunk 16kHz mono 迭代器) |
python — 语音播报 + 播放音效
await robot.audio.volume(0.7)
await robot.audio.say("欢迎光临,我是 Futurist")
with open("chime.wav", "rb") as f:
await robot.audio.play_wav(f.read())
09vision · 视觉
async vision.frame(source: str = "head_front") -> CameraFrame
vision.stream_camera(source: str = "default") -> AsyncIterator[CameraFrame]
| CameraFrame 字段 | 说明 |
|---|---|
data: bytes | 图像数据(JPEG) |
width / height | 分辨率 |
encoding | 编码格式 |
timestamp | 采集时间戳 |
source | 相机标识(默认头部前向相机 head_front) |
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 · 表情与显示
| 方法 | 状态 | 说明 |
|---|---|---|
await display.show_expression(preset) | ✅ | 播放面屏表情(按名称) |
await display.list_expressions() | ✅ | 列出表情库全部可用表情名 |
await display.show_text(text) | 🟡 | 面屏显示文字 |
await display.set_led(color=…, pattern=…) | ⏳ | LED 灯效 |
python — 表情库探索
names = await robot.display.list_expressions()
print(names) # ('smile', 'blink', 'thinking', ...)
await robot.display.show_expression("smile")
表情名以运行时为准
表情库随固件版本更新,写代码前先
list_expressions() 拿当前这台机器的真实清单,
不要硬编码假设。
11arm · 机械臂 🟡 部分
| 方法 | 说明 |
|---|---|
await arm.pose_arm(joints, duration_s=2.0) | 按关节角组(ArmJointAngles)运动到目标位姿 |
await arm.current_tcp(arm="right") | 读末端 TCP 位姿(TcpPose) |
await arm.grasp(arm="right") / release() | 手部抓取 / 松开 |
arm.joint_servo_stream(…) | 手臂关节伺服流(进阶,同 joint_stream 安全要求) |
await arm.read_arm_state() | 读手臂关节状态 |
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 · 人脸考勤 🟡 部分
| 方法 | 说明 |
|---|---|
await checkin.enroll(name, employee_id=…, department=…) | 注册人脸 → EnrollResult(含 job_id) |
await checkin.enroll_status(job_id) | 查注册任务进度 |
await checkin.recognize(jpg) | 识别一张 JPEG → RecognitionResult(name / score / bbox) |
await checkin.list_faces() | 列出已注册人脸 |
await checkin.set_auto_greet(enabled) | 开关“识别到熟人自动打招呼” |
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("初次见面,请问怎么称呼?")
14跨平台 Skills
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 两者都支持,效果最完整)
15异常与诊断
| 异常 | 什么时候抛 |
|---|---|
FfSdkError | 所有 SDK 异常的根类 |
ConfigError / AuthenticationError | 配置 / 身份问题 |
ConnectionError / TransportError / TimeoutError | 连接 / 线路 / 超时 |
PlatformError | 平台适配层翻译的底层错误 |
CapabilityNotSupported | 能力在该平台不可用 |
EStopActiveError | 紧急停止激活中 |
StateError | 状态不允许(充电 / OTA / 故障中) |
python — diagnose 先行
report = robot.diagnose()
print(report)
# 控制 / 遥测 / 语音 / 视觉各链路是否在线,排错第一步永远先看体检
16示例索引
| 示例 | 内容 |
|---|---|
01_hello_connect.py | 第一次连接 + 诊断 + 紧急停止 |
02_diagnose.py | 体检报告详解 |
03_estop.py | 紧急停止 + 回调 + 重置 |
cookbook/context_manager.py | async with 上下文管理 |
cookbook/safety_watchdog.py | 安全看门狗 |
cookbook/graceful_shutdown.py | 优雅关闭 |
cookbook/multi_robot.py | 多机器人并发控制 |
cookbook/sim_to_real.py | 仿真到真机迁移(mujoco://a2 → A2-<sn>) |
cookbook/diagnose_report.py | 诊断报告导出 |
17FAQ / 排错
| 现象 | 可能原因 | 解决 |
|---|---|---|
| 运动指令被拒绝 | 正在充电 / 急停激活 | 看 state.battery().is_charging 与 session_state;脱桩 / 复位后重试 |
say() 没声音 | 音量为 0 / 音频服务未就绪 | 先 audio.volume(0.7);看 diagnose() 音频链路 |
| 表情没播放 | 表情名拼错 | 用 list_expressions() 拿真实清单 |
vision.frame() 超时 | 相机服务未就绪 | diagnose() 查视觉链路;稍等服务启动完成 |
能力 CapabilityNotSupported | 程序没跑在机器人本体上 | 部分能力依赖本体服务;把程序部署上机 |