TurtleBotJEPA-PPO / tests /test_adapter.py
penji2803's picture
TurtleBotJEPA-PPO: ready-to-run JEPA + PPO policy for a real TurtleBot3 (LDS-02), guide incl. mapping and map goals
4421dc3 verified
Raw History Blame Contribute Delete
3.13 kB
"""Unit tests for the LDS-02 adapter (no ROS): python3 tests/test_adapter.py"""
import math
import os
import sys
import numpy as np
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from lds02 import ScanCleaner, lds02_corrupt, sample_params # noqa: E402
from lds02_adapter import FRONT_IDX, RAY_ANGLES, LidarAdapter, bin_scan # noqa: E402
def scene(angles):
"""Ranges seen from the origin: wall at 2 m everywhere, a 0.5 m object straight ahead (+-10 deg), one at 1 m on
the left (80..100 deg)."""
a = np.mod(angles, 2 * math.pi)
r = np.full(len(a), 2.0)
r[(a < math.radians(10)) | (a > math.radians(350))] = 0.5
r[(a > math.radians(80)) & (a < math.radians(100))] = 1.0
return r
def test_layouts():
for n, amin, sign in ((230, 0.0, 1), (360, 0.0, 1), (460, 0.0, 1), (360, -math.pi, 1), (360, 0.0, -1), (455, 1.0, -1)):
inc = sign * 2 * math.pi / n
ang = amin + np.arange(n) * inc
out, seen = bin_scan(scene(ang), amin, inc)
ref = scene(RAY_ANGLES)
ok = np.mean(np.abs(out - ref) < 1e-6)
assert ok > 0.97, (n, amin, sign, ok) # only edge rays may differ by a bin
assert out[0] == 0.5 and abs(out[90] - 1.0) < 1e-6 and out[180] == 2.0, (n, amin, sign)
print('layouts ok (230 / 360 / 460 points, offset start, clockwise)')
def test_invalid_and_hold():
c = ScanCleaner()
s1 = np.full(360, 2.0); s1[40:45] = 0.25
s2 = np.full(360, 2.0); s2[40:45] = 0.0; s2[300] = np.inf
c(s1, 0.0)
o, held = c(s2, 0.2)
assert abs(o[42] - 0.25) < 1e-6 and o[300] == 3.5 and held == 5
o, _ = c(np.zeros(360), 1.0)
assert (o == 3.5).all()
print('invalid readings / near-field hold ok')
def test_sim_equivalence():
"""The simulator path (Gazebo 360 rays -> lds02_corrupt -> ScanCleaner, front beams by FRONT_GRID) and the robot
path (LaserScan -> bin_scan -> ScanCleaner) give identical frames for the same raw readings."""
rng = np.random.default_rng(0)
p = sample_params(rng)
ad, cl = LidarAdapter(), ScanCleaner()
for k in range(12):
raw = lds02_corrupt(scene(RAY_ANGLES) - 0.05 * k, rng, p)
ad.push(raw, 0.0, 6.28 / 359, 0.2 * k)
sim, _ = cl(raw, 0.2 * k)
assert np.array_equal(ad.frames[-1], sim)
assert np.array_equal(ad.front_beams(0), sim[FRONT_IDX])
x, v = ad.window()
assert x.shape == (20, 360) and v.sum() == 12 and x.min() >= 0.12 and x.max() <= 3.5
print('sim / robot pipelines identical')
def test_timing():
ad = LidarAdapter()
added = [ad.push(np.full(360, 2.0), 0.0, 6.28 / 359, t) for t in np.arange(0, 2.0, 0.1)] # a 10 Hz lidar
assert sum(added) == 10
ad = LidarAdapter()
added = [ad.push(np.full(360, 2.0), 0.0, 6.28 / 359, t) for t in np.arange(0, 2.0, 1 / 5.8)] # a 5.8 Hz LDS-02
assert all(added)
print('frame timing ok (10 Hz -> every other scan, 5.8 Hz -> every scan)')
if __name__ == '__main__':
test_layouts()
test_invalid_and_hold()
test_sim_equivalence()
test_timing()
print('ALL TESTS PASSED')