From 5263c459af79f899d03bacbd08473799a6a3ebcf Mon Sep 17 00:00:00 2001 From: Eloi Charpentier Date: Mon, 30 Oct 2023 14:39:08 +0100 Subject: [PATCH] core: pathfinding: filter out routes without blocks --- .../PathfindingResultConverter.java | 37 +++++++++++++++---- .../ScheduleMetadataExtractor.kt | 2 +- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fr/sncf/osrd/api/pathfinding/PathfindingResultConverter.java b/core/src/main/java/fr/sncf/osrd/api/pathfinding/PathfindingResultConverter.java index 71d211e0a84..76215ffdade 100644 --- a/core/src/main/java/fr/sncf/osrd/api/pathfinding/PathfindingResultConverter.java +++ b/core/src/main/java/fr/sncf/osrd/api/pathfinding/PathfindingResultConverter.java @@ -2,6 +2,7 @@ import static fr.sncf.osrd.railjson.schema.common.graph.EdgeDirection.START_TO_STOP; import static fr.sncf.osrd.railjson.schema.common.graph.EdgeDirection.STOP_TO_START; +import static fr.sncf.osrd.sim_infra.utils.BlockRecoveryKt.recoverBlocks; import static fr.sncf.osrd.utils.KtToJavaConverter.toIntList; import static fr.sncf.osrd.utils.indexing.DirStaticIdxKt.toDirection; import static fr.sncf.osrd.utils.indexing.DirStaticIdxKt.toValue; @@ -17,13 +18,11 @@ import fr.sncf.osrd.railjson.schema.infra.RJSRoutePath; import fr.sncf.osrd.railjson.schema.infra.trackranges.RJSDirectionalTrackRange; import fr.sncf.osrd.reporting.warnings.DiagnosticRecorderImpl; -import fr.sncf.osrd.sim_infra.api.BlockInfra; -import fr.sncf.osrd.sim_infra.api.PathProperties; -import fr.sncf.osrd.sim_infra.api.RawSignalingInfra; -import fr.sncf.osrd.sim_infra.api.RawSignalingInfraKt; +import fr.sncf.osrd.sim_infra.api.*; import fr.sncf.osrd.utils.Direction; import fr.sncf.osrd.utils.DistanceRangeMap; import fr.sncf.osrd.utils.graph.Pathfinding; +import fr.sncf.osrd.utils.indexing.MutableStaticIdxArrayList; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; @@ -193,7 +192,7 @@ static List makeRoutePath( .map(Pathfinding.EdgeRange::edge) .toList(); var chunkPath = chunksOnBlocks(blockInfra, blocks); - var routes = chunksToRoutes(rawInfra, chunkPath); + var routes = chunksToRoutes(rawInfra, blockInfra, chunkPath); var startOffset = findStartOffset(blockInfra, rawInfra, chunkPath.get(0), routes.get(0), ranges.get(0)); var endOffset = findEndOffset(blockInfra, rawInfra, Iterables.getLast(chunkPath), Iterables.getLast(routes), Iterables.getLast(ranges)); @@ -347,12 +346,13 @@ private static List chunksOnBlocks(BlockInfra blockInfra, List /** Converts a list of dir chunks into a list of routes */ public static List chunksToRoutes( RawSignalingInfra infra, + BlockInfra blockInfra, List pathChunks ) { var chunkStartIndex = 0; var res = new ArrayList(); while (chunkStartIndex < pathChunks.size()) { - var route = findRoute(infra, pathChunks, chunkStartIndex, chunkStartIndex != 0); + var route = findRoute(infra, blockInfra, pathChunks, chunkStartIndex, chunkStartIndex != 0); res.add(route); var chunkSetOnRoute = new HashSet<>(toIntList(infra.getChunksOnRoute(route))); while (chunkStartIndex < pathChunks.size() && chunkSetOnRoute.contains(pathChunks.get(chunkStartIndex))) @@ -364,6 +364,7 @@ public static List chunksToRoutes( /** Finds a valid route that follows the given path */ private static int findRoute( RawSignalingInfra infra, + BlockInfra blockInfra, List chunks, int startIndex, boolean routeMustIncludeStart @@ -374,7 +375,7 @@ private static int findRoute( routes.sort(Comparator.comparingInt(r -> -infra.getChunksOnRoute(r).getSize())); for (var routeId : routes) - if (routeMatchPath(infra, chunks, startIndex, routeMustIncludeStart, routeId)) + if (routeMatchPath(infra, blockInfra, chunks, startIndex, routeMustIncludeStart, routeId)) return routeId; throw new RuntimeException("Couldn't find a route matching the given chunk list"); } @@ -382,11 +383,14 @@ private static int findRoute( /** Returns false if the route differs from the path */ private static boolean routeMatchPath( RawSignalingInfra infra, + BlockInfra blockInfra, List chunks, int chunkIndex, boolean routeMustIncludeStart, int routeId ) { + if (!routeHasBlockPath(infra, blockInfra, routeId)) + return false; // Filter out routes that don't have block, they would cause issues later on var firstChunk = chunks.get(chunkIndex); var routeChunks = infra.getChunksOnRoute(routeId); var routeChunkIndex = 0; @@ -408,4 +412,23 @@ private static boolean routeMatchPath( chunkIndex++; } } + + /** Returns true if the route contains a valid block path. + *

+ * This should always be true, but it can be false on infrastructures with errors in its signaling data + * (such as the ones imported from poor data sources). + * At this step we know that there is at least one route with a valid block path, + * we just need to filter out the ones that don't. */ + private static boolean routeHasBlockPath( + RawSignalingInfra infra, + BlockInfra blockInfra, + int routeId + ) { + var routeIds = new MutableStaticIdxArrayList(); + routeIds.add(routeId); + var blockPaths = recoverBlocks( + infra, blockInfra, routeIds, null + ); + return !blockPaths.isEmpty(); + } } diff --git a/core/src/main/java/fr/sncf/osrd/standalone_sim/ScheduleMetadataExtractor.kt b/core/src/main/java/fr/sncf/osrd/standalone_sim/ScheduleMetadataExtractor.kt index b061024b47e..196831a6e08 100644 --- a/core/src/main/java/fr/sncf/osrd/standalone_sim/ScheduleMetadataExtractor.kt +++ b/core/src/main/java/fr/sncf/osrd/standalone_sim/ScheduleMetadataExtractor.kt @@ -78,7 +78,7 @@ fun run(envelope: Envelope, trainPath: PathProperties, chunkPath: ChunkPath, sch val simulator = fullInfra.signalingSimulator // get a new generation route path - val routePath = toRouteIdList(chunksToRoutes(rawInfra, toIntList(chunkPath.chunks))) + val routePath = toRouteIdList(chunksToRoutes(rawInfra, fullInfra.blockInfra, toIntList(chunkPath.chunks))) // recover blocks from the route paths val detailedBlockPath = recoverBlockPath(simulator, fullInfra, routePath)