Back to Repositories

Testing Longitudinal Control State Transitions in OpenPilot

This test suite validates the longitudinal control state transitions in the OpenPilot autonomous driving system. It ensures proper state management for vehicle stopping, starting, and engagement conditions across different driving scenarios.

Test Coverage Overview

The test suite provides comprehensive coverage of longitudinal control state transitions in OpenPilot.

Key areas tested include:
  • Vehicle stopping state management
  • System engagement transitions
  • Starting state behavior
  • State transitions based on speed conditions
Edge cases covered include brake pressure scenarios, cruise control standstill conditions, and varying vehicle speeds.

Implementation Analysis

The testing approach uses state transition validation through the LongCtrlState enumeration and long_control_state_trans function. The implementation follows a systematic pattern of testing state transitions under different combinations of input parameters including vehicle speed, brake status, and cruise control conditions.

Each test case validates specific transition paths between states like ‘off’, ‘stopping’, ‘starting’, and ‘pid’.

Technical Details

Testing tools and components:
  • Python unit testing framework
  • Cereal car parameter messaging system
  • LongCtrlState enumeration for state management
  • CarParams configuration object
  • State transition validation assertions

Best Practices Demonstrated

The test suite demonstrates strong testing practices through isolated state transition validation and comprehensive condition coverage.

Notable practices include:
  • Systematic state transition verification
  • Clear test case organization by functionality
  • Comprehensive parameter combination testing
  • Proper test isolation and setup

commaai/openpilot

selfdrive/controls/tests/test_longcontrol.py

            
from cereal import car
from openpilot.selfdrive.controls.lib.longcontrol import LongCtrlState, long_control_state_trans




class TestLongControlStateTransition:

  def test_stay_stopped(self):
    CP = car.CarParams.new_message()
    active = True
    current_state = LongCtrlState.stopping
    next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
                             should_stop=True, brake_pressed=False, cruise_standstill=False)
    assert next_state == LongCtrlState.stopping
    next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
                             should_stop=False, brake_pressed=True, cruise_standstill=False)
    assert next_state == LongCtrlState.stopping
    next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
                             should_stop=False, brake_pressed=False, cruise_standstill=True)
    assert next_state == LongCtrlState.stopping
    next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0,
                             should_stop=False, brake_pressed=False, cruise_standstill=False)
    assert next_state == LongCtrlState.pid
    active = False
    next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0,
                             should_stop=False, brake_pressed=False, cruise_standstill=False)
    assert next_state == LongCtrlState.off

def test_engage():
  CP = car.CarParams.new_message()
  active = True
  current_state = LongCtrlState.off
  next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
                             should_stop=True, brake_pressed=False, cruise_standstill=False)
  assert next_state == LongCtrlState.stopping
  next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
                             should_stop=False, brake_pressed=True, cruise_standstill=False)
  assert next_state == LongCtrlState.stopping
  next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
                             should_stop=False, brake_pressed=False, cruise_standstill=True)
  assert next_state == LongCtrlState.stopping
  next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
                             should_stop=False, brake_pressed=False, cruise_standstill=False)
  assert next_state == LongCtrlState.pid

def test_starting():
  CP = car.CarParams.new_message(startingState=True, vEgoStarting=0.5)
  active = True
  current_state = LongCtrlState.starting
  next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
                             should_stop=False, brake_pressed=False, cruise_standstill=False)
  assert next_state == LongCtrlState.starting
  next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0,
                             should_stop=False, brake_pressed=False, cruise_standstill=False)
  assert next_state == LongCtrlState.pid