yard-management
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseYard Management
堆场管理
You are an expert in yard management and trailer logistics. Your goal is to help optimize yard operations, improve trailer visibility, reduce detention costs, and maximize dock door utilization through efficient yard management practices and technology.
您是yard management和拖车物流领域的专家。您的目标是通过高效的堆场管理实践与技术,帮助优化堆场作业、提升拖车可见性、降低滞留成本,并最大化码头门利用率。
Initial Assessment
初始评估
Before optimizing yard operations, understand:
-
Facility Characteristics
- Yard size and capacity? (trailer spots)
- Number of dock doors?
- Layout constraints? (space, access, turning radius)
- Gate security and check-in process?
-
Operational Volume
- Daily inbound/outbound trailers?
- Average dwell time per trailer?
- Peak times and patterns?
- Types of trailers? (dry van, reefer, flatbed)
-
Current Challenges
- Trailer visibility issues?
- Long wait times at gate or dock?
- High detention/demurrage costs?
- Difficulty finding trailers in yard?
- Congestion at doors?
-
Resources
- Number of yard jockeys?
- Yard tractors available?
- Technology in place? (YMS, GPS, RFID)
- Staffing and shifts?
在优化堆场作业前,需了解以下信息:
-
设施特征
- 堆场规模与容量?(拖车泊位数量)
- 码头门数量?
- 布局限制?(空间、通道、转弯半径)
- 闸口安全与登记流程?
-
作业量
- 每日进出拖车数量?
- 每辆拖车的平均停留时间?
- 高峰时段与规律?
- 拖车类型?(干货厢式车、冷藏车、平板车)
-
当前挑战
- 拖车可见性问题?
- 闸口或码头等待时间过长?
- 高额滞留/滞期费用?
- 难以在堆场中找到拖车?
- 码头门拥堵?
-
资源情况
- yard jockey数量?
- 可用堆场牵引车数量?
- 现有技术?(YMS、GPS、RFID)
- 人员配置与轮班情况?
Yard Management Framework
堆场管理框架
Core Functions of Yard Management
堆场管理核心功能
1. Gate Management
- Check-in/check-out process
- Carrier credential verification
- BOL and documentation
- Safety inspections
- Appointment verification
2. Yard Planning & Layout
- Trailer parking locations
- Staging zones by priority
- Dock door assignments
- Traffic flow optimization
3. Trailer Movement
- Yard jockey dispatch
- Spotting trailers at doors
- Repositioning for loading/unloading
- Trailer pool management
4. Tracking & Visibility
- Real-time trailer location
- Load status (empty, loaded, in-process)
- Dwell time monitoring
- Exception management
5. Dock Scheduling
- Appointment booking
- Door assignment
- Load/unload coordination
- Carrier communication
1. 闸口管理
- 登记/注销流程
- 承运人资质验证
- BOL与文件处理
- 安全检查
- 预约验证
2. 堆场规划与布局
- 拖车停放位置
- 按优先级划分的 staging zones
- 码头门分配
- 交通流向优化
3. 拖车调度
- yard jockey调度
- 拖车停靠码头门
- 为装卸作业重新调度拖车
- 拖车池管理
4. 跟踪与可见性
- 实时拖车位置
- 装载状态(空车、已装载、作业中)
- 停留时间监控
- 异常管理
5. 码头调度
- 预约预订
- 码头门分配
- 装卸协调
- 承运人沟通
Yard Layout Optimization
堆场布局优化
Yard Design Principles
堆场设计原则
python
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import distance
class YardLayoutOptimizer:
"""
Optimize yard layout and trailer positioning
Minimize jockey moves and door spotting time
"""
def __init__(self, num_doors, yard_capacity, dock_positions):
"""
Parameters:
- num_doors: number of dock doors
- yard_capacity: total trailer parking spots
- dock_positions: list of (x, y) coordinates for each door
"""
self.num_doors = num_doors
self.yard_capacity = yard_capacity
self.dock_positions = np.array(dock_positions)
def design_staging_zones(self, zone_types=['inbound', 'outbound',
'live', 'empty']):
"""
Design staging zones based on trailer status
Returns optimal zone assignments
"""
# Allocate yard capacity by zone
# Typical allocation:
# - Inbound waiting: 30%
# - Outbound ready: 25%
# - Live loading/unloading: 20%
# - Empty/drop trailers: 25%
allocations = {
'inbound': int(self.yard_capacity * 0.30),
'outbound': int(self.yard_capacity * 0.25),
'live': int(self.yard_capacity * 0.20),
'empty': int(self.yard_capacity * 0.25)
}
# Position zones near relevant doors
zones = {}
# Inbound zone: Near inbound doors (first half)
zones['inbound'] = {
'capacity': allocations['inbound'],
'preferred_doors': list(range(self.num_doors // 2)),
'avg_distance_to_door': 50 # feet
}
# Outbound zone: Near outbound doors (second half)
zones['outbound'] = {
'capacity': allocations['outbound'],
'preferred_doors': list(range(self.num_doors // 2, self.num_doors)),
'avg_distance_to_door': 50
}
# Live zone: Immediately adjacent to doors
zones['live'] = {
'capacity': allocations['live'],
'preferred_doors': list(range(self.num_doors)),
'avg_distance_to_door': 20 # Closest
}
# Empty zone: Furthest from doors
zones['empty'] = {
'capacity': allocations['empty'],
'preferred_doors': [],
'avg_distance_to_door': 150 # Furthest
}
return zones
def calculate_optimal_spot_locations(self, num_spots, zone_center,
spacing=60):
"""
Calculate grid of trailer parking spots
Parameters:
- num_spots: number of spots needed
- zone_center: (x, y) center of zone
- spacing: feet between trailers
"""
# Create grid layout
spots_per_row = 10 # Standard configuration
num_rows = int(np.ceil(num_spots / spots_per_row))
spots = []
for row in range(num_rows):
for col in range(spots_per_row):
if len(spots) >= num_spots:
break
x = zone_center[0] + (col * spacing)
y = zone_center[1] + (row * spacing)
spots.append({
'spot_id': f'S{len(spots)+1:03d}',
'position': (x, y),
'row': row,
'col': col
})
return spots
def assign_trailer_to_spot(self, trailer_status, trailer_door_assignment,
available_spots):
"""
Assign trailer to optimal parking spot
Minimize distance to assigned door
Parameters:
- trailer_status: 'inbound', 'outbound', 'live', 'empty'
- trailer_door_assignment: door number (if assigned)
- available_spots: list of available spot dictionaries
"""
# Filter spots by zone preference
zone_spots = [
spot for spot in available_spots
if spot.get('zone') == trailer_status
]
if not zone_spots:
zone_spots = available_spots # Use any available
if not zone_spots:
return None # Yard full
# If door assigned, find closest spot to that door
if trailer_door_assignment is not None:
door_position = self.dock_positions[trailer_door_assignment]
# Calculate distances
distances = [
distance.euclidean(spot['position'], door_position)
for spot in zone_spots
]
# Select closest spot
best_spot_idx = np.argmin(distances)
assigned_spot = zone_spots[best_spot_idx]
else:
# No door assigned, use first available in zone
assigned_spot = zone_spots[0]
return assigned_spot
def analyze_yard_utilization(self, occupied_spots, total_spots):
"""
Calculate yard utilization metrics
Returns utilization by zone and overall
"""
utilization = {
'total_spots': total_spots,
'occupied_spots': len(occupied_spots),
'utilization_pct': len(occupied_spots) / total_spots * 100,
'available_spots': total_spots - len(occupied_spots)
}
# By zone
zones = {}
for spot in occupied_spots:
zone = spot.get('zone', 'unknown')
if zone not in zones:
zones[zone] = 0
zones[zone] += 1
utilization['by_zone'] = zones
return utilizationpython
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import distance
class YardLayoutOptimizer:
"""
Optimize yard layout and trailer positioning
Minimize jockey moves and door spotting time
"""
def __init__(self, num_doors, yard_capacity, dock_positions):
"""
Parameters:
- num_doors: number of dock doors
- yard_capacity: total trailer parking spots
- dock_positions: list of (x, y) coordinates for each door
"""
self.num_doors = num_doors
self.yard_capacity = yard_capacity
self.dock_positions = np.array(dock_positions)
def design_staging_zones(self, zone_types=['inbound', 'outbound',
'live', 'empty']):
"""
Design staging zones based on trailer status
Returns optimal zone assignments
"""
# Allocate yard capacity by zone
# Typical allocation:
# - Inbound waiting: 30%
# - Outbound ready: 25%
# - Live loading/unloading: 20%
# - Empty/drop trailers: 25%
allocations = {
'inbound': int(self.yard_capacity * 0.30),
'outbound': int(self.yard_capacity * 0.25),
'live': int(self.yard_capacity * 0.20),
'empty': int(self.yard_capacity * 0.25)
}
# Position zones near relevant doors
zones = {}
# Inbound zone: Near inbound doors (first half)
zones['inbound'] = {
'capacity': allocations['inbound'],
'preferred_doors': list(range(self.num_doors // 2)),
'avg_distance_to_door': 50 # feet
}
# Outbound zone: Near outbound doors (second half)
zones['outbound'] = {
'capacity': allocations['outbound'],
'preferred_doors': list(range(self.num_doors // 2, self.num_doors)),
'avg_distance_to_door': 50
}
# Live zone: Immediately adjacent to doors
zones['live'] = {
'capacity': allocations['live'],
'preferred_doors': list(range(self.num_doors)),
'avg_distance_to_door': 20 # Closest
}
# Empty zone: Furthest from doors
zones['empty'] = {
'capacity': allocations['empty'],
'preferred_doors': [],
'avg_distance_to_door': 150 # Furthest
}
return zones
def calculate_optimal_spot_locations(self, num_spots, zone_center,
spacing=60):
"""
Calculate grid of trailer parking spots
Parameters:
- num_spots: number of spots needed
- zone_center: (x, y) center of zone
- spacing: feet between trailers
"""
# Create grid layout
spots_per_row = 10 # Standard configuration
num_rows = int(np.ceil(num_spots / spots_per_row))
spots = []
for row in range(num_rows):
for col in range(spots_per_row):
if len(spots) >= num_spots:
break
x = zone_center[0] + (col * spacing)
y = zone_center[1] + (row * spacing)
spots.append({
'spot_id': f'S{len(spots)+1:03d}',
'position': (x, y),
'row': row,
'col': col
})
return spots
def assign_trailer_to_spot(self, trailer_status, trailer_door_assignment,
available_spots):
"""
Assign trailer to optimal parking spot
Minimize distance to assigned door
Parameters:
- trailer_status: 'inbound', 'outbound', 'live', 'empty'
- trailer_door_assignment: door number (if assigned)
- available_spots: list of available spot dictionaries
"""
# Filter spots by zone preference
zone_spots = [
spot for spot in available_spots
if spot.get('zone') == trailer_status
]
if not zone_spots:
zone_spots = available_spots # Use any available
if not zone_spots:
return None # Yard full
# If door assigned, find closest spot to that door
if trailer_door_assignment is not None:
door_position = self.dock_positions[trailer_door_assignment]
# Calculate distances
distances = [
distance.euclidean(spot['position'], door_position)
for spot in zone_spots
]
# Select closest spot
best_spot_idx = np.argmin(distances)
assigned_spot = zone_spots[best_spot_idx]
else:
# No door assigned, use first available in zone
assigned_spot = zone_spots[0]
return assigned_spot
def analyze_yard_utilization(self, occupied_spots, total_spots):
"""
Calculate yard utilization metrics
Returns utilization by zone and overall
"""
utilization = {
'total_spots': total_spots,
'occupied_spots': len(occupied_spots),
'utilization_pct': len(occupied_spots) / total_spots * 100,
'available_spots': total_spots - len(occupied_spots)
}
# By zone
zones = {}
for spot in occupied_spots:
zone = spot.get('zone', 'unknown')
if zone not in zones:
zones[zone] = 0
zones[zone] += 1
utilization['by_zone'] = zones
return utilizationExample usage
Example usage
optimizer = YardLayoutOptimizer(
num_doors=40,
yard_capacity=200,
dock_positions=[(i*20, 0) for i in range(40)] # Doors in a line
)
zones = optimizer.design_staging_zones()
print("Staging Zones:")
for zone_name, zone_info in zones.items():
print(f" {zone_name}: {zone_info['capacity']} spots, "
f"avg distance {zone_info['avg_distance_to_door']} ft")
---optimizer = YardLayoutOptimizer(
num_doors=40,
yard_capacity=200,
dock_positions=[(i*20, 0) for i in range(40)] # Doors in a line
)
zones = optimizer.design_staging_zones()
print("Staging Zones:")
for zone_name, zone_info in zones.items():
print(f" {zone_name}: {zone_info['capacity']} spots, "
f"avg distance {zone_info['avg_distance_to_door']} ft")
---Dock Door Scheduling
码头门调度
Appointment Scheduling System
预约调度系统
python
import pandas as pd
from datetime import datetime, timedelta
class DockSchedulingSystem:
"""
Manage dock door appointments and scheduling
Optimize door utilization and minimize wait times
"""
def __init__(self, num_doors, hours_of_operation=(6, 22)):
"""
Parameters:
- num_doors: number of dock doors
- hours_of_operation: (start_hour, end_hour) tuple
"""
self.num_doors = num_doors
self.start_hour = hours_of_operation[0]
self.end_hour = hours_of_operation[1]
self.schedule = {}
def create_time_slots(self, date, slot_duration_hours=2):
"""
Create available time slots for a date
Returns list of time slots
"""
slots = []
current_time = datetime.combine(date, datetime.min.time()).replace(
hour=self.start_hour
)
end_time = datetime.combine(date, datetime.min.time()).replace(
hour=self.end_hour
)
while current_time < end_time:
slot_end = current_time + timedelta(hours=slot_duration_hours)
slots.append({
'start_time': current_time,
'end_time': slot_end,
'available_doors': list(range(self.num_doors))
})
current_time = slot_end
return slots
def book_appointment(self, carrier, appointment_type, requested_time,
duration_hours=2, door_preference=None):
"""
Book dock appointment
Parameters:
- carrier: carrier name
- appointment_type: 'inbound' or 'outbound'
- requested_time: datetime
- duration_hours: expected duration
- door_preference: specific door number (optional)
"""
date = requested_time.date()
# Get or create slots for date
if date not in self.schedule:
self.schedule[date] = self.create_time_slots(date)
# Find matching time slot
for slot in self.schedule[date]:
if (slot['start_time'] <= requested_time <
slot['end_time'] and
len(slot['available_doors']) > 0):
# Assign door
if door_preference and door_preference in slot['available_doors']:
assigned_door = door_preference
else:
assigned_door = slot['available_doors'][0]
# Remove door from available
slot['available_doors'].remove(assigned_door)
appointment = {
'appointment_id': f"APT{len(self.schedule)*100 + 1}",
'carrier': carrier,
'type': appointment_type,
'scheduled_time': slot['start_time'],
'door': assigned_door,
'duration': duration_hours,
'status': 'scheduled'
}
return appointment
# No available slot found
return {
'error': 'No available slot',
'requested_time': requested_time,
'suggestion': 'Try different time or date'
}
def check_availability(self, date, appointment_type=None):
"""
Check door availability for a date
Returns available slots
"""
if date not in self.schedule:
self.schedule[date] = self.create_time_slots(date)
availability = []
for slot in self.schedule[date]:
if len(slot['available_doors']) > 0:
availability.append({
'time_slot': f"{slot['start_time'].strftime('%H:%M')} - "
f"{slot['end_time'].strftime('%H:%M')}",
'available_doors': len(slot['available_doors']),
'door_numbers': slot['available_doors'][:5] # Show first 5
})
return availability
def calculate_utilization(self, date):
"""
Calculate door utilization for a date
Returns utilization percentage
"""
if date not in self.schedule:
return {'utilization': 0, 'message': 'No appointments scheduled'}
total_door_slots = 0
used_door_slots = 0
for slot in self.schedule[date]:
# Each slot has potential of all doors
total_door_slots += self.num_doors
# Count used doors (initially available - currently available)
used_doors = self.num_doors - len(slot['available_doors'])
used_door_slots += used_doors
utilization = used_door_slots / total_door_slots * 100 if total_door_slots > 0 else 0
return {
'date': date,
'utilization_pct': utilization,
'total_door_slots': total_door_slots,
'used_door_slots': used_door_slots,
'target_utilization': 75 # Best practice target
}
def optimize_door_assignments(self, appointments):
"""
Re-optimize door assignments to minimize moves
Group similar appointment types on adjacent doors
"""
# Separate by type
inbound = [a for a in appointments if a['type'] == 'inbound']
outbound = [a for a in appointments if a['type'] == 'outbound']
# Assign inbound to first half of doors
inbound_doors = list(range(self.num_doors // 2))
outbound_doors = list(range(self.num_doors // 2, self.num_doors))
# Reassign
for idx, appt in enumerate(inbound):
if idx < len(inbound_doors):
appt['door'] = inbound_doors[idx]
for idx, appt in enumerate(outbound):
if idx < len(outbound_doors):
appt['door'] = outbound_doors[idx]
return appointmentspython
import pandas as pd
from datetime import datetime, timedelta
class DockSchedulingSystem:
"""
Manage dock door appointments and scheduling
Optimize door utilization and minimize wait times
"""
def __init__(self, num_doors, hours_of_operation=(6, 22)):
"""
Parameters:
- num_doors: number of dock doors
- hours_of_operation: (start_hour, end_hour) tuple
"""
self.num_doors = num_doors
self.start_hour = hours_of_operation[0]
self.end_hour = hours_of_operation[1]
self.schedule = {}
def create_time_slots(self, date, slot_duration_hours=2):
"""
Create available time slots for a date
Returns list of time slots
"""
slots = []
current_time = datetime.combine(date, datetime.min.time()).replace(
hour=self.start_hour
)
end_time = datetime.combine(date, datetime.min.time()).replace(
hour=self.end_hour
)
while current_time < end_time:
slot_end = current_time + timedelta(hours=slot_duration_hours)
slots.append({
'start_time': current_time,
'end_time': slot_end,
'available_doors': list(range(self.num_doors))
})
current_time = slot_end
return slots
def book_appointment(self, carrier, appointment_type, requested_time,
duration_hours=2, door_preference=None):
"""
Book dock appointment
Parameters:
- carrier: carrier name
- appointment_type: 'inbound' or 'outbound'
- requested_time: datetime
- duration_hours: expected duration
- door_preference: specific door number (optional)
"""
date = requested_time.date()
# Get or create slots for date
if date not in self.schedule:
self.schedule[date] = self.create_time_slots(date)
# Find matching time slot
for slot in self.schedule[date]:
if (slot['start_time'] <= requested_time <
slot['end_time'] and
len(slot['available_doors']) > 0):
# Assign door
if door_preference and door_preference in slot['available_doors']:
assigned_door = door_preference
else:
assigned_door = slot['available_doors'][0]
# Remove door from available
slot['available_doors'].remove(assigned_door)
appointment = {
'appointment_id': f"APT{len(self.schedule)*100 + 1}",
'carrier': carrier,
'type': appointment_type,
'scheduled_time': slot['start_time'],
'door': assigned_door,
'duration': duration_hours,
'status': 'scheduled'
}
return appointment
# No available slot found
return {
'error': 'No available slot',
'requested_time': requested_time,
'suggestion': 'Try different time or date'
}
def check_availability(self, date, appointment_type=None):
"""
Check door availability for a date
Returns available slots
"""
if date not in self.schedule:
self.schedule[date] = self.create_time_slots(date)
availability = []
for slot in self.schedule[date]:
if len(slot['available_doors']) > 0:
availability.append({
'time_slot': f"{slot['start_time'].strftime('%H:%M')} - "
f"{slot['end_time'].strftime('%H:%M')}",
'available_doors': len(slot['available_doors']),
'door_numbers': slot['available_doors'][:5] # Show first 5
})
return availability
def calculate_utilization(self, date):
"""
Calculate door utilization for a date
Returns utilization percentage
"""
if date not in self.schedule:
return {'utilization': 0, 'message': 'No appointments scheduled'}
total_door_slots = 0
used_door_slots = 0
for slot in self.schedule[date]:
# Each slot has potential of all doors
total_door_slots += self.num_doors
# Count used doors (initially available - currently available)
used_doors = self.num_doors - len(slot['available_doors'])
used_door_slots += used_doors
utilization = used_door_slots / total_door_slots * 100 if total_door_slots > 0 else 0
return {
'date': date,
'utilization_pct': utilization,
'total_door_slots': total_door_slots,
'used_door_slots': used_door_slots,
'target_utilization': 75 # Best practice target
}
def optimize_door_assignments(self, appointments):
"""
Re-optimize door assignments to minimize moves
Group similar appointment types on adjacent doors
"""
# Separate by type
inbound = [a for a in appointments if a['type'] == 'inbound']
outbound = [a for a in appointments if a['type'] == 'outbound']
# Assign inbound to first half of doors
inbound_doors = list(range(self.num_doors // 2))
outbound_doors = list(range(self.num_doors // 2, self.num_doors))
# Reassign
for idx, appt in enumerate(inbound):
if idx < len(inbound_doors):
appt['door'] = inbound_doors[idx]
for idx, appt in enumerate(outbound):
if idx < len(outbound_doors):
appt['door'] = outbound_doors[idx]
return appointmentsExample usage
Example usage
scheduler = DockSchedulingSystem(num_doors=40)
scheduler = DockSchedulingSystem(num_doors=40)
Book appointments
Book appointments
appt1 = scheduler.book_appointment(
carrier='ABC Trucking',
appointment_type='inbound',
requested_time=datetime.now().replace(hour=8, minute=0)
)
print(f"Appointment booked: Door {appt1.get('door')} at "
f"{appt1.get('scheduled_time')}")
appt1 = scheduler.book_appointment(
carrier='ABC Trucking',
appointment_type='inbound',
requested_time=datetime.now().replace(hour=8, minute=0)
)
print(f"Appointment booked: Door {appt1.get('door')} at "
f"{appt1.get('scheduled_time')}")
Check availability
Check availability
tomorrow = datetime.now().date() + timedelta(days=1)
availability = scheduler.check_availability(tomorrow)
print(f"\nAvailability for {tomorrow}:")
for slot in availability[:3]:
print(f" {slot['time_slot']}: {slot['available_doors']} doors available")
---tomorrow = datetime.now().date() + timedelta(days=1)
availability = scheduler.check_availability(tomorrow)
print(f"\nAvailability for {tomorrow}:")
for slot in availability[:3]:
print(f" {slot['time_slot']}: {slot['available_doors']} doors available")
---Trailer Tracking & Visibility
拖车跟踪与可见性
Yard Management System (YMS) Core Functions
堆场管理系统(YMS)核心功能
python
class YardManagementSystem:
"""
Core yard management system functionality
Track trailers, manage moves, monitor dwell time
"""
def __init__(self):
self.trailers = {} # trailer_id -> trailer info
self.yard_spots = {} # spot_id -> trailer_id
self.move_history = []
self.alerts = []
def check_in_trailer(self, trailer_id, carrier, seal_number,
trailer_type='dry_van', is_loaded=True):
"""
Check in trailer at gate
Creates trailer record in system
"""
check_in_time = datetime.now()
trailer_info = {
'trailer_id': trailer_id,
'carrier': carrier,
'seal_number': seal_number,
'trailer_type': trailer_type,
'is_loaded': is_loaded,
'status': 'in_yard',
'check_in_time': check_in_time,
'current_location': 'gate',
'dock_door': None,
'moves': 0
}
self.trailers[trailer_id] = trailer_info
# Log move
self.move_history.append({
'trailer_id': trailer_id,
'timestamp': check_in_time,
'action': 'check_in',
'location': 'gate'
})
return trailer_info
def assign_yard_spot(self, trailer_id, spot_id):
"""
Assign trailer to yard parking spot
Parameters:
- trailer_id: unique trailer identifier
- spot_id: yard spot identifier
"""
if trailer_id not in self.trailers:
return {'error': f'Trailer {trailer_id} not found'}
if spot_id in self.yard_spots and self.yard_spots[spot_id] is not None:
return {'error': f'Spot {spot_id} already occupied'}
# Update trailer location
trailer = self.trailers[trailer_id]
old_location = trailer['current_location']
trailer['current_location'] = spot_id
trailer['moves'] += 1
# Update spot
if old_location in self.yard_spots:
self.yard_spots[old_location] = None # Free old spot
self.yard_spots[spot_id] = trailer_id
# Log move
self.move_history.append({
'trailer_id': trailer_id,
'timestamp': datetime.now(),
'action': 'move_to_spot',
'from': old_location,
'to': spot_id
})
return {
'trailer_id': trailer_id,
'assigned_spot': spot_id,
'moves': trailer['moves']
}
def spot_trailer_at_door(self, trailer_id, door_number):
"""
Spot trailer at dock door for loading/unloading
Parameters:
- trailer_id: trailer to spot
- door_number: dock door number
"""
if trailer_id not in self.trailers:
return {'error': f'Trailer {trailer_id} not found'}
trailer = self.trailers[trailer_id]
old_location = trailer['current_location']
# Update trailer
trailer['current_location'] = f'door_{door_number}'
trailer['dock_door'] = door_number
trailer['status'] = 'at_door'
trailer['door_arrival_time'] = datetime.now()
trailer['moves'] += 1
# Free old spot if in yard
if old_location in self.yard_spots:
self.yard_spots[old_location] = None
# Log move
self.move_history.append({
'trailer_id': trailer_id,
'timestamp': datetime.now(),
'action': 'spot_at_door',
'door': door_number,
'from': old_location
})
return {
'trailer_id': trailer_id,
'door': door_number,
'spotted_time': trailer['door_arrival_time']
}
def complete_door_activity(self, trailer_id):
"""
Complete loading/unloading at door
Move trailer back to yard or check out
"""
if trailer_id not in self.trailers:
return {'error': f'Trailer {trailer_id} not found'}
trailer = self.trailers[trailer_id]
if trailer['status'] != 'at_door':
return {'error': 'Trailer not at door'}
# Calculate door dwell time
door_dwell = (datetime.now() - trailer['door_arrival_time']).total_seconds() / 3600
trailer['status'] = 'completed'
trailer['door_departure_time'] = datetime.now()
trailer['door_dwell_hours'] = door_dwell
# Log
self.move_history.append({
'trailer_id': trailer_id,
'timestamp': datetime.now(),
'action': 'complete_door_activity',
'door_dwell_hours': door_dwell
})
# Check for excessive door time (>2 hours)
if door_dwell > 2:
self.alerts.append({
'alert_type': 'excessive_door_dwell',
'trailer_id': trailer_id,
'door_dwell_hours': door_dwell,
'timestamp': datetime.now()
})
return {
'trailer_id': trailer_id,
'door_dwell_hours': door_dwell,
'status': 'completed'
}
def check_out_trailer(self, trailer_id):
"""
Check out trailer from facility
Final step before trailer leaves
"""
if trailer_id not in self.trailers:
return {'error': f'Trailer {trailer_id} not found'}
trailer = self.trailers[trailer_id]
# Calculate total yard dwell
total_dwell = (datetime.now() - trailer['check_in_time']).total_seconds() / 3600
trailer['status'] = 'checked_out'
trailer['check_out_time'] = datetime.now()
trailer['total_yard_dwell_hours'] = total_dwell
# Log
self.move_history.append({
'trailer_id': trailer_id,
'timestamp': datetime.now(),
'action': 'check_out',
'total_dwell_hours': total_dwell
})
# Alert if excessive yard dwell (>24 hours)
if total_dwell > 24:
self.alerts.append({
'alert_type': 'excessive_yard_dwell',
'trailer_id': trailer_id,
'total_dwell_hours': total_dwell,
'timestamp': datetime.now()
})
return {
'trailer_id': trailer_id,
'total_yard_dwell_hours': total_dwell,
'total_moves': trailer['moves']
}
def get_yard_status(self):
"""
Get current yard status summary
Returns counts by status
"""
status_counts = {}
for trailer in self.trailers.values():
status = trailer['status']
status_counts[status] = status_counts.get(status, 0) + 1
total_trailers = len(self.trailers)
occupied_spots = sum(1 for spot in self.yard_spots.values()
if spot is not None)
return {
'total_trailers_in_yard': total_trailers,
'occupied_spots': occupied_spots,
'by_status': status_counts,
'active_alerts': len(self.alerts)
}
def find_trailer(self, trailer_id):
"""
Locate trailer in yard
Returns current location
"""
if trailer_id not in self.trailers:
return {'error': 'Trailer not found'}
trailer = self.trailers[trailer_id]
return {
'trailer_id': trailer_id,
'current_location': trailer['current_location'],
'status': trailer['status'],
'carrier': trailer['carrier'],
'dwell_time_hours': (datetime.now() - trailer['check_in_time']).total_seconds() / 3600
}
def calculate_performance_metrics(self):
"""
Calculate yard performance metrics
Returns KPIs
"""
if not self.trailers:
return {'message': 'No data available'}
# Average dwell time
dwell_times = []
for trailer in self.trailers.values():
if 'total_yard_dwell_hours' in trailer:
dwell_times.append(trailer['total_yard_dwell_hours'])
avg_dwell = np.mean(dwell_times) if dwell_times else 0
# Average moves per trailer
moves = [t['moves'] for t in self.trailers.values()]
avg_moves = np.mean(moves) if moves else 0
# Door dwell times
door_dwells = []
for trailer in self.trailers.values():
if 'door_dwell_hours' in trailer:
door_dwells.append(trailer['door_dwell_hours'])
avg_door_dwell = np.mean(door_dwells) if door_dwells else 0
return {
'avg_yard_dwell_hours': avg_dwell,
'avg_moves_per_trailer': avg_moves,
'avg_door_dwell_hours': avg_door_dwell,
'total_trailers': len(self.trailers),
'total_alerts': len(self.alerts),
'target_yard_dwell_hours': 24,
'target_door_dwell_hours': 2
}python
class YardManagementSystem:
"""
Core yard management system functionality
Track trailers, manage moves, monitor dwell time
"""
def __init__(self):
self.trailers = {} # trailer_id -> trailer info
self.yard_spots = {} # spot_id -> trailer_id
self.move_history = []
self.alerts = []
def check_in_trailer(self, trailer_id, carrier, seal_number,
trailer_type='dry_van', is_loaded=True):
"""
Check in trailer at gate
Creates trailer record in system
"""
check_in_time = datetime.now()
trailer_info = {
'trailer_id': trailer_id,
'carrier': carrier,
'seal_number': seal_number,
'trailer_type': trailer_type,
'is_loaded': is_loaded,
'status': 'in_yard',
'check_in_time': check_in_time,
'current_location': 'gate',
'dock_door': None,
'moves': 0
}
self.trailers[trailer_id] = trailer_info
# Log move
self.move_history.append({
'trailer_id': trailer_id,
'timestamp': check_in_time,
'action': 'check_in',
'location': 'gate'
})
return trailer_info
def assign_yard_spot(self, trailer_id, spot_id):
"""
Assign trailer to yard parking spot
Parameters:
- trailer_id: unique trailer identifier
- spot_id: yard spot identifier
"""
if trailer_id not in self.trailers:
return {'error': f'Trailer {trailer_id} not found'}
if spot_id in self.yard_spots and self.yard_spots[spot_id] is not None:
return {'error': f'Spot {spot_id} already occupied'}
# Update trailer location
trailer = self.trailers[trailer_id]
old_location = trailer['current_location']
trailer['current_location'] = spot_id
trailer['moves'] += 1
# Update spot
if old_location in self.yard_spots:
self.yard_spots[old_location] = None # Free old spot
self.yard_spots[spot_id] = trailer_id
# Log move
self.move_history.append({
'trailer_id': trailer_id,
'timestamp': datetime.now(),
'action': 'move_to_spot',
'from': old_location,
'to': spot_id
})
return {
'trailer_id': trailer_id,
'assigned_spot': spot_id,
'moves': trailer['moves']
}
def spot_trailer_at_door(self, trailer_id, door_number):
"""
Spot trailer at dock door for loading/unloading
Parameters:
- trailer_id: trailer to spot
- door_number: dock door number
"""
if trailer_id not in self.trailers:
return {'error': f'Trailer {trailer_id} not found'}
trailer = self.trailers[trailer_id]
old_location = trailer['current_location']
# Update trailer
trailer['current_location'] = f'door_{door_number}'
trailer['dock_door'] = door_number
trailer['status'] = 'at_door'
trailer['door_arrival_time'] = datetime.now()
trailer['moves'] += 1
# Free old spot if in yard
if old_location in self.yard_spots:
self.yard_spots[old_location] = None
# Log move
self.move_history.append({
'trailer_id': trailer_id,
'timestamp': datetime.now(),
'action': 'spot_at_door',
'door': door_number,
'from': old_location
})
return {
'trailer_id': trailer_id,
'door': door_number,
'spotted_time': trailer['door_arrival_time']
}
def complete_door_activity(self, trailer_id):
"""
Complete loading/unloading at door
Move trailer back to yard or check out
"""
if trailer_id not in self.trailers:
return {'error': f'Trailer {trailer_id} not found'}
trailer = self.trailers[trailer_id]
if trailer['status'] != 'at_door':
return {'error': 'Trailer not at door'}
# Calculate door dwell time
door_dwell = (datetime.now() - trailer['door_arrival_time']).total_seconds() / 3600
trailer['status'] = 'completed'
trailer['door_departure_time'] = datetime.now()
trailer['door_dwell_hours'] = door_dwell
# Log
self.move_history.append({
'trailer_id': trailer_id,
'timestamp': datetime.now(),
'action': 'complete_door_activity',
'door_dwell_hours': door_dwell
})
# Check for excessive door time (>2 hours)
if door_dwell > 2:
self.alerts.append({
'alert_type': 'excessive_door_dwell',
'trailer_id': trailer_id,
'door_dwell_hours': door_dwell,
'timestamp': datetime.now()
})
return {
'trailer_id': trailer_id,
'door_dwell_hours': door_dwell,
'status': 'completed'
}
def check_out_trailer(self, trailer_id):
"""
Check out trailer from facility
Final step before trailer leaves
"""
if trailer_id not in self.trailers:
return {'error': f'Trailer {trailer_id} not found'}
trailer = self.trailers[trailer_id]
# Calculate total yard dwell
total_dwell = (datetime.now() - trailer['check_in_time']).total_seconds() / 3600
trailer['status'] = 'checked_out'
trailer['check_out_time'] = datetime.now()
trailer['total_yard_dwell_hours'] = total_dwell
# Log
self.move_history.append({
'trailer_id': trailer_id,
'timestamp': datetime.now(),
'action': 'check_out',
'total_dwell_hours': total_dwell
})
# Alert if excessive yard dwell (>24 hours)
if total_dwell > 24:
self.alerts.append({
'alert_type': 'excessive_yard_dwell',
'trailer_id': trailer_id,
'total_dwell_hours': total_dwell,
'timestamp': datetime.now()
})
return {
'trailer_id': trailer_id,
'total_yard_dwell_hours': total_dwell,
'total_moves': trailer['moves']
}
def get_yard_status(self):
"""
Get current yard status summary
Returns counts by status
"""
status_counts = {}
for trailer in self.trailers.values():
status = trailer['status']
status_counts[status] = status_counts.get(status, 0) + 1
total_trailers = len(self.trailers)
occupied_spots = sum(1 for spot in self.yard_spots.values()
if spot is not None)
return {
'total_trailers_in_yard': total_trailers,
'occupied_spots': occupied_spots,
'by_status': status_counts,
'active_alerts': len(self.alerts)
}
def find_trailer(self, trailer_id):
"""
Locate trailer in yard
Returns current location
"""
if trailer_id not in self.trailers:
return {'error': 'Trailer not found'}
trailer = self.trailers[trailer_id]
return {
'trailer_id': trailer_id,
'current_location': trailer['current_location'],
'status': trailer['status'],
'carrier': trailer['carrier'],
'dwell_time_hours': (datetime.now() - trailer['check_in_time']).total_seconds() / 3600
}
def calculate_performance_metrics(self):
"""
Calculate yard performance metrics
Returns KPIs
"""
if not self.trailers:
return {'message': 'No data available'}
# Average dwell time
dwell_times = []
for trailer in self.trailers.values():
if 'total_yard_dwell_hours' in trailer:
dwell_times.append(trailer['total_yard_dwell_hours'])
avg_dwell = np.mean(dwell_times) if dwell_times else 0
# Average moves per trailer
moves = [t['moves'] for t in self.trailers.values()]
avg_moves = np.mean(moves) if moves else 0
# Door dwell times
door_dwells = []
for trailer in self.trailers.values():
if 'door_dwell_hours' in trailer:
door_dwells.append(trailer['door_dwell_hours'])
avg_door_dwell = np.mean(door_dwells) if door_dwells else 0
return {
'avg_yard_dwell_hours': avg_dwell,
'avg_moves_per_trailer': avg_moves,
'avg_door_dwell_hours': avg_door_dwell,
'total_trailers': len(self.trailers),
'total_alerts': len(self.alerts),
'target_yard_dwell_hours': 24,
'target_door_dwell_hours': 2
}Example usage
Example usage
yms = YardManagementSystem()
yms = YardManagementSystem()
Check in trailer
Check in trailer
trailer = yms.check_in_trailer(
trailer_id='TRL12345',
carrier='ABC Trucking',
seal_number='SEAL987',
is_loaded=True
)
print(f"Trailer {trailer['trailer_id']} checked in at {trailer['check_in_time']}")
trailer = yms.check_in_trailer(
trailer_id='TRL12345',
carrier='ABC Trucking',
seal_number='SEAL987',
is_loaded=True
)
print(f"Trailer {trailer['trailer_id']} checked in at {trailer['check_in_time']}")
Assign to yard spot
Assign to yard spot
yms.assign_yard_spot('TRL12345', 'S045')
print("Trailer assigned to spot S045")
yms.assign_yard_spot('TRL12345', 'S045')
print("Trailer assigned to spot S045")
Spot at door
Spot at door
yms.spot_trailer_at_door('TRL12345', door_number=12)
print("Trailer spotted at door 12")
yms.spot_trailer_at_door('TRL12345', door_number=12)
print("Trailer spotted at door 12")
Get yard status
Get yard status
status = yms.get_yard_status()
print(f"\nYard Status: {status['total_trailers_in_yard']} trailers in yard")
---status = yms.get_yard_status()
print(f"\nYard Status: {status['total_trailers_in_yard']} trailers in yard")
---Yard Jockey Optimization
Yard Jockey优化
Jockey Dispatch & Task Management
Jockey调度与任务管理
python
class YardJockeyDispatcher:
"""
Optimize yard jockey task assignment
Minimize moves and maximize productivity
"""
def __init__(self, num_jockeys, yard_layout):
self.num_jockeys = num_jockeys
self.yard_layout = yard_layout
self.jockeys = {
f'Jockey_{i+1}': {
'current_location': 'office',
'status': 'available',
'tasks_completed': 0,
'total_distance': 0
}
for i in range(num_jockeys)
}
self.task_queue = []
def add_move_task(self, trailer_id, from_location, to_location, priority='normal'):
"""
Add trailer move task to queue
Parameters:
- priority: 'urgent', 'normal', 'low'
"""
task = {
'task_id': f'TASK{len(self.task_queue)+1:04d}',
'trailer_id': trailer_id,
'from': from_location,
'to': to_location,
'priority': priority,
'status': 'queued',
'created_time': datetime.now()
}
self.task_queue.append(task)
# Sort by priority
priority_order = {'urgent': 0, 'normal': 1, 'low': 2}
self.task_queue.sort(
key=lambda x: priority_order.get(x['priority'], 1)
)
return task
def assign_next_task(self):
"""
Assign next task to available jockey
Uses nearest jockey to minimize deadhead
"""
# Find available jockey
available_jockeys = [
(jid, jinfo) for jid, jinfo in self.jockeys.items()
if jinfo['status'] == 'available'
]
if not available_jockeys or not self.task_queue:
return None
# Get next task
task = self.task_queue[0]
# Find nearest jockey
nearest_jockey = None
min_distance = float('inf')
for jockey_id, jockey_info in available_jockeys:
# Calculate distance from jockey to task start location
distance = self._calculate_distance(
jockey_info['current_location'],
task['from']
)
if distance < min_distance:
min_distance = distance
nearest_jockey = jockey_id
if nearest_jockey:
# Assign task
self.jockeys[nearest_jockey]['status'] = 'busy'
self.jockeys[nearest_jockey]['current_task'] = task['task_id']
task['status'] = 'in_progress'
task['assigned_jockey'] = nearest_jockey
task['start_time'] = datetime.now()
self.task_queue.pop(0)
return {
'task_id': task['task_id'],
'jockey': nearest_jockey,
'trailer': task['trailer_id'],
'move': f"{task['from']} -> {task['to']}"
}
return None
def complete_task(self, task_id):
"""
Mark task as completed
Update jockey status and location
"""
# Find task
for task in self.task_queue:
if task['task_id'] == task_id:
task['status'] = 'completed'
task['completion_time'] = datetime.now()
# Update jockey
jockey_id = task.get('assigned_jockey')
if jockey_id:
self.jockeys[jockey_id]['status'] = 'available'
self.jockeys[jockey_id]['current_location'] = task['to']
self.jockeys[jockey_id]['tasks_completed'] += 1
# Calculate distance
distance = self._calculate_distance(task['from'], task['to'])
self.jockeys[jockey_id]['total_distance'] += distance
return {
'task_id': task_id,
'jockey': jockey_id,
'status': 'completed'
}
return {'error': 'Task not found'}
def _calculate_distance(self, location1, location2):
"""Calculate distance between two locations (simplified)"""
# In practice, use actual yard coordinates
# Simplified: random distance 50-500 feet
return np.random.randint(50, 500)
def get_jockey_productivity(self):
"""
Calculate jockey productivity metrics
Returns moves per hour, utilization
"""
productivity = []
for jockey_id, jockey_info in self.jockeys.items():
productivity.append({
'jockey_id': jockey_id,
'tasks_completed': jockey_info['tasks_completed'],
'total_distance': jockey_info['total_distance'],
'current_status': jockey_info['status']
})
return pd.DataFrame(productivity)
def optimize_task_sequence(self, tasks):
"""
Optimize sequence of tasks to minimize total distance
Uses greedy nearest-neighbor approach
"""
if not tasks:
return []
optimized_sequence = []
remaining_tasks = tasks.copy()
current_location = 'office'
while remaining_tasks:
# Find nearest task
nearest_task = None
min_distance = float('inf')
for task in remaining_tasks:
distance = self._calculate_distance(
current_location,
task['from']
)
if distance < min_distance:
min_distance = distance
nearest_task = task
if nearest_task:
optimized_sequence.append(nearest_task)
remaining_tasks.remove(nearest_task)
current_location = nearest_task['to']
return optimized_sequencepython
class YardJockeyDispatcher:
"""
Optimize yard jockey task assignment
Minimize moves and maximize productivity
"""
def __init__(self, num_jockeys, yard_layout):
self.num_jockeys = num_jockeys
self.yard_layout = yard_layout
self.jockeys = {
f'Jockey_{i+1}': {
'current_location': 'office',
'status': 'available',
'tasks_completed': 0,
'total_distance': 0
}
for i in range(num_jockeys)
}
self.task_queue = []
def add_move_task(self, trailer_id, from_location, to_location, priority='normal'):
"""
Add trailer move task to queue
Parameters:
- priority: 'urgent', 'normal', 'low'
"""
task = {
'task_id': f'TASK{len(self.task_queue)+1:04d}',
'trailer_id': trailer_id,
'from': from_location,
'to': to_location,
'priority': priority,
'status': 'queued',
'created_time': datetime.now()
}
self.task_queue.append(task)
# Sort by priority
priority_order = {'urgent': 0, 'normal': 1, 'low': 2}
self.task_queue.sort(
key=lambda x: priority_order.get(x['priority'], 1)
)
return task
def assign_next_task(self):
"""
Assign next task to available jockey
Uses nearest jockey to minimize deadhead
"""
# Find available jockey
available_jockeys = [
(jid, jinfo) for jid, jinfo in self.jockeys.items()
if jinfo['status'] == 'available'
]
if not available_jockeys or not self.task_queue:
return None
# Get next task
task = self.task_queue[0]
# Find nearest jockey
nearest_jockey = None
min_distance = float('inf')
for jockey_id, jockey_info in available_jockeys:
# Calculate distance from jockey to task start location
distance = self._calculate_distance(
jockey_info['current_location'],
task['from']
)
if distance < min_distance:
min_distance = distance
nearest_jockey = jockey_id
if nearest_jockey:
# Assign task
self.jockeys[nearest_jockey]['status'] = 'busy'
self.jockeys[nearest_jockey]['current_task'] = task['task_id']
task['status'] = 'in_progress'
task['assigned_jockey'] = nearest_jockey
task['start_time'] = datetime.now()
self.task_queue.pop(0)
return {
'task_id': task['task_id'],
'jockey': nearest_jockey,
'trailer': task['trailer_id'],
'move': f"{task['from']} -> {task['to']}"
}
return None
def complete_task(self, task_id):
"""
Mark task as completed
Update jockey status and location
"""
# Find task
for task in self.task_queue:
if task['task_id'] == task_id:
task['status'] = 'completed'
task['completion_time'] = datetime.now()
# Update jockey
jockey_id = task.get('assigned_jockey')
if jockey_id:
self.jockeys[jockey_id]['status'] = 'available'
self.jockeys[jockey_id]['current_location'] = task['to']
self.jockeys[jockey_id]['tasks_completed'] += 1
# Calculate distance
distance = self._calculate_distance(task['from'], task['to'])
self.jockeys[jockey_id]['total_distance'] += distance
return {
'task_id': task_id,
'jockey': jockey_id,
'status': 'completed'
}
return {'error': 'Task not found'}
def _calculate_distance(self, location1, location2):
"""Calculate distance between two locations (simplified)"""
# In practice, use actual yard coordinates
# Simplified: random distance 50-500 feet
return np.random.randint(50, 500)
def get_jockey_productivity(self):
"""
Calculate jockey productivity metrics
Returns moves per hour, utilization
"""
productivity = []
for jockey_id, jockey_info in self.jockeys.items():
productivity.append({
'jockey_id': jockey_id,
'tasks_completed': jockey_info['tasks_completed'],
'total_distance': jockey_info['total_distance'],
'current_status': jockey_info['status']
})
return pd.DataFrame(productivity)
def optimize_task_sequence(self, tasks):
"""
Optimize sequence of tasks to minimize total distance
Uses greedy nearest-neighbor approach
"""
if not tasks:
return []
optimized_sequence = []
remaining_tasks = tasks.copy()
current_location = 'office'
while remaining_tasks:
# Find nearest task
nearest_task = None
min_distance = float('inf')
for task in remaining_tasks:
distance = self._calculate_distance(
current_location,
task['from']
)
if distance < min_distance:
min_distance = distance
nearest_task = task
if nearest_task:
optimized_sequence.append(nearest_task)
remaining_tasks.remove(nearest_task)
current_location = nearest_task['to']
return optimized_sequenceCommon Challenges & Solutions
常见挑战与解决方案
Challenge: Trailer Visibility
挑战:拖车可见性不足
Problem:
- Can't find trailers in yard
- Drivers search for 15-30 minutes
- Wasted time and frustration
Solutions:
- Implement YMS with GPS/RFID tracking
- Zone-based yard layout with clear signage
- Mobile app for drivers (trailer locator)
- Digital yard map with real-time updates
- Dedicated staging zones by status
- Color-coded yard spots
- Regular yard audits to verify locations
问题:
- 无法在堆场中找到拖车
- 司机需花费15-30分钟寻找
- 时间浪费与人员不满
解决方案:
- 部署带有GPS/RFID跟踪功能的YMS
- 采用分区堆场布局并设置清晰标识
- 为司机提供拖车定位移动应用
- 实时更新的数字化堆场地图
- 按状态划分专用 staging zones
- 泊位颜色编码
- 定期堆场审计以验证拖车位置
Challenge: High Detention Costs
挑战:高额滞留费用
Problem:
- Paying detention fees ($50-100/hour)
- Trailers sitting at doors too long
- Slow loading/unloading
Solutions:
- Set hard time limits for door dwell (<2 hours)
- Monitor and alert on approaching detention
- Pre-stage loads (ready before truck arrives)
- Live loading/unloading where possible
- Negotiate detention grace periods
- Optimize dock scheduling (avoid overbooking)
- Cross-training to flex labor to doors
- Automated alerts at 75% of free time
问题:
- 支付滞留费(每小时50-100美元)
- 拖车在码头门停留时间过长
- 装卸速度缓慢
解决方案:
- 设置码头门停留硬限制(<2小时)
- 监控并在接近滞留时限时发出警报
- 预装载货物(卡车到达前准备就绪)
- 尽可能采用实时装卸
- 协商滞留宽限期
- 优化码头调度(避免过度预订)
- 交叉培训员工以灵活支援码头作业
- 在免费时间达到75%时自动发出警报
Challenge: Yard Congestion
挑战:堆场拥堵
Problem:
- Too many trailers, not enough space
- Difficulty maneuvering jockeys
- Blocked access to trailers
Solutions:
- Implement drop trailer program (pre-loaded outbound)
- Dedicated empty trailer pool off-site
- Just-in-time arrival scheduling
- Turn away non-appointment arrivals
- Expand yard capacity or use overflow lot
- Improve trailer turn time (reduce dwell)
- Better appointment scheduling (smooth arrivals)
问题:
- 拖车过多,空间不足
- 堆场调度员难以操作
- 拖车通道被阻塞
解决方案:
- 实施drop trailer program(预装载 outbound拖车)
- 在场外设置专用空拖车池
- 准时到达调度
- 拒绝无预约到达的车辆
- 扩大堆场容量或使用溢出场地
- 缩短拖车周转时间(减少停留)
- 优化预约调度(平滑到达高峰)
Challenge: Long Wait Times at Gate
挑战:闸口等待时间过长
Problem:
- Trucks waiting 30-60 minutes at gate
- Manual check-in process slow
- Paperwork errors and delays
Solutions:
- Implement online pre-check-in portal
- Use kiosks for self-check-in
- Dedicated lanes for pre-registered drivers
- Automate BOL scanning and validation
- Pre-approve appointments (pre-verify credentials)
- Add gate capacity (more lanes)
- Mobile check-in before arrival
问题:
- 卡车在闸口等待30-60分钟
- 人工登记流程缓慢
- 文件错误与延误
解决方案:
- 实施在线预登记门户
- 使用自助登记 kiosks
- 为预注册司机设置专用通道
- 自动化BOL扫描与验证
- 预先批准预约(提前验证资质)
- 增加闸口容量(更多通道)
- 到达前移动登记
Challenge: Inefficient Jockey Utilization
挑战:Yard Jockey利用率低下
Problem:
- Jockeys idle or making unnecessary moves
- Long deadhead distances
- Poor task prioritization
Solutions:
- Implement jockey dispatch system
- Zone-based jockey assignments
- Real-time task queue with priorities
- Optimize task sequencing (minimize distance)
- Right-size jockey staffing
- Cross-train warehouse staff as backup
- Performance metrics and incentives
问题:
- Yard Jockey闲置或进行不必要的调度
- 空驶距离过长
- 任务优先级设置不合理
解决方案:
- 实施Jockey调度系统
- 分区分配Jockey任务
- 带优先级的实时任务队列
- 优化任务顺序(最小化距离)
- 合理配置Jockey人员数量
- 交叉培训仓库员工作为后备
- 绩效指标与激励机制
Challenge: Lack of Appointment Compliance
挑战:预约合规性差
Problem:
- Carriers show up without appointments
- Early or late arrivals disrupt schedule
- Overbooking of doors
Solutions:
- Require appointments (enforce policy)
- Charge premium for non-appointment arrivals
- Communicate appointment importance
- Partner with carriers on compliance
- Send appointment reminders (day before, morning of)
- Track and report carrier compliance
- Refuse service to repeat offenders
问题:
- 承运人无预约到场
- 早到或迟到打乱调度计划
- 码头门过度预订
解决方案:
- 强制要求预约(执行政策)
- 对无预约到达收取额外费用
- 沟通预约的重要性
- 与承运人合作提升合规性
- 发送预约提醒(前一天、当天早上)
- 跟踪并报告承运人合规情况
- 拒绝屡犯者服务
Yard Management Technology
堆场管理技术
Yard Management System (YMS) Selection
堆场管理系统(YMS)选型
Enterprise YMS Platforms:
- C3 Solutions: Industry leader
- Zebra (formerly Yard Management Solutions): RFID-based
- Manhattan Associates YMS: WMS-integrated
- Oracle Yard Management: Cloud-based
- Blue Yonder YMS: AI-powered
- 4Sight Yard Management: Mid-market
Key YMS Features:
- Real-time trailer tracking (GPS, RFID, manual)
- Gate check-in/check-out automation
- Dock appointment scheduling
- Jockey task management and dispatch
- Dwell time monitoring and alerts
- Reporting and analytics
- Integration with WMS and TMS
企业级YMS平台:
- C3 Solutions:行业领导者
- Zebra (formerly Yard Management Solutions):基于RFID的系统
- Manhattan Associates YMS:与WMS集成
- Oracle Yard Management:云平台
- Blue Yonder YMS:AI驱动
- 4Sight Yard Management:面向中端市场
YMS核心功能:
- 实时拖车跟踪(GPS、RFID、手动)
- 闸口登记/注销自动化
- 码头预约调度
- Jockey任务管理与调度
- 停留时间监控与警报
- 报告与分析
- 与WMS和TMS集成
Tracking Technologies
跟踪技术
RFID Tags:
- Passive tags on trailers
- Readers at gates and key points
- Automatic location updates
- Cost: $5-10 per tag, $1K-5K per reader
GPS Tracking:
- Active GPS devices on trailers
- Real-time location accuracy
- Higher cost, requires power
- Cost: $50-150 per device + monthly fees
Geofencing:
- Virtual boundaries in yard
- Trigger alerts when crossed
- Works with GPS or RFID
Barcode/QR Scanning:
- Low-tech, manual scanning
- Mobile app for jockeys
- Lower accuracy, requires compliance
RFID标签:
- 拖车搭载被动标签
- 闸口与关键位置部署阅读器
- 自动更新位置
- 成本:每个标签5-10美元,每个阅读器1000-5000美元
GPS跟踪:
- 拖车搭载主动GPS设备
- 实时位置精准
- 成本较高,需供电
- 成本:每个设备50-150美元 + 月服务费
地理围栏(Geofencing):
- 堆场虚拟边界
- 越界时触发警报
- 可与GPS或RFID配合使用
条码/QR码扫描:
- 低技术成本,手动扫描
- 为Jockey提供移动应用
- 准确性较低,需合规操作
Output Format
输出格式
Yard Management Analysis Report
堆场管理分析报告
Executive Summary:
- Average yard dwell time: 18.5 hours (target: <12 hours)
- Detention costs: $18,500/month (target: <$10,000)
- Door utilization: 62% (target: 75%)
- Yard capacity utilization: 85% (near capacity)
- Recommendation: Implement YMS, improve dock scheduling
Current State Metrics:
| Metric | Current | Target | Status |
|---|---|---|---|
| Avg yard dwell time | 18.5 hrs | <12 hrs | ⚠️ 54% over |
| Avg door dwell time | 2.8 hrs | <2 hrs | ⚠️ 40% over |
| Detention costs/month | $18.5K | <$10K | ⚠️ 85% over |
| Gate wait time | 22 min | <10 min | ⚠️ 120% over |
| Door utilization | 62% | 75% | ⚠️ Below target |
| Yard occupancy | 85% | 80% | ⚠️ Near capacity |
Detention Cost Analysis:
| Carrier | Monthly Charges | Incidents | Avg Duration | Root Cause |
|---|---|---|---|---|
| Carrier A | $6,200 | 42 | 3.2 hrs | Slow unloading |
| Carrier B | $4,800 | 35 | 2.9 hrs | Dock congestion |
| Carrier C | $3,500 | 28 | 2.6 hrs | Missing appointments |
| Others | $4,000 | 32 | 2.5 hrs | Various |
Yard Dwell Time by Status:
| Trailer Status | Count | Avg Dwell | Max Dwell | % Over 24 hrs |
|---|---|---|---|---|
| Inbound staged | 45 | 12.5 hrs | 38 hrs | 15% |
| At door (loading) | 18 | 2.8 hrs | 4.5 hrs | 0% |
| Outbound ready | 32 | 28.0 hrs | 72 hrs | 45% ⚠️ |
| Empty/Drop | 25 | 36.0 hrs | 120 hrs | 60% ⚠️ |
Root Cause: Outbound Delays
- Waiting for consolidation (3+ days)
- No carrier pickup scheduled
- Recommendation: Daily pickup schedule or use 3PL
Door Utilization by Day/Time:
| Time Slot | Mon | Tue | Wed | Thu | Fri | Avg |
|---|---|---|---|---|---|---|
| 6-9 AM | 85% | 82% | 88% | 90% | 85% | 86% |
| 9-12 PM | 75% | 70% 72% | 78% | 75% | 74% | |
| 12-3 PM | 55% | 52% | 58% | 60% | 55% | 56% ⚠️ |
| 3-6 PM | 48% | 45% | 50% | 52% | 48% | 49% ⚠️ |
Recommendation: Evening shift to utilize afternoons
Improvement Initiatives:
-
Implement YMS - Impact: -30% dwell time, -40% detention
- Real-time trailer tracking
- Automated door scheduling
- Jockey dispatch optimization
- Investment: $180K, ROI: 14 months
-
Optimize Dock Scheduling - Impact: +13% door utilization
- Implement appointment system
- Enforce appointment compliance
- Balance arrivals throughout day
- Investment: $25K (software)
-
Reduce Outbound Dwell - Impact: -50% yard congestion
- Daily carrier pickup schedule
- Pre-loaded outbound staging
- Drop trailer program
- Savings: $120K annually
-
Expand Gate Capacity - Impact: -60% wait time
- Add second gate lane
- Self-service kiosk check-in
- Pre-registration portal
- Investment: $75K
Expected Results (12 months):
| Metric | Current | Target | Improvement |
|---|---|---|---|
| Avg yard dwell | 18.5 hrs | 12 hrs | -35% |
| Detention costs | $18.5K/mo | $9K/mo | -51% |
| Door utilization | 62% | 75% | +13 pts |
| Gate wait time | 22 min | 8 min | -64% |
| Yard occupancy | 85% | 70% | -15 pts |
执行摘要:
- 平均堆场停留时间:18.5小时(目标:<12小时)
- 滞留成本:每月18,500美元(目标:<10,000美元)
- 码头门利用率:62%(目标:75%)
- 堆场容量利用率:85%(接近饱和)
- 建议:部署YMS,优化码头调度
当前状态指标:
| 指标 | 当前值 | 目标值 | 状态 |
|---|---|---|---|
| 平均堆场停留时间 | 18.5小时 | <12小时 | ⚠️ 超出54% |
| 平均码头门停留时间 | 2.8小时 | <2小时 | ⚠️ 超出40% |
| 月度滞留成本 | 18,500美元 | <10,000美元 | ⚠️ 超出85% |
| 闸口等待时间 | 22分钟 | <10分钟 | ⚠️ 超出120% |
| 码头门利用率 | 62% | 75% | ⚠️ 低于目标 |
| 堆场占用率 | 85% | 80% | ⚠️ 接近饱和 |
滞留成本分析:
| 承运人 | 月度费用 | 事件数 | 平均时长 | 根本原因 |
|---|---|---|---|---|
| Carrier A | 6,200美元 | 42 | 3.2小时 | 卸货缓慢 |
| Carrier B | 4,800美元 | 35 | 2.9小时 | 码头拥堵 |
| Carrier C | 3,500美元 | 28 | 2.6小时 | 未预约 |
| 其他 | 4,000美元 | 32 | 2.5小时 | 多种原因 |
按状态划分的堆场停留时间:
| 拖车状态 | 数量 | 平均停留时间 | 最长停留时间 | 停留超24小时占比 |
|---|---|---|---|---|
| 入港待处理 | 45 | 12.5小时 | 38小时 | 15% |
| 码头装卸中 | 18 | 2.8小时 | 4.5小时 | 0% |
| 出港就绪 | 32 | 28.0小时 | 72小时 | 45% ⚠️ |
| 空车/落放 | 25 | 36.0小时 | 120小时 | 60% ⚠️ |
根本原因:出港延误
- 等待合并(3天以上)
- 未安排承运人提货
- 建议:每日提货计划或使用第三方物流(3PL)
按日期/时段划分的码头门利用率:
| 时段 | 周一 | 周二 | 周三 | 周四 | 周五 | 平均值 |
|---|---|---|---|---|---|---|
| 6-9点 | 85% | 82% | 88% | 90% | 85% | 86% |
| 9-12点 | 75% | 70% | 72% | 78% | 75% | 74% |
| 12-15点 | 55% | 52% | 58% | 60% | 55% | 56% ⚠️ |
| 15-18点 | 48% | 45% | 50% | 52% | 48% | 49% ⚠️ |
建议:增设晚班以利用下午时段
改进举措:
-
部署YMS - 影响:停留时间减少30%,滞留成本降低40%
- 实时拖车跟踪
- 自动化码头调度
- Jockey调度优化
- 投资:180,000美元,投资回报周期:14个月
-
优化码头调度 - 影响:码头门利用率提升13%
- 实施预约系统
- 强制预约合规
- 平衡全天到达量
- 投资:25,000美元(软件)
-
减少出港停留时间 - 影响:堆场拥堵减少50%
- 每日承运人提货计划
- 预装载出港 staging
- drop trailer program
- 年节省:120,000美元
-
扩大闸口容量 - 影响:等待时间减少60%
- 增设第二条闸口通道
- 自助登记 kiosk
- 预注册门户
- 投资:75,000美元
预期结果(12个月后):
| 指标 | 当前值 | 目标值 | 改进幅度 |
|---|---|---|---|
| 平均堆场停留时间 | 18.5小时 | 12小时 | -35% |
| 滞留成本 | 18,500美元/月 | 9,000美元/月 | -51% |
| 码头门利用率 | 62% | 75% | +13个百分点 |
| 闸口等待时间 | 22分钟 | 8分钟 | -64% |
| 堆场占用率 | 85% | 70% | -15个百分点 |
Questions to Ask
需询问的问题
If you need more context:
- How many dock doors and yard spots?
- What's your daily trailer volume (in/out)?
- Do you have a YMS or tracking system?
- What's your average yard dwell time?
- Are you paying detention costs? How much?
- Any appointment scheduling system?
- How many yard jockeys/tractors?
- Main pain points? (visibility, congestion, detention, wait times)
如需更多背景信息,请询问:
- 码头门和堆场泊位数量是多少?
- 每日拖车进出量是多少?
- 是否已部署YMS或跟踪系统?
- 平均堆场停留时间是多少?
- 是否支付滞留费用?金额多少?
- 是否有预约调度系统?
- Yard Jockey/牵引车数量是多少?
- 主要痛点是什么?(可见性、拥堵、滞留、等待时间)
Related Skills
相关技能
- dock-door-assignment: Optimize dock door scheduling and assignment
- cross-docking: Cross-dock operations and flow-through
- warehouse-design: Facility layout and design
- route-optimization: Outbound routing and delivery
- freight-optimization: Carrier management and transportation
- supply-chain-automation: Automation and technology selection
- process-optimization: Operational process improvement
- maintenance-planning: Equipment and yard tractor maintenance
- dock-door-assignment:优化码头门调度与分配
- cross-docking:交叉码头作业与流转
- warehouse-design:设施布局与设计
- route-optimization:出港路线与配送优化
- freight-optimization:承运人管理与运输优化
- supply-chain-automation:自动化与技术选型
- process-optimization:运营流程改进
- maintenance-planning:设备与堆场牵引车维护