
04-无人车补货配送-前置仓与任务的枢纽作者黒漂技术佬系列URM Ultra 方案理念与架构篇前几篇我们把卖货的柜子讲透了。现在镜头转向物流——没人把货运过来柜子迟早空。URM Ultra 里负责运的是无人车。它在三端里位置很妙上接后台调度下接机械臂上货中间还杵着一个前置仓。可以说它是整套补货链路的枢纽。这一篇就把无人车讲明白它接什么任务、状态怎么流转、前置仓是怎么回事。一、无人车在三端里的位置回顾全景售货机管卖机械臂管上无人车管运。但运不是单一动作需求里明确写了无人车承接三类业务业务任务类型起点 → 终点一句话补货REPLENISH前置仓 → 售货机点位把货从仓运到柜子旁配送DELIVERY前置仓 → 收货点把货送到指定收货位置前置仓中转库存节点仓本身是库存/中转中心车在仓和用户间往返看明白没前置仓是无人车的老家和货源地。车从仓里取货运到目的地再回仓。没有前置仓车就是无源之水。前置仓(WH-0001) │ 取货 │ ┌──────┴───────┐ ▼ ▼ 售货机点位 收货点 (REPLENISH) (DELIVERY) │ │ ▼ ▼ 机械臂上货 送达完成二、三个核心模型Vehicle / VehicleTask / FrontWarehouse无人车这端在后台对应三张表我称为一车、一任务、一仓。2.1 Vehicle车本身// 项目源码无人车实体EntityTable(namevec_vehicle)publicclassVehicleextendsBaseEntity{Column(uniquetrue)privateStringvehicleNo;// 车牌号如 VEH-0001privateStringname;privateStringmodel;// 如园区配送车privateVehicleStatusstatus;// IDLE/BUSY/CHARGING/OFFLINE/FAULTprivateintbattery;// 电量百分比privateStringlocation;// 当前位置如前置仓privateLocalDateTimelastHeartbeat;}VehicleStatus五种状态比设备多了充电中和更细的忙闲publicenumVehicleStatus{IDLE,BUSY,CHARGING,OFFLINE,FAULT}battery是无人车特有的字段——它要跑路得有电。调度真上线时电量约束低电量不让派长途是必做的Demo 先留着字段。2.2 VehicleTask任务// 项目源码无人车任务EntityTable(namevec_vehicle_task)publicclassVehicleTaskextendsBaseEntity{Column(uniquetrue)privateStringtaskNo;// 任务号如 VT时间随机privateVehicleTaskTypetype;// REPLENISH / DELIVERYprivateVehicleTaskStatusstatus;// PENDING/DISPATCHED/EXECUTING/...privateLongvehicleId;// 派给哪台车privateStringfromLocation;// 起点privateStringtoLocation;// 终点privateStringpayload;// 载荷(JSON, 最长2000)privateStringrefNo;// 关联单号(补货计划号/配送单号)privateintpriority;// 优先级越小越先privateLocalDateTimestartedAt;privateLocalDateTimefinishedAt;}payload是个妙设计它用 JSON 字符串装这趟车拉了啥货。比如补货任务payload 里就是{deviceNo, items:[{slotNo, productName, quantity}]}。任务表不冗余建子表灵活又省事。refNo是任务挂靠业务单的纽带补货任务指向ReplenishPlan.planNo配送任务指向DeliveryOrder.deliveryNo。后台靠它把车跑一趟和为什么跑串起来。2.3 FrontWarehouse前置仓// 项目源码前置仓EntityTable(namevec_front_warehouse)publicclassFrontWarehouseextendsBaseEntity{Column(uniquetrue)privateStringcode;// 仓编码如 WH-0001privateStringname;// 中央前置仓privateStringlocation;privateintcapacity;// 容量如 5000}前置仓就是离用户近的小型仓库。大仓在城郊补货太慢在前置仓囤一批热销货车几分钟就能送到柜子。这是无人零售即时补货的关键设施。三、状态机车是怎么从闲到忙再闲的无人车的核心不是会跑而是状态可控。它的状态机长这样OFFLINE ──心跳──▶ IDLE ──领任务──▶ BUSY ──完成任务──▶ IDLE │ └──任务失败──▶ FAULT对应到VehicleTask这边任务也有自己的生命周期PENDING ──派发──▶ DISPATCHED ──领到──▶ EXECUTING ──▶ COMPLETED │ └──▶ FAILED我用一个真实场景串一遍项目源码逻辑车上线设备端心跳POST /device-api/vehicle/{no}/heartbeatVehicleService.heartbeat把OFFLINE→IDLE顺带报battery和location。建任务运营或系统建VehicleTask默认PENDING。派发dispatch(taskId, vehicleId)仅PENDING可派车置BUSY任务DISPATCHED。车领任务车端轮询GET /device-api/vehicle/{no}/task/nextnextTask先取定向派给我的 DISPATCHED 任务没有就按priority asc抢公开的 PENDING 任务置EXECUTING车保持BUSY。车上报执行完POST /device-api/vehicle/task/{no}/report?statusCOMPLETEDreportTask把任务置COMPLETED车BUSY→IDLE若上报FAILED车→FAULT。设计亮点定向派发和抢单并存。运营可以手动指定某台车定向也可以让车自己按优先级抢公开。真实调度里抢单模式配合路径规划、电量约束就能做就近派单。Demo 先把模式跑通。四、两类任务REPLENISH 与 DELIVERYVehicleTaskType只有两个值但撑起了无人车的全部活4.1 REPLENISH补货补货任务由补货计划派发时自动创建第 05 篇细讲联动。它的fromLocation前置仓toLocation售货机点位payload装着要补的货清单。车把这趟货送到柜子旁交给机械臂去上架。4.2 DELIVERY配送配送是另一条独立业务线——不一定是给柜子补货可能是给用户送个包裹。后台DeliveryOrder创建时同步建一个VehicleTask(DELIVERY)refNo指向deliveryNofromLocation前置仓toLocation收货点。// 项目源码逻辑创建配送单时联动建车任务DeliveryOrderordernewDeliveryOrder(...);// PENDINGVehicleTasktaskvehicleService.createTask(DELIVERY,fromLocation,toLocation,goodsDesc,deliveryNo,0);order.setVehicleTaskNo(task.getTaskNo());// 回写关联一张表对比两类任务维度REPLENISHDELIVERY触发方补货计划派发配送单创建终点售货机点位任意收货点是否联动机械臂是LOAD 上货否refNo 指向ReplenishPlanDeliveryOrder业务目标柜子补货商品送达五、设备端 Agent车是怎么自己跑的后台定义好任务和状态机真正开车的是urm-vehicle这个 Python 脚本。它极简只做三件事循环while True: 1) 心跳上报电量位置 2) 领下一个任务GET task/next 3) 有任务就执行模拟3步×1.5秒→ 上报 COMPLETED 4) 没任务就空闲等注意它只用 Python 标准库urllib不发第三方请求。每 3 秒领一次任务、每 10 秒心跳一次。执行是假的固定 3 步延时返回成功但状态流转是真的——后台的车状态、任务状态全被它如实驱动。这就是为什么 Demo 能看起来像真在跑传输层用 HTTP 替代 MQTT执行层用延时替代真实行驶但状态机的每条边都是真的。你将来把execute_task换成真调用底盘 SDK 沿路径规划走系统其余部分一行不用改。六、调度接口一览运营视角AdminVehicleController给运营提供了车的全套管理动作路径说明车列表GET /admin-api/vehicle/list看所有车状态电量建车POST /admin-api/vehicle/录入一台车任务分页GET /admin-api/vehicle/task/page看任务状态建任务POST /admin-api/vehicle/tasktype/from/to/payload派发POST /admin-api/vehicle/task/{id}/dispatch指定车辆前置仓GET /admin-api/vehicle/warehouse/list看仓演示数据里预置了 2 台车VEH-0001/0002电量 85/60位置都在前置仓和 1 个仓WH-0001容量 5000你起项目就能直接派任务玩。七、无人车这端的真与假照例说清取舍免得你误以为 Demo 能直接上路项真假车/任务/仓的 CRUD 与状态机真事务 状态流转完整派发 / 抢单 / 上报 状态联动真车的实际行驶、路径规划假延时模拟电量约束、就近派单算法留字段未做无人车这端骨架是真的肉真实行驶、智能调度等你往里填。下一篇压轴——机械臂。它和无人车打配合完成最后十米的上货。那是整套系统里最有机械感的一环。