suboptimumg.loganalysis.corrections#

Post-intake data corrections for known CAN log issues.

suboptimumg.loganalysis.corrections.compute_ned_from_body(df, vel_x_col='pcm.vnav.velocityBody.x', vel_y_col='pcm.vnav.velocityBody.y', vel_z_col='pcm.vnav.velocityBody.z', yaw_col='pcm.vnav.yawPitchRoll.yaw', ned_cols=('velN', 'velE', 'velD'))[source]#

Compute NED velocities from body-frame (FRD) using yaw rotation.

Used when the VectorNav is correctly configured and velocityBody columns contain true body-frame data. The inverse of the rotation in patch_ned_velocity():

velN =  v_fwd * cos(yaw) - v_right * sin(yaw)
velE =  v_fwd * sin(yaw) + v_right * cos(yaw)
velD =  v_down            (unchanged)
Parameters:
  • df (DataFrame)

  • vel_x_col (str)

  • vel_y_col (str)

  • vel_z_col (str)

  • yaw_col (str)

  • ned_cols (tuple[str, str, str])

Return type:

DataFrame

suboptimumg.loganalysis.corrections.convert_wheelspeeds_to_m_per_s(df, cols)[source]#

Convert wheel speed columns from mph to m/s.

Backs up original mph values into {col}_mph columns before overwriting with the converted values.

Parameters:
  • df (pd.DataFrame)

  • cols (list[str]) – Column names to convert.

Returns:

The same DataFrame, modified in-place and returned for chaining.

Return type:

pd.DataFrame

suboptimumg.loganalysis.corrections.correct_motor_data(df, rpm_col='pcm.moc.motor.angularSpeed', out_col='pcm.moc.motor.wheelSpeed', gear_ratio=None, tire_radius_in=None, car_yaml='parameters/car.yaml')[source]#

Flip motor RPM sign and compute driven wheel speed.

The inverter logs motor RPM as negative for forward motion. This function negates the RPM (so positive = forward) and computes the corresponding driven wheel linear speed in m/s.

Parameters:
  • df (pd.DataFrame)

  • rpm_col (str) – Motor angular speed column (RPM, raw sign: negative = forward).

  • out_col (str) – Column name for the computed wheel speed (m/s).

  • gear_ratio (float or None) – Overall gear ratio (motor RPM / wheel RPM). If None, loaded from car_yaml (pwrtn.ratio).

  • tire_radius_in (float or None) – Loaded tire radius in inches. If None, loaded from car_yaml (tires.tire_radius).

  • car_yaml (str) – Path to car YAML file, used when gear_ratio or tire_radius_in are not provided.

Returns:

Modified in-place and returned for chaining.

Return type:

pd.DataFrame

suboptimumg.loganalysis.corrections.patch_ned_velocity(df, vel_x_col='pcm.vnav.velocityBody.x', vel_y_col='pcm.vnav.velocityBody.y', vel_z_col='pcm.vnav.velocityBody.z', yaw_col='pcm.vnav.yawPitchRoll.yaw', ned_cols=('velN', 'velE', 'velD'))[source]#

Correct mislabeled NED velocities that were logged as body-frame.

Due to a VectorNav configuration issue, velocityBody.x/y/z actually contains NED (North/East/Down) velocities rather than body-frame (Forward/Right/Down) velocities. This function:

  1. Copies the raw NED data into new columns (ned_cols).

  2. Rotates NED → FRD body frame using yaw and overwrites the original velocityBody columns with corrected values.

The rotation (yaw-only, ignoring pitch/roll for ground vehicles):

v_fwd   =  velN * cos(yaw) + velE * sin(yaw)
v_right = -velN * sin(yaw) + velE * cos(yaw)
v_down  =  velD            (unchanged)

This is a temporary workaround. When the VectorNav is reconfigured to output body-frame velocities natively, skip this step entirely.

Parameters:
  • df (pd.DataFrame) – DataFrame with velocity and yaw columns (typically from perda_to_dataframe).

  • vel_x_col (str) – The mislabeled velocity columns (actually NED).

  • vel_y_col (str) – The mislabeled velocity columns (actually NED).

  • vel_z_col (str) – The mislabeled velocity columns (actually NED).

  • yaw_col (str) – Heading column in degrees (0 = North, 90 = East, CW positive).

  • ned_cols (tuple[str, str, str]) – Names for the preserved NED copy columns.

Returns:

The same DataFrame, modified in-place and returned for chaining.

Return type:

pd.DataFrame

suboptimumg.loganalysis.corrections.recompute_steering_angle(df, raw_col='ludwig.steeringWheel.raw', angle_col='ludwig.steeringWheel.angle', calibration=((1.86, -97.0), (2.93, 0.0), (3.96, 97.0)))[source]#

Regenerate ludwig.steeringWheel.angle from the raw analog voltage.

The on-vehicle DSP that produces steeringWheel.angle has been observed to drift relative to the raw pot signal. This function rebuilds the angle column from steeringWheel.raw using a least-squares polynomial fit through the calibration points (quadratic by default — exact fit for the standard 3-point left/center/right calibration, capturing the small nonlinearity of the pot).

Any existing angle_col is preserved as {angle_col}_original.

Parameters:
  • df (pd.DataFrame) – Must contain raw_col.

  • raw_col (str) – Raw analog steering voltage column (volts).

  • angle_col (str) – Output / overwritten angle column (degrees).

  • calibration (tuple of (voltage, angle) pairs) – Calibration points. With three points a quadratic fits all of them exactly; with more points it’s a least-squares quadratic. With two points it falls back to a linear fit.

Returns:

Modified in-place and returned for chaining.

Return type:

pd.DataFrame