From fac4d713d846855f23743a27c8a7599afa642264 Mon Sep 17 00:00:00 2001 From: Vladimir Yakunin Date: Mon, 7 Sep 2026 12:24:06 +0000 Subject: [PATCH 1/2] Name the DROID sideviews by side, and give each one a camera dict MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The station carries two sideviews and the DROID embodiment binds one exterior. Which one it binds was decided by which serial the dict named, so the side a task asks for reached the rig as an instruction to a human to aim the camera. `sideview_left` and `sideview_right` name the two serials for their sides, and `droid_right` binds the other one into the single exterior slot. `droid_left` is the unsided default, which already binds the left sideview, so the left binding has one definition rather than two. Each carries the same keys as `droid`, so a policy trained on that observation set sees the set it expects and only the vantage moves. Which serial sits on which side is ASSUMED, not measured: the names are numbered rather than sided and no rig log carries a serial. The two alias lines are the one place to correct it. The test pins what a launch actually does — override `cameras` on an embodiment a caller has already overridden elsewhere — and that the other override survives it. Ticket: Positronic-Robotics/internal#1131 #refs --- positronic/cfg/hardware/camera.py | 16 ++++++++-- positronic/cfg/tests/test_camera.py | 49 +++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 positronic/cfg/tests/test_camera.py diff --git a/positronic/cfg/hardware/camera.py b/positronic/cfg/hardware/camera.py index 07acc4b5a..c36cb6e08 100644 --- a/positronic/cfg/hardware/camera.py +++ b/positronic/cfg/hardware/camera.py @@ -35,11 +35,23 @@ def zed(**kwargs): zed_2i = zed.override(serial_number=39567055) zed_2i_second = zed.override(serial_number=13785037) +# The station's two sideviews, by side. UNVERIFIED against the rig: correct these two lines and +# every sided config below follows them. +sideview_left = zed_2i +sideview_right = zed_2i_second + _DROID_STREAM = {'view': 'left', 'resolution': 'hd720', 'fps': 30, 'image_enhancement': False} -droid = {keys.WRIST_IMAGE: zed_m.override(**_DROID_STREAM), keys.EXTERIOR_IMAGE: zed_2i.override(**_DROID_STREAM)} +droid = { + keys.WRIST_IMAGE: zed_m.override(**_DROID_STREAM), + keys.EXTERIOR_IMAGE: sideview_left.override(**_DROID_STREAM), +} + +droid_3cam = {**droid, keys.EXTERIOR_IMAGE_2: sideview_right.override(**_DROID_STREAM)} -droid_3cam = {**droid, keys.EXTERIOR_IMAGE_2: zed_2i_second.override(**_DROID_STREAM)} +# One exterior each, by side. Same keys as `droid`, so only the vantage moves. +droid_left = droid # the unsided default already binds the left sideview +droid_right = {**droid, keys.EXTERIOR_IMAGE: sideview_right.override(**_DROID_STREAM)} # YAM station (brunello): ZED X overhead + two ZED X One wrist cameras on the ZED Link Duo. zed_x_top = zed.override(serial_number=48953814) diff --git a/positronic/cfg/tests/test_camera.py b/positronic/cfg/tests/test_camera.py new file mode 100644 index 000000000..4ca1274ae --- /dev/null +++ b/positronic/cfg/tests/test_camera.py @@ -0,0 +1,49 @@ +import configuronic as cfn + +from positronic import keys +from positronic.cfg.hardware import camera + + +def _serials(cameras: dict) -> dict[str, int]: + return {name: cfg.kwargs['serial_number'] for name, cfg in cameras.items()} + + +def test_each_sided_droid_carries_the_same_cameras_as_the_unsided_one(): + assert set(camera.droid_left) == set(camera.droid) == {keys.WRIST_IMAGE, keys.EXTERIOR_IMAGE} + assert set(camera.droid_right) == set(camera.droid) + + +def test_the_two_sides_bind_different_sideviews_and_share_the_wrist(): + left, right = _serials(camera.droid_left), _serials(camera.droid_right) + + assert left[keys.EXTERIOR_IMAGE] != right[keys.EXTERIOR_IMAGE] + assert left[keys.WRIST_IMAGE] == right[keys.WRIST_IMAGE] + + +def test_each_side_binds_the_sideview_the_station_declares_for_it(): + assert _serials(camera.droid_left)[keys.EXTERIOR_IMAGE] == camera.sideview_left.kwargs['serial_number'] + assert _serials(camera.droid_right)[keys.EXTERIOR_IMAGE] == camera.sideview_right.kwargs['serial_number'] + + +def test_the_launcher_reference_binds_the_side_without_disturbing_the_rest(): + """An `@` reference resolves to a plain dict, and overriding `cameras` alone leaves a sibling + override on the same config standing.""" + + @cfn.config() + def arm(brake_after_idle_s: float = 0.0): + return brake_after_idle_s + + @cfn.config(robot_arm=arm, cameras=camera.droid) + def embodiment(robot_arm, cameras): + return robot_arm, cameras + + # Written out rather than derived from `camera.__name__`: the dotted path is this module's + # public name, so a derived reference would follow a rename instead of failing on one. + right_sideview_ref = '@positronic.cfg.hardware.camera.droid_right' + + pinned = embodiment.override(robot_arm=arm.override(brake_after_idle_s=600.0)) + bound = cfn.Config(lambda e: e, e=pinned).override(**{'e.cameras': right_sideview_ref}).kwargs['e'] + + assert _serials(bound.kwargs['cameras']) == _serials(camera.droid_right) + assert bound.kwargs['robot_arm'].kwargs == {'brake_after_idle_s': 600.0} + assert _serials(camera.droid) != _serials(camera.droid_right) # the module dict is not mutated From b8fd4ff0653bd4ecb0278e56ab375c856028c18c Mon Sep 17 00:00:00 2001 From: Vladimir Yakunin Date: Mon, 7 Sep 2026 14:10:38 +0000 Subject: [PATCH 2/2] Name the two camera tests for what they check One compares the observation keys of a sided embodiment with the unsided one. The other checks that an @ reference overrides the cameras and leaves a sibling override standing. Shelved with the pull request. Ticket: Positronic-Robotics/internal#1131 #refs --- positronic/cfg/tests/test_camera.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/positronic/cfg/tests/test_camera.py b/positronic/cfg/tests/test_camera.py index 4ca1274ae..4563f73bc 100644 --- a/positronic/cfg/tests/test_camera.py +++ b/positronic/cfg/tests/test_camera.py @@ -8,7 +8,7 @@ def _serials(cameras: dict) -> dict[str, int]: return {name: cfg.kwargs['serial_number'] for name, cfg in cameras.items()} -def test_each_sided_droid_carries_the_same_cameras_as_the_unsided_one(): +def test_each_sided_droid_keeps_the_observation_keys_of_the_unsided_one(): assert set(camera.droid_left) == set(camera.droid) == {keys.WRIST_IMAGE, keys.EXTERIOR_IMAGE} assert set(camera.droid_right) == set(camera.droid) @@ -25,7 +25,7 @@ def test_each_side_binds_the_sideview_the_station_declares_for_it(): assert _serials(camera.droid_right)[keys.EXTERIOR_IMAGE] == camera.sideview_right.kwargs['serial_number'] -def test_the_launcher_reference_binds_the_side_without_disturbing_the_rest(): +def test_an_at_reference_overrides_cameras_and_leaves_a_sibling_override_standing(): """An `@` reference resolves to a plain dict, and overriding `cameras` alone leaves a sibling override on the same config standing."""