Skip to content

Commit 0c56364

Browse files
committed
core: paths: migrate most endpoints to new path model
Some parts are too large and haven't been included, such as ScheduleMetadataExtractor. Signed-off-by: Eloi Charpentier <[email protected]>
1 parent 6769f32 commit 0c56364

File tree

9 files changed

+159
-228
lines changed

9 files changed

+159
-228
lines changed

core/src/main/kotlin/fr/sncf/osrd/api/etcs/ETCSBrakingCurvesEndpoint.kt

Lines changed: 10 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,10 @@ import fr.sncf.osrd.envelope.part.EnvelopePart
77
import fr.sncf.osrd.envelope_sim.EnvelopeProfile
88
import fr.sncf.osrd.envelope_sim.EnvelopeSimContext
99
import fr.sncf.osrd.envelope_sim.etcs.*
10-
import fr.sncf.osrd.path.interfaces.BlockPath
10+
import fr.sncf.osrd.path.interfaces.TrainPath
1111
import fr.sncf.osrd.path.interfaces.TravelledPath
12-
import fr.sncf.osrd.path.interfaces.getLegacyBlockPath
13-
import fr.sncf.osrd.path.interfaces.getLegacyChunkPath
14-
import fr.sncf.osrd.path.interfaces.getLegacyRoutePath
1512
import fr.sncf.osrd.signaling.etcs_level2.ETCS_LEVEL2
1613
import fr.sncf.osrd.sim_infra.api.*
17-
import fr.sncf.osrd.standalone_sim.PathOffsetBuilder
1814
import fr.sncf.osrd.standalone_sim.buildSignalingRanges
1915
import fr.sncf.osrd.standalone_sim.getSimStops
2016
import fr.sncf.osrd.standalone_sim.makeETCSContext
@@ -66,9 +62,6 @@ class ETCSBrakingCurvesEndpoint(
6662
// Parse path.
6763
val trainPath =
6864
request.path.toTrainPath(infra.rawInfra, infra.blockInfra, electricalProfileMap)
69-
val chunkPath = trainPath.getLegacyChunkPath()
70-
val routePath = trainPath.getLegacyRoutePath()
71-
val blockPath = trainPath.getLegacyBlockPath()
7265
val powerRestrictionsLegacyMap =
7366
parsePowerRestrictions(request.powerRestrictions).toRangeMap()
7467
val electrificationMap =
@@ -80,22 +73,15 @@ class ETCSBrakingCurvesEndpoint(
8073
)
8174
val curvesAndConditions =
8275
rollingStock.mapTractiveEffortCurves(electrificationMap, request.comfort)
83-
val signalingRanges = buildSignalingRanges(infra, blockPath, chunkPath)
76+
val signalingRanges = buildSignalingRanges(infra, trainPath)
8477
val stops = getSimStops(parseRawSimulationScheduleItems(request.schedule))
8578
val context =
8679
EnvelopeSimContext(
8780
rollingStock,
8881
trainPath,
8982
2.0,
9083
curvesAndConditions.curves,
91-
makeETCSContext(
92-
rollingStock,
93-
infra,
94-
chunkPath,
95-
routePath,
96-
blockPath,
97-
signalingRanges,
98-
),
84+
makeETCSContext(rollingStock, infra, trainPath, signalingRanges),
9985
)
10086

10187
// Parse mrsp.
@@ -115,17 +101,11 @@ class ETCSBrakingCurvesEndpoint(
115101
EoaType.STOP,
116102
)
117103
val stopBrakingCurves = etcsSimulator.computeStopBrakingCurves(mrsp, etcsStops)
118-
// Compute conflict braking curves on each of the path's ETCS signals.
119-
val pathOffsetBuilder =
120-
PathOffsetBuilder(
121-
trainPathBlockOffset(infra.rawInfra, infra.blockInfra, blockPath, chunkPath)
122-
.distance
123-
)
124-
val etcsSignals =
125-
getTravelledPathSignals(infra, blockPath, pathOffsetBuilder, ETCS_LEVEL2.id)
104+
val etcsSignals = getTravelledPathSignals(infra, trainPath, ETCS_LEVEL2.id)
126105
val etcsSignalsOnPath =
127106
etcsSignals.filter {
128-
it.offset.distance > Distance.ZERO && it.offset.distance <= chunkPath.length
107+
it.offset.distance > Distance.ZERO &&
108+
it.offset.distance <= trainPath.getLength()
129109
}
130110
val etcsSignalOffsets = etcsSignalsOnPath.map { it.offset }
131111
val areEtcsSignalRouteDelimiters = etcsSignalsOnPath.map { it.isRouteDelimiter }
@@ -175,26 +155,23 @@ class ETCSBrakingCurvesEndpoint(
175155
*/
176156
private fun getTravelledPathSignals(
177157
fullInfra: FullInfra,
178-
blockPath: List<BlockId>,
179-
pathOffsetBuilder: PathOffsetBuilder,
158+
trainPath: TrainPath,
180159
signalingSystemId: String? = null,
181160
): List<TravelledPathSignal> {
182161
val res = mutableSetOf<TravelledPathSignal>()
183-
var currentOffset = Offset<BlockPath>(Distance.ZERO)
184-
for (block in blockPath) {
162+
for (blockRange in trainPath.getBlocks()) {
163+
val block = blockRange.value
185164
val blockSignalsPositions = fullInfra.blockInfra.getSignalsPositions(block)
186165
val blockSignals = fullInfra.blockInfra.getBlockSignals(block)
187166
assert(blockSignalsPositions.size == blockSignals.size)
188167
for ((signalPosition, signal) in blockSignalsPositions zip blockSignals) {
189168
val signSystemId = fullInfra.rawInfra.getSignalingSystemId(signal)
190169
val isRouteDelimiter = fullInfra.loadedSignalInfra.getSettings(signal).getFlag("Nf")
191170
if (signalingSystemId == null || signSystemId == signalingSystemId) {
192-
val signalOffset =
193-
pathOffsetBuilder.toTravelledPath(currentOffset + signalPosition.distance)
171+
val signalOffset = blockRange.offsetToTrainPath(signalPosition)
194172
res.add(TravelledPathSignal(signalOffset, isRouteDelimiter))
195173
}
196174
}
197-
currentOffset += fullInfra.blockInfra.getBlockLength(block).distance
198175
}
199176
return res.sorted()
200177
}

core/src/main/kotlin/fr/sncf/osrd/api/standalone_sim/SimulationEndpoint.kt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package fr.sncf.osrd.api.standalone_sim
22

33
import fr.sncf.osrd.api.*
4-
import fr.sncf.osrd.path.interfaces.getLegacyBlockPath
5-
import fr.sncf.osrd.path.interfaces.getLegacyChunkPath
6-
import fr.sncf.osrd.path.interfaces.getLegacyRoutePath
74
import fr.sncf.osrd.reporting.exceptions.OSRDError
85
import fr.sncf.osrd.standalone_sim.runStandaloneSimulation
96
import fr.sncf.osrd.utils.*
@@ -59,17 +56,11 @@ class SimulationEndpoint(
5956
// Parse path
6057
val trainPath =
6158
request.path.toTrainPath(infra.rawInfra, infra.blockInfra, electricalProfileMap)
62-
val chunkPath = trainPath.getLegacyChunkPath()
63-
val routePath = trainPath.getLegacyRoutePath()
64-
val blockPath = trainPath.getLegacyBlockPath()
6559

6660
val res =
6761
runStandaloneSimulation(
6862
infra,
6963
trainPath,
70-
chunkPath,
71-
routePath,
72-
blockPath,
7364
rollingStock,
7465
request.comfort,
7566
request.constraintDistribution.toRJS(),

core/src/main/kotlin/fr/sncf/osrd/standalone_sim/SafetySpeed.kt

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,12 @@ package fr.sncf.osrd.standalone_sim
22

33
import fr.sncf.osrd.api.FullInfra
44
import fr.sncf.osrd.api.standalone_sim.SimulationScheduleItem
5-
import fr.sncf.osrd.path.implementations.ChunkPath
6-
import fr.sncf.osrd.path.interfaces.BlockPath
7-
import fr.sncf.osrd.path.interfaces.TravelledPath
5+
import fr.sncf.osrd.path.interfaces.TrainPath
86
import fr.sncf.osrd.railjson.schema.schedule.RJSTrainStop
97
import fr.sncf.osrd.signaling.etcs_level2.ETCS_LEVEL2
108
import fr.sncf.osrd.sim_infra.api.*
119
import fr.sncf.osrd.utils.DistanceRangeMap
1210
import fr.sncf.osrd.utils.distanceRangeMapOf
13-
import fr.sncf.osrd.utils.getRoutePathStartOffset
14-
import fr.sncf.osrd.utils.indexing.StaticIdx
1511
import fr.sncf.osrd.utils.units.Offset
1612
import fr.sncf.osrd.utils.units.Speed
1713
import fr.sncf.osrd.utils.units.kilometersPerHour
@@ -21,7 +17,7 @@ import fr.sncf.osrd.utils.units.meters
2117
* Simple internal class representing a stop with safety speed. Makes the function logic more
2218
* straightforward.
2319
*/
24-
private data class SafetySpeedStop(val offset: Offset<TravelledPath>, val isShortSlip: Boolean)
20+
private data class SafetySpeedStop(val offset: Offset<TrainPath>, val isShortSlip: Boolean)
2521

2622
/**
2723
* Compute safety speed ranges, areas where the train has a lower speed limit because of a scheduled
@@ -30,15 +26,12 @@ private data class SafetySpeedStop(val offset: Offset<TravelledPath>, val isShor
3026
*/
3127
fun makeSafetySpeedRanges(
3228
infra: FullInfra,
33-
chunkPath: ChunkPath,
34-
routes: List<RouteId>,
29+
trainPath: TrainPath,
3530
schedule: List<SimulationScheduleItem>,
3631
signalingRanges: DistanceRangeMap<String>,
3732
): DistanceRangeMap<Speed> {
3833
val rawInfra = infra.rawInfra
39-
val zonePaths = routes.flatMap { rawInfra.getRoutePath(it) }
40-
val zonePathStartOffset = getRoutePathStartOffset(rawInfra, chunkPath, routes)
41-
val signalOffsets = getSignalOffsets(infra, zonePaths, zonePathStartOffset)
34+
val signalOffsets = getSignalOffsets(infra, trainPath)
4235

4336
val stopsWithSafetySpeed =
4437
schedule
@@ -66,7 +59,7 @@ fun makeSafetySpeedRanges(
6659
ETCS_LEVEL2.id,
6760
)
6861
) {
69-
makeEndOfPathStop(rawInfra, routes, signalOffsets)?.let { stopsWithSafetySpeed.add(it) }
62+
makeEndOfPathStop(rawInfra, trainPath, signalOffsets)?.let { stopsWithSafetySpeed.add(it) }
7063
}
7164

7265
val res = distanceRangeMapOf<Speed>()
@@ -88,12 +81,12 @@ fun makeSafetySpeedRanges(
8881
}
8982
}
9083
// Safety speed areas may extend outside the path
91-
return res.subMap(0.meters, chunkPath.length)
84+
return res.subMap(0.meters, trainPath.getLength())
9285
}
9386

9487
/** Check if a given stop is in a range of a given signaling system. */
9588
private fun isStopInSignalingSystemRange(
96-
stopOffset: Offset<TravelledPath>,
89+
stopOffset: Offset<TrainPath>,
9790
signalingRanges: DistanceRangeMap<String>,
9891
signalingSystem: String,
9992
): Boolean {
@@ -106,41 +99,38 @@ private fun isStopInSignalingSystemRange(
10699
*/
107100
private fun makeEndOfPathStop(
108101
infra: RawSignalingInfra,
109-
routes: List<RouteId>,
110-
signalOffsets: List<Offset<TravelledPath>>,
102+
trainPath: TrainPath,
103+
signalOffsets: List<Offset<TrainPath>>,
111104
): SafetySpeedStop? {
112-
val lastRouteExit = infra.getRouteExit(routes.last())
105+
val lastRouteExit = infra.getRouteExit(trainPath.getRoutes().last().value)
113106
val isBufferStop = infra.isBufferStop(lastRouteExit.value)
114107
if (isBufferStop) return SafetySpeedStop(signalOffsets.last(), true)
115108
return null
116109
}
117110

118111
/** Return the offsets of block-delimiting signals on the path. */
119-
private fun getSignalOffsets(
120-
infra: FullInfra,
121-
zonePaths: List<StaticIdx<ZonePath>>,
122-
pathStartOffset: Offset<BlockPath>,
123-
): List<Offset<TravelledPath>> {
124-
val res = mutableListOf<Offset<TravelledPath>>()
112+
private fun getSignalOffsets(infra: FullInfra, trainPath: TrainPath): List<Offset<TrainPath>> {
113+
val res = mutableListOf<Offset<TrainPath>>()
125114
val rawInfra = infra.rawInfra
126115
val signalingInfra = infra.loadedSignalInfra
127116
var prevZonePathsLength = 0.meters
128-
for (zonePath in zonePaths) {
117+
for (zonePathRange in trainPath.getZonePaths()) {
118+
val zonePath = zonePathRange.value
129119
val signalPositions = rawInfra.getSignalPositions(zonePath)
130120
val signals = rawInfra.getSignals(zonePath)
131121
for ((signal, signalPosition) in signals zip signalPositions) {
132122
val isDelimiter =
133-
signalingInfra.getLogicalSignals(signal).any { signalingInfra.isBlockDelimiter(it) }
123+
signalingInfra.getLogicalSignals(signal).any(signalingInfra::isBlockDelimiter)
134124
if (isDelimiter) {
135-
res.add(
136-
Offset(prevZonePathsLength + signalPosition.distance - pathStartOffset.distance)
137-
)
125+
res.add(zonePathRange.offsetToTrainPath(signalPosition))
138126
}
139127
}
140128
prevZonePathsLength += rawInfra.getZonePathLength(zonePath).distance
141129
}
142130
// Add one "signal" at the end of the last route no matter what.
143131
// There must be either a signal or a buffer stop, on which we may end safety speed ranges.
144-
res.add(Offset(prevZonePathsLength - pathStartOffset.distance))
132+
val lastRouteRange = trainPath.getRoutes().last()
133+
res.add(lastRouteRange.getObjectAbsolutePathEnd(rawInfra.getRouteLength(lastRouteRange.value)))
134+
145135
return res.filter { it.distance >= 0.meters }
146136
}

core/src/main/kotlin/fr/sncf/osrd/standalone_sim/StandaloneSimulation.kt

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ import fr.sncf.osrd.envelope_sim.pipelines.maxEffortEnvelopeFrom
2323
import fr.sncf.osrd.envelope_sim.pipelines.maxSpeedEnvelopeFrom
2424
import fr.sncf.osrd.envelope_sim_infra.HasMissingSpeedTag
2525
import fr.sncf.osrd.envelope_sim_infra.computeMRSP
26-
import fr.sncf.osrd.path.implementations.ChunkPath
2726
import fr.sncf.osrd.path.interfaces.TrainPath
2827
import fr.sncf.osrd.path.interfaces.TravelledPath
28+
import fr.sncf.osrd.path.interfaces.getLegacyBlockPath
29+
import fr.sncf.osrd.path.interfaces.getLegacyChunkPath
30+
import fr.sncf.osrd.path.interfaces.getLegacyRoutePath
2931
import fr.sncf.osrd.railjson.schema.rollingstock.Comfort
3032
import fr.sncf.osrd.railjson.schema.schedule.RJSAllowanceDistribution
3133
import fr.sncf.osrd.reporting.exceptions.ErrorType.ZeroLengthPath
@@ -39,7 +41,6 @@ import fr.sncf.osrd.utils.DistanceRangeMap
3941
import fr.sncf.osrd.utils.distanceRangeMapOf
4042
import fr.sncf.osrd.utils.entries
4143
import fr.sncf.osrd.utils.toRangeMap
42-
import fr.sncf.osrd.utils.trainPathBlockOffset
4344
import fr.sncf.osrd.utils.units.Distance
4445
import fr.sncf.osrd.utils.units.Offset
4546
import fr.sncf.osrd.utils.units.meters
@@ -54,9 +55,6 @@ val standaloneSimLogger: Logger = LoggerFactory.getLogger("StandaloneSimulation"
5455
fun runStandaloneSimulation(
5556
infra: FullInfra,
5657
trainPath: TrainPath,
57-
chunkPath: ChunkPath,
58-
routes: List<RouteId>,
59-
blockPath: List<BlockId>,
6058
rollingStock: RollingStock,
6159
comfort: Comfort,
6260
constraintDistribution: RJSAllowanceDistribution,
@@ -71,11 +69,10 @@ fun runStandaloneSimulation(
7169
pathItemPositions: List<Offset<TravelledPath>>,
7270
driverBehaviour: DriverBehaviour = DriverBehaviour(),
7371
): SimulationSuccess {
74-
if (chunkPath.length == 0.meters) throw OSRDError(ZeroLengthPath)
75-
val signalingRanges = buildSignalingRanges(infra, blockPath, chunkPath)
72+
if (trainPath.getLength() == 0.meters) throw OSRDError(ZeroLengthPath)
73+
val signalingRanges = buildSignalingRanges(infra, trainPath)
7674
// MRSP & SpeedLimits
77-
val safetySpeedRanges =
78-
makeSafetySpeedRanges(infra, chunkPath, routes, schedule, signalingRanges)
75+
val safetySpeedRanges = makeSafetySpeedRanges(infra, trainPath, schedule, signalingRanges)
7976
var mrsp =
8077
computeMRSP(
8178
trainPath,
@@ -110,7 +107,7 @@ fun runStandaloneSimulation(
110107
trainPath,
111108
timeStep,
112109
curvesAndConditions.curves,
113-
makeETCSContext(rollingStock, infra, chunkPath, routes, blockPath, signalingRanges),
110+
makeETCSContext(rollingStock, infra, trainPath, signalingRanges),
114111
)
115112

116113
// Max speed envelope
@@ -166,10 +163,10 @@ fun runStandaloneSimulation(
166163
runScheduleMetadataExtractor(
167164
finalEnvelope,
168165
trainPath,
169-
chunkPath,
166+
trainPath.getLegacyChunkPath(), // TODO path migration
170167
infra,
171-
routes,
172-
blockPath,
168+
trainPath.getLegacyRoutePath(),
169+
trainPath.getLegacyBlockPath(),
173170
rollingStock,
174171
schedule,
175172
pathItemPositions,
@@ -185,30 +182,14 @@ fun runStandaloneSimulation(
185182
)
186183
}
187184

188-
/** Returns the ranges where each signaling system is encountered, as travelled path offsets. */
189-
fun buildSignalingRanges(
190-
infra: FullInfra,
191-
blockPath: List<BlockId>,
192-
chunkPath: ChunkPath,
193-
): DistanceRangeMap<String> {
185+
/** Returns the ranges where each signaling system is encountered. */
186+
fun buildSignalingRanges(infra: FullInfra, trainPath: TrainPath): DistanceRangeMap<String> {
194187
val blockInfra = infra.blockInfra
195-
var blockStartOffset =
196-
Offset<TravelledPath>(
197-
trainPathBlockOffset(infra.rawInfra, infra.blockInfra, blockPath, chunkPath).distance *
198-
-1.0
199-
)
200188
val res = distanceRangeMapOf<String>()
201-
for (blockId in blockPath) {
202-
val blockLength = blockInfra.getBlockLength(blockId)
203-
val blockEndOffset = blockStartOffset + blockLength.distance
204-
val sigSystem = blockInfra.getBlockSignalingSystem(blockId)
205-
val name = infra.signalingSimulator.sigModuleManager.getName(sigSystem)
206-
res.put(
207-
Distance.max(blockStartOffset.distance, Distance.ZERO),
208-
Distance.min(blockEndOffset.distance, chunkPath.length),
209-
name,
210-
)
211-
blockStartOffset += blockLength.distance
189+
for (blockRange in trainPath.getBlocks()) {
190+
val sigSystem = blockInfra.getBlockSignalingSystem(blockRange.value)
191+
val sigSystemName = infra.signalingSimulator.sigModuleManager.getName(sigSystem)
192+
res.put(blockRange.pathBegin.distance, blockRange.pathEnd.distance, sigSystemName)
212193
}
213194
return res
214195
}

0 commit comments

Comments
 (0)