Source code for suboptimumg.log_analysis.steering
import numpy as np
from perda.core_data_structures.data_instance import DataInstance
from perda.core_data_structures.single_run_data import SingleRunData
from ..vehicle.irl_vehicle import IrlCar
from .kinematics import CURVATURE_BODY, CURVATURE_TRACK
BODY_FRAME_STEER_ANGLE = "body.steerAngle"
TRACK_FRAME_STEER_ANGLE = "track.steerAngle"
FRONT_LEFT_TIRE_STEERING_ANGLE = "front.steerAngle.left"
FRONT_RIGHT_TIRE_STEERING_ANGLE = "front.steerAngle.right"
FRONT_BICYCLE_MODEL_STEER_ANGLE = "front.steerAngle.bicycle"
[docs]
def add_kinematic_steer_angle(
data: SingleRunData,
wb: float,
) -> SingleRunData:
"""Add the kinematic steer angle from curvature using the bicycle model.
Expects curvature DataInstances to already be present, as added by `add_curvature()`.
Computes ``delta = degrees(arctan(wheelbase * curvature))`` for both
body and track frames and stores the results as ``body.steerAngle`` and
``track.steerAngle``. All angles are in degrees.
Parameters
----------
data : SingleRunData
wb : float
Wheelbase (m).
Returns
-------
SingleRunData
"""
missing = [c for c in (CURVATURE_BODY, CURVATURE_TRACK) if c not in data]
if missing:
raise KeyError(
f"add_kinematic_steer_angle: missing variable(s) {missing}.\n"
f"Try running run add_curvature first."
)
curv_body = data[CURVATURE_BODY]
data[BODY_FRAME_STEER_ANGLE] = DataInstance(
timestamp_np=curv_body.timestamp_np,
value_np=np.degrees(np.arctan(wb * curv_body.value_np)),
label="Kinematic Steer Angle — Body Frame (deg)",
cpp_name=BODY_FRAME_STEER_ANGLE,
)
curv_track = data[CURVATURE_TRACK]
data[TRACK_FRAME_STEER_ANGLE] = DataInstance(
timestamp_np=curv_track.timestamp_np,
value_np=np.degrees(np.arctan(wb * curv_track.value_np)),
label="Kinematic Steer Angle — Track Frame (deg)",
cpp_name=TRACK_FRAME_STEER_ANGLE,
)
return data
[docs]
def add_bicycle_steer_angle(
data: SingleRunData,
irl_car: IrlCar,
sw_col: str = "ludwig.steeringWheel.angle",
) -> SingleRunData:
"""Add front tire steer angles from the steering wheel sensor.
Converts the steering wheel angle to individual left/right tire angles
using the Ackermann polynomial in ``irl_car``, then averages them for
the bicycle-model front axle steer angle. Stores the results as
'front.steerAngle.left', 'front.steerAngle.right', and 'front.steerAngle.bicycle'.
All outputs are in degrees.
Parameters
----------
data : SingleRunData
irl_car : IrlCar
Provides the Ackermann polynomial via ``tire_angles()``.
sw_col : str
Steering wheel angle variable name (degrees).
Returns
-------
SingleRunData
"""
if sw_col not in data:
raise KeyError(f"add_bicycle_steer_angle: missing variable '{sw_col}'")
sw = data[sw_col]
left_vals, right_vals = irl_car.tire_angles(sw.value_np)
avg_vals = (left_vals + right_vals) / 2.0
data[FRONT_LEFT_TIRE_STEERING_ANGLE] = DataInstance(
timestamp_np=sw.timestamp_np,
value_np=left_vals,
label="Left Tire Steer Angle (deg)",
cpp_name=FRONT_LEFT_TIRE_STEERING_ANGLE,
)
data[FRONT_RIGHT_TIRE_STEERING_ANGLE] = DataInstance(
timestamp_np=sw.timestamp_np,
value_np=right_vals,
label="Right Tire Steer Angle (deg)",
cpp_name=FRONT_RIGHT_TIRE_STEERING_ANGLE,
)
data[FRONT_BICYCLE_MODEL_STEER_ANGLE] = DataInstance(
timestamp_np=sw.timestamp_np,
value_np=avg_vals,
label="Bicycle Model Steer Angle (deg)",
cpp_name=FRONT_BICYCLE_MODEL_STEER_ANGLE,
)
return data