diff --git a/core/osrd-reporting/src/main/java/fr/sncf/osrd/reporting/exceptions/ErrorType.java b/core/osrd-reporting/src/main/java/fr/sncf/osrd/reporting/exceptions/ErrorType.java index db2eeab9407..e6bc927c400 100644 --- a/core/osrd-reporting/src/main/java/fr/sncf/osrd/reporting/exceptions/ErrorType.java +++ b/core/osrd-reporting/src/main/java/fr/sncf/osrd/reporting/exceptions/ErrorType.java @@ -298,11 +298,6 @@ public enum ErrorType { "invalid envelope, envelope parts are not contiguous", ErrorCause.USER ), - NoCompatibleEnvelopeFound( - "no_compatible_envelope", - "Couldn't find an envelope that wouldn't cause a conflict", - ErrorCause.USER - ), SignalingError( "signaling_error", "Unknown signaling system: $sigSystem", diff --git a/core/src/main/java/fr/sncf/osrd/stdcm/graph/STDCMStandardAllowance.java b/core/src/main/java/fr/sncf/osrd/stdcm/graph/STDCMStandardAllowance.java index 78ec2e490fa..bf4c6fcf26d 100644 --- a/core/src/main/java/fr/sncf/osrd/stdcm/graph/STDCMStandardAllowance.java +++ b/core/src/main/java/fr/sncf/osrd/stdcm/graph/STDCMStandardAllowance.java @@ -2,13 +2,13 @@ import static fr.sncf.osrd.envelope_sim.TrainPhysicsIntegrator.POSITION_EPSILON; +import fr.sncf.osrd.envelope_sim.EnvelopeSimContext; import fr.sncf.osrd.envelope_sim.EnvelopeSimPath; import fr.sncf.osrd.envelope.Envelope; +import fr.sncf.osrd.envelope_sim.allowances.LinearAllowance; import fr.sncf.osrd.envelope_sim.allowances.MarecoAllowance; import fr.sncf.osrd.envelope_sim.allowances.utils.AllowanceRange; import fr.sncf.osrd.envelope_sim.allowances.utils.AllowanceValue; -import fr.sncf.osrd.reporting.exceptions.ErrorType; -import fr.sncf.osrd.reporting.exceptions.OSRDError; import fr.sncf.osrd.standalone_sim.EnvelopeStopWrapper; import fr.sncf.osrd.stdcm.preprocessing.interfaces.BlockAvailabilityInterface; import fr.sncf.osrd.train.RollingStock; @@ -40,28 +40,40 @@ static Envelope applyAllowance( double departureTime, List stops ) { - if (standardAllowance == null) - return envelope; // This isn't just an optimization, it avoids float inaccuracies + if (standardAllowance == null + || standardAllowance.getAllowanceTime(envelope.getTotalTime(), envelope.getTotalDistance()) < 1e-5) + return envelope; // This isn't just an optimization, it avoids float inaccuracies and possible errors var rangeTransitions = initRangeTransitions(stops); + var context = EnvelopeSimContextBuilder.build(rollingStock, envelopeSimPath, timeStep, comfort); for (int i = 0; i < 10; i++) { var newEnvelope = applyAllowanceWithTransitions( envelope, standardAllowance, - envelopeSimPath, - rollingStock, - timeStep, - comfort, - rangeTransitions + rangeTransitions, + context ); var conflictOffset = findConflictOffsets( newEnvelope, blockAvailability, ranges, departureTime, stops); if (conflictOffset < 0) return newEnvelope; - assert !rangeTransitions.contains(conflictOffset) : "conflict offset is already on a range transition"; + if (rangeTransitions.contains(conflictOffset)) + break; // Error case, we exit and fallback to the linear envelope logger.info("Conflict in new envelope at offset {}, splitting mareco ranges", conflictOffset); rangeTransitions.add(conflictOffset); } - throw new OSRDError(ErrorType.NoCompatibleEnvelopeFound); + logger.info("Failed to compute a mareco standard allowance, fallback to linear allowance"); + return makeFallbackEnvelope(envelope, standardAllowance, context); + } + + /** Creates an envelope with a linear allowance. To be used in case we fail to compute a mareco envelope */ + private static Envelope makeFallbackEnvelope( + Envelope envelope, + AllowanceValue standardAllowance, + EnvelopeSimContext context + ) { + return new LinearAllowance(0, envelope.getEndPos(), 0, List.of( + new AllowanceRange(0, envelope.getEndPos(), standardAllowance) + )).apply(envelope, context); } /** Initiates the range transitions with one transition on each stop */ @@ -108,12 +120,8 @@ private static long findConflictOffsets( private static Envelope applyAllowanceWithTransitions( Envelope envelope, AllowanceValue standardAllowance, - EnvelopeSimPath envelopeSimPath, - RollingStock rollingStock, - double timeStep, - RollingStock.Comfort comfort, - NavigableSet rangeTransitions - ) { + NavigableSet rangeTransitions, + EnvelopeSimContext context) { var allowance = new MarecoAllowance( 0, @@ -121,8 +129,7 @@ private static Envelope applyAllowanceWithTransitions( 1, makeAllowanceRanges(standardAllowance, envelope.getEndPos(), rangeTransitions) ); - return allowance.apply(envelope, - EnvelopeSimContextBuilder.build(rollingStock, envelopeSimPath, timeStep, comfort)); + return allowance.apply(envelope, context); } /** Create the list of `AllowanceRange`, with the given transitions */