The robot that grows with you.
基于 NVIDIA Jetson Nano 的桌面机器人平台,通过 HTTP API 控制底盘、舵机、语音和摄像头,并提供 Web 控制台界面。
# 安装依赖
uv sync
# 启动服务
uv run uvicorn app.main:app --host 0.0.0.0 --port 8000启动后访问以下地址(将 localhost 替换为 Jetson 的 IP 地址):
| 地址 | 说明 |
|---|---|
http://<IP>:8000/ |
Web 控制台(推荐) |
http://<IP>:8000/docs |
Swagger UI 交互式文档 |
http://<IP>:8000/openapi.json |
OpenAPI JSON 规范 |
访问 http://<IP>:8000/ 打开控制台,功能包括:
- 点击 "连接视频" 按钮开始接收摄像头画面
- 点击 "截图" 可下载当前帧为 JPEG 图片
- 视频通过 WebSocket 传输,约 10fps
- 使用方向键面板(▲▼◄►)控制底盘移动
- 支持键盘快捷键:
W/A/S/D或方向键移动,空格键停止 - 速度和转向速度可通过滑块调节
- 水平转头:拖动滑块选择角度(-50° ~ 50°),点击 GO 执行
- 垂直俯仰:拖动滑块选择角度(-20° ~ 30°),点击 GO 执行
- 归零复位:一键将水平和俯仰舵机回到 0°
- 输入文本,点击 "播报" 按钮
- 支持中文文本,基于 Piper TTS 引擎
- 页面顶部显示 API 连接状态(绿色 = 在线)和视频流状态
| 变量 | 默认值 | 说明 |
|---|---|---|
CHASSIS_PORT |
/dev/ttyACM0 |
底盘串口 |
SERVO_PORT |
/dev/ttyACM2 |
舵机串口 |
TTS_MODEL_PATH |
piper_models/zh_CN-huayan-medium.onnx |
Piper TTS 模型路径 |
CAMERA_DEVICE |
0 |
摄像头设备编号(自动探测) |
CAMERA_WIDTH |
640 |
摄像头分辨率宽度 |
CAMERA_HEIGHT |
480 |
摄像头分辨率高度 |
CAMERA_FPS |
30 |
摄像头帧率 |
CAMERA_JPEG_QUALITY |
70 |
视频流 JPEG 压缩质量 (10-100) |
LIDAR_PORT |
/dev/ttyACM1 |
LD06 雷达串口 |
LIDAR_PRODUCT |
LD06 |
雷达型号 |
curl http://localhost:8000/api/health# 语音播报
curl -X POST http://localhost:8000/voice/speak \
-H "Content-Type: application/json" \
-d '{"text": "你好,我是 Hermes JetBot"}'
# 查看 TTS 状态
curl http://localhost:8000/voice/status# 前进
curl -X POST http://localhost:8000/chassis/move \
-H "Content-Type: application/json" \
-d '{"direction": "forward", "speed": 0.2}'
# 左转
curl -X POST http://localhost:8000/chassis/move \
-H "Content-Type: application/json" \
-d '{"direction": "left", "turn_speed": 0.4}'
# 紧急停止
curl -X POST http://localhost:8000/chassis/stop# 水平转头(-50° ~ 50°)
curl -X POST http://localhost:8000/servo/head/pan \
-H "Content-Type: application/json" \
-d '{"angle": 30.0}'
# 垂直俯仰(-20° ~ 30°)
curl -X POST http://localhost:8000/servo/head/tilt \
-H "Content-Type: application/json" \
-d '{"angle": -10.0}'
# 舵机归零
curl -X POST http://localhost:8000/servo/reset# 检测摄像头
curl http://localhost:8000/camera/detect
# 拍摄截图
curl -o snapshot.jpg http://localhost:8000/camera/snapshotconst ws = new WebSocket('ws://localhost:8000/camera/stream');
ws.binaryType = 'arraybuffer';
ws.onmessage = (e) => {
// 每帧是 JPEG ArrayBuffer
document.getElementById('video').src =
URL.createObjectURL(new Blob([e.data], {type: 'image/jpeg'}));
};# 查看雷达状态
curl http://localhost:8000/lidar/status
# 启动雷达(使用默认串口)
curl -X POST http://localhost:8000/lidar/start
# 指定串口启动
curl -X POST "http://localhost:8000/lidar/start?port=/dev/ttyACM1"
# 获取最新 360° 扫描数据(完整对象)
curl http://localhost:8000/lidar/scan
# 获取极坐标数组 [[angle, distance_mm], ...]
curl http://localhost:8000/lidar/scan/polar
# 获取直角坐标数组 [[x_m, y_m], ...]
curl http://localhost:8000/lidar/scan/cartesian
# 停止雷达
curl -X POST http://localhost:8000/lidar/stopconst ws = new WebSocket('ws://localhost:8000/lidar/stream');
ws.onmessage = (e) => {
const { scan_freq_hz, points } = JSON.parse(e.data);
// points: [[angle, distance_mm], ...] 约 10Hz 推送
console.log(`频率 ${scan_freq_hz}Hz, ${points.length} 个点`);
};hermes-jetbot/
├── app/ # HTTP API 服务
│ ├── main.py # FastAPI 入口
│ ├── hardware.py # 硬件管理器
│ ├── schemas.py # 请求/响应模型
│ └── routers/ # 路由模块
├── static/ # 前端页面
│ └── index.html # Web 控制台
├── chassis/ # 底盘驱动
├── servo/ # 舵机驱动
├── voice/ # TTS 脚本
├── vedio/ # 摄像头工具
├── radar/ # LD06 雷达 SDK
├── doc/ # 设计文档
└── pyproject.toml # 项目配置
| 硬件 | 接口 | 说明 |
|---|---|---|
| 底盘电机 | /dev/ttyACM0 (串口 115200) |
CLB 机器人底盘 |
| 舵机 x2 | /dev/ttyACM2 (串口 115200) |
Fashion Star 总线舵机 |
| USB 摄像头 | /dev/video* (V4L2) |
自动探测,优先 USB 摄像头 |
| 扬声器 | audio jack / USB audio | Piper TTS 语音输出 |
| LD06 雷达 | /dev/ttyACM1 (串口 230400) |
360° 激光测距,~10Hz 扫描 |
MIT
