Files
Car-Simulation/Car simulation/Drivetrain.cs
2026-01-14 17:29:48 +01:00

165 lines
6.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

namespace Car_simulation
{
public class Drivetrain
{
// Connected components
public Engine Engine { get; private set; }
public WheelSystem WheelSystem { get; private set; }
private int currentGear = 1;
public float[] GearRatios { get; set; } =
{
3.8f, // 1st
2.5f, // 2nd
1.8f, // 3rd
1.3f, // 4th
1.0f, // 5th
0.8f, // 6th
0.65f // 7th
};
public float FinalDriveRatio { get; set; } = 4.0f;
public float Efficiency { get; set; } = 0.95f;
public float ClutchEngagement { get; set; } = 0f; // 0 = disengaged, 1 = fully engaged
// Clutch properties
public float MaxClutchTorque { get; set; } = 400f;
public float ClutchStiffness { get; set; } = 50f;
// State
public float ClutchTorque { get; private set; }
public float TransmittedPower { get; private set; }
public float ClutchSlipRatio { get; private set; }
public Drivetrain(Engine engine, WheelSystem wheelSystem)
{
Engine = engine;
WheelSystem = wheelSystem;
}
public void Update(float deltaTime)
{
if (ClutchEngagement <= 0.01f || TotalRatio == 0)
{
ClutchTorque = 0;
TransmittedPower = 0;
ClutchSlipRatio = 1f;
return;
}
// Calculate expected vs actual wheel speeds
float expectedWheelOmega = Engine.AngularVelocity / TotalRatio;
float actualWheelOmega = WheelSystem.AngularVelocity;
float omegaDifference = actualWheelOmega - expectedWheelOmega;
// Calculate max torque clutch can transmit
float maxClutchTorque = MaxClutchTorque * ClutchEngagement;
// Simple spring model: torque tries to sync speeds
float desiredTorque = -omegaDifference * ClutchStiffness;
// Clamp to clutch capacity
desiredTorque = Math.Clamp(desiredTorque, -maxClutchTorque, maxClutchTorque);
// Also limit by engine capability when accelerating
if (desiredTorque > 0)
{
float engineTorque = Engine.GetTorqueOutput() * Engine.GetActualThrottle();
float maxEngineTorqueAtWheels = engineTorque * TotalRatio * Efficiency;
desiredTorque = Math.Min(desiredTorque, maxEngineTorqueAtWheels);
}
ClutchTorque = desiredTorque;
// Calculate energy transfer based on torque
float energyTransferred = 0f;
if (omegaDifference > 0.01f) // Wheels → Engine (engine braking)
{
// Power = torque × angular velocity (at slower side - engine)
float power = ClutchTorque * (Engine.AngularVelocity);
energyTransferred = power * deltaTime;
// Wheels lose energy, engine gains (minus efficiency losses)
float wheelEnergyLoss = Math.Abs(energyTransferred);
float engineEnergyGain = wheelEnergyLoss * Efficiency;
WheelSystem.TotalEnergy -= wheelEnergyLoss;
Engine.FlywheelEnergy += engineEnergyGain;
}
else if (omegaDifference < -0.01f) // Engine → Wheels (acceleration)
{
// Power = torque × angular velocity (at faster side - engine)
float power = -ClutchTorque * Engine.AngularVelocity; // Negative torque, positive power
energyTransferred = power * deltaTime;
// Engine loses energy, wheels gain
float engineEnergyLoss = Math.Abs(energyTransferred);
float wheelEnergyGain = engineEnergyLoss * Efficiency;
Engine.FlywheelEnergy -= engineEnergyLoss;
WheelSystem.TotalEnergy += wheelEnergyGain;
}
else
{
// Nearly synchronized
energyTransferred = 0;
}
// Calculate transmitted power
TransmittedPower = energyTransferred / deltaTime;
// Calculate clutch slip CORRECTLY:
// Slip = 0 when torque < max torque (clutch can handle it)
// Slip = 1 when torque = max torque (clutch is slipping)
if (maxClutchTorque > 0)
{
float torqueRatio = Math.Abs(ClutchTorque) / maxClutchTorque;
// If we're transmitting max torque, clutch is slipping
// If we're transmitting less, clutch is gripping
ClutchSlipRatio = torqueRatio; // 0 = no slip, 1 = full slip
}
else
{
ClutchSlipRatio = 1f;
}
}
// Other methods...
public float GearRatio => GetCurrentGearRatio();
public float TotalRatio => GearRatio * FinalDriveRatio;
private float GetCurrentGearRatio()
{
if (currentGear == 0) return 0f;
if (currentGear == -1) return -3.5f;
if (currentGear > 0 && currentGear <= GearRatios.Length)
return GearRatios[currentGear - 1];
return 0f;
}
public float GetSpeedDifferenceRPM()
{
float expectedWheelOmega = Engine.AngularVelocity / TotalRatio;
float actualWheelOmega = WheelSystem.AngularVelocity;
return (actualWheelOmega - expectedWheelOmega) * PhysicsUtil.RAD_PER_SEC_TO_RPM;
}
public string GetCurrentGearName()
{
return currentGear switch
{
-1 => "R",
0 => "N",
_ => currentGear.ToString()
};
}
public float GetClutchSlipPercent()
{
return ClutchSlipRatio * 100f;
}
public void GearUp() { if (currentGear < GearRatios.Length) currentGear++; }
public void GearDown() { if (currentGear > 1) currentGear--; }
}
}