Claude Code Plugins

Community-maintained marketplace

Feedback

Implement routing strategies for warehouse order picking. Use this skill when determining optimal pick sequences, applying heuristic routing methods, calculating travel distances, or optimizing picker movements through storage areas.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name pick-routing
description Implement routing strategies for warehouse order picking. Use this skill when determining optimal pick sequences, applying heuristic routing methods, calculating travel distances, or optimizing picker movements through storage areas.

Pick Routing

Implement efficient routing strategies for warehouse order picking operations.

Installation

pip install numpy pandas networkx

Quick Start

import numpy as np

# Define pick locations
picks = [
    {'sku': 'A100', 'zone': 'A', 'aisle': 1, 'bay': 5, 'level': 2},
    {'sku': 'B200', 'zone': 'A', 'aisle': 3, 'bay': 12, 'level': 1},
    {'sku': 'C300', 'zone': 'B', 'aisle': 2, 'bay': 8, 'level': 3}
]

# Generate optimal pick sequence
route = optimize_pick_route(picks)

Routing Strategies

Traversal Strategy

def traversal_routing(picks, aisles_in_zone):
    """
    Traverse entire aisles that contain picks.
    Best for high-density picking.
    """
    # Group picks by aisle
    picks_by_aisle = {}
    for pick in picks:
        key = (pick['zone'], pick['aisle'])
        if key not in picks_by_aisle:
            picks_by_aisle[key] = []
        picks_by_aisle[key].append(pick)

    route = []
    direction = 1  # 1 = forward, -1 = backward

    for zone_aisle in sorted(picks_by_aisle.keys()):
        aisle_picks = picks_by_aisle[zone_aisle]
        # Sort by bay position
        aisle_picks.sort(key=lambda p: p['bay'], reverse=(direction == -1))
        route.extend(aisle_picks)
        direction *= -1  # Alternate direction

    return route

Return Strategy

def return_routing(picks):
    """
    Enter and exit each aisle from the same end.
    Best for low-density picking.
    """
    picks_by_aisle = {}
    for pick in picks:
        key = (pick['zone'], pick['aisle'])
        if key not in picks_by_aisle:
            picks_by_aisle[key] = []
        picks_by_aisle[key].append(pick)

    route = []
    for zone_aisle in sorted(picks_by_aisle.keys()):
        aisle_picks = sorted(picks_by_aisle[zone_aisle], key=lambda p: p['bay'])
        route.extend(aisle_picks)
        # Implicit return to aisle entrance

    return route

Combined Strategy

def combined_routing(picks, aisle_length, threshold=0.5):
    """
    Use traversal for aisles with many picks, return for sparse aisles.
    """
    picks_by_aisle = {}
    for pick in picks:
        key = (pick['zone'], pick['aisle'])
        if key not in picks_by_aisle:
            picks_by_aisle[key] = []
        picks_by_aisle[key].append(pick)

    route = []
    current_end = 'front'

    for zone_aisle in sorted(picks_by_aisle.keys()):
        aisle_picks = picks_by_aisle[zone_aisle]
        positions = [p['bay'] for p in aisle_picks]

        # Calculate coverage
        coverage = (max(positions) - min(positions)) / aisle_length

        if coverage > threshold:
            # Traversal - go through entire aisle
            if current_end == 'front':
                aisle_picks.sort(key=lambda p: p['bay'])
                current_end = 'back'
            else:
                aisle_picks.sort(key=lambda p: p['bay'], reverse=True)
                current_end = 'front'
        else:
            # Return - enter and exit same side
            if current_end == 'front':
                aisle_picks.sort(key=lambda p: p['bay'])
            else:
                aisle_picks.sort(key=lambda p: p['bay'], reverse=True)

        route.extend(aisle_picks)

    return route

Pick Sequence Optimization

def optimize_sequence_nearest_neighbor(picks, start_location):
    """Sequence picks using nearest neighbor heuristic."""

    def distance(p1, p2):
        return (abs(p1['aisle'] - p2['aisle']) * 10 +
                abs(p1['bay'] - p2['bay']) +
                abs(p1['level'] - p2['level']) * 2)

    remaining = picks.copy()
    sequence = []
    current = start_location

    while remaining:
        nearest = min(remaining, key=lambda p: distance(current, p))
        sequence.append(nearest)
        remaining.remove(nearest)
        current = nearest

    return sequence

def optimize_sequence_2opt(picks, distance_func):
    """Improve pick sequence using 2-opt."""
    best = picks.copy()
    improved = True

    while improved:
        improved = False
        for i in range(1, len(best) - 1):
            for j in range(i + 1, len(best)):
                # Try reversing segment
                new_route = best[:i] + best[i:j+1][::-1] + best[j+1:]

                old_dist = sum(distance_func(best[k], best[k+1])
                              for k in range(len(best)-1))
                new_dist = sum(distance_func(new_route[k], new_route[k+1])
                              for k in range(len(new_route)-1))

                if new_dist < old_dist:
                    best = new_route
                    improved = True
                    break
            if improved:
                break

    return best

Multi-Level Picking

def level_optimized_routing(picks):
    """
    Optimize routing considering vertical travel between levels.
    Group picks by level to minimize elevator/lift usage.
    """
    picks_by_level = {}
    for pick in picks:
        level = pick['level']
        if level not in picks_by_level:
            picks_by_level[level] = []
        picks_by_level[level].append(pick)

    route = []

    # Process levels in order (bottom to top or vice versa)
    for level in sorted(picks_by_level.keys()):
        level_picks = picks_by_level[level]
        # Apply horizontal routing strategy within each level
        level_route = traversal_routing(level_picks, aisles_in_zone=10)
        route.extend(level_route)

    return route

def calculate_vertical_travel(route, level_travel_time=5):
    """Calculate additional time for level changes."""
    level_changes = 0
    for i in range(1, len(route)):
        if route[i]['level'] != route[i-1]['level']:
            level_changes += abs(route[i]['level'] - route[i-1]['level'])

    return level_changes * level_travel_time

Route Distance Calculation

class WarehouseDistanceCalculator:
    def __init__(self, aisle_width, bay_depth, level_height):
        self.aisle_width = aisle_width
        self.bay_depth = bay_depth
        self.level_height = level_height

    def distance(self, loc1, loc2):
        """Calculate travel distance between two locations."""
        horizontal = 0

        if loc1['aisle'] == loc2['aisle']:
            # Same aisle
            horizontal = abs(loc1['bay'] - loc2['bay']) * self.bay_depth
        else:
            # Different aisles
            aisle_diff = abs(loc1['aisle'] - loc2['aisle'])
            horizontal = (aisle_diff * self.aisle_width +
                         abs(loc1['bay'] - loc2['bay']) * self.bay_depth)

        vertical = abs(loc1['level'] - loc2['level']) * self.level_height

        return horizontal + vertical

    def route_distance(self, route, start=None, end=None):
        """Calculate total route distance."""
        total = 0

        if start:
            total += self.distance(start, route[0])

        for i in range(len(route) - 1):
            total += self.distance(route[i], route[i+1])

        if end:
            total += self.distance(route[-1], end)

        return total

Pick Time Estimation

def estimate_pick_time(route, walk_speed=1.2, pick_time=5, level_change_time=10):
    """
    Estimate total time to complete pick route.
    walk_speed: meters per second
    pick_time: seconds per pick
    """
    calc = WarehouseDistanceCalculator(
        aisle_width=3.0, bay_depth=1.2, level_height=1.5
    )

    walk_distance = calc.route_distance(route)
    walk_time = walk_distance / walk_speed

    total_pick_time = len(route) * pick_time

    level_changes = sum(
        1 for i in range(1, len(route))
        if route[i]['level'] != route[i-1]['level']
    )

    total_time = walk_time + total_pick_time + (level_changes * level_change_time)

    return {
        'walk_distance': walk_distance,
        'walk_time': walk_time,
        'pick_time': total_pick_time,
        'level_change_time': level_changes * level_change_time,
        'total_time': total_time
    }