# SPDX-License-Identifier: Apache-2.0 """The CPU fp32 reference (``tt_streampetr.reference``) against ONNX Runtime on the three deployed ONNX graphs (PLAN.md 0.3 item 1; ORT runs them as-is, S:6). Gates: - before any data-dependent selection: PCC >= 0.9999 (``img_feats``, ``pos_embed`` / ``cone``, every head output computed before the top-256: cls, bbox, ``outs_dec``, the decoder inputs); - after it (the top-256 selection, the post-update memory rows, the detections): set-based or teacher-forced -- the top-256 overlap, the post memory with ORT's own selection (recovered from its ``post_memory_embedding``), and the detection F1 of the end-to-end runs (same label, 1 m). Runs in the research venv (onnxruntime); skipped where onnxruntime, torch or the weights are absent:: cd bundles/streampetr-p150 && OMP_NUM_THREADS=3 PYTHONPATH=$PWD/code \\ /home/ubuntu/experiments/tt-models/tools/research-venv/bin/python -m pytest -q -s -p no:cacheprovider \\ code/tt_streampetr/tests/test_reference_cpu.py Inputs: the staged PandaSet sample (frames 40-43 through the full node pipeline) and the research teacher-forcing records of the public sequences (``research/streampetr/public_data``; nuScenes is internal only). """ from __future__ import annotations import os import numpy as np import pytest ort = pytest.importorskip("onnxruntime") torch = pytest.importorskip("torch") pytest.importorskip("onnx") from tt_streampetr.host import inputs as hin # noqa: E402 from tt_streampetr.host import postprocess as hp # noqa: E402 from tt_streampetr.host.agreement import detection_f1, recover_topk_indices, topk_overlap # noqa: E402 from tt_streampetr.host.temporal import StreamState # noqa: E402 from tt_streampetr.reference.config import default_config # noqa: E402 from tt_streampetr.tests import paths # noqa: E402 from tt_streampetr.ttaw.metrics import pcc # noqa: E402 REF_PCC = 0.9999 # PLAN.md 0.3 item 1 CFG = default_config() THREADS = int(os.environ.get("STREAMPETR_TEST_THREADS", "3")) # workspace rule: <= 4 CPU threads PRE_SELECTION = ("all_cls_scores", "all_bbox_preds", "outs_dec", "reference_points", "tgt", "query_pos", "temp_memory", "temp_pos", "query_pos_in") POST_MEMORY = ("post_memory_embedding", "post_memory_reference_point", "post_memory_egopose", "post_memory_velo") FRAMES = (40, 41, 42, 43) @pytest.fixture(scope="module") def weights(): w = paths.weights_dir() if w is None: pytest.skip("camera_streampetr v1.0 weights not found (set STREAMPETR_WEIGHTS_DIR)") return w @pytest.fixture(scope="module") def oracle(weights): from tt_streampetr.reference.ort import OrtOracle return OrtOracle(weights, threads=THREADS) @pytest.fixture(scope="module") def reference(weights): from tt_streampetr.reference.pipeline import StreamPETRReference return StreamPETRReference(weights, CFG, threads=THREADS, preprocess_workers=2) @pytest.fixture(scope="module") def sample_run(reference, oracle): """The staged PandaSet sample (019 frames 40-43, one stream from a cold start) through the reference pipeline and, with the same host inputs and the same host memory loop, through ORT.""" from tt_streampetr.ttaw.golden import TapRegistry paths.need_pandaset() reference.streams.clear() st_ort = StreamState(CFG) runs = [] for f in FRAMES: kw = hin.load_sample(paths.pandaset_sample(f)) taps = TapRegistry(include=("img_feats",)) det, outs, plan, img = reference(**kw, taps=taps, return_outputs=True) frame = hin.prepare_frame(**kw, cfg=CFG) p_ort = st_ort.begin(frame.anchor_stamp, frame.stream.T_world_from_ego, frame.camera_stamps) pe_o = oracle.position_embedding(**frame.rig.pe_inputs()) feats_o = oracle.backbone(img) feeds = {"x": feats_o, "pos_embed": pe_o["pos_embed"], "cone": pe_o["cone"], "data_ego_pose": p_ort.E, "data_ego_pose_inv": p_ort.Einv, **p_ort.pre} outs_o = oracle.head(feeds) st_ort.end(p_ort, outs_o) runs.append({"frame": f, "img": img, "rig": frame.rig, "plan": plan, "outs": outs, "det": det, "feats_o": feats_o, "pe_o": pe_o, "feeds_o": feeds, "outs_o": outs_o, "plan_o": p_ort}) return runs def test_backbone_vs_ort(sample_run): for r in sample_run[:2]: p = pcc(r["outs"]["img_feats"], r["feats_o"]) print(f" frame {r['frame']} img_feats pcc={p:.12f} max_abs=" f"{np.abs(r['outs']['img_feats'] - r['feats_o']).max():.2e} (|x| <= {np.abs(r['feats_o']).max():.0f})") assert p >= REF_PCC def test_position_embedding_vs_ort(reference, sample_run): r = sample_run[0] pos, cone = reference.position_embedding(r["rig"]) p = pcc(pos, r["pe_o"]["pos_embed"]) print(f" pos_embed pcc={p:.12f} max_abs={np.abs(pos - r['pe_o']['pos_embed']).max():.2e}; cone max_abs=" f"{np.abs(cone - r['pe_o']['cone']).max():.2e}") assert p >= REF_PCC and pcc(cone, r["pe_o"]["cone"]) >= REF_PCC def test_head_vs_ort_on_the_same_inputs(reference, sample_run): """The head with ORT's own inputs (ORT backbone / PE / memory) at every frame of the sample.""" for r in sample_run: fo = r["feeds_o"] pre = {k: fo[k] for k in fo if k.startswith("pre_")} out = reference.head(fo["x"], fo["pos_embed"], fo["cone"], fo["data_ego_pose"], fo["data_ego_pose_inv"], pre) for k in PRE_SELECTION: p = pcc(out[k], r["outs_o"][k]) assert p >= REF_PCC, (r["frame"], k, p) idx_o = recover_topk_indices(r["outs_o"]["post_memory_embedding"], r["outs_o"]["outs_dec"]) ov = topk_overlap(out["topk_idx"].reshape(-1), idx_o) tf = reference.head(fo["x"], fo["pos_embed"], fo["cone"], fo["data_ego_pose"], fo["data_ego_pose_inv"], pre, topk_idx=idx_o) worst = min(pcc(tf[k], r["outs_o"][k]) for k in POST_MEMORY) print(f" frame {r['frame']}: cls pcc={pcc(out['all_cls_scores'], r['outs_o']['all_cls_scores']):.10f} " f"top-256 overlap={ov:.4f} teacher-forced post-memory min pcc={worst:.10f}") assert ov >= 0.99 and worst >= REF_PCC assert np.array_equal(tf["post_memory_timestamp"], r["outs_o"]["post_memory_timestamp"]) def test_end_to_end_detections_vs_ort(sample_run): """Free-running over the 4 frames (each side with its own memory): the node's objects agree (set-based).""" for r in sample_run: ours = hp.autoware_postprocess(r["outs"]["all_cls_scores"], r["outs"]["all_bbox_preds"], CFG)["objects"] theirs = hp.autoware_postprocess(r["outs_o"]["all_cls_scores"], r["outs_o"]["all_bbox_preds"], CFG)["objects"] m = detection_f1(ours, theirs, dist=1.0) print(f" frame {r['frame']}: {len(ours)} vs {len(theirs)} objects, F1={m['f1']:.4f} " f"centre err max {m['centre_err_max']:.4f} m, score err max {m['score_err_max']:.2e}") assert m["f1"] >= 0.99 and m["centre_err_max"] < 0.05 assert r["det"].to_dict()["num_detections"] == len(ours) def _tf_records(): out = [] for run, f in (("ns0103", 1), ("ns0916", 0)): g = paths.public_golden(run) if g is not None and (g / f"tf_{f:04d}.npz").is_file(): out.append((run, f)) return out @pytest.mark.parametrize("run,frame", _tf_records(), ids=[f"{r}-{f}" for r, f in _tf_records()]) def test_head_vs_ort_on_nuscenes_records(reference, oracle, run, frame): """A second rig (1600x900 nuScenes cameras, internal validation data): PE and head vs ORT.""" g = paths.public_golden(run) rec, pe = np.load(g / f"tf_{frame:04d}.npz"), np.load(g / "pe_inputs_outputs.npz") pe_o = oracle.position_embedding(pe["img_metas_pad"], pe["intrinsics"], pe["img2lidar"]) pos, cone = reference.net.pe(pe["img_metas_pad"], pe["intrinsics"], pe["img2lidar"]) assert pcc(pos.detach().numpy(), pe_o["pos_embed"]) >= REF_PCC pre = {k: rec[k] for k in rec.files if k.startswith("pre_")} feeds = {"x": rec["img_feats"], "pos_embed": pe_o["pos_embed"], "cone": pe_o["cone"], "data_ego_pose": rec["data_ego_pose"], "data_ego_pose_inv": rec["data_ego_pose_inv"], **pre} outs_o = oracle.head(feeds) out = reference.head(rec["img_feats"], pe_o["pos_embed"], pe_o["cone"], rec["data_ego_pose"], rec["data_ego_pose_inv"], pre) for k in PRE_SELECTION: assert pcc(out[k], outs_o[k]) >= REF_PCC, k