13 KiB
部署与运维手册(项目总结)
本文面向 生产/外场部署:说明 voice_drone_assistant 是什么、与 云端 / ROS 伴飞桥 / PX4 如何衔接,以及 推荐启动顺序、环境变量与常见问题。
协议细节见 llmcon.md,通用配置索引见 PROJECT_GUIDE.md,伴飞桥行为见 FLIGHT_BRIDGE_ROS1.md,flight_intent 字段见 FLIGHT_INTENT_SCHEMA_v1.md。
1. 项目总结
1.1 定位
voice_drone_assistant 是板端 语音无人机助手:麦克风 → 降噪/VAD → SenseVoice STT → 唤醒词 → 用户一句指令 → 云端 WebSocket(LLM + TTS)或 本地 Qwen + Kokoro → 若服务端返回 flight_intent,可在本机 校验后执行(TCP Socket 旧路径,或 ROS 伴飞桥 推荐路径)。
1.2 推荐数据流(方案一:云 → 语音程序 → ROS 桥)
flowchart LR
subgraph cloud [云端]
WS[WebSocket LLM+TTS]
end
subgraph board [机载 香橙派等]
MIC[麦克风]
MAIN[main.py TakeoffPrintRecognizer]
ROSPUB[子进程 publish JSON]
BRIDGE[flight_bridge ros1_node]
MAV[MAVROS]
end
FCU[PX4 飞控]
MIC --> MAIN
MAIN <-->|WSS pcm_asr_uplink + flight_intent| WS
MAIN -->|ROCKET_FLIGHT_INTENT_ROS_BRIDGE| ROSPUB
ROSPUB -->|std_msgs/String /input| BRIDGE
BRIDGE --> MAV --> FCU
- 不把 ROS 直接暴露给公网:云端只连板子的 WSS/WS;飞控由 本机 MAVROS + 伴飞桥 执行。
- TCP Socket(
system.yaml→socket_server)是另一条试飞控通道,与云端 无关;未起 Socket 服务端时仅会重连日志,不影响 ROS 方案。
1.3 目录与核心入口(仓库根 = voice_drone_assistant/)
| 路径 | 说明 |
|---|---|
main.py |
语音助手入口 |
with_system_alsa.sh |
建议包装启动,修正 Conda 与系统 ALSA |
voice_drone/main_app.py |
唤醒、云端/本地 LLM、TTS、flight_intent 执行策略 |
voice_drone/flight_bridge/ros1_node.py |
ROS1 订阅 /input,执行 flight_intent |
voice_drone/flight_bridge/ros1_mavros_executor.py |
MAVROS:offboard / AUTO.LAND / RTL |
voice_drone/tools/publish_flight_intent_ros_once.py |
单次向 ROS 发布 JSON(主程序 ROS 桥会子进程调用) |
scripts/run_flight_bridge_with_mavros.sh |
一键:roscore(可选)+ MAVROS + 伴飞桥 |
scripts/run_flight_intent_bridge_ros1.sh |
仅伴飞桥(须已有 roscore + MAVROS) |
voice_drone/config/system.yaml |
音频、STT、TTS、云端、assistant 等 |
requirements.txt |
Python 依赖;rospy 来自 apt 的 ROS Noetic,见文件内注释 |
2. 环境与依赖
2.1 硬件与系统(典型)
- ARM64 板卡(如 RK3588)、ES8388 等音频编解码器、USB/内置麦克风。
- Ubuntu 20.04 + ROS Noetic(伴飞桥 / MAVROS 路径);同机运行语音进程与
ros1_node。 - 飞控串口(如
/dev/ttyACM0)与 MAVROSfcu_url一致。
2.2 Python
-
Python 3.10+(与原仓库一致即可)。
-
在
voice_drone_assistant根目录:pip install -r requirements.txt
2.3 ROS / MAVROS(伴飞桥方案必选)
sudo apt install ros-noetic-ros-base ros-noetic-mavros ros-noetic-mavros-extras
# 按官方文档执行 mavros 地理库安装(如有)
- 语音主程序的 ROS 桥子进程会
source /opt/ros/noetic/setup.bash并 prependPYTHONPATH,不要在未 source ROS 的 shell 里把PYTHONPATH设成「只有工程根」,否则会找不到rospy(参见main_app中_publish_flight_intent_to_ros_bridge)。
2.4 模型与权重
- STT / TTS /(可选)VAD 放入
models/,或bash scripts/bundle_for_device.sh从原仓库打包。 - 本地 LLM:GGUF 默认路径或
ROCKET_LLM_GGUF;纯云端对话时可弱化本地模型,但回退/混合模式仍需。
3. 部署拓扑
3.1 单机一体化(常见)
同一台香橙派上同时运行:
- roscore(若尚无 master,由
run_flight_bridge_with_mavros.sh拉起)。 - MAVROS(
px4.launch,串口连 PX4)。 - 伴飞桥
python3 -m voice_drone.flight_bridge.ros1_node(订阅/input)。 - 语音
bash with_system_alsa.sh python main.py。
ROS_MASTER_URI / ROS_HOSTNAME:一键脚本内默认 http://127.0.0.1:11311 与 127.0.0.1;新开调试终端 执行 rostopic/rosservice 前须自行 source /opt/ros/noetic/setup.bash 并 export 同一 ROS_MASTER_URI(见下文「常见问题」)。
3.2 网络
- 板子能访问 云端 WebSocket(
ROCKET_CLOUD_WS_URL)。 - PX4 + 遥控 + 安全开关等按外场规范配置;本文不替代安全检校清单。
4. 启动顺序(推荐)
4.1 终端 A:飞控栈 + 伴飞桥
在 voice_drone_assistant 根目录:
cd /path/to/voice_drone_assistant
bash scripts/run_flight_bridge_with_mavros.sh /dev/ttyACM0 921600
脚本会:
- 设置
ROS_MASTER_URI、ROS_HOSTNAME(未预设时默认为本机 master); - 如无 master 则启动 roscore;
- 启动 MAVROS 并等待
/mavros/stateconnected; - 前台启动伴飞桥,日志中应出现:
flight_intent_bridge 就绪:订阅 /input。
仅桥(已有 MAVROS 时):
source /opt/ros/noetic/setup.bash
export ROS_MASTER_URI="${ROS_MASTER_URI:-http://127.0.0.1:11311}"
export ROS_HOSTNAME="${ROS_HOSTNAME:-127.0.0.1}"
bash scripts/run_flight_intent_bridge_ros1.sh
4.2 终端 B:语音助手 + 云端 + 执行飞控
cd /path/to/voice_drone_assistant
export ROCKET_CLOUD_VOICE=1
export ROCKET_CLOUD_WS_URL='ws://<云主机>:8766/v1/voice/session'
export ROCKET_CLOUD_AUTH_TOKEN='<token>'
export ROCKET_CLOUD_DEVICE_ID='drone-001' # 可选
# 云端返回 flight_intent 时是否在机端执行
export ROCKET_CLOUD_EXECUTE_FLIGHT=1
# 走 ROS 伴飞桥(与 Socket/offboard 序列互斥,勿双开重复执行)
export ROCKET_FLIGHT_INTENT_ROS_BRIDGE=1
# 可选:ROCKET_FLIGHT_BRIDGE_TOPIC=/input ROCKET_FLIGHT_BRIDGE_WAIT_SUB=2
# 默认关闭本地「起飞演示」口令直起 offboard;需要时再设为 1
# export ROCKET_LOCAL_KEYWORD_TAKEOFF=1
bash with_system_alsa.sh python main.py
成功时日志类似:[飞控-ROS桥] 已发布至 /input;伴飞桥端出现 执行 flight_intent:steps=...。
4.3 配置写进 YAML(可选)
- 云端:
system.yaml→cloud_voice(enabled、server_url、auth_token等)。 - 本地口令起飞:
assistant.local_keyword_takeoff_enabled(默认false);环境变量ROCKET_LOCAL_KEYWORD_TAKEOFF非空时优先生效。
5. 环境变量速查(飞控与云端)
| 变量 | 含义 |
|---|---|
ROCKET_CLOUD_VOICE |
1:对话走云端 WebSocket |
ROCKET_CLOUD_WS_URL |
云端会话地址 |
ROCKET_CLOUD_AUTH_TOKEN |
WS 鉴权 |
ROCKET_CLOUD_DEVICE_ID |
设备 ID(可选) |
ROCKET_CLOUD_EXECUTE_FLIGHT |
1:云端 flight_intent 在机端执行 |
ROCKET_FLIGHT_INTENT_ROS_BRIDGE |
1:执行方式为 发布到 ROS /input,不跑机内 Socket+offboard 序列 |
ROCKET_FLIGHT_BRIDGE_TOPIC |
默认 /input |
ROCKET_FLIGHT_BRIDGE_SETUP |
子进程内 source ROS 的命令,默认 source /opt/ros/noetic/setup.bash |
ROCKET_FLIGHT_BRIDGE_WAIT_SUB |
发布前等待订阅者的秒数,默认 2;0 即尽可能快发 |
ROCKET_LOCAL_KEYWORD_TAKEOFF |
非空时:1/true/yes 开启 keywords.yaml takeoff → 本地 offboard |
ROCKET_CLOUD_PX4_CONTEXT_FILE |
覆盖 cloud_voice.px4_context_file,合并进 session.start |
更多调试变量见 voice_drone/main_app.py 文件头注释 与 PROJECT_GUIDE.md 第 5 节。
6. 联调与自测
6.1 仅测 ROS 链(无语音)
终端已 source /opt/ros/noetic/setup.bash 且与 master 一致:
rostopic pub -1 /input std_msgs/String \
"data: '{\"is_flight_intent\":true,\"version\":1,\"actions\":[{\"type\":\"land\",\"args\":{}}],\"summary\":\"测\"}'"
注意:std_msgs/String 在命令行里只能写 data: '...json...',不能把 JSON 放在消息顶层。
6.2 确认话题与 master
source /opt/ros/noetic/setup.bash
export ROS_MASTER_URI=http://127.0.0.1:11311
rosnode list
rostopic info /input
rosservice list | grep set_mode
若 Unable to communicate with master!:当前 shell 未连上正在运行的 roscore(或未 export 正确 ROS_MASTER_URI)。
7. 常见问题(摘录)
| 现象 | 可能原因 | 处理 |
|---|---|---|
ModuleNotFoundError: rospy |
子进程未继承 ROS 的 PYTHONPATH |
已修复为 PYTHONPATH=<根>:$PYTHONPATH;确保 ROCKET_FLIGHT_BRIDGE_SETUP 能 source Noetic |
| 语音端「已发布」但桥无日志 | 曾用相对 input,与全局 /input 不一致 |
伴飞桥默认已改为订阅 /input;重启桥 |
set_mode unavailable / land 失败 |
OFFBOARD 断流、MAVROS 异常等 | 伴飞桥降落逻辑已带持续 setpoint + 重连 proxy;仍失败则查 rosservice、/mavros/state、链路 |
| takeoff 超时 | 未进 OFFBOARD、未解锁、定位未就绪 | 查地面站、/mavros/state、适当增大 ~takeoff_timeout_sec(ROS 私有参数) |
| ALSA underrun | 播放与采集竞争 | 板端常见;可调缓冲区/设备或 recognizer.ack_pause_mic_for_playback |
8. 安全与运维建议
- 外场前在 SITL 或系留 环境验证完整
flight_intent序列。 - 云端 token、WS URL 勿提交到公开仓库;用环境变量或本机 overlay 配置注入。
- 升级伴飞桥或 MAVROS 后清日志重试一遍
/input手发 JSON。
9. 迁移到另一台香橙派:是否只拷贝 voice_drone_assistant 即可?
结论:目录是「代码 + 配置」的核心载体,但仅靠「整文件夹 scp 过去」通常不够;新板必须再装系统级依赖、模型与(可选)ROS,并按现场改配置。
9.1 拷贝目录本身会带上什么
| 已包含 | 说明 |
|---|---|
全部 Python 源码、voice_drone/config/*.yaml 默认配置 |
可直接改 YAML / 环境变量适配新环境 |
scripts/、with_system_alsa.sh、docs/ |
启动与说明在包内 |
9.2 新板必须单独准备(不随目录自动存在)
| 项 | 说明 |
|---|---|
| Ubuntu + 音频/ALSA | 与当前开发板同代或自行适配;录音设备索引可能变化,需重选或设 ROCKET_INPUT_DEVICE_INDEX |
pip install -r requirements.txt |
每台新 Python 环境执行一次(或整体迁移同一 conda 目录) |
models/ |
STT/TTS/VAD 体积大,务必在本机先 bash scripts/bundle_for_device.sh /path/to/rocket_drone_audio 或手工拷入,见 models/README.txt |
cache/ GGUF |
纯云端可不强依赖;若需本地 Qwen 回退,拷贝或设 ROCKET_LLM_GGUF |
| ROS Noetic + MAVROS | apt 安装;伴飞桥方案 必选;rospy 不要指望只靠 pip |
| 云端连通 | 新板 IP/防火墙能访问 ROCKET_CLOUD_WS_URL;token 用环境变量注入 |
dialout 等权限 |
访问 /dev/ttyACM0 的用户加入 dialout,否则 MAVROS 无串口 |
system.yaml 现场差异 |
socket_server IP、可选 tts.output_device、若麦索引固定可写 audio.input_device_index |
9.3 推荐迁移流程(简表)
- 在旧机或 CI:bundle 模型 → 打包整个
voice_drone_assistant(含models/,按需含cache/)。 - 新香橙派:解压到任意路径,安装
requirements.txt、ROS+MAVROS、系统音频工具。 - 用
with_system_alsa.sh python main.py试麦与 STT;再按本文 §4 双终端起 桥 + 语音。 - 首次外场前做一次
rostopic pub /input手发 JSON(见 §6)。
9.4 常见误区
- 只拉 Git、不拷
models/:STT/TTS 启动即失败。 - 新板 Noetic 未装却开
ROCKET_FLIGHT_INTENT_ROS_BRIDGE:发布子进程仍可能报错。 - 假设麦克风设备号一定相同:Orange Pi 刷机或换内核后常变,以首次启动日志为准。
10. 文档索引
| 文档 | 用途 |
|---|---|
README.md |
仓库简介、模型、bundle |
PROJECT_GUIDE.md |
配置项与日常用法索引 |
| 本文 | 部署拓扑、启动顺序、环境变量、联调、§9 迁移清单 |
FLIGHT_BRIDGE_ROS1.md |
伴飞桥参数、PX4 行为、rostopic pub 注意 |
FLIGHT_INTENT_SCHEMA_v1.md |
JSON 协议 |
llmcon.md |
云端协议 |
CLOUD_VOICE_FLIGHT_CONFIRM_v1.md |
飞控口头二次确认(闲聊不变、确认/取消/超时)云端与机端字段约定 |
文档版本与仓库同步;若行为与代码不一致,以当前 main_app.py、flight_bridge/*.py 为准。