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