See Beneath the Ice
A submarine-style pilot control interface for a DIY ice fishing ROV. Features a simulated underwater camera feed, depth/compass/attitude instruments, sonar display, thruster controls, and mission logging — all running on simulated data, ready to wire to real Raspberry Pi hardware.
Working prototype — UI-only with simulated sensor data. No hardware integration yet.
- Camera Feed — Canvas-rendered underwater viewport with depth-dependent color grading, caustic light effects, floating sediment particles, bubble streams, fish silhouettes, vignette, and toggleable scanlines. HUD overlay shows depth, heading, temp, camera tilt, zoom level, and LED brightness. Center crosshair.
- Depth Gauge — Circular SVG gauge (0-30m) with sweeping needle, tick marks, and three color zones: blue (safe), amber (caution at 15m), red (danger at 25m). Displays meters and feet.
- Compass — Rotating compass rose with N/S/E/W labels, minor tick marks, fixed heading indicator triangle, and numeric heading readout with cardinal direction.
- Attitude Indicator — Aircraft-style artificial horizon showing pitch (±45°) and roll (±30°) with pitch ladder, roll pointer, and fixed aircraft symbol.
- Water Temperature — Numeric readout in °C and °F with vertical bar gauge. Simulates thermocline (temperature decreases with depth).
- Thruster Status — Four thruster bars (Fwd Port, Fwd Stbd, Aft Port, Aft Stbd) showing power level from -100% to +100%. Color-coded: green (forward), amber (idle), red (reverse).
- Tether Status — Tether payout length, 5-bar signal quality indicator, and tension state (slack/normal/taut).
- Sonar Display — Two modes switchable via button or Tab key:
- Cone View: Top-down sonar with rotating sweep line, phosphor afterglow trail, range rings at 2m intervals, bottom return ring, and fish blips that fade over time.
- Profile View: Scrolling fish-finder style depth profile with bottom contour, ROV depth line, fish arch indicators, and depth scale.
- Status Bar — Top bar showing: FROSTBYTE branding, arm/disarm toggle, battery level with drain indicator, tether length, signal quality, internal electronics temp, leak sensor status, SD card space, recording indicator, and depth warning alert.
- Controls Display — WASD key visualization that highlights on press. LED brightness slider. Arm/disarm safety toggle.
- Mission Log — Timestamped event log showing arm/disarm, recording, waypoints, screenshots, and battery warnings. Waypoints section shows recent marks with depth and heading.
- Keyboard Controls — Full keyboard piloting with WASD thrust, Q/E vertical, arrow keys for camera tilt, and hotkeys for all actions.
- Simulation Engine — Zustand-based state with smooth random walk sensor data, thermocline temperature model, battery drain proportional to thrust, fish event spawning, and sonar history tracking.
- Waypoints — Saved to localStorage, persist across sessions.
- Real hardware integration (Raspberry Pi, thrusters, camera)
- WebRTC / MJPEG video streaming
- Sound effects (motor hum, sonar ping, bubbles)
- Gamepad / joystick support
- Camera zoom functionality (UI exists, no visual zoom on canvas)
npm install npm run devOpen http://localhost:5173 (or whichever port Vite assigns).
| Key | Action |
|---|---|
| W / S | Forward / Backward |
| A / D | Yaw Left / Right |
| Q / E | Ascend / Descend |
| Arrow Up/Down | Camera Tilt |
| Space | Arm / Disarm |
| L | Toggle Lights |
| R | Toggle Recording |
| M | Mark Waypoint |
| P | Screenshot (log entry) |
| Tab | Switch Sonar Mode |
| Layer | Technology |
|---|---|
| Framework | React 18 + Vite 5 |
| Gauges | Custom SVG components |
| Sonar / Camera | HTML Canvas |
| Animation | CSS animations |
| State | Zustand 4 |
| Styling | Tailwind CSS 3 |
src/ ├── App.jsx # Root component ├── main.jsx # Entry point ├── index.css # Tailwind + design system ├── components/ │ ├── PilotHUD.jsx # Main layout │ ├── CameraFeed/ │ │ ├── MainFeed.jsx # Canvas underwater scene │ │ ├── FeedOverlay.jsx # HUD overlay │ │ └── RecordingIndicator.jsx # REC indicator │ ├── Instruments/ │ │ ├── DepthGauge.jsx # Circular depth gauge │ │ ├── Compass.jsx # Heading compass rose │ │ ├── AttitudeIndicator.jsx # Pitch + roll horizon │ │ ├── TempGauge.jsx # Water temperature │ │ ├── ThrusterBars.jsx # 4x thruster power bars │ │ └── TetherLength.jsx # Tether + signal + tension │ ├── Sonar/ │ │ └── SonarDisplay.jsx # Cone view + profile view │ ├── Controls/ │ │ ├── ThrusterControls.jsx # WASD key display │ │ ├── LightControls.jsx # LED brightness slider │ │ └── ArmSwitch.jsx # Arm/disarm toggle │ ├── StatusBar/ │ │ └── StatusBar.jsx # Top status bar │ └── MissionLog/ │ └── LogPanel.jsx # Event log + waypoints ├── data/ │ ├── rovConfig.js # ROV specs │ └── simulatedSensors.js # Sensor simulation ├── hooks/ │ ├── useStore.js # Zustand store │ ├── useKeyboardControls.js # Keyboard bindings │ └── useSimulation.js # RAF simulation loop └── utils/ └── formatters.js # Display formatters npm run build # Output in dist/ — serve statically or run locallyMIT