velocity.report
A privacy-focused traffic logging tool for neighbourhood change-makers.
Measure vehicle speeds, make streets safer.
░░░░
▒▓███▓▓▓▓▒
▒▓▒▒
░▓▓▓▓▓▓▓▓▓▓▓▓░ ░▓▒▒
▒▓▓▓▓▓██████▓▓░ ▒▓██▓▒
▒▒▓▒▓▓░ ▒▓▒░
░▓▓░ ▓▒▒
░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██████▓░
▓▓█▓▒▒▒▒▒▒░░░░ ░▓▓▒
░▓▓▒▓▓░ ░▒▓▓▓▓░
░░▒▒▒▒░ ░▓▒░ ▒▓▒ ▒▓▓▒ ▓▓▒ ░▒▒▓▓▒▒░
▒▓▓▓██▓▓▓██▓▓▓▓▓▒ ░▓▓░ ▒▓▓▒ ▒██▓▓█▓▓▓▓▓▓▒▓▓▒░
░▓▓▓▓▓▒░ ░ ▒▒██▓▒▒ ▒▓▒░ ░▓▓▒ ▓▓█▓█▓ ░░ ▒▒▓▒▓▒
▒▓▓▓▓░ ░░ ░▓▓░▒▓▓▒ ▒▓▒ ▓▓▓ ░▓▓▓░░▓▓░ ░░ ▒█▓▒▒
░▒█▒▓░▒ ░░ ░▓▒░ ░▓▓▒░ ░▓▓ ░████▓ ▒█▓░ ▒▓█▒ ░▓▓░ ░░ ▒░░▒█▓▒
▒▓▒▓ ▒░ ░░ ▒▓▓ ░▓▓▓░ ░▓▒ ░▓▒ ░▓▓▒ ▒▓█▒░▒ ▒█▒ ░ ▒░ ░▒▓▓▒
░▓█▓ ░▒░ ░░▒▓▒ ░▓▓▒░▒▓████▒ ▒▓▓░ ▒▓▓▒ ▒▒ ▓▓▒ ░ ░▒ ░▓▓▒░
▒▓▓▒ ░▒▒▓█▓▓▓███▓▓▓▓████▓█▓▓▒▒▓▓▓▒ ▒█▓░ ░▓▓▓▒▒▒▒ ▒▓▒▒
▒▓▓▒░░▒▒▒▓▒▒▓▓██▓▒▒░▒░░░ ▒▓▒▒▓▓▓▓▓█▓▓▓░ ▒█▓░ ░░░▒█▓▓▒▒▒░░░░░░░▒█▓░
▒▓▓▒ ░▒▒▓▒░ ▓▓▓░▒▓▓▓▓▓▒▒▓░ ▒▓▓▒▒░░░░░ ░▒▓░▒░ ▓▓▓░
░▓█▓░ ░▒░ ░▒ ▒░ ▒▓▓▒ ▒███▓▓▓░ ░▓▓▒ ░░ ░ ░▒░ ░▓▓▓░
▒▓▓▓░ ▒░ ▒ ▒░ ░▓▓▓░ ▒▓ ▓▓▓░ ▒ ░░ ░▒░ ░▓█▓░
▒▓▓▓▒░ ░▒ ░▒ ▒▓▓▒ ░▓▒ ░▒▓▓░ ░░ ░░ ▒▒▓▓▓░
▒▓▓▓▒░ ▒ ░▓▓▓▒ ▓█▓▓█░ ▒▓▓▓▒░ ▒░ ░▓█▓▓░
░▒▓██▓▒▒ ▒ ░▒▓▓█▓▒░ ░▓▓█▓▓░ ░░ ░▒▓█▓▓▓░
░░░▒▒▓▓████▓██▓▓░ ░░ ▒▓▓▓▓██▓▓▓████▓▒░
░░░░░░░░░░░░▒▒░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░ ░░░▒▒▒▒▓▒▒░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░ ░░░░ ░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░
░░░ ░░░░░░ ░░░░ ░░░░░░░░░░░░ ░░░░░ ░░░░░░ ░░░░░░ ░░░░░░░░░░░ ░░░░
░░░ ░░░░ ░░░░ ░░░░ ░░░ ░░░░ ░░░░░ ░░░░░ ░░░░░
Overview
velocity.report is a complete citizen radar system for neighbourhood traffic monitoring. The system consists of four main components:
- Go Server - High-performance data collection and API server
- Python PDF Generator - Professional PDF report generation with LaTeX
- Web Frontend - Real-time data visualisation (Svelte)
- macOS Visualiser - Native 3D visualisation for LiDAR tracking (M1+ Macs)
The system collects vehicle speed data from radar/LIDAR sensors, stores it in SQLite, and provides multiple ways to visualise and report on the data—all while maintaining complete privacy (no license plate recognition, no video recording).
Privacy & Ethics
This project is designed with privacy as a core principle:
- ✅ No license plate recognition
- ✅ No video recording
- ✅ No personally identifiable information
The goal is to empower communities to make data-driven decisions about street safety without compromising individual privacy.
Quick Start
For Go Server Development
git clone git@github.com:banshee-data/velocity.report.git
cd velocity.report
make build-radar-local
./velocity-report-local --disable-radar
If an existing SQLite database is available, place it in ./sensor_data.db (the default location for development). For production deployments, use the --db-path flag to specify a different location (see Deployment section).
For PDF Report Generation
See tools/pdf-generator/README.md for detailed instructions.
Quick version:
cd tools/pdf-generator
make install-python # One-time setup
make pdf-config # Create config template
make pdf-report CONFIG=config.json
For Web Frontend Development
See web/README.md for detailed instructions.
For macOS Visualiser (LiDAR 3D Tracking)
The macOS visualiser provides real-time 3D visualisation of LiDAR point clouds, object tracking, and debug overlays. Requires macOS 14+ and Apple Silicon (M1/M2/M3) or Intel Mac with Metal support.
See tools/visualiser-macos/README.md for detailed instructions.
Quick version:
# Build the visualiser
make build-mac
# Start synthetic data server for testing
go run ./cmd/tools/visualiser-server -rate 10 -points 5000
# Launch the visualiser
open tools/visualiser-macos/build/Build/Products/Release/VelocityVisualiser.app
# Or replay recorded data
go run ./cmd/tools/visualiser-server -mode replay -log /path/to/recording.vrlog
M1 Features (Milestone 1):
- ✅ Recorder/Replayer with deterministic playback
- ✅ Pause/Play/Seek/Rate control via gRPC
- ✅ Frame-by-frame navigation
- ✅ Timeline scrubbing
- ✅ 3D camera controls (orbit, pan, zoom)
- ✅ Mouse/trackpad gesture support
Project Structure
velocity.report/
├── cmd/ # Go CLI applications
│ ├── radar/ # Radar/LiDAR sensor integration
│ ├── deploy/ # Deployment management tool
│ ├── sweep/ # Parameter sweep utilities
│ ├── tools/ # Go utility tools
│ │ ├── visualiser-server/ # Synthetic data generator and replay server
│ │ ├── gen-vrlog/ # Generate sample .vrlog recordings
│ │ ├── pcap-analyse/ # PCAP packet analysis
│ │ └── ... # Other utilities
│ └── transit-backfill/ # Transit data backfill tool
├── internal/ # Go server internals (private packages)
│ ├── api/ # HTTP API endpoints
│ ├── db/ # SQLite database layer + migrations
│ ├── radar/ # Radar sensor logic
│ ├── lidar/ # LiDAR sensor logic + tracking
│ │ └── visualiser/ # gRPC streaming for 3D visualisation
│ │ └── recorder/ # Record/replay .vrlog files
│ ├── monitoring/ # System monitoring
│ ├── security/ # Path validation and security
│ ├── serialmux/ # Serial port multiplexing
│ ├── units/ # Unit conversion utilities
│ └── version/ # Version information
├── web/ # Svelte web frontend
│ ├── src/ # Frontend source code
│ └── static/ # Static assets
├── tools/ # Python tooling and native apps
│ ├── pdf-generator/ # PDF report generation (Python)
│ │ ├── pdf_generator/ # Python package
│ │ │ ├── cli/ # CLI tools
│ │ │ ├── core/ # Core modules
│ │ │ └── tests/ # Test suite
│ │ └── output/ # Generated PDFs
│ └── visualiser-macos/ # macOS LiDAR visualiser (Swift/Metal)
│ ├── VelocityVisualiser/ # SwiftUI app
│ │ ├── App/ # Application entry
│ │ ├── gRPC/ # gRPC client
│ │ ├── Rendering/ # Metal renderer
│ │ └── UI/ # SwiftUI views
│ └── VelocityVisualiserTests/ # XCTest suite
├── data/ # Sample data and alignment utilities
├── docs/ # Internal project documentation
├── public_html/ # Public documentation site (Eleventy)
├── scripts/ # Development shell scripts
└── static/ # Static server assets
Architecture
Data Flow
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│ Sensors │────►│ Go Server │◄───►│ SQLite Database │
│ (Radar / LIDAR) │ │ (API/Processing) │ │ (Time-series) │
└───────────────────┘ └───────────────────┘ └───────────────────┘
│
│
┌─────────────────┴──────────────────┐
│ │
▼ ▼
┌─────────────────────────────┐ ┌─────────────────────────────┐
│ Web Frontend │ │ Python PDF Generator │
│ (Real-time via Svelte) │ │ (Offline Reports via LaTeX) │
└─────────────────────────────┘ └─────────────────────────────┘
Components
1. Go Server (/cmd/, /internal/)
- Collects data from radar/LIDAR sensors
- Stores time-series data in SQLite
- Provides HTTP API for data access
- Handles background processing tasks
- Runs as systemd service on Raspberry Pi
2. Python PDF Generator (/tools/pdf-generator/)
- Generates professional PDF reports using LaTeX
- Creates charts and visualisations with matplotlib
- Processes statistical summaries
- Highly configurable via JSON
- Comprehensive test suite
3. Web Frontend (/web/)
- Real-time data visualisation
- Interactive charts and graphs
- Built with Svelte and TypeScript
- Responsive design
See ARCHITECTURE.md for detailed architecture documentation.
Development
Prerequisites
For Go Development:
For Python PDF Generation:
For Web Frontend:
Go Server Development
Build the development server:
make build-radar-local
./velocity-report-local --disable-radar
Run tests:
make test
Build for production (Raspberry Pi):
make build-radar-linux
# or manually:
GOOS=linux GOARCH=arm64 go build -o velocity-report-linux-arm64 ./cmd/radar
Python PDF Generator Development
The repository uses a single shared Python virtual environment for all Python tools (PDF generator, data visualisation, analysis scripts).
Setup:
make install-python # Creates .venv and installs all dependencies
Activate manually (optional):
source .venv/bin/activate
What's installed:
- PDF generation: PyLaTeX
- Data analysis: pandas, numpy
- Visualisation: matplotlib, seaborn
- Testing: pytest, pytest-cov
- Formatting: black, ruff
Run PDF Generator:
make pdf-test # Run test suite
make pdf-demo # Run interactive demo
make pdf-config # Create config template
make pdf-report CONFIG=config.json # Generate PDF report
Option 1: Format on demand (recommended for new contributors)
make format # Format all code before commit
make lint # Verify formatting (what CI checks)
Option 2: Editor integration
- VS Code: Install Prettier, ESLint, Go extensions
- Format-on-save handles most cases
Option 3: Pre-commit hooks (recommended for regular contributors)
pip install pre-commit
pre-commit install
Hooks auto-format code on every commit — no manual make format needed.
What runs on commit (if hooks enabled):
- File hygiene (trailing whitespace, large files, etc.)
- Go formatting (gofmt)
- Python formatting (ruff + black) for PDF generator code
- Web formatting (prettier)
Note: CI lint jobs are advisory (non-blocking), so PRs can merge even without perfect formatting. A weekly automated workflow cleans up any missed formatting issues. See .github/workflows/lint-autofix.yml for details.
Web Frontend Development
cd web
pnpm install
pnpm dev
See web/README.md for details.
Deployment
Go Server (Raspberry Pi)
The Go server runs as a systemd service on Raspberry Pi. Use the new velocity-deploy tool for comprehensive deployment management.
Quick Start - Deploy to Raspberry Pi:
# Build the binary and deployment tool
make build-radar-linux
make build-deploy
# Deploy to remote Pi
./velocity-deploy install \
--target pi@192.168.1.100 \
--ssh-key ~/.ssh/id_rsa \
--binary ./velocity-report-linux-arm64
Or use Make shortcuts for local deployment:
make build-radar-linux
make deploy-install
The deployment will:
- Install the binary to
/usr/local/bin/velocity-report
- Create a dedicated service user and working directory
- Install and enable the systemd service
- Optionally migrate existing database
Upgrade to new version:
make build-radar-linux
./velocity-deploy upgrade --target pi@192.168.1.100 --binary ./velocity-report-linux-arm64
Monitor service health:
# Comprehensive health check
./velocity-deploy health --target pi@192.168.1.100
# Check status
./velocity-deploy status --target pi@192.168.1.100
# View logs
sudo journalctl -u velocity-report.service -f
See also:
Legacy deployment:
The previous scripts/setup-radar-host.sh script is still available but the new velocity-deploy tool is recommended for all deployments.
Python PDF Generator
The PDF generator is deployed as a Python package via PYTHONPATH:
cd tools/pdf-generator
make install-python
# PDF generator is now ready at tools/pdf-generator/pdf_generator/
No installation required - use PYTHONPATH method as documented in tools/pdf-generator/README.md.
Documentation
Testing
Go Tests
make test
Performance regression testing:
make test-perf NAME=kirk0 # Run performance test against baseline
This compares current performance against saved baselines. If no baseline exists, it creates one.
Python Tests (PDF Generator)
cd tools/pdf-generator
make pdf-test
# or with coverage:
make test-python-cov
Make Targets
The project uses a consistent naming scheme for all make targets: <action>-<subsystem>[-<variant>]
action should be an imperative verb (for example: build, test, check, sync).
subsystem should name the functional surface (for example: go, web, config).
variant is optional and narrows behaviour (for example: strict, cov, linux).
For config consistency workflows, canonical targets are verb-first (check-*, sync-*). Legacy aliases are kept for compatibility.
Core Subsystem Targets
| Action |
Go |
Python |
Web |
Docs |
macOS |
| install |
- |
install-python |
install-web |
install-docs |
- |
| build |
build-radar-* |
- |
build-web |
build-docs |
build-mac |
| dev |
dev-go |
- |
dev-web |
dev-docs |
dev-mac |
| dev (variant) |
dev-go-lidar
dev-go-lidar-both
dev-go-kill-server |
- |
- |
- |
- |
| run |
- |
- |
- |
- |
run-mac |
| test |
test-go |
test-python |
test-web |
- |
test-mac |
| test (variant) |
test-go-cov
test-go-coverage-summary |
test-python-cov |
test-web-cov |
- |
- |
| format |
format-go |
format-python |
format-web |
format-docs |
format-mac |
| lint |
lint-go |
lint-python |
lint-web |
- |
- |
| clean |
- |
clean-python |
- |
- |
clean-mac |
Cross-cutting formatting targets:
format-sql - Format SQL files (migrations and schema)
Aggregate Targets
test - Run all tests (Go + Python + Web + macOS)
format - Format all code (Go + Python + Web + macOS + SQL + Markdown)
lint - Lint all code (Go + Python + Web), fails if formatting needed
coverage - Generate coverage reports for all components
Build Targets (Go cross-compilation)
build-radar-linux - Build for Linux ARM64 (no pcap)
build-radar-linux-pcap - Build for Linux ARM64 with pcap
build-radar-mac - Build for macOS ARM64 with pcap
build-radar-mac-intel - Build for macOS AMD64 with pcap
build-radar-local - Build for local development with pcap
build-tools - Build sweep tool
build-deploy - Build velocity-deploy deployment manager
build-deploy-linux - Build velocity-deploy for Linux ARM64
build-web - Build web frontend (SvelteKit)
build-docs - Build documentation site (Eleventy)
Testing Targets
test - Run all tests (Go + Python + Web + macOS)
test-go - Run Go unit tests
test-go-cov - Run Go tests with coverage
test-go-coverage-summary - Show coverage summary for cmd/ and internal/
test-python - Run Python PDF generator tests
test-python-cov - Run Python tests with coverage
test-web - Run web tests (Jest)
test-web-cov - Run web tests with coverage
test-mac - Run macOS visualiser tests (XCTest)
test-perf - Run performance regression tests (NAME=kirk0)
coverage - Generate coverage reports for all components
macOS Visualiser Targets
build-mac - Build macOS LiDAR visualiser (Xcode)
clean-mac - Clean macOS visualiser build artifacts
run-mac - Run macOS visualiser (requires build-mac)
dev-mac - Kill, build, and run macOS visualiser
test-mac - Run macOS visualiser tests (XCTest)
format-mac - Format macOS Swift code (swift-format)
Protobuf Code Generation
proto-gen - Generate protobuf stubs for all languages
proto-gen-go - Generate Go protobuf stubs
proto-gen-swift - Generate Swift protobuf stubs (macOS visualiser)
Deployment Targets
setup-radar - Install server on this host (requires sudo, legacy)
deploy-install - Install using velocity-deploy (local)
deploy-upgrade - Upgrade using velocity-deploy (local)
deploy-status - Check service status using velocity-deploy
deploy-health - Run health check using velocity-deploy
deploy-install-latex - Install LaTeX on remote target (for PDF generation)
deploy-update-deps - Update source, LaTeX, and Python deps on remote target
format - Format all code (Go + Python + Web + macOS + SQL + Markdown)
format-go - Format Go code (gofmt)
format-python - Format Python code (black + ruff)
format-web - Format web code (prettier)
format-mac - Format macOS Swift code (swift-format)
format-docs - Format Markdown files (prettier)
format-sql - Format SQL files (sql-formatter)
Linting Targets
lint - Lint all code (Go + Python + Web), fails if formatting needed
lint-go - Check Go formatting
lint-python - Check Python formatting
lint-web - Check web formatting
Config Schema Consistency Targets
check-config-order - Validate canonical tuning key order across config and docs surfaces
sync-config-order - Rewrite config/docs targets to canonical tuning key order
check-config-maths - Validate README.maths keys against docs JSON, tuning*.json, and Go schema sources
check-config-maths-strict - Strict parity mode; also requires full webserver POST schema parity
Current status: optional in CI until webserver schema parity backlog is complete.
- Compatibility aliases:
config-order-check, config-order-sync, readme-maths-check, readme-maths-check-strict
Database Migration Targets
migrate-up - Apply all pending migrations
migrate-down - Rollback one migration
migrate-status - Show current migration status
migrate-detect - Detect schema version (for legacy databases)
migrate-version - Migrate to specific version (VERSION=N)
migrate-force - Force version (recovery, VERSION=N)
migrate-baseline - Set baseline version (VERSION=N)
schema-sync - Regenerate schema.sql from latest migrations
PDF Generator Targets
pdf-report - Generate PDF from config file
pdf-config - Create example configuration
pdf-demo - Run configuration demo
pdf-test - Run PDF tests (alias for test-python)
pdf - Convenience alias for pdf-report
Utility Targets
set-version - Update version across codebase (VER=0.4.0 TARGETS='--all')
log-go-tail - Tail most recent Go server log
log-go-cat - Cat most recent Go server log
log-go-tail-all - Tail most recent Go server log plus debug log
git-fs - Show the git files that differ from main
Data Visualisation Targets
plot-noise-sweep - Generate noise sweep line plot (FILE=data.csv)
plot-multisweep - Generate multi-parameter grid (FILE=data.csv)
plot-noise-buckets - Generate per-noise bar charts (FILE=data.csv)
stats-live - Capture live LiDAR snapshots (INTERVAL=10 DURATION=60)
stats-pcap - Capture PCAP replay snapshots (PCAP=file.pcap INTERVAL=5)
API Shortcut Targets (LiDAR HTTP API)
Grid endpoints:
api-grid-status - Get grid status
api-grid-reset - Reset background grid
api-grid-heatmap - Get grid heatmap
Snapshot endpoints:
api-snapshot - Get current snapshot
api-snapshots - List all snapshots
Acceptance endpoints:
api-acceptance - Get acceptance metrics
api-acceptance-reset - Reset acceptance counters
Parameter endpoints:
api-params - Get algorithm parameters
api-params-set - Set parameters (PARAMS='{}')
Persistence and export endpoints:
api-persist - Trigger snapshot persistence
api-export-snapshot - Export specific snapshot
api-export-next-frame - Export next LiDAR frame
Status & data source endpoints:
api-status - Get server status
api-start-pcap - Start PCAP replay (PCAP=file.pcap)
api-stop-pcap - Stop PCAP replay
api-switch-data-source - Switch live/pcap (SOURCE=live|pcap)
Run make help or make to see all available targets with descriptions.
Contributing
We welcome contributions! Please see CONTRIBUTING.md for:
- Development workflow (Go + Python + Web)
- Testing requirements
- Code style guidelines
- Pull request process
License
Apache License 2.0 - See LICENSE for details.

Join our Discord community to discuss the project, get help, and contribute to making streets safer.