// Update is called once per frame void FixedUpdate() { foreach (Particle2DLink it in linkList) { it.CreateContacts(particleList[it.id1], particleList[it.id2]); } ContactResolver resolver = new ContactResolver(); resolver.resolveContacts(contacts); for (int i = 0; i < particleList.Count; i++) { if (particleList[i] != null) { if (Vector2.Distance(particleList[i].transform.position, target.transform.position) <= .5) { particleList[i].GetComponent <Particle2D>().Remove(); target.GetComponent <Target>().GetHit(); } Integrator.Integrate(particleList[i]); } } foreach (int itr in destroyList) { Destroy(particleList[itr]); particleList[itr] = null; } destroyList.Clear(); }
protected override double CreateMatrixElement( BoundaryElement <T> elem1, BoundaryElement <T> elem2, ConditionType conditionType) { if (conditionType == ConditionType.Robin) { var IsExponental = true; if (IsExponental) { var enumerator = KirghoffTransformation.U0 * KirghoffTransformation.U0 * KirghoffTransformation.LAMDA0 * Integrator.Integrate(elem1, elem2.Center, FundamentalSolution); var denumerator = KirghoffTransformation.BETALAMDA * KirghoffTransformation.BETALAMDA * (U(elem2.Center, solution) + 1); return(KirghoffTransformation.Nuv(elem2.Center) * enumerator / denumerator - 0.5 * Kroneker(elem1, elem2) + Integrator.IntegratedQdnx(elem1, elem2, Derivates)); } else { var enumerator = Integrator.Integrate(elem1, elem2.Center, FundamentalSolution); var denumerator = Math.Sqrt( 1 + 2 * KirghoffTransformation.BETALAMDA * U(elem2.Center, solution) / (KirghoffTransformation.LAMDA0 * KirghoffTransformation.U0)); return(KirghoffTransformation.Nuv(elem2.Center) * enumerator / (KirghoffTransformation.LAMDA0 * denumerator) - 0.5 * Kroneker(elem1, elem2) + Integrator.IntegratedQdnx(elem1, elem2, Derivates)); } } else { return(0); } }
public void Execute() { float gravityLengthInOneStep = math.length(Gravity * TimeStep); for (int i = 0; i < MotionVelocities.Length; i++) { var motionData = MotionDatas[i]; var motionVelocity = MotionVelocities[i]; // Clip velocities using a simple heuristic: // zero out velocities that are smaller than gravity in one step if (math.length(motionVelocity.LinearVelocity) < motionVelocity.GravityFactor * gravityLengthInOneStep) { // Revert integration Integrator.Integrate(ref motionData.WorldFromMotion, motionVelocity, -TimeStep); // Clip velocity motionVelocity.LinearVelocity = float3.zero; motionVelocity.AngularVelocity = float3.zero; // Write back MotionDatas[i] = motionData; MotionVelocities[i] = motionVelocity; } } }
protected override double CreateMatrixElement( BoundaryElement <T> elem1, BoundaryElement <T> elem2, ConditionType conditionType) { double sum = 1; switch (conditionType) { case ConditionType.Pow: var derivate2 = Integrator.Integrate(elem1, elem2.Center, Derivates); var enumerator = Integrator.Integrate(elem1, elem2.Center, FundamentalSolution); var denumerator = Math.Sqrt( 1 + 2 * KirghoffTransformation.BETALAMDA * sum / (KirghoffTransformation.LAMDA0 * KirghoffTransformation.U0)); return(KirghoffTransformation.Nuv(elem2.Center) * enumerator / (KirghoffTransformation.LAMDA0 * denumerator) - 0.5 * Kroneker(elem1, elem2) + derivate2.ScalarMultiply(elem1.Normal)); case ConditionType.Exp: return(0); } return(double.NaN); }
public State Update(double step, State currentState) { State tempState = Integrator.Integrate(currentState, step); DistributeFuelConsumption((ImmediateHourlyFuelConsumption() / 3600) * step); return(tempState); }
public virtual void Update(double timeSpan) { //revolutionsRad += timeSpan / inertiaKgm2 * (developedTorqueNm + loadTorqueNm + (revolutionsRad == 0.0 ? 0.0 : frictionTorqueNm)); //if (revolutionsRad < 0.0) // revolutionsRad = 0.0; temperatureK = (float)tempIntegrator.Integrate(timeSpan, 1.0 / (SpecificHeatCapacityJ_kg_C * WeightKg) * ((powerLossesW - CoolingPowerW) / (ThermalCoeffJ_m2sC * SurfaceM) - temperatureK)); }
// Update is called once per frame void FixedUpdate() { foreach (Particle2DLink it in linkList) { it.CreateContacts(particleManager.GetParticle(it.id1), particleManager.GetParticle(it.id2), contactPrefab); } resolver.resolveContacts(contacts); particleManager.ParticleUpdate(); for (int i = 0; i < particleManager.GetCount(); i++) { if (particleManager.GetParticle(i) != null) { if (Vector2.Distance(particleManager.GetParticle(i).transform.position, target.transform.position) <= .5) { particleManager.GetParticle(i).GetComponent <Particle2D>().Remove(); target.GetComponent <Target>().GetHit(); } Integrator.Integrate(particleManager.GetParticle(i)); } } foreach (int itr in destroyList) { particleManager.RemoveParticle(itr); } destroyList.Clear(); frame += .016f; if (frame >= .25) { MakeRandomProjectile(randomParticle); frame = 0; } }
protected override double CreateMatrixElement(BoundaryElement <T> elem1, BoundaryElement <T> elem2, ConditionType conditionType) { switch (conditionType) { case ConditionType.Dirichlet: if (elem1.Bound.IsOuter && elem2.Bound.IsOuter) { return(Integrator.Integrate(elem1, elem2.Center, FundamentalSolution)); } if (elem1.Bound.IsOuter && !elem2.Bound.IsOuter) { return(Integrator.IntegratedQdnx(elem1, elem2, Derivates)); } if (!elem1.Bound.IsOuter && elem2.Bound.IsOuter) { return(Integrator.IntegratedQdny(elem1, elem2, Derivates)); } if (!elem1.Bound.IsOuter && !elem2.Bound.IsOuter) { return(lambda * Kroneker(elem1, elem2) + Integrator.IntegratedQdnxdny(elem1, elem2, Derivates)); } break; } return(double.NaN); }
protected override double CreateMatrixElement(BoundaryElement <T> elem1, BoundaryElement <T> elem2, ConditionType conditionType) { switch (conditionType) { case ConditionType.Dirichlet: return(Integrator.Integrate(elem1, elem2, FundamentalSolution)); } return(double.NaN); }
public double U(Point3D x, BoundaryElement <Point3D> elem, int boundNumber, int boundElem, int count) { if (elem.Bound.Name == BoundNumber.Bound12) { return(Integrator.Integrate(elem, x, functionsForSemiSpace.U1) * Solution[boundElem]); } if (elem.Bound.Name == BoundNumber.Bound13) { return(Integrator.Integrate(elem, x, functionsForSemiSpace.U1) * Solution[boundNumber * count + boundElem]); } return(0); }
public override double U(T x) { return(CalculateSolutiuon(Solution, (bound, element) => { if (bound.IsOuter) { return -1 * Integrator.IntegratedQdny(element, x, Derivates); } return Integrator.Integrate(element, x, FundamentalSolution); })); }
private double InnerSourceImplact(T x) { double res = 0; foreach (var innerSource in InnerSources) { foreach (var elem in innerSource.Bound.Elements) { res += Integrator.Integrate(elem, x, innerSource.Function, FundamentalSolution); } } return(res); }
// Update is called once per frame void Update() { mContacts.Clear(); foreach (var link in mParticleLinks) { link.CreateContacts(mContacts); } mResolver.SetIterations(10); mResolver.ResolveContacts(mContacts, Time.deltaTime); mForceManager.UpdateForceGenerators(); mIntegrator.Integrate(Time.deltaTime); CheckBounds(); }
public virtual double GetLength(double t0, double t1) { Contract.Assert(t0 <= t1); if (t0 < this.TMin) { t0 = this.TMin; } if (t1 > this.TMax) { t1 = this.TMax; } return(Integrator.Integrate(this.GetSpeed, t0, t1, Integrator.Type.RombergIntegrator, IntegralMaxEval)); }
protected override double CreateMatrixElement(BoundaryElement <T> elem1, BoundaryElement <T> elem2, ConditionType conditionType) { switch (conditionType) { case ConditionType.Dirichlet: return(Integrator.Integrate(elem1, elem2.Center, FundamentalSolution)); case ConditionType.Neumann: return(Integrator.IntegratedQdnx(elem1, elem2, Derivates)); case ConditionType.Robin: return(Integrator.Integrate(elem1, elem2.Center, FundamentalSolution) - Integrator.IntegratedQdnx(elem1, elem2, Derivates)); } return(double.NaN); }
public void IntegrateTest() { double a = 5; int n = 2; var target = new Integrator <Point3D>(n); BoundaryElement2DFirstOrder elem = new BoundaryElement2DFirstOrder( new Point3D(), new Point3D(0, 0, a), new Point3D(0, a, a), new Point3D(0, a, 0), new Point3D(0, a / 2, a / 2)); Point3D eta = new Point3D(); Func <Point3D, Point3D, double> f = (p1, p2) => 1; double expected = a * a; double actual; actual = target.Integrate(elem, eta, f); Assert.AreEqual(expected, actual); }
private void FixedUpdate() { ForceManager.ApplyForce(this); Integrator.Integrate(this); }
public void Integrate_WithConstantFunction_ReturnsCorrectArea(double expectedArea, int c, int steps) { var area = Integrator.Integrate(x => c, steps); Assert.Equal(expectedArea, area); }
void FixedUpdate() { float dt = Time.fixedDeltaTime; Integrator.Integrate(ref mpPhysicsData, dt); }
public void Integrate_WithLinearFunction_ReturnsCorrectArea(double expectedArea, int a, int b, int steps) { var area = Integrator.Integrate(x => x * a + b, steps); Assert.Equal(expectedArea, area); }
protected virtual double GetLength(int key, double dt0, double dt1) { Contract.Assert(dt0 <= dt1); return(Integrator.Integrate(t => this.GetSpeed(key, t), dt0, dt1, Integrator.Type.RombergIntegrator, IntegralMaxEval)); }
private static bool Integration() { Console.Write("Введите левый конец отрезка интегрирования: "); var left = 0d; while (!double.TryParse(Console.ReadLine(), out left) || !left.IsNumber()) { Console.Write("Некорректное значение: введите вещественное число: "); } Console.Write("Введите правый конец отрезка интегрирования: "); var right = 0d; while (!double.TryParse(Console.ReadLine(), out right) || !right.IsNumber() || right <= left) { Console.Write("Некорректное значение: введите вещественное число, большее левого конца отрезка интегрирования: "); } Console.Write("Введите число промежутков деления отрезка интегрирования: "); var segmentNumber = 0; while (!int.TryParse(Console.ReadLine(), out segmentNumber) || segmentNumber <= 0) { Console.Write("Некорректное значение: введите положительное целое число: "); } var segmentLength = (right - left) / segmentNumber; Func <double, double> composition = (x => Weight(x) * Function(x)); var integral = Integrator.Integrate(composition, left, right, segmentNumber); var precise = (Antiderivative(right) - Antiderivative(left)); Func <double, int, double> theoreticalError = (c, d) => { return((right - left) * MonotonousFunctionAbsMax(Derivative(d), left, right) * c * Math.Pow(segmentLength, d)); }; Console.WriteLine($"\nФункция: f(x) = exp(x) + x"); Console.WriteLine($"Отрезок интегрирования: [{left.Format(5)}, {right.Format(5)}]"); Console.WriteLine($"Число отрезков деления: {segmentNumber}"); Console.WriteLine($"Длина отрезка: {segmentLength.Format()}\n"); Console.WriteLine($"Точное значение интеграла: {precise.Format()}\n"); Console.WriteLine( $"Формула левых прямоугольников\n" + $"Вычисленное приближенное значение: {integral.LeftRecangle.Format()}\n" + $"Абсолютная фактическая погрешность: {Math.Abs(integral.LeftRecangle - precise).Format()}\n" + $"Теоретическая погрешность: {theoreticalError(LeftConst, LeftDegree + 1).Format()}\n\n" + $"Формула правых прямоугольников\n" + $"Вычисленное приближенное значение: {integral.RightRecangle.Format()}\n" + $"Абсолютная фактическая погрешность: {Math.Abs(integral.RightRecangle - precise).Format()}\n" + $"Теоретическая погрешность: {theoreticalError(RightConst, RightDegree + 1).Format()}\n\n" + $"Формула средних прямоугольников\n" + $"Вычисленное приближенное значение: {integral.MiddleRecangle.Format()}\n" + $"Абсолютная фактическая погрешность: {Math.Abs(integral.MiddleRecangle - precise).Format()}\n" + $"Теоретическая погрешность: {theoreticalError(MiddleConst, MiddleDegree + 1).Format()}\n\n" + $"Формула трапеций\n" + $"Вычисленное приближенное значение: {integral.Trapezoidal.Format()}\n" + $"Абсолютная фактическая погрешность: {Math.Abs(integral.Trapezoidal - precise).Format()}\n" + $"Теоретическая погрешность: {theoreticalError(TrapezoidalConst, TrapezoidalDegree + 1).Format()}\n\n" + $"Формула Симпсона\n" + $"Вычисленное приближенное значение: {integral.Simpsons.Format()}\n" + $"Абсолютная фактическая погрешность: {Math.Abs(integral.Simpsons - precise).Format()}\n" + $"Теоретическая погрешность: {theoreticalError(SimpsonsConst, SimpsonsDegree + 1).Format()}\n"); Console.WriteLine($"\nЧтобы выйти, нажмите \'Esc\'\n"); if (Console.ReadKey().Key == ConsoleKey.Escape) { return(false); } return(true); }
protected virtual double GetLength(int index, double tInSegment0, double tInSegment1) { Contract.Assert(tInSegment0 <= tInSegment1); return(Integrator.Integrate(t => this.GetSpeed(index, t), tInSegment0, tInSegment1, Integrator.Type.RombergIntegrator, IntegralMaxEval)); }
protected override double CreateMatrixElement(BoundaryElement <Point3D> elem1, BoundaryElement <Point3D> elem2, ConditionType conditionType) { if (elem1.Bound.Name == BoundNumber.Bound12 && elem2.Bound.Name == BoundNumber.Bound12) { return(Integrator.Integrate(elem1, elem2.Center, functionsForSemiSpace.U1)); } if (elem1.Bound.Name == BoundNumber.Bound12 && elem2.Bound.Name == BoundNumber.Bound2) { return(-Integrator.Integrate(elem1, elem2.Center, functionsForSemiSpace.U2)); } if (elem1.Bound.Name == BoundNumber.Bound12 && elem2.Bound.Name == BoundNumber.Bound13) { return(Integrator.Integrate(elem1, elem2.Center, functionsForSemiSpace.U1)); } if (elem1.Bound.Name == BoundNumber.Bound12 && elem2.Bound.Name == BoundNumber.Bound3) { return(0); } //2----------------------------------------------- if (elem1.Bound.Name == BoundNumber.Bound2 && elem2.Bound.Name == BoundNumber.Bound12) { return(Integrator.IntegratedQdnx(elem1, elem2, FunctionsForSemiSpace.Derivates)); } if (elem1.Bound.Name == BoundNumber.Bound2 && elem2.Bound.Name == BoundNumber.Bound2) { return(-Integrator.IntegratedQdnx(elem1, elem2, FunctionFactory.Derivates)); } if (elem1.Bound.Name == BoundNumber.Bound2 && elem2.Bound.Name == BoundNumber.Bound13) { return(Integrator.IntegratedQdnx(elem1, elem2, FunctionsForSemiSpace.Derivates)); } if (elem1.Bound.Name == BoundNumber.Bound2 && elem2.Bound.Name == BoundNumber.Bound3) { return(0); } //3----------------------------------------------- if (elem1.Bound.Name == BoundNumber.Bound13 && elem2.Bound.Name == BoundNumber.Bound12) { return(Integrator.Integrate(elem1, elem2.Center, functionsForSemiSpace.U1)); } if (elem1.Bound.Name == BoundNumber.Bound13 && elem2.Bound.Name == BoundNumber.Bound2) { return(0); } if (elem1.Bound.Name == BoundNumber.Bound13 && elem2.Bound.Name == BoundNumber.Bound13) { return(Integrator.Integrate(elem1, elem2.Center, functionsForSemiSpace.U1)); } if (elem1.Bound.Name == BoundNumber.Bound13 && elem2.Bound.Name == BoundNumber.Bound3) { return(-(Integrator.Integrate(elem1, elem2.Center, functionsForSemiSpace.U3))); } //4------------------------------------------------ if (elem1.Bound.Name == BoundNumber.Bound3 && elem2.Bound.Name == BoundNumber.Bound12) { return(Integrator.IntegratedQdnx(elem1, elem2, FunctionsForSemiSpace.Derivates)); } if (elem1.Bound.Name == BoundNumber.Bound3 && elem2.Bound.Name == BoundNumber.Bound2) { return(0); } if (elem1.Bound.Name == BoundNumber.Bound3 && elem2.Bound.Name == BoundNumber.Bound13) { return(Integrator.IntegratedQdnx(elem1, elem2, FunctionsForSemiSpace.Derivates)); } if (elem1.Bound.Name == BoundNumber.Bound3 && elem2.Bound.Name == BoundNumber.Bound3) { return(-Integrator.IntegratedQdnx(elem1, elem2, FunctionFactory.Derivates)); } throw new Exception("Invalid boundaries"); }
protected override double CreateVectorElement(BoundaryElement <T> elem1, Func <T, double> function, ConditionType conditionType) { return(Integrator.Integrate(elem1, function)); }
/// <summary> /// Main Update method /// - computes slip characteristics to get new axle force /// - computes axle dynamic model according to its driveType /// - computes wheelslip indicators /// </summary> /// <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; switch (driveType) { case AxleDriveType.NotDriven: //Axle revolutions integration axleSpeedMpS = AxleRevolutionsInt.Integrate(timeSpan, axleDiameterM * axleDiameterM / (4.0f * (totalInertiaKgm2)) * (2.0f * transmissionRatio / axleDiameterM * (-Math.Abs(brakeRetardForceN)) - AxleForceN)); break; case AxleDriveType.MotorDriven: //Axle revolutions integration if (TrainSpeedMpS == 0.0f) { dampingNs = 0.0f; brakeRetardForceN = 0.0f; } axleSpeedMpS = AxleRevolutionsInt.Integrate(timeSpan, axleDiameterM * axleDiameterM / (4.0f * (totalInertiaKgm2)) * (2.0f * transmissionRatio / axleDiameterM * motor.DevelopedTorqueNm * transmissionEfficiency - Math.Abs(brakeRetardForceN) - (axleSpeedMpS > 0.0 ? Math.Abs(dampingNs) : 0.0f)) - AxleForceN); //update motor values motor.RevolutionsRad = axleSpeedMpS * 2.0f * transmissionRatio / (axleDiameterM); motor.Update(timeSpan); break; case AxleDriveType.ForceDriven: //Axle revolutions integration if (TrainSpeedMpS > 0.01f) { axleSpeedMpS = AxleRevolutionsInt.Integrate(timeSpan, ( driveForceN * transmissionEfficiency - brakeRetardForceN - slipDerivationMpSS * dampingNs - Math.Abs(SlipSpeedMpS) * frictionN - AxleForceN ) / totalInertiaKgm2 ); compensateAxleForceN = axleForceN + brakeRetardForceN; if (Math.Abs(compensateAxleForceN) > Math.Abs(driveForceN)) { compensateAxleForceN = driveForceN; } if (brakeRetardForceN > driveForceN && AxleSpeedMpS < 0.1f) { axleSpeedMpS = 0.0f; axleForceN = -brakeRetardForceN + driveForceN; compensateAxleForceN = driveForceN; } } else if (TrainSpeedMpS < -0.01f) { axleSpeedMpS = AxleRevolutionsInt.Integrate(timeSpan, ( driveForceN * transmissionEfficiency + brakeRetardForceN - slipDerivationMpSS * dampingNs + Math.Abs(SlipSpeedMpS) * frictionN - AxleForceN ) / totalInertiaKgm2 ); compensateAxleForceN = axleForceN - brakeRetardForceN; if (Math.Abs(compensateAxleForceN) > Math.Abs(driveForceN)) { compensateAxleForceN = driveForceN; } if (brakeRetardForceN > Math.Abs(driveForceN) && AxleSpeedMpS > -0.1f) { axleSpeedMpS = 0.0f; axleForceN = brakeRetardForceN - driveForceN; compensateAxleForceN = driveForceN; } } else { if (Math.Abs(driveForceN) < 1f) { Reset(); axleSpeedMpS = 0.0f; //axleForceN = 0.0f; } else { axleForceN = driveForceN - brakeRetardForceN; compensateAxleForceN = driveForceN; if (Math.Abs(axleSpeedMpS) < 0.01f) { Reset(); } } //Reset(TrainSpeedMpS); //axleForceN = driveForceN - brakeRetardForceN; //axleSpeedMpS = AxleRevolutionsInt.Value; } break; default: totalInertiaKgm2 = inertiaKgm2; break; } if (timeSpan > 0.0f) { slipDerivationMpSS = (SlipSpeedMpS - previousSlipSpeedMpS) / timeSpan; previousSlipSpeedMpS = SlipSpeedMpS; slipDerivationPercentpS = (SlipSpeedPercent - previousSlipPercent) / timeSpan; previousSlipPercent = SlipSpeedPercent; } //Stability Correction if (StabilityCorrection) { if (slipDerivationPercentpS > 300.0f) { adhesionK += 0.0001f * slipDerivationPercentpS; } else { adhesionK = (adhesionK <= 0.7f) ? 0.7f : (adhesionK - 0.005f); } } // Set output MotiveForce to actual value exclusive of brake force. compensatedaxleForceN = CompensatedFilterMovingAverage.Update(Math.Abs(compensatedaxleForceN) > Math.Abs(driveForceN) ? driveForceN : compensateAxleForceN); axleForceN = FilterMovingAverage.Update(Math.Abs(axleForceN) > Math.Abs(driveForceN) ? driveForceN : axleForceN); }
public double U(T x, Vector solution) { return(CalculateSolutiuon( solution, (bound, element) => Integrator.Integrate(element, x, FundamentalSolution)) + InnerSourceImplact(x)); }
public virtual void Update() { //sum spring forces foreach (List <Spring> sprList in springList) { foreach (Spring spring in sprList) { spring.ApplyForce(null); } } foreach (List <SimMass> objList in simObjects) { //sum global forces on all objects foreach (SimMass simObject in objList) { if (simObject.SimObjectType == SimObjectType.ACTIVE) { foreach (ForceGenerator forceGenerator in globalForceGenerators) { forceGenerator.ApplyForce(simObject); } } } foreach (SimMass simObject in objList) { if (simObject.SimObjectType == SimObjectType.ACTIVE) { //find acceleration acceleration = simObject.ResultantForce / simObject.Mass; //integrate integrator.Integrate(acceleration, simObject); } } //do constraint calculations int constraintInterations = 1; for (int i = 0; i < constraintInterations; i++) { foreach (List <LengthConstraint> constraints in constraintsList) { foreach (LengthConstraint constraint in constraints) { constraint.SatisfyConstraint(); } } } //update objects foreach (SimMass simObject in objList) { simObject.Update(); } //reset forces on each object foreach (SimMass simObject in objList) { simObject.ResetForces(); } } }
// Update is called once per frame void Update() { //mForceManager.UpdateForceGenerators(); gravityForceGenerator.UpdateForce(); mIntegrator.Integrate(Time.deltaTime); }
/// <summary> /// Main Update method /// - computes slip characteristics to get new axle force /// - computes axle dynamic model according to its driveType /// - computes wheelslip indicators /// </summary> /// <param name="timeSpan"></param> public virtual void Update(float timeSpan) { //Update axle force ( = k * loadTorqueNm) axleForceN = AxleWeightN * SlipCharacteristics(AxleSpeedMpS - TrainSpeedMpS, TrainSpeedMpS, AdhesionK, AdhesionConditions, Adhesion2); switch (driveType) { case AxleDriveType.NotDriven: //Axle revolutions integration axleSpeedMpS = AxleRevolutionsInt.Integrate(timeSpan, axleDiameterM * axleDiameterM / (4.0f * (totalInertiaKgm2)) * (2.0f * transmissionRatio / axleDiameterM * (-Math.Abs(brakeRetardForceN)) - AxleForceN)); break; case AxleDriveType.MotorDriven: //Axle revolutions integration if (TrainSpeedMpS == 0.0f) { dampingNs = 0.0f; brakeRetardForceN = 0.0f; } axleSpeedMpS = AxleRevolutionsInt.Integrate(timeSpan, axleDiameterM * axleDiameterM / (4.0f * (totalInertiaKgm2)) * (2.0f * transmissionRatio / axleDiameterM * motor.DevelopedTorqueNm * transmissionEfficiency - Math.Abs(brakeRetardForceN) - (axleSpeedMpS > 0.0 ? Math.Abs(dampingNs) : 0.0f)) - AxleForceN); //update motor values motor.RevolutionsRad = axleSpeedMpS * 2.0f * transmissionRatio / (axleDiameterM); motor.Update(timeSpan); break; case AxleDriveType.ForceDriven: //Axle revolutions integration if (TrainSpeedMpS > 0.01f) { axleSpeedMpS = AxleRevolutionsInt.Integrate(timeSpan, ( driveForceN * transmissionEfficiency - brakeRetardForceN - slipDerivationMpSS * dampingNs - Math.Abs(SlipSpeedMpS) * frictionN - AxleForceN ) / totalInertiaKgm2 ); if (brakeRetardForceN > driveForceN && AxleSpeedMpS < 0.1f) { axleSpeedMpS = 0.0f; axleForceN = -brakeRetardForceN + driveForceN; } } else if (TrainSpeedMpS < -0.01f) { axleSpeedMpS = AxleRevolutionsInt.Integrate(timeSpan, ( driveForceN * transmissionEfficiency + brakeRetardForceN - slipDerivationMpSS * dampingNs + Math.Abs(SlipSpeedMpS) * frictionN - AxleForceN ) / totalInertiaKgm2 ); if (brakeRetardForceN > Math.Abs(driveForceN) && AxleSpeedMpS > -0.1f) { axleSpeedMpS = 0.0f; axleForceN = brakeRetardForceN - driveForceN; } } else { if (Math.Abs(driveForceN) < 1f) { Reset(); axleSpeedMpS = 0.0f; //axleForceN = 0.0f; } else { axleForceN = driveForceN - brakeRetardForceN; if (Math.Abs(axleSpeedMpS) < 0.01f) { Reset(); } } //Reset(TrainSpeedMpS); //axleForceN = driveForceN - brakeRetardForceN; //axleSpeedMpS = AxleRevolutionsInt.Value; } break; default: totalInertiaKgm2 = inertiaKgm2; break; } if (timeSpan > 0.0f) { slipDerivationMpSS = (SlipSpeedMpS - previousSlipSpeedMpS) / timeSpan; previousSlipSpeedMpS = SlipSpeedMpS; slipDerivationPercentpS = (SlipSpeedPercent - previousSlipPercent) / timeSpan; previousSlipPercent = SlipSpeedPercent; } //Stability Correction if (StabilityCorrection) { if (slipDerivationPercentpS > 300.0f) { adhesionK += 0.0001f * slipDerivationPercentpS; } else { adhesionK = (adhesionK <= 0.7f) ? 0.7f : (adhesionK - 0.005f); } } axleForceN = FilterMovingAverage.Update(Math.Abs(axleForceN) > Math.Abs(driveForceN) ? driveForceN : axleForceN); }