perda.utils.preprocessing#

class perda.utils.preprocessing.ConvertWheelspeedsToMPerSLambda(wheelspeed_fr='pcm.wheelSpeeds.frontRight', wheelspeed_fl='pcm.wheelSpeeds.frontLeft', wheelspeed_rr='pcm.wheelSpeeds.backRight', wheelspeed_rl='pcm.wheelSpeeds.backLeft')[source]#

Bases: object

Backing class for the convert_wheelspeeds_to_m_per_s preprocessing step.

Parameters:
  • wheelspeed_fr (str)

  • wheelspeed_fl (str)

  • wheelspeed_rr (str)

  • wheelspeed_rl (str)

class perda.utils.preprocessing.CorrectMotorDataLambda(gear_ratio=5.6, tire_radius_in=7.85, motor_rpm='pcm.moc.motor.angularSpeed', motor_wheelspeed='pcm.moc.motor.wheelSpeed')[source]#

Bases: object

Backing class for the correct_motor_data preprocessing step.

Parameters:
  • gear_ratio (float)

  • tire_radius_in (float)

  • motor_rpm (str)

  • motor_wheelspeed (str)

class perda.utils.preprocessing.CorrectSteeringAngleLambda(calibration=((1.86, -97.0), (2.93, 0.0), (3.96, 97.0)), steering_raw='ludwig.steeringWheel.raw', steering_angle='ludwig.steeringWheel.angle')[source]#

Bases: object

Backing class for the correct_steering_angle preprocessing step.

Fits a polynomial through calibration points (voltage, angle) at construction time, then rewrites the angle channel from the raw voltage channel on each call.

Parameters:
  • calibration (tuple[tuple[float, float], ...])

  • steering_raw (str)

  • steering_angle (str)

class perda.utils.preprocessing.PatchNedVelocityLambda(body_vel_x='pcm.vnav.velocityBody.x', body_vel_y='pcm.vnav.velocityBody.y', body_vel_z='pcm.vnav.velocityBody.z', yaw='pcm.vnav.yawPitchRoll.yaw', ned_vel_n='velN', ned_vel_e='velE', ned_vel_d='velD')[source]#

Bases: object

Backing class for the patch_ned_velocity preprocessing step.

Parameters:
  • body_vel_x (str)

  • body_vel_y (str)

  • body_vel_z (str)

  • yaw (str)

  • ned_vel_n (str)

  • ned_vel_e (str)

  • ned_vel_d (str)

perda.utils.preprocessing.apply_preprocessing(data, steps)[source]#

Run a sequence of preprocessing steps on a SingleRunData instance.

Parameters:
  • data (SingleRunData) – Parsed run data to preprocess.

  • steps (list of PreprocessingStep) – Ordered list of SingleRunData -> SingleRunData callables to apply.

Returns:

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

Return type:

SingleRunData

Examples

>>> apply_preprocessing(data, [correct_motor_data, convert_wheelspeeds_to_m_per_s])
>>> apply_preprocessing(data, [
...     correct_motor_data(gear_ratio=6.2, tire_radius_in=8.0),
...     correct_steering_angle(((1.5, -90.0), (3.0, 0.0), (4.5, 90.0))),
... ])
perda.utils.preprocessing.convert_wheelspeeds_to_m_per_s = <perda.utils.preprocessing.ConvertWheelspeedsToMPerSLambda object>#

convert all four wheel speed channels from mph to m/s.

Each channel is converted in-place; the original mph values are preserved as <channel_name>_mph backup channels (only created once — idempotent on repeated calls).

Use directly in a preprocessing pipeline, or call with keyword arguments to get a reconfigured copy that operates on non-default variable names.

Examples

>>> Analyzer(preprocessing=[convert_wheelspeeds_to_m_per_s])
>>> Analyzer(preprocessing=[convert_wheelspeeds_to_m_per_s(wheelspeed_fr="my.ws.fr")])
Type:

Preprocessing step

Parameters:
  • data (SingleRunData | None)

  • wheelspeed_fr (str | None)

  • wheelspeed_fl (str | None)

  • wheelspeed_rr (str | None)

  • wheelspeed_rl (str | None)

Return type:

SingleRunData | ConvertWheelspeedsToMPerSLambda

perda.utils.preprocessing.correct_motor_data = <perda.utils.preprocessing.CorrectMotorDataLambda object>#

flip motor RPM sign and derive driven wheel speed.

The motor reports RPM with the sign inverted (negative when driving forward). This step:

  1. Preserves the original RPM as <motor_rpm>_raw.

  2. Flips the sign of the RPM channel in-place.

  3. Derives a driven wheel linear speed (m/s) from RPM, gear ratio, and tire radius, and writes it to motor_wheelspeed.

Use directly in a preprocessing pipeline, or call with keyword arguments to get a reconfigured copy with different physical constants or variable names.

Examples

>>> Analyzer(preprocessing=[correct_motor_data])
>>> Analyzer(preprocessing=[correct_motor_data(gear_ratio=6.2, tire_radius_in=8.0)])
Type:

Preprocessing step

Parameters:
  • data (SingleRunData | None)

  • gear_ratio (float | None)

  • tire_radius_in (float | None)

  • motor_rpm (str | None)

  • motor_wheelspeed (str | None)

Return type:

SingleRunData | CorrectMotorDataLambda

perda.utils.preprocessing.correct_steering_angle = <perda.utils.preprocessing.CorrectSteeringAngleLambda object>#

recompute steering angle from raw potentiometer voltage.

Fits a polynomial through a set of (voltage, angle_deg) calibration points, then evaluates it on the raw voltage channel to produce a corrected angle. This corrects for sensor drift relative to the previously stored angle channel.

If the angle channel already exists, the old values are preserved as <steering_angle>_original before being overwritten. The backup is only created once — idempotent on repeated calls.

Use directly in a preprocessing pipeline, or call with keyword arguments to get a reconfigured copy.

Examples

>>> Analyzer(preprocessing=[correct_steering_angle])
>>> Analyzer(preprocessing=[correct_steering_angle(calibration=((1.5, -90.0), (3.0, 0.0), (4.5, 90.0)))])
>>> Analyzer(preprocessing=[correct_steering_angle(steering_raw="my.raw")])
>>> Analyzer(preprocessing=[correct_steering_angle(calibration=my_cal, steering_angle="my.angle")])
Type:

Preprocessing step

Parameters:
  • data (SingleRunData | None)

  • calibration (tuple[tuple[float, float], ...] | None)

  • steering_raw (str | None)

  • steering_angle (str | None)

Return type:

SingleRunData | CorrectSteeringAngleLambda

perda.utils.preprocessing.patch_ned_velocity = <perda.utils.preprocessing.PatchNedVelocityLambda object>#

fix VectorNav NED-in-body-frame bug.

Corrects a firmware bug where velocityBody.x/y/z contains NED-frame velocities instead of body-frame (FRD) velocities. The raw NED values are preserved as new channels (velN, velE, velD), and the body velocity channels are overwritten with the correctly rotated values using the yaw angle.

Use directly in a preprocessing pipeline, or call with keyword arguments to get a reconfigured copy that operates on non-default variable names.

Examples

>>> Analyzer(preprocessing=[patch_ned_velocity])
>>> Analyzer(preprocessing=[patch_ned_velocity(yaw="my.custom.yaw")])
>>> Analyzer(preprocessing=[patch_ned_velocity(body_vel_x="my.vel.x", ned_vel_n="my.ned.n")])
Type:

Preprocessing step

Parameters:
  • data (SingleRunData | None)

  • body_vel_x (str | None)

  • body_vel_y (str | None)

  • body_vel_z (str | None)

  • yaw (str | None)

  • ned_vel_n (str | None)

  • ned_vel_e (str | None)

  • ned_vel_d (str | None)

Return type:

SingleRunData | PatchNedVelocityLambda