fix: clean gitignore for Godot C#
This commit is contained in:
131
Scripts/Components/Engine.cs
Normal file
131
Scripts/Components/Engine.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
using System;
|
||||
|
||||
public class Engine : RotatingComponent
|
||||
{
|
||||
public double ThrottlePosition { get; set; }
|
||||
public double CurrentPower { get; private set; }
|
||||
public double CombustionPower { get; private set; }
|
||||
public int CylinderCount { get; private set; }
|
||||
public EngineControlUnit Ecu = new EngineControlUnit();
|
||||
|
||||
// Friction
|
||||
private const double _baseFriction = 12.0; // Seals, oil pump, valvetrain (Nm)
|
||||
private const double _linearFriction = 0.025; // Hydrodynamic bearing drag (Nm/(rad/s))
|
||||
private const double _quadraticFriction = 0.00002; // Windage & churning (Nm/(rad/s)²)
|
||||
|
||||
// Engine geometry
|
||||
private double _displacementCC;
|
||||
private double _compressionRatio;
|
||||
|
||||
// Volumetric efficiency tuning – now in rad/s
|
||||
public double VolumetricEfficiencyPeak { get; set; } = 1.15; // was 1.10
|
||||
public double AngularVelocityForVEPeak { get; set; } = 550.0; // 5250 RPM (rad/s = 550)
|
||||
public double AngularVelocityForVEMin { get; set; } = 800.0; // 7639 RPM
|
||||
public double VEminAtRedline { get; set; } = 0.85; // much higher at redline
|
||||
|
||||
// Physics constants
|
||||
private const double ATM_PRESSURE_KPA = 101.3;
|
||||
private const double AIR_DENSITY_KG_PER_M3 = 1.225;
|
||||
private const double FUEL_HEAT_VALUE_J_PER_KG = 43e6;
|
||||
private const double STOICHIOMETRIC_AIR_FUEL_RATIO = 14.7;
|
||||
|
||||
public Engine(double inertia, int cylinders, double displacementCC, double compressionRatio)
|
||||
{
|
||||
CylinderCount = cylinders;
|
||||
_displacementCC = displacementCC;
|
||||
_compressionRatio = compressionRatio;
|
||||
|
||||
MomentOfInertia = inertia;
|
||||
AngularVelocity = 100; // rad/s (~955 RPM)
|
||||
}
|
||||
|
||||
public override void Update(double dt)
|
||||
{
|
||||
Ecu.Update(dt, this);
|
||||
|
||||
ApplyThrottleTorque();
|
||||
ApplyFrictionTorque();
|
||||
|
||||
CurrentPower = AccumulatedTorque * AngularVelocity;
|
||||
|
||||
base.Update(dt);
|
||||
}
|
||||
|
||||
private double ComputeIndicatedTorque()
|
||||
{
|
||||
double w = AngularVelocity; // rad/s
|
||||
double throttle = Math.Clamp(ThrottlePosition, 0.0, 1.0);
|
||||
|
||||
// Volumetric Efficiency (WOT) as function of w (rad/s)
|
||||
double veWOT;
|
||||
if (w <= AngularVelocityForVEPeak)
|
||||
{
|
||||
// Start at a realistic 0.75 at zero RPM, peaking at your target
|
||||
double t = w / AngularVelocityForVEPeak;
|
||||
veWOT = 0.75 + (VolumetricEfficiencyPeak - 0.75) * t * (2 - t);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Linear drop from VE_peak to VEminAtRedline
|
||||
double t = (w - AngularVelocityForVEPeak) / (AngularVelocityForVEMin - AngularVelocityForVEPeak);
|
||||
t = Math.Clamp(t, 0.0, 1.0);
|
||||
veWOT = VolumetricEfficiencyPeak - t * (VolumetricEfficiencyPeak - VEminAtRedline);
|
||||
}
|
||||
veWOT = Math.Clamp(veWOT, 0.25, VolumetricEfficiencyPeak);
|
||||
|
||||
// Intake loss
|
||||
double maxEngineDemandSpeed = 700.0; // rad/s, roughly 6700 RPM
|
||||
double throttleArea = Math.Pow(throttle, 1.5);
|
||||
double engineDemand = (w / maxEngineDemandSpeed) * veWOT;
|
||||
|
||||
const double intakeResistance = 0.03; // was 0.5 – now physically realistic
|
||||
double mapFraction = throttleArea / (throttleArea + intakeResistance * engineDemand);
|
||||
|
||||
if (throttle == 0) mapFraction = 0;
|
||||
|
||||
double manifoldPressureKpa = ATM_PRESSURE_KPA * mapFraction;
|
||||
manifoldPressureKpa = Math.Clamp(manifoldPressureKpa, 0, ATM_PRESSURE_KPA);
|
||||
|
||||
double veActual = veWOT * (manifoldPressureKpa / ATM_PRESSURE_KPA);
|
||||
|
||||
// Exhaust loss (backpressure)
|
||||
double exhaustBackpressureKpa = 2.0e-5 * w * w;
|
||||
double exhaustLossFactor = 1.0 - Math.Min(0.25, exhaustBackpressureKpa / ATM_PRESSURE_KPA);
|
||||
|
||||
// Air & fuel mass per cycle
|
||||
double displacementM3 = _displacementCC * 1e-6;
|
||||
double airMassPerCycleKg = veActual * AIR_DENSITY_KG_PER_M3 * displacementM3;
|
||||
double fuelMassPerCycleKg = airMassPerCycleKg / STOICHIOMETRIC_AIR_FUEL_RATIO;
|
||||
double energyPerCycleJ = fuelMassPerCycleKg * FUEL_HEAT_VALUE_J_PER_KG;
|
||||
|
||||
// Thermal efficiency
|
||||
double gamma = 1.4;
|
||||
double ottoEfficiency = 1.0 - 1.0 / Math.Pow(_compressionRatio, gamma - 1.0);
|
||||
double thermalEfficiency = 0.65 * ottoEfficiency;
|
||||
|
||||
double workPerCycleJ = energyPerCycleJ * thermalEfficiency * exhaustLossFactor;
|
||||
|
||||
double indicatedTorque = workPerCycleJ / (4.0 * Math.PI);
|
||||
indicatedTorque = Math.Min(600.0, Math.Max(0.0, indicatedTorque));
|
||||
|
||||
return indicatedTorque;
|
||||
}
|
||||
|
||||
public void ApplyThrottleTorque()
|
||||
{
|
||||
double torque = ComputeIndicatedTorque();
|
||||
CombustionPower = torque * AngularVelocity;
|
||||
ApplyTorque(torque);
|
||||
}
|
||||
|
||||
public void ApplyFrictionTorque()
|
||||
{
|
||||
// Friction uses angular velocity (rad/s) directly
|
||||
double w = AngularVelocity;
|
||||
double frictionMag = _baseFriction
|
||||
+ _linearFriction * Math.Abs(w)
|
||||
+ _quadraticFriction * w * w;
|
||||
double frictionTorque = -Math.Sign(w) * frictionMag;
|
||||
ApplyTorque(frictionTorque);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user