Source code for suboptimumg.vehicle.suspension.tire

import math

from ...constants import in_to_m
from ..models import VehicleModel


[docs] class Tires: def __init__( self, vehicle_model: VehicleModel, ): self.vehicle_model = vehicle_model self.params = self.vehicle_model.tires self.fl, self.fr, self.bl, self.br = [Tire() for _ in range(4)] self.list = [self.fl, self.fr, self.bl, self.br]
[docs] def initialize_tires( self, fl_norm: float, fr_norm: float, bl_norm: float, br_norm: float ): self.fl.normal = fl_norm self.fr.normal = fr_norm self.bl.normal = bl_norm self.br.normal = br_norm
[docs] def reset_tires( self, fl_norm: float, fr_norm: float, bl_norm: float, br_norm: float ): for tire in self.list: tire.reset() self.fl.normal = fl_norm self.fr.normal = fr_norm self.bl.normal = bl_norm self.br.normal = br_norm
[docs] class Tire: # TODO: redo the tire model # assumes maximum slip ratio def __init__(self): self.normal = 1e-6 # normal force (N) default value self.lateral = 0 # lateral grip (N) self.longitudinal = 0 # longitudinal grip (N)
[docs] def reset(self): self.normal = 1e-6 self.lateral = 0 self.longitudinal = 0
[docs] def calc_mu(self, mu_long_lat_ratio, mu_lat_zero_load): """ Calculate mu_lat and mu_long according to an equation fitted from TTC data. Parameters ---------- mu_long_lat_ratio : float Ratio of longitudinal to lateral friction coefficients (unitless) mu_lat_zero_load : float Lateral friction coefficient at zero normal force (unitless) 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 * self.normal**2 - 2.82666e-4 * self.normal + mu_lat_zero_load ) mu_lat = max(mu_lat, 0) # Clip if bad mu_long = mu_lat * mu_long_lat_ratio if self.normal <= 0: # if the tire is lifted up, it has no grip. return 0, 0 return mu_lat, mu_long
[docs] def is_current_lateral_force_valid(self, mu_long_lat_ratio, mu_lat_zero_load): """ Check whether the requested lateral force results in oversaturating the tire. Parameters ---------- mu_long_lat_ratio : float Ratio of longitudinal to lateral friction coefficients (unitless) mu_lat_zero_load : float Lateral friction coefficient at zero normal force (unitless) Returns ------- bool True if current lateral force is valid, False otherwise Notes ----- Should be called only after lateral force is correctly updated. """ mu_lat, _ = self.calc_mu(mu_long_lat_ratio, mu_lat_zero_load) max_lat = self.normal * mu_lat return self.lateral < max_lat
[docs] def long_remain(self, mu_long_lat_ratio, mu_lat_zero_load): """ Calculates the remaining longitudinal grip of the tire based on a friction ellipse ELLIPSE EQN: (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 ) ) Returns: float: Remaining longitudinal grip (N). """ # Calculate remaining longitudinal grip with friction ellipse mu_lat, mu_long = self.calc_mu(mu_long_lat_ratio, mu_lat_zero_load) grip_diff = self.normal**2 - (self.lateral**2 / mu_lat**2) f_long = mu_long * (math.sqrt(grip_diff)) return f_long