Rename CritterScope → Drones (repo, subdomain, branding)
Worker + subdomain now drones.theradicalparty.com; in-app title/brand, package names, docs updated. D1 database binding kept as-is. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
48866acc97
commit
224792550f
12 changed files with 25 additions and 24 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
# 🛰️ CritterScope
|
# 🚁 Drones
|
||||||
|
|
||||||
Turn a drone survey into **georeferenced animal/object detections on a 3D map.**
|
Turn a drone survey into **georeferenced animal/object detections on a 3D map.**
|
||||||
|
|
||||||
|
|
@ -15,7 +15,7 @@ testable before any drone arrives. Real footage feeds the *same* dashboard via
|
||||||
- **Cloudflare Worker + Hono** (`src/index.js`)
|
- **Cloudflare Worker + Hono** (`src/index.js`)
|
||||||
- **MapLibre GL JS** — satellite imagery + Terrarium DEM for real 3D terrain (no API key)
|
- **MapLibre GL JS** — satellite imagery + Terrarium DEM for real 3D terrain (no API key)
|
||||||
- **D1** (optional) — stores real surveys/detections; schema in `schema.sql`
|
- **D1** (optional) — stores real surveys/detections; schema in `schema.sql`
|
||||||
- Deploys to `critterscope.theradicalparty.com`
|
- Deploys to `drones.theradicalparty.com`
|
||||||
|
|
||||||
## Run locally
|
## Run locally
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -41,7 +41,7 @@ Open `/` for the dashboard. Point it anywhere:
|
||||||
`type` ∈ `deer | fox | rabbit | boar | kangaroo | person | vehicle | unknown`.
|
`type` ∈ `deer | fox | rabbit | boar | kangaroo | person | vehicle | unknown`.
|
||||||
|
|
||||||
## Feeding real drone data
|
## Feeding real drone data
|
||||||
1. `wrangler d1 create critterscope`, paste the id into `wrangler.toml`, uncomment the binding.
|
1. `wrangler d1 create drones`, paste the id into `wrangler.toml`, uncomment the binding.
|
||||||
2. `npm run db:init`
|
2. `npm run db:init`
|
||||||
3. `POST /api/ingest` with `{ survey, flight, detections }`.
|
3. `POST /api/ingest` with `{ survey, flight, detections }`.
|
||||||
4. View it at `/?survey=<id>`.
|
4. View it at `/?survey=<id>`.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "critterscope",
|
"name": "drones",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "Thermal/RGB drone survey → georeferenced animal detections on a 3D map",
|
"description": "Thermal/RGB drone survey → georeferenced animal detections on a 3D map",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# CritterScope drone ingest pipeline
|
# Drones drone ingest pipeline
|
||||||
|
|
||||||
Turns drone footage + telemetry into georeferenced detections and pushes them to
|
Turns drone footage + telemetry into georeferenced detections and pushes them to
|
||||||
a CritterScope instance.
|
a Drones instance.
|
||||||
|
|
||||||
```
|
```
|
||||||
video / RTMP frames + telemetry (DJI .SRT)
|
video / RTMP frames + telemetry (DJI .SRT)
|
||||||
|
|
@ -24,7 +24,7 @@ would send — proves the whole chain:
|
||||||
cd pipeline
|
cd pipeline
|
||||||
node src/run.js --synthetic --dry-run
|
node src/run.js --synthetic --dry-run
|
||||||
```
|
```
|
||||||
Push it into a running local CritterScope (with local D1, see root README):
|
Push it into a running local Drones (with local D1, see root README):
|
||||||
```bash
|
```bash
|
||||||
node src/run.js --synthetic --name "test-survey" --base-url http://localhost:8787
|
node src/run.js --synthetic --name "test-survey" --base-url http://localhost:8787
|
||||||
# → View it: http://localhost:8787/?survey=sv-test-survey-...
|
# → View it: http://localhost:8787/?survey=sv-test-survey-...
|
||||||
|
|
@ -37,7 +37,7 @@ node src/run.js \
|
||||||
--detector onnx --model yolo-thermal.onnx \
|
--detector onnx --model yolo-thermal.onnx \
|
||||||
--width 1920 --height 1080 \
|
--width 1920 --height 1080 \
|
||||||
--drone "DJI Mavic 2 Enterprise Advanced" \
|
--drone "DJI Mavic 2 Enterprise Advanced" \
|
||||||
--base-url https://critterscope.theradicalparty.com
|
--base-url https://drones.theradicalparty.com
|
||||||
```
|
```
|
||||||
|
|
||||||
## Live RTMP (DJI Fly app livestream)
|
## Live RTMP (DJI Fly app livestream)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"name": "critterscope-pipeline",
|
"name": "drones-pipeline",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "Drone footage + telemetry → georeferenced detections → CritterScope",
|
"description": "Drone footage + telemetry → georeferenced detections → Drones",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bin": { "critterscope-ingest": "src/run.js" },
|
"bin": { "drones-ingest": "src/run.js" },
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"demo": "node src/run.js --synthetic --dry-run",
|
"demo": "node src/run.js --synthetic --dry-run",
|
||||||
"demo:ingest": "node src/run.js --synthetic --base-url http://localhost:8787"
|
"demo:ingest": "node src/run.js --synthetic --base-url http://localhost:8787"
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
// - stub: deterministic synthetic detections so the whole pipeline runs and
|
// - stub: deterministic synthetic detections so the whole pipeline runs and
|
||||||
// can be validated end-to-end without a model or real footage.
|
// can be validated end-to-end without a model or real footage.
|
||||||
//
|
//
|
||||||
// The class list is COCO-ish remapped to the CritterScope species vocabulary.
|
// The class list is COCO-ish remapped to the Drones species vocabulary.
|
||||||
// For thermal you'd train/fine-tune on thermal wildlife imagery; the interface
|
// For thermal you'd train/fine-tune on thermal wildlife imagery; the interface
|
||||||
// is identical.
|
// is identical.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// POST an assembled survey to a CritterScope instance.
|
// POST an assembled survey to a Drones instance.
|
||||||
|
|
||||||
export async function postSurvey({ baseUrl, survey, flight, detections }) {
|
export async function postSurvey({ baseUrl, survey, flight, detections }) {
|
||||||
const res = await fetch(`${baseUrl.replace(/\/$/, "")}/api/ingest`, {
|
const res = await fetch(`${baseUrl.replace(/\/$/, "")}/api/ingest`, {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
// CritterScope drone ingest pipeline.
|
// Drones drone ingest pipeline.
|
||||||
//
|
//
|
||||||
// video/RTMP frames + telemetry (DJI SRT) → detector → georeferencer
|
// video/RTMP frames + telemetry (DJI SRT) → detector → georeferencer
|
||||||
// → survey JSON → POST /api/ingest → view at /?survey=<id>
|
// → survey JSON → POST /api/ingest → view at /?survey=<id>
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
//
|
//
|
||||||
// # real footage:
|
// # real footage:
|
||||||
// node src/run.js --source flight.MP4 --srt flight.SRT --detector onnx \
|
// node src/run.js --source flight.MP4 --srt flight.SRT --detector onnx \
|
||||||
// --model yolo-thermal.onnx --base-url https://critterscope.theradicalparty.com
|
// --model yolo-thermal.onnx --base-url https://drones.theradicalparty.com
|
||||||
//
|
//
|
||||||
// # live RTMP stream from the DJI Fly app:
|
// # live RTMP stream from the DJI Fly app:
|
||||||
// node src/run.js --source rtmp://localhost/live/stream --srt live.SRT --fps 1
|
// node src/run.js --source rtmp://localhost/live/stream --srt live.SRT --fps 1
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
-- CritterScope data model.
|
-- Drones data model.
|
||||||
-- A "survey" is one drone flight over an area; "detections" are georeferenced
|
-- A "survey" is one drone flight over an area; "detections" are georeferenced
|
||||||
-- animals/objects found in that survey. The demo runs off the live simulator,
|
-- animals/objects found in that survey. The demo runs off the live simulator,
|
||||||
-- but real drone footage lands here via POST /api/ingest.
|
-- but real drone footage lands here via POST /api/ingest.
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ app.post("/api/ingest", async (c) => {
|
||||||
return c.json({ ok: true, survey: id, detections: (body.detections || []).length });
|
return c.json({ ok: true, survey: id, detections: (body.detections || []).length });
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/health", (c) => c.json({ ok: true, service: "critterscope" }));
|
app.get("/health", (c) => c.json({ ok: true, service: "drones" }));
|
||||||
|
|
||||||
async function loadSurvey(db, id) {
|
async function loadSurvey(db, id) {
|
||||||
const survey = await db.prepare(`SELECT * FROM surveys WHERE id=?`).bind(id).first();
|
const survey = await db.prepare(`SELECT * FROM surveys WHERE id=?`).bind(id).first();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// The CritterScope dashboard, served as a single self-contained HTML document.
|
// The Drones dashboard, served as a single self-contained HTML document.
|
||||||
// MapLibre GL JS (free, no API key): satellite imagery + Terrarium DEM for real
|
// MapLibre GL JS (free, no API key): satellite imagery + Terrarium DEM for real
|
||||||
// 3D terrain relief. Detections render as species markers draped on the terrain;
|
// 3D terrain relief. Detections render as species markers draped on the terrain;
|
||||||
// a timeline scrubber replays the survey as the drone flew it.
|
// a timeline scrubber replays the survey as the drone flew it.
|
||||||
|
|
@ -10,7 +10,7 @@ export function page(cfg) {
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
||||||
<title>CritterScope — drone wildlife survey</title>
|
<title>Drones — drone wildlife survey</title>
|
||||||
<link href="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css" rel="stylesheet" />
|
<link href="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css" rel="stylesheet" />
|
||||||
<script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
|
<script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
|
||||||
<style>
|
<style>
|
||||||
|
|
@ -56,7 +56,7 @@ export function page(cfg) {
|
||||||
<div id="loading">Loading terrain & survey…</div>
|
<div id="loading">Loading terrain & survey…</div>
|
||||||
|
|
||||||
<div id="hud" class="panel">
|
<div id="hud" class="panel">
|
||||||
<h1>🛰️ CritterScope <span id="mode" class="badge sim">SIM</span></h1>
|
<h1>🚁 Drones <span id="mode" class="badge sim">SIM</span></h1>
|
||||||
<div class="sub" id="surveyName">—</div>
|
<div class="sub" id="surveyName">—</div>
|
||||||
<div class="stats">
|
<div class="stats">
|
||||||
<div class="stat"><b id="sTotal">0</b><span>detections</span></div>
|
<div class="stat"><b id="sTotal">0</b><span>detections</span></div>
|
||||||
|
|
@ -230,6 +230,7 @@ playBtn.onclick=()=>{
|
||||||
// initialise clock once loaded
|
// initialise clock once loaded
|
||||||
const _origRender=renderSurvey;
|
const _origRender=renderSurvey;
|
||||||
</script>
|
</script>
|
||||||
|
<script src="https://theradicalparty.com/footer.js" data-mode="pill" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>`;
|
</html>`;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
# The live deploy uses wrangler.toml (simulator; no D1) until a D1-capable
|
# The live deploy uses wrangler.toml (simulator; no D1) until a D1-capable
|
||||||
# Cloudflare token is available — then move this binding into wrangler.toml
|
# Cloudflare token is available — then move this binding into wrangler.toml
|
||||||
# with the real database_id.
|
# with the real database_id.
|
||||||
name = "critterscope"
|
name = "drones"
|
||||||
main = "src/index.js"
|
main = "src/index.js"
|
||||||
compatibility_date = "2024-11-01"
|
compatibility_date = "2024-11-01"
|
||||||
compatibility_flags = ["nodejs_compat"]
|
compatibility_flags = ["nodejs_compat"]
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
name = "critterscope"
|
name = "drones"
|
||||||
main = "src/index.js"
|
main = "src/index.js"
|
||||||
compatibility_date = "2024-11-01"
|
compatibility_date = "2024-11-01"
|
||||||
compatibility_flags = ["nodejs_compat"]
|
compatibility_flags = ["nodejs_compat"]
|
||||||
|
|
||||||
routes = [{ pattern = "critterscope.theradicalparty.com", custom_domain = true }]
|
routes = [{ pattern = "drones.theradicalparty.com", custom_domain = true }]
|
||||||
|
|
||||||
[vars]
|
[vars]
|
||||||
BASE_URL = "https://critterscope.theradicalparty.com"
|
BASE_URL = "https://drones.theradicalparty.com"
|
||||||
# Default map center [lon, lat] and survey radius (metres). Override per-survey via ?lat=&lon=&r=
|
# Default map center [lon, lat] and survey radius (metres). Override per-survey via ?lat=&lon=&r=
|
||||||
DEFAULT_LON = "150.3119"
|
DEFAULT_LON = "150.3119"
|
||||||
DEFAULT_LAT = "-33.7300"
|
DEFAULT_LAT = "-33.7300"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue