libstp.step.wait_for_light

Automatic wait-for-light using Kalman-filtered flank detection.

Designed for a downward-facing light sensor (no shielding required). A Kalman filter tracks the ambient baseline. When the start lamp turns on, light reflects off the table surface and the sensor value drops sharply. The step triggers when the raw reading falls below a configurable fraction of the filtered baseline for several consecutive samples.

Based on: “Comprehensive Light-Start Methods in Botball” (Gosling et al.)

Classes

WaitForLight

Automatic light-start with Kalman-filtered flank detection.

WaitForLightLegacy

Legacy threshold-based wait-for-light with manual calibration.

Functions

wait_for_light(→ WaitForLight)

Wait for the start lamp using automatic Kalman-filtered flank detection.

wait_for_light_legacy(→ WaitForLightLegacy)

Wait for light using the legacy manual-calibration threshold method.

Module Contents

class libstp.step.wait_for_light.WaitForLight(sensor: libstp.hal.AnalogSensor, drop_fraction: float, confirm_count: int, warmup_seconds: float, poll_interval: float)

Bases: libstp.ui.UIStep

Automatic light-start with Kalman-filtered flank detection.

class libstp.step.wait_for_light.WaitForLightLegacy(sensor: libstp.hal.AnalogSensor)

Bases: libstp.ui.UIStep

Legacy threshold-based wait-for-light with manual calibration.

libstp.step.wait_for_light.wait_for_light(sensor: libstp.hal.AnalogSensor, *, drop_fraction: float = 0.15, confirm_count: int = 3, warmup_seconds: float = 1.0, poll_interval: float = 0.005) WaitForLight

Wait for the start lamp using automatic Kalman-filtered flank detection.

Mount the light sensor facing downward with no shielding. The step establishes a stable baseline reading via a 1D Kalman filter during a short warm-up phase, then arms and polls for a sharp brightness increase (sensor value drop). When the raw reading falls below baseline * (1 - drop_fraction) for confirm_count consecutive samples, the step returns and the mission begins.

The downward-facing mount reduces environmental noise by up to 76% compared to a horizontal mount (Gosling et al., 2023). No black tape or straw shielding is required.

Prerequisites:

An analog light sensor (LDR) connected to the Wombat and mounted facing the table surface. The start lamp should be positioned diagonally above the sensor.

Parameters:
  • sensor – The AnalogSensor instance for the light sensor.

  • drop_fraction – Fraction the raw value must drop below the baseline to trigger. 0.15 means a 15% brightness increase triggers the start. Lower values are more sensitive (faster but riskier), higher values are safer but need a stronger signal. Default 0.15.

  • confirm_count – Number of consecutive triggering samples required before starting. At the default 200 Hz poll rate, 3 samples equals ~15 ms of confirmation — effectively instant while rejecting single-sample noise spikes. Default 3.

  • warmup_seconds – Duration in seconds to collect baseline samples before arming the detector. Default 1.0.

  • poll_interval – Seconds between sensor reads. 0.005 gives ~200 Hz. Default 0.005.

Returns:

A WaitForLight step that blocks until the lamp turns on.

Example:

from libstp.step.wait_for_light import wait_for_light

# Default settings — works well for most setups
wait_for_light(robot.defs.wait_for_light_sensor)

# More sensitive (10% drop, 2 confirms) for weak lamp signal
wait_for_light(robot.defs.wait_for_light_sensor, drop_fraction=0.10, confirm_count=2)

# More conservative (20% drop, 5 confirms) for noisy environments
wait_for_light(robot.defs.wait_for_light_sensor, drop_fraction=0.20, confirm_count=5)
libstp.step.wait_for_light.wait_for_light_legacy(sensor: libstp.hal.AnalogSensor) WaitForLightLegacy

Wait for light using the legacy manual-calibration threshold method.

Runs the traditional two-step calibration flow: the operator measures the sensor with the lamp off, then with it on, confirms the threshold, and the robot starts immediately. This approach requires manual interaction at the start of each run and uses a fixed midpoint threshold between the dark and light readings.

Use this only if the automatic flank-detection method (wait_for_light) does not work for your setup, for example when the sensor is not mounted downward or when the lamp signal is too weak for reliable flank detection.

Parameters:

sensor – The AnalogSensor instance for the light sensor.

Returns:

A WaitForLightLegacy step that runs manual calibration.

Example:

from libstp.step.wait_for_light import wait_for_light_legacy

wait_for_light_legacy(robot.defs.wait_for_light_sensor)