Project Overview
This is a professional-grade Android application engineered for civil engineers, road survey teams, highway contractors, and infrastructure inspection agencies who need to capture geotagged video documentation of road alignments while simultaneously recording distance-along-alignment ("chainage"), location telemetry, and road-roughness metrics. The product solves a problem that has historically required two or three separate pieces of equipment — a GPS odometer, a professional roughness profilometer, and a dashcam — and collapses them into a single handheld device any field engineer can operate from the passenger seat of a standard vehicle.
From a business perspective, the application is aimed at reducing the cost and logistical complexity of road-condition surveys for public-works departments, contractors executing road-inspection contracts, and quality-assurance consultants. Traditional class-1 profilometers cost tens of thousands of dollars, require specialist operators, and produce outputs decoupled from the visual condition of the road. This platform allows a technician to drive a stretch of road once and return with a single overlaid video showing the exact chainage marker, GPS coordinates, timestamp, vehicle speed, compass heading, mounting tilt, and running roughness score burnt into every frame — along with structured log files suitable for auditing, reporting, and archival. The resulting artefact is self-describing evidence: a reviewer can scrub the video to any point on the alignment and see, at that instant, where the vehicle was, how fast it was moving, how the phone was oriented, and how rough the road surface measured beneath the tyres.
Key Features & Functionality
Geotagged Video Recording with Live On-Screen Overlay. Every recorded video carries a burnt-in stamp that updates in real time as the vehicle moves. The stamp is fully configurable — operators choose which fields appear (chainage value, GPS coordinates, speed, accuracy, date, time, description line, company branding), which corner they occupy, how large they render, and which text colour they use. The overlay is rendered directly into the encoded video stream, so the resulting file is evidentiary-grade and tamper-resistant.
Two Chainage Calculation Modes. Operators can run a simple cumulative-distance mode for greenfield surveys where no centreline is available, or a polyline-snap mode in which the app loads a reference alignment (exported from GIS tooling) and reports chainage projected onto that alignment. Both modes honour freeze-below-1-km/h behaviour to eliminate GPS drift artefacts at standstill.
International Roughness Index (IRI) Measurement. The application ingests inertial sensor data at high frequency, passes it through a calibrated processing pipeline based on the standard Golden-Car quarter-car reference, and emits segment-wise roughness scores at operator-chosen intervals (20 m, 100 m, or 1 000 m). A pre-recording survey wizard captures the contextual metadata — vehicle class, mounting position, phone orientation, tilt handling — so each roughness log is interpretable and comparable.
Live Compass, Camera-Tilt Telemetry, and Ultra-Wide Lens Support. A real-time compass needle overlays the preview and optionally burns into the video, the current camera tilt is reported numerically for mounting diagnostics, and on multi-lens devices the operator can swap between the main lens and an ultra-wide lens with a single tap.
Structured Data Export. Alongside the overlaid video, each recording session writes CSV and JSON logs of the raw location stream, the chainage series, and per-segment IRI results — making the output immediately consumable by downstream analysis pipelines, GIS platforms, and reporting tools.
Technology Stack
The application is built natively for Android in Kotlin, targeting API 34 and supporting devices down to API 26 (Android 8.0). The codebase follows an MVVM pattern organised around Android Jetpack components with ViewBinding for layout access.
- Language & build: Kotlin 1.9 on the Android Gradle Plugin 8.3 toolchain, JDK 11 target.
- UI layer: XML layouts with Material Design components, AndroidX AppCompat, ConstraintLayout, and BottomSheetDialogFragment-based settings flows.
- Dependency injection: Dagger Hilt.
- Camera & video: AndroidX CameraX including the Effects API for GPU-accelerated overlay composition, plus a community-maintained FFmpegKit distribution for post-processing workflows.
- Location & sensors: Google Play Services Location (fused provider) combined with the raw Android Sensor framework for accelerometer, gyroscope, and rotation-vector telemetry.
- Mathematics & geodesy: GeographicLib for WGS-84 geodesic calculations and Apache Commons Math for matrix operations used by the filter stack.
- Persistence & concurrency: DataStore Preferences for configuration, Kotlinx Coroutines and Flow for all asynchronous work, Kotlinx Serialization for structured log output, and Gson for interchange with GIS tooling.
- Testing: JUnit 4 and MockK for unit tests, Espresso for instrumented tests.
Technical Complexity & Challenges
Several aspects of the project pushed well beyond what a standard Android application demands.
Real-time GPU overlay inside the camera pipeline. Rather than overlaying metadata as a post-processing step — which would double storage requirements and break single-take workflows — the product composites the overlay directly into the CameraX video-capture pipeline using the Effects API. This requires running OpenGL rendering on the camera graphics thread, which is intolerant of allocations, garbage-collection pauses, or blocking work. The rendering layer was engineered to avoid per-frame object creation entirely, pre-computing paints, paths, and shaders once and mutating only the values that change between frames. A parallel preview renderer, driven from a single shared snapshot of the current frame data, keeps the on-screen preview and the burnt-in video overlay visually identical.
Standards-grade roughness computation on a mobile device. Producing a meaningful IRI number from an inertial sensor in a phone required building a multi-stage signal-processing pipeline: a gravity-compensated vertical-acceleration extractor, a band-pass filter tuned to the spatial frequencies relevant to vehicle response, a road-profile integrator, a standard quarter-car dynamic model, and a segment accumulator that emits values synchronised to chainage rather than to clock time. Each stage had to run deterministically at the sensor rate without drifting, while remaining robust to speed variation, operator-induced tilt, and GPS outages. A quality-flag system marks each emitted segment with warnings for speed variation, excessive mounting tilt, or low sample counts, so downstream consumers can filter on confidence.
A defensible GPS filter chain. Consumer-grade phone GPS is noisy, biased, and prone to jumps, particularly near buildings, bridges, and tree cover. A layered filter chain — accuracy gating, jump rejection, and a Kalman estimator — was assembled to produce a smooth, confidence-weighted position stream the chainage calculators can trust. The polyline chainage mode additionally projects filtered fixes onto a supplied reference alignment using geodesic mathematics on the WGS-84 ellipsoid.
Sensor and thread lifecycle discipline. Rotation-vector, accelerometer, and gyroscope listeners each carry latency, battery, and threading cost. The app routes all such work through a small number of long-lived worker threads that are allocated once per process and reused across recording sessions, with care to avoid leaks across configuration changes. The foreground location service is configured to remain resilient to process death and battery optimisation while respecting the stricter foreground-service rules introduced in modern Android.
Design & User Experience
The interface is built for a field operator holding a phone in a car mount, often in bright sunlight, frequently with gloves on, and usually with only a few seconds between pressing the record button and losing the opening stretch of a survey. The UI therefore presents a large, unambiguous record control, a high-contrast status indicator for GPS and sensor readiness, and an always-visible chainage read-out that mirrors exactly what will be burnt into the video.
Advanced configuration is routed through a set of bottom-sheet dialogs that keep the main screen clean while still exposing the depth of control power users need — granular toggles for every overlay field, colour chips for text and background, position and text-size controls, unit preferences, and full roughness-survey metadata. Settings use DataStore so they persist across sessions and are applied atomically.
Accessibility considerations include high text contrast, large tap targets on the primary controls, and a deliberate choice to use black text with a white shadow on the overlay so the stamp remains legible against both dark asphalt and bright concrete in the captured video.
Scale & Scope
The project comprises over fifty Kotlin source files organised into roughly a dozen feature packages — camera, recording, overlay, chainage, geodesic, filters, location, sensor, IRI processing, logging, settings, and UI — with a corresponding resource library of more than a hundred and seventy layout, drawable, theme, string, and configuration files. Features are deliberately decomposed into small, single-responsibility units: the roughness pipeline alone is split across seven collaborating components, the location layer maintains a clean separation between the provider, the filter chain, and the calculators, and the recording stack isolates the camera controller from the effect, the data provider, and the encoder.
Noteworthy integrations include the Google Play Services fused location provider, the Android Sensor framework, the CameraX Effects pipeline, an FFmpeg-based post-processing toolchain, a WGS-84 geodesic library, a matrix-mathematics library, and the system foreground-service and notification APIs. The build supports both debug and release configurations and is compatible with modern 16 KB page-size devices.
Business Impact & Use Case
The primary users are road and highway engineering organisations — government public-works departments, national and state highway authorities, toll-road concessionaires, and the consulting and contracting firms that serve them. In jurisdictions where chainage is the canonical reference system for road assets (much of South Asia, the Middle East, and parts of Africa and Southeast Asia), the term is embedded in tender documents, defect liability reports, and as-built drawings, making a chainage-aware video tool immediately fit-for-purpose.
Typical workflows the application enables include routine condition surveys in which an inspector drives a stretch of road and produces, in a single pass, a video record plus a machine-readable roughness log; defect-liability inspections during the maintenance period of a newly constructed road, where the chainage-stamped video becomes an indisputable record of what was observed, where, and when; pre-bid asset audits for concessionaires evaluating an existing road before taking over operations; and pothole and distress documentation, where the burnt-in chainage and GPS coordinates let a remote office issue precise work orders without re-visiting the site.
By collapsing specialist hardware into a device the field team already owns, the product meaningfully lowers the cost of entry into systematic road-condition monitoring for smaller agencies and contractors who would otherwise be priced out of it.
Development Approach
The project follows a disciplined, modular architecture with clear separation between data sources (location provider, sensor collector, camera), processing layers (filter chain, chainage calculators, roughness pipeline), presentation state (ViewModel and overlay providers), and rendering surfaces (preview overlay view, video-stream effect). Dependency injection via Hilt enforces these seams: no component reaches across boundaries to instantiate its collaborators, which keeps the system testable and reasoned about piece by piece.
Configuration state is centralised in a strongly-typed settings layer backed by DataStore so preferences are reactive, typed, and resilient across process restarts. Logging is structured and written in both human-readable and machine-readable formats, making the output directly useful in both field debugging and downstream analytics.
Performance discipline is a first-class concern — the rendering layer is held to strict per-frame budgets and zero-allocation rules, sensor streams are throttled to the minimum rate required by the consumer, and long-lived threads are created once and reused rather than spun up per session. Error paths around camera initialisation, permission denial, GPS unavailability, and storage exhaustion are handled explicitly with user-visible recovery affordances rather than silent failures.
The test scaffolding covers both unit-level mathematics (filters, calculators) through MockK-based tests and higher-level UI flows through Espresso, giving the team confidence to evolve individual components without regressing the integrated behaviour that the end user ultimately depends on.
Tech stack
- Kotlin 1.9
- Android Jetpack + ViewBinding
- Dagger Hilt
- AndroidX CameraX (Effects API)
- FFmpegKit
- Fused Location + Sensor Framework
- GeographicLib (WGS-84)
- Apache Commons Math
- Kotlinx Coroutines & Flow
- JUnit + MockK + Espresso