M4 如何为多负载机器人拼单

料箱车是典型的多负载机器人,身上多个背篓可以同时承载多个运单的货物。如何将多个运单智能地分配给同一台车,并在执行过程中持续优化取放顺序——这就是 M4 中“拼单”机制要解决的问题。
本文将沿着一个运单从下发到执行完成的全过程,逐层拆解 M4 的拼单能力。
起点:一个运单搬运一个料箱
在 M4 调度中,运单的定义是搬运一个容器。一个运单只能包含一次取货和一次放货(或没有取放货的纯移动)。不允许一个运单里放多次取货、多次放货,也不允许只取不放或只放不取。
这意味着,如果要搬运 6 个料箱,需要创建 6 个运单。拼单不是把 6 个料箱塞进一个运单,而是 M4 在派单阶段,把这 6 个运单分配给同一台料箱车,由机器人在一趟行程中分别执行各自的取放步骤。
这个设计的好处是运单结构简单、状态清晰,拼单的复杂度完全由调度层承担,不需要上游系统处理多货物编排。
自动拼单:不只是“打包分配”
M4 的拼单不是在派单瞬间一次性把所有运单绑定给一台车。它是一个持续运行的动态过程,在机器人执行任务的全程中不断调整。
- 动态追加
料箱机器人 A 有 3 个背篓,当前接了 2 单正在执行。执行途中上游又下发了 1 单,新单符合拼入条件,系统会直接将其追加给机器人 A,不需要等前两单做完。
- 动态调整执行顺序
追加新单后,系统不是简单地把新单排在队尾。如果机器人刚取完第一单的货,此时第三单(新追加的)比第二单距离更近,系统会优先执行第三单。执行顺序主要依据路径成本动态决定。
- 挤走单
如果机器人 A 的 3 个背篓都已分配了运单,此时又来了一个优先级更高或路径成本更低的新单,系统可以把已分配但未执行的旧单“挤走”——撤回旧单让它重新参与全局派单,腾出背篓给新单。挤走的前提是旧单尚未开始取货,且新单确实更优。
- 二次分派
已经分配给机器人 B 的运单,如果机器人 A 刚完成一单空出了背篓,且 A 比 B 离这个运单更近,系统会将运单从 B 撤回、重新分配给 A。即使运单已经开始执行(机器人正在去取货的路上),只要该步骤标记了允许重分派(withdrawOrderAllowed),也可以被中断并转交给更优的机器人。
这一整套机制的核心逻辑是:派单不是一次性决策,而是每一轮派单周期都在重新评估全局最优分配。
取放顺序优化:不必先取完再放完
多负载机器人接了多个运单后,一个直觉的执行方式是“先把所有货取完,再一起去放”。但在实际场景中,取货点和放货点可能分散在不同区域,严格的先取后放反而会增加总路径长度。
M4 支持取放交叉执行。假设机器人接了 3 个运单,执行顺序可能是:取单 1 → 取单 2 → 放单 1 → 取单 3 → 放单 3 → 放单 2。具体顺序由系统根据路径成本动态计算——每完成一个步骤后,系统从该机器人所有待执行的步骤中选出导航成本最低的那个作为下一步。
当机器人同时有多个运单待执行时,系统通过“选步骤”逻辑来决策下一步:机器人处于空闲或移动中时,系统遍历所有可执行的步骤(跨运单),按原地执行优先、运单优先级、导航成本等因素综合排序,选出最合适的一个。如果选出的步骤与当前正在执行的不同,且机器人还在移动中,系统会先打断当前导航,再切换到新步骤。
按组拼单:taskBatch 机制
自动拼单解决的是“谁和谁拼更高效”的问题。但在某些业务场景中,还存在一个更强的约束:某几个运单必须由同一台车完成。
一个典型的场景来自出库流程:料箱车从密集货架取出料箱,放到中转料架上,再由顶升车将整个料架搬到产线。如果同一个中转料架的料箱被分配给了多台料箱车,就会出现多车去同一个料架放货导致接驳区拥堵的问题,而且料架要等最后一台车到齐才能被顶走。
M4 通过 taskBatch 字段解决这类需求。创建运单时,给同一批运单填写相同的 taskBatch 值(一个字符串标识),系统在派单时保证同组运单分配给同一台料箱车。
taskBatch 的核心规则如下:
- 同组运单必须分给同一台车
一旦某组的第一个运单被分配,后续同组运单只能分配给这台机器人。
- 不同组不能混拼
即使一台车有 8 个背篓,组 A 占 4 个、组 B 占 4 个看起来刚好,也不允许拼在一起。机器人身上不能同时存在不同 taskBatch 的货物。
- 一组运单同时只占一台车
如果一组有 10 个运单但机器人只有 8 个背篓,系统会先装满一台车的背篓,而不是同时分配给两台车。这是为了避免最差情况——多台车同时去接同一组,每台只载一个货,导致其他组完全没有机器人可用。
- 不填 taskBatch 的运单正常参与自动拼单,不受上述约束
不填的运单和填了 taskBatch 的运单不会被拼在一起。组内的执行顺序仍由调度根据路径成本动态决定,taskBatch 只控制“分给谁”,不控制“先执行哪个”。
输送线场景:三个机制的协作
在输送线(滚筒线、传送带)场景中,拼单面临一个特殊问题:料箱车在输送线取完一个料箱后,输送线上可能很快又会来一个新料箱,但系统还没来得及下发新运单。如果机器人取完就立刻去放货或去其他地方接单,等新料箱到达时机器人已经离开了,再折返回来会严重降低效率。
M4 通过三个机制的组合来解决这类问题,每个机制负责不同层面。
- 限制接单范围(原地等待)
解决的是执行层面的问题——取货完成后,不立即执行放货步骤,而是在原地等待一段时间。等待期间只接当前位置(或指定范围内)的新取货运单。超时或满载后,才继续执行后续步骤。这个功能需要两步配置:先在场景级设置等待时间和接单范围,再在运单步骤中启用“限制接单范围”参数。
- 暂停自动拼单
解决的是派单层面的问题——防止机器人在等待期间被派去其他站台。多储位机器人默认会自动拼上新的运单,如果另一个输送线也有取货任务,机器人可能会被拼上那个任务而离开当前输送线。暂停自动拼单状态开启后,机器人只接指定了该机器人的运单,拒绝自动拼入。
- 站台租约
面向更复杂的多输送线、多机器人协调场景。机器人到达输送线并取货后,系统为它创建一个该站台的租约。租约期间,这条输送线的所有新货物都只分配给持有租约的机器人,其他机器人无法插队。租约支持续期(每次取货后重置计时)和多种结束条件(满载、超时、故障)。可以类比为停车场租车位——机器人到达就“租”了一个专属位,租期内独占这条线的服务权。
三者的分工可以这样理解:taskBatch 或运单序列保证新运单分给同一台车(派单层约束),暂停自动拼单防止机器人被派去别的地方(派单层约束),限制接单范围让机器人取货后暂停、不立即去放货(执行层约束)。实际使用中,根据场景复杂度选择组合:简单场景下限制接单范围单独就能满足需求,复杂的多站台场景则可能需要三者配合。
不拼单模式
并非所有场景都需要拼单。如果业务上要求严格的一车一单,可以在机器人组配置中将最大载货数设置为 1,系统会彻底关闭拼单,每台机器人同一时间只执行一个运单。
当前限制与演进方向
M4 的拼单能力仍在持续扩展中。目前已支持的核心能力包括动态拼单、动态执行顺序、挤走单、二次分派、taskBatch 按组拼单、取放顺序优化和限制接单范围。
部分能力尚在规划或开发中:指定拼单键拼单(通过 taskBatch 传入产线编号、物料大类等条件,只有条件匹配的运单才允许拼在一起);优先级相同规则(只拼相同优先级的运单);脚本扩展(支持通过自定义脚本定制运单排序、机器人筛选和避让逻辑);运单序列(比 taskBatch 更完整的工作流管理,支持显式的创建、封口和生命周期控制);以及任务执行中智能停靠到缓存区(机器人取完货后电梯不可用时先去缓存区等待)。
此外还有一个特殊场景值得关注:双深位货架的拼单。当需要取内侧料箱时,必须先把外侧料箱搬走。目前有两种方式——在车上预留空位临时存放外侧料箱,或者在货架上找空库位做移库。这类场景对拼单的背篓管理和路径规划提出了更高要求。
拼单:持续决策的过程
料箱车的拼单不是一个孤立的功能,而是 M4 中派单、选步骤、执行控制、异常恢复等多个子系统协同运作的结果。从自动拼单的动态追加和挤走,到 taskBatch 的按组约束,再到输送线场景下三个机制的精细配合——拼单能力的丰富程度,正是多负载机器人对 M4 提出的要求,也是 M4 持续演进的方向。