fix(javaTest): validate route quality inputs

This commit is contained in:
zgw
2026-08-06 19:54:33 +08:00
parent 1dac889734
commit 1cd9a7c1c0
4 changed files with 61 additions and 12 deletions

View File

@@ -9,6 +9,7 @@ import java.util.List;
/** 使用同一个实时交通快照为有界候选排序并选择业务质量最优路线。 */
public final class RouteQualityEvaluator {
private static final double DISTANCE_EPSILON = 0.000001d;
/**
* 评价全部候选并按固定质量元组选择第一名。
@@ -54,6 +55,7 @@ public final class RouteQualityEvaluator {
throw new IllegalArgumentException("map, candidate, snapshot and owners are required");
}
List<String> path = candidate.getPath();
validateCandidatePath(map, candidate);
int opposite = 0;
int occupied = 0;
int incompatible = 0;
@@ -64,8 +66,8 @@ public final class RouteQualityEvaluator {
String from = path.get(index - 1);
String to = path.get(index);
if (snapshot.isOccupiedByOther(to, vehicleId)) occupied++;
boolean oppositeOnEdge = snapshot.hasOppositeDirectionOwnedByOther(
from, to, taskId);
boolean oppositeOnEdge = snapshot.hasOppositeDirectionOwnedByOther(from, to, taskId)
|| snapshot.hasOppositeActiveRoute(from, to, taskId);
if (oppositeOnEdge) opposite++;
// 同一物理边已计为对向风险时不在“不兼容边预约”中重复处罚。
if (!oppositeOnEdge
@@ -79,6 +81,17 @@ public final class RouteQualityEvaluator {
countTurns(map, path), candidate.getPhysicalDistance(), path);
}
/**
* 在公开评价入口重新确认候选仍然属于权威地图,防止调用方绕过候选规划器注入非法路径。
*/
private void validateCandidatePath(GridMap map, RouteCandidate candidate) {
double actualDistance = new RouteCandidatePlanner().pathDistance(map, candidate.getPath());
if (Math.abs(actualDistance - candidate.getPhysicalDistance()) > DISTANCE_EPSILON) {
throw new IllegalArgumentException("candidate distance does not match map path: "
+ candidate.getPhysicalDistance() + " != " + actualDistance);
}
}
/** 计算连续边方向向量改变次数;同一直线上的不同边长不算转弯。 */
private int countTurns(GridMap map, List<String> path) {
int turns = 0;

View File

@@ -56,6 +56,23 @@ public final class TrafficRouteSnapshot {
return containsOther(directedReservations.get(directedEdge(to, from)), taskId);
}
/**
* 判断候选边是否与其他活动任务的剩余路线反向重叠;活动路线还未走完,因此也属于对向风险。
*/
boolean hasOppositeActiveRoute(String from, String to, String taskId) {
for (Map.Entry<String, List<String>> entry : activeRoutes.entrySet()) {
if (entry.getKey().equals(taskId)) continue;
List<String> route = entry.getValue();
for (int index = 1; index < route.size(); index++) {
if (directedEdge(from, to).equals(
directedEdge(route.get(index), route.get(index - 1)))) {
return true;
}
}
}
return false;
}
/** 判断候选物理边是否与其他活动任务尚未执行的路线重合。 */
boolean overlapsOtherActiveRoute(String from, String to, String taskId) {
String edge = canonicalEdge(from, to);