mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-10-28 00:53:45 +08:00
Include camera conversion in vision CPU budget
This commit is contained in:
@@ -247,7 +247,8 @@ def main() -> None:
|
||||
inference_interval_ns = _inference_interval_ns(processing_interval_ns, int(core.last_detection_at * 1e9), pair[0])
|
||||
if pair[0] - last_inference_ns < inference_interval_ns:
|
||||
continue
|
||||
last_inference_ns = pair[0]
|
||||
# Budget camera conversion together with inference, as in the original Dom loop.
|
||||
last_inference_ns = admission_pair[0]
|
||||
try:
|
||||
# The observation belongs to the original camera frame, not the end of
|
||||
# CPU inference. Completion never restamps an older camera observation.
|
||||
|
||||
@@ -294,57 +294,65 @@ class TestVisionProducer(unittest.TestCase):
|
||||
self.assertEqual(messages[0].speedMps, 0)
|
||||
|
||||
def test_followup_confirms_brief_candidate_without_changing_thresholds(self):
|
||||
core = VisionModelCore.__new__(VisionModelCore)
|
||||
core.is_metric = False
|
||||
core.history = deque()
|
||||
core.reset()
|
||||
client = Mock()
|
||||
client.is_connected.return_value = True
|
||||
camera = Mock(return_value=client)
|
||||
road = {VisionStreamType.VISION_STREAM_NARROW_ROAD}
|
||||
camera.available_streams.side_effect = [road] * 3 + [EndProducer()]
|
||||
sources = (1_000_000_000, 1_100_000_000, 1_300_000_000)
|
||||
buffers = [(object(), t + 4_000_000_000, i) for i, t in enumerate(sources)]
|
||||
frames = [(np.full((2, 2, 3), i), b[1], b[2]) for i, b in enumerate(buffers)]
|
||||
current = [0, 0]
|
||||
pending = iter(buffers)
|
||||
messages = []
|
||||
for conversion_ns, sources, expected in (
|
||||
(0, (1_000_000_000, 1_100_000_000, 1_300_000_000), ['unknown', 'valid', 'valid']),
|
||||
(80_000_000, (1_000_000_000, 1_200_000_000, 1_400_000_000), ['unknown', 'unknown']),
|
||||
):
|
||||
with self.subTest(conversion_ns=conversion_ns):
|
||||
core = VisionModelCore.__new__(VisionModelCore)
|
||||
core.is_metric = False
|
||||
core.history = deque()
|
||||
core.reset()
|
||||
client = Mock()
|
||||
client.is_connected.return_value = True
|
||||
camera = Mock(return_value=client)
|
||||
road = {VisionStreamType.VISION_STREAM_NARROW_ROAD}
|
||||
camera.available_streams.side_effect = [road] * 3 + [EndProducer()]
|
||||
buffers = [(object(), t + 4_000_000_000, i) for i, t in enumerate(sources)]
|
||||
frames = [(np.full((2, 2, 3), i), b[1], b[2]) for i, b in enumerate(buffers)]
|
||||
current = [0, 0]
|
||||
pending = iter(buffers)
|
||||
messages = []
|
||||
|
||||
def receive(_client):
|
||||
buffer = next(pending)
|
||||
current[:] = [buffer[2], 0]
|
||||
return buffer
|
||||
def receive(_client, pending=pending, current=current):
|
||||
buffer = next(pending)
|
||||
current[:] = [buffer[2], 0]
|
||||
return buffer
|
||||
|
||||
def clock_pair():
|
||||
now = sources[current[0]] + (10_000_000 if current[1] >= 2 else 0)
|
||||
current[1] += 1
|
||||
self.sm.logMonoTime['drivingModelData'] = now
|
||||
return now, now + 4_000_000_000
|
||||
def clock_pair(sources=sources, current=current, conversion_ns=conversion_ns):
|
||||
now = sources[current[0]] + (0, conversion_ns, conversion_ns + 10_000_000)[min(current[1], 2)]
|
||||
current[1] += 1
|
||||
self.sm.logMonoTime['drivingModelData'] = now
|
||||
return now, now + 4_000_000_000
|
||||
|
||||
def send(_service, event):
|
||||
messages.append(messaging.log_from_bytes(event.to_bytes()).slcVisionObservation.vision)
|
||||
def send(_service, event, messages=messages):
|
||||
messages.append(messaging.log_from_bytes(event.to_bytes()).slcVisionObservation.vision)
|
||||
|
||||
with patch('msgq.visionipc.VisionIpcClient', camera), \
|
||||
patch('openpilot.common.params.Params', return_value=SimpleNamespace(get_bool=lambda _: False)), \
|
||||
patch.object(messaging, 'PubMaster', return_value=SimpleNamespace(send=send)), \
|
||||
patch.object(producer, 'VisionModelCore', return_value=core), \
|
||||
patch.object(producer, '_camera_buffer', side_effect=receive), \
|
||||
patch.object(producer, '_convert_camera_buffer', side_effect=lambda buffer: frames[buffer[2]]), \
|
||||
patch.object(producer, 'clock_pair_ns', side_effect=clock_pair), \
|
||||
patch.object(producer.time, 'sleep'), \
|
||||
patch.object(core, 'infer', side_effect=lambda frame: Detection(55, 0.60) if frame[0, 0, 0] < 2 else None), \
|
||||
self.assertRaises(EndProducer):
|
||||
producer.main()
|
||||
with patch('msgq.visionipc.VisionIpcClient', camera), \
|
||||
patch('openpilot.common.params.Params', return_value=SimpleNamespace(get_bool=lambda _: False)), \
|
||||
patch.object(messaging, 'PubMaster', return_value=SimpleNamespace(send=send)), \
|
||||
patch.object(producer, 'VisionModelCore', return_value=core), \
|
||||
patch.object(producer, '_camera_buffer', side_effect=receive), \
|
||||
patch.object(producer, '_convert_camera_buffer', side_effect=lambda buffer, frames=frames: frames[buffer[2]]), \
|
||||
patch.object(producer, 'clock_pair_ns', side_effect=clock_pair), \
|
||||
patch.object(producer.time, 'sleep'), \
|
||||
patch.object(core, 'infer', side_effect=lambda frame: Detection(55, 0.60) if frame[0, 0, 0] < 2 else None), \
|
||||
self.assertRaises(EndProducer):
|
||||
producer.main()
|
||||
|
||||
self.assertEqual([str(message.status) for message in messages], ['unknown', 'valid', 'valid'])
|
||||
self.assertEqual([message.frameId for message in messages], [0, 1, 2])
|
||||
self.assertEqual(messages[1].supportCount, 2)
|
||||
self.assertEqual(messages[1].observedMonoTime, 1_100_000_000)
|
||||
self.assertEqual(messages[2].observedMonoTime, 1_100_000_000)
|
||||
self.assertEqual(messages[1].validUntilMonoTime, 3_100_000_000)
|
||||
self.assertEqual(messages[2].validUntilMonoTime, 3_300_000_000)
|
||||
self.assertEqual(core.last_detection_at, 1.1)
|
||||
self.assertEqual(messages[1].confidence, messages[2].confidence)
|
||||
self.assertEqual([str(message.status) for message in messages], expected)
|
||||
if conversion_ns:
|
||||
self.assertEqual([message.frameId for message in messages], [0, 2])
|
||||
self.assertEqual(core.last_detection_at, 1.)
|
||||
continue
|
||||
self.assertEqual([message.frameId for message in messages], [0, 1, 2])
|
||||
self.assertEqual(messages[1].supportCount, 2)
|
||||
self.assertEqual(messages[1].observedMonoTime, 1_100_000_000)
|
||||
self.assertEqual(messages[2].observedMonoTime, 1_100_000_000)
|
||||
self.assertEqual(messages[1].validUntilMonoTime, 3_100_000_000)
|
||||
self.assertEqual(messages[2].validUntilMonoTime, 3_300_000_000)
|
||||
self.assertEqual(core.last_detection_at, 1.1)
|
||||
self.assertEqual(messages[1].confidence, messages[2].confidence)
|
||||
|
||||
def test_followup_preserves_processing_cost_and_expires(self):
|
||||
interval = producer._inference_interval_ns
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"protected_inventory_sha256": "2ae7eb2cde24cdf5dc6ab526f0c0c2c30735fdcb0f33df2f51eca15eee349a83", "schema_version": 1}
|
||||
{"protected_inventory_sha256": "66e62824cc864d2942c8eb3ddbd302f84ba0223df8513290f3ef2c4244a4ac1d", "schema_version": 1}
|
||||
|
||||
Reference in New Issue
Block a user