Skip to content

Commit

Permalink
core: update simulation to take into account extended dead sections
Browse files Browse the repository at this point in the history
Co-authored-by: Baptiste Prevot <[email protected]>
  • Loading branch information
2 people authored and flomonster committed Jul 6, 2023
1 parent e3f7bdb commit b36fcf5
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,9 @@ public EnvelopeSimContext(
this.timeStep = timeStep;
this.tractiveEffortCurveMap = tractiveEffortCurveMap;
}

public EnvelopeSimContext updateCurves(
RangeMap<Double, PhysicsRollingStock.TractiveEffortPoint[]> tractiveEffortCurveMap) {
return new EnvelopeSimContext(rollingStock, path, timeStep, tractiveEffortCurveMap);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ public class RJSRollingStock implements Identified {
@Json(name = "loading_gauge")
public RJSLoadingGaugeType loadingGauge = null;

@Json(name = "electrical_power_startup_time")
public Double electricalPowerStartUpTime = null;

@Json(name = "raise_pantograph_time")
public Double raisePantographTime = null;

public enum GammaType {
CONST,
MAX
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public Collection<Pathfinding.Range> apply(SignalingRoute reservationRoute) {
* because it needs electrified tracks and isn't compatible with the catenaries in some range
*/
private static Set<Pathfinding.Range> getBlockedRanges(RollingStock stock, ReservationRoute route) {
if (!stock.isElectricOnly())
if (stock.isThermal())
return Set.of();

var res = new HashSet<Pathfinding.Range>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ else if (!rjsRollingStock.version.equals(RJSRollingStock.CURRENT_VERSION))
modes,
rjsRollingStock.effortCurves.defaultMode,
rjsRollingStock.basePowerClass,
rjsRollingStock.powerRestrictions
rjsRollingStock.powerRestrictions,
rjsRollingStock.electricalPowerStartUpTime,
rjsRollingStock.raisePantographTime
);
}

Expand Down
29 changes: 14 additions & 15 deletions core/src/main/java/fr/sncf/osrd/standalone_sim/StandaloneSim.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,14 @@ public static StandaloneSimResult run(
for (var trainSchedule : schedules) {
if (!cacheMaxEffort.containsKey(trainSchedule)) {
var rollingStock = trainSchedule.rollingStock;

// MRSP & SpeedLimits
var mrsp = MRSP.from(trainPath, rollingStock, true, trainSchedule.tag);
var speedLimits = MRSP.from(trainPath, rollingStock, false, trainSchedule.tag);
mrsp = driverBehaviour.applyToMRSP(mrsp);
cacheSpeedLimits.put(trainSchedule, ResultEnvelopePoint.from(speedLimits));

// Base
// Context
var electrificationMap = envelopeSimPath.getElectrificationMap(rollingStock.basePowerClass,
trainSchedule.powerRestrictionMap, rollingStock.powerRestrictions,
trainSchedule.options.ignoreElectricalProfiles);
Expand All @@ -78,7 +79,18 @@ public static StandaloneSimResult run(
curvesAndConditions.conditions(), electrificationMap));
cachePowerRestrictionRanges.put(trainSchedule, PowerRestrictionRange.from(
curvesAndConditions.conditions(), trainSchedule.powerRestrictionMap));
var envelope = computeMaxEffortEnvelope(context, mrsp, trainSchedule);

// MaxSpeedEnvelope
var maxSpeedEnvelope = MaxSpeedEnvelope.from(context, trainSchedule.getStopsPositions(), mrsp);

// MaxEffortEnvelope
// need to compute a new effort curve mapping with the maxSpeedEnvelope in order to extend the
// neutral sections (with time to lower/raise pantograph...)
context = context.updateCurves(
rollingStock.addNeutralSystemTimes(electrificationMap, trainSchedule.comfort, maxSpeedEnvelope,
context.tractiveEffortCurveMap));
var envelope = MaxEffortEnvelope.from(context, trainSchedule.initialSpeed, maxSpeedEnvelope);

var simResultTrain = ScheduleMetadataExtractor.run(
envelope,
trainPath,
Expand Down Expand Up @@ -140,19 +152,6 @@ public static StandaloneSimResult runFromRJS(
);
}

/**
* Compute the max effort envelope given a path, MRSP and a schedule
*/
public static Envelope computeMaxEffortEnvelope(
EnvelopeSimContext context,
Envelope mrsp,
StandaloneTrainSchedule schedule
) {
final var stops = schedule.getStopsPositions();
final var maxSpeedEnvelope = MaxSpeedEnvelope.from(context, stops, mrsp);
return MaxEffortEnvelope.from(context, schedule.initialSpeed, maxSpeedEnvelope);
}

/**
* Apply a list of allowances, in order
*/
Expand Down
112 changes: 97 additions & 15 deletions core/src/main/java/fr/sncf/osrd/train/RollingStock.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package fr.sncf.osrd.train;

import com.google.common.collect.ImmutableRangeMap;
import com.google.common.collect.Range;
import com.google.common.collect.RangeMap;
import com.google.common.collect.TreeRangeMap;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import fr.sncf.osrd.envelope.Envelope;
import fr.sncf.osrd.envelope_sim.PhysicsRollingStock;
import fr.sncf.osrd.envelope_sim.electrification.Electrification;
import fr.sncf.osrd.envelope_sim.electrification.Electrified;
Expand Down Expand Up @@ -96,6 +98,8 @@ public class RollingStock implements PhysicsRollingStock {
private final String defaultMode;
public final String basePowerClass;
public final Map<String, String> powerRestrictions;
public final Double electricalPowerStartUpTime;
public final Double raisePantographTime;

@Override
public double getMass() {
Expand Down Expand Up @@ -188,17 +192,18 @@ public double getDeceleration() {
}

/**
* Returns the tractive effort curve that matches best, along with the infra conditions that matched
* Returns the tractive effort curve that matches best, along with the electrification conditions that matched
*/
protected CurveAndCondition findTractiveEffortCurve(Comfort comfort, Electrification electrification) {
if (electrification instanceof Neutral n) {
var wouldUseRes = findTractiveEffortCurve(comfort, n.overlappedElectrification);
if (!modes.get(wouldUseRes.cond.mode).isElectric) {
return wouldUseRes;
} else {
return new CurveAndCondition(COASTING_CURVE, new InfraConditions(null, null, null));
var overlappedCurve = findTractiveEffortCurve(comfort, n.overlappedElectrification);
var isOverlappedCurveThermal = !modes.get(overlappedCurve.cond.mode).isElectric;
if (isOverlappedCurveThermal) {
return overlappedCurve;
}
} else if (electrification instanceof NonElectrified) {
return new CurveAndCondition(COASTING_CURVE, new InfraConditions(null, null, null));
}
if (electrification instanceof NonElectrified) {
return new CurveAndCondition(modes.get(defaultMode).defaultCurve,
new InfraConditions(defaultMode, null, null));
}
Expand All @@ -221,6 +226,7 @@ protected CurveAndCondition findTractiveEffortCurve(Comfort comfort, Electrifica

/**
* Returns the tractive effort curves corresponding to the electrical conditions map
* The neutral sections are not extended in this function.
*
* @param electrificationMap The map of electrification conditions to use
* @param comfort The comfort level to get the curves for
Expand All @@ -238,19 +244,88 @@ public CurvesAndConditions mapTractiveEffortCurves(RangeMap<Double, Electrificat
return new CurvesAndConditions(ImmutableRangeMap.copyOf(res), ImmutableRangeMap.copyOf(conditionsUsed));
}


protected Range<Double> computeDeadSectionRange(Range<Double> neutralRange, Neutral n, Envelope maxEffortEnvelope) {
var endRange = neutralRange.upperEndpoint();
var finalSpeed = maxEffortEnvelope.interpolateSpeedLeftDir(endRange, 1);
double additionalRange = finalSpeed * electricalPowerStartUpTime;
if (n.isDropPantograph) {
additionalRange += finalSpeed * raisePantographTime;
}
return Range.closed(neutralRange.lowerEndpoint(), neutralRange.upperEndpoint() + additionalRange);
}

/**
* Returns the tractive effort curves corresponding to the electrical conditions map with neutral sections
*
* @param electrificationMap The map of electrification conditions to use
* @param comfort The comfort level to get the curves for
* @param maxSpeedEnvelope The maxSpeedEnvelope used to extend the neutral sections
*/
public RangeMap<Double, TractiveEffortPoint[]> addNeutralSystemTimes(
RangeMap<Double, Electrification> electrificationMap, Comfort comfort, Envelope maxSpeedEnvelope,
RangeMap<Double, TractiveEffortPoint[]> curvesUsed) {

TreeRangeMap<Double, TractiveEffortPoint[]> newCurves = TreeRangeMap.create();
newCurves.putAll(curvesUsed);

for (var elecCondEntry : electrificationMap.asMapOfRanges().entrySet()) {
if (elecCondEntry.getValue() instanceof Neutral n) {
// estimate the distance during which the train will be coasting, due to having respected the
// neutral section
var deadSectionRange = computeDeadSectionRange(elecCondEntry.getKey(), n, maxSpeedEnvelope);
var curveAndCondition = findTractiveEffortCurve(comfort, n);
if (curveAndCondition.cond.mode == null) { // The train is effectively coasting
newCurves.put(deadSectionRange, curveAndCondition.curve);
}
}
}
return ImmutableRangeMap.copyOf(newCurves);
}

public Set<String> getModeNames() {
return modes.keySet();
}

/**
* Return whether this rolling stock support only electric modes
* Return whether this rolling stock's default mode is thermal
*/
public boolean isElectricOnly() {
for (var mode : modes.values()) {
if (!mode.isElectric)
return false;
}
return true;
public boolean isThermal() {
return !modes.get(defaultMode).isElectric();
}

/**
* Return whether this rolling stock's has an electric mode
*/
public final boolean isElectric() {
return modes.values().stream().anyMatch(ModeEffortCurves::isElectric);
}

/**
* Creates a new rolling stock (a physical train inventory item).
*/
public RollingStock(
String id,
double length,
double mass,
double inertiaCoefficient,
double a,
double b,
double c,
double maxSpeed,
double startUpTime,
double startUpAcceleration,
double comfortAcceleration,
double gamma,
GammaType gammaType,
RJSLoadingGaugeType loadingGaugeType,
Map<String, ModeEffortCurves> modes,
String defaultMode,
String basePowerclass
) {
this(id, length, mass, inertiaCoefficient, a, b, c, maxSpeed, startUpTime, startUpAcceleration,
comfortAcceleration, gamma, gammaType, loadingGaugeType, modes, defaultMode, basePowerclass, Map.of(),
0., 0.);
}

/**
Expand All @@ -274,7 +349,9 @@ public RollingStock(
Map<String, ModeEffortCurves> modes,
String defaultMode,
String basePowerclass,
Map<String, String> powerRestrictions
Map<String, String> powerRestrictions,
Double electricalPowerStartUpTime,
Double raisePantographTime
) {
this.id = id;
this.A = a;
Expand All @@ -295,5 +372,10 @@ public RollingStock(
this.loadingGaugeType = loadingGaugeType;
this.basePowerClass = basePowerclass;
this.powerRestrictions = powerRestrictions;
this.electricalPowerStartUpTime = electricalPowerStartUpTime;
this.raisePantographTime = raisePantographTime;

assert !isElectric() || (this.electricalPowerStartUpTime != null && this.raisePantographTime != null) :
"Electrical power start up time and Raise pantograph time must be defined for an electric train";
}
}
22 changes: 9 additions & 13 deletions core/src/test/java/fr/sncf/osrd/train/TestTrains.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ private static Map<String, RollingStock.ModeEffortCurves> createModeEffortCurves
RJSLoadingGaugeType.G1,
linearModeEffortCurves,
"thermal",
"1",
Map.of()
"1"
);

VERY_LONG_FAST_TRAIN = new RollingStock(
Expand All @@ -125,8 +124,7 @@ private static Map<String, RollingStock.ModeEffortCurves> createModeEffortCurves
RJSLoadingGaugeType.G1,
linearModeEffortCurves,
"thermal",
"1",
Map.of()
"1"
);

REALISTIC_FAST_TRAIN = new RollingStock(
Expand All @@ -144,7 +142,9 @@ private static Map<String, RollingStock.ModeEffortCurves> createModeEffortCurves
complexModeEffortCurves,
"thermal",
"5",
Map.of("Restrict1", "4", "Restrict2", "3")
Map.of("Restrict1", "4", "Restrict2", "3"),
0.,
0.
);

REALISTIC_FAST_TRAIN_MAX_DEC_TYPE = new RollingStock(
Expand All @@ -161,8 +161,7 @@ private static Map<String, RollingStock.ModeEffortCurves> createModeEffortCurves
RJSLoadingGaugeType.G1,
linearModeEffortCurves,
"thermal",
"1",
Map.of()
"1"
);

FAST_TRAIN_LARGE_GAUGE = new RollingStock(
Expand All @@ -179,8 +178,7 @@ private static Map<String, RollingStock.ModeEffortCurves> createModeEffortCurves
RJSLoadingGaugeType.GC,
linearModeEffortCurves,
"thermal",
"1",
Map.of()
"1"
);

FAST_ELECTRIC_TRAIN = new RollingStock(
Expand All @@ -198,8 +196,7 @@ private static Map<String, RollingStock.ModeEffortCurves> createModeEffortCurves
createModeEffortCurves(MAX_SPEED, CurveShape.LINEAR,
Map.of("25000", new RollingStock.EffortCurveConditions[0])),
"25000",
"1",
Map.of()
"1"
);

CONSTANT_POWER_TRAIN = new RollingStock(
Expand All @@ -217,8 +214,7 @@ private static Map<String, RollingStock.ModeEffortCurves> createModeEffortCurves
createModeEffortCurves(MAX_SPEED, CurveShape.HYPERBOLIC,
Map.of("thermal", new RollingStock.EffortCurveConditions[0])),
"thermal",
"1",
Map.of()
"1"
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1902,5 +1902,7 @@
"C1": 3,
"C2": 1
},
"energy_sources": []
"energy_sources": [],
"electrical_power_startup_time": 5.0,
"raise_pantograph_time": 15.0
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,5 @@
"unit": ""
},
"power_restrictions": {},
"energy_sources": [],
"electrical_power_startup_time": 5.0,
"raise_pantograph_time": 15.0
"energy_sources": []
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,5 @@
}
},
"base_power_class": "1",
"energy_sources": [],
"electrical_power_startup_time": null,
"raise_pantograph_time": null
"energy_sources": []
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,5 @@
}
},
"base_power_class": "1",
"energy_sources": [],
"electrical_power_startup_time": null,
"raise_pantograph_time": null
"energy_sources": []
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,5 @@
}
},
"base_power_class": "1",
"energy_sources": [],
"electrical_power_startup_time": null,
"raise_pantograph_time": null
"energy_sources": []
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,5 @@
}
},
"base_power_class": "1",
"energy_sources": [],
"electrical_power_startup_time": null,
"raise_pantograph_time": null
"energy_sources": []
}

0 comments on commit b36fcf5

Please sign in to comment.