mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
new top down stuff
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
@@ -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-ys6pPVMX.js"></script>
|
<script type="module" crossorigin src="/assets/index-jVd0ekcb.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-D2GpvMU5.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-D2GpvMU5.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ import React from 'react';
|
|||||||
function TopDownMap({ sensors = {}, variant = 'full', size: overrideSize, overlay = false }) {
|
function TopDownMap({ sensors = {}, variant = 'full', size: overrideSize, overlay = false }) {
|
||||||
const size = overrideSize || (variant === 'mini' ? 190 : 260);
|
const size = overrideSize || (variant === 'mini' ? 190 : 260);
|
||||||
const center = size / 2;
|
const center = size / 2;
|
||||||
|
const offsetY = size * 0.07; // nudge everything downward within the viewBox
|
||||||
|
const centerX = center;
|
||||||
|
const centerY = center + offsetY;
|
||||||
const innerCircle = center * 0.8; // keep proportions consistent as size changes
|
const innerCircle = center * 0.8; // keep proportions consistent as size changes
|
||||||
const lightRingInner = innerCircle - 4;
|
const lightRingInner = innerCircle - 4;
|
||||||
const lightRingOuter = innerCircle + 4;
|
const lightRingOuter = innerCircle + 4;
|
||||||
@@ -61,32 +64,32 @@ function TopDownMap({ sensors = {}, variant = 'full', size: overrideSize, overla
|
|||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
<svg width="100%" height="100%" viewBox={`0 0 ${size} ${size}`} preserveAspectRatio="xMidYMid meet" className="mx-auto block">
|
<svg width="100%" height="100%" viewBox={`0 0 ${size} ${size}`} preserveAspectRatio="xMidYMid meet" className="mx-auto block">
|
||||||
<circle cx={center} cy={center} r={innerCircle} fill="#0f172a" stroke="#334155" strokeWidth="2" />
|
<circle cx={centerX} cy={centerY} r={innerCircle} fill="#0f172a" stroke="#334155" strokeWidth="2" />
|
||||||
<WheelVisual
|
<WheelVisual
|
||||||
cx={center - wheelLineOffset}
|
cx={centerX - wheelLineOffset}
|
||||||
cy={center}
|
cy={centerY}
|
||||||
current={wheelCurrentLeft}
|
current={wheelCurrentLeft}
|
||||||
drop={bumps.wheelDropLeft}
|
drop={bumps.wheelDropLeft}
|
||||||
overcurrent={wheelOver.leftWheel}
|
overcurrent={wheelOver.leftWheel}
|
||||||
label="L"
|
label="L"
|
||||||
/>
|
/>
|
||||||
<WheelVisual
|
<WheelVisual
|
||||||
cx={center + wheelLineOffset}
|
cx={centerX + wheelLineOffset}
|
||||||
cy={center}
|
cy={centerY}
|
||||||
current={wheelCurrentRight}
|
current={wheelCurrentRight}
|
||||||
drop={bumps.wheelDropRight}
|
drop={bumps.wheelDropRight}
|
||||||
overcurrent={wheelOver.rightWheel}
|
overcurrent={wheelOver.rightWheel}
|
||||||
label="R"
|
label="R"
|
||||||
/>
|
/>
|
||||||
<SideBrushVisual
|
<SideBrushVisual
|
||||||
cx={center + innerCircle * 0.65}
|
cx={centerX + innerCircle * 0.65}
|
||||||
cy={center - innerCircle * 0.55}
|
cy={centerY - innerCircle * 0.55}
|
||||||
current={sideBrushCurrent}
|
current={sideBrushCurrent}
|
||||||
overcurrent={wheelOver.sideBrush}
|
overcurrent={wheelOver.sideBrush}
|
||||||
/>
|
/>
|
||||||
<MainBrushVisual
|
<MainBrushVisual
|
||||||
cx={center}
|
cx={centerX}
|
||||||
cy={center}
|
cy={centerY}
|
||||||
current={mainBrushCurrent}
|
current={mainBrushCurrent}
|
||||||
overcurrent={wheelOver.mainBrush}
|
overcurrent={wheelOver.mainBrush}
|
||||||
variant={variant}
|
variant={variant}
|
||||||
@@ -94,19 +97,21 @@ function TopDownMap({ sensors = {}, variant = 'full', size: overrideSize, overla
|
|||||||
dirtRight={sensors?.dirtDetect}
|
dirtRight={sensors?.dirtDetect}
|
||||||
/>
|
/>
|
||||||
{lightSegments.map((seg) => {
|
{lightSegments.map((seg) => {
|
||||||
const color = lightBumpColor(seg.value);
|
const color = lightBumpColor(seg.value, maxLight);
|
||||||
|
const tipR = lightRingOuter + 4; // point starts just outside bump arc
|
||||||
|
const baseR = tipR + 28; // extend starting length for more resolution
|
||||||
return (
|
return (
|
||||||
<ArcSegment
|
<ConeSegment
|
||||||
key={seg.label}
|
key={seg.label}
|
||||||
cx={center}
|
cx={centerX}
|
||||||
cy={center}
|
cy={centerY}
|
||||||
rInner={lightRingInner}
|
rBase={baseR}
|
||||||
rOuter={lightRingOuter}
|
rTip={tipR}
|
||||||
startDeg={seg.start}
|
startDeg={seg.start}
|
||||||
endDeg={seg.end}
|
endDeg={seg.end}
|
||||||
color={color}
|
color={color}
|
||||||
opacity={1}
|
value={seg.value}
|
||||||
pulse={false}
|
max={maxLight}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -115,8 +120,8 @@ function TopDownMap({ sensors = {}, variant = 'full', size: overrideSize, overla
|
|||||||
return (
|
return (
|
||||||
<ArcSegment
|
<ArcSegment
|
||||||
key={seg.label}
|
key={seg.label}
|
||||||
cx={center}
|
cx={centerX}
|
||||||
cy={center}
|
cy={centerY}
|
||||||
rInner={cliffRingInner}
|
rInner={cliffRingInner}
|
||||||
rOuter={cliffRingOuter}
|
rOuter={cliffRingOuter}
|
||||||
startDeg={seg.start}
|
startDeg={seg.start}
|
||||||
@@ -128,10 +133,10 @@ function TopDownMap({ sensors = {}, variant = 'full', size: overrideSize, overla
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<ArcSegment
|
<ArcSegment
|
||||||
cx={center}
|
cx={centerX}
|
||||||
cy={center}
|
cy={centerY}
|
||||||
rInner={lightRingOuter + 2}
|
rInner={lightRingInner}
|
||||||
rOuter={lightRingOuter + 8}
|
rOuter={lightRingOuter}
|
||||||
startDeg={-70}
|
startDeg={-70}
|
||||||
endDeg={-6}
|
endDeg={-6}
|
||||||
color={bumps.bumpLeft ? '#ef4444' : '#475569'}
|
color={bumps.bumpLeft ? '#ef4444' : '#475569'}
|
||||||
@@ -139,10 +144,10 @@ function TopDownMap({ sensors = {}, variant = 'full', size: overrideSize, overla
|
|||||||
pulse={Boolean(bumps.bumpLeft)}
|
pulse={Boolean(bumps.bumpLeft)}
|
||||||
/>
|
/>
|
||||||
<ArcSegment
|
<ArcSegment
|
||||||
cx={center}
|
cx={centerX}
|
||||||
cy={center}
|
cy={centerY}
|
||||||
rInner={lightRingOuter + 2}
|
rInner={lightRingInner}
|
||||||
rOuter={lightRingOuter + 8}
|
rOuter={lightRingOuter}
|
||||||
startDeg={6}
|
startDeg={6}
|
||||||
endDeg={70}
|
endDeg={70}
|
||||||
color={bumps.bumpRight ? '#ef4444' : '#475569'}
|
color={bumps.bumpRight ? '#ef4444' : '#475569'}
|
||||||
@@ -176,6 +181,23 @@ function ArcSegment({ cx, cy, rInner, rOuter, startDeg, endDeg, color, pulse = f
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ConeSegment({ cx, cy, rBase, rTip, startDeg, endDeg, color, value, max }) {
|
||||||
|
const mid = (startDeg + endDeg) / 2;
|
||||||
|
const baseA = polarToCartesian(cx, cy, rBase, startDeg);
|
||||||
|
const baseB = polarToCartesian(cx, cy, rBase, endDeg);
|
||||||
|
const tip = polarToCartesian(cx, cy, rTip, mid);
|
||||||
|
const norm = clamp01(value != null ? value / (max || 1) : 0);
|
||||||
|
const eased = Math.pow(norm, 0.35); // even more sensitive near the start, softer near the end
|
||||||
|
// higher value = closer obstacle → bar shrinks toward the tip (reverse fill)
|
||||||
|
const filledR = rBase - (rBase - rTip) * eased;
|
||||||
|
const barR = Math.max(rTip, Math.min(filledR, rBase));
|
||||||
|
const filledA = polarToCartesian(cx, cy, filledR, startDeg);
|
||||||
|
const filledB = polarToCartesian(cx, cy, filledR, endDeg);
|
||||||
|
const fg = `M ${tip.x} ${tip.y} L ${filledA.x} ${filledA.y} L ${filledB.x} ${filledB.y} Z`;
|
||||||
|
|
||||||
|
return <path d={fg} fill={color} opacity={1} stroke="none" />;
|
||||||
|
}
|
||||||
|
|
||||||
function describeArc(cx, cy, r, startDeg, endDeg) {
|
function describeArc(cx, cy, r, startDeg, endDeg) {
|
||||||
let start = startDeg;
|
let start = startDeg;
|
||||||
let end = endDeg;
|
let end = endDeg;
|
||||||
@@ -304,10 +326,14 @@ function MainBrushVisual({ cx, cy, current, overcurrent, variant, dirtLeft, dirt
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const LIGHT_BUMP_SENSITIVITY = 0.18;
|
function lightBumpColor(value, max) {
|
||||||
function lightBumpColor(value) {
|
if (value == null || value <= 0) return 'hsl(200 60% 18%)'; // faint blue instead of black
|
||||||
if (value == null || value <= 0) return '#000000';
|
const maxVal = max || 1;
|
||||||
const hue = (value * LIGHT_BUMP_SENSITIVITY) % 360;
|
const norm = clamp01(value / maxVal);
|
||||||
|
const eased = Math.pow(norm, 0.45); // match cone fill sensitivity
|
||||||
|
// offset the start hue so we don't begin at red, still sweep the full rainbow
|
||||||
|
const startHue = 200; // deep cyan/blue start
|
||||||
|
const hue = (startHue + eased * 360) % 360;
|
||||||
return `hsl(${hue} 100% 60%)`;
|
return `hsl(${hue} 100% 60%)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user