A browser-based collision detection prototype that uses GPS, speed, and heading data to detect potential vehicle collisions in real time. No app install, no backend required.
| File | Purpose |
|---|---|
collision_detection.html |
Full simulation — 3 vehicles, map view, multiple scenarios |
real_sensor_test.html |
Real GPS mode — uses your phone's actual sensors |
relay.js |
Optional WebSocket relay server for multi-phone testing |
README.md |
This file |
The engine runs three calculations on every GPS update:
Calculates the straight-line distance in metres between two GPS coordinates. Works accurately for short distances (under a few kilometres).
a = sin²(Δlat/2) + cos(lat1) × cos(lat2) × sin²(Δlon/2)
distance = 2R × atan2(√a, √(1−a)) where R = 6,371,000 m
Converts each vehicle's heading + speed into a 2D velocity vector (east/north components), then projects the relative velocity along the line connecting the two vehicles. A positive value means they are approaching each other.
closing_speed = −(relative_velocity · unit_separation_vector)
TTC = distance / closing_speed (Infinity if diverging)
| Condition | Risk Level |
|---|---|
| Distance < 20 m | HIGH |
| Distance < 60 m AND TTC < 5 s AND approaching | HIGH |
| Distance < 120 m OR TTC < 12 s AND approaching | MEDIUM |
| All other cases | LOW |
File: collision_detection.html
Double-click collision_detection.html — it opens directly in any browser.
No server, no install, no internet connection required.
┌─────────────────────────────┬──────────────────┐
│ │ Alert Status │
│ Top-down map view │ Pair Metrics │
│ with vehicle arrows │ Vehicle Sensors │
│ and distance labels │ Risk Matrix │
│ │ Controls │
└─────────────────────────────┴──────────────────┘
- Coloured circles = vehicles (red, blue, green)
- Arrows = direction of travel
- Dashed lines = distance between each pair
- Glow effect = vehicle is in HIGH risk state
Click a scenario button in the Controls panel:
| Scenario | Description | What to Expect |
|---|---|---|
| Head-On | Two cars driving directly at each other | Risk goes LOW → MEDIUM → HIGH in ~4 seconds |
| T-Bone | One car heading east, one heading south, meeting at an intersection | Diagonal collision course |
| Near Miss | Vehicles slightly offset so they just avoid each other | Risk peaks at MEDIUM, never reaches HIGH |
- Pause / Resume — freeze the simulation to inspect sensor values
- Reset — restart the current scenario from the beginning
- Simulation auto-resets after a collision (distance < 3 m) or when vehicles drift too far apart (> 300 m)
| Metric | What It Means |
|---|---|
| Distance | Current separation between the closest pair, in metres |
| Closing Speed | How fast they are approaching (▼) or moving apart (▲) in m/s |
| Time-To-Collision | Seconds until impact at current speeds and headings |
| Bearing A→B | Compass direction from vehicle A to vehicle B |
File: real_sensor_test.html
Uses your phone's GPS, speed sensor, and compass for Vehicle 1. Vehicle 2 is simulated and placed ahead of you using sliders.
Option A — ngrok (works on both iOS and Android):
# Install ngrok from https://ngrok.com/download
# Then in this folder:
npx serve . # serves on http://localhost:3000
ngrok http 3000 # creates a public HTTPS URL
# Copy the https://xxxx.ngrok.io URL and open it on your phoneOption B — Same Wi-Fi network (Android Chrome only):
python3 -m http.server 8080
# Find your laptop IP: run `ifconfig` (Mac/Linux) or `ipconfig` (Windows)
# On your Android phone open: http://YOUR_LAPTOP_IP:8080/real_sensor_test.htmlNote: iOS Safari requires HTTPS for GPS access. Use ngrok for iPhone testing.
When you open the page on your phone:
- Tap Start GPS
- Allow location access when the browser prompts
- On iPhone, also allow motion/orientation access when prompted (for compass)
| Field | Source | Notes |
|---|---|---|
| Latitude / Longitude | GPS chip | Updated every ~1 second |
| Speed | GPS doppler | In m/s. Accurate above ~1 m/s. Zero when stationary |
| Heading | GPS track or compass | GPS track used when moving; device compass used when still |
| Accuracy | GPS chip | Typical values: 5–15 m outdoors, 20–50 m indoors |
| GPS Source | Auto-detected | Shows which heading method is active |
Use the sliders to place Vehicle 2 ahead of you:
| Slider | What It Does |
|---|---|
| Offset (m) | How far ahead of you V2 is placed (along your current heading) |
| Heading | Which direction V2 is travelling. Set 180° opposite to you for a head-on scenario |
| Speed | V2's speed in m/s (0 = parked car) |
Head-on collision test:
- Walk or drive forward
- Set V2 offset to 80 m, heading to 180° (opposite to you), speed to 12 m/s
- Watch risk change: LOW → MEDIUM → HIGH as closing speed increases
Parked car test:
- Set V2 speed to 0 m/s, offset to 30 m
- Walk toward it
- Risk will reach HIGH when you are within 20 m
Near miss test:
- Set V2 heading to 90° (perpendicular to you)
- Risk stays LOW or MEDIUM — vehicles are not on a collision course
Both phones share live GPS with each other over your local network.
# Requires Node.js — download from https://nodejs.org
npm init -y
npm install wsCreate a file called relay.js in this folder with this content:
const { WebSocketServer } = require('ws');
const wss = new WebSocketServer({ port: 8765 });
const clients = new Set();
wss.on('connection', ws => {
clients.add(ws);
console.log(`Client connected. Total: ${clients.size}`);
ws.on('message', data => {
// Broadcast this phone's GPS to all other connected phones
for (const c of clients) {
if (c !== ws && c.readyState === 1) c.send(data);
}
});
ws.on('close', () => {
clients.delete(ws);
console.log(`Client disconnected. Total: ${clients.size}`);
});
});
console.log('Relay server running on ws://0.0.0.0:8765');node relay.js
# Output: Relay server running on ws://0.0.0.0:8765In real_sensor_test.html, find this line near the top of the <script>:
// TODO: set your laptop's local IP here before testing
const RELAY_URL = 'ws://YOUR_LAPTOP_IP:8765';Replace YOUR_LAPTOP_IP with your machine's IP address:
# Mac/Linux
ifconfig | grep "inet " | grep -v 127.0.0.1
# Windows
ipconfig | findstr "IPv4"Then serve the file and open it on both phones (same Wi-Fi network):
python3 -m http.server 8080
# Android: http://YOUR_LAPTOP_IP:8080/real_sensor_test.html
# iOS: use ngrok for HTTPS- Start the relay server on your laptop
- Open the page on both phones, tap Start GPS on each
- Walk apart ~100 m then walk toward each other
- Both phones will independently calculate collision risk using live GPS from both devices
For testing across different networks (e.g. two cars in the real world), use Firebase Realtime Database which gives ~200 ms update latency globally. Free tier supports up to 100 simultaneous connections.
- Go to https://console.firebase.google.com
- Click Add Project → name it (e.g.
collision-demo) → Continue - Disable Google Analytics → Create Project
- In the left sidebar: Build → Realtime Database → Create Database
- Choose a region, start in test mode (allows read/write for 30 days)
- In Firebase console: Project Settings → General → Your apps → Web app (</>)
- Register the app (any nickname)
- Copy the config object — it looks like this:
const firebaseConfig = {
apiKey: "AIza...",
authDomain: "your-project.firebaseapp.com",
databaseURL: "https://your-project-default-rtdb.firebaseio.com",
projectId: "your-project",
storageBucket: "your-project.appspot.com",
messagingSenderId: "123456789",
appId: "1:123456789:web:abc123"
};At the top of the <script> section, add:
<script type="module">
import { initializeApp } from "https://www.gstatic.com/firebasejs/10.12.0/firebase-app.js";
import { getDatabase, ref, set, onValue, remove }
from "https://www.gstatic.com/firebasejs/10.12.0/firebase-database.js";
const firebaseConfig = { /* paste your config here */ };
const app = initializeApp(firebaseConfig);
const db = getDatabase(app);
// Generate a unique ID for this device session
const myId = 'v_' + Math.random().toString(36).slice(2, 8);
// Called on every GPS update — write this device's position
function publishGPS(lat, lon, speed, heading) {
set(ref(db, `vehicles/${myId}`), { lat, lon, speed, heading, ts: Date.now() });
}
// Listen for all other vehicles and run collision check against each
onValue(ref(db, 'vehicles'), snapshot => {
const all = snapshot.val() || {};
const others = Object.entries(all)
.filter(([id]) => id !== myId)
.map(([, v]) => v);
for (const other of others) {
const result = assess(myVehicle, other);
// update UI with result
}
});
// Clean up this device's entry when the page closes
window.addEventListener('beforeunload', () => remove(ref(db, `vehicles/${myId}`)));
</script>- Open the page on each phone (any network, 4G/5G works)
- Each phone writes its GPS to Firebase every second
- All phones receive each other's GPS and run collision detection independently
| Sensor | Typical Accuracy | Impact on Detection |
|---|---|---|
| GPS position | ±5–15 m outdoors | Keep HIGH threshold at 20 m minimum |
| GPS speed | ±0.1 m/s when moving | Very reliable for TTC calculation |
| GPS heading | ±5° when moving fast | Less reliable below walking pace |
| Compass heading | ±10–20° | Sufficient for direction comparison |
| GPS update rate | 1 Hz (once per second) | Enough for vehicle-speed scenarios |
| Parameter | Simulation Default | Recommended for Real GPS |
|---|---|---|
| HIGH risk distance | 20 m | 30–50 m (compensates for GPS error) |
| MEDIUM risk distance | 60 m | 80–100 m |
| HIGH TTC | 5 s | 5 s (keep the same) |
| MEDIUM TTC | 12 s | 12 s (keep the same) |
| Problem | Cause | Fix |
|---|---|---|
| GPS permission denied | Page not served over HTTPS | Use ngrok or serve on localhost |
| Heading shows 0° always | Device not moving / no compass | Walk at normal pace; GPS heading activates above ~1 m/s |
| Speed always 0 | Standing still | Expected — TTC will show ∞ (diverging) |
| Very high GPS error (±50 m) | Indoors or urban canyon | Test outdoors, away from tall buildings |
| iOS compass not working | Permission not granted | Tap Start GPS — the requestPermission call handles it |
| ngrok URL not loading | Free ngrok session expired | Restart ngrok and copy the new URL |
| Two phones not syncing | Different Wi-Fi networks | Use Firebase approach (Part 4) instead |
Just want to see it work?
→ Open collision_detection.html in any browser
Testing with your own movement?
→ Open real_sensor_test.html via ngrok on your phone
Testing with a second person?
→ Same Wi-Fi: use relay.js + real_sensor_test.html
→ Different networks: use Firebase integration
Demo to stakeholders?
→ collision_detection.html (no setup, works anywhere)