step.calibration.setup.session

Robot service that accumulates setup-time calibration evidence.

The service is a passive ledger: CollectDrive / CollectIrSet record opportunistic samples into it during the setup mission, and CalibrationGate reads them back to finalize the persisted compensation layers. It never changes the active odometry source or applies a trim itself — that is the gate’s job.

Classes

CalibrationAxis

Create a collection of name/value pairs.

DriveCalibrationSample

IrCalibrationSet

SetupCalibrationSession

Accumulates setup-time calibration evidence and applies a final trim.

Module Contents

class step.calibration.setup.session.CalibrationAxis(*args, **kwds)

Bases: enum.Enum

Create a collection of name/value pairs.

Example enumeration:

>>> class Color(Enum):
...     RED = 1
...     BLUE = 2
...     GREEN = 3

Access them by:

  • attribute access:

    >>> Color.RED
    <Color.RED: 1>
    
  • value lookup:

    >>> Color(1)
    <Color.RED: 1>
    
  • name lookup:

    >>> Color['RED']
    <Color.RED: 1>
    

Enumerations can be iterated over, and know how many members they have:

>>> len(Color)
3
>>> list(Color)
[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]

Methods can be added to enumerations, and members can have their own attributes – see the documentation for details.

FORWARD = 'forward'
LATERAL = 'lateral'
class step.calibration.setup.session.DriveCalibrationSample
axis: CalibrationAxis
odom_distance_m: float
ground_truth_distance_m: float
source: str
property scale: float

Absolute distance-trim scale this sample implies (odom / ground_truth).

The trim is applied as commanded * scale and the gate assigns this value directly via MotionTrimService.set_axis_scale (it is the target scale, not a delta — so it is set, never composed; composing would diverge geometrically on repeated calibration). odom_distance and ground_truth are measured over the same physical drive, so the ratio is independent of whatever scale was active during the drive.

Direction: the internal odometry regulates the drive, so when it over-reports (odom > ground_truth, e.g. 56.7cm odom for 53.0cm actually travelled) a commanded distance under-shoots physically. The scale is then > 1 to lengthen the commanded target back onto the real distance — this is verified against hardware (a < 1 scale here drives the robot SHORT).

A distance trim is a magnitude correction, so it is inherently positive. Absolute distances are used because the calibration board’s pose frame has a constant 180° mounting offset — its projected displacement may carry the opposite sign of the internal odometry even though both measure the same forward travel, and a signed ratio would yield a bogus negative scale.

class step.calibration.setup.session.IrCalibrationSet
sensor_ports: set[int]
samples_by_port: dict[int, list[float]]
add(port: int, samples: list[float]) None
has_minimum_samples(min_samples: int) bool
class step.calibration.setup.session.SetupCalibrationSession(robot: raccoon.robot.api.GenericRobot)

Accumulates setup-time calibration evidence and applies a final trim.

property board_available: bool
property gate_completed: bool
mark_pending() None
require_axis(axis: CalibrationAxis) None
require_ir_set(set_name: str) None
axes_to_finalize(requested: list[CalibrationAxis] | None) list[CalibrationAxis]
ir_sets_to_finalize(requested: list[str] | None) list[str]
add_drive_sample(sample: DriveCalibrationSample) None
get_drive_samples(axis: CalibrationAxis) list[DriveCalibrationSample]
clear_drive_samples(axis: CalibrationAxis) None

Drop all accumulated samples for an axis (operator asked to re-drive).

add_ir_samples(set_name: str, sensor_ports: list[int], samples_by_port: dict[int, list[float]]) None
get_ir_set(set_name: str) IrCalibrationSet
finish_gate() None
median_axis_scale(axis: CalibrationAxis) float

Median distance-trim scale across this axis’ samples (1.0 if none).

median_axis_sample(axis: CalibrationAxis) DriveCalibrationSample | None

The sample whose scale is the median, for a representative summary.

Returns None when the axis has no samples. The applied trim is always median_axis_scale(); this just picks a real (odom, ground_truth) pair to display alongside it.

ensure_board_probe(robot: raccoon.robot.api.GenericRobot, log_step) None
static capture_internal_snapshot(robot: raccoon.robot.api.GenericRobot) _PoseSnapshot
static capture_reference_snapshot(robot: raccoon.robot.api.GenericRobot) _PoseSnapshot
static reference_pose(robot: raccoon.robot.api.GenericRobot)

Read the calibration-board pose directly, without changing the active source.

static axis_distance_m(start: _PoseSnapshot, end_pose, axis: CalibrationAxis) float
static detect_axis(start: _PoseSnapshot, end_pose) CalibrationAxis

Infer the driven axis from the dominant internal-odometry displacement.