package com.zy.asrs.utils;
|
|
import java.util.*;
|
import java.util.concurrent.atomic.AtomicReference;
|
|
import lombok.Data;
|
|
public class SchedulingCarUtil {
|
|
private static final Map<Integer, Double> STATION_PRIORITIES =
|
Collections.unmodifiableMap(new HashMap<Integer, Double>() {{
|
put(5101, 0.8);
|
put(5120, 0.9);
|
// ...
|
}});
|
private static final Map<String, Double> AREA_WEIGHTS =
|
Collections.unmodifiableMap(new HashMap<String, Double>() {{
|
put("A", 1.2);
|
put("B", 1.0);
|
put("C", 0.8);
|
// ...
|
}});
|
|
// 常量配置
|
private static final double WAIT_THRESHOLD = 120.0; // 等待临界点(秒)
|
private static final double MAX_DISTANCE = 1000.0; // 轨道最大长度
|
private static final double DIST_PENALTY = -0.5; // 最低距离系数
|
|
// 新增线性增长阈值和系数
|
private static final double LINEAR_THRESHOLD = 300.0; // 线性增长起点(秒)
|
private static final double LINEAR_FACTOR = 0.0083; // 线性增长系数(≈0.5/60)
|
|
private static final double LOAD_THRESHOLD = 0.7;
|
private static final double ADJUSTMENT_STEP = 0.01;
|
|
// 权重参数 (可动态调整)
|
private double baseWeight = 0.40;
|
private double waitWeight = 0.35;
|
private double distWeight = 0.25;
|
|
private static final double[] EXP_CACHE = new double[1800]; // 缓存0~1800秒(30分钟)
|
static {
|
for (int i = 0; i < EXP_CACHE.length; i++) {
|
EXP_CACHE[i] = 0.8 * (1 - Math.exp(-0.02 * i));
|
}
|
}
|
|
// 预计算常量
|
private static final double EXP_BASE = 0.5;
|
private static final double EXP_FACTOR = 3.0;
|
|
private static class Weights {
|
double base = 0.40, wait = 0.35, dist = 0.25;
|
}
|
private final AtomicReference<Weights> weightsRef = new AtomicReference<>(new Weights());
|
|
// // 复用对象(线程安全)
|
// private final ThreadLocal<Double> distanceCache = ThreadLocal.withInitial(() -> 0.0);
|
/**
|
* 计算任务综合优先级
|
* @param task 当前任务对象
|
* @param agv 当前小车对象
|
* @return 综合优先级得分(0.0 - 1.0 ~ ∞)
|
*/
|
public double calculatePriority(Task task, AGV agv) {
|
// 1. 站点基础优先级计算
|
double stationPriority = calculateStationPriority(task.getStationId());
|
|
// 2. 任务等待时间优先级
|
double waitPriority = calculateWaitPriority(task.getWaitSeconds());
|
|
// 3. 小车距离优先级
|
double distancePriority = calculateDistancePriority(
|
agv.getPosition(),
|
task.getTargetPosition()
|
);
|
|
applyDynamicWeightAdjustment();
|
|
return (stationPriority * baseWeight)
|
+ (waitPriority * waitWeight)
|
+ (distancePriority * distWeight);
|
}
|
|
private void applyDynamicWeightAdjustment() {
|
Weights current = weightsRef.get();
|
Weights updated = new Weights();
|
|
double loadFactor = SystemMonitor.getLoadFactor();
|
if (loadFactor > LOAD_THRESHOLD) {
|
waitWeight = Math.min(0.55, waitWeight + ADJUSTMENT_STEP);
|
distWeight = Math.max(0.10, distWeight - ADJUSTMENT_STEP/2);
|
} else if (loadFactor < LOAD_THRESHOLD - 0.05) {
|
// 负载降低时逐步恢复权重
|
waitWeight = Math.max(0.35, waitWeight - ADJUSTMENT_STEP);
|
distWeight = Math.min(0.25, distWeight + ADJUSTMENT_STEP/2);
|
}
|
|
weightsRef.compareAndSet(current, updated); // CAS更新
|
}
|
|
/**
|
* 站点基础优先级(固定值+区域权重)
|
*/
|
private double calculateStationPriority(int stationId) {
|
double basePriority = STATION_PRIORITIES.getOrDefault(stationId, 0.5);
|
String area = "A";
|
return basePriority * AREA_WEIGHTS.getOrDefault(area, 1.0);
|
}
|
|
/**
|
* 等待时间优先级(非线性增长)
|
*/
|
private double calculateWaitPriority(double waitSeconds) {
|
// if (waitSeconds <= WAIT_THRESHOLD) {
|
// return 0.2; // 基础值
|
// }
|
// // 等待超时后的指数增长(无峰值上限)
|
// return Math.min(1.0, 0.2 + 0.8 * (1 - Math.exp(-0.02*(waitSeconds-WAIT_THRESHOLD))));
|
|
if (waitSeconds <= WAIT_THRESHOLD) {
|
return 0.2; // 基础值
|
}
|
|
double exceedSeconds = waitSeconds - WAIT_THRESHOLD;
|
double expPart = (exceedSeconds < EXP_CACHE.length) ?
|
EXP_CACHE[(int) exceedSeconds] :
|
0.8 * (1 - Math.exp(-0.02 * exceedSeconds));
|
|
// double exceedSeconds = waitSeconds - WAIT_THRESHOLD;
|
// // 指数增长阶段(0~300秒)
|
// double expPart = 0.8 * (1 - Math.exp(-0.02 * exceedSeconds));
|
|
// 线性增长阶段(300秒后)
|
double linearPart = (exceedSeconds > LINEAR_THRESHOLD) ?
|
LINEAR_FACTOR * (exceedSeconds - LINEAR_THRESHOLD) : 0;
|
|
return 0.2 + expPart + linearPart; // 突破1.0上限
|
}
|
|
/**
|
* 小车距离优先级(含负向调节)
|
*/
|
private double calculateDistancePriority(double agvPos, double stationPos) {
|
// 计算轨道有效距离(考虑单向移动)
|
double distance = calculateEffectiveDistance(agvPos, stationPos);
|
//
|
// double distance = distanceCache.get();
|
// if (distance == 0.0) { // 0表示未计算
|
// distance = calculateEffectiveDistance(agvPos, stationPos);
|
// distanceCache.set(distance);
|
// }
|
|
// 非线性衰减公式(近距离奖励,远距离惩罚)
|
double ratio = distance / MAX_DISTANCE;
|
// return Math.max(DIST_PENALTY, 0.5 * (Math.pow(0.5, ratio * 3) - 0.5));
|
double exponentValue = Math.pow(EXP_BASE, ratio * EXP_FACTOR);
|
return Math.max(DIST_PENALTY, 0.5 * (exponentValue - 0.5));
|
}
|
|
/**
|
* 计算有效距离(单方向轨道逻辑)
|
*/
|
private double calculateEffectiveDistance(double agvPos, double stationPos) {
|
// 单向轨道场景:若小车已过站点,需绕行至终点再返回起点
|
// if (agvPos > stationPos) {
|
// return (MAX_DISTANCE - agvPos) + stationPos;
|
// }
|
// return stationPos - agvPos;
|
return (stationPos - agvPos + MAX_DISTANCE) % MAX_DISTANCE;
|
}
|
}
|
|
@Data
|
class Task {
|
private int taskId;
|
private int stationId;
|
private double targetPosition;
|
private long createTime; // 任务创建时间戳
|
private static final long THIRTY_DAYS_MS = 30L * 24 * 60 * 60 * 1000;
|
|
public double getWaitSeconds() {
|
long elapsed = (System.currentTimeMillis() - createTime) ;
|
// 固定为30天
|
return (elapsed > THIRTY_DAYS_MS) ? (THIRTY_DAYS_MS / 1000.0) : (elapsed / 1000.0);
|
}
|
}
|
|
@Data
|
class AGV {
|
private int agvId;
|
private double position; // 当前轨道位置(0-MAX_DISTANCE)
|
}
|
|
// 系统监控类(示例)
|
@Data
|
class SystemMonitor {
|
public static double getLoadFactor() {
|
// 实际实现中读取系统负载率
|
return 0.1;
|
// return LoadHolder.cachedLoad; // 定时更新,非实时读取
|
}
|
// private static class LoadHolder {
|
// static double cachedLoad = 0.1;
|
// static { ScheduledExecutorService.scheduleAtFixedRate(() ->
|
// cachedLoad = realTimeLoad(), 5, 5, TimeUnit.SECONDS); }
|
// }
|
}
|