Source code for suboptimumg.vehicle.suspension.tire
import math
from ...models import TireForce
from ..vehicle_models import VehicleModel
[docs]
class Tires:
def __init__(
self,
vehicle_model: VehicleModel,
) -> None:
"""
Initialize the tire model for a vehicle.
Parameters
----------
vehicle_model : VehicleModel
Vehicle model providing the tire parameters.
"""
self.vehicle_model = vehicle_model
self.params = self.vehicle_model.tires
[docs]
def calc_mu(self, normal: float) -> tuple[float, float]:
"""
Calculate mu_lat and mu_long according to an equation fitted from TTC data.
Parameters
----------
normal : float
Normal force on the tire (N)
Returns
-------
float
mu_lat - Lateral friction coefficient
float
mu_long - Longitudinal friction coefficient
Notes
-----
Uses quadratic fit from TTC (Tire Test Consortium) data.
Returns (0, 0) if tire is lifted (normal force <= 0).
"""
mu_lat = -7.66113e-8 * normal**2 - 2.82666e-4 * normal + self.params.mu_lat_zero_load
mu_lat = max(mu_lat, 0) # Clip if bad
mu_long = mu_lat * self.params.mu_long_lat_ratio
if normal <= 0: # if the tire is lifted up, it has no grip.
return 0, 0
return mu_lat, mu_long
[docs]
def is_lateral_force_valid(self, force: TireForce) -> bool:
"""
Check whether the requested lateral force results in oversaturating the tire.
Parameters
----------
force : TireForce
Forces on the tire
Returns
-------
bool
True if the lateral force is valid, False otherwise
"""
mu_lat, _ = self.calc_mu(force.normal)
max_lat = force.normal * mu_lat
return force.lateral < max_lat
[docs]
def long_remain(self, force: TireForce) -> float:
"""
Calculate the remaining longitudinal grip of the tire based on a friction ellipse.
Parameters
----------
force : TireForce
Forces on the tire
Returns
-------
float
Remaining longitudinal grip (N)
Notes
-----
Friction ellipse equation:
(x^2 / radius_x^2) + (y^2 / radius_y^2) = n^2
(f_lat^2 / mu_lat^2) + (f_long^2 / mu_long^2) = f_normal^2
f_long = mu_long * sqrt( f_normal^2 - ( f_lat^2 / mu_lat^2 ) )
"""
# Calculate remaining longitudinal grip with friction ellipse
mu_lat, mu_long = self.calc_mu(force.normal)
grip_diff = force.normal**2 - (force.lateral**2 / mu_lat**2)
f_long = mu_long * (math.sqrt(grip_diff))
return f_long