using System; public abstract class RotatingComponent { public double MomentOfInertia { get; set; } // kg·m² public double AngularVelocity { get; set; } // rad/s public double AngularPosition { get; set; } // rad (0..2π, wrapped) public double TotalAngularPosition { get; set; } // rad (never wraps) public double AccumulatedTorque {get; private set; } public RotatingComponent(double momentOfInertia = 0.1, double angularVelocity = 0, double angularPosition = 0) { MomentOfInertia = momentOfInertia; AngularVelocity = angularVelocity; AngularPosition = angularPosition; TotalAngularPosition = angularPosition; AccumulatedTorque = 0; } public virtual void ApplyTorque(double torqueNm) { AccumulatedTorque += torqueNm; } public virtual void Update(double dt) { if (dt <= 0) return; if (MomentOfInertia > 0) { double angularAcceleration = AccumulatedTorque / MomentOfInertia; AngularVelocity += angularAcceleration * dt; } double deltaAngle = AngularVelocity * dt; TotalAngularPosition += deltaAngle; AngularPosition += deltaAngle; // Wrap AngularPosition to 0..2π for sin/cos AngularPosition = AngularPosition % (2 * Math.PI); if (AngularPosition < 0) AngularPosition += 2 * Math.PI; AccumulatedTorque = 0; } public double RPM => AngularVelocity * 60 / (2 * Math.PI); public double TotalAngleDeg => TotalAngularPosition * 180 / Math.PI; public void SetRPM(double rpm) { AngularVelocity = rpm * 2 * Math.PI / 60; } public virtual void ResetTorque() { AccumulatedTorque = 0; } }