"""目标隔离测试(规格 §4:track_id 优先 + 框位置最近邻、帧末老化清理)。""" from stereo_ranger import StereoConfig, TargetStore CFG = StereoConfig() # isolation_gate_px = 50,filter_reset_frames = 5 def test_track_key_stable_across_position_move(): store = TargetStore(CFG) key_1 = store.resolve(0, 7, (100.0, 100.0), 1) key_2 = store.resolve(0, 7, (400.0, 100.0), 2) # 位置大幅移动仍是同一目标 assert key_1 == key_2 assert store.count == 1 def test_nearest_neighbor_keeps_identity_within_gate(): store = TargetStore(CFG) key_1 = store.resolve(0, None, (100.0, 100.0), 1) key_2 = store.resolve(0, None, (130.0, 140.0), 2) # 距离 50 ≤ 门限 assert key_1 == key_2 def test_beyond_gate_creates_new_key(): store = TargetStore(CFG) key_1 = store.resolve(0, None, (100.0, 100.0), 1) key_2 = store.resolve(0, None, (200.0, 100.0), 2) # 距离 100 > 门限 assert key_1 != key_2 assert store.count == 2 def test_class_id_separates_states(): store = TargetStore(CFG) assert store.resolve(0, None, (100.0, 100.0), 1) != store.resolve(1, None, (100.0, 100.0), 1) def test_two_boxes_same_frame_claim_distinct_states(): store = TargetStore(CFG) key_1 = store.resolve(0, None, (100.0, 100.0), 1) key_2 = store.resolve(0, None, (110.0, 100.0), 1) # 同帧第二框不得接管已占用状态 assert key_1 != key_2 assert store.count == 2 def test_state_evicted_after_reset_frames_unseen(): store = TargetStore(CFG) key = store.resolve(0, None, (100.0, 100.0), 1) store.distance_filter.advance(key, 5.0) store.consistency.advance(key, 9.6) for frame in range(2, 7): # 第 2~6 帧:连续 5 帧缺席 store.end_frame(frame) assert store.count == 0 assert store.distance_filter.value(key) is None assert store.consistency.streak(key) == 0 def test_present_but_invalid_keeps_position_state(): store = TargetStore(CFG) key = store.resolve(0, None, (100.0, 100.0), 1) store.distance_filter.advance(key, 5.0) for frame in range(2, 8): store.resolve(0, None, (100.0, 100.0), frame) # 每帧仍出现 store.distance_filter.invalidate(key) assert store.count == 1 # 位置状态保留 assert store.distance_filter.value(key) is None # 滤波状态已按门限清空 def test_clear_resets_everything(): store = TargetStore(CFG) key = store.resolve(0, 5, (100.0, 100.0), 1) store.distance_filter.advance(key, 5.0) store.clear() assert store.count == 0 assert store.distance_filter.value(key) is None