Skip to content

Commit

Permalink
core: add requirement margin for stop on closed signal
Browse files Browse the repository at this point in the history
20 s anticipation for the start of resource requirement when stopping on
closed signal.
  • Loading branch information
bougue-pe committed Oct 4, 2024
1 parent 5a6ae29 commit 5db36e8
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import fr.sncf.osrd.signaling.SignalingSimulator
import fr.sncf.osrd.signaling.SignalingTrainState
import fr.sncf.osrd.signaling.ZoneStatus
import fr.sncf.osrd.sim_infra.api.*
import fr.sncf.osrd.standalone_sim.CLOSED_SIGNAL_RESERVATION_MARGIN
import fr.sncf.osrd.standalone_sim.result.ResultTrain.SpacingRequirement
import fr.sncf.osrd.utils.indexing.mutableStaticIdxArrayListOf
import fr.sncf.osrd.utils.units.Offset
Expand Down Expand Up @@ -432,7 +433,7 @@ class SpacingRequirementAutomaton(
if (stopEndTime.isInfinite()) {
return null
}
beginTime = maxOf(beginTime, stopEndTime)
beginTime = maxOf(beginTime, stopEndTime - CLOSED_SIGNAL_RESERVATION_MARGIN)
}

val departureTime = callbacks.departureTimeFromRange(zoneEntryOffset, zoneExitOffset)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import mu.KotlinLogging

private val logger = KotlinLogging.logger {}

const val CLOSED_SIGNAL_RESERVATION_MARGIN = 20.0

// the start offset is the distance from the start of the first block to the start location
class PathOffsetBuilder(val startOffset: Distance) {
fun toTravelledPath(offset: Offset<Path>): Offset<TravelledPath> {
Expand Down Expand Up @@ -371,6 +373,7 @@ fun routingRequirements(

// find the location at which establishing the route becomes necessary
var criticalPos = blockOffset + limitingSignalOffset - sightDistance
var reservationMargin = 0.0

// check if an arrival on stop signal is scheduled between the critical position and the
// entry signal of the route
Expand All @@ -386,16 +389,20 @@ fun routingRequirements(
) {
// stop duration is included in interpolateDepartureFromClamp()
criticalPos = stopTravelledOffset
reservationMargin = CLOSED_SIGNAL_RESERVATION_MARGIN
break
}
if (stopTravelledOffset < criticalPos) {
break
}
}

// find last time when the train is at the critical location (including stop duration if at
// stop)
return envelope.interpolateDepartureFromClamp(criticalPos.distance.meters)
// find last time when the train is at the critical location (adding stop duration and
// removing anticipation margin if at stop)
return maxOf(
envelope.interpolateDepartureFromClamp(criticalPos.distance.meters) - reservationMargin,
0.0
)
}

val res = mutableListOf<RoutingRequirement>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,86 @@ public void conflictDetectionForOvertakeInStation(
assertFalse(conflicts.stream().anyMatch(conflict -> !conflict.workScheduleIds.isEmpty()));
}

@ParameterizedTest
@CsvSource({
"OPEN, 213.458699", // first sight of the limiting signal for switch's zone
"STOP, 812.429826", // 20 s before the departure from the 10-min stop at Mid_West_station
"SHORT_SLIP_STOP, 812.429826",
})
public void resourceReservation(RJSReceptionSignal receptionSignal, double switchReqBegin) throws Exception {
var rjsInfra = Helpers.getExampleInfra("small_infra/infra.json");
var fullInfra = fullInfraFromRJS(rjsInfra);
var rawInfra = fullInfra.rawInfra();

var ta6 = getTrackSectionFromNameOrThrow("TA6", rawInfra);
var td0 = getTrackSectionFromNameOrThrow("TD0", rawInfra);

var chunkPathCenter = chunkPathFromRoutes(
rawInfra,
List.of("rt.DA0->DA5", "rt.DA5->DC5", "rt.DC5->DD2"),
makeTrackLocation(ta6, fromMeters(1000)), // start after DA3
makeTrackLocation(td0, fromMeters(24820)));
var pathPropsCenter = makePathProperties(rawInfra, chunkPathCenter, null);
var chunkPathNorth = chunkPathFromRoutes(
rawInfra,
List.of("rt.DA0->DA5", "rt.DA5->DC4", "rt.DC4->DD2"),
makeTrackLocation(ta6, fromMeters(1000)),
makeTrackLocation(td0, fromMeters(24820)));
var pathPropsNorth = makePathProperties(rawInfra, chunkPathNorth, null);

var stop = new TrainStop(9700, 600, receptionSignal);
var simResultCenterWithStop =
simpleSim(fullInfra, pathPropsCenter, chunkPathCenter, 0, Double.POSITIVE_INFINITY, List.of(stop));
var simResultNorthOvertaking =
simpleSim(fullInfra, pathPropsNorth, chunkPathNorth, 0, Double.POSITIVE_INFINITY, List.of());

var reqWithStop = convertRequirements(0L, 0.0, simResultCenterWithStop.train);
var directStartTime = 300; // 5 min after stopping train
var reqOvertaking = convertRequirements(1L, directStartTime, simResultNorthOvertaking.train);

// check spacing and routing requirements for the zone of the switch after (East) Mid_West_station
var switchZoneName = "zone.[DC4:INCREASING, DC5:INCREASING, DD0:DECREASING]";

// requirements for train with stop
var switchZoneExitTime = 844.837492;
var switchSpacingReqWithStop = reqWithStop.getSpacingRequirements().stream()
.filter(it -> it.zone.equals(switchZoneName))
.findFirst()
.get();
assertEquals(switchReqBegin, switchSpacingReqWithStop.beginTime);
assertEquals(switchZoneExitTime, switchSpacingReqWithStop.endTime);
var switchRouteReqWithStop = reqWithStop.getRoutingRequirements().stream()
.filter(it -> it.route.equals("rt.DC5->DD2"))
.findFirst()
.get();
var switchRouteCrossingZoneReqWithStop = switchRouteReqWithStop.zones.stream()
.filter(it -> it.zone.equals(switchZoneName))
.findFirst()
.get();
assertEquals(switchReqBegin, switchRouteReqWithStop.beginTime);
assertEquals(switchZoneExitTime, switchRouteCrossingZoneReqWithStop.endTime);

// requirements for overtaking train (no stop)
var overtakingSwitchZoneExitTime = 545.533259;
var overtakingSwitchLimitingSignalSight = 513.458699;
var overtakingSwitchSpacingReqWithStop = reqOvertaking.getSpacingRequirements().stream()
.filter(it -> it.zone.equals(switchZoneName))
.findFirst()
.get();
assertEquals(overtakingSwitchLimitingSignalSight, overtakingSwitchSpacingReqWithStop.beginTime);
assertEquals(overtakingSwitchZoneExitTime, overtakingSwitchSpacingReqWithStop.endTime);
var overtakingSwitchRouteReqWithStop = reqOvertaking.getRoutingRequirements().stream()
.filter(it -> it.route.equals("rt.DC4->DD2"))
.findFirst()
.get();
var overtakingSwitchRouteCrossingZoneReqWithStop = overtakingSwitchRouteReqWithStop.zones.stream()
.filter(it -> it.zone.equals(switchZoneName))
.findFirst()
.get();
assertEquals(overtakingSwitchLimitingSignalSight, overtakingSwitchRouteReqWithStop.beginTime);
assertEquals(overtakingSwitchZoneExitTime, overtakingSwitchRouteCrossingZoneReqWithStop.endTime);
}

@ParameterizedTest
@MethodSource("workScheduleArgs")
public void testWorkSchedules(
Expand Down

0 comments on commit 5db36e8

Please sign in to comment.