Files
StarPilot/openpilot/common/tests/test_scalar_clip.py
T
firestar5683 6d742eb343 CI
Add control trace and platform qualification tools that exercise explicit safety modes and vehicle coverage.

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com>
Co-authored-by: Kacper Rączy <gfw.kra@gmail.com>
Co-authored-by: YassineYousfi <yyousfi1@binghamton.edu>
Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com>

Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com>

Co-authored-by: prabhaavp <prabhaav@msu.edu>
2026-10-14 19:56:17 -05:00

58 lines
2.2 KiB
Python

import math
import random
import struct
import unittest
import warnings
import numpy as np
from openpilot.common.scalar_clip import clip_scalar
class TestScalarClip(unittest.TestCase):
def compare(self, value, lower, upper):
results = []
for function in (lambda v, lo, hi: float(np.clip(v, lo, hi)), clip_scalar):
with warnings.catch_warnings(record=True) as seen:
warnings.simplefilter('always')
try:
result = ('value', struct.pack('>d', function(value, lower, upper)))
except Exception as error:
result = ('error', type(error), str(error))
results.append((result, [(warning.category, str(warning.message)) for warning in seen]))
self.assertEqual(results[0], results[1], (value, lower, upper))
def test_binary64_inputs_match_numpy_exactly(self):
randomizer = random.Random(20261015)
def finite():
while True:
value = struct.unpack('>d', randomizer.getrandbits(64).to_bytes(8, 'big'))[0]
if math.isfinite(value):
return value
for _ in range(3000):
lower, upper = sorted((finite(), finite()))
value = finite()
self.compare(value, lower, upper)
self.compare(np.float64(value), lower, upper)
def test_boundary_bits_and_nonfinite_inputs(self):
values = (-0.0, 0.0, -math.ulp(0.0), math.ulp(0.0), -1.0, 1.0,
math.nextafter(1.0, -math.inf), math.nextafter(1.0, math.inf),
-math.inf, math.inf, math.nan)
bounds = ((-1.0, 1.0), (-0.0, 1.0), (0.0, 1.0), (-1.0, -0.0), (-1.0, 0.0),
(-0.0, 0.0), (0.0, -0.0), (1.0, 1.0), (1.0, -1.0),
(-math.inf, math.inf), (math.nan, 1.0), (-1.0, math.nan))
for lower, upper in bounds:
for value in values:
self.compare(value, lower, upper)
self.compare(np.float64(value), lower, upper)
def test_other_types_keep_numpy_results_errors_and_warnings(self):
class FloatSubclass(float):
pass
values = (0, True, None, '0', np.float32(0.2), np.int64(2), FloatSubclass(0.2),
np.array(0.2), np.array([0.2]), np.array([0.2, 0.5]))
for value in values:
for lower, upper in ((-1.0, 1.0), (-1, 1), (np.float32(-1), np.float32(1))):
self.compare(value, lower, upper)