mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
?plooooo
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-DNer42rE.js"></script>
|
<script type="module" crossorigin src="/assets/index-ZItnCUqh.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-BBEWYgmH.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-BBEWYgmH.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default function OvercurrentLimiterPanel() {
|
|||||||
) : (
|
) : (
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
{groups.map((key) => {
|
{groups.map((key) => {
|
||||||
const temperature = overcurrentLimiter?.temperatures?.[key] ?? 0;
|
const cap = overcurrentLimiter?.caps?.[key] ?? 0;
|
||||||
const over = overcurrentLimiter?.overcurrent?.groups?.[key] ?? false;
|
const over = overcurrentLimiter?.overcurrent?.groups?.[key] ?? false;
|
||||||
const scale = overcurrentLimiter?.scales?.perGroup?.[key] ?? 1;
|
const scale = overcurrentLimiter?.scales?.perGroup?.[key] ?? 1;
|
||||||
return (
|
return (
|
||||||
@@ -52,10 +52,10 @@ export default function OvercurrentLimiterPanel() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
<div className="flex items-center justify-between text-[0.7rem] text-slate-400">
|
<div className="flex items-center justify-between text-[0.7rem] text-slate-400">
|
||||||
<span>Temperature</span>
|
<span>Cap</span>
|
||||||
<span>{formatPct(temperature)}</span>
|
<span>{formatPct(cap)}</span>
|
||||||
</div>
|
</div>
|
||||||
<ProgressBar value={temperature} color="bg-amber-500" />
|
<ProgressBar value={cap} color="bg-amber-500" />
|
||||||
<div className="flex items-center justify-between text-[0.7rem] text-slate-400">
|
<div className="flex items-center justify-between text-[0.7rem] text-slate-400">
|
||||||
<span>Scale</span>
|
<span>Scale</span>
|
||||||
<span>{formatPct(scale)}</span>
|
<span>{formatPct(scale)}</span>
|
||||||
@@ -65,8 +65,7 @@ export default function OvercurrentLimiterPanel() {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<div className="surface text-[0.7rem] text-slate-400">
|
<div className="surface text-[0.7rem] text-slate-400">
|
||||||
<div>{`Heat up ${overcurrentLimiter?.config?.heatUpSec}s · Cool down ${overcurrentLimiter?.config?.coolDownSec}s`}</div>
|
<div>{`Down rate ${overcurrentLimiter?.config?.downRatePerSec}/s · Up rate ${overcurrentLimiter?.config?.upRatePerSec}/s`}</div>
|
||||||
<div>{`Knee ${overcurrentLimiter?.config?.kneeSec}s`}</div>
|
|
||||||
<div>{`Output rate ${overcurrentLimiter?.config?.outputRateMs}ms`}</div>
|
<div>{`Output rate ${overcurrentLimiter?.config?.outputRateMs}ms`}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,15 +8,14 @@ export const OVERCURRENT_GROUPS = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const DEFAULT_OVERCURRENT_LIMITS = {
|
export const DEFAULT_OVERCURRENT_LIMITS = {
|
||||||
heatUpSec: 2,
|
downRatePerSec: 0.25,
|
||||||
coolDownSec: 12,
|
upRatePerSec: 0.1,
|
||||||
kneeSec: 0,
|
|
||||||
outputRateMs: 250,
|
outputRateMs: 250,
|
||||||
};
|
};
|
||||||
|
|
||||||
function createInitialTemperatures() {
|
function createInitialCaps() {
|
||||||
return OVERCURRENT_GROUPS.reduce((acc, group) => {
|
return OVERCURRENT_GROUPS.reduce((acc, group) => {
|
||||||
acc[group.key] = 0;
|
acc[group.key] = 1;
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
@@ -26,14 +25,6 @@ function clampUnit(value) {
|
|||||||
return Math.max(0, Math.min(1, value));
|
return Math.max(0, Math.min(1, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
function stepValue(current, delta, seconds, direction) {
|
|
||||||
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
||||||
return direction === 'up' ? 1 : 0;
|
|
||||||
}
|
|
||||||
const amount = delta / seconds;
|
|
||||||
return direction === 'up' ? current + amount : current - amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useOvercurrentLimiter(roverId, options = {}) {
|
export function useOvercurrentLimiter(roverId, options = {}) {
|
||||||
const { session } = useSession();
|
const { session } = useSession();
|
||||||
const frame = useTelemetryFrame(roverId);
|
const frame = useTelemetryFrame(roverId);
|
||||||
@@ -43,7 +34,7 @@ export function useOvercurrentLimiter(roverId, options = {}) {
|
|||||||
() => ({ ...DEFAULT_OVERCURRENT_LIMITS, ...(options.config || {}) }),
|
() => ({ ...DEFAULT_OVERCURRENT_LIMITS, ...(options.config || {}) }),
|
||||||
[options.config],
|
[options.config],
|
||||||
);
|
);
|
||||||
const [temperatures, setTemperatures] = useState(() => createInitialTemperatures());
|
const [caps, setCaps] = useState(() => createInitialCaps());
|
||||||
const lastTickRef = useRef(typeof performance !== 'undefined' ? performance.now() : Date.now());
|
const lastTickRef = useRef(typeof performance !== 'undefined' ? performance.now() : Date.now());
|
||||||
const flagsRef = useRef(overcurrentFlags);
|
const flagsRef = useRef(overcurrentFlags);
|
||||||
|
|
||||||
@@ -52,7 +43,7 @@ export function useOvercurrentLimiter(roverId, options = {}) {
|
|||||||
}, [overcurrentFlags]);
|
}, [overcurrentFlags]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTemperatures(createInitialTemperatures());
|
setCaps(createInitialCaps());
|
||||||
}, [roverId]);
|
}, [roverId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -62,39 +53,32 @@ export function useOvercurrentLimiter(roverId, options = {}) {
|
|||||||
lastTickRef.current = now;
|
lastTickRef.current = now;
|
||||||
const deltaSec = deltaMs / 1000;
|
const deltaSec = deltaMs / 1000;
|
||||||
if (deltaSec <= 0) return;
|
if (deltaSec <= 0) return;
|
||||||
setTemperatures((prev) => {
|
setCaps((prev) => {
|
||||||
let changed = false;
|
let changed = false;
|
||||||
const next = {};
|
const next = {};
|
||||||
|
const downRate = Number.isFinite(config.downRatePerSec) ? Math.max(0, config.downRatePerSec) : 0;
|
||||||
|
const upRate = Number.isFinite(config.upRatePerSec) ? Math.max(0, config.upRatePerSec) : 0;
|
||||||
OVERCURRENT_GROUPS.forEach((group) => {
|
OVERCURRENT_GROUPS.forEach((group) => {
|
||||||
const prevEntry = Number.isFinite(prev[group.key]) ? prev[group.key] : 0;
|
const prevEntry = Number.isFinite(prev[group.key]) ? prev[group.key] : 1;
|
||||||
const over = group.motors.some((motor) => Boolean(flagsRef.current?.[motor]));
|
const over = group.motors.some((motor) => Boolean(flagsRef.current?.[motor]));
|
||||||
const nextTemp = clampUnit(
|
const nextCap = clampUnit(
|
||||||
stepValue(
|
over ? prevEntry - downRate * deltaSec : prevEntry + upRate * deltaSec,
|
||||||
prevEntry,
|
|
||||||
deltaSec,
|
|
||||||
over ? config.heatUpSec : config.coolDownSec,
|
|
||||||
over ? 'up' : 'down',
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
if (Math.abs(nextTemp - prevEntry) > 0.0001) {
|
if (Math.abs(nextCap - prevEntry) > 0.0001) {
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
next[group.key] = nextTemp;
|
next[group.key] = nextCap;
|
||||||
});
|
});
|
||||||
return changed ? next : prev;
|
return changed ? next : prev;
|
||||||
});
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, [config.heatUpSec, config.coolDownSec]);
|
}, [config.downRatePerSec, config.upRatePerSec]);
|
||||||
|
|
||||||
const scales = useMemo(() => {
|
const scales = useMemo(() => {
|
||||||
const kneeSec = Number.isFinite(config.kneeSec) ? Math.max(0, config.kneeSec) : 0;
|
|
||||||
const heatUpSec = Number.isFinite(config.heatUpSec) ? Math.max(0.001, config.heatUpSec) : 0.001;
|
|
||||||
const kneeTemp = clampUnit(kneeSec / heatUpSec);
|
|
||||||
const perGroup = OVERCURRENT_GROUPS.reduce((acc, group) => {
|
const perGroup = OVERCURRENT_GROUPS.reduce((acc, group) => {
|
||||||
const temp = Number.isFinite(temperatures?.[group.key]) ? temperatures[group.key] : 0;
|
const cap = Number.isFinite(caps?.[group.key]) ? caps[group.key] : 1;
|
||||||
const normalized = kneeTemp >= 1 ? 0 : clampUnit((temp - kneeTemp) / (1 - kneeTemp));
|
acc[group.key] = clampUnit(cap);
|
||||||
acc[group.key] = clampUnit(1 - normalized);
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
return {
|
return {
|
||||||
@@ -109,7 +93,7 @@ export function useOvercurrentLimiter(roverId, options = {}) {
|
|||||||
vacuum: 1,
|
vacuum: 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}, [config.heatUpSec, config.kneeSec, temperatures]);
|
}, [caps]);
|
||||||
|
|
||||||
const overcurrent = useMemo(() => {
|
const overcurrent = useMemo(() => {
|
||||||
const motors = {};
|
const motors = {};
|
||||||
@@ -132,14 +116,14 @@ export function useOvercurrentLimiter(roverId, options = {}) {
|
|||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
temperatures,
|
caps,
|
||||||
overcurrent,
|
overcurrent,
|
||||||
scales,
|
scales,
|
||||||
isActive: (scales?.drive?.left ?? 1) < 1 || (scales?.drive?.right ?? 1) < 1 || (scales?.aux?.main ?? 1) < 1 || (scales?.aux?.side ?? 1) < 1,
|
isActive: (scales?.drive?.left ?? 1) < 1 || (scales?.drive?.right ?? 1) < 1 || (scales?.aux?.main ?? 1) < 1 || (scales?.aux?.side ?? 1) < 1,
|
||||||
config,
|
config,
|
||||||
adminImmune,
|
adminImmune,
|
||||||
}),
|
}),
|
||||||
[temperatures, overcurrent, scales, config, adminImmune],
|
[caps, overcurrent, scales, config, adminImmune],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user