commaai/openpilot · error · ValueError

invalid speed group, see help

Error message

invalid speed group, see help

What it means

Raised by __init__ of the stats class in measure_steering_accuracy.py when the --group argument is neither 'all' nor one of the defined speed-group keys ('residential', '30-50mph', '70mph', 'crawl' per all_groups). It is a simple CLI argument validation error: the script could not map your group string to a speed bucket.

Source

Thrown at tools/car_porting/measure_steering_accuracy.py:34

class SteeringAccuracyTool:
  all_groups = {"germany":  (45, "45 - up m/s  //  162 - up km/h  //  101 - up mph"),
                "veryfast": (35, "35 - 45 m/s  //  126 - 162 km/h  //  78 - 101 mph"),
                "fast":     (25, "25 - 35 m/s  //  90 - 126 km/h  //  56 - 78 mph"),
                "medium":   (15, "15 - 25 m/s  //  54 - 90 km/h  //  34 - 56 mph"),
                "slow":     (5,  " 5 - 15 m/s  //  18 - 54 km/h  //  11 - 34 mph"),
                "crawl":    (0,  " 0 - 5 m/s  //  0 - 18 km/h  //  0 - 11 mph")}

  def __init__(self, args):
    self.msg_cnt = 0
    self.cnt = 0
    self.total_error = 0

    if args.group == "all":
      self.display_groups = self.all_groups.keys()
    elif args.group in self.all_groups.keys():
      self.display_groups = [args.group]
    else:
      raise ValueError("invalid speed group, see help")

    self.speed_group_stats = {}
    for group in self.all_groups:
      self.speed_group_stats[group] = defaultdict(lambda: {'err': 0, "cnt": 0, "=": 0, "+": 0, "-": 0, "steer": 0, "limited": 0, "saturated": 0, "dpp": 0})

  def update(self, sm):
    self.msg_cnt += 1

    lateralControlState = sm['controlsState'].lateralControlState
    control_type = list(lateralControlState.to_dict().keys())[0]
    control_state = lateralControlState.__getattr__(control_type)

    v_ego = sm['carState'].vEgo
    active = sm['controlsState'].active
    steer = sm['carOutput'].actuatorsOutput.torque
    standstill = sm['carState'].standstill
    steer_limited_by_safety = abs(sm['carControl'].actuators.torque - sm['carControl'].actuatorsOutput.torque) > 1e-2
    overriding = sm['carState'].steeringPressed

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Run the script with --help and copy a valid group name exactly (e.g. --group '30-50mph' with quotes).
  2. Use --group all if you want all speed buckets instead of guessing a name.
  3. Check the all_groups dict at the top of tools/car_porting/measure_steering_accuracy.py for the exact accepted keys in your checkout.

Example fix

# before
python tools/car_porting/measure_steering_accuracy.py --group residential2

# after
python tools/car_porting/measure_steering_accuracy.py --group all
Defensive patterns

Strategy: validation

Validate before calling

from tools.car_porting.measure_steering_accuracy import SpeedStats  # module containing all_groups
valid = set(SpeedStats.all_groups) | {'all'}
if args.group not in valid:
    raise SystemExit(f"--group must be one of {sorted(valid)}")

Try / catch

try:
    stats = SpeedStats(args)
except ValueError as e:
    if 'invalid speed group' in str(e):
        print(f"valid groups: {sorted(set(SpeedStats.all_groups) | {'all'})}"); sys.exit(2)
    raise

Prevention

When it happens

Trigger: Running measure_steering_accuracy.py --group <name> where <name> is misspelled (e.g. 'residental', '30-50', 'City') or omitted-but-defaulted to an invalid value. Valid choices are exactly the keys of all_groups plus the literal 'all'.

Common situations: Typos from memory instead of --help, using group names from an older version of the script whose buckets were renamed, or passing units ('mph') instead of the bucket key.

Related errors


AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15). Data as JSON: /api/errors/3de6370f18f4f4a0. Report an issue: GitHub.