feat(perception): integrate calibrated operator pipeline
Add calibrated K1 projection, recorded and near-live perception qualification, unified Rerun operator layers, bounded replay admission, audited viewer controls, worker experiments, and lab evidence.
This commit is contained in:
@@ -88,7 +88,22 @@ const paletteOptions: Array<{ value: PointPalette; label: string; description: s
|
||||
{ value: "custom", label: "Свой цвет", description: "Один назначенный цвет" },
|
||||
];
|
||||
|
||||
function toViewerSettings(settings: SceneSettings): ViewerSettings {
|
||||
interface LivePerceptionLayers {
|
||||
detections2d: boolean;
|
||||
segmentation: boolean;
|
||||
cuboids3d: boolean;
|
||||
}
|
||||
|
||||
const defaultLivePerceptionLayers: LivePerceptionLayers = {
|
||||
detections2d: false,
|
||||
segmentation: false,
|
||||
cuboids3d: false,
|
||||
};
|
||||
|
||||
function toViewerSettings(
|
||||
settings: SceneSettings,
|
||||
perception: LivePerceptionLayers = defaultLivePerceptionLayers,
|
||||
): ViewerSettings {
|
||||
return {
|
||||
point_size: settings.pointSize,
|
||||
color_mode: settings.colorMode,
|
||||
@@ -98,6 +113,9 @@ function toViewerSettings(settings: SceneSettings): ViewerSettings {
|
||||
show_points: settings.showPoints,
|
||||
show_trajectory: settings.showTrajectory,
|
||||
show_grid: settings.showGrid,
|
||||
show_detections_2d: perception.detections2d,
|
||||
show_segmentation: perception.segmentation,
|
||||
show_cuboids_3d: perception.cuboids3d,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -149,6 +167,9 @@ export default function App() {
|
||||
const [layoutSaveNotice, setLayoutSaveNotice] = useState<string | null>(null);
|
||||
const [sceneSettings, setSceneSettings] = useState<SceneSettings>(defaultSceneSettings);
|
||||
const [displayDraft, setDisplayDraft] = useState<SceneSettings>(defaultSceneSettings);
|
||||
const [livePerceptionLayers, setLivePerceptionLayers] = useState<LivePerceptionLayers>(
|
||||
defaultLivePerceptionLayers,
|
||||
);
|
||||
const sourceSwitchBlocked = isSpatialSourceSwitchBlocked(runtime.state);
|
||||
const sourceSwitchBlockedReason = sourceSwitchBlocked
|
||||
? SPATIAL_SOURCE_SWITCH_BLOCKED_REASON
|
||||
@@ -161,6 +182,8 @@ export default function App() {
|
||||
const confirmedSceneSettingsRef = useRef<SceneSettings>(defaultSceneSettings);
|
||||
const viewerSettingsCommitTimerRef = useRef<number | null>(null);
|
||||
const runtimeUpdateViewerSettingsRef = useRef(runtime.updateViewerSettings);
|
||||
const livePerceptionLayersRef = useRef<LivePerceptionLayers>(defaultLivePerceptionLayers);
|
||||
const livePerceptionRevisionRef = useRef(0);
|
||||
const replayActiveRef = useRef(false);
|
||||
const sceneSettingsCommitterActiveRef = useRef(true);
|
||||
const sceneSettingsCommitterRef = useRef<LatestAsyncCommitter<SceneSettings> | null>(null);
|
||||
@@ -197,7 +220,9 @@ export default function App() {
|
||||
sceneSettingsCommitterRef.current = createLatestAsyncCommitter<SceneSettings>({
|
||||
commit: (settings) => replayActiveRef.current
|
||||
? Promise.resolve(true)
|
||||
: runtimeUpdateViewerSettingsRef.current(toViewerSettings(settings)),
|
||||
: runtimeUpdateViewerSettingsRef.current(
|
||||
toViewerSettings(settings, livePerceptionLayersRef.current),
|
||||
),
|
||||
onSettled: ({ value, applied, superseded }) => {
|
||||
if (!sceneSettingsCommitterActiveRef.current) return;
|
||||
if (applied) confirmedSceneSettingsRef.current = value;
|
||||
@@ -275,6 +300,13 @@ export default function App() {
|
||||
sceneSettingsCommitterRef.current?.isBusy()
|
||||
) return;
|
||||
const merged = mergeViewerSettings(sceneSettingsRef.current, remote);
|
||||
const remoteLayers = {
|
||||
detections2d: remote.show_detections_2d ?? false,
|
||||
segmentation: remote.show_segmentation ?? false,
|
||||
cuboids3d: remote.show_cuboids_3d ?? false,
|
||||
};
|
||||
livePerceptionLayersRef.current = remoteLayers;
|
||||
setLivePerceptionLayers(remoteLayers);
|
||||
sceneSettingsRef.current = merged;
|
||||
confirmedSceneSettingsRef.current = merged;
|
||||
setSceneSettings(merged);
|
||||
@@ -334,7 +366,9 @@ export default function App() {
|
||||
return;
|
||||
}
|
||||
appliedProfileKeyRef.current = applicationKey;
|
||||
void runtime.updateViewerSettings(toViewerSettings(profile.sceneSettings)).then((applied) => {
|
||||
void runtime.updateViewerSettings(
|
||||
toViewerSettings(profile.sceneSettings, livePerceptionLayersRef.current),
|
||||
).then((applied) => {
|
||||
if (!applied && appliedProfileKeyRef.current === applicationKey) {
|
||||
appliedProfileKeyRef.current = null;
|
||||
}
|
||||
@@ -441,6 +475,21 @@ export default function App() {
|
||||
activateSceneWindow("layers");
|
||||
};
|
||||
|
||||
const changeLivePerceptionLayers = useCallback((next: LivePerceptionLayers) => {
|
||||
const previous = livePerceptionLayersRef.current;
|
||||
const revision = ++livePerceptionRevisionRef.current;
|
||||
livePerceptionLayersRef.current = next;
|
||||
setLivePerceptionLayers(next);
|
||||
if (replayActiveRef.current) return;
|
||||
void runtimeUpdateViewerSettingsRef.current(
|
||||
toViewerSettings(sceneSettingsRef.current, next),
|
||||
).then((applied) => {
|
||||
if (applied || livePerceptionRevisionRef.current !== revision) return;
|
||||
livePerceptionLayersRef.current = previous;
|
||||
setLivePerceptionLayers(previous);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const beginRecordedReplaySwitch = useCallback(async () => {
|
||||
if (sourceSwitchBlockedRef.current) {
|
||||
throw new Error(SPATIAL_SOURCE_SWITCH_BLOCKED_REASON);
|
||||
@@ -706,6 +755,8 @@ export default function App() {
|
||||
onAccumulationChange={(accumulationSeconds) =>
|
||||
stageDisplayPatch({ accumulationSeconds })}
|
||||
onAccumulationCommit={flushDisplaySettings}
|
||||
livePerceptionLayers={livePerceptionLayers}
|
||||
onLivePerceptionLayersChange={changeLivePerceptionLayers}
|
||||
observationLayout={observationLayout}
|
||||
spatialControls={selection?.SpatialControlsView
|
||||
? {
|
||||
|
||||
Reference in New Issue
Block a user