suboptimumg.log_analysis.yaw_segmentation#

suboptimumg.log_analysis.yaw_segmentation.add_ax_from_speed(data, speed_col='pcm.vnav.velocityBody.x', out_col='ax.fromSpeed', smooth_hz=2.0)[source]#

Add longitudinal acceleration as the time derivative of speed.

Differentiation amplifies high-frequency noise, so the derivative is lowpass-filtered at smooth_hz (zero-phase, so no group delay is introduced). Duplicate and out-of-order timestamps are repaired first – a single bad sample would otherwise poison the whole signal through the filter.

Parameters:
  • data (SingleRunData)

  • speed_col (str) – Source speed channel (m/s).

  • out_col (str) – Destination acceleration channel (m/s^2).

  • smooth_hz (float) – Lowpass cutoff (Hz); 0 disables smoothing.

Returns:

data, with out_col added, returned for chaining.

Return type:

SingleRunData

suboptimumg.log_analysis.yaw_segmentation.auto_segment(data, manual_windows, min_speed_mps=4.0, max_slip_deg=7.0, min_window_s=8.0, speed_col='pcm.vnav.velocityBody.x', slip_col='body.slipAngle')[source]#

Split each coarse window into clean sub-windows by masking.

Within each window, samples below min_speed_mps (the car is not really driving, and every 1/V term blows up) or above max_slip_deg of body slip (the tires are past the linear region the bicycle model describes) are dropped. Surviving runs shorter than min_window_s carry too little low-frequency content to identify anything and are dropped too.

Parameters:
  • data (SingleRunData)

  • manual_windows (list of (t_start, t_end)) – Coarse windows (s), typically read off the GPS trajectory.

  • min_speed_mps (float) – Mask and length thresholds.

  • max_slip_deg (float) – Mask and length thresholds.

  • min_window_s (float) – Mask and length thresholds.

  • speed_col (str)

  • slip_col (str)

Returns:

  • subwindows (list of SingleRunData) – A flat list of every accepted sub-window, across all manual windows.

  • reports (list of MaskReport) – One report per manual window.

Return type:

tuple[list[SingleRunData], list[MaskReport]]

suboptimumg.log_analysis.yaw_segmentation.resample_subwindows(subwindows, target_hz=100.0, method=ResampleMethod.LINEAR)[source]#

Put every sub-window channel on a common uniform grid at target_hz.

Raw logs run near 1 kHz with dt jitter, but the yaw mode is only a few Hz wide, so 100 Hz is ample and roughly ten times cheaper to simulate. Landing every channel on the same grid also makes the later left-join a no-op.

Parameters:
  • subwindows (list of SingleRunData) – Output of auto_segment.

  • target_hz (float)

  • method (ResampleMethod)

Returns:

New sub-windows on the uniform grid. Channels with fewer than two samples are dropped, and a sub-window left with no channels at all is omitted.

Return type:

list of SingleRunData

suboptimumg.log_analysis.yaw_segmentation.scan_speed_stationarity(data, win_lengths_s=(3.0, 5.0, 8.0, 12.0, 20.0), tol_pcts=(2.5, 5.0, 10.0, 15.0), speed_col='pcm.vnav.velocityBody.x', overlap=0.5)[source]#

Measure how often the car holds an approximately constant speed.

For each (window length, tolerance) pair, count the fraction of sliding windows whose peak-to-peak speed stays within tolerance percent of the window mean. Near-zero fractions at the long windows are the evidence that a nonparametric FRF will not work on this data.

Parameters:
  • data (SingleRunData)

  • win_lengths_s (tuple of float) – Sliding-window lengths to test (s).

  • tol_pcts (tuple of float) – Allowed peak-to-peak speed variation, as a percent of the window mean.

  • speed_col (str)

  • overlap (float) – Window overlap fraction (0 = none, 0.5 = 50%).

Return type:

StationarityReport

Notes

Lapping data is not a frequency-response test: the car is accelerating, braking, and occasionally sliding. This scan quantifies how rarely the speed is even approximately constant, and is the justification for identifying the yaw response with a parametric LPV output-error fit (yaw_fit) rather than a nonparametric Welch FRF, which would need long constant-speed holds this data does not contain.

suboptimumg.log_analysis.yaw_segmentation.summarize_subwindows(subwindows, ax_col='ax.fromSpeed', input_col='ludwig.steeringWheel.angle', speed_col='pcm.vnav.velocityBody.x', slip_col='body.slipAngle')[source]#

Per-sub-window quality summary, for triaging windows before fitting.

Duration and steering excitation say whether a window can identify anything; speed hold and |a_x| say how hard the LPV scheduling is working; slip RMS says how close to the linear region it stayed.

Parameters:
  • subwindows (list of SingleRunData)

  • ax_col (str) – Channels to summarize. Any that are absent are reported as NaN.

  • input_col (str) – Channels to summarize. Any that are absent are reported as NaN.

  • speed_col (str) – Channels to summarize. Any that are absent are reported as NaN.

  • slip_col (str) – Channels to summarize. Any that are absent are reported as NaN.

Return type:

list of SubwindowSummary