单车上位机软件推荐采用"5 层 + 2 侧"架构 :
5 层 :硬件抽象层 → 驱动执行层 → 实时控制层 → 决策规划层 → 应用业务层
2 侧:诊断与运维侧、安全与保护侧(横切各层)
这样既符合主流机器人软件分层思想,也和 ROS2 那种"硬件驱动层--核心算法层--应用逻辑层"的 AGV 实践对齐。
一、整体架构一图看懂

二、各层职责 & 实时性要求
1. 硬件抽象层(HAL)
- 目标:屏蔽硬件差异,让上层软件不依赖具体传感器/驱动型号。
- 典型内容:
- 统一设备接口:
LidarDriver、ImuDriver、MotorDriver、IODriver等 - 对 GPIO / SPI / I2C / CAN / EtherCAT 等封装为统一 AP
- 热插拔、设备发现、故障上报
- 统一设备接口:
- 实时性:非实时或软实时,只在初始化/故障时慢一点没关系。
2. 驱动执行层
- 目标:把硬件数据"搬"上来,把控制指令"送"下去。
- 典型内容:
- 传感器驱动:激光雷达、IMU、编码器、超声波、视觉等数据采集
- 执行器驱动:电机驱动器、IO 模块、电磁阀等控制下发
- 总线通信:CAN / EtherCAT / Modbus / 串口 等协议栈
- 特点:
- 数据以原始/半原始形式发布:
/scan,/imu,/odom,/io_state等 - 控制接口接收速度/位置/IO 指令,转成帧下发给驱动器/PLC
- 数据以原始/半原始形式发布:
- 实时性:软~硬实时,周期通常 1--20ms,不能有大抖动。
3. 实时控制层
- 目标:闭环控制 + 实时安全,相当于 AGV 的"小脑"。
- 典型内容:
- 里程计 & 传感器融合:EKF/UKF 融合轮式里程计 + IMU + 视觉/SLAM 结果
- 轨迹跟踪控制器:Pure Pursuit、Stanley、MPC 或 PID,跟踪上层轨迹
- 速度/加速度限制、加减速曲线规划
- 实时安全逻辑:防撞区、限速、急停联动、防溜坡等
- 实时性:硬实时,周期 1--10ms,必须优先级最高,不允许被非实时任务抢占。
- 与下位机分工:
- 若你车上有独立 PLC/MCU 做电流/速度环,这层主要做位姿轨迹级控制;
- 若工控机直接驱动电机,则这层要下到速度/电流环,实时性要求更苛刻。
4. 决策规划层
- 目标:从"我在哪、要去哪"到"怎么走、怎么避障",是单车智能的核心。
- 典型内容:
- SLAM / 地图服务:Cartographer、Gmapping、SLAM Toolbox 等
- 定位:AMCL / UWB / 二维码定位 / 视觉定位
- 全局路径规划:A*、Dijkstra、NavFn 等
- 局部规划与避障:DWA、TEB、Time Elastic Band 等
- 行为树 / 状态机:长任务拆解、异常恢复、降级模式
- 单车任务调度:本车任务队列、优先级、超时处理
- 实时性:软实时,周期通常 50--200ms,偶尔抖动影响不大,但不要秒级卡顿。
- 与多车调度系统的关系:
- 这层只管本车:局部避障、路径跟踪、单任务执行;
- 多车交通管制、任务分配由车间调度上位机完成。
5. 应用业务层
- 目标:对外接口 + 人机交互 + 运维,是"看得见摸得着"的部分。
- 典型内容:
- 任务接口:与调度/MES/WMS 通信(REST/MQTT/OPC UA/自定义 TCP)
- 本地任务状态机:排队、执行、暂停、取消、完成上报
- 本地 HMI:Web/Qt/RViz2 界面,显示地图、位置、任务、电量、报警
- 日志与远程诊断:运行日志、故障记录、远程升级(OTA)
- 参数配置:地图、车辆参数、导航参数、网络配置等
- 实时性:非实时,只要别让界面卡到影响操作即可。
三、横切:诊断与运维 / 安全与保护
这两块不是单独一层,而是贯穿各层的"横切关注点"。
1. 诊断与运维侧
- 日志系统:分级日志(DEBUG/INFO/WARN/ERROR),按模块/时间归档
- 报警与事件:故障码、报警等级、上报云端/本地 HMI
- 远程诊断:通过 VPN/云平台查看状态、下发指令
- 固件/软件升级:驱动、算法、应用的版本管理与升级
2. 安全与保护侧
- 急停链路:硬件急停 → 驱动层立即断使能 → 控制层零速度 → 规划层标记不可运行
- 安全区域/限速:充电区、人区、门口等区域限速、禁止进入
- 传感器故障保护:雷达/IMU/编码器故障时降级(慢行/停驶/回退安全点)
- 看门狗 & 监控:进程挂死自动重启、关键线程超时报警
四、和 ROS2 的典型映射(如果你用 ROS2)
以 ROS2 + Nav2 为例,可以很自然地套到上面的分层里:
| 分层 | ROS2 典型节点/包 | 说明 |
|---|---|---|
| 硬件抽象层 | xxx_bringup、xxx_hal |
统一封装传感器/驱动,对外提供 ROS2 接口 |
| 驱动执行层 | rplidar_ros、imu_driver、base_driver |
发布 /scan、/imu、/odom,订阅 /cmd_vel |
| 实时控制层 | controller_manager + 自定义 controller |
订阅轨迹/路径,发布 /cmd_vel,做跟踪/安全限制 |
| 决策规划层 | nav2_navfn_planner、nav2_dwb_controller、slam_toolbox |
全局/局部规划、SLAM、行为树 |
| 应用业务层 | agv_task_manager、agv_hmi、agv_diag |
任务接口、HMI、日志/远程升级 |
五、如果你不用 ROS,怎么落地?
一个偏嵌入式/自研的实践方案,可以参考"组态式 AGV 导航控制嵌入式软件架构"的思路:bsp 层 / drv 层 / app 层 / com 组件层。对应到上面 5 层,大致是:
- bsp + drv 层:对应这里的 硬件抽象层 + 驱动执行层
- app 层:对应 实时控制层 + 决策规划层 + 应用业务层
- com 组件层:把 PID、任务管理、日志、参数等做成通用组件,被 app 层调用
技术栈可以选:
- OS:Linux + 实时扩展(Xenomai/RT‑Preempt)或 RTOS(QNX/RT‑Thread)
- 通信:自定义二进制帧 / Modbus TCP / 自研协议栈(类似 RoboLink/CVC2.0 那种)
- 语言:C/C++ 做实时控制,Python/Go/C# 做业务 & 接口
六、设计时几个关键决策点
-
实时边界在哪?
- 建议:控制层以上可以非实时,控制层及以下必须硬实时。
- 不要在控制周期里做 SLAM / 大规划 / 网络请求。
-
任务/状态机怎么拆?
- 把"任务"拆成:
Idle → NavToPick → Loading → NavToPlace → Unloading → Idle - 每个状态对应不同的规划/控制策略(是否允许避障、是否限速等)。
- 把"任务"拆成:
-
与多车调度如何分工?
- 单车上位机:只管"怎么去"(路径/避障/控制)
- 车间调度:管"谁去、什么时候去、走哪条大路线"
-
安全等级如何映射?
- 把安全要求拆成:硬件级(驱动层)、控制级(控制层)、业务级(应用层),三层都要有防护,而不是只在"上位机界面"里加急停按钮。