仿生手 — USB 和 BLE 控制
BrainCo Revo II 设置指南
BrainCo Revo II 仿生手的分步设置 — 从 USB 或 BLE 连接到校准、姿势控制和平台集成。
1
USB-CDC 连接
安装Python依赖项
pip install pyserial websockets
连接并识别端口
通过 USB 连接 Revo II。 在 Linux 上,设备枚举为 /dev/ttyACM0 (如果存在其他 ACM 设备,则为 ttyACM1)。 在 Windows 上,检查设备管理器中的 COM 端口。
ls /dev/ttyACM* # Linux — find the device # Windows: check Device Manager → Ports (COM & LPT)
修复 Linux 上的权限
如果您收到权限被拒绝错误,请将您的用户添加到 dialout 组,然后注销并重新登录:
sudo usermod -aG dialout $USER
# Log out and back in for the change to take effect
波特率
Revo II 的通讯速率准确 115200 波特率。 任何其他速率将产生不可读的输出。 命令是以换行符结尾的 UTF-8 JSON 字符串。
2
蓝牙低功耗 (BLE) 连接
相同的 JSON 命令协议适用于 BLE GATT。 使用此路径进行无线部署。
安装BLE库
pip install bleak
扫描 Revo II
import asyncio
from bleak import BleakScanner
async def scan():
devices = await BleakScanner.discover(timeout=5.0)
for d in devices:
print(d.address, d.name)
asyncio.run(scan())
# Look for a device named "BrainCo" or similar — note its address
是 GATT UUID
- 服务:
0000ffe0-0000-1000-8000-00805f9b34fb - 写特征:
0000ffe1-0000-1000-8000-00805f9b34fb - 通知特征:
0000ffe2-0000-1000-8000-00805f9b34fb
通过 BLE 连接并发送命令
import asyncio, json from bleak import BleakClient WRITE_CHAR = "0000ffe1-0000-1000-8000-00805f9b34fb" ADDRESS = "AA:BB:CC:DD:EE:FF" # replace with your device address async def main(): async with BleakClient(ADDRESS) as client: # Close all fingers to 50% cmd = json.dumps({"cmd": "set_pose", "positions": [50,50,50,50,50]}) await client.write_gatt_char(WRITE_CHAR, cmd.encode("utf-8"), response=False) await asyncio.sleep(1.0) # Open all fingers cmd2 = json.dumps({"cmd": "set_pose", "positions": [0,0,0,0,0]}) await client.write_gatt_char(WRITE_CHAR, cmd2.encode("utf-8"), response=False) asyncio.run(main())
3
第一个姿势命令 (USB)
JSON 协议中的位置值是整数 0–100(闭合百分比)。 Python SDK 使用标准化浮点数 0.0–1.0 并在内部进行转换。
原始串行命令
import serial, json, time
port = serial.Serial("/dev/ttyACM0", baudrate=115200, timeout=1.0)
def set_pose(positions):
pcts = [int(p * 100) for p in positions]
cmd = json.dumps({"cmd": "set_pose", "positions": pcts}) + "\n"
port.write(cmd.encode("utf-8"))
# Open all fingers
set_pose([0.0, 0.0, 0.0, 0.0, 0.0])
time.sleep(1.0)
# Point with thumb extended, close others
set_pose([0.0, 0.8, 0.8, 0.8, 0.8])
time.sleep(1.0)
# Fist
set_pose([1.0, 1.0, 1.0, 1.0, 1.0])
time.sleep(1.0)
# Open again
set_pose([0.0] * 5)
port.close()
手指索引映射
- 0 — 拇指(2 DOF:屈曲 + 旋转 = 屈曲 × 0.4)
- 1 — 索引(1 自由度弯曲)
- 2 — 中(1 自由度弯曲)
- 3 — 环(1 自由度弯曲)
- 4 — Pinky(1 自由度弯曲)
设置单指
# Set index finger to 75% closure
cmd = json.dumps({"cmd": "set_finger", "finger": 1, "position": 75}) + "\n"
port.write(cmd.encode("utf-8"))
没有硬件? 使用模拟模式
跑步
python brainco_revo_agent.py --mock --session test --self-test 无需任何物理设备即可练习所有 API 方法和钢琴按下顺序。
4
校准波序列
校准在固件中确定每个手指的行程限制。 在首次连接和任何机械调整后运行此操作。
校准顺序(自动)
- 所有手指均打开至 0% 关闭
- 等待 300 毫秒进行机械稳定
- 对于每个手指(拇指→食指→中指→无名指→小指):
- 接近 90% 关闭 — 等待 120 毫秒
- 打开至 0% 关闭 — 等待 120 毫秒
- 所有手指都停留在悬停位置(15% 闭合)
- 发送
{"cmd": "calibrate"}锁定固件限制
通过 SDK 运行校准
import asyncio
from brainco_revo_agent import BrainCoReVoController
async def calibrate():
ctrl = BrainCoReVoController(mock=False)
await ctrl.connect("/dev/ttyACM0")
await ctrl.calibrate() # runs full wave then sends calibrate cmd
print("Calibration complete")
await ctrl.disconnect()
asyncio.run(calibrate())
5
平台 Teleop 集成
这 brainco_revo_agent.py 通过 WebSocket 将 Revo II 连接到 RoboticsCenter 平台,从而实现远程操作、手指位置监控以及从浏览器收集演示数据。
启动代理
# Real hardware (USB) python brainco_revo_agent.py \ --backend wss://your-backend.run.app \ --session YOUR_SESSION_ID \ --device /dev/ttyACM0 # Real hardware (BLE) python brainco_revo_agent.py \ --backend wss://your-backend.run.app \ --session YOUR_SESSION_ID \ --ble AA:BB:CC:DD:EE:FF # Mock mode — no hardware required python brainco_revo_agent.py \ --backend ws://localhost:8000 \ --session test-session \ --mock
通过平台的钢琴模式
从浏览器遥控面板触发钢琴按键。 每次按下都会执行 4 相序列:伸出 (20 ms) → 驱动 (30 ms) → 保持 → 缩回 (20 ms)。 支持并发手指按压。
高级SDK API
import asyncio
from brainco_revo_agent import BrainCoReVoController
async def main():
ctrl = BrainCoReVoController(mock=False)
await ctrl.connect("/dev/ttyACM0")
# Set all fingers to 60% closure
await ctrl.set_hand_pose([0.6, 0.6, 0.6, 0.6, 0.6])
await asyncio.sleep(0.5)
# Read current state
snap = await ctrl.snapshot()
print(snap["positions_dict"]) # {"thumb":0.6, "index":0.6, ...}
await ctrl.disconnect()
asyncio.run(main())