|
|
|
|
@@ -47,25 +47,14 @@ public partial class VeloXWheel
|
|
|
|
|
public Vector3 ContactRight => hitSidewaysDirection;
|
|
|
|
|
public Vector3 ContactForward => hitForwardDirection;
|
|
|
|
|
|
|
|
|
|
[Sync]
|
|
|
|
|
public float LongitudinalSlip
|
|
|
|
|
{
|
|
|
|
|
get => ForwardFriction.Slip;
|
|
|
|
|
private set => ForwardFriction.Slip = value;
|
|
|
|
|
}
|
|
|
|
|
public float LongitudinalSlip => ForwardFriction.Slip;
|
|
|
|
|
|
|
|
|
|
public float LongitudinalSpeed => ForwardFriction.Speed;
|
|
|
|
|
public bool IsSkiddingLongitudinally => NormalizedLongitudinalSlip > 0.35f;
|
|
|
|
|
public float NormalizedLongitudinalSlip => Math.Clamp( Math.Abs( LongitudinalSlip ), 0, 1 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[Sync]
|
|
|
|
|
public float LateralSlip
|
|
|
|
|
{
|
|
|
|
|
get => SidewayFriction.Slip;
|
|
|
|
|
private set => SidewayFriction.Slip = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public float LateralSlip => SidewayFriction.Slip;
|
|
|
|
|
public float LateralSpeed => SidewayFriction.Speed;
|
|
|
|
|
public bool IsSkiddingLaterally => NormalizedLateralSlip > 0.35f;
|
|
|
|
|
public float NormalizedLateralSlip => Math.Clamp( Math.Abs( LateralSlip ), 0, 1 );
|
|
|
|
|
@@ -86,8 +75,8 @@ public partial class VeloXWheel
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ForwardFriction.Speed = 0f;
|
|
|
|
|
SidewayFriction.Speed = 0f;
|
|
|
|
|
ForwardFriction = new();
|
|
|
|
|
SidewayFriction = new();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -97,6 +86,7 @@ public partial class VeloXWheel
|
|
|
|
|
private Vector3 currentPosition;
|
|
|
|
|
private Vector3 referenceError;
|
|
|
|
|
private Vector3 correctiveForce;
|
|
|
|
|
public bool wheelIsBlocked;
|
|
|
|
|
private void UpdateFriction( float dt )
|
|
|
|
|
{
|
|
|
|
|
var motorTorque = DriveTorque;
|
|
|
|
|
@@ -120,8 +110,6 @@ public partial class VeloXWheel
|
|
|
|
|
|
|
|
|
|
float loadPercent = Math.Clamp( Fz / LoadRating, 0f, 1f );
|
|
|
|
|
float slipLoadModifier = 1f - loadPercent * 0.4f;
|
|
|
|
|
//DebugOverlay.Text( WorldPosition, SidewayFriction.Speed.ToString(), overlay: true );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float mass = Vehicle.Body.Mass;
|
|
|
|
|
float absForwardSpeed = Math.Abs( ForwardFriction.Speed );
|
|
|
|
|
@@ -133,10 +121,7 @@ public partial class VeloXWheel
|
|
|
|
|
forwardSpeedClamp = Math.Clamp( forwardSpeedClamp, 1.5f, 10f );
|
|
|
|
|
float clampedAbsForwardSpeed = Math.Max( absForwardSpeed, forwardSpeedClamp );
|
|
|
|
|
|
|
|
|
|
// Calculate effect of camber on friction
|
|
|
|
|
float camberFrictionCoeff = Math.Max( 0, Vehicle.WorldRotation.Up.Dot( ContactNormal ) );
|
|
|
|
|
|
|
|
|
|
float peakForwardFrictionForce = forwardLoadFactor;
|
|
|
|
|
float peakForwardFrictionForce = 11000 * (1 - MathF.Exp( -0.00014f * forwardLoadFactor ));
|
|
|
|
|
float absCombinedBrakeTorque = Math.Max( 0, brakeTorque + RollingResistanceTorque );
|
|
|
|
|
|
|
|
|
|
float signedCombinedBrakeTorque = absCombinedBrakeTorque * -Math.Sign( ForwardFriction.Speed );
|
|
|
|
|
@@ -152,7 +137,7 @@ public partial class VeloXWheel
|
|
|
|
|
ForwardFriction.Force = forwardInputForce > maxForwardForce ? maxForwardForce
|
|
|
|
|
: forwardInputForce < -maxForwardForce ? -maxForwardForce : forwardInputForce;
|
|
|
|
|
|
|
|
|
|
bool wheelIsBlocked = false;
|
|
|
|
|
wheelIsBlocked = false;
|
|
|
|
|
if ( IsOnGround )
|
|
|
|
|
{
|
|
|
|
|
float combinedWheelForce = motorForce + absCombinedBrakeTorque * invRadius * -Math.Sign( AngularVelocity );
|
|
|
|
|
@@ -195,7 +180,6 @@ public partial class VeloXWheel
|
|
|
|
|
float maxCounterTorque = inertia * absAngularVelocity;
|
|
|
|
|
CounterTorque = Math.Clamp( (signedCombinedBrakeForce - ForwardFriction.Force) * mRadius, -maxCounterTorque, maxCounterTorque );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ForwardFriction.Slip = (ForwardFriction.Speed - AngularVelocity * mRadius) / clampedAbsForwardSpeed;
|
|
|
|
|
ForwardFriction.Slip *= slipLoadModifier;
|
|
|
|
|
|
|
|
|
|
@@ -204,10 +188,13 @@ public partial class VeloXWheel
|
|
|
|
|
|
|
|
|
|
float sideSlipSign = SidewayFriction.Slip > 0 ? 1 : -1;
|
|
|
|
|
float absSideSlip = Math.Abs( SidewayFriction.Slip );
|
|
|
|
|
float peakSideFrictionForce = sideLoadFactor;
|
|
|
|
|
float peakSideFrictionForce = 18000 * (1 - MathF.Exp( -0.0001f * sideLoadFactor ));
|
|
|
|
|
|
|
|
|
|
float sideForce = -sideSlipSign * Tire.Evaluate( absSideSlip ) * sideLoadFactor;
|
|
|
|
|
float sideForce = -sideSlipSign * Tire.Evaluate( absSideSlip ) * peakSideFrictionForce;
|
|
|
|
|
SidewayFriction.Force = Math.Clamp( sideForce, -sideForceClamp, sideForceClamp );
|
|
|
|
|
|
|
|
|
|
// Calculate effect of camber on friction
|
|
|
|
|
float camberFrictionCoeff = Math.Max( 0, Vehicle.WorldRotation.Up.Dot( ContactNormal ) );
|
|
|
|
|
SidewayFriction.Force *= camberFrictionCoeff;
|
|
|
|
|
|
|
|
|
|
if ( IsOnGround && absForwardSpeed < 0.12f && absSideSpeed < 0.12f )
|
|
|
|
|
@@ -241,9 +228,7 @@ public partial class VeloXWheel
|
|
|
|
|
ForwardFriction.Force += correctiveForce.Dot( hitForwardDirection );
|
|
|
|
|
}
|
|
|
|
|
SidewayFriction.Force += correctiveForce.Dot( hitSidewaysDirection );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
@@ -251,46 +236,56 @@ public partial class VeloXWheel
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ForwardFriction.Force = Math.Clamp( ForwardFriction.Force, -peakForwardFrictionForce, peakForwardFrictionForce );
|
|
|
|
|
//float forwardSlipPercent = -ForwardFriction.Slip / Tire.GetPeakSlip();
|
|
|
|
|
//float sideSlipPercent = SidewayFriction.Slip / Tire.GetPeakSlip();
|
|
|
|
|
//float slipCircleLimit = MathF.Sqrt( forwardSlipPercent * forwardSlipPercent + sideSlipPercent * sideSlipPercent );
|
|
|
|
|
//if ( slipCircleLimit > 1f )
|
|
|
|
|
//{
|
|
|
|
|
// float beta = MathF.Atan2( sideSlipPercent, forwardSlipPercent * 1.05f );
|
|
|
|
|
// float sinBeta = MathF.Sin( beta );
|
|
|
|
|
// float cosBeta = MathF.Cos( beta );
|
|
|
|
|
|
|
|
|
|
SidewayFriction.Force = Math.Clamp( SidewayFriction.Force, -peakSideFrictionForce, peakSideFrictionForce );
|
|
|
|
|
// float absForwardForce = ForwardFriction.Force < 0 ? -ForwardFriction.Force : ForwardFriction.Force;
|
|
|
|
|
|
|
|
|
|
// float absSideForce = SidewayFriction.Force < 0 ? -SidewayFriction.Force : SidewayFriction.Force;
|
|
|
|
|
// float f = absForwardForce * cosBeta * cosBeta + absSideForce * sinBeta * sinBeta;
|
|
|
|
|
|
|
|
|
|
if ( absForwardSpeed > 0.01f || absAngularVelocity > 0.01f )
|
|
|
|
|
{
|
|
|
|
|
// ForwardFriction.Force = 0.5f * ForwardFriction.Force - f * cosBeta;
|
|
|
|
|
// SidewayFriction.Force = 0.5f * SidewayFriction.Force - f * sinBeta;
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
float forwardSlipPercent = ForwardFriction.Slip / Tire.GetPeakSlip();
|
|
|
|
|
float sideSlipPercent = SidewayFriction.Slip / Tire.GetPeakSlip();
|
|
|
|
|
float slipCircleLimit = MathF.Sqrt( forwardSlipPercent * forwardSlipPercent + sideSlipPercent * sideSlipPercent );
|
|
|
|
|
if ( slipCircleLimit > 1f )
|
|
|
|
|
{
|
|
|
|
|
float beta = MathF.Atan2( sideSlipPercent, forwardSlipPercent * 1.05f );
|
|
|
|
|
float sinBeta = MathF.Sin( beta );
|
|
|
|
|
float cosBeta = MathF.Cos( beta );
|
|
|
|
|
//var slipVector = new Vector2(
|
|
|
|
|
// ForwardFriction.Slip,
|
|
|
|
|
// SidewayFriction.Slip
|
|
|
|
|
//);
|
|
|
|
|
//if ( slipVector.Length > 0.001f )
|
|
|
|
|
//{
|
|
|
|
|
// var frictionDirection = slipVector.Normal;
|
|
|
|
|
|
|
|
|
|
float absForwardForce = ForwardFriction.Force < 0 ? -ForwardFriction.Force : ForwardFriction.Force;
|
|
|
|
|
// float frictionMagnitude = MathF.Sqrt(
|
|
|
|
|
// ForwardFriction.Force * ForwardFriction.Force +
|
|
|
|
|
// SidewayFriction.Force * SidewayFriction.Force
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
float absSideForce = SidewayFriction.Force < 0 ? -SidewayFriction.Force : SidewayFriction.Force;
|
|
|
|
|
float f = absForwardForce * cosBeta * cosBeta + absSideForce * sinBeta * sinBeta;
|
|
|
|
|
// ForwardFriction.Force = Math.Abs( frictionDirection.x ) * frictionMagnitude * Math.Sign( ForwardFriction.Force );
|
|
|
|
|
// SidewayFriction.Force = Math.Abs( frictionDirection.y ) * frictionMagnitude * Math.Sign( SidewayFriction.Force );
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
var f = MathF.Sqrt( ForwardFriction.Force * ForwardFriction.Force + SidewayFriction.Force * SidewayFriction.Force );
|
|
|
|
|
var d = Math.Abs( new Vector2( ForwardFriction.Slip, SidewayFriction.Slip ).Normal.y );
|
|
|
|
|
SidewayFriction.Force = f * d * Math.Sign( SidewayFriction.Force );
|
|
|
|
|
|
|
|
|
|
ForwardFriction.Force = 0.5f * ForwardFriction.Force - f * cosBeta;
|
|
|
|
|
SidewayFriction.Force = 0.5f * SidewayFriction.Force - f * sinBeta;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( IsOnGround )
|
|
|
|
|
{
|
|
|
|
|
FrictionForce.x = (hitSidewaysDirection.x * SidewayFriction.Force + hitForwardDirection.x * ForwardFriction.Force).MeterToInch();
|
|
|
|
|
FrictionForce.y = (hitSidewaysDirection.y * SidewayFriction.Force + hitForwardDirection.y * ForwardFriction.Force).MeterToInch();
|
|
|
|
|
FrictionForce.z = (hitSidewaysDirection.z * SidewayFriction.Force + hitForwardDirection.z * ForwardFriction.Force).MeterToInch();
|
|
|
|
|
//DebugOverlay.Normal( WorldPosition, hitSidewaysDirection * 10, overlay: true );
|
|
|
|
|
//DebugOverlay.Normal( WorldPosition, hitForwardDirection * 10, overlay: true );
|
|
|
|
|
//DebugOverlay.Normal( WorldPosition, FrictionForce / 100, overlay: true );
|
|
|
|
|
//DebugOverlay.Normal( ContactPosition, Vector3.Up * AngularVelocity, overlay: true );
|
|
|
|
|
|
|
|
|
|
//DebugOverlay.Sphere( new( ContactPosition, 4 ), overlay: true );
|
|
|
|
|
//Vehicle.Body.ApplyForceAt( ContactPosition, FrictionForce );
|
|
|
|
|
|
|
|
|
|
//DebugOverlay.Normal( WorldPosition, hitSidewaysDirection * 10, overlay: true, color: Color.Red );
|
|
|
|
|
//DebugOverlay.Normal( WorldPosition, hitForwardDirection * 10, overlay: true, color: Color.Green );
|
|
|
|
|
//DebugOverlay.Normal( WorldPosition, FrictionForce.ClampLength( 30 ), overlay: true, color: Color.Cyan );
|
|
|
|
|
//DebugOverlay.ScreenText( Scene.Camera.PointToScreenPixels( WorldPosition ), $"{ForwardFriction}\nMotor:{(int)motorTorque}\nBrake:{(int)brakeTorque}", flags: TextFlag.LeftTop );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
FrictionForce = Vector3.Zero;
|
|
|
|
|
|