fix(viewer): preserve follow camera across layer toggles
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Callable
|
||||
from contextlib import suppress
|
||||
from threading import Lock
|
||||
from typing import Any, Literal
|
||||
@@ -62,6 +63,7 @@ class _RecordedBlueprintStream:
|
||||
self.view_reset_generation = view_reset_generation
|
||||
self._lock = Lock()
|
||||
self._sequence = 0
|
||||
self._follow_trajectory: bool | None = None
|
||||
self._closed = False
|
||||
native = bindings.new_blueprint(
|
||||
application_id=application_id,
|
||||
@@ -78,10 +80,20 @@ class _RecordedBlueprintStream:
|
||||
)
|
||||
self._transport = rr.binary_stream(self._transport_recording)
|
||||
|
||||
def render(self, blueprint: rrb.Blueprint) -> bytes:
|
||||
def render(
|
||||
self,
|
||||
blueprint_factory: Callable[[bool], rrb.Blueprint],
|
||||
*,
|
||||
follow_trajectory: bool,
|
||||
) -> bytes:
|
||||
with self._lock:
|
||||
if self._closed:
|
||||
raise RecordedBlueprintError("stable blueprint stream is closed")
|
||||
update_eye_controls = (
|
||||
self._follow_trajectory is None
|
||||
or self._follow_trajectory != follow_trajectory
|
||||
)
|
||||
blueprint = blueprint_factory(update_eye_controls)
|
||||
self._blueprint_recording.set_time(
|
||||
"blueprint",
|
||||
sequence=self._sequence,
|
||||
@@ -98,6 +110,7 @@ class _RecordedBlueprintStream:
|
||||
payload = self._transport.read(flush=True, flush_timeout_sec=5.0)
|
||||
if not payload:
|
||||
raise RecordedBlueprintError("stable blueprint stream produced no data")
|
||||
self._follow_trajectory = follow_trajectory
|
||||
return payload
|
||||
|
||||
def close(self) -> None:
|
||||
@@ -156,6 +169,7 @@ def recorded_blueprint(
|
||||
show_segmentation: bool = False,
|
||||
show_cuboids_3d: bool = False,
|
||||
follow_trajectory: bool = False,
|
||||
update_eye_controls: bool = True,
|
||||
) -> rrb.Blueprint:
|
||||
accumulation = max(0.0, settings.accumulation_seconds)
|
||||
time_ranges: list[rr.VisibleTimeRange] | None = None
|
||||
@@ -218,9 +232,13 @@ def recorded_blueprint(
|
||||
# Keeping the view id stable preserves the current orbit offset when
|
||||
# tracking is toggled. An explicit empty path clears tracking without
|
||||
# overwriting the position/look-target saved by user interaction.
|
||||
eye_controls=rrb.EyeControls3D.from_fields(
|
||||
kind=rrb.Eye3DKind.Orbital if follow_trajectory else None,
|
||||
tracking_entity="/world/sensor_pose" if follow_trajectory else "",
|
||||
eye_controls=(
|
||||
rrb.EyeControls3D.from_fields(
|
||||
kind=rrb.Eye3DKind.Orbital if follow_trajectory else None,
|
||||
tracking_entity="/world/sensor_pose" if follow_trajectory else "",
|
||||
)
|
||||
if update_eye_controls
|
||||
else None
|
||||
),
|
||||
)
|
||||
spatial_view.id = (
|
||||
@@ -274,9 +292,13 @@ def recorded_blueprint(
|
||||
# native cloud from /world/points.
|
||||
"/world/perception/lidar": rrb.EntityBehavior(visible=False),
|
||||
},
|
||||
eye_controls=rrb.EyeControls3D.from_fields(
|
||||
kind=rrb.Eye3DKind.Orbital if follow_trajectory else None,
|
||||
tracking_entity="/world/sensor_pose" if follow_trajectory else "",
|
||||
eye_controls=(
|
||||
rrb.EyeControls3D.from_fields(
|
||||
kind=rrb.Eye3DKind.Orbital if follow_trajectory else None,
|
||||
tracking_entity="/world/sensor_pose" if follow_trajectory else "",
|
||||
)
|
||||
if update_eye_controls
|
||||
else None
|
||||
),
|
||||
)
|
||||
perception_3d_view.id = (
|
||||
@@ -385,17 +407,20 @@ def recorded_blueprint_rrd(
|
||||
) -> bytes:
|
||||
"""Serialize a bounded active blueprint update without recorded data."""
|
||||
|
||||
blueprint = recorded_blueprint(
|
||||
settings,
|
||||
include_initial_playback_state=False,
|
||||
active_view=active_view,
|
||||
view_reset_generation=view_reset_generation,
|
||||
unified_perception=unified_perception,
|
||||
show_detections_2d=show_detections_2d,
|
||||
show_segmentation=show_segmentation,
|
||||
show_cuboids_3d=show_cuboids_3d,
|
||||
follow_trajectory=follow_trajectory,
|
||||
)
|
||||
def build_blueprint(update_eye_controls: bool) -> rrb.Blueprint:
|
||||
return recorded_blueprint(
|
||||
settings,
|
||||
include_initial_playback_state=False,
|
||||
active_view=active_view,
|
||||
view_reset_generation=view_reset_generation,
|
||||
unified_perception=unified_perception,
|
||||
show_detections_2d=show_detections_2d,
|
||||
show_segmentation=show_segmentation,
|
||||
show_cuboids_3d=show_cuboids_3d,
|
||||
follow_trajectory=follow_trajectory,
|
||||
update_eye_controls=update_eye_controls,
|
||||
)
|
||||
|
||||
payload: bytes | None
|
||||
if blueprint_session_id is not None:
|
||||
try:
|
||||
@@ -404,12 +429,16 @@ def recorded_blueprint_rrd(
|
||||
recording_id=recording_id,
|
||||
blueprint_session_id=blueprint_session_id,
|
||||
view_reset_generation=view_reset_generation,
|
||||
).render(blueprint)
|
||||
).render(
|
||||
build_blueprint,
|
||||
follow_trajectory=follow_trajectory,
|
||||
)
|
||||
except RecordedBlueprintError:
|
||||
raise
|
||||
except Exception as exc:
|
||||
raise RecordedBlueprintError("failed to serialize stable recorded blueprint") from exc
|
||||
else:
|
||||
blueprint = build_blueprint(True)
|
||||
recording = rr.RecordingStream(
|
||||
application_id,
|
||||
recording_id=recording_id,
|
||||
|
||||
Reference in New Issue
Block a user