# d360_deploy **Repository Path**: electech6/d360_deploy ## Basic Information - **Project Name**: d360_deploy - **Description**: D360 一键部署脚本 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-09 - **Last Updated**: 2026-09-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # d360_deploy D360 设备部署脚本(Jetson + Ubuntu 20.04 + ROS1 Noetic) **两个版本 + 两个可选附加组件,互不影响:** | 版本 / 组件 | 装什么 | 是否默认执行 | |---|---|---| | **基础版本**:`setup_env.bash` | 基础三容器 `core` / `firmware-sensors` / `ota_web` + 环境(Docker/ROS/串口别名/**图传链路静态 IP**) | 一键,装机会跑 | | **导航进阶版本**:`nav2d/install_2d_nav.sh` | 在基础版本之上**追加**:2D 导航容器 `scout-nav` | **默认不装,必须手动执行** | | **附加硬件(可选)**:`udev_rules/install_extra_serial_aliases.sh` | 在任意版本之上**追加**:BOX 六麦阵列(`/dev/lg_speech_serial`)等附加串口别名 | **默认不装,必须手动执行** | | **语音助手(可选)**:`voice/install_voice_assistant.sh` | 在**导航起来之后**追加:唤醒「小飞小飞」+ 本地离线识别 + 对话回复/到点播报。**独立容器镜像** `d360_voice_assistant` + compose 服务 `voice-assistant`,另加一个宿主 systemd 单元(给导航容器补音频节点,见下) | **默认不装,必须手动执行** | > 版本构成:**基础版本** = 上表第 1 行;**导航进阶版本** = 基础版本 + 第 2 行。第 3、4 行与版本无关,按设备实际硬件与需求决定。 > > **顺序约束(语音)**:`voice/` 必须在**导航容器 `scout-nav` 起来之后**再装——语音容器的启动门禁检查 `/dev/lg_speech_serial`、六麦声卡、USB 音箱、`5011/health`(容器内讯飞网关)与 `5000/health`(导航 API),导航未就绪时识别进程会一直等待(不会报错退出)。 > > **语音还要装一个宿主单元**:`slamibot-audio-node-sync.service`。导航容器在启动那一刻快照了 `/dev/snd`,而六麦阵列/USB 音箱是开机后几十秒到十几分钟才枚举出来——没有这个单元,导航的**到点播报会静默无声**。语音进容器后宿主不再有语音进程,这段逻辑必须独立成单元(安装脚本会自动装并启用)。 > > 四者**完全解耦**:`setup_env.bash` 不会调用后三者,也不会往 compose 里写导航服务;附加硬件脚本**不改写**基础脚本生成的 STM32/RTK/DOG/Gimbal 规则行,只在规则文件里加一个带 `BEGIN/END` 标记的独立区块——装完一眼能看出哪些行来自附加组件,不会和基础版本混在一起。 --- ## 一、基础装机(一键,三容器) ```bash bash <(curl -fsSL https://gitee.com/electech6/d360_deploy/raw/master/setup_env.bash) ``` 脚本做的事: 1. 安装 python3-pip、jetson-stats 2. 通过 fishros 安装 Docker 与 ROS1 Noetic 3. 安装 pyserial 4. 安装 udev 规则(`/dev/ttyRTK`、`/dev/ttySTM32`),检查串口 5. **配置图传链路静态 IP 档案**(下载并执行 `net/install_static_ips.sh`,见下一节) 6. 把 `docker-compose.yml` 部署到 `/etc/slamibot/system/` 并 `docker compose up -d` 7. 打印 FRP 客户端配置提示 > **机型差异:前相机位置(不需要任何配置)**:新机型(715 那一代)的相机装法是 `CAM_A` = 前(中间)、`CAM_B` = 左、`CAM_C` = 右。 > 固件与导航的**代码默认值**已按新机型固化——导航订阅的相机话题默认就是 `/SLB_CAM_A/compressed`,开始作业预览的拼接顺序 `B,A,C`(左、前、右)与之对应。 > 所以现场装机**不需要**写任何配置文件、**不需要**跑任何脚本。 --- ## 二、图传链路静态 IP(基础装机自动执行) D360 有三条网络链路:**热点 / WiFi / 图传(video link)**。图传对端(实测 `192.168.144.11`) 要求本机在对应网口上有 `192.168.144.87/24` 才能通信,这个地址由 NetworkManager 档案提供。 `setup_env.bash` 第 5 步会自动下载并执行 `net/install_static_ips.sh`,**不需要手工操作**; 本节用于解释它在做什么、怎么自查、出问题怎么排查。 ### 为什么必须做这一步(事故复盘) 档案用 `connection.interface-name` **硬绑网卡名**,而**网卡名因机型而异**: | | 701(正常) | 715(不通) | |---|---|---| | NM 档案 | `eth2-static`(在用)+ `eth1-static`(未激活) | **两份都没有** | | 承载网卡 | `eth2`,UP 有载波 | `eth1`,UP 有载波但**无 IPv4** | | `ping 192.168.144.87` | 通 | 100% 丢包;APP 里改 IP 也连不上 | 现场表现是「**链路通、有载波、但没 IP**」——APP 里改 IP 之所以没用,是因为 APP 改的是 **档案里**的地址,档案缺失时没有任何东西可改。这种故障极难查,所以纳入一键装机。 ### 脚本怎么选网口(两层,不硬编码单一网卡名) 1. **自动探测**:在「有载波、当前无 IPv4、名字形如 `ethN`/`enpNsM`」的网口里挑**唯一**一个, 按它**实际的名字**建 `-static`;候选不唯一时**不猜**(避免把 `192.168.144.87` 配到雷达口上),会提示改用 `--ifname` 指定。 已知的非图传网口按 **USB VID:PID** 排除(比按名字判可靠): `0fe6:9900` = 雷达 USB-LAN(本机 `eth0` = `192.168.1.55`)、`2c7c:0125` = 4G 模块。 2. **约定兜底**:无论探测结果如何,都补齐 `eth1-static` / `eth2-static` 两份已知机型约定档案 (701 现场就是这么存的)——档案绑到不存在的网卡时 NM 不会激活它,无害。 档案名一律沿用 `-static` 约定(可能有别的东西按名字引用它)。 ### 常用参数 | 参数 | 说明 | |---|---| | `--ifname IF` | 明确指定图传网口(默认自动探测;候选不唯一或探测不到时用它) | | `--exclude IF[,IF]` | 额外排除网口(例如上述之外的雷达口) | | `--peer IP` | 图传对端地址,默认 `192.168.144.11`(只用于 `ip neigh` 验收判断) | | `--no-up` | 只建/校正档案,不激活 | | `--dry-run` | 只打印计划与将执行的 `nmcli` 命令,不改任何档案 | ### 自查 / 排查 ```bash # 只看计划(不改任何东西)——现场首选 sudo bash /tmp/install_static_ips.sh --dry-run # 网口名和 eth1/eth2 都不同时,明确指定 sudo bash /tmp/install_static_ips.sh --ifname eth1 # 验收三件套(脚本结束时会自动打印这些;把 <图传网口> 换成实际网口名) ip -4 -br addr show <图传网口> # 应有 192.168.144.87/24 ip route | grep 144 # 应有 192.168.144.0/24 dev <图传网口> ip neigh | grep 192.168.144 # REACHABLE = 对端在线、链路真通(比 ping 自己可靠) ``` 边界:脚本只新增/校正它自己的 `-static` 档案;**不动**其它档案、WiFi/热点/4G, 不删地址、不 flush 路由、不重启网络或设备;单步失败只报警,**不会让装机流程中断** (`setup_env.bash` 里也是失败只 `warn`,不影响其它步骤)。 > **默认路由优先级**(实测):`WiFi 600 < 4G 20102 < 图传 20103`。 > 图传口 metric 最大 = 最低优先级,**不抢上网流量**。若你看到图传口变成了 metric 最小的默认路由, > 那是网口插错了,先查线,不要靠在设备上改路由来绕(脚本结束时会打印默认路由改动前后的对比)。 > > **4G 上网卡的激活**不在此脚本范围内,也不会由我方代办:见 `net/CUSTOMER-4G-ACTIVATION.md`(客户自行开通 SIM 与套餐)。 --- ## 三、可选:2D 导航(`scout-nav`) **前提**:设备已买了 2D 导航套餐,且基础三容器已装好(`core` 在运行)。 **注意**:本步骤会往 `/etc/slamibot/system/docker-compose.yml` **新增一个** `scout-nav` 服务—— 没买套餐的设备请不要执行。 ```bash # 1) 取脚本 curl -fsSL -o /tmp/install_2d_nav.sh \ https://gitee.com/electech6/d360_deploy/raw/master/nav2d/install_2d_nav.sh # 2) 先看它要改什么(只打印,不动文件) sudo bash /tmp/install_2d_nav.sh --dry-run # 3) 正式安装 sudo bash /tmp/install_2d_nav.sh ``` 常用参数: | 参数 | 说明 | |---|---| | `--image TAG` | 镜像,默认 `registry.cn-shanghai.aliyuncs.com/slamibot/d360_nav2d:1.2.3` | | `--service NAME` | compose 服务名,默认 `scout-nav` | | `--data-dir PATH` | 数据根,默认 `/var/lib/slamibot/scout-nav` | | `--compose PATH` | compose 文件,默认 `/etc/slamibot/system/docker-compose.yml` | | `--no-pull` | 不联网拉镜像(只用本地已有) | | `--skip-sensor-check` | 跳过传感器前置检查 | | `--wait-sec N` | health 等待上限,默认 120 | | `--dry-run` | 只打印将写入的服务片段与 diff,不改任何文件 | 边界(脚本内已约束): - 只新增/更新 `scout-nav` 一个服务,**不动** `core` / `firmware-sensors` / `ota_web`; - 不删镜像、不 prune、不删数据; - compose 采用**最小文本插入**,改前自动备份为 `docker-compose.yml.bak-<时间戳>`,health 超时自动回滚。 ### 验收 ```bash curl -s http://127.0.0.1:5000/health # 期望 rosbridgeConnected:true ss -lntp | grep -E ':(80|5000|9090|19090)\b' # 四个端口都在听 浏览器 http://<设备IP>/app/ # 能看到界面 ``` 首次使用:容器起来后是 idle,需先切一次模式把基础感知层拉起,再建图/导航: ```bash curl -s 'http://127.0.0.1:5000/api/control/mode/navigation/ensure' curl -s -X POST http://127.0.0.1:5000/api/launch/mapping/start ``` ### 升级 / 回滚 ```bash # 升级:改 compose 里的 tag,或重跑脚本并指定 --image sudo bash /tmp/install_2d_nav.sh --image registry.cn-shanghai.aliyuncs.com/slamibot/d360_nav2d:1.2.3 # 回滚:用脚本自动留下的备份 sudo cp -p /etc/slamibot/system/docker-compose.yml.bak-<时间戳> /etc/slamibot/system/docker-compose.yml sudo docker compose -f /etc/slamibot/system/docker-compose.yml up -d scout-nav ``` ### 镜像版本 ``` registry.cn-shanghai.aliyuncs.com/slamibot/d360_nav2d:1.2.3 # 当前发布:不含任何开发地图 registry.cn-shanghai.aliyuncs.com/slamibot/d360_nav2d:1.2.2 # 只去掉会被 APP 登记的那批演示地图 registry.cn-shanghai.aliyuncs.com/slamibot/d360_nav2d:1.2.1 # 到点播报预热 + 缓存优先 registry.cn-shanghai.aliyuncs.com/slamibot/d360_nav2d:1.2 # 建图资源修复版 (1.1 缺 FAST-LIO 建图资源,勿用) ``` 镜像仓库为公开仓库,**无需 docker login**。新增设备时:先建图、再导航(1.2.2 起镜像不带演示地图,地图列表为空属正常)。 ### 基础装机跳过了 udev 时(导航版本可单独补跑) `setup_env.bash` 只在 `/dev/ttyRTK` 与 `/dev/ttySTM32` **都不存在**时才安装 udev 规则; 设备上若有旧符号链接,它会整段跳过——规则可能仍是旧拓扑。此时在导航版本上单独补跑一次: ```bash # 1) 先按当前拓扑重写基础串口规则(STM32 / RTK / DOG) curl -fsSL -o /tmp/setup_udev_rules.py \ https://gitee.com/electech6/d360_deploy/raw/master/udev_rules/setup_udev_rules.py sudo python3 /tmp/setup_udev_rules.py # 2) 再补附加硬件别名(BOX 六麦阵列),见下一节 curl -fsSL -o /tmp/install_extra_serial_aliases.sh \ https://gitee.com/electech6/d360_deploy/raw/master/udev_rules/install_extra_serial_aliases.sh sudo bash /tmp/install_extra_serial_aliases.sh --dry-run sudo bash /tmp/install_extra_serial_aliases.sh ``` > **顺序不能反**:`setup_udev_rules.py` 是整体重写规则文件,先跑附加脚本的话它的区块会被覆盖掉。 > 注意两台设备的 USB 拓扑可能不同(同一支 hub 下的相对位置一致,但绝对路径号可能不同,如 `1-2.1.x` 与 `1-2.3.x`),所以规则必须**按台核对**,不要照抄。 --- ## 四、可选:附加硬件串口别名(BOX 六麦阵列 / SBUS) **前提**:设备已装好基础版本(`/etc/udev/rules.d/99-serial-aliases.rules` 存在)。 **注意**:本脚本只**增补**附加硬件需要的别名,**不是**基础串口规则脚本——基础规则由 `udev_rules/setup_udev_rules.py` 生成、并由 `setup_env.bash` 自动调用,两者请勿混用。 ```bash # 1) 取脚本 curl -fsSL -o /tmp/install_extra_serial_aliases.sh \ https://gitee.com/electech6/d360_deploy/raw/master/udev_rules/install_extra_serial_aliases.sh # 2) 先看它要改什么(只打印,不动文件) sudo bash /tmp/install_extra_serial_aliases.sh --dry-run # 3) 正式安装 sudo bash /tmp/install_extra_serial_aliases.sh ``` 常用参数: | 参数 | 说明 | |---|---| | `--rules PATH` | 规则文件,默认 `/etc/udev/rules.d/99-serial-aliases.rules` | | `--box-kernel PATH` | BOX 控制串口的 USB 路径(默认按拓扑自动探测) | | `--dog-kernel PATH` | 额外写一条 DOG/SBUS 行到该 USB 路径(默认不动 DOG 相关) | | `--dry-run` | 只打印将写入的内容与 diff,不改任何文件 | 它做什么 / 不做什么: - 自动识别 BOX(ListenGo 六麦阵列 `2208:0001`)**同级的 CH340**,写成 `SYMLINK+="lg_speech_serial"`;复合设备自己的 `ttyACM` 口会枚举但**没有协议数据**,不能指它; - 只维护规则文件里 `BEGIN/END extra serial aliases` 之间的行,**不碰**基础脚本写的 STM32/RTK/DOG/Gimbal 行;重复执行幂等(内容没变化就不写入); - 若 BOX 同级有多颗 CH340 无法判定,会**列出候选**并按 D360 基准硬件的既定位置回落(`1-2.4.4.4`)**并打印警告**;此时建议用 `--box-kernel` 明确指定; - 改前把原文件临时存到 `/tmp/99-serial-aliases.rules.bak-<时间戳>`(重启即清),随后 `udevadm control --reload-rules` + `udevadm trigger --subsystem-match=tty`,并逐个校验别名。 ### 验收 ```bash ls -l /dev/lg_speech_serial # 期望指向某个 ttyUSB udevadm info -q property -n /dev/lg_speech_serial | grep DEVPATH # 期望 …/1-2.4.4.4/… ``` --- ## 五、目录 ``` setup_env.bash # 基础版本一键脚本 docker-compose.yml # 基础三容器定义(保持原样) udev_rules/setup_udev_rules.py # 基础串口别名规则(由 setup_env.bash 调用) net/install_static_ips.sh # 基础:图传链路静态 IP 档案(由 setup_env.bash 调用,也可单独跑) nav2d/install_2d_nav.sh # 可选:2D 导航(导航进阶版本) udev_rules/install_extra_serial_aliases.sh # 可选:附加硬件串口别名(BOX 六麦阵列 / SBUS) voice/ # 可选:语音助手(安装脚本 + 容器镜像定义 Dockerfile/build_and_push.sh + 客户指南) voice/install_voice_assistant.sh # 可选:语音助手安装器(写 compose 服务 voice-assistant + 宿主音频节点同步单元) net/CUSTOMER-4G-ACTIVATION.md # 客户文档:4G 上网卡怎么自行开通与验证(我方不代办激活) docs/DELIVERY-CLEANUP-CHECKLIST.md # 内部清单:交付前清理(凭据/密钥/测试数据/遗留物/免密 sudo) ``` > `net/install_static_ips.sh` 属**基础版本**的一部分(`setup_env.bash` 会自动调用它), > 但也可以单独重跑:`sudo bash net/install_static_ips.sh --dry-run`。 > 其余组件(nav2d / 附加硬件 / 语音)仍保持 opt-in,`setup_env.bash` 不会调用它们。