mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
ugh
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -11,8 +11,8 @@
|
|||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
|
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
|
||||||
<title>Multi Roomba Rover</title>
|
<title>Multi Roomba Rover</title>
|
||||||
<script type="module" crossorigin src="/assets/index-7hRMuQfF.js"></script>
|
<script type="module" crossorigin src="/assets/index-DgZ30KmZ.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-8DhFQlpJ.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-BBEWYgmH.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ export default function DriverVideoPanel({layoutFormat = 'desktop'}) {
|
|||||||
const { session } = useSession();
|
const { session } = useSession();
|
||||||
const {
|
const {
|
||||||
state: { song, lastControlIntentAt },
|
state: { song, lastControlIntentAt },
|
||||||
overcurrentLimiter,
|
|
||||||
} = useControlSystem();
|
} = useControlSystem();
|
||||||
const [now, setNow] = useState(() => Date.now());
|
const [now, setNow] = useState(() => Date.now());
|
||||||
const [turnCueVisible, setTurnCueVisible] = useState(false);
|
const [turnCueVisible, setTurnCueVisible] = useState(false);
|
||||||
@@ -123,7 +122,6 @@ export default function DriverVideoPanel({layoutFormat = 'desktop'}) {
|
|||||||
telemetryFrame={frame}
|
telemetryFrame={frame}
|
||||||
batteryConfig={batteryConfig}
|
batteryConfig={batteryConfig}
|
||||||
layoutFormat={layoutFormat}
|
layoutFormat={layoutFormat}
|
||||||
overcurrentLimiter={overcurrentLimiter}
|
|
||||||
songNote={song?.note}
|
songNote={song?.note}
|
||||||
qualityNotice={!shouldShowVideo ? 'Preview feed (low FPS) until your turn.' : null}
|
qualityNotice={!shouldShowVideo ? 'Preview feed (low FPS) until your turn.' : null}
|
||||||
showTurnCue={turnCueVisible}
|
showTurnCue={turnCueVisible}
|
||||||
|
|||||||
@@ -37,11 +37,6 @@ function buildBatteryVisual(charge, config) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function clampUnit(value) {
|
|
||||||
if (!Number.isFinite(value)) return 0;
|
|
||||||
return Math.max(0, Math.min(1, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function VideoTile({
|
export default function VideoTile({
|
||||||
sessionInfo,
|
sessionInfo,
|
||||||
audioSessionInfo,
|
audioSessionInfo,
|
||||||
@@ -59,7 +54,6 @@ export default function VideoTile({
|
|||||||
hudMapPosition = 'top-right',
|
hudMapPosition = 'top-right',
|
||||||
hudLabelScale = 1,
|
hudLabelScale = 1,
|
||||||
fitParent = false,
|
fitParent = false,
|
||||||
overcurrentLimiter = null,
|
|
||||||
showTurnCue = false,
|
showTurnCue = false,
|
||||||
turnTimerText = null,
|
turnTimerText = null,
|
||||||
turnSeconds = null,
|
turnSeconds = null,
|
||||||
@@ -100,48 +94,6 @@ export default function VideoTile({
|
|||||||
: Object.entries(wheelOvercurrents)
|
: Object.entries(wheelOvercurrents)
|
||||||
.filter(([, active]) => Boolean(active))
|
.filter(([, active]) => Boolean(active))
|
||||||
.map(([key]) => key);
|
.map(([key]) => key);
|
||||||
const limiterCaps = overcurrentLimiter?.caps || null;
|
|
||||||
const limiterGroups = overcurrentLimiter?.overcurrent?.groups || null;
|
|
||||||
const limiterFill = useMemo(() => {
|
|
||||||
if (!limiterCaps) return null;
|
|
||||||
const driveCap = Number.isFinite(limiterCaps?.drive?.cap) ? limiterCaps.drive.cap : 1;
|
|
||||||
const auxCap = Number.isFinite(limiterCaps?.aux?.cap) ? limiterCaps.aux.cap : 1;
|
|
||||||
return Math.max(0, Math.min(1, 1 - Math.min(driveCap, auxCap)));
|
|
||||||
}, [limiterCaps]);
|
|
||||||
const fallbackLabels = useMemo(
|
|
||||||
() => overcurrentMotors.map((name) => OVERCURRENT_LABELS[name] || name),
|
|
||||||
[overcurrentMotors],
|
|
||||||
);
|
|
||||||
const overcurrentActive = Boolean(
|
|
||||||
(limiterGroups?.drive || limiterGroups?.aux) || overcurrentMotors.length,
|
|
||||||
);
|
|
||||||
const overlayFill = overcurrentLimiter
|
|
||||||
? limiterFill ?? (overcurrentMotors.length ? 1 : 0)
|
|
||||||
: overcurrentMotors.length
|
|
||||||
? 1
|
|
||||||
: 0;
|
|
||||||
const overlayVisible = overcurrentActive || overlayFill > 0.01;
|
|
||||||
const overlayOpacity = clampUnit(
|
|
||||||
overlayVisible ? Math.max(overlayFill * 1.2, overcurrentActive ? 0.6 : 0.3) : 0,
|
|
||||||
);
|
|
||||||
const overcurrentLabels = useMemo(() => {
|
|
||||||
if (!overcurrentLimiter) {
|
|
||||||
return fallbackLabels;
|
|
||||||
}
|
|
||||||
const labels = [];
|
|
||||||
const driveCap = Number.isFinite(limiterCaps?.drive?.cap) ? limiterCaps.drive.cap : 1;
|
|
||||||
const auxCap = Number.isFinite(limiterCaps?.aux?.cap) ? limiterCaps.aux.cap : 1;
|
|
||||||
const driveActive = Boolean(limiterGroups?.drive) || driveCap < 0.999;
|
|
||||||
const auxActive = Boolean(limiterGroups?.aux) || auxCap < 0.999;
|
|
||||||
if (driveActive) labels.push('Drive wheels');
|
|
||||||
if (auxActive) labels.push('Aux motors');
|
|
||||||
return labels.length ? labels : fallbackLabels;
|
|
||||||
}, [fallbackLabels, limiterCaps, limiterGroups, overcurrentLimiter]);
|
|
||||||
const overlayLabels = useMemo(() => {
|
|
||||||
if (overcurrentLabels?.length) return overcurrentLabels;
|
|
||||||
if (overlayVisible) return ['Overcurrent'];
|
|
||||||
return [];
|
|
||||||
}, [overcurrentLabels, overlayVisible]);
|
|
||||||
|
|
||||||
const scheduleRestart = useCallback(() => {
|
const scheduleRestart = useCallback(() => {
|
||||||
clearTimeout(restartTimer.current);
|
clearTimeout(restartTimer.current);
|
||||||
@@ -468,18 +420,7 @@ export default function VideoTile({
|
|||||||
labelScale={hudLabelScale}
|
labelScale={hudLabelScale}
|
||||||
/>
|
/>
|
||||||
<HudChatInput compact={mobileHud} />
|
<HudChatInput compact={mobileHud} />
|
||||||
{overcurrentLimiter ? (
|
<OvercurrentOverlay motors={overcurrentMotors} compact={mobileHud} />
|
||||||
<div className="pointer-events-none absolute right-1 top-1 z-40 rounded bg-black/70 px-1 py-0.5 text-[0.6rem] text-red-200">
|
|
||||||
{`OC HUD ${overlayVisible ? 'on' : 'off'} · fill ${Math.round(overlayFill * 100)}%`}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
<OvercurrentOverlay
|
|
||||||
labels={overlayLabels}
|
|
||||||
fill={overlayFill}
|
|
||||||
opacity={overlayOpacity}
|
|
||||||
visible={overlayVisible}
|
|
||||||
compact={mobileHud}
|
|
||||||
/>
|
|
||||||
<LowBatteryOverlay charge={batteryCharge} config={batteryConfig} compact={mobileHud} />
|
<LowBatteryOverlay charge={batteryCharge} config={batteryConfig} compact={mobileHud} />
|
||||||
{showVerticalBattery && batteryVisual.available ? (
|
{showVerticalBattery && batteryVisual.available ? (
|
||||||
<BatteryBarVertical visual={batteryVisual} />
|
<BatteryBarVertical visual={batteryVisual} />
|
||||||
@@ -779,25 +720,19 @@ const OVERCURRENT_LABELS = {
|
|||||||
sideBrush: 'Side brush',
|
sideBrush: 'Side brush',
|
||||||
};
|
};
|
||||||
|
|
||||||
function OvercurrentOverlay({ labels, fill = 0, opacity = 1, visible = false, compact = false }) {
|
function OvercurrentOverlay({ motors, compact = false }) {
|
||||||
if (!visible && !labels?.length) return null;
|
if (!motors?.length) return null;
|
||||||
const displayLabels = labels?.length ? labels : ['Overcurrent'];
|
const labels = motors.map((name) => OVERCURRENT_LABELS[name] || name);
|
||||||
const containerClass = compact ? 'p-2' : 'p-4';
|
const containerClass = compact ? 'p-2' : 'p-4';
|
||||||
const textClass = compact ? 'text-lg' : 'text-4xl';
|
const textClass = compact ? 'text-lg' : 'text-4xl';
|
||||||
const subTextClass = compact ? 'text-xs' : 'text-xl';
|
const subTextClass = compact ? 'text-xs' : 'text-xl';
|
||||||
const fillWidth = `${Math.round(clampUnit(fill) * 100)}%`;
|
|
||||||
const resolvedOpacity = clampUnit(opacity);
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`pointer-events-none absolute z-40 flex items-center justify-center bg-red-900/80 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 ${containerClass} relative`}
|
className={`pointer-events-none absolute flex items-center justify-center bg-red-900/60 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 ${containerClass}`}
|
||||||
style={{ opacity: resolvedOpacity }}
|
|
||||||
>
|
>
|
||||||
<div className="absolute inset-0 overflow-hidden">
|
<div className={`text-center font-semibold text-white animate-pulse ${textClass}`}>
|
||||||
<div className="h-full bg-red-700/60" style={{ width: fillWidth }} />
|
|
||||||
</div>
|
|
||||||
<div className={`relative z-10 text-center font-semibold text-white animate-pulse ${textClass}`}>
|
|
||||||
<div>OVERCURRENT</div>
|
<div>OVERCURRENT</div>
|
||||||
<div className={`mt-0 font-medium text-white ${subTextClass}`}>{displayLabels.join(', ')}</div>
|
<div className={`mt-0 font-medium text-white ${subTextClass}`}>{labels.join(', ')}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user