本文系统梳理了本工程中拣货路径距离的建模、计算逻辑、业务意义及实现细节,适合开发、产品和业务同学查阅。
目录
1. 位置建模
每个拣货点(WarehouseLocation)包含:
- 货架编号(shelvingId)
- 左右侧(Side.LEFT/RIGHT)
- 行号(row)
- 这样能唯一确定仓库中的一个实际拣货点。
2. 距离计算主方法
- 由
Warehouse.calculateDistance(WarehouseLocation start, WarehouseLocation end)
实现。 - 先将每个点(含左右)转换为绝对坐标(getAbsoluteX/Y)。
3. 距离计算的具体逻辑
- 同货架同侧:只算纵向距离(Y轴差),即
abs(startY - endY)
。 同货架不同侧:
- 横向距离加上货架宽度(
deltaX = SHELVING_WIDTH
)。 - 纵向距离用
calculateBestYDistanceInShelvingRow
,模拟只能从货架头/尾绕行。
- 横向距离加上货架宽度(
- 同一行不同货架:横向距离按货架间距算,纵向按实际差值或绕行。
- 不同行:直接用绝对坐标差。
4. 货架宽度的体现
- 只有在同货架不同侧时,才加上
SHELVING_WIDTH
。 - 纵向绕行距离和货架宽度最后统一相加。
5. 业务意义
- 这种实现方式大部分情况下等价于曼哈顿距离。
- 对于同货架不同侧,模拟了实际拣货员只能从货架两端绕行的真实场景。
- 路径优化时,优化器会自动根据真实距离(含左右、货架宽度、绕行)来排序和分配路径。
6. 关键代码片段
if (startShelving == endShelving) {
if (start.getSide() == end.getSide()) {
deltaY = abs(startY - endY);
} else {
deltaX = SHELVING_WIDTH;
deltaY = calculateBestYDistanceInShelvingRow(start.getRow(), end.getRow());
}
}
return deltaX + deltaY;
7. 绝对坐标的转换原理
在仓库建模中,每个拣货点(WarehouseLocation)由货架编号、左右侧(Side)、行号(row)唯一确定。但距离计算时,需要将这些信息转成仓库平面上的绝对坐标(X, Y)。
关键代码
getAbsoluteX
private static int getAbsoluteX(Shelving shelving, WarehouseLocation location) {
if (location.getSide() == Shelving.Side.LEFT) {
return shelving.getX();
} else {
return shelving.getX() + SHELVING_WIDTH;
}
}
- 如果在左侧,X坐标就是货架的起点。
- 如果在右侧,X坐标是货架起点加上货架宽度。
getAbsoluteY
private static int getAbsoluteY(Shelving shelving, WarehouseLocation location) {
return shelving.getY() + location.getRow();
}
- Y坐标 = 货架起点Y + 行号。
图示举例
假设货架 (A,1) 左下角坐标是 (10, 20),宽度是2:
- 左侧第3行:X=10,Y=23
- 右侧第3行:X=12,Y=23
形象图解
总结
- getAbsoluteX 根据左右侧决定横坐标。
- getAbsoluteY 用货架起点Y加行号决定纵坐标。
- 这样就能把"货架+侧+行号"唯一映射到仓库平面上的一个点,便于距离计算。
8. 总结
本工程的距离计算兼顾了仓库实际操作的复杂性和优化算法的高效性,既保证了模型的真实性,也方便了路径优化。
下一篇,我们将Timefold 求解流程概览,敬请期待!
本文首发于微信公众号【Timefold技术前线】
我正在学习和探索 Timefold,内容难免有不足之处,欢迎大家留言指正、补充,一起交流共同进步!
关注公众号,第一时间获取更多原创内容,和我一起持续学习、成长。
本文由博客一文多发平台 OpenWrite 发布!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。