关于 picker-routing-optimization
面向仓库运营团队的技能,用于评估布局与拣选约束、比较拣货路线方法并制定路线建议。内容涵盖图与 TSP 建模、路由算法、拥堵及多层仓库。
主要功能
- 01仓库布局与拣选评估
- 02S 形、返回、中点和最大间隙路线
- 03基于 TSP 的路线建模
- 04拥堵感知与多层路由
- 05路线比较与报告
适用场景
- 01为仓库布局选择路线方法
- 02比较路线距离和预计时间
- 03规划单向巷道及拥堵路线
- 04审查多层仓库路线
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ kishorkukreja/ awesome-supply-chain --skill picker-routing-optimization安装后在 Claude Code 中输入/picker-routing-optimization确认已加载。
详细介绍
拣货员路径优化
你是仓库拣货员路径规划和行走路线优化方面的专家。你的目标是帮助设计最优拣货路线,以尽量缩短行走距离、减少拣货时间、提高拣货员的工作效率,并最大限度地提升仓库效率。
初步评估
在优化拣货员路径前,请先了解:
-
仓库布局
- 布局类型(网格、对角线、混合)?
- 通道数量和长度?
- 通道宽度(双向还是单向)?
- 横向通道(中间位置、仅两端)?
- 拣货位配置(单侧、双侧)?
- 仓库区/暂存区位置?
-
拣货限制
- 拣货方式(单订单、批次、分区)?
- 设备(步行、拣货车、叉车、前移式叉车)?
- 没有拣货任务时,是否可以跳过通道?
- 是否可以双向穿行通道?
- 是否可以在通道中途横向穿行?
- 拣货清单的顺序是否可以调整?
-
订单特征
- 每个订单/批次的平均拣货数量?
- 拣货密度(每条通道的拣货数量)?
- 拣货任务在仓库内的分布情况?
- 商品位置模式?
-
当前绩效
- 当前采用哪种路径规划方法?
- 每个订单的平均行走距离?
- 每小时拣货量?
- 拣货员对路线的反馈?
拣货员路径规划框架
路径规划策略
1. S 形(穿行)路径规划
- 进入有拣货任务的每条通道,并穿行整条通道
- 从远端离开,前往下一条有拣货任务的通道
- 优点:简单,无需在通道内折返
- 缺点:可能需要穿行没有拣货任务的通道区段
- 效率:中等(最优路线的 60-70%)
2. 折返路径规划
- 进入通道,拣取商品,然后从同一端返回
- 移动到下一条通道
- 优点:非常简单、路线可预测
- 缺点:需要大量折返,行走距离最长
- 效率:较差(最优路线的 40-50%)
- 适用场景:窄通道、仅允许单向通行
3. 中点路径规划
- 若拣货任务位于前半段,则从前端折返
- 若拣货任务位于后半段,则穿行至后端
- 需要在中间设置横向通道
- 优点:优于纯 S 形或折返路径规划
- 缺点:需要横向通道设施
- 效率:良好(最优路线的 70-80%)
4. 最大间隙路径规划
- 找出通道内拣货点之间最大的间隙
- 选择进出路线,避免穿行该最大间隙
- 优点:可根据拣货点分布调整路线
- 缺点:更复杂,需要进行计算
- 效率:非常好(最优路线的 80-90%)
5. 最优路径规划(基于 TSP)
- 将问题建模为旅行商问题
- 找出遍历所有拣货点的最短路径
- 优点:可得出最佳路线
- 缺点:计算复杂(NP-hard)
- 效率:最优(100%)
路径规划目标
Primary Goal:
Minimize total travel distance
Secondary Goals:
- Minimize pick time (travel + access)
- Balance picker workload
- Respect aisle traffic constraints
- Maintain pick accuracy (logical sequence)
Constraints:
- Aisle layout (can't cut through racks)
- One-way aisles (directional constraints)
- Congestion (avoid other pickers)
- Equipment limitations (turning radius, height)
数学建模
将仓库建模为图
将仓库建模为有向图 G = (V, E):
顶点(V):
- 拣货位置
- 通道端点
- 横向通道交叉点
- 仓库区(起点/终点)
边(E):
- 顶点之间的行走路段
- 边权重 = 距离或时间
- 单向通道使用有向边
路径规划问题:
Find shortest path from depot visiting all pick locations
and returning to depot
This is a variant of the Traveling Salesman Problem (TSP)
with special structure (rectilinear geometry)
仓库路径规划的 TSP 建模
决策变量:
- x[i,j] = 若拣货员从位置 i 前往位置 j,则为 1;否则为 0
- u[i] = 位置 i 在路线中的顺序(用于消除子回路)
参数:
- d[i,j] = 从位置 i 到位置 j 的距离
- P = 拣货位置集合
- depot = 起点/终点
目标:
Minimize: Σ Σ (d[i,j] × x[i,j]) for all i,j in (P ∪ {depot})
约束:
# 1. Leave each location exactly once (except depot twice - start and end)
for i in P:
Σ x[i,j] = 1 for all j != i
# 2. Enter each location exactly once
for j in P:
Σ x[i,j] = 1 for all i != j
# 3. Flow conservation
for k in P:
Σ x[i,k] = Σ x[k,j] for all i,j
# 4. Start and end at depot
Σ x[depot,j] = 1 for all j in P
Σ x[i,depot] = 1 for all i in P
# 5. Subtour elimination (Miller-Tucker-Zemlin)
for i,j in P:
u[i] - u[j] + n × x[i,j] <= n - 1
# 6. Aisle constraints (can't pass through racks)
for i,j not adjacent:
if no path exists:
x[i,j] = 0
路径规划算法
S 形路径规划
import numpy as np
import pandas as pd
def s_shape_routing(picks, aisles, cross_aisle_locations):
"""
S-Shape routing algorithm
Parameters:
-----------
picks : DataFrame
Columns: pick_id, aisle, position_in_aisle, side (left/right)
aisles : dict
{aisle_id: {'length': length, 'width': width}}
cross_aisle_locations : dict
{aisle_id: [positions...]} # Where cross-aisles exist
Returns:
--------
Route sequence and total distance
"""
# Group picks by aisle
picks_by_aisle = picks.groupby('aisle')
route = []
total_distance = 0
current_position = 0 # Start at position 0 (front of warehouse)
current_aisle = 0 # Start at aisle 0
# Get aisles with picks (sorted)
aisles_with_picks = sorted(picks_by_aisle.groups.keys())
for aisle_id in aisles_with_picks:
aisle_picks = picks_by_aisle.get_group(aisle_id).sort_values('position_in_aisle')
# Move to aisle (cross-aisle travel)
cross_aisle_distance = abs(aisle_id - current_aisle) * aisles[0].get('width', 10)
total_distance += cross_aisle_distance
# Determine entry point (front or back)
# For S-shape: alternate front and back entry
aisle_index = aisles_with_picks.index(aisle_id)
if aisle_index % 2 == 0:
# Enter from front, traverse to back
entry_position = 0
exit_position = aisles[aisle_id]['length']
picks_order = aisle_picks.sort_values('position_in_aisle')
else:
# Enter from back, traverse to front
entry_position = aisles[aisle_id]['length']
exit_position = 0
picks_order = aisle_picks.sort_values('position_in_aisle', ascending=False)
# Move to entry point
total_distance += abs(entry_position - current_position)
# Traverse aisle and pick items
for idx, pick in picks_order.iterrows():
route.append({
'pick_id': pick['pick_id'],
'aisle': aisle_id,
'position': pick['position_in_aisle'],
'sequence': len(route) + 1
})
# Add traversal distance
total_distance += abs(exit_position - entry_position)
current_position = exit_position
current_aisle = aisle_id
# Return to depot
total_distance += abs(current_position - 0)
total_distance += abs(current_aisle - 0) * aisles[0].get('width', 10)
return {
'route': pd.DataFrame(route),
'total_distance': total_distance,
'num_picks': len(picks)
}
# Example usage
picks = pd.DataFrame({
'pick_id': [f'P{i:03d}' for i in range(1, 21)],
'aisle': np.random.randint(1, 11, 20), # 10 aisles
'position_in_aisle': np.random.uniform(0, 100, 20), # 100 ft aisles
'side': np.random.choice(['left', 'right'], 20)
})
aisles = {i: {'length': 100, 'width': 12} for i in range(1, 11)}
cross_aisles = {i: [0, 100] for i in range(1, 11)} # Front and back only
result = s_shape_routing(picks, aisles, cross_aisles)
print(f"S-Shape Routing:")
print(f"Total Distance: {result['total_distance']:.2f} ft")
print(f"Number of Picks: {result['num_picks']}")
print(f"\nFirst 5 picks in sequence:")
print(result['route'].head())
最大间隙路径规划
def largest_gap_routing(picks, aisles):
"""
Largest gap routing algorithm
For each aisle:
- If picks only in front half: enter and return from front
- If picks only in back half: enter and return from back
- If picks in both halves: enter from one side, exit from other (S-shape)
but choose entry/exit to minimize distance
Parameters:
-----------
picks : DataFrame
Pick locations
aisles : dict
Aisle specifications
Returns:
--------
Optimized route
"""
picks_by_aisle = picks.groupby('aisle')
route = []
total_distance = 0
current_position = 0
current_aisle = 0
aisles_with_picks = sorted(picks_by_aisle.groups.keys())
for aisle_id in aisles_with_picks:
aisle_picks = picks_by_aisle.get_group(aisle_id).sort_values('position_in_aisle')
aisle_length = aisles[aisle_id]['length']
# Find largest gap between consecutive picks
positions = sorted(aisle_picks['position_in_aisle'].tolist())
# Add aisle endpoints to gap calculation
gaps = []
gaps.append({'gap_size': positions[0] - 0,
'start': 0, 'end': positions[0]})
for i in range(len(positions) - 1):
gaps.append({'gap_size': positions[i+1] - positions[i],
'start': positions[i], 'end': positions[i+1]})
gaps.append({'gap_size': aisle_length - positions[-1],
'start': positions[-1], 'end': aisle_length})
largest_gap = max(gaps, key=lambda x: x['gap_size'])
# Determine routing strategy based on largest gap location
if largest_gap['start'] == 0:
# Largest gap at front, enter from back
entry_position = aisle_length
exit_position = aisle_length
picks_order = aisle_picks.sort_values('position_in_aisle', ascending=False)
elif largest_gap['end'] == aisle_length:
# Largest gap at back, enter from front
entry_position = 0
exit_position = 0
picks_order = aisle_picks.sort_values('position_in_aisle')
else:
# Largest gap in middle, traverse around it
# Enter from front, exit from back (or vice versa)
# Choose direction that minimizes total travel
# Option 1: Front to back
dist1 = aisle_length - largest_gap['gap_size']
# Option 2: Back to front
dist2 = aisle_length - largest_gap['gap_size']
# Both same for middle gaps, so use S-shape logic
if current_position < aisle_length / 2:
entry_position = 0
exit_position = aisle_length
picks_order = aisle_picks.sort_values('position_in_aisle')
else:
entry_position = aisle_length
exit_position = 0
picks_order = aisle_picks.sort_values('position_in_aisle', ascending=False)
# Move to aisle
cross_aisle_distance = abs(aisle_id - current_aisle) * aisles[0].get('width', 10)
total_distance += cross_aisle_distance
# Move to entry point
total_distance += abs(entry_position - current_position)
# Pick items
for idx, pick in picks_order.iterrows():
route.append({
'pick_id': pick['pick_id'],
'aisle': aisle_id,
'position': pick['position_in_aisle'],
'sequence': len(route) + 1
})
# Calculate actual travel distance in aisle (excluding largest gap if avoided)
if entry_position == exit_position:
# Return routing
furthest_pick = picks_order.iloc[-1]['position_in_aisle']
aisle_travel = 2 * abs(furthest_pick - entry_position)
else:
# Traversal routing (minus largest gap if skipped)
aisle_travel = abs(exit_position - entry_position)
total_distance += aisle_travel
current_position = exit_position
current_aisle = aisle_id
# Return to depot
total_distance += abs(current_position - 0)
total_distance += abs(current_aisle - 0) * aisles[0].get('width', 10)
return {
'route': pd.DataFrame(route) if route else pd.DataFrame(),
'total_distance': total_distance,
'num_picks': len(picks)
}
result_lg = largest_gap_routing(picks, aisles)
print(f"\nLargest Gap Routing:")
print(f"Total Distance: {result_lg['total_distance']:.2f} ft")
print(f"Improvement vs S-Shape: {(result['total_distance'] - result_lg['total_distance']) / result['total_distance'] * 100:.1f}%")
基于 TSP 的最优路径规划
from scipy.spatial.distance import pdist, squareform
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp
def tsp_optimal_routing(picks, warehouse_graph):
"""
Optimal routing using TSP solver (Google OR-Tools)
Parameters:
-----------
picks : DataFrame
Pick locations with x, y coordinates
warehouse_graph : dict
Distance matrix considering warehouse layout constraints
Returns:
--------
Optimal route
"""
# Create distance matrix
# In real warehouse, distance is constrained by aisles (not Euclidean)
# Use warehouse_graph or calculate Manhattan distance
locations = picks[['x', 'y']].values
n_locations = len(locations)
# Add depot (0, 0)
depot_location = np.array([[0, 0]])
all_locations = np.vstack([depot_location, locations])
# Calculate distance matrix (Manhattan distance for warehouse)
def manhattan_distance(loc1, loc2):
return abs(loc1[0] - loc2[0]) + abs(loc1[1] - loc2[1])
n = len(all_locations)
distance_matrix = np.zeros((n, n))
for i in range(n):
for j in range(n):
if i != j:
distance_matrix[i][j] = manhattan_distance(
all_locations[i], all_locations[j]
)
# Convert to integer (OR-Tools requirement)
distance_matrix = (distance_matrix * 100).astype(int)
# Create routing model
manager = pywrapcp.RoutingIndexManager(n, 1, 0) # n locations, 1 vehicle, depot=0
routing = pywrapcp.RoutingModel(manager)
# Create distance callback
def distance_callback(from_index, to_index):
from_node = manager.IndexToNode(from_index)
to_node = manager.IndexToNode(to_index)
return distance_matrix[from_node][to_node]
transit_callback_index = routing.RegisterTransitCallback(distance_callback)
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
# Search parameters
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
search_parameters.first_solution_strategy = (
routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
)
search_parameters.local_search_metaheuristic = (
routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH
)
search_parameters.time_limit.seconds = 10
# Solve
solution = routing.SolveWithParameters(search_parameters)
if solution:
# Extract route
route = []
index = routing.Start(0)
total_distance = 0
while not routing.IsEnd(index):
node = manager.IndexToNode(index)
if node > 0: # Skip depot at start
route.append({
'pick_id': picks.iloc[node - 1]['pick_id'],
'x': picks.iloc[node - 1]['x'],
'y': picks.iloc[node - 1]['y'],
'sequence': len(route) + 1
})
next_index = solution.Value(routing.NextVar(index))
total_distance += routing.GetArcCostForVehicle(index, next_index, 0)
index = next_index
return {
'route': pd.DataFrame(route),
'total_distance': total_distance / 100, # Convert back from integer
'num_picks': len(picks),
'optimal': True
}
return {'route': pd.DataFrame(), 'total_distance': 0, 'optimal': False}
# Example with coordinates
picks_with_coords = pd.DataFrame({
'pick_id': [f'P{i:03d}' for i in range(1, 21)],
'x': np.random.uniform(0, 100, 20), # x coordinate (across aisles)
'y': np.random.uniform(0, 100, 20), # y coordinate (down aisle)
})
# Note: In real implementation, would use actual warehouse graph
# that respects aisle structure
result_tsp = tsp_optimal_routing(picks_with_coords, warehouse_graph={})
if result_tsp['optimal']:
print(f"\nTSP Optimal Routing:")
print(f"Total Distance: {result_tsp['total_distance']:.2f} ft")
print(f"First 5 picks:")
print(result_tsp['route'].head())
高级路径规划技术
避开拥堵的动态路径规划
class DynamicRouter:
"""
Dynamic routing that adapts to warehouse congestion
"""
def __init__(self, warehouse_layout, real_time_tracking=False):
self.warehouse_layout = warehouse_layout
self.real_time_tracking = real_time_tracking
self.picker_locations = {} # {picker_id: (aisle, position)}
self.congestion_map = {} # {aisle: congestion_level}
def update_picker_location(self, picker_id, aisle, position):
"""Update picker location for congestion tracking"""
self.picker_locations[picker_id] = (aisle, position)
self.update_congestion_map()
def update_congestion_map(self):
"""Calculate congestion level for each aisle"""
aisle_counts = {}
for picker_id, (aisle, position) in self.picker_locations.items():
aisle_counts[aisle] = aisle_counts.get(aisle, 0) + 1
# Congestion level: number of pickers / aisle capacity
for aisle in self.warehouse_layout['aisles']:
count = aisle_counts.get(aisle, 0)
capacity = 3 # Assume max 3 pickers per aisle comfortably
self.congestion_map[aisle] = count / capacity
def route_with_congestion(self, picks, picker_id):
"""
Calculate route considering current congestion
Penalize aisles with high congestion
"""
# Start with base routing algorithm (e.g., largest gap)
base_route = largest_gap_routing(picks, self.warehouse_layout['aisles'])
if not self.real_time_tracking:
return base_route
# Adjust route based on congestion
# Re-sequence to visit less congested aisles first
route_df = base_route['route'].copy()
route_df['aisle'] = picks.set_index('pick_id').loc[route_df['pick_id'], 'aisle'].values
route_df['congestion'] = route_df['aisle'].map(self.congestion_map).fillna(0)
# Sort picks within each priority group by congestion
route_df = route_df.sort_values(['congestion', 'aisle'])
route_df['sequence'] = range(1, len(route_df) + 1)
return {
'route': route_df,
'total_distance': base_route['total_distance'] * 1.05, # Slight penalty for re-sequencing
'congestion_adjusted': True
}
# Example usage
warehouse_layout = {
'aisles': list(range(1, 11)),
'aisle_specs': {i: {'length': 100, 'width': 12} for i in range(1, 11)}
}
router = DynamicRouter(warehouse_layout, real_time_tracking=True)
# Simulate other pickers
router.update_picker_location('picker_1', aisle=3, position=50)
router.update_picker_location('picker_2', aisle=3, position=30)
router.update_picker_location('picker_3', aisle=7, position=60)
# Route new picker
route_dynamic = router.route_with_congestion(picks, 'picker_4')
print("\nDynamic Routing with Congestion:")
print(f"Congestion Map: {router.congestion_map}")
多层仓库路径规划
def multi_level_routing(picks, levels, vertical_travel_time=30):
"""
Routing for multi-level warehouses (mezzanines, multi-story)
Parameters:
-----------
picks : DataFrame
Picks with level, aisle, position
levels : list
Available levels
vertical_travel_time : float
Seconds to move between levels
Returns:
--------
Optimized route considering vertical travel
"""
# Group picks by level
picks_by_level = picks.groupby('level')
# Strategy: Minimize level changes
# Visit all picks on one level before moving to next
route = []
total_distance = 0
total_time = 0
current_level = 1 # Start at ground level
# Determine optimal level sequence
# Heuristic: Ground level first, then upper levels in order
level_sequence = sorted(picks_by_level.groups.keys())
for level in level_sequence:
level_picks = picks_by_level.get_group(level)
# Move to level (vertical travel)
if level != current_level:
level_changes = abs(level - current_level)
total_time += level_changes * vertical_travel_time
current_level = level
# Route within level (use largest gap or TSP)
level_route = largest_gap_routing(
level_picks,
aisles={i: {'length': 100, 'width': 12} for i in range(1, 11)}
)
# Add to total route
level_route_df = level_route['route']
level_route_df['level'] = level
route.append(level_route_df)
total_distance += level_route['total_distance']
# Combine all levels
full_route = pd.concat(route, ignore_index=True)
full_route['sequence'] = range(1, len(full_route) + 1)
return {
'route': full_route,
'total_distance': total_distance,
'total_time': total_time,
'num_picks': len(picks),
'levels_visited': len(level_sequence)
}
# Example
picks_multi_level = pd.DataFrame({
'pick_id': [f'P{i:03d}' for i in range(1, 31)],
'level': np.random.choice([1, 2, 3], 30),
'aisle': np.random.randint(1, 11, 30),
'position_in_aisle': np.random.uniform(0, 100, 30),
})
result_ml = multi_level_routing(picks_multi_level, levels=[1, 2, 3])
print("\nMulti-Level Routing:")
print(f"Total Distance: {result_ml['total_distance']:.2f} ft")
print(f"Vertical Travel Time: {result_ml['total_time']:.0f} sec")
print(f"Levels Visited: {result_ml['levels_visited']}")
工具和库
路由软件
仓库管理系统:
- Manhattan WMS:优化拣选路径生成
- Blue Yonder (JDA) WMS:AI 驱动的路由
- SAP EWM:按订单和按波次拣选路由
- HighJump WMS:支持实时更新的动态路由
专业优化工具:
- Lucas Systems:语音引导拣选与优化路线
- Voxware:具备智能路由功能的语音拣选
- Google OR-Tools:开源路由优化工具
- Gurobi/CPLEX:商业优化求解器
Python 库
# Routing Optimization
from ortools.constraint_solver import routing_enums_pb2, pywrapcp
from scipy.optimize import linear_sum_assignment
import networkx as nx # Graph algorithms
# TSP Solvers
from python_tsp.exact import solve_tsp_dynamic_programming
from python_tsp.heuristics import solve_tsp_simulated_annealing
# Distance Calculations
from scipy.spatial.distance import pdist, squareform, cityblock
import numpy as np
# Visualization
import matplotlib.pyplot as plt
import matplotlib.patches as patches
常见挑战与解决方案
挑战:单向通道
问题:
- 通道狭窄,只允许单向通行
- 无法使用 S 形路线(不能双向穿行)
- 必须从入口返回
解决方案:
- 采用往返路线作为基准
- 优化入口/出口位置(前端与后端)
- 有横向通道时使用中点
- 考虑拓宽关键通道,以支持双向通行
- 实施通道方向交替规则(奇数/偶数)
挑战:拥堵与阻塞
问题:
- 多名拣选员在同一通道作业
- 出现阻塞和等待时间
- 为避让而导致路线变长
解决方案:
- 使用能感知拥堵情况的实时路由
- 错开拣选员的开始时间(间隔 5-10 分钟)
- 按区域拣选(为拣选员分配专用通道)
- 通过移动应用/语音系统动态重新规划路线
- 分析交通流量以识别瓶颈
挑战:大型拣选清单
问题:
- 单个订单/批次有 100 个以上的拣选位置
- TSP 的计算开销过大
- 无法进行实时路由
解决方案:
- 使用启发式算法(最大间隔、S 形路线),而非 TSP
- 拆分为较小批次
- 离线预先计算路线(适用于重复订单)
- 使用近似 TSP(LKH、Christofides)
- 限制优化时间(在 5 秒内找到最佳路线)
挑战:拣选时间不固定
问题:
- 有些拣选需要 5 秒,另一些则需要 60 秒
- 重物、高层货架、按数量拣选
- 基于距离的路由忽略了时间差异
解决方案:
- 按时间而非距离为边加权
- 在路线优化中纳入拣选时间
- 优先安排困难的拣选任务(趁拣选员精力充沛时)
- 预先摆放重型/大件物品(采用单独的工作流)
- 通过时间与动作研究进行校准
挑战:布局变更
问题:
- 仓库布局发生变化(库位规划调整)
- 路线不再最优
- 拣选员对库位变更感到困惑
解决方案:
- 库位规划变更后重新计算路线
- 逐步推出(按区域进行)
- 立即更新 WMS 库位主数据
- 培训拣选员熟悉新布局
- 使用 RF/语音进行引导(不依赖具体库位)
输出格式
拣选员路由报告
路线优化分析 - 订单 #12345
拣选清单摘要:
- 拣选总数:42 行
- 涉及通道:8 条(2、4、5、7、9、11、13、15)
- 仓库区域:A(18 次拣选)、B(15 次拣选)、C(9 次拣选)
路由对比:
| 方法 | 距离(英尺) | 预计时间(分钟) | 改进幅度 |
|---|---|---|---|
| 往返路线 | 1,845 | 28.5 | 基准 |
| S 形路线 | 1,124 | 17.4 | 39% |
| 最大间隔法 | 892 | 13.8 | 52% |
| TSP 最优路线 | 834 | 12.9 | 55% |
推荐路线(最大间隔法):
Sequence | Pick ID | SKU | Aisle | Position | Side | Qty |
---------|---------|-----|-------|----------|------|-----|
1 | P001 | SKU_A | 2 | 15.3 | L | 2 |
2 | P002 | SKU_B | 2 | 28.7 | R | 1 |
3 | P003 | SKU_C | 2 | 45.2 | L | 3 |
4 | [Cross to Aisle 4]
5 | P008 | SKU_H | 4 | 82.1 | R | 1 |
6 | P009 | SKU_I | 4 | 67.3 | L | 2 |
...
路线可视化:
Depot (Start)
↓
Aisle 2 [Enter Front → Pick 3 items → Exit Front]
↓
Cross-Aisle Travel (2 → 4)
↓
Aisle 4 [Enter Back → Pick 5 items → Exit Front]
↓
Cross-Aisle Travel (4 → 5)
↓
Aisle 5 [Enter Front → Pick 4 items → Exit Front]
...
↓
Return to Depot (End)
Total Distance: 892 ft
Estimated Time: 13.8 minutes (assuming 100 ft/min walk + 10 sec/pick)
绩效指标:
- 每次拣选距离:21.2 英尺/次
- 预计每小时拣选量:182 次(往返路线为 145 次)
- 生产效率提升:+26%
需要了解的问题
如需更多背景信息:
- 仓库布局是什么样的(网格、横向通道)?
- 通道是单向还是双向的?
- 采用哪种拣选方式(单件、批次、分区)?
- 每个订单/批次的平均拣选量是多少?
- 目前使用哪种路由方法?
- 目前每小时拣选量是多少?
- 是否有具备路由功能的 WMS?
- 是否存在拥堵或阻塞问题?
相关技能
- traveling-salesman-problem:用于 TSP 算法和理论
- order-batching-optimization:用于创建最优配送批次
- warehouse-slotting-optimization:用于影响路线的 SKU 布局
- wave-planning-optimization:用于影响路径规划的波次设计
- network-flow-optimization:用于仓库流建模
- graph-algorithms:用于最短路径和路径规划
- metaheuristic-optimization:用于大规模路径规划问题
评论
支持 Markdown