- Hono Worker + MapLibre GL 3D terrain map (satellite + Terrarium DEM, no API key) - Deterministic survey simulator: lawnmower flight + georeferenced detections - Species markers, flight path, timeline scrubber, confidence + type filters - D1 schema + POST /api/ingest for real drone data feeding the same dashboard Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
55 lines
2.2 KiB
Markdown
55 lines
2.2 KiB
Markdown
# 🛰️ CritterScope
|
|
|
|
Turn a drone survey into **georeferenced animal/object detections on a 3D map.**
|
|
|
|
A drone flies a survey → thermal+RGB frames + telemetry → an AI detector emits
|
|
warm-blob detections → each is projected onto terrain as `(lat, lon, type,
|
|
confidence, temp, time)` → this app plots them on a 3D terrain globe with a
|
|
timeline you can replay.
|
|
|
|
The dashboard runs **today** off a built-in simulator, so the whole UI is done and
|
|
testable before any drone arrives. Real footage feeds the *same* dashboard via
|
|
`POST /api/ingest`.
|
|
|
|
## Stack
|
|
- **Cloudflare Worker + Hono** (`src/index.js`)
|
|
- **MapLibre GL JS** — satellite imagery + Terrarium DEM for real 3D terrain (no API key)
|
|
- **D1** (optional) — stores real surveys/detections; schema in `schema.sql`
|
|
- Deploys to `critterscope.theradicalparty.com`
|
|
|
|
## Run locally
|
|
```bash
|
|
npm install
|
|
npm run dev # http://localhost:8787
|
|
```
|
|
Open `/` for the dashboard. Point it anywhere:
|
|
```
|
|
/?lat=-33.73&lon=150.31&r=1000 # center, radius (m)
|
|
/?seed=42 # different simulated survey
|
|
```
|
|
|
|
## Data contract (what the drone pipeline must produce)
|
|
`GET /api/survey` returns:
|
|
```jsonc
|
|
{
|
|
"survey": { "id","name","center_lon","center_lat","radius_m","sensor","drone","started_at","ended_at","simulated" },
|
|
"flight": [ { "seq","lon","lat","agl_m","t" } ],
|
|
"detections": [ { "id","type","lon","lat","confidence","temp_c","t","frame" } ],
|
|
"stats": { "total","counts","area_km2","duration_min" }
|
|
}
|
|
```
|
|
`type` ∈ `deer | fox | rabbit | boar | kangaroo | person | vehicle | unknown`.
|
|
|
|
## Feeding real drone data
|
|
1. `wrangler d1 create critterscope`, paste the id into `wrangler.toml`, uncomment the binding.
|
|
2. `npm run db:init`
|
|
3. `POST /api/ingest` with `{ survey, flight, detections }`.
|
|
4. View it at `/?survey=<id>`.
|
|
|
|
The georeferencing step (frame + drone GPS + gimbal angle + terrain → lat/lon) lives
|
|
in the drone pipeline, not here — this app just needs the resulting detections.
|
|
|
|
## Roadmap
|
|
- [ ] Drone ingest pipeline (RTMP/SRT frames → YOLO thermal detector → georeferencer)
|
|
- [ ] Live mode (stream detections during flight, not just post-survey)
|
|
- [ ] Track clustering (merge repeat sightings of the same animal across passes)
|