Python实现的Sony Xperia Hello机器人SCU (System Control Unit) 控制器。
基于对Android 8.0固件的逆向工程分析实现。
pip install -r requirements.txt
from scu_controller import SCUController, MotorId
scu = SCUController('COM8') # Windows
# scu = SCUController('/dev/ttyUSB0') # Linux
if scu.connect():
# 移动头部
scu.move_head_pan(45.0, duration_ms=1000) # 右看45°
scu.move_head_tilt(-10.0, duration_ms=500) # 下看10°
scu.turn_body(90.0, duration_ms=1500) # 身体右转90°
scu.home_position() # 回到初始位置
# LED控制
scu.set_neck_led(255, 0, 0) # 颈部LED红色
scu.set_eye_led(0x1F, 0x1F) # 眼睛LED全开 (5个LED段)
# 设置事件监听
scu.set_touch_listener(lambda: print("触摸!"))
scu.set_proximity_listener(lambda dirs: print(f"检测到人: {dirs}"))
scu.disconnect()
from scu_controller import SCUController
scu = SCUController('COM8')
scu.connect()
# 方式1: 直接播放文件
scu.play_motion_file('BA_P_09.smd', on_complete=lambda: print("完成"))
# 方式2: 播放帧数据
from motion_parser import MotionFile
motion = MotionFile('BA_P_09.smd')
if motion.load():
frame_data = motion.get_fullframe_data()
scu.play_motion_data(frame_data, motion.header.total_duration_ms)
# 停止播放
scu.stop_motion()
scu.disconnect()
from motion_parser import MotionFile
motion = MotionFile('BA_S_01.smd')
if motion.load():
print(f"帧数: {motion.header.frame_count}")
print(f"帧时间: {motion.header.frame_time}ms")
print(f"时长: {motion.header.total_duration_ms}ms")
print(f"资源: {motion.header.resource_list}")
print(f"有关键帧: {motion.header.has_keyframe}")
# 交互模式
python motion_playback.py -p COM8 -i
# 播放动作文件
python motion_playback.py -p COM8 -m BA_P_09.smd
# 列出动作文件
python motion_playback.py -l --path /path/to/motions
python_scu/
├── scu_controller.py # SCU控制器主类
├── motion_parser.py # 动作文件解析器
├── motion_playback.py # 命令行播放工具
├── ANALYSIS.md # 协议分析文档
├── requirements.txt # 依赖包
└── README.md # 说明文档
命令格式: :<CMD>[参数]\r\n
响应格式: :<CMD>:[OK|BF|BE]\r\n
事件格式: <EVT[type][param]
| 命令 | 功能 | 格式 |
|---|---|---|
| MOS | 开始播放动作 | :MOS\r\n |
| MOC | 清除动作缓冲 | :MOC\r\n |
| MOT | 传输请求 | :MOT<帧数>\r\n |
| MOD | 发送帧数据 | :MOD<二进制数据> |
| P2P | 点对点移动 | :P2P<id><pos><dur><curve>\r\n |
| MCX | 电机控制 | :MCX<id><enable>\r\n |
| GMP | 获取电机位置 | :GMP<id>\r\n |
| MKS | 开始关键帧 | :MKS<流ID>\r\n |
| MKC | 取消关键帧 | :MKC<流ID>\r\n |
| MKL | 加载关键帧 | :MKL<流ID><Base64数据>\r\n |
| LED2 | 颈部LED | :LED2<RGB>\r\n |
| LED4 | 眼睛LED | :LED4<左><右>\r\n |
| 类型(十六进制) | 值(十进制) | 事件 |
|---|---|---|
| 0x80 | 128 | 距离检测 (PROXIMITY) |
| 0x81 | 129 | 触摸检测 (TOUCH) |
| 0x82 | 130 | 电源连接 (AC_CONNECTED) |
| 0x86 | 134 | 动作缓冲就绪 (MOTION_BUFFER) |
| 0x87 | 135 | 动作播放完成 (MOTION_STOP) |
| 0x89 | 137 | 关键帧完成 (KEYFRAME_STOP) |
| 0xE2 | 226 | 过流保护 (OVER_CURRENT) |
┌────────────────┬────────────────────────────────────┐
│ 偏移 (字节) │ 内容 │
├────────────────┼────────────────────────────────────┤
│ 0-7 │ "SONY:SMD" 魔数 │
│ 8-15 │ "BRTX0001" 版本号 │
│ 16-19 │ 动作数据偏移 │
│ 20-23 │ 动作数据大小 │
│ 24-27 │ 帧数 │
│ 28-31 │ 帧时间 (ms) │
│ 32-35 │ 资源使用标志 (位掩码) │
│ 36-39 │ 关键帧数据偏移 │
│ 40+ │ 动作帧数据 (每帧16字节) │
└────────────────┴────────────────────────────────────┘
| Bit | 值 | 资源 |
|---|---|---|
| bit 0 | 1 | NECK_LED (颈部LED) |
| bit 1 | 2 | EYE_LED (眼睛LED) |
| bit 2 | 4 | HEAD_PAN (头部水平电机) |
| bit 3 | 8 | HEAD_TILT (头部俯仰电机) |
| bit 4 | 16 | BODY (身体电机) |
| ID | 名称 | 说明 |
|---|---|---|
| 0 | HEAD_TILT | 头部垂直倾斜 |
| 1 | HEAD_PAN | 头部水平旋转 |
| 2 | BODY | 机身旋转 |
BA_S_01.smd - 睡眠待机 (循环)BA_S_02.smd - 检测人体后醒来BA_S_03.smd - 进入睡眠BA_P_01.smd - 倾听状态 (循环)BA_P_02.smd - 空闲待机 (循环)BA_P_03.smd - 呼吸动作 (循环)BA_P_09.smd - 眨眼BA_P_17.smd - 初始位置/归位BA_O_03.smd - 抱歉/未听清BA_O_05.smd - 告别BA_O_06.smd - 触摸屏幕反应BA_N_01.smd - 打招呼BA_N_04.smd - 四处张望 (循环)BA_Bore_01.smd ~ BA_Bore_14.smd (随机播放)仅供学习研究使用,请尊重Sony的知识产权。
3 commits
Hacker News (1)
Python
100.0%
Python实现的Sony Xperia Hello机器人SCU (System Control Unit) 控制器。
基于对Android 8.0固件的逆向工程分析实现。
pip install -r requirements.txt
from scu_controller import SCUController, MotorId
scu = SCUController('COM8') # Windows
# scu = SCUController('/dev/ttyUSB0') # Linux
if scu.connect():
# 移动头部
scu.move_head_pan(45.0, duration_ms=1000) # 右看45°
scu.move_head_tilt(-10.0, duration_ms=500) # 下看10°
scu.turn_body(90.0, duration_ms=1500) # 身体右转90°
scu.home_position() # 回到初始位置
# LED控制
scu.set_neck_led(255, 0, 0) # 颈部LED红色
scu.set_eye_led(0x1F, 0x1F) # 眼睛LED全开 (5个LED段)
# 设置事件监听
scu.set_touch_listener(lambda: print("触摸!"))
scu.set_proximity_listener(lambda dirs: print(f"检测到人: {dirs}"))
scu.disconnect()
from scu_controller import SCUController
scu = SCUController('COM8')
scu.connect()
# 方式1: 直接播放文件
scu.play_motion_file('BA_P_09.smd', on_complete=lambda: print("完成"))
# 方式2: 播放帧数据
from motion_parser import MotionFile
motion = MotionFile('BA_P_09.smd')
if motion.load():
frame_data = motion.get_fullframe_data()
scu.play_motion_data(frame_data, motion.header.total_duration_ms)
# 停止播放
scu.stop_motion()
scu.disconnect()
from motion_parser import MotionFile
motion = MotionFile('BA_S_01.smd')
if motion.load():
print(f"帧数: {motion.header.frame_count}")
print(f"帧时间: {motion.header.frame_time}ms")
print(f"时长: {motion.header.total_duration_ms}ms")
print(f"资源: {motion.header.resource_list}")
print(f"有关键帧: {motion.header.has_keyframe}")
# 交互模式
python motion_playback.py -p COM8 -i
# 播放动作文件
python motion_playback.py -p COM8 -m BA_P_09.smd
# 列出动作文件
python motion_playback.py -l --path /path/to/motions
python_scu/
├── scu_controller.py # SCU控制器主类
├── motion_parser.py # 动作文件解析器
├── motion_playback.py # 命令行播放工具
├── ANALYSIS.md # 协议分析文档
├── requirements.txt # 依赖包
└── README.md # 说明文档
命令格式: :<CMD>[参数]\r\n
响应格式: :<CMD>:[OK|BF|BE]\r\n
事件格式: <EVT[type][param]
| 命令 | 功能 | 格式 |
|---|---|---|
| MOS | 开始播放动作 | :MOS\r\n |
| MOC | 清除动作缓冲 | :MOC\r\n |
| MOT | 传输请求 | :MOT<帧数>\r\n |
| MOD | 发送帧数据 | :MOD<二进制数据> |
| P2P | 点对点移动 | :P2P<id><pos><dur><curve>\r\n |
| MCX | 电机控制 | :MCX<id><enable>\r\n |
| GMP | 获取电机位置 | :GMP<id>\r\n |
| MKS | 开始关键帧 | :MKS<流ID>\r\n |
| MKC | 取消关键帧 | :MKC<流ID>\r\n |
| MKL | 加载关键帧 | :MKL<流ID><Base64数据>\r\n |
| LED2 | 颈部LED | :LED2<RGB>\r\n |
| LED4 | 眼睛LED | :LED4<左><右>\r\n |
| 类型(十六进制) | 值(十进制) | 事件 |
|---|---|---|
| 0x80 | 128 | 距离检测 (PROXIMITY) |
| 0x81 | 129 | 触摸检测 (TOUCH) |
| 0x82 | 130 | 电源连接 (AC_CONNECTED) |
| 0x86 | 134 | 动作缓冲就绪 (MOTION_BUFFER) |
| 0x87 | 135 | 动作播放完成 (MOTION_STOP) |
| 0x89 | 137 | 关键帧完成 (KEYFRAME_STOP) |
| 0xE2 | 226 | 过流保护 (OVER_CURRENT) |
┌────────────────┬────────────────────────────────────┐
│ 偏移 (字节) │ 内容 │
├────────────────┼────────────────────────────────────┤
│ 0-7 │ "SONY:SMD" 魔数 │
│ 8-15 │ "BRTX0001" 版本号 │
│ 16-19 │ 动作数据偏移 │
│ 20-23 │ 动作数据大小 │
│ 24-27 │ 帧数 │
│ 28-31 │ 帧时间 (ms) │
│ 32-35 │ 资源使用标志 (位掩码) │
│ 36-39 │ 关键帧数据偏移 │
│ 40+ │ 动作帧数据 (每帧16字节) │
└────────────────┴────────────────────────────────────┘
| Bit | 值 | 资源 |
|---|---|---|
| bit 0 | 1 | NECK_LED (颈部LED) |
| bit 1 | 2 | EYE_LED (眼睛LED) |
| bit 2 | 4 | HEAD_PAN (头部水平电机) |
| bit 3 | 8 | HEAD_TILT (头部俯仰电机) |
| bit 4 | 16 | BODY (身体电机) |
| ID | 名称 | 说明 |
|---|---|---|
| 0 | HEAD_TILT | 头部垂直倾斜 |
| 1 | HEAD_PAN | 头部水平旋转 |
| 2 | BODY | 机身旋转 |
BA_S_01.smd - 睡眠待机 (循环)BA_S_02.smd - 检测人体后醒来BA_S_03.smd - 进入睡眠BA_P_01.smd - 倾听状态 (循环)BA_P_02.smd - 空闲待机 (循环)BA_P_03.smd - 呼吸动作 (循环)BA_P_09.smd - 眨眼BA_P_17.smd - 初始位置/归位BA_O_03.smd - 抱歉/未听清BA_O_05.smd - 告别BA_O_06.smd - 触摸屏幕反应BA_N_01.smd - 打招呼BA_N_04.smd - 四处张望 (循环)BA_Bore_01.smd ~ BA_Bore_14.smd (随机播放)仅供学习研究使用,请尊重Sony的知识产权。
Hacker News (1)
3 commits
Python
100.0%