Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions positronic/cfg/hardware/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
49 changes: 49 additions & 0 deletions positronic/cfg/tests/test_camera.py
Original file line number Diff line number Diff line change
@@ -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()}
Comment thread
v-positronic marked this conversation as resolved.


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)


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_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."""

@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
Loading