Skip to content

Commit

Permalink
Implement slip based friction coefficient solution (Approach 6)
Browse files Browse the repository at this point in the history
  • Loading branch information
Vatsal Ambastha committed Sep 28, 2020
1 parent d6e169f commit f244b9a
Show file tree
Hide file tree
Showing 5 changed files with 686 additions and 69 deletions.
20 changes: 20 additions & 0 deletions Assets/Tork/Runtime/Core/SlipFrictionCurve.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Adrenak.Tork {
[System.Serializable]
public class SlipFrictionCurve {
public float maxCoeff;
public float minCoeff;
public float softness;
public float criticalSlip;

public float Evaluate(float slip) {
if (slip < criticalSlip - softness / 2)
return maxCoeff;
else if (slip > criticalSlip + softness / 2)
return minCoeff;
else {
float delta = slip - (criticalSlip - softness / 2);
return minCoeff + delta * (maxCoeff - minCoeff) / softness;
}
}
}
}
11 changes: 11 additions & 0 deletions Assets/Tork/Runtime/Core/SlipFrictionCurve.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

221 changes: 160 additions & 61 deletions Assets/Tork/Runtime/Core/TorkWheel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,6 @@ public class TorkWheel : MonoBehaviour {
/// </summary>
public Vector3 SuspensionForce { get; private set; }

public float frictionCoeff;
public float driftiness;

Ray m_Ray;
new Rigidbody rigidbody;
public const float k_ExtraRayLegnth = 1;
Expand All @@ -157,12 +154,12 @@ void FixedUpdate() {
Velocity = rigidbody.GetPointVelocity(transform.position);

transform.localEulerAngles = new Vector3(
transform.localEulerAngles.x,
SteerAngle,
transform.localEulerAngles.x,
SteerAngle,
transform.localEulerAngles.z
);
CalculateSuspension();
CalculateFriction3();
CalculateFriction6();
CalculateRPM();
}

Expand Down Expand Up @@ -213,81 +210,181 @@ bool WheelRaycast(float maxDistance, ref RaycastHit hit) {
return false;
}

void CalculateFriction_Uncharted4() {
#region APPROACH_1
//public float frictionCoeff;
//void CalculateFriction1() {
// if (!IsGrounded) return;

// // Contact basis (can be different from wheel basis)
// Vector3 right = transform.right;
// Vector3 forward = transform.forward;
// Vector3 Velocity = rigidbody.GetPointVelocity(Hit.point);

// var Vf = Vector3.Project(Velocity, forward).magnitude;
// var Vl = Vector3.Project(Velocity, right).magnitude;
// var N = SuspensionForce.magnitude;

// var Favail = N * frictionCoeff;
// var Ff = MotorTorque / radius;
// var Fl = Mathf.Abs(Vl) / Mathf.Abs(Vf) * N;
// var Ft = Mathf.Sqrt(Ff * Ff + Fl * Fl);

// var Fs = Favail / Ft;

// var Flapplied = Fl * Fs;
// var Ffmax = Ff * Fs;
// float Ffa;
// if (Ff > 0)
// Ffa = Mathf.Clamp(Ff, 0, Ffmax);
// else
// Ffa = Mathf.Clamp(Ff, Ffmax, 0);

// rigidbody.AddForceAtPosition(-Vector3.Project(Velocity, right).normalized * Flapplied, Hit.point);
// rigidbody.AddForceAtPosition(forward * Ffa * engineShaftToWheelRatio, Hit.point);
//}
#endregion

#region APPROACH_2
//public float esslip;
//public float grip;
//public float drift;

//WheelFrictionCurve curve;

//void CalculateFriction() {
// if (!IsGrounded) return;

// curve.extremumSlip = esslip;
// curve.extremumValue = esslip * grip;
// curve.asymptoteSlip = esslip * 1.5f;
// curve.asymptoteValue = esslip * drift;

// // Contact basis (can be different from wheel basis)
// Vector3 right = transform.right;
// Vector3 forward = transform.forward;
// Vector3 Velocity = rigidbody.GetPointVelocity(Hit.point);

// var Vf = Vector3.Project(Velocity, forward).magnitude;
// var Vl = Vector3.Project(Velocity, right).magnitude;
// var N = SuspensionForce.magnitude;

// var Ff = MotorTorque / radius;
// var Fl = curve.Evaluate(Vl);
// Debug.Log(Vl);
// //Debug.Log(Vl > curve.extremumSlip ? "Slipping" : "Gripping");

// var Fs = 1;

// var Flapplied = Fl * Fs;
// var Ffmax = Ff * frictionCoeff;
// float Ffa;
// if (Ff > 0)
// Ffa = Mathf.Clamp(Ff, 0, Ffmax);
// else
// Ffa = Mathf.Clamp(Ff, Ffmax, 0);

// rigidbody.AddForceAtPosition(-Vector3.Project(Velocity, right).normalized * Flapplied, Hit.point);
// rigidbody.AddForceAtPosition(forward * Ffa * engineShaftToWheelRatio, Hit.point);
//}
#endregion

#region APPROACH_3
void CalculateFriction3() {
if (!IsGrounded) return;

// Contact basis (can be different from wheel basis)
Vector3 right = transform.right;
Vector3 forward = transform.forward;
Vector3 Velocity = rigidbody.GetPointVelocity(Hit.point);

var Vf = Vector3.Project(Velocity, forward).magnitude;
var Vl = Vector3.Project(Velocity, right).magnitude;
var N = SuspensionForce.magnitude;

var Favail = N * frictionCoeff;
var Ff = MotorTorque / radius;
var Fl = Mathf.Abs(Vl) / Mathf.Abs(Vf) * N;
var Ft = Mathf.Sqrt(Ff * Ff + Fl * Fl);

var Fs = Favail / Ft;

var Flapplied = Fl * Fs;
var Ffmax = Ff * Fs;
float Ffa;
if (Ff > 0)
Ffa = Mathf.Clamp(Ff, 0, Ffmax);
Vector3 lateralVelocity = Vector3.Project(Velocity, right);
Vector3 forwardVelocity = Vector3.Project(Velocity, forward);
Vector3 slip = (forwardVelocity + lateralVelocity) / 2;

float lateralFriction = Vector3.Project(right, slip).magnitude * SuspensionForce.magnitude / 9.8f / Time.fixedDeltaTime * sidewaysGrip;
rigidbody.AddForceAtPosition(-Vector3.Project(slip, lateralVelocity).normalized * lateralFriction, Hit.point);

float motorForce = MotorTorque / radius;
float maxForwardFriction = motorForce * forwardGrip;
float appliedForwardFriction = 0;
if (motorForce > 0)
appliedForwardFriction = Mathf.Clamp(motorForce, 0, maxForwardFriction);
else
Ffa = Mathf.Clamp(Ff, Ffmax, 0);
appliedForwardFriction = Mathf.Clamp(motorForce, maxForwardFriction, 0);

rigidbody.AddForceAtPosition(-Vector3.Project(Velocity, right).normalized * Flapplied, Hit.point);
rigidbody.AddForceAtPosition(forward * Ffa * engineShaftToWheelRatio, Hit.point);
rigidbody.AddForceAtPosition(forward * appliedForwardFriction * engineShaftToWheelRatio, Hit.point);
}
#region APPROACH_2
public float esslip;
public float grip;
public float drift;
#endregion

WheelFrictionCurve curve;
#region APPROACH_4
//public float maxSlip;
//public float grip;
//public float drift;

void CalculateFriction() {
if (!IsGrounded) return;
//WheelFrictionCurve curve4;
//void CalculateFriction4() {
// if (!IsGrounded) return;

curve.extremumSlip = esslip;
curve.extremumValue = esslip * grip;
curve.asymptoteSlip = esslip * 1.5f;
curve.asymptoteValue = esslip * drift;
// curve4.extremumSlip = maxSlip;
// curve4.extremumValue = grip;
// curve4.asymptoteValue = drift;

// Contact basis (can be different from wheel basis)
Vector3 right = transform.right;
Vector3 forward = transform.forward;
Vector3 Velocity = rigidbody.GetPointVelocity(Hit.point);
// Vector3 right = transform.right;
// Vector3 forward = transform.forward;
// Vector3 Velocity = rigidbody.GetPointVelocity(Hit.point);

var Vf = Vector3.Project(Velocity, forward).magnitude;
var Vl = Vector3.Project(Velocity, right).magnitude;
var N = SuspensionForce.magnitude;
// Vector3 lateralVelocity = Vector3.Project(Velocity, right);
// Vector3 forwardVelocity = Vector3.Project(Velocity, forward);
// Vector3 slip = (forwardVelocity + lateralVelocity) / 2;

var Ff = MotorTorque / radius;
var Fl = curve.Evaluate(Vl);
Debug.Log(Vl);
//Debug.Log(Vl > curve.extremumSlip ? "Slipping" : "Gripping");
// sidewaysGrip = curve4.Evaluate2(Vector3.Project(Velocity, right).magnitude);

var Fs = 1;
// float lateralFriction = Vector3.Project(right, slip).magnitude * SuspensionForce.magnitude / 9.8f / Time.fixedDeltaTime * sidewaysGrip;
// rigidbody.AddForceAtPosition(-Vector3.Project(slip, lateralVelocity).normalized * lateralFriction, Hit.point);

var Flapplied = Fl * Fs;
var Ffmax = Ff * frictionCoeff;
float Ffa;
if (Ff > 0)
Ffa = Mathf.Clamp(Ff, 0, Ffmax);
else
Ffa = Mathf.Clamp(Ff, Ffmax, 0);
// float motorForce = MotorTorque / radius;
// float maxForwardFriction = motorForce * forwardGrip;
// float appliedForwardFriction = 0;
// if (motorForce > 0)
// appliedForwardFriction = Mathf.Clamp(motorForce, 0, maxForwardFriction);
// else
// appliedForwardFriction = Mathf.Clamp(motorForce, maxForwardFriction, 0);

rigidbody.AddForceAtPosition(-Vector3.Project(Velocity, right).normalized * Flapplied, Hit.point);
rigidbody.AddForceAtPosition(forward * Ffa * engineShaftToWheelRatio, Hit.point);
}
// rigidbody.AddForceAtPosition(forward * appliedForwardFriction * engineShaftToWheelRatio, Hit.point);
//}
#endregion

void CalculateFriction3() {
#region APPROACH5
//public AnimationCurve curve5 = AnimationCurve.Constant(0, 100, .8f);
//void CalculateFriction5() {
// if (!IsGrounded) return;

// Vector3 right = transform.right;
// Vector3 forward = transform.forward;
// Vector3 Velocity = rigidbody.GetPointVelocity(Hit.point);

// Vector3 lateralVelocity = Vector3.Project(Velocity, right);
// Vector3 forwardVelocity = Vector3.Project(Velocity, forward);
// Vector3 slip = (forwardVelocity + lateralVelocity) / 2;

// sidewaysGrip = curve5.Evaluate(Vector3.Project(Velocity, right).magnitude);

// float lateralFriction = Vector3.Project(right, slip).magnitude * SuspensionForce.magnitude / 9.8f / Time.fixedDeltaTime * sidewaysGrip;
// rigidbody.AddForceAtPosition(-Vector3.Project(slip, lateralVelocity).normalized * lateralFriction, Hit.point);

// float motorForce = MotorTorque / radius;
// float maxForwardFriction = motorForce * forwardGrip;
// float appliedForwardFriction = 0;
// if (motorForce > 0)
// appliedForwardFriction = Mathf.Clamp(motorForce, 0, maxForwardFriction);
// else
// appliedForwardFriction = Mathf.Clamp(motorForce, maxForwardFriction, 0);

// rigidbody.AddForceAtPosition(forward * appliedForwardFriction * engineShaftToWheelRatio, Hit.point);
//}
#endregion

public SlipFrictionCurve curve6;
void CalculateFriction6() {
if (!IsGrounded) return;

Vector3 right = transform.right;
Expand All @@ -298,6 +395,8 @@ void CalculateFriction3() {
Vector3 forwardVelocity = Vector3.Project(Velocity, forward);
Vector3 slip = (forwardVelocity + lateralVelocity) / 2;

sidewaysGrip = curve6.Evaluate(Vector3.Project(Velocity, right).magnitude);

float lateralFriction = Vector3.Project(right, slip).magnitude * SuspensionForce.magnitude / 9.8f / Time.fixedDeltaTime * sidewaysGrip;
rigidbody.AddForceAtPosition(-Vector3.Project(slip, lateralVelocity).normalized * lateralFriction, Hit.point);

Expand Down
7 changes: 7 additions & 0 deletions Assets/Tork/Runtime/Utils/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,12 @@ public static float Evaluate(this WheelFrictionCurve curve, float slip) {
//return curve.asymptoteValue;
return ((slip - curve.asymptoteSlip) * (curve.extremumValue - curve.asymptoteValue) / (curve.extremumSlip - curve.asymptoteSlip)) + curve.asymptoteValue;
}

public static float Evaluate2(this WheelFrictionCurve curve, float slip) {
if (slip < curve.extremumSlip)
return curve.extremumValue;
else
return curve.asymptoteValue;
}
}
}
Loading

0 comments on commit f244b9a

Please sign in to comment.