Skip to content

Commit

Permalink
core: Remove chunks from PathProperties
Browse files Browse the repository at this point in the history
  • Loading branch information
Erashin committed Oct 9, 2023
1 parent b95abdf commit 32e19ba
Show file tree
Hide file tree
Showing 17 changed files with 224 additions and 198 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package fr.sncf.osrd.sim_infra.api

import fr.sncf.osrd.geom.LineString
import fr.sncf.osrd.reporting.exceptions.ErrorType
import fr.sncf.osrd.reporting.exceptions.OSRDError
import fr.sncf.osrd.sim_infra.impl.ChunkPath
import fr.sncf.osrd.sim_infra.impl.NeutralSection
import fr.sncf.osrd.sim_infra.impl.PathPropertiesImpl
import fr.sncf.osrd.sim_infra.impl.buildChunkPath
import fr.sncf.osrd.utils.DistanceRangeMap
import fr.sncf.osrd.utils.indexing.DirStaticIdxList
import fr.sncf.osrd.utils.indexing.StaticIdx
import fr.sncf.osrd.utils.indexing.mutableDirStaticIdxArrayListOf
import fr.sncf.osrd.utils.units.Distance
import fr.sncf.osrd.utils.units.Offset
import fr.sncf.osrd.utils.units.Speed
import fr.sncf.osrd.utils.units.meters

data class IdxWithOffset<T>(
@get:JvmName("getValue")
Expand Down Expand Up @@ -49,10 +47,6 @@ interface PathProperties {
@JvmName("getTrackLocationOffset")
fun getTrackLocationOffset(location: TrackLocation): Distance?
fun <T> getRangeMapFromUndirected(getData: (chunkId: TrackChunkId) -> DistanceRangeMap<T>): DistanceRangeMap<T>

val chunks: DirStaticIdxList<TrackChunk>
/** Returns the offset where the train starts (must be located on the first chunk) */
val beginOffset: Distance
}

/** Build a Path from chunks and offsets, filtering the chunks outside the offsets */
Expand All @@ -63,27 +57,13 @@ fun buildPathPropertiesFrom(
pathBeginOffset: Distance,
pathEndOffset: Distance,
): PathProperties {
val filteredChunks = mutableDirStaticIdxArrayListOf<TrackChunk>()
var totalLength = 0.meters
var mutBeginOffset = pathBeginOffset
var mutEndOffset = pathEndOffset
for (dirChunkId in chunks) {
if (totalLength >= pathEndOffset)
break
val length = infra.getTrackChunkLength(dirChunkId.value)
val blockEndOffset = totalLength + length.distance
val chunkPath = buildChunkPath(infra, chunks, pathBeginOffset, pathEndOffset)
return makePathProperties(infra, chunkPath)
}

// if the block ends before the path starts, it can be safely skipped
// If a block ends where the path starts, it can be skipped too
if (pathBeginOffset >= blockEndOffset) {
mutBeginOffset -= length.distance
mutEndOffset -= length.distance
} else {
filteredChunks.add(dirChunkId)
}
totalLength += length.distance
}
return PathPropertiesImpl(infra, filteredChunks, mutBeginOffset, mutEndOffset)
@JvmName("makePathProperties")
fun makePathProperties(infra: TrackProperties, chunkPath: ChunkPath): PathProperties {
return PathPropertiesImpl(infra, chunkPath)
}

/** For java interoperability purpose */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
package fr.sncf.osrd.sim_infra.impl

import fr.sncf.osrd.geom.LineString
import fr.sncf.osrd.sim_infra.api.DirTrackChunkId
import fr.sncf.osrd.sim_infra.api.IdxWithOffset
import fr.sncf.osrd.sim_infra.api.LoadingGaugeConstraint
import fr.sncf.osrd.sim_infra.api.OperationalPointPart
import fr.sncf.osrd.sim_infra.api.PathProperties
import fr.sncf.osrd.sim_infra.api.TrackChunk
import fr.sncf.osrd.sim_infra.api.TrackChunkId
import fr.sncf.osrd.sim_infra.api.TrackLocation
import fr.sncf.osrd.sim_infra.api.TrackProperties
import fr.sncf.osrd.sim_infra.api.*
import fr.sncf.osrd.utils.Direction
import fr.sncf.osrd.utils.DistanceRangeMap
import fr.sncf.osrd.utils.distanceRangeMapOf
import fr.sncf.osrd.utils.indexing.DirStaticIdxList
import fr.sncf.osrd.utils.indexing.mutableDirStaticIdxArrayListOf
import fr.sncf.osrd.utils.units.Distance
import fr.sncf.osrd.utils.units.Offset
import fr.sncf.osrd.utils.units.Speed
import fr.sncf.osrd.utils.units.meters

data class PathPropertiesImpl(
val infra: TrackProperties,
override val chunks: DirStaticIdxList<TrackChunk>,
data class ChunkPath(
@get:JvmName("getChunks")
val chunks: DirStaticIdxList<TrackChunk>,
@get:JvmName("getBeginOffset")
override val beginOffset: Distance,
val beginOffset: Distance,
@get:JvmName("getEndOffset")
val endOffset: Distance,
val endOffset: Distance
)

data class PathPropertiesImpl(
val infra: TrackProperties,
val chunkPath: ChunkPath
) : PathProperties {
override fun getSlopes(): DistanceRangeMap<Double> {
return getRangeMap { dirChunkId -> infra.getTrackChunkSlope(dirChunkId) }
Expand Down Expand Up @@ -67,13 +65,13 @@ data class PathPropertiesImpl(
}

override fun getLength(): Distance {
return endOffset - beginOffset
return chunkPath.endOffset - chunkPath.beginOffset
}

override fun getTrackLocationAtOffset(pathOffset: Distance): TrackLocation {
val offset = pathOffset + beginOffset
val offset = pathOffset + chunkPath.beginOffset
var lengthPrevChunks = 0.meters
for (chunk in chunks) {
for (chunk in chunkPath.chunks) {
val chunkLength = infra.getTrackChunkLength(chunk.value).distance
if (lengthPrevChunks + chunkLength >= offset) {
val trackId = infra.getTrackFromChunk(chunk.value)
Expand All @@ -90,10 +88,10 @@ data class PathPropertiesImpl(
}

override fun getTrackLocationOffset(location: TrackLocation): Distance? {
val offset = getOffsetOfTrackLocationOnChunks(infra, location, chunks) ?: return null
if (offset < beginOffset || offset > endOffset)
val offset = getOffsetOfTrackLocationOnChunks(infra, location, chunkPath.chunks) ?: return null
if (offset < chunkPath.beginOffset || offset > chunkPath.endOffset)
return null
return offset - beginOffset
return offset - chunkPath.beginOffset
}

private fun projectLineString(getData: (chunkId: TrackChunkId) -> LineString): LineString {
Expand All @@ -119,19 +117,20 @@ data class PathPropertiesImpl(
)
}

val chunks = chunkPath.chunks
if (chunks.size == 0)
return LineString.make(doubleArrayOf(), doubleArrayOf())
if (chunks.size == 1)
return sliceChunkData(chunks.first(), beginOffset, endOffset)
return sliceChunkData(chunks.first(), chunkPath.beginOffset, chunkPath.endOffset)

val lineStrings = arrayListOf<LineString>()
lineStrings.add(sliceChunkData(chunks.first(), beginOffset, null))
lineStrings.add(sliceChunkData(chunks.first(), chunkPath.beginOffset, null))
var totalChunkDistance = infra.getTrackChunkLength(chunks.first().value).distance
for (i in 1 until chunks.size - 1) {
lineStrings.add(getDirData(chunks[i]))
totalChunkDistance += infra.getTrackChunkLength(chunks[i].value).distance
}
lineStrings.add(sliceChunkData(chunks.last(), null, endOffset - totalChunkDistance))
lineStrings.add(sliceChunkData(chunks.last(), null, chunkPath.endOffset - totalChunkDistance))
return LineString.concatenate(lineStrings)
}

Expand All @@ -141,13 +140,13 @@ data class PathPropertiesImpl(
): DistanceRangeMap<T> {
val maps = ArrayList<DistanceRangeMap<T>>()
val distances = ArrayList<Distance>()
for (dirChunk in chunks) {
for (dirChunk in chunkPath.chunks) {
maps.add(getData.invoke(dirChunk))
distances.add(infra.getTrackChunkLength(dirChunk.value).distance)
}
val mergedMap = mergeMaps(maps, distances)
mergedMap.truncate(beginOffset, endOffset)
mergedMap.shiftPositions(-beginOffset)
mergedMap.truncate(chunkPath.beginOffset, chunkPath.endOffset)
mergedMap.shiftPositions(-chunkPath.beginOffset)
return mergedMap
}

Expand Down Expand Up @@ -178,7 +177,7 @@ data class PathPropertiesImpl(
): List<IdxWithOffset<T>> {
val res = ArrayList<IdxWithOffset<T>>()
var chunkOffset = 0.meters
for (chunk in chunks) {
for (chunk in chunkPath.chunks) {
for ((element, offset) in getData.invoke(chunk)) {
val projectedOffset = projectPosition(chunk, offset)
res.add(IdxWithOffset(element, chunkOffset + projectedOffset))
Expand All @@ -202,9 +201,8 @@ data class PathPropertiesImpl(
/** Keeps only the elements that are not outside the path, and shift the offsets to start at 0 */
private fun <T>filterAndShiftElementsOnPath(res: List<IdxWithOffset<T>>): List<IdxWithOffset<T>> {
return res
.filter { element -> element.offset >= beginOffset }
.filter { element -> element.offset <= endOffset }
.map { element -> IdxWithOffset(element.value, element.offset - beginOffset) }
.filter { element -> element.offset >= chunkPath.beginOffset && element.offset <= chunkPath.endOffset }
.map { element -> IdxWithOffset(element.value, element.offset - chunkPath.beginOffset) }
}

/** Merge all the given range maps, offsetting them by the given distances. The list sizes must match. */
Expand Down Expand Up @@ -255,3 +253,33 @@ fun getOffsetOfTrackLocationOnChunksOrThrow(
): Distance {
return getOffsetOfTrackLocationOnChunks(infra, location, chunks) ?: throw RuntimeException()
}

@JvmName("buildChunkPath")
fun buildChunkPath(
infra: TrackProperties,
chunks: DirStaticIdxList<TrackChunk>,
pathBeginOffset: Distance,
pathEndOffset: Distance
): ChunkPath {
val filteredChunks = mutableDirStaticIdxArrayListOf<TrackChunk>()
var totalLength = 0.meters
var mutBeginOffset = pathBeginOffset
var mutEndOffset = pathEndOffset
for (dirChunkId in chunks) {
if (totalLength >= pathEndOffset)
break
val length = infra.getTrackChunkLength(dirChunkId.value)
val blockEndOffset = totalLength + length.distance

// if the block ends before the path starts, it can be safely skipped
// If a block ends where the path starts, it can be skipped too
if (pathBeginOffset >= blockEndOffset) {
mutBeginOffset -= length.distance
mutEndOffset -= length.distance
} else {
filteredChunks.add(dirChunkId)
}
totalLength += length.distance
}
return ChunkPath(filteredChunks, mutBeginOffset, mutEndOffset)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package fr.sncf.osrd.api;

import static fr.sncf.osrd.api.utils.PathPropUtils.makePathProps;
import static fr.sncf.osrd.api.utils.PathPropUtils.makeChunkPath;

import com.squareup.moshi.Json;
import com.squareup.moshi.JsonAdapter;
Expand All @@ -13,7 +13,8 @@
import fr.sncf.osrd.reporting.warnings.DiagnosticRecorderImpl;
import fr.sncf.osrd.reporting.warnings.Warning;
import fr.sncf.osrd.standalone_sim.SignalProjectionKt;
import fr.sncf.osrd.standalone_sim.result.*;
import fr.sncf.osrd.standalone_sim.result.ResultTrain;
import fr.sncf.osrd.standalone_sim.result.SignalUpdate;
import org.takes.Request;
import org.takes.Response;
import org.takes.Take;
Expand Down Expand Up @@ -57,11 +58,11 @@ public Response act(Request req) throws Exception {
var infra = infraManager.getInfra(request.infra, request.expectedVersion, recorder);

// Parse trainPath
var trainPath = makePathProps(infra.rawInfra(), request.trainPath);
var chunkPath = makeChunkPath(infra.rawInfra(), request.trainPath);
var routePath = request.trainPath.routePath.stream()
.map(rjsRoutePath -> infra.rawInfra().getRouteFromName(rjsRoutePath.route))
.toList();
var result = SignalProjectionKt.project(infra, trainPath, routePath, request.signalSightings,
var result = SignalProjectionKt.project(infra, chunkPath, routePath, request.signalSightings,
request.zoneUpdates);

result.warnings = recorder.warnings;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ public Response act(Request req) throws OSRDError {
simResult.baseSimulations.add(ScheduleMetadataExtractor.run(
res.envelope(),
res.trainPath(),
res.chunkPath(),
makeTrainSchedule(res.envelope().getEndPos(), rollingStock, comfort, res.stopResults()),
infra
));
Expand Down
27 changes: 22 additions & 5 deletions core/src/main/java/fr/sncf/osrd/api/utils/PathPropUtils.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package fr.sncf.osrd.api.utils;

import static fr.sncf.osrd.sim_infra.api.PathPropertiesKt.buildPathPropertiesFrom;
import static fr.sncf.osrd.sim_infra.api.PathPropertiesKt.makePathProperties;
import static fr.sncf.osrd.sim_infra.api.TrackInfraKt.getTrackSectionFromNameOrThrow;
import static fr.sncf.osrd.sim_infra.impl.PathPropertiesImplKt.buildChunkPath;
import static fr.sncf.osrd.utils.KtToJavaConverter.toIntList;
import static fr.sncf.osrd.utils.units.Distance.fromMeters;

Expand All @@ -10,8 +12,10 @@
import fr.sncf.osrd.railjson.schema.infra.trackranges.RJSDirectionalTrackRange;
import fr.sncf.osrd.railjson.schema.schedule.RJSTrainPath;
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.*;
import fr.sncf.osrd.sim_infra.api.TrackChunk;
import fr.sncf.osrd.sim_infra.impl.ChunkPath;
import fr.sncf.osrd.utils.Direction;
import fr.sncf.osrd.utils.graph.Pathfinding;
import fr.sncf.osrd.utils.indexing.DirStaticIdxKt;
Expand Down Expand Up @@ -58,6 +62,19 @@ public static PathProperties makePathProps(RawSignalingInfra rawInfra, BlockInfr
/** Creates a `Path` instance from a list of block ranges */
public static PathProperties makePathProps(RawSignalingInfra rawInfra, BlockInfra blockInfra,
List<Pathfinding.EdgeRange<Integer>> blockRanges) {
var chunkPath = makeChunkPath(rawInfra, blockInfra, blockRanges);
return makePathProperties(rawInfra, chunkPath);
}

/** Builds a PathProperties from an RJSTrainPath */
public static PathProperties makePathProps(RawSignalingInfra rawInfra, RJSTrainPath rjsPath) {
var chunkPath = makeChunkPath(rawInfra, rjsPath);
return makePathProperties(rawInfra, chunkPath);
}

/** Creates a ChunkPath from a list of block ranges */
public static ChunkPath makeChunkPath(RawSignalingInfra rawInfra, BlockInfra blockInfra,
List<Pathfinding.EdgeRange<Integer>> blockRanges) {
assert !blockRanges.isEmpty();
long totalBlockPathLength = 0;
var chunks = new MutableDirStaticIdxArrayList<TrackChunk>();
Expand All @@ -73,11 +90,11 @@ public static PathProperties makePathProps(RawSignalingInfra rawInfra, BlockInfr
var lastRange = blockRanges.get(blockRanges.size() - 1);
var lastBlockLength = blockInfra.getBlockLength(lastRange.edge());
var endOffset = totalBlockPathLength - lastBlockLength + lastRange.end();
return buildPathPropertiesFrom(rawInfra, chunks, startOffset, endOffset);
return buildChunkPath(rawInfra, chunks, startOffset, endOffset);
}

/** Builds a PathProperties from an RJSTrainPath */
public static PathProperties makePathProps(RawSignalingInfra rawInfra, RJSTrainPath rjsPath) {
/** Builds a ChunkPath from an RJSTrainPath */
public static ChunkPath makeChunkPath(RawSignalingInfra rawInfra, RJSTrainPath rjsPath) {
var trackRanges = new ArrayList<RJSDirectionalTrackRange>();
for (var routePath : rjsPath.routePath) {
for (var trackRange : routePath.trackSections) {
Expand Down Expand Up @@ -115,6 +132,6 @@ public static PathProperties makePathProps(RawSignalingInfra rawInfra, RJSTrainP
.mapToDouble(r -> r.end - r.begin)
.sum()
);
return buildPathPropertiesFrom(rawInfra, chunks, startOffset, endOffset);
return buildChunkPath(rawInfra, chunks, startOffset, endOffset);
}
}
Loading

0 comments on commit 32e19ba

Please sign in to comment.