Stream in costmap from mediamtx.

This commit is contained in:
James Pace 2026-05-26 15:38:15 -04:00
parent 4408a1359a
commit 3a2589d6aa
5 changed files with 50 additions and 29 deletions

24
.pnp.cjs generated
View File

@ -45,6 +45,7 @@ const RAW_RUNTIME_STATE =
["globals", "npm:16.5.0"],\ ["globals", "npm:16.5.0"],\
["jotai", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:2.18.0"],\ ["jotai", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:2.18.0"],\
["jotai-tanstack-query", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:0.11.0"],\ ["jotai-tanstack-query", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:0.11.0"],\
["mediamtx-webrtc-react", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:1.0.1"],\
["prettier", "npm:3.8.1"],\ ["prettier", "npm:3.8.1"],\
["react", "npm:19.2.4"],\ ["react", "npm:19.2.4"],\
["react-bootstrap", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:2.10.10"],\ ["react-bootstrap", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:2.10.10"],\
@ -1670,6 +1671,7 @@ const RAW_RUNTIME_STATE =
["globals", "npm:16.5.0"],\ ["globals", "npm:16.5.0"],\
["jotai", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:2.18.0"],\ ["jotai", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:2.18.0"],\
["jotai-tanstack-query", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:0.11.0"],\ ["jotai-tanstack-query", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:0.11.0"],\
["mediamtx-webrtc-react", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:1.0.1"],\
["prettier", "npm:3.8.1"],\ ["prettier", "npm:3.8.1"],\
["react", "npm:19.2.4"],\ ["react", "npm:19.2.4"],\
["react-bootstrap", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:2.10.10"],\ ["react-bootstrap", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:2.10.10"],\
@ -2787,6 +2789,28 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\ "linkType": "HARD"\
}]\ }]\
]],\ ]],\
["mediamtx-webrtc-react", [\
["npm:1.0.1", {\
"packageLocation": "./.yarn/cache/mediamtx-webrtc-react-npm-1.0.1-de237e3035-ee1e630f20.zip/node_modules/mediamtx-webrtc-react/",\
"packageDependencies": [\
["mediamtx-webrtc-react", "npm:1.0.1"]\
],\
"linkType": "SOFT"\
}],\
["virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:1.0.1", {\
"packageLocation": "./.yarn/__virtual__/mediamtx-webrtc-react-virtual-8ea5a37835/0/cache/mediamtx-webrtc-react-npm-1.0.1-de237e3035-ee1e630f20.zip/node_modules/mediamtx-webrtc-react/",\
"packageDependencies": [\
["@types/react", "npm:19.2.14"],\
["mediamtx-webrtc-react", "virtual:ae939b5bf1c4da31987d1d461851d6cc956667f76e9d6d3a45643e06af20bf533b9bcec6bab70ed0ca795aebf9ce43b3ed74bd20004783b74b2a0cc963cd86b8#npm:1.0.1"],\
["react", "npm:19.2.4"]\
],\
"packagePeers": [\
"@types/react",\
"react"\
],\
"linkType": "HARD"\
}]\
]],\
["minimatch", [\ ["minimatch", [\
["npm:10.2.4", {\ ["npm:10.2.4", {\
"packageLocation": "./.yarn/cache/minimatch-npm-10.2.4-11f0605299-35f3dfb7b9.zip/node_modules/minimatch/",\ "packageLocation": "./.yarn/cache/minimatch-npm-10.2.4-11f0605299-35f3dfb7b9.zip/node_modules/minimatch/",\

View File

@ -16,6 +16,7 @@
"bootstrap": "^5.3.8", "bootstrap": "^5.3.8",
"jotai": "^2.18.0", "jotai": "^2.18.0",
"jotai-tanstack-query": "^0.11.0", "jotai-tanstack-query": "^0.11.0",
"mediamtx-webrtc-react": "^1.0.1",
"prettier": "^3.8.1", "prettier": "^3.8.1",
"react": "^19.2.0", "react": "^19.2.0",
"react-bootstrap": "^2.10.10", "react-bootstrap": "^2.10.10",

View File

@ -12,33 +12,7 @@ import { AppNav, Footer } from "./AppNav.tsx";
import { Container, Row, Col, Image, Card } from "react-bootstrap"; import { Container, Row, Col, Image, Card } from "react-bootstrap";
import { atom, useAtomValue } from "jotai"; import { atom, useAtomValue } from "jotai";
import { atomWithQuery } from "jotai-tanstack-query"; import { atomWithQuery } from "jotai-tanstack-query";
import { WebRTCVideo } from "mediamtx-webrtc-react";
const costmapImageQuery = async () => {
const resp = await fetch("api/costmap_image");
if (!resp.ok) {
throw new Error("Network response was not ok");
}
const blob = await resp.blob();
return URL.createObjectURL(blob);
};
const costmapImageQueryAtom = atomWithQuery(() => ({
queryKey: ["costmap_image"],
queryFn: costmapImageQuery,
refetchInterval: 1000, // 1s
}));
const costmapImageAtom = atom((get) => {
const response = get(costmapImageQueryAtom);
if (response.isPending) {
return <p>"Loading..."</p>;
}
if (response.isError) {
return <p>"Error loading!"</p>;
}
const costmapStyle = {
minHeight: "65svb",
};
return <Image src={response.data} fluid style={costmapStyle} />;
});
const statusStringQuery = async () => { const statusStringQuery = async () => {
const resp = await fetch("api/status"); const resp = await fetch("api/status");
@ -81,7 +55,6 @@ const latLongAtom = atom((get) => {
}); });
export function Autonomy() { export function Autonomy() {
const costmapImage = useAtomValue(costmapImageAtom);
const statusString = useAtomValue(statusStringAtom); const statusString = useAtomValue(statusStringAtom);
const latLong = useAtomValue(latLongAtom); const latLong = useAtomValue(latLongAtom);
@ -91,7 +64,14 @@ export function Autonomy() {
<Container className="vert-padded"> <Container className="vert-padded">
<Card className="padded"> <Card className="padded">
<Row> <Row>
<Col lg={8}>{costmapImage}</Col> <Col lg={8}>
<WebRTCVideo
url="http://localhost:8889/image/whep"
controls
autoPlay
style={{ width: "100%", maxWidth: "800px" }}
/>
</Col>
<Col lg={4}> <Col lg={4}>
<p>Status:</p> <p>Status:</p>
<pre>{statusString}</pre> <pre>{statusString}</pre>

View File

@ -1188,6 +1188,7 @@ __metadata:
globals: "npm:^16.5.0" globals: "npm:^16.5.0"
jotai: "npm:^2.18.0" jotai: "npm:^2.18.0"
jotai-tanstack-query: "npm:^0.11.0" jotai-tanstack-query: "npm:^0.11.0"
mediamtx-webrtc-react: "npm:^1.0.1"
prettier: "npm:^3.8.1" prettier: "npm:^3.8.1"
react: "npm:^19.2.0" react: "npm:^19.2.0"
react-bootstrap: "npm:^2.10.10" react-bootstrap: "npm:^2.10.10"
@ -2167,6 +2168,21 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"mediamtx-webrtc-react@npm:^1.0.1":
version: 1.0.1
resolution: "mediamtx-webrtc-react@npm:1.0.1"
peerDependencies:
"@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
peerDependenciesMeta:
"@types/react":
optional: true
react:
optional: true
checksum: 10c0/ee1e630f203b94ddba9e2caa20187f05989098814cc6efd89a0c32e75e887dc3a536ca74ea7ed26689ef7dd732fa0f18b3222570ae915eb86fcf70ae665f662d
languageName: node
linkType: hard
"minimatch@npm:^10.2.2": "minimatch@npm:^10.2.2":
version: 10.2.4 version: 10.2.4
resolution: "minimatch@npm:10.2.4" resolution: "minimatch@npm:10.2.4"