Files
2025-05-13 03:19:28 +03:00

151 lines
4.6 KiB
C#

using UnityEngine;
using UnityEditor;
using System.Collections;
using System;
[ExecuteInEditMode]
public class Tyre : MonoBehaviour {
public double height = 0.15f;
public double k_RollLinear = 0.0038;
public double k_RollQuad = 0.000026;
public double GetRollingResistance(double Fz, double wheelEffectiveRadius, double velocity, double resistanceFactor) {
return Fz * wheelEffectiveRadius * resistanceFactor * (k_RollLinear + k_RollQuad * (velocity )) * Math.Sign(velocity);
}
private double oldLatSlip;
public double latFilter = 0.85f;
public PacejkaParameters pacejkaParams;
/* public void Slip(double patch_speed, Vector3 hub_velocity, out double slipLon, out double slipLat) {
var absLongVelocity = (double)Mathf.Abs(hub_velocity.z);
absLongVelocity = Math.Max(absLongVelocity, dampAbsRoadVelo);
slipLon = CalcSlipRatio(patch_speed, hub_velocity) * 100.0f;
slipLat = (Mathf.Atan2(hub_velocity.x, (float)absLongVelocity)) * Mathf.Rad2Deg;
}
public Double3 FrictionForce(double normalForce, double slipLon, double slipLat, double camber, PacejkaCoeffs coeffs) {
if(normalForce < 1e-4f) { return Double3.zero; }
normalForce = MathEx.Clamp(normalForce, 0, 100000);
//compute Pacejka params
var lateralParams = Pacejka.LateralParams(normalForce, camber, coeffs);
var longitudinalParams = Pacejka.LongitudinalParams(normalForce, coeffs);
var aligningParams = Pacejka.AligningParams(normalForce, camber, coeffs);
//compute friction forces
Double3 result;
result.x = Pacejka.MagicFormula(slipLon, longitudinalParams);
result.y = Pacejka.MagicFormula(slipLat, lateralParams);
result.z = Pacejka.MagicFormula(slipLat, aligningParams);
/* //do combined friction
double d_lon = slipLon / (1.0 + slipLon);
double d_lat = Math.Tan(slipLat) / (1.0 + slipLon);
double d = Math.Sqrt(d_lat * d_lat + d_lon * d_lon);
if(d > 0.001) {
result.x *= (float)Math.Abs(d_lon / d);
result.y *= (float)Math.Abs(d_lat / d);
}*/
// return result;
// }
void OnValidate() {
if(enabled) {
if(transform.parent != null && gameObject.activeInHierarchy)
{
SceneView.RepaintAll();
// transform.parent.gameObject.SendMessage("OnValidate");
}
}
}
// SAE950311 implementation
// private double lastU;
// private double signU = 1;
//private double oldSlip = 0;
// public double tau;
// public double B = 0.091f;//relaxationLengthLong
public double relaxLong = 0.00172688486f;
// private double _integratedSlip;
public double speedThreshold = 3.0f;
public double dampAbsRoadVelo = 1;
public double kBLong = 0.35f;
public double fixedTimeBase = 0.02f;
public double CalcSlipRatio(double patch_speed, Vector3 hub_velocity) {
bool IsOnSurface = true;
if(!IsOnSurface) {
// _integratedSlip = 0;
return 0;
}
/* double deltaTime = Time.fixedDeltaTime;
double dampSRreversal = 0.5f;
double B = relaxLong*100;
double fixedTimeStepScalar = fixedTimeBase / Time.fixedDeltaTime;
double invFixedTimeStepScalar = 1.0f / fixedTimeStepScalar;
if(B < kBLong * invFixedTimeStepScalar)
B = kBLong * invFixedTimeStepScalar;
// damp sliAngle and slipRatio oscilation
double factor = hub_velocity.z * 3.6f * 0.02f; // divided by 50
if(factor < 1)
factor = 1;
B *= factor;
*/
// SAE950311 algorithm
var longVelocity = (double)hub_velocity.z;
// var absLongVelocity = Math.Abs(longVelocity);
if (Math.Abs(longVelocity - patch_speed) > 1.0e-4)
{
double denom = Math.Max(Math.Abs(longVelocity), dampAbsRoadVelo);
return MathEx.Clamp((patch_speed - longVelocity)/denom, -1.0, 1.0);
}
else
{
return 0;
}
/*
absLongVelocity = Math.Max(absLongVelocity, dampAbsRoadVelo);
if((lastU < 0 && longVelocity >= 0) || (lastU >= 0 && longVelocity < 0)) {
_integratedSlip = -dampSRreversal * _integratedSlip;
}
lastU = Math.Sign(longVelocity);
double derivative = (patch_speed - longVelocity) - absLongVelocity * _integratedSlip;
derivative /= B;
// Integrate
_integratedSlip += derivative * deltaTime;
return MathEx.Clamp(_integratedSlip + tau * derivative, -1.5, 1.5);*/
}
}