mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-15 17:12:59 -04:00
guhwhu
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
# general idea
|
||||||
|
- IR led on the front of each roomba
|
||||||
|
- connected to a pin on the pi
|
||||||
|
- made to be very directional
|
||||||
|
- each roomba has a different IR code
|
||||||
|
- use the omni reciever to get a shot
|
||||||
|
- keep score per user
|
||||||
|
- use the go alert system
|
||||||
|
- alert discord with a live score count
|
||||||
+14
-8
@@ -4,14 +4,20 @@
|
|||||||
- video stream currently unloads and reloads based on the tab being active
|
- video stream currently unloads and reloads based on the tab being active
|
||||||
- just remove this feature. It needs to stay running all the time.
|
- just remove this feature. It needs to stay running all the time.
|
||||||
|
|
||||||
## server sensor decoding
|
|
||||||
- OI mode is not decoded properly
|
|
||||||
- says "safe" when in passive, and "unknown" when in full.
|
|
||||||
|
|
||||||
## UI and session info
|
## UI and session info
|
||||||
- UI needs a display for the turns mode
|
- UI needs a display for the turns mode
|
||||||
|
|
||||||
## Mobile UI
|
## UI tweaks and fixes
|
||||||
- need to make it good
|
- remove redundant rover name tags everywhere
|
||||||
- joystick needs to be floating
|
- just have one in the hud: "You are driving <name>"
|
||||||
- aux motor buttons need redone
|
- unify colors and roundeds
|
||||||
|
- no borders, ever
|
||||||
|
- no ALL CAPS FONTS ever
|
||||||
|
- nothing should be rounded at all.
|
||||||
|
- webpage background color: black
|
||||||
|
- panels should all be the same lighter gray
|
||||||
|
- things inside panels should be a darker gray
|
||||||
|
- buttons should be even darker, almost black
|
||||||
|
- all buttons should have a hover effect which lightens them a little
|
||||||
|
- text should be either white or gray
|
||||||
|
-
|
||||||
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
@@ -5,8 +5,8 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>webui</title>
|
<title>webui</title>
|
||||||
<script type="module" crossorigin src="/assets/index-qVLATLih.js"></script>
|
<script type="module" crossorigin src="/assets/index-DZfa02-s.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-C_9jprs0.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-DHDtmVNU.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ function AlertToast({ alert }) {
|
|||||||
? 'bg-amber-500/30 text-amber-100'
|
? 'bg-amber-500/30 text-amber-100'
|
||||||
: 'bg-emerald-500/30 text-emerald-100';
|
: 'bg-emerald-500/30 text-emerald-100';
|
||||||
return (
|
return (
|
||||||
<div className={`pointer-events-auto rounded-sm px-1 py-1 text-[0.75rem] shadow-lg shadow-black/60 ${colorClasses}`}>
|
<div className={`pointer-events-auto rounded-sm px-1 py-1 text-[0.75rem] ${colorClasses}`}>
|
||||||
<p className="text-[0.65rem] text-slate-300">{alert.title || 'Alert'}</p>
|
<p className="text-[0.65rem] text-slate-300">{alert.title || 'Alert'}</p>
|
||||||
<p className="text-sm text-white">{alert.message}</p>
|
<p className="text-sm text-white">{alert.message}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -21,9 +21,13 @@ export default function VideoTile({ sessionInfo, label, forceMute = false, telem
|
|||||||
// config: batteryConfig,
|
// config: batteryConfig,
|
||||||
// });
|
// });
|
||||||
const wheelOvercurrents = sensors?.wheelOvercurrents || null;
|
const wheelOvercurrents = sensors?.wheelOvercurrents || null;
|
||||||
const overcurrentActive = Boolean(
|
const overcurrentMotors =
|
||||||
wheelOvercurrents && Object.values(wheelOvercurrents).some((value) => Boolean(value)),
|
wheelOvercurrents == null
|
||||||
);
|
? []
|
||||||
|
: Object.entries(wheelOvercurrents)
|
||||||
|
.filter(([, active]) => Boolean(active))
|
||||||
|
.map(([key]) => key);
|
||||||
|
const overcurrentActive = overcurrentMotors.length > 0;
|
||||||
|
|
||||||
const scheduleRestart = useCallback(() => {
|
const scheduleRestart = useCallback(() => {
|
||||||
clearTimeout(restartTimer.current);
|
clearTimeout(restartTimer.current);
|
||||||
@@ -140,7 +144,7 @@ export default function VideoTile({ sessionInfo, label, forceMute = false, telem
|
|||||||
className="h-full w-full object-contain"
|
className="h-full w-full object-contain"
|
||||||
/>
|
/>
|
||||||
<HudOverlay frame={telemetryFrame} />
|
<HudOverlay frame={telemetryFrame} />
|
||||||
<OvercurrentOverlay active={overcurrentActive} />
|
<OvercurrentOverlay motors={overcurrentMotors} />
|
||||||
</div>
|
</div>
|
||||||
<BatteryBar charge={batteryCharge} config={batteryConfig} label={label} status={renderedStatus} />
|
<BatteryBar charge={batteryCharge} config={batteryConfig} label={label} status={renderedStatus} />
|
||||||
</div>
|
</div>
|
||||||
@@ -200,18 +204,18 @@ function HudOverlay({ frame }) {
|
|||||||
|
|
||||||
const pulse = frame?.receivedAt ? now - frame.receivedAt < 200 : false;
|
const pulse = frame?.receivedAt ? now - frame.receivedAt < 200 : false;
|
||||||
|
|
||||||
const bumperBadges = [
|
// const bumperBadges = [
|
||||||
{ label: 'B-L', active: bumps.bumpLeft },
|
// { label: 'B-L', active: bumps.bumpLeft },
|
||||||
{ label: 'B-R', active: bumps.bumpRight },
|
// { label: 'B-R', active: bumps.bumpRight },
|
||||||
];
|
// ];
|
||||||
const wheelBadges = [
|
// const wheelBadges = [
|
||||||
{ label: 'Drop L', active: bumps.wheelDropLeft },
|
// { label: 'Drop L', active: bumps.wheelDropLeft },
|
||||||
{ label: 'Drop R', active: bumps.wheelDropRight },
|
// { label: 'Drop R', active: bumps.wheelDropRight },
|
||||||
];
|
// ];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="pointer-events-none absolute inset-0 flex flex-col justify-between p-1 text-[0.65rem] text-slate-200">
|
<div className="pointer-events-none absolute inset-0 flex flex-col justify-between p-1 text-[0.65rem] text-slate-200">
|
||||||
<div className="flex items-center justify-between gap-1">
|
{/* <div className="flex items-center justify-between gap-1">
|
||||||
<div className="flex items-center gap-1 text-[0.55rem] text-slate-400">
|
<div className="flex items-center gap-1 text-[0.55rem] text-slate-400">
|
||||||
<span className={`h-2 w-2 rounded-full ${pulse ? 'bg-emerald-300 shadow-[0_0_4px_rgba(16,185,129,0.8)]' : 'bg-slate-700'}`} />
|
<span className={`h-2 w-2 rounded-full ${pulse ? 'bg-emerald-300 shadow-[0_0_4px_rgba(16,185,129,0.8)]' : 'bg-slate-700'}`} />
|
||||||
<span>sensor</span>
|
<span>sensor</span>
|
||||||
@@ -226,26 +230,55 @@ function HudOverlay({ frame }) {
|
|||||||
{wheelBadges.map((badge) => (
|
{wheelBadges.map((badge) => (
|
||||||
<HudBadge key={badge.label} label={badge.label} active={badge.active} />
|
<HudBadge key={badge.label} label={badge.label} active={badge.active} />
|
||||||
))}
|
))}
|
||||||
|
</div> */}
|
||||||
|
{/* bump and wheel drops bar */}
|
||||||
|
<div className="flex top-3 left-1/2 -translate-x-1/2 gap-1 bg-gray-900/40 rounded-full">
|
||||||
|
<div className={`px-1 py-0.5 rounded-full ${bumps.bumpLeft ? 'bg-red-500 text-white animate-pulse' : 'bg-black/40 text-slate-500'}`}>
|
||||||
|
Left Bump
|
||||||
|
</div>
|
||||||
|
{/* left wheel drop */}
|
||||||
|
<div className={`px-1 py-0.5 rounded-full ${bumps.wheelDropLeft ? 'bg-red-500 text-white animate-pulse' : 'bg-black/40 text-slate-500'}`}>
|
||||||
|
Left Wheel Drop
|
||||||
|
</div>
|
||||||
|
{/* right wheel drop */}
|
||||||
|
<div className={`px-1 py-0.5 rounded-full ${bumps.wheelDropRight ? 'bg-red-500 text-white animate-pulse' : 'bg-black/40 text-slate-500'}`}>
|
||||||
|
Right Wheel Drop
|
||||||
|
</div>
|
||||||
|
{/* right bump */}
|
||||||
|
<div className={`px-1 py-0.5 rounded-full ${bumps.bumpRight ? 'bg-red-500 text-white animate-pulse' : 'bg-black/40 text-slate-500'}`}>
|
||||||
|
Right Bump
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function HudBadge({ label, active }) {
|
// function HudBadge({ label, active }) {
|
||||||
return (
|
// return (
|
||||||
<span
|
// <span
|
||||||
className={`rounded-sm px-1 py-0.5 text-[0.55rem] ${active ? 'bg-emerald-500/30 text-emerald-100' : 'bg-black/40 text-slate-500'}`}
|
// className={`rounded-sm px-1 py-0.5 text-[0.55rem] ${active ? 'bg-emerald-500/30 text-emerald-100' : 'bg-black/40 text-slate-500'}`}
|
||||||
>
|
// >
|
||||||
{label}
|
// {label}
|
||||||
</span>
|
// </span>
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
function OvercurrentOverlay({ active }) {
|
const OVERCURRENT_LABELS = {
|
||||||
if (!active) return null;
|
leftWheel: 'Left wheel',
|
||||||
|
rightWheel: 'Right wheel',
|
||||||
|
mainBrush: 'Main brush',
|
||||||
|
sideBrush: 'Side brush',
|
||||||
|
};
|
||||||
|
|
||||||
|
function OvercurrentOverlay({ motors }) {
|
||||||
|
if (!motors?.length) return null;
|
||||||
|
const labels = motors.map((name) => OVERCURRENT_LABELS[name] || name);
|
||||||
return (
|
return (
|
||||||
<div className="pointer-events-none absolute inset-0 flex items-center justify-center bg-red-900/60">
|
<div className="pointer-events-none absolute inset-0 flex items-center justify-center bg-red-900/60">
|
||||||
<div className="text-center text-sm font-semibold text-red-100 animate-pulse">Overcurrent</div>
|
<div className="text-center text-2xl font-semibold text-white animate-pulse">
|
||||||
|
<div>Overcurrent</div>
|
||||||
|
<div className="mt-1 text-xl font-medium text-white">{labels.join(', ')}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user