Skip to content

Commit

Permalink
Automatic merge of T1.4-431-g76abf4e69 and 16 pull requests
Browse files Browse the repository at this point in the history
- Pull request #525 at 614b222: TCS extensions
- Pull request #613 at 39fb000: fix: Use properly FPS-independent smoothing function
- Pull request #615 at 75bf3a4:  Management of EOT devices  https://blueprints.launchpad.net/or/+spec/eot
- Pull request #616 at 1b168a0: Improvements in graduated/full release braking
- Pull request #617 at 99c6474: 02m: Removed menu option Debrief Evaluation. Now always available.
- Pull request #619 at ea10bfc: Adjust HuD to display relevant parameters for DM locomotive
- Pull request #620 at 67c67f1: Adjust kinietic friction calculations
- Pull request #622 at c01c4a6: Bug fix for https://bugs.launchpad.net/or/+bug/1965311. TDI: The vacuum brake value is misaligned.
- Pull request #624 at 01231e1: Menu option04 - invert controls
- Pull request #625 at b161625: Menu > Options - Change defaults for best graphics
- Pull request #627 at 69dabe4: Improve advanced adhesion model
- Pull request #629 at 34abd9c: Refined label for downloading Testing Version
- Pull request #630 at 688d0cd: Sky Color Fix (Addresses Trello Roadmap Card #367 for More accurate sunrise and sunset)
- Pull request #631 at 443fc13: Get correct signal id if signal ahead is in same Track Circuit
- Pull request #633 at 7ce52a7: Removed ViewDispatcher setting
- Pull request #635 at b731488: Minor steam locomotive issues.
  • Loading branch information
openrails-bot committed Apr 3, 2022
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 96 deletions.
1 change: 0 additions & 1 deletion Source/Orts.Simulation/Simulation/AIs/AITrain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6286,7 +6286,6 @@ public bool SwitchToPlayerControl()
var loco = car as MSTSLocomotive;
loco.LocomotiveAxle.Reset(Simulator.GameTime, SpeedMpS);
loco.LocomotiveAxle.AxleSpeedMpS = SpeedMpS;
loco.LocomotiveAxle.FilterMovingAverage.Initialize(loco.AverageForceN);
loco.AntiSlip = false; // <CSComment> TODO Temporary patch until AntiSlip is re-implemented
}
if (car == Simulator.PlayerLocomotive) { leadLocomotiveIndex = j; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,6 @@ public MSTSLocomotive(Simulator simulator, string wagPath)
LocomotiveAxle.DriveType = AxleDriveType.ForceDriven;
LocomotiveAxle.DampingNs = MassKG / 1000.0f;
LocomotiveAxle.FrictionN = MassKG / 100.0f;
LocomotiveAxle.StabilityCorrection = true;
LocomotiveAxle.FilterMovingAverage.Size = Simulator.Settings.AdhesionMovingAverageFilterSize;
CurrentFilter = new IIRFilter(IIRFilter.FilterTypes.Butterworth, 1, IIRFilter.HzToRad(0.5f), 0.001f);
AdhesionFilter = new IIRFilter(IIRFilter.FilterTypes.Butterworth, 1, IIRFilter.HzToRad(1f), 0.001f);

Expand Down Expand Up @@ -1289,7 +1287,6 @@ public override void Restore(BinaryReader inf)

LocomotiveAxle = new Axle(inf);
MoveParamsToAxle();
LocomotiveAxle.FilterMovingAverage.Initialize(AverageForceN);
LocomotiveAxle.Reset(Simulator.GameTime, axleSpeedMpS);
}

Expand Down Expand Up @@ -1652,7 +1649,6 @@ public override void InitializeMoving()
AverageForceN = MaxForceN * Train.MUThrottlePercent / 100;
float maxPowerW = MaxPowerW * Train.MUThrottlePercent * Train.MUThrottlePercent / 10000;
if (AverageForceN * SpeedMpS > maxPowerW) AverageForceN = maxPowerW / SpeedMpS;
LocomotiveAxle.FilterMovingAverage.Initialize(AverageForceN);
LocomotivePowerSupply?.InitializeMoving();
if (Train.IsActualPlayerTrain)
{
Expand Down Expand Up @@ -2605,9 +2601,10 @@ public void AdvancedAdhesion(float elapsedClockSeconds)
LocomotiveAxle.DriveForceN = MotiveForceN; //Total force applied to wheels
LocomotiveAxle.TrainSpeedMpS = SpeedMpS; //Set the train speed of the axle mod
// The axle calculations must have a lower update interval to be accurate and stable
int integrationSteps = (int)Math.Max(elapsedClockSeconds / (LocomotiveAxle.InertiaKgm2 / MaxPowerW / 5.0f), 1);
int integrationSteps = (int)Math.Max(elapsedClockSeconds / (LocomotiveAxle.InertiaKgm2 / MaxForceN / 5), 1);
LocomotiveAxle.NumOfSubstepsPS = integrationSteps;
float avgAxleOutForceN=0;
for (int i=0; i< integrationSteps; i++)
for (int i=0; i < integrationSteps; i++)
{
LocomotiveAxle.Update(elapsedClockSeconds/ integrationSteps); //Main updater of the axle model
avgAxleOutForceN += LocomotiveAxle.CompensatedAxleForceN; //Get the Axle force and use it for the motion (use compensated value as it is independent of brake force)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,7 @@ public enum AxleDriveType
/// </summary>
public class Axle
{
/// <summary>
/// Integrator used for axle dynamic solving
/// </summary>
public Integrator AxleRevolutionsInt = new Integrator(0.0f, IntegratorMethods.RungeKutta4);

public MovingAverage FilterMovingAverage = new MovingAverage(10);
public MovingAverage CompensatedFilterMovingAverage = new MovingAverage(10);
public int NumOfSubstepsPS { get; set; }

/// <summary>
/// Brake force covered by BrakeForceN interface
Expand All @@ -74,11 +68,6 @@ public float BrakeRetardForceN
get { return brakeRetardForceN; }
}

/// <summary>
/// Total force to store sum of all functions
/// </summary>
protected float totalForceN;

/// <summary>
/// Damping force covered by DampingForceN interface
/// </summary>
Expand All @@ -92,13 +81,6 @@ public float BrakeRetardForceN

public float FrictionN { set { frictionN = Math.Abs(value); } get { return frictionN; } }

/// <summary>
/// Read/Write flag to enable/disable stability correction.
/// If enabled, AdhesionK is increased by 0.05 each time the slipSpeedDerivationPercent reaches 1000%/s
/// This causes the slip characteristics to be more flat what reduces oscilations.
/// </summary>
public bool StabilityCorrection { set; get; }

/// <summary>
/// Axle drive type covered by DriveType interface
/// </summary>
Expand Down Expand Up @@ -388,7 +370,7 @@ public float WheelSlipThresholdMpS
{
if (AdhesionK == 0.0f)
AdhesionK = 1.0f;
float umax = (CurtiusKnifflerA / (MpS.ToKpH(TrainSpeedMpS) + CurtiusKnifflerB) + CurtiusKnifflerC); // Curtius - Kniffler equation
float umax = (CurtiusKnifflerA / (MpS.ToKpH(Math.Abs(TrainSpeedMpS)) + CurtiusKnifflerB) + CurtiusKnifflerC); // Curtius - Kniffler equation
umax *= AdhesionConditions;
return MpS.FromKpH(AdhesionK / umax);
}
Expand Down Expand Up @@ -492,21 +474,16 @@ public Axle()
transmissionEfficiency = 0.99f;
SlipWarningTresholdPercent = 70.0f;
driveType = AxleDriveType.ForceDriven;
AxleRevolutionsInt.IsLimited = true;
Adhesion2 = 0.331455f;

switch (driveType)
{
case AxleDriveType.NotDriven:
break;
case AxleDriveType.MotorDriven:
AxleRevolutionsInt.Max = 5000.0f;
AxleRevolutionsInt.Min = -5000.0f;
totalInertiaKgm2 = inertiaKgm2 + transmissionRatio * transmissionRatio * motor.InertiaKgm2;
break;
case AxleDriveType.ForceDriven:
AxleRevolutionsInt.Max = 1000.0f;
AxleRevolutionsInt.Min = -1000.0f;
totalInertiaKgm2 = inertiaKgm2;
break;
default:
Expand All @@ -529,7 +506,6 @@ public Axle(ElectricMotor electricMotor)
motor.AxleConnected = this;
transmissionEfficiency = 0.99f;
driveType = AxleDriveType.MotorDriven;
AxleRevolutionsInt.IsLimited = true;
Adhesion2 = 0.331455f;

switch (driveType)
Expand All @@ -538,13 +514,9 @@ public Axle(ElectricMotor electricMotor)
totalInertiaKgm2 = inertiaKgm2;
break;
case AxleDriveType.MotorDriven:
AxleRevolutionsInt.Max = 5000.0f;
AxleRevolutionsInt.Min = -5000.0f;
totalInertiaKgm2 = inertiaKgm2 + transmissionRatio * transmissionRatio * motor.InertiaKgm2;
break;
case AxleDriveType.ForceDriven:
AxleRevolutionsInt.Max = 100.0f;
AxleRevolutionsInt.Min = -100.0f;
totalInertiaKgm2 = inertiaKgm2;
break;
default:
Expand Down Expand Up @@ -592,16 +564,9 @@ public void Save(BinaryWriter outf)
/// <param name="timeSpan"></param>
public virtual void Update(float timeSpan)
{

//Update axle force ( = k * loadTorqueNm)
axleForceN = AxleWeightN * SlipCharacteristics(AxleSpeedMpS - TrainSpeedMpS, TrainSpeedMpS, AdhesionK, AdhesionConditions, Adhesion2);

// The Axle module subtracts brake force from the motive force for calculation purposes. However brake force is already taken into account in the braking module.
// And thus there is a duplication of the braking effect in OR. To compensate for this, after the slip characteristics have been calculated, the output of the axle module
// has the brake force "added" back in to give the appropriate motive force output for the locomotive. Braking force is handled separately.
// Hence CompensatedAxleForce is the actual output force on the axle.
var compensateAxleForceN = axleForceN;

float motiveAxleForceN = -axleForceN;
if (driveType == AxleDriveType.ForceDriven)
motiveAxleForceN += driveForceN * transmissionEfficiency;
Expand Down Expand Up @@ -629,17 +594,20 @@ public virtual void Update(float timeSpan)
totalAxleForceN * axleDiameterM * axleDiameterM / 4
/ totalInertiaKgm2;
}
if ((prevSpeedMpS > 0 && axleSpeedMpS <= 0 /*&& motiveAxleForceN > -frictionalForceN*/) || (prevSpeedMpS < 0 && axleSpeedMpS >= 0/* && motiveAxleForceN < frictionalForceN*/))
if ((prevSpeedMpS > 0 && axleSpeedMpS <= 0 && motiveAxleForceN > -frictionalForceN) || (prevSpeedMpS < 0 && axleSpeedMpS >= 0 && motiveAxleForceN < frictionalForceN))
{
Reset();
axleSpeedMpS = 0;
}
// TODO: We should calculate brake force here
// Adding and substracting the brake force is correct for normal operation,
// but during wheelslip this will produce wrong results
if (axleSpeedMpS > 0) compensateAxleForceN = axleForceN + brakeRetardForceN;
else if (axleSpeedMpS < 0) compensateAxleForceN = axleForceN - brakeRetardForceN;
else compensateAxleForceN = 0;
// but during wheelslip this will produce wrong results.
// The Axle module subtracts brake force from the motive force for calculation purposes. However brake force is already taken into account in the braking module.
// And thus there is a duplication of the braking effect in OR. To compensate for this, after the slip characteristics have been calculated, the output of the axle module
// has the brake force "added" back in to give the appropriate motive force output for the locomotive. Braking force is handled separately.
// Hence CompensatedAxleForce is the actual output force on the axle.
if (axleSpeedMpS > 0) CompensatedAxleForceN = axleForceN + brakeRetardForceN;
else if (axleSpeedMpS < 0) CompensatedAxleForceN = axleForceN - brakeRetardForceN;
else CompensatedAxleForceN = 0;

if (driveType == AxleDriveType.MotorDriven)
{
Expand All @@ -654,27 +622,14 @@ public virtual void Update(float timeSpan)
slipDerivationPercentpS = (SlipSpeedPercent - previousSlipPercent) / timeSpan;
previousSlipPercent = SlipSpeedPercent;
}
//Stability Correction
/*if (StabilityCorrection)
{
if (slipDerivationPercentpS > 300.0f)
adhesionK += 0.0001f * slipDerivationPercentpS;
else
adhesionK = Math.Max(adhesionK_orig, adhesionK - 0.005f);
}*/

// Set output MotiveForce to actual value exclusive of brake force.
CompensatedAxleForceN = CompensatedFilterMovingAverage.Update(compensateAxleForceN);

//axleForceN = FilterMovingAverage.Update(axleForceN);
}

/// <summary>
/// Resets all integral values (set to zero)
/// </summary>
public void Reset()
{
AxleRevolutionsInt.Reset();
AxleSpeedMpS = 0;
adhesionK = adhesionK_orig;
if (motor != null)
motor.Reset();
Expand All @@ -687,10 +642,8 @@ public void Reset()
/// <param name="initValue">Initial condition</param>
public void Reset(double resetTime, float initValue)
{
AxleSpeedMpS = initValue;
ResetTime = resetTime;
AxleRevolutionsInt.InitialCondition = initValue;
AxleRevolutionsInt.Reset();
AxleRevolutionsInt.InitialCondition = 0.0f;
if (motor != null)
motor.Reset();
}
Expand Down Expand Up @@ -736,27 +689,5 @@ public float SlipCharacteristics(float slipSpeedMpS, float speedMpS, float K, fl
}
return 2.0f * K * umax * umax * (slipSpeedKpH / (umax * umax * slipSpeedKpH * slipSpeedKpH + K * K));
}

/// <summary>
/// Optional Friction computation function
/// - Computes Davis formula for given parameters:
/// Fo = Weight / 9810 * (A + B * V + C * V^2)
/// </summary>
/// <param name="A">Static friction parameter [N/kN]</param>
/// <param name="B">Rolling friction parameter [N/kN]</param>
/// <param name="C">Air friction parameter [N/kN]</param>
/// <param name="speedMpS">Speed in MpS</param>
/// <param name="weight">Weight in kg</param>
/// <returns>Friction force in Newtons, Returns zero for zero speed, Returns negative for negative speed</returns>
public static float Friction(float A, float B, float C, float speedMpS, float weight)
{
speedMpS *= 3.6f;
if (speedMpS == 0.0f)
return 0.0f;
if (speedMpS > 0.0f)
return weight / 1000.0f * 9.81f * (A + B * speedMpS + C * speedMpS * speedMpS);
else
return -weight / 1000.0f * 9.81f * (A + B * -1.0f * speedMpS + C * speedMpS * speedMpS);
}
}
}
11 changes: 4 additions & 7 deletions Source/RunActivity/Viewer3D/Popups/HUDWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ public override void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime, bo
ForceGraphDynamicForce.AddSample(-loco.MotiveForceN / loco.MaxForceN);
}

ForceGraphNumOfSubsteps.AddSample((float)loco.LocomotiveAxle.AxleRevolutionsInt.NumOfSubstepsPS / (float)loco.LocomotiveAxle.AxleRevolutionsInt.MaxSubsteps);
ForceGraphNumOfSubsteps.AddSample(loco.LocomotiveAxle.NumOfSubstepsPS);

ForceGraphs.PrepareFrame(frame);
}
Expand All @@ -310,8 +310,8 @@ public override void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime, bo
LocomotiveGraphsThrottle.AddSample(loco.ThrottlePercent * 0.01f);
if (locoD != null)
{
LocomotiveGraphsInputPower.AddSample(locoD.DieselEngines.MaxOutputPowerW / locoD.DieselEngines.MaxPowerW);
LocomotiveGraphsOutputPower.AddSample(locoD.DieselEngines.PowerW / locoD.DieselEngines.MaxPowerW);
LocomotiveGraphsInputPower.AddSample(locoD.DieselEngines.MaxOutputPowerW / locoD.DieselEngines.MaxPowerW);
LocomotiveGraphsOutputPower.AddSample(locoD.DieselEngines.PowerW / locoD.DieselEngines.MaxPowerW);
}
if (locoE != null)
{
Expand Down Expand Up @@ -1175,10 +1175,7 @@ void TextPageForceInfo(TableData table)
TableAddLabelValue(table, Viewer.Catalog.GetString("Axle drive force"), "{0} ({1})", FormatStrings.FormatForce(mstsLocomotive.LocomotiveAxle.DriveForceN, mstsLocomotive.IsMetric),
FormatStrings.FormatPower(mstsLocomotive.LocomotiveAxle.DriveForceN * mstsLocomotive.AbsTractionSpeedMpS, mstsLocomotive.IsMetric, false, false));
TableAddLabelValue(table, Viewer.Catalog.GetString("Axle brake force"), "{0}", FormatStrings.FormatForce(mstsLocomotive.LocomotiveAxle.BrakeRetardForceN, mstsLocomotive.IsMetric));
TableAddLabelValue(table, Viewer.Catalog.GetString("Number of substeps"), "{0:F0} ({1})", mstsLocomotive.LocomotiveAxle.AxleRevolutionsInt.NumOfSubstepsPS,
Viewer.Catalog.GetStringFmt("filtered by {0:F0}", mstsLocomotive.LocomotiveAxle.FilterMovingAverage.Size));
TableAddLabelValue(table, Viewer.Catalog.GetString("Solver"), "{0}", mstsLocomotive.LocomotiveAxle.AxleRevolutionsInt.Method.ToString());
TableAddLabelValue(table, Viewer.Catalog.GetString("Stability correction"), "{0:F0}", mstsLocomotive.LocomotiveAxle.AdhesionK);
TableAddLabelValue(table, Viewer.Catalog.GetString("Number of substeps"), "{0:F0}", mstsLocomotive.LocomotiveAxle.NumOfSubstepsPS);
TableAddLabelValue(table, Viewer.Catalog.GetString("Axle out force"), "{0} ({1})",
FormatStrings.FormatForce(mstsLocomotive.LocomotiveAxle.AxleForceN, mstsLocomotive.IsMetric),
FormatStrings.FormatPower(mstsLocomotive.LocomotiveAxle.AxleForceN * mstsLocomotive.AbsTractionSpeedMpS, mstsLocomotive.IsMetric, false, false));
Expand Down

0 comments on commit d6d28a9

Please sign in to comment.