54 lines
1.8 KiB
C#
54 lines
1.8 KiB
C#
// Components/Crankshaft.cs
|
||
using System;
|
||
|
||
namespace FluidSim.Components
|
||
{
|
||
public class Crankshaft
|
||
{
|
||
public double AngularVelocity { get; set; } // rad/s
|
||
public double CrankAngle { get; set; } // rad, 0 … 4π (four‑stroke cycle)
|
||
public double PreviousAngle { get; set; } // ← now has public setter
|
||
|
||
public double Inertia { get; set; } = 0.2;
|
||
public double FrictionConstant { get; set; } = 2.0; // N·m
|
||
public double FrictionViscous { get; set; } = 0.005; // N·m per rad/s
|
||
|
||
private double externalTorque;
|
||
|
||
public Crankshaft(double initialRPM = 400.0)
|
||
{
|
||
AngularVelocity = initialRPM * 2.0 * Math.PI / 60.0;
|
||
CrankAngle = 0.0;
|
||
PreviousAngle = 0.0;
|
||
}
|
||
|
||
public void AddTorque(double torque) => externalTorque += torque;
|
||
|
||
public void Step(double dt)
|
||
{
|
||
// Catch NaN before it propagates
|
||
if (double.IsNaN(AngularVelocity) || double.IsInfinity(AngularVelocity))
|
||
AngularVelocity = 0.0;
|
||
if (double.IsNaN(externalTorque) || double.IsInfinity(externalTorque))
|
||
externalTorque = 0.0;
|
||
|
||
PreviousAngle = CrankAngle;
|
||
|
||
double friction = FrictionConstant * Math.Sign(AngularVelocity) + FrictionViscous * AngularVelocity;
|
||
double netTorque = externalTorque - friction;
|
||
double alpha = netTorque / Inertia;
|
||
AngularVelocity += alpha * dt;
|
||
|
||
if (AngularVelocity < 0) AngularVelocity = 0;
|
||
|
||
CrankAngle += AngularVelocity * dt;
|
||
|
||
if (CrankAngle >= 4.0 * Math.PI)
|
||
CrankAngle -= 4.0 * Math.PI;
|
||
else if (CrankAngle < 0)
|
||
CrankAngle += 4.0 * Math.PI;
|
||
|
||
externalTorque = 0.0;
|
||
}
|
||
}
|
||
} |