跳到主要内容

二次开发

本页说明 UGV 的开发环境、官方接口、最小验证方法和恢复流程。具体应用功能由开发目标决定,本文不包含所有项目场景的完整业务实现。

提示

本页覆盖开发环境、官方接口和最小开发链路。视觉应用、Web 应用、自动巡检、AI 服务、导航策略和新增硬件等功能,需要根据实际项目设计和验证。

开发架构与入口

开发环境分层

开发内容推荐环境说明
Notebook、视觉和参数调整Jetson / JupyterLab用于原型验证,详细操作见 上位机教程
普通 Python 项目Jetson 上位机个人项目目录使用个人 .venv,不替换官方环境
Web 扩展Jetson / Flask使用独立页面或独立端口,不覆盖官方主流程
ROS 2 节点ROS 2 Docker使用个人 overlay,不写入官方 ugv_ws/src
JSON 接口Jetson → ESP32调用已有下位机功能,详见 下位机教程
ESP32 固件Windows / Arduino IDE / Flash Download Tool编译 Arduino 工程包,或直接写入 Flash 下载包

官方资源

资源用途入口
Jetson 上位机源码Web、视觉和上位机功能相关资料中的“Jetson 上位机源码”
ROS 2 工作空间源码ROS 2 驱动和功能包相关资料中的“ROS 2 工作空间源码”
下位机固件(Arduino 工程包)Arduino IDE 编译和上传相关资料中的“Arduino 工程包”
下位机固件(Flash 下载包)通过下载工具直接写入相关资料中的“Flash 下载包”
下位机驱动板原理图下位机接口与硬件电路参考相关资料中的“下位机驱动板原理图”

~/ugv_jetson 是官方上位机程序目录,/home/ws/ugv_ws 是 ROS 2 Docker 内的官方工作空间。保留它们的原始状态,个人代码使用后文的独立目录与 overlay。

开放接口索引

接口用途安全边界
JupyterLab / Notebook视觉、参数和原型验证摄像头或串口只能由一个程序占用
Web 上位机程序状态查看与既有功能新接口先独立运行,不修改 app.py 主流程
JSON 指令下位机已有控制和状态能力/send_command 的风险取决于具体命令内容
ROS 2 Topic状态订阅、定位、传感器和控制/voltage/scan/odom 为只读入口;/cmd_vel 和导航目标为控制入口
下位机固件ESP32 程序文件和下载工具操作前确认使用 Arduino 工程包还是 Flash 下载包

如何选择开发入口

开发目标推荐入口最小验证参考
视觉算法JupyterLab复制并运行官方 Notebook上位机教程
普通 Python 功能上位机个人项目运行只读脚本官方上位机源码
Web 扩展独立端口返回只读 JSON官方上位机源码
ROS 2 扩展个人 overlay运行只读电压节点ROS 2 教程
下位机接口JSON执行已有低风险指令下位机教程
固件编译与上传Arduino IDE打开 ROS_Driver.ino 并完成验证编译Arduino 工程包
固件直接写入Flash Download Tool打开下载工具并识别目标 COMFlash 下载包

上位机开发环境

本节在 Jetson 上位机中建立与官方程序隔离的个人项目目录和 Python 环境。

JupyterLab 的打开方式,以及 Notebook、Console 和 Terminal 的基础操作,见 上位机教程。官方程序保留在 ~/ugv_jetson;普通自定义代码保存在 ~/ugv_projects 的上位机个人项目中。

创建个人项目

mkdir -p ~/ugv_projects/my_project/{scripts,configs,logs,data,tests,notebooks}
cd ~/ugv_projects/my_project

该操作不访问串口、摄像头和底盘。创建失败时,检查当前账号、主目录权限和剩余空间。

Python 虚拟环境

上位机个人项目使用 ~/ugv_projects/my_project/.venv。官方 Web 和上位机程序的 ~/ugv_jetson/ugv-env 不作为所有自定义任务的默认解释器。

cd ~/ugv_projects/my_project
python3 -m venv .venv
source .venv/bin/activate
which python
python --version
pip --version
deactivate

不要运行无目标的 pip install --upgrade,也不要随意替换 OpenCV、NumPy、MediaPipe、DepthAI 或系统 Python。摄像头、GPIO 和 Jetson 系统库是否需要 --system-site-packages,应由当前镜像和实际依赖决定。

个人项目版本管理

Git 只管理上位机个人项目:

cd ~/ugv_projects/my_project
git init
git status
git diff
.venv/
__pycache__/
*.pyc
logs/
data/
.ipynb_checkpoints/

不要用上位机个人项目仓库覆盖 ~/ugv_jetson/home/ws/ugv_ws,也不要将不明确的全目录回退作为默认操作。

最小环境验证

scripts/project_check.py 中保存以下脚本。它只使用 Python 标准库,不访问串口、摄像头、JSON、ROS 2、LED、云台或底盘:

import platform
import sys
from pathlib import Path

project_dir = Path("~/ugv_projects/my_project").expanduser()
log_dir = project_dir / "logs"
log_dir.mkdir(parents=True, exist_ok=True)

print("Python:", sys.version)
print("Platform:", platform.platform())
print("Project:", project_dir)
print("Log directory:", log_dir)
print("Project exists:", project_dir.exists())

激活个人环境后,执行 python scripts/project_check.py。输出包含 Python 版本、系统信息和目录状态;失败时检查 .venv、脚本路径与主目录权限。

ROS 2 开发环境

进入 Docker 和加载 ROS 2 环境的步骤见 ROS 2 教程。以下说明个人 overlay 的最小开发链路。

官方工作空间与个人工作空间

官方工作空间为 /home/ws/ugv_ws。推荐的个人 overlay 为 /home/ws/ugv_ws/ugv_custom_ws:它位于已挂载的官方工作空间目录内,但不写入官方 ugv_ws/src

首次使用前,在 Jetson 宿主机执行一次检查,确认目录来自持久化挂载且容器内可写:

docker inspect ugv_jetson_ros_humble --format '{{range .Mounts}}{{println .Source "->" .Destination}}{{end}}'
docker exec ugv_jetson_ros_humble sh -lc 'test -w /home/ws/ugv_ws && echo /home/ws/ugv_ws: writable'

只有输出显示 /home/ws/ugv_ws 为宿主机挂载目录且可写时,才使用该推荐路径。未满足该条件时,不要在容器临时目录创建个人工作空间;先恢复或确认官方 Docker 挂载,再继续。

创建自定义 overlay

在 ROS 2 Docker 中按系统 ROS 2、官方 underlay、个人 overlay 的顺序执行:

source /opt/ros/humble/setup.bash
source /home/ws/ugv_ws/install/setup.bash
export UGV_CUSTOM_WS=/home/ws/ugv_ws/ugv_custom_ws
mkdir -p "$UGV_CUSTOM_WS/src"
cd "$UGV_CUSTOM_WS/src"
ros2 pkg create ugv_custom_monitor --build-type ament_python --dependencies rclpy std_msgs

最小只读节点验证

ugv_custom_monitor/ugv_custom_monitor/voltage_monitor.py 中保存以下节点:

import rclpy
from rclpy.node import Node
from std_msgs.msg import Float32


class VoltageMonitor(Node):
def __init__(self):
super().__init__("voltage_monitor")
self.create_subscription(Float32, "/voltage", self.on_voltage, 10)

def on_voltage(self, msg):
self.get_logger().info(f"voltage: {msg.data:.2f} V")


def main(args=None):
rclpy.init(args=args)
node = VoltageMonitor()
try:
rclpy.spin(node)
finally:
node.destroy_node()
rclpy.shutdown()

将自动生成的 setup.py 中的 entry_points 替换为:

entry_points={
"console_scripts": [
"voltage_monitor = ugv_custom_monitor.voltage_monitor:main",
],
},

官方工作空间中的 /voltage 使用 std_msgs/msg/Float32。运行前执行 ros2 topic type /voltage;输出不是该类型时,不要运行此示例,以当前镜像实际类型为准。确认类型后构建并运行:

cd "$UGV_CUSTOM_WS"
colcon build --symlink-install --packages-select ugv_custom_monitor
source install/setup.bash
ros2 run ugv_custom_monitor voltage_monitor

节点只订阅 /voltage,不发布 /cmd_vel、导航目标或任何控制消息。按 Ctrl + C 停止。

停止与资源恢复

停止节点后检查终端没有残留个人进程。仅在确认当前目录为个人 overlay 后,才可清理其构建产物:

cd "$UGV_CUSTOM_WS"
pwd
rm -rf build install log

该命令只清理个人工作空间的构建目录,保留 src,不清理官方 /home/ws/ugv_ws

ESP32 下位机开发环境

调用既有 JSON 指令通常不需要重新写入 ESP32 固件。修改下位机程序或恢复下位机程序时,使用本节的 Arduino 工程包或 Flash 下载包。需要核对下位机接口、电源或外围电路时,参考 下位机驱动板原理图

获取官方工程与恢复包

下位机固件提供 Arduino 工程包和 Flash 下载包。两种固件包的用途和操作工具不同。

Arduino 工程包

下载 下位机固件(Arduino 工程包),解压后进入 ROS_Driver\ROS_Driver 目录。该目录包含 ROS_Driver.inodata 目录和配套头文件。

下位机固件 Arduino 工程目录

使用 Arduino IDE 打开 ROS_Driver.ino。工程目录中的 .ino.h 文件和 data 目录应保持原有结构。

Flash 下载包

下载 下位机固件(Flash 下载包),解压后保留原始副本。

进入 flash_download_tool_3.9.5\flash_download_tool_3.9.5 目录,可看到 bincombineconfiguredl_tempdoclogs 等目录,以及 flash_download_tool_3.9.5.exe

下位机固件包解压后的目录

Flash 下载包通过 Flash Download Tool 写入 ESP32,不作为 Arduino IDE 工程打开。工具包内的 configure\esp32\multi_download.conf 已关联 bin 目录中的程序文件和地址;运行工具时不要移动或拆分这些目录。

安装 Arduino IDE

Arduino IDE 用于打开、编译和上传 Arduino 工程包。前往 Arduino 官网 下载当前稳定版本;不要使用 alpha、beta、nightly 或预览版本。本次使用 Arduino IDE 2.3.10

如需中文界面,选择“文件” > “首选项”。

在 Arduino IDE 中打开首选项

在“语言”中选择“中文(简体)”,然后重新启动 Arduino IDE。界面语言不会影响编译或上传。

在 Arduino IDE 中选择中文界面

Arduino IDE 界面与常用操作

Arduino IDE 顶部从左到右依次提供“验证”和“上传”按钮;开发板选择框用于选择 ESP32 Dev Module,串口选择位于“工具” > “端口”。编辑区域上方的项目文件标签用于切换 .ino.h 文件,底部输出区域显示编译、连接和写入信息。

Arduino IDE 的功能区域

配置 ESP32 开发板环境

  1. 打开 Arduino IDE,选择“文件” > “首选项”。
  2. 在“附加开发板管理器网址”中添加 Espressif 官方开发板源,点击“确定”保存设置:
https://espressif.github.io/arduino-esp32/package_esp32_index.json

Arduino IDE 首选项中的 Espressif 默认开发板源

中国大陆网络访问 GitHub 工具链超时,或出现 GitHub HEAD request、crosstool-NG、连接超时等错误时,使用以下镜像地址替换默认源。默认源和中国镜像二选一,不要同时添加:

https://jihulab.com/esp-mirror/espressif/arduino-esp32/-/raw/gh-pages/package_esp32_index_cn.json

Arduino IDE 首选项中的中国镜像地址

  1. 选择“工具” > “开发板” > “开发板管理器”,搜索 ESP32,选择 esp32 by Espressif Systems

  2. 使用默认源时,安装 2.0.11;使用中国镜像时,安装 2.0.11-cn。不要点击“全部更新”。

Arduino IDE 中选择 ESP32 Arduino Core 2.0.11-cn

  1. 安装完成后重启 Arduino IDE,再选择“工具” > “开发板” > “ESP32” > ESP32 Dev Module

  2. 再次打开“工具”菜单,确认开发板显示为 ESP32 Dev Module,并按下图设置其它选项。各项数值也可在“开发者参数与工程说明”中查看。

选择 ESP32 Dev Module 并设置工具菜单参数

图中的 COM14 仅用于说明菜单位置。上传时应选择连接 ESP32 后新增的端口,不要套用固定 COM 号。

提示

Arduino IDE 可以使用当前稳定版本;本次使用 Arduino IDE 2.3.10

当前 ROS_Driver 工程使用 ESP32 Arduino Core 2.0.11。使用中国镜像时,选择对应的 2.0.11-cn

ESP32 Arduino Core 3.x 已调整 LEDC 和 ESP-NOW API,直接编译当前官方工程会出现 ledcSetupledcAttachPin 或 ESP-NOW 回调类型不兼容等错误。不要为适配 3.x 直接修改官方源码,也不要自动升级开发板包。

3.3.10-cn 可以完成开发板包安装和 BareMinimum 编译,但不能编译当前官方 ROS_Driver 工程。

切换版本后,先编译 BareMinimum,再编译未修改的官方 ROS_Driver.ino

验证 ESP32 开发板环境

在安装 UGV 依赖库前,先确认 ESP32 Arduino Core 和工具链能够独立工作:

  1. 打开“文件” > “示例” > “01.Basics” > BareMinimum
  2. 选择 ESP32 Dev Module
  3. 点击“验证”。

此步骤不需要连接实体设备。编译成功后再安装 UGV 依赖库。

BareMinimum 编译完成

通过时,不应出现 ESP32 系统头文件或工具链文件缺失,例如 esp_idf_version.hesp_system.h 等开发板包内部错误。

报错位置优先检查
Arduino15\packages\esp32ESP32 Arduino Core 安装不完整或已损坏。
Sketchbook 的 libraries第三方依赖库缺失、重复或版本冲突。
ROS_Driver 工程目录工程结构或源码文件缺失。
编译器或 tools 目录工具链下载或解压不完整。

esp_idf_version.h: No such file or directory 表示 ESP32 Arduino Core 的内部文件缺失,不应通过修改 UGV 固件源码或手工补充单个头文件处理。

可按以下顺序恢复开发板环境:关闭 Arduino IDE → 在开发板管理器中卸载 ESP32 开发板包 → 删除损坏的 Arduino15\packages\esp32 目录 → 重新安装 ESP32 Arduino Core → 再次编译 BareMinimum。不要删除整个 Sketchbook 或个人工程目录。

确认 Sketchbook 路径

在 Arduino IDE 中打开“文件” > “首选项”,查看或修改“项目文件夹地址”。依赖库的通用路径为:

<Arduino 项目文件夹地址>\libraries

本次测试电脑的路径为:

E:\Arduino-Sketchbook\libraries

Arduino IDE 首选项中的项目文件夹地址

E:\Arduino-Sketchbook 仅为本文示例,不是固定路径。

安装依赖库

下载并解压 UGV 的 Arduino 依赖库压缩包。关闭 Arduino IDE 后,将压缩包内各独立库文件夹复制到已确认的 <Arduino 项目文件夹地址>\libraries

每个库目录应直接位于 <Sketchbook>\libraries,并包含 library.propertiessrc 或主要头文件。不要形成:

E:\Arduino-Sketchbook\libraries\libraries\ArduinoJson

正确的目录结构为:

E:\Arduino-Sketchbook\libraries\ArduinoJson

依赖库使用官方 Libraries.zip 中的版本,不执行“全部更新”。依赖库已经复制但仍提示头文件不存在时,先检查是否多出一层 libraries;批量检查与整理方法见 产品 FAQ

验证编译

按以下顺序验证,避免先排查已修改工程:

BareMinimum
→ 官方原始 ROS_Driver.ino
→ 修改后的工程

打开 ROS_Driver\ROS_Driver\ROS_Driver.ino,确认已选择 ESP32 Dev Module,然后点击“验证”。验证编译不会写入实体设备。

Arduino IDE 中打开官方 ROS_Driver 工程

本次使用官方 Libraries.zip 中的依赖库、ESP32 Arduino Core 2.0.11-cnESP32 Dev Module 编译未修改的官方 ROS_Driver.ino,编译通过。

现象优先检查
ESP32 系统头文件或 tools 文件缺失先重新安装 ESP32 Arduino Core,并重新编译 BareMinimum
UGV 第三方库头文件缺失检查 <Sketchbook 路径>\libraries 中是否缺少压缩包内对应库。
找到多个同名库将旧库移出 Sketchbook 的 libraries 目录后再次编译。
.ino.h 文件不在同一工程目录恢复 ROS_Driver\ROS_Driver 的原始目录层级。
API 或类型不兼容检查 ESP32 Arduino Core 与官方依赖库的版本组合;不要直接修改工程以绕过错误。
开发者参数与工程说明
设置使用值
Arduino IDE2.3.10
ESP32 Arduino Core2.0.11-cn
BoardESP32 Dev Module
CPU Frequency240MHz (WiFi/BT)
Core Debug LevelNone
Erase All Flash Before Sketch UploadEnabled
Events Run OnCore 1
Flash Frequency80MHz
Flash ModeQIO
Flash Size4MB (32Mb)
JTAG AdapterDisabled
Arduino Runs OnCore 1
Partition SchemeDefault 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
PSRAMEnabled
Upload Speed921600

上表与本页工具菜单参数图一致。不要套用其它产品的参数。Arduino IDE 的 Upload Speed 与 Flash Download Tool 的 BAUD 是不同设置。

Erase All Flash Before Sketch Upload 设为 Enabled 后,上传会清除 ESP32 中的现有内容。上传前应保留当前自定义源码,并准备 Flash 下载包。

data 是 LittleFS 的配置文件源目录,不是已转换并编入头文件的资源。普通“上传草图”不会自动把该目录写入文件系统。当前工程包未提供单独的 LittleFS 上传工具或操作说明;保持工程原始目录结构即可。只有需要把 data 中的配置写入设备时,才使用适配当前 ESP32 Arduino Core 的 LittleFS 上传工具。不要将其中的配置文件作为公开示例,也不要在未确认用途前用其它文件覆盖设备内已有配置。

ESP32 Arduino Core 2.x3.x 的 LEDC、ESP-NOW API 存在差异。当前官方 ROS_Driver 工程使用 2.0.112.0.11-cn,不修改官方源码以兼容 3.x

上传前准备

完成验证编译后,再按以下顺序准备实体上传:

停止 Web、Notebook、ROS 2 和自定义控制程序
→ 确认底盘已停止
→ 正常停止可能占用串口的上位机程序
→ 关闭产品电源
→ 连接 ESP32 下载 USB
→ 在设备管理器确认新增 COM
→ 再执行上传

按下图露出下位机主控,并连接标出的 USB 通信/下载接口。

UGV 下位机 USB 通信与下载接口位置

使用支持数据传输的 USB 线。在 Windows 设备管理器中对比连接前后的端口,选择新出现的 ESP32 COM;不要选择雷达对应端口,也不要套用固定 COM 号。找不到新增 COM 时,依次检查数据线、USB 接口和实际 USB 转串口芯片对应的驱动,不笼统安装“Arduino USB Driver”。

Arduino IDE 中“工具 &gt; 端口”的 ESP32 COM 选择位置

写入下位机固件

使用 Arduino IDE

  1. 打开官方原始 ROS_Driver.ino
  2. 选择 ESP32 Arduino Core 2.0.11,中国镜像环境选择 2.0.11-cn
  3. 选择 ESP32 Dev Module,并使用“开发者参数与工程说明”中的工具菜单值。
  4. 选择新增的 ESP32 COM,确认未选择雷达端口。
  5. 点击“上传”,依次观察编译、连接和写入阶段。
  6. 写入完成后,按驱动板说明复位或重新上电。

上传失败时,先检查数据线、COM、驱动、供电、ESP32 Arduino Core 和工具菜单参数。

写入后基础验证

写入后按低风险到高风险顺序检查。每一步异常时均停止后续测试,先停止当前控制入口并恢复下位机固件,再重新开始基础验证。

顺序检查内容正常现象与停止方式
1ESP32 启动启动后无持续复位或异常提示;异常时断开下载 USB 并停止后续测试。
2OLED 或启动信息显示内容或启动信息恢复;异常时不继续发送控制指令。
3Jetson 下位机反馈上位机可重新收到下位机反馈;异常时停止上位机控制程序。
4电压可读取电压反馈;异常时检查供电后再继续。
5IMU可读取 IMU 反馈;异常时停止传感器相关测试。
6编码器可读取编码器反馈;异常时不进行运动测试。
7LED通过已有低风险指令确认 LED;异常时发送关闭指令。
8OLED 指令通过已有指令显示并恢复默认内容;异常时停止发送指令。
9云台小角度动作使用已有指令进行小角度、低速动作;异常时停止控制并检查线缆。
10架空底盘短时低速动作架空底盘后进行短时低速动作,结束立即发送停止指令。
11Web、Notebook 和 ROS 2依次恢复既有程序,确认不会重复占用串口或摄像头。

产品类型、模块类型、串口波特率、JSON 通信和心跳停止逻辑的检查入口见 下位机教程。无法确认自定义固件的影响时,使用 Flash 下载包恢复下位机程序后,再从低风险项目开始检查。

Flash Download Tool 恢复

  1. 在保留 binconfigure 等原始目录结构的前提下,运行 Flash 下载包中的 flash_download_tool_3.9.5.exe
  2. 在启动窗口中选择 ChipType ESP32、WorkMode Factory 和 LoadMode UART,然后点击 OK

Flash Download Tool 的 ESP32 Factory 启动选项

  1. 进入 FactoryMultiDownload 界面后,确认左侧已经加载以下程序文件和地址:
程序文件地址
bin\boot_app0.bin0xe000
bin\ROS_Driver.ino.bootloader.bin0x1000
bin\ROS_Driver.ino.bin0x10000
bin\ROS_Driver.ino.partitions.bin0x8000

Flash Download Tool 已加载固件包配置

保留固件包中的预配置和 LockSettings 状态,不手工修改程序文件、地址、SPI SPEED 或 SPI MODE。 界面中的 PASSFAIL 计数可能包含此前的下载记录,当前写入结果应以本次操作结束后的状态为准。

  1. DownloadPanel 1 中选择连接 ESP32 后新增的 COM。下拉列表中的其它端口可能属于雷达或其它设备,不要按截图套用固定端口号。

在 Flash Download Tool 中选择 ESP32 串口

  1. 确认 BAUD 为 921600,然后点击左下角的 START ALL 开始写入。Flash Download Tool 的 BAUD 与 Arduino IDE 的 Upload Speed 是不同设置,不要互相替代。

在 Flash Download Tool 中点击 START ALL

  1. 等待工具完成写入。显示 FINISH 后,再按驱动板说明复位或重新上电。写入过程中不要断开 USB 或产品电源。

写入失败时,先检查 USB 数据线、COM、供电和固件包完整性。Arduino IDE 方式还应检查 ESP32 Arduino Core、依赖库和工具参数;Flash Download Tool 方式还应检查是否在完整的固件包目录中运行工具。

通用开发方法
  • 将官方 Notebook、脚本或源码复制到上位机个人项目后再修改。Notebook 原型先显示数据或图像结果,不连续控制底盘;详细操作见 上位机教程
  • 接入真实接口前,先使用 dry-run 输出计划、参数和日志。日志记录启动、配置、关键操作、异常和停止。
  • 对速度、角度、持续时间和重复次数设置合理范围,并处理无效参数、通信中断和超时。
  • 控制程序应提供人工停止方式,并在异常路径中执行停止逻辑。停止一个控制入口后,再启动另一个入口。
  • 部署前完成手动启动、停止、禁用和日志查看验证。依赖串口、摄像头或 ROS 2 的任务不套用通用服务模板。

二次开发验收

部署前记录自定义任务的启动、停止、资源占用和回退方法;确认恢复官方程序后,Web、下位机反馈和 ROS 2 基础功能正常。