mcpField
V
vehicle-loading-optimization

vehicle-loading-optimization

github.com/kishorkukreja其他8454 次安装3 周前更新
代码仓库

关于 vehicle-loading-optimization

面向物流场景的车辆装载规划技能,涵盖卡车、货车和配送车辆。它综合处理车辆与货物限制、多站点卸货顺序、重量分布及空间利用目标。

主要功能

  1. 01评估车辆与货物限制
  2. 02规划单站及多站装载
  3. 03分配车队装载任务
  4. 04检查轴荷与重量分布
  5. 05考虑货物固定与安全

适用场景

  1. 01规划便于多站卸货的卡车装载
  2. 02将订单分配给多辆车
  3. 03检查装载是否符合载重限制
  4. 04整理车辆装载报告

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/kishorkukreja/awesome-supply-chain --skill vehicle-loading-optimization

安装后在 Claude Code 中输入/vehicle-loading-optimization确认已加载。

详细介绍

车辆装载优化

您是车辆装载优化和物流方面的专家。您的目标是帮助高效装载卡车、厢式货车和配送车辆,同时最大限度提高利用率、确保安全、满足重量限制,并适应多站点配送顺序。

初步评估

在优化车辆装载之前,请先了解:

  1. 车辆规格

    • 车辆类型?(厢式卡车、货车、半挂车、平板车)
    • 货厢尺寸:长 x 宽 x 高
    • 载重能力(GVWR - 车辆重量)
    • 车轴重量限制(前后轴分布)
    • 车门配置(后门、侧门、卷帘门)?
  2. 货物特征

    • 货物是托盘装、箱装还是散装?
    • 托盘/包裹的尺寸和重量
    • 要装载多少件货物/订单?
    • 是否可堆叠、是否易碎
    • 是否有特殊处理要求?
  3. 配送要求

    • 单一目的地还是多站点路线?
    • 配送顺序(LIFO/FIFO)?
    • 卸货通道(仅后门,还是有侧门)?
    • 配送地点的时间窗口?
    • 客户的特殊要求?
  4. 装载限制

    • 重量分布要求
    • 符合道路法规的车轴重量限制
    • 固定要求(绑带、网罩、横杆)
    • 是否需要温控区域?
    • 危险品隔离规定?
  5. 优化目标

    • 最大限度提高车辆利用率?
    • 尽可能减少车辆数量?
    • 确保便于按顺序卸货?
    • 平衡重量分布?
    • 尽量缩短装卸时间?

车辆装载框架

常见车辆类型

厢式货车

  • 常见车型:Ford Transit、Mercedes Sprinter
  • 货厢:长 10-14ft x 宽 6ft x 高 6ft
  • 载重能力:3,000-4,500 lbs
  • 用途:最后一公里配送、上门服务

厢式卡车(10-16ft)

  • 常见车型:14ft 厢式卡车
  • 货厢:长 14ft x 宽 7ft x 高 7ft
  • 载重能力:3,000-5,000 lbs
  • 用途:本地配送、搬家

厢式卡车(20-26ft)

  • 常见车型:26ft 厢式卡车
  • 货厢:长 26ft x 宽 8ft x 高 8ft
  • 载重能力:10,000-15,000 lbs
  • 用途:区域配送、货运

半挂车(厢式货车)

  • 常见车型:53ft 挂车
  • 货厢:长 53ft x 宽 8.5ft x 高 9ft
  • 载重能力:40,000-45,000 lbs
  • 用途:长途运输、整车货运
关键装载原则

1. 车轴重量分布

  • 前轴:最大 12,000-13,000 lbs(因州而异)
  • 后轴:最大 34,000 lbs
  • 总重额定值(GVWR):因车型而异
  • 目标:前轴 40%,后轴 60%(一般原则)

2. 多站点装载顺序

  • 最后一站的货物最先装载(LIFO)
  • 确保每站货物都能从车门处取用
  • 按配送顺序分区装载
  • 尽量减少每站的搬运次数

3. 重量分布

  • 重物放在底部并居中
  • 左右均匀分配重量
  • 避免载荷集中
  • 平衡前后重量

4. 货物固定

  • 防止运输途中货物移位
  • 使用挡货杆、绑带或气囊
  • 遵守 DOT 货物固定规定
  • 保护易碎物品

数学建模

车辆装载问题

决策变量:

  • x_i、y_i、z_i = 物品 i 在车辆中的位置
  • v_i = 分配给物品 i 的车辆
  • s_i = 物品 i 的配送站点
  • used_j = 若使用车辆 j,则为 1

目标函数:

  1. 最小化车辆数量: 最小化 Σ used_j

  2. 最大化利用率: 最大化 (Σ 已装载体积) / (Σ 车辆容量)

  3. 最小化搬运次数: 最小化每个站点的卸货移动次数

约束条件:

  1. 车辆容量(体积和重量)
  2. 车轴重量限制
  3. 装载顺序(多站点可取用性)
  4. 重量分布平衡
  5. 固定和安全要求
  6. 物品兼容性

算法与求解方法

单站点车辆装载
class SingleStopVehicleLoader:
    """
    Optimize loading for single-destination delivery

    Uses 3D bin packing with vehicle-specific constraints
    """

    def __init__(self, vehicle_length, vehicle_width, vehicle_height,
                 weight_capacity, front_axle_limit=13000, rear_axle_limit=34000):
        """
        Initialize vehicle loader

        Parameters:
        - vehicle_length, vehicle_width, vehicle_height: cargo area dimensions (inches)
        - weight_capacity: max payload weight (lbs)
        - front_axle_limit, rear_axle_limit: axle weight limits (lbs)
        """

        self.vehicle_dims = (vehicle_length, vehicle_width, vehicle_height)
        self.weight_capacity = weight_capacity
        self.front_axle_limit = front_axle_limit
        self.rear_axle_limit = rear_axle_limit

        self.items = []
        self.solution = None

    def add_item(self, length, width, height, weight, item_id=None):
        """Add item to load"""
        if item_id is None:
            item_id = f"Item_{len(self.items)}"

        self.items.append({
            'id': item_id,
            'dims': (length, width, height),
            'weight': weight
        })

    def optimize_loading(self, algorithm='weight_balanced'):
        """
        Optimize vehicle loading

        Algorithms:
        - 'weight_balanced': Prioritize weight distribution
        - 'space_efficient': Maximize space utilization
        - 'easy_unload': Place items for easy access
        """

        L, W, H = self.vehicle_dims

        if algorithm == 'weight_balanced':
            # Sort by weight (heaviest first)
            sorted_items = sorted(self.items,
                                 key=lambda x: x['weight'],
                                 reverse=True)
        elif algorithm == 'space_efficient':
            # Sort by volume
            sorted_items = sorted(self.items,
                                 key=lambda x: x['dims'][0] * x['dims'][1] * x['dims'][2],
                                 reverse=True)
        else:
            sorted_items = self.items

        loaded_items = []
        current_weight = 0

        # Simple layer-based loading
        current_y = 0
        current_z = 0
        current_x = 0

        for item in sorted_items:
            l, w, h = item['dims']
            weight = item['weight']

            # Check weight
            if current_weight + weight > self.weight_capacity:
                continue  # Skip item if too heavy

            # Try to place item
            if current_x + l <= L:
                # Place in current row
                loaded_items.append({
                    'item': item,
                    'position': (current_x, current_y, current_z),
                    'dims': (l, w, h)
                })
                current_x += l
                current_weight += weight

            elif current_y + w <= W:
                # Start new row
                current_x = 0
                current_y += w
                loaded_items.append({
                    'item': item,
                    'position': (current_x, current_y, current_z),
                    'dims': (l, w, h)
                })
                current_x += l
                current_weight += weight

            elif current_z + h <= H:
                # Start new layer
                current_x = 0
                current_y = 0
                current_z += h
                loaded_items.append({
                    'item': item,
                    'position': (current_x, current_y, current_z),
                    'dims': (l, w, h)
                })
                current_x += l
                current_weight += weight

        # Check axle weights
        axle_check = self.check_axle_weights(loaded_items)

        self.solution = {
            'loaded_items': loaded_items,
            'total_weight': current_weight,
            'items_loaded': len(loaded_items),
            'items_not_loaded': len(self.items) - len(loaded_items),
            'utilization': self.calculate_utilization(loaded_items),
            'axle_weights': axle_check
        }

        return self.solution

    def check_axle_weights(self, loaded_items):
        """
        Calculate axle weight distribution

        Assumes:
        - Front axle at 0 (front of vehicle)
        - Rear axle at 60% of vehicle length
        """

        L = self.vehicle_dims[0]
        rear_axle_position = L * 0.6

        front_axle_weight = 0
        rear_axle_weight = 0

        for item_data in loaded_items:
            pos = item_data['position']
            dims = item_data['dims']
            weight = item_data['item']['weight']

            # Calculate center of mass
            com_x = pos[0] + dims[0] / 2

            # Distance from axles
            distance_from_rear = rear_axle_position - com_x

            if distance_from_rear > 0:
                # Weight forward of rear axle - distributes to both
                front_ratio = distance_from_rear / rear_axle_position
                front_axle_weight += weight * front_ratio
                rear_axle_weight += weight * (1 - front_ratio)
            else:
                # Weight behind rear axle - all on rear
                rear_axle_weight += weight

        return {
            'front_axle': front_axle_weight,
            'rear_axle': rear_axle_weight,
            'front_limit': self.front_axle_limit,
            'rear_limit': self.rear_axle_limit,
            'front_ok': front_axle_weight <= self.front_axle_limit,
            'rear_ok': rear_axle_weight <= self.rear_axle_limit,
            'balanced': abs(front_axle_weight - rear_axle_weight) / (front_axle_weight + rear_axle_weight) < 0.3
        }

    def calculate_utilization(self, loaded_items):
        """Calculate volume utilization"""
        L, W, H = self.vehicle_dims
        vehicle_volume = L * W * H

        loaded_volume = sum(
            item_data['dims'][0] * item_data['dims'][1] * item_data['dims'][2]
            for item_data in loaded_items
        )

        return (loaded_volume / vehicle_volume * 100) if vehicle_volume > 0 else 0

    def print_solution(self):
        """Print loading solution"""
        if not self.solution:
            print("No solution available")
            return

        print("=" * 70)
        print("VEHICLE LOADING SOLUTION")
        print("=" * 70)
        print(f"Vehicle: {self.vehicle_dims[0]}L x {self.vehicle_dims[1]}W x {self.vehicle_dims[2]}H in")
        print(f"Weight Capacity: {self.weight_capacity:,} lbs")
        print()
        print(f"Items Loaded: {self.solution['items_loaded']} / {len(self.items)}")
        print(f"Total Weight: {self.solution['total_weight']:,} lbs")
        print(f"Utilization: {self.solution['utilization']:.1f}%")
        print()
        print("Axle Weight Distribution:")
        axle = self.solution['axle_weights']
        print(f"  Front Axle: {axle['front_axle']:,.0f} lbs "
              f"({'OK' if axle['front_ok'] else 'OVER LIMIT'})")
        print(f"  Rear Axle: {axle['rear_axle']:,.0f} lbs "
              f"({'OK' if axle['rear_ok'] else 'OVER LIMIT'})")
        print(f"  Balanced: {'Yes' if axle['balanced'] else 'No - adjust load'}")


# Example usage
if __name__ == "__main__":
    # 26ft box truck
    loader = SingleStopVehicleLoader(
        vehicle_length=312,  # 26ft in inches
        vehicle_width=96,    # 8ft
        vehicle_height=96,   # 8ft
        weight_capacity=10000  # lbs
    )

    # Add items
    loader.add_item(48, 40, 60, 800, "Pallet_1")
    loader.add_item(48, 40, 50, 700, "Pallet_2")
    loader.add_item(48, 40, 55, 750, "Pallet_3")
    loader.add_item(36, 30, 40, 500, "Box_1")
    loader.add_item(36, 30, 40, 500, "Box_2")

    # Optimize
    solution = loader.optimize_loading(algorithm='weight_balanced')
    loader.print_solution()
多站点车辆装载
class MultiStopVehicleLoader:
    """
    Optimize vehicle loading for multi-stop delivery routes

    Ensures items are accessible in delivery sequence
    """

    def __init__(self, vehicle_dims, weight_capacity):
        self.vehicle_dims = vehicle_dims
        self.weight_capacity = weight_capacity
        self.stops = []  # List of delivery stops
        self.solution = None

    def add_stop(self, stop_id, items, delivery_sequence):
        """
        Add delivery stop with items

        Parameters:
        - stop_id: stop identifier
        - items: list of item dicts with 'dims' and 'weight'
        - delivery_sequence: order in route (1, 2, 3, ...)
        """

        self.stops.append({
            'id': stop_id,
            'items': items,
            'sequence': delivery_sequence
        })

    def optimize_loading(self):
        """
        Optimize loading for multi-stop delivery

        Strategy:
        - Zone vehicle by delivery sequence
        - Last stop loaded first (at door)
        - Earlier stops loaded deeper in vehicle
        """

        # Sort stops by reverse delivery sequence
        sorted_stops = sorted(self.stops,
                            key=lambda s: s['sequence'],
                            reverse=True)

        L, W, H = self.vehicle_dims

        # Calculate zones
        num_stops = len(sorted_stops)
        zone_length = L / num_stops

        zones = []
        current_weight = 0

        for idx, stop in enumerate(sorted_stops):
            zone_start = idx * zone_length
            zone_end = (idx + 1) * zone_length

            zone_items = []

            # Load items for this stop in this zone
            for item in stop['items']:
                if current_weight + item['weight'] <= self.weight_capacity:
                    # Simple placement (could be more sophisticated)
                    zone_items.append({
                        'item': item,
                        'stop_id': stop['id'],
                        'zone': (zone_start, zone_end)
                    })
                    current_weight += item['weight']

            zones.append({
                'stop': stop,
                'zone': (zone_start, zone_end),
                'items': zone_items
            })

        self.solution = {
            'zones': zones,
            'total_weight': current_weight,
            'stops_loaded': len(zones),
            'total_items': sum(len(z['items']) for z in zones)
        }

        return self.solution

    def print_solution(self):
        """Print multi-stop loading plan"""
        if not self.solution:
            print("No solution available")
            return

        print("=" * 70)
        print("MULTI-STOP VEHICLE LOADING PLAN")
        print("=" * 70)
        print(f"Total Weight: {self.solution['total_weight']:,} lbs")
        print(f"Stops: {self.solution['stops_loaded']}")
        print(f"Total Items: {self.solution['total_items']}")
        print()

        for zone_data in self.solution['zones']:
            stop = zone_data['stop']
            zone = zone_data['zone']
            print(f"Stop {stop['sequence']}: {stop['id']}")
            print(f"  Zone: {zone[0]:.0f}-{zone[1]:.0f} inches from front")
            print(f"  Items: {len(zone_data['items'])}")
            print()
车队装载优化
def optimize_fleet_loading(orders, vehicles):
    """
    Optimize loading across multiple vehicles

    Assigns orders to vehicles to minimize:
    - Number of vehicles used
    - Total distance traveled
    - Loading/unloading complexity

    Parameters:
    - orders: list of order dicts with items, destination, priority
    - vehicles: list of available vehicle specs

    Returns: assignment of orders to vehicles
    """

    from pulp import *

    n_orders = len(orders)
    n_vehicles = len(vehicles)

    # Create problem
    prob = LpProblem("Fleet_Loading", LpMinimize)

    # Decision variables
    # x[i,j] = 1 if order i assigned to vehicle j
    x = LpVariable.dicts("assign",
                        [(i, j) for i in range(n_orders) for j in range(n_vehicles)],
                        cat='Binary')

    # y[j] = 1 if vehicle j is used
    y = LpVariable.dicts("use_vehicle", range(n_vehicles), cat='Binary')

    # Objective: Minimize vehicles used + routing cost
    prob += lpSum([y[j] * vehicles[j]['cost']
                   for j in range(n_vehicles)]), "Total_Cost"

    # Constraints

    # 1. Each order assigned to exactly one vehicle
    for i in range(n_orders):
        prob += lpSum([x[i,j] for j in range(n_vehicles)]) == 1, f"Order_{i}"

    # 2. Vehicle capacity (weight)
    for j in range(n_vehicles):
        prob += (lpSum([orders[i]['weight'] * x[i,j] for i in range(n_orders)]) <=
                vehicles[j]['weight_capacity']), f"Weight_{j}"

    # 3. Vehicle capacity (volume)
    for j in range(n_vehicles):
        prob += (lpSum([orders[i]['volume'] * x[i,j] for i in range(n_orders)]) <=
                vehicles[j]['volume_capacity']), f"Volume_{j}"

    # 4. Vehicle used if orders assigned
    for j in range(n_vehicles):
        for i in range(n_orders):
            prob += x[i,j] <= y[j], f"VehicleUsed_{i}_{j}"

    # Solve
    prob.solve(PULP_CBC_CMD(msg=0))

    # Extract solution
    assignments = [[] for _ in range(n_vehicles)]

    for i in range(n_orders):
        for j in range(n_vehicles):
            if x[i,j].varValue and x[i,j].varValue > 0.5:
                assignments[j].append(i)

    return {
        'status': LpStatus[prob.status],
        'vehicles_used': sum(1 for a in assignments if a),
        'assignments': assignments
    }

常见挑战与解决方案

挑战:车轴超重

问题:

  • 前轴或后轴超过法定限值
  • 路边检查不合格
  • 安全问题

解决方案:

  • 在优化中使用车轴重量计算
  • 将重物放在车轴之间
  • 避免将过多货物装在前部或后部
  • 使用货物挡杆调整重量分布
  • 考虑添加或移除物品
挑战:多站点装卸便利性

问题:

  • 早期站点的物品被埋在深处
  • 每站都需要卸货和重新装载
  • 浪费时间,还存在物品损坏风险

解决方案:

  • 按配送顺序分区装载
  • 最后一站的货物放在车门处,第一站的货物放在最前面
  • 每个分区内采用垂直堆叠
  • 将轻小物品放在顶部,便于取出
  • 考虑使用带侧门的车辆
挑战:物品尺寸各异

问题:

  • 托盘和散装箱混装
  • 高度不同导致空间浪费
  • 难以固定

解决方案:

  • 将相似物品放在一起
  • 用托盘作为散装物品的底座
  • 用软质货物或填充材料填补空隙
  • 将较小物品堆放在较大的底座上
  • 使用货网或绑带

输出格式

车辆装载报告

车辆:26 英尺厢式卡车

  • 尺寸:26'L x 8'W x 8'H
  • 载重上限:12,000 lbs
  • 路线:5 个站点

装载计划:

分区 1(0-5ft)- 站点 5(最后一站):

  • 3 个托盘:P045、P046、P047
  • 重量:2,100 lbs
  • 可从后门取货

分区 2(5-10ft)- 站点 4:

  • 2 个托盘 + 8 个箱子
  • 重量:1,850 lbs

分区 3(10-15ft)- 站点 3:

  • 4 个托盘
  • 重量:2,800 lbs

分区 4(15-20ft)- 站点 2:

  • 3 个托盘 + 12 个箱子
  • 重量:2,400 lbs

分区 5(20-26ft)- 站点 1(第一站):

  • 2 个托盘
  • 重量:1,600 lbs

摘要:

  • 总重量:10,750 lbs(载重上限的 90%)
  • 容积利用率:82%
  • 车轴重量:前轴 4,200 lbs,后轴 6,550 lbs ✓
  • 货物已固定:是(4 根货物挡杆、缠绕膜)

需要询问的问题

  1. 车辆类型是什么?(厢式车、厢式卡车、半挂车?)
  2. 货物的尺寸和载重上限是多少?
  3. 是单一目的地还是多个站点?
  4. 如果有多个站点,配送顺序是什么?
  5. 是否有车轴重量方面的顾虑或限制?
  6. 物品是装在托盘上还是散装?
  7. 是否有特殊处理要求?

相关技能

  • route-optimization:用于配送路线规划
  • 3d-bin-packing:用于通用 3D 装箱算法
  • pallet-loading:用于托盘级优化
  • container-loading-optimization:用于集装箱装载
  • fleet-management:用于车队优化
  • last-mile-delivery:用于末端配送优化

评论

支持 Markdown