mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
tweak
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -11,7 +11,7 @@
|
|||||||
<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-CoUbgLnI.js"></script>
|
<script type="module" crossorigin src="/assets/index-Bap-IGi3.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-COtFQYoW.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-COtFQYoW.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -2,16 +2,13 @@ import { useMemo } from 'react';
|
|||||||
import { useDockIr } from '../hooks/useDockIr.js';
|
import { useDockIr } from '../hooks/useDockIr.js';
|
||||||
|
|
||||||
const SVG_W = 120;
|
const SVG_W = 120;
|
||||||
const SVG_H = 110;
|
const SVG_H = 96;
|
||||||
const CX = SVG_W / 2;
|
const CX = SVG_W / 2;
|
||||||
const DOCK_Y = 16;
|
const DOCK_Y = 14;
|
||||||
const ROVER_Y = 80;
|
const ROVER_Y = 74;
|
||||||
|
|
||||||
function lobePath(side = 'left') {
|
function alignmentBarPath() {
|
||||||
if (side === 'left') {
|
return `M ${CX - 3} ${DOCK_Y + 4} L ${CX - 10} ${ROVER_Y - 6} L ${CX + 10} ${ROVER_Y - 6} Z`;
|
||||||
return `M ${CX} ${DOCK_Y} C ${CX - 10} ${DOCK_Y + 8} ${CX - 12} ${ROVER_Y - 18} ${CX - 4} ${ROVER_Y - 6} L ${CX} ${ROVER_Y - 10} Z`;
|
|
||||||
}
|
|
||||||
return `M ${CX} ${DOCK_Y} C ${CX + 10} ${DOCK_Y + 8} ${CX + 12} ${ROVER_Y - 18} ${CX + 4} ${ROVER_Y - 6} L ${CX} ${ROVER_Y - 10} Z`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function DockAssistHUD({ sensors }) {
|
export default function DockAssistHUD({ sensors }) {
|
||||||
@@ -29,38 +26,29 @@ export default function DockAssistHUD({ sensors }) {
|
|||||||
|
|
||||||
if (!state.visible) return null;
|
if (!state.visible) return null;
|
||||||
|
|
||||||
const nudge = state.balance * 6;
|
const nudge = state.balance * 5;
|
||||||
const leftActive = state.left.red || state.left.green || state.left.force;
|
const leftHit = state.left.active;
|
||||||
const rightActive = state.right.red || state.right.green || state.right.force;
|
const rightHit = state.right.active;
|
||||||
|
const forceHit = state.omni.force || state.forceDetected;
|
||||||
const allAligned = Boolean(state.left.green && state.right.red && state.omni.force);
|
const allAligned = Boolean(state.left.green && state.right.red && state.omni.force);
|
||||||
|
const hasAny = leftHit || rightHit || forceHit;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="pointer-events-none absolute inset-x-0 top-0 flex justify-center p-0.25">
|
<div className="pointer-events-none absolute inset-x-0 top-0 flex justify-center p-0.25">
|
||||||
<svg width={SVG_W} height={SVG_H} viewBox={`0 0 ${SVG_W} ${SVG_H}`} role="img" aria-label="Docking assist">
|
<svg width={SVG_W} height={SVG_H} viewBox={`0 0 ${SVG_W} ${SVG_H}`} role="img" aria-label="Docking assist">
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="gradGreen" x1="0%" y1="0%" x2="0%" y2="100%">
|
<linearGradient id="alignGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
<stop offset="0%" stopColor={palette.green[0]} />
|
<stop offset="0%" stopColor="rgba(148,163,184,0.9)" />
|
||||||
<stop offset="60%" stopColor={palette.green[1]} />
|
<stop offset="100%" stopColor="rgba(148,163,184,0)" />
|
||||||
<stop offset="100%" stopColor={palette.green[2]} />
|
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
<linearGradient id="gradRed" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
||||||
<stop offset="0%" stopColor={palette.red[0]} />
|
|
||||||
<stop offset="60%" stopColor={palette.red[1]} />
|
|
||||||
<stop offset="100%" stopColor={palette.red[2]} />
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="halo" cx="50%" cy="20%" r="60%">
|
|
||||||
<stop offset="0%" stopColor="rgba(59,130,246,0.45)" />
|
|
||||||
<stop offset="100%" stopColor="rgba(59,130,246,0)" />
|
|
||||||
</radialGradient>
|
|
||||||
</defs>
|
</defs>
|
||||||
|
|
||||||
{/* Lobes */}
|
{/* Alignment wedge */}
|
||||||
<path d={lobePath('left')} fill={leftActive ? 'url(#gradGreen)' : 'rgba(16,185,129,0.12)'} />
|
{hasAny ? (
|
||||||
<path d={lobePath('right')} fill={rightActive ? 'url(#gradRed)' : 'rgba(239,68,68,0.12)'} />
|
|
||||||
{leftActive && rightActive ? (
|
|
||||||
<path
|
<path
|
||||||
d={`M ${CX - 6} ${ROVER_Y - 12} Q ${CX} ${ROVER_Y - 4} ${CX + 6} ${ROVER_Y - 12}`}
|
d={alignmentBarPath()}
|
||||||
fill="rgba(255,255,255,0.08)"
|
fill="url(#alignGrad)"
|
||||||
|
transform={`translate(${nudge * 3}, 0) rotate(${state.balance * 8}, ${CX}, ${ROVER_Y - 6})`}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
@@ -119,11 +107,7 @@ export default function DockAssistHUD({ sensors }) {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Thumbs up when fully aligned */}
|
{/* Thumbs up when fully aligned */}
|
||||||
{allAligned ? (
|
{allAligned ? <text x={CX + 30} y={DOCK_Y + 8} fontSize="12" fill="#fbbf24" fontFamily="sans-serif">👍</text> : null}
|
||||||
<text x={CX + 30} y={DOCK_Y + 8} fontSize="12" fill="#fbbf24" fontFamily="sans-serif">
|
|
||||||
👍
|
|
||||||
</text>
|
|
||||||
) : null}
|
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -113,10 +113,8 @@ function SensorDetails({ sensors }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid gap-0.5 md:grid-cols-2">
|
<div className="grid gap-0.5 md:grid-cols-2">
|
||||||
<DetailCard title="Dock IR (raw)">
|
<DetailCard title="Dock IR">
|
||||||
<ValueRow label="Left" value={formatNumber(sensors?.infraredCharacterLeft)} />
|
<DockMiniStatus sensors={sensors} />
|
||||||
<ValueRow label="Omni" value={formatNumber(sensors?.infraredCharacterOmni)} />
|
|
||||||
<ValueRow label="Right" value={formatNumber(sensors?.infraredCharacterRight)} />
|
|
||||||
</DetailCard>
|
</DetailCard>
|
||||||
|
|
||||||
<DetailCard title="Bumps & drops">
|
<DetailCard title="Bumps & drops">
|
||||||
@@ -200,3 +198,30 @@ function formatNumber(value, unit) {
|
|||||||
if (value == null || Number.isNaN(value)) return '--';
|
if (value == null || Number.isNaN(value)) return '--';
|
||||||
return unit ? `${value} ${unit}` : value;
|
return unit ? `${value} ${unit}` : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function DockMiniStatus({ sensors }) {
|
||||||
|
const left = sensors?.infraredCharacterLeft;
|
||||||
|
const right = sensors?.infraredCharacterRight;
|
||||||
|
const omni = sensors?.infraredCharacterOmni;
|
||||||
|
const badge = (code) => (
|
||||||
|
<span className={`rounded px-1 py-0.25 text-[0.7rem] font-semibold ${code ? 'bg-emerald-600 text-white' : 'bg-slate-700 text-slate-300'}`}>
|
||||||
|
{code || '--'}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<div className="flex items-center justify-between gap-1 text-xs text-slate-200">
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<span className="text-slate-400">L</span>
|
||||||
|
{badge(left)}
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<span className="text-slate-400">O</span>
|
||||||
|
{badge(omni)}
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<span className="text-slate-400">R</span>
|
||||||
|
{badge(right)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user