2026-08-26 15:57:18 +02:00
# Requirements traceability matrix
Maps every section of `V2X_MicrOBU_Android_App_Requirements_v15.pdf` (37 pages, chapters 0– 13) to
its implementation and to the evidence that it works.
**Status as of 2026-08-25** , commit `cc35994` . Test counts refer to `app/src/test/` (41 tests,
0 failures); bench measurements refer to `05-obu-bench-test-2026-08-25.md` .
## How to read this
The project began against the **consider it CiT One OBU** and later added the **ESP32-C5** as a
second hardware path (requirements chapter 13). That transition is the single biggest source of
divergence in this table, and it is deliberate rather than drift: chapter 13 was written to describe
it. Where a requirement was authored assuming the CiT One, the ESP32-C5 path may satisfy it by a
different mechanism, satisfy it only partly, or make it inapplicable.
Status values:
| status | meaning |
|---|---|
| **Done** | implemented and exercised on both hardware paths |
| **Done (CiT One)** | implemented; applies only to the CiT One path by design |
| **Done (ESP32-C5)** | implemented; applies only to the ESP32-C5 path by design |
| **Partial** | implemented in part, with the remainder identified |
| **Backlog** | explicitly deferred in the requirements themselves |
| **Superseded** | the ESP32-C5 transition changed the answer; see the note |
| **Not started** | no implementation |
"Cited" means a source file names the section in a KDoc comment — 23 files do. Absence of a citation
is **not** absence of implementation; several well-covered areas were written before that convention
and are mapped here by inspection.
---
## 0. Project Context & Main Goal
| § | Title | Status | Implementation | Evidence |
|---|---|---|---|---|
| 0.1 | Technological Innovation Context | n/a | context, not a requirement | — |
| 0.2 | Bicycle Safety Use Case Foundation (C2C-CC) | **Done** | `DenmUseCase.kt` *(cited)* , `UseCaseType.kt` | use cases 1.1/1.2 below |
**Note.** 0.2 is the origin of the project's central architectural rule: the CAM-based use cases
never generate DENM. `DenmUseCase.kt` records this, and it survived the ESP32 transition unchanged.
## 1. Phase 01 — Data Collection
| § | Title | Status | Implementation | Evidence |
|---|---|---|---|---|
| 1.1 | Test Intersections & Use Cases | **Done** | `UseCaseDetectionEngine.kt` , `UseCaseType.kt` *(both cited)* | IMA-S observed firing on hardware, 2026-08-25 |
| 1.2 | C2C-CC Use Case Mapping & Roadmap | **Done** | `UseCaseType.kt` , `UseCaseDetectionConfig.kt` *(both cited)* | 5 use cases enumerated: IMA-B, IMA-S, RTW-B, LTW-B, SMVA/BCW-B |
## 2. Functional Requirements
| § | Title | Status | Implementation | Evidence |
|---|---|---|---|---|
| 2.1 | Screens & Features | **Done** | `ui/screens/` — Dashboard, Record, Trips, V2X, Settings | bench screenshots |
| 2.2 | User Interactions | **Done** | `UseCaseAlertPreferences.kt` *(cited)* , Settings screen | per-use-case toggles |
| 2.3 | Backend, Database & Login | **Partial** | `data/db/` (Room: sessions, trips, events, V2X messages) | no login/backend; local-only by design |
**Gap.** 2.3's backend and login have no implementation. Everything is on-device. Worth stating
explicitly in the thesis as a scope boundary rather than leaving it to be discovered.
## 3. Non-Functional Requirements
| § | Title | Status | Implementation | Evidence |
|---|---|---|---|---|
| 3.1 | Android Version & Target Devices | **Done** | `minSdk 29` , `targetSdk 36` | runs on Pixel 9 Pro |
| 3.2 | Performance & Offline | **Done** | offline by construction on the ESP32-C5 path | 210 MB PSS, 43 threads, no GC pressure attributable to the app |
**ESP32-C5 note.** 3.2's offline requirement is *more* satisfied after the transition: the ESP32-C5
path needs no MQTT broker and no network at all.
## 4. Technical Requirements
| § | Title | Status | Implementation | Evidence |
|---|---|---|---|---|
| 4.1 | Development Environment | **Done** | Gradle 8.10.2, AGP, Android Studio JBR | builds from CLI |
| 4.2 | Architecture | **Done** | `UseCaseDetectionEngine.kt` *(cited)* ; MVVM + Hilt + repositories | pure-domain classes unit-tested without Android |
| 4.3 | Key Libraries | **Done** | Compose, Room, Hilt, osmdroid, usb-serial-for-android, Paho MQTT | — |
| 4.4 | Security Requirements (future) | **Backlog** | — | see note |
**Security note (4.4).** ETSI TS 103 097 message signing is not implemented and is out of scope. The
firmware rejects secured packets (GN `NextHeader=2` ) rather than mis-parsing them; 75 such frames
were observed on the bench. The OBU under test runs `ItsGnSecurity = 0` , so this has not blocked
anything. **This is the most likely reviewer question and the answer should be pre-written.**
## 5. Design Requirements
| § | Title | Status | Implementation | Evidence |
|---|---|---|---|---|
| 5.1– 5.4 | Visual language, system bars, UX, wireframes | **Done** | Compose Material 3, edge-to-edge | screenshots |
| 5.5 | Alert Level Model (C2C-CC three-tier) | **Done** | `AlertLevel.kt` , `UseCaseDetectionConfig.kt` , `UseCaseDetectionEngine.kt` *(all cited)* | Info / Awareness / Warning; observed WARNING on hardware |
## 6. Sensor Data Streams (Phase 01)
| § | Title | Status | Implementation | Evidence |
|---|---|---|---|---|
| 6 | Sensor Data Streams | **Done** | `SensorRepository.kt` , `CamUseCaseRepository.kt` *(cited)* | GNSS, accel, gyro, magnetometer, barometer |
## 7. Recording Session & Data Export
| § | Title | Status | Implementation | Evidence |
|---|---|---|---|---|
| 7.1 | Recording Mode | **Done** | `TripRecordingService.kt` , `RecordingScreen.kt` | — |
| 7.2 | CSV Export Format | **Done** | `CsvExporter.kt` , `TripExporter.kt` | export includes V2X messages and RSSI |
## 8. Connectivity
| § | Title | Status | Implementation | Evidence |
|---|---|---|---|---|
| 8.1 | Connection Phase Roadmap | **Superseded** | `ObuHardware.kt` , `TransportType.kt` | chapter 13 replaced the roadmap |
| 8.2 | Transport Methods Detail | **Partial** | `UsbSerialTransport.kt` , `UsbNetworkDetector.kt` , `MqttRepository.kt` | USB-C both paths; **Bluetooth not implemented** (13.9 keeps it open) |
## 9. Phase 01 Key Design Principles
| § | Title | Status | Implementation | Evidence |
|---|---|---|---|---|
| 9 | Key Design Principles | **Done** | pure-domain `domain/` packages, no Android imports | `EventDetectorTest` , `UseCaseDetectionEngine` unit-testable |
## 10. Phase 02 — OBU Communication (CAM-based use cases)
| § | Title | Status | Implementation | Evidence |
|---|---|---|---|---|
| 10.1 | USB-C Wired Transport | **Done (CiT One)** | `UsbNetworkDetector.kt` (IP over USB tethering) | superseded on the ESP32-C5 path by USB serial |
| 10.2 | CAM Reception & Use Case Detection | **Done** | `Cam.kt` , `CamUseCaseRepository.kt` , `MqttViewModel.kt` , `MqttTopicViewerScreen.kt` *(all cited)* | 1244 CAMs decoded in 305 s, 0 failures |
| 10.2.1 | Detection Algorithm Detail | **Done** | `UseCaseDetectionEngine.kt` , `UseCaseDetectionConfig.kt` | IMA-S fired with TTC 4.8 s on hardware |
| 10.3 | Test and Verification Procedure | **Done** | `CamParser.kt` , `UseCaseDetectionConfig.kt` , `UseCaseDetectionEngine.kt` *(all cited)* | extended well beyond the original procedure — see chapter 14 below |
| 10.4 | New/Updated UI Elements | **Done** | `MqttTopicViewerScreen.kt` *(cited)* | alert panel, list/topics/map |
| 10.5 | Phase 02 Key Technical Decisions | **Done** | `DenmUseCase.kt` | DENM decoupled from sensor triggers |
**Transition note (10.1).** Phase 02 assumed IP-over-USB tethering to the CiT One. The ESP32-C5 path
uses a custom framed serial protocol over USB CDC instead. Both are "USB-C wired transport", but they
share no code. The requirement is satisfied twice, by different means.
## 11. Phase A — Trip Recording & Cyclist Event Detection
| § | Title | Status | Implementation | Evidence |
|---|---|---|---|---|
| 11.1 | Orientation-Independent Sensor Strategy | **Done** | `SensorRepository.kt` (magnitude-based) | — |
| 11.2 | Running Standard Deviation Event Detector | **Done** | `EventDetector.kt` , `RunningStats.kt` | **18 unit tests, 0 failures** |
| 11.3 | Trip Recording Architecture | **Done** | `TripRepository.kt` , `TripRecordingService.kt` *(cited)* | — |
2026-09-08 16:29:02 +02:00
| 11.4 | Data Model | **Partial — scope reduced** | `data/db/` Room entities *(cited)* | `detected_events` dropped in schema v5, see scope note |
2026-09-08 16:20:14 +02:00
| 11.5 | New UI Elements for Phase A | **Partial — scope reduced** | `TripHistoryScreen.kt` , `TripReviewScreen.kt` | event pins/counters removed by decision, see note |
2026-08-26 15:57:18 +02:00
| 11.6 | Phase A Success Criteria | **Partial** | — | needs a real ride; see Open Items |
**Correction note (11.2).** Four `EventDetectorTest` cases had been failing since the initial commit.
Investigation (2026-08-25) established the **detector was correct and the tests were wrong** : they
described stimuli the detector cannot physically see, because they ignored the settling time of the
rolling standard-deviation window. Tests corrected, assertions unchanged, detector untouched. This is
worth reporting — it is a finding about test design, not a defect.
2026-09-08 16:20:14 +02:00
**Scope note (11.5).** The event-detection UI — the live per-type counters on the recording screen,
the coloured event pins and detail sheet on the trip review map, and the event count on the trip
history card — was removed deliberately. A count of the rider's own braking events is not a goal of
this project. The detector itself still runs: it is the input to the CAM transmit-rate policy
(§ 13), which raises the beacon rate from 1 Hz to the elevated rate for five seconds after a
2026-09-08 16:29:02 +02:00
detected manoeuvre. That is now its only effect: the `detected_events` table was dropped in schema
v5 and the per-event rows removed from the trip CSV, so a detected manoeuvre is consumed and
discarded. `trips.eventCount` is kept as a single integer per ride, since dropping a SQLite column
means recreating the table.
2026-09-08 16:20:14 +02:00
**Defect note (11.2).** Two defects found while documenting the detector were fixed on 2026-09-07.
The nine threshold overrides in `TripRecordingService` 's constructor were promoted to
`DetectionConfig` 's defaults and the override deleted, so there is one configuration and
`EventDetectorTest` exercises the shipping thresholds rather than the superseded Phase A ones;
detector sensitivity is unchanged, and the synthetic stimuli were re-derived because several no
longer cleared the stricter real thresholds. `brakingHighConfidenceRate` was renamed
`brakingHighConfidencePeakDrop` : it was documented as a rate but has always been compared against
the peak cumulative speed drop. The name was corrected rather than the comparison, so detector
output is unchanged and the confidence assertions remain valid evidence.
2026-08-26 15:57:18 +02:00
## 12. Future Architecture & Open Design Questions
| § | Title | Status | Notes |
|---|---|---|---|
| 12.1 | Multi-Vehicle Handling & Notification Limits | **Partial** | engine tracks per-station history; no notification cap |
| 12.2 | Intersection Ambiguity: Traffic-Light State | **Partial — advanced** | **SPATEM now decoded** (`SpatemUperCodec.kt` ), see below |
| 12.3 | Shared-Road / Bike Lane Awareness Dataset | **Not started** | would need MAPEM lane geometry |
| 12.4 | Geo-Server for Crowdsourced Trajectory Data | **Not started** | related to the 2.3 backend gap |
| 12.5 | Geofencing Around High-Risk Intersections | **Not started** | — |
| 12.6 | Sensor Fusion Roadmap (Kalman Filter) | **Not started** | — |
| 12.7 | EventDetector Evolution | **Not started** | — |
**12.2 is the notable movement.** The requirements listed traffic-light state as future/backlog. It
is now partly delivered: SPATEM is received over the air and decoded to per-signal-group phase and
timing, validated against 79,042 real messages. What remains is the *association* problem — knowing
which signal group applies to the rider's lane — which needs MAPEM geometry (12.3). Worth presenting
as a backlog item advanced ahead of schedule, with the remaining half named precisely.
## 13. Phase 03 — ESP32-C5 Dual-OBU & Phone-Generated CAM
The transition chapter. Cited by **16 source files** , more than any other.
| § | Title | Status | Implementation | Evidence |
|---|---|---|---|---|
| 13.1 | ESP32-C5 as a Second OBU Option | **Done** | `obu-firmware/` , `ObuHardware.kt` | bench campaign T1– T9 |
| 13.2 | Transport: USB-C to ESP32 | **Done** | `SerialFrame.kt` , `serial_link.c` | 2868 frames / 305 s, 0 errors |
| 13.3 | Settings: OBU Hardware Selection | **Done** | `ObuHardwarePreferences.kt` , Settings | both paths selectable |
| 13.4 | DENM Trigger Retained for CiT One Only | **Done (CiT One)** | `MqttTopicViewerScreen.kt` gating | trigger hidden on the ESP32-C5 path |
| 13.5 | Phone-Generated CAM | **Done (ESP32-C5)** | `PhoneCamBuilder.kt` , `CamUperCodec.kt` , `CamTransmitLoop.kt` | **golden-byte test** ; 26 own CAMs verified off-air by an independent decoder |
| 13.6 | Adaptive CAM Transmission Rate | **Partial** | `CamTransmitConfig.kt` | fixed 1 Hz pinger; adaptive rate not implemented |
| 13.7 | UI Updates: Map View & Dashboard | **Done** | `V2xLiveMapView.kt` , `DashboardScreen.kt` | screenshots |
| 13.8 | Detection Engine: Unchanged for Reception | **Done** | `UseCaseDetectionEngine.kt` | engine is transport-agnostic; confirmed by inspection — zero SPATEM/MAPEM references |
| 13.9 | Bluetooth Transport (Open Discussion) | **Not started** | — | remains open, as the requirement says |
**13.8 is the load-bearing claim of the transition** and it holds: the same detection engine serves
both hardware paths, fed by `CamUseCaseRepository` from either MQTT or serial. That is what makes the
ESP32-C5 a drop-in second OBU rather than a fork of the application.
---
## Beyond the requirements
Work delivered that chapter 13 does not cover, because it postdates v15 of the document. For a
publication these are contributions rather than scope creep, and they need their own section.
| area | what | evidence |
|---|---|---|
| DENM over-the-air receive | GeoBroadcast unwrapping, `DenmUperCodec` | 1885 DENMs cross-checked, 0 mismatches |
| SPATEM receive | `SpatemUperCodec` , live signal phase UI | 79,042 messages cross-checked, 0 mismatches |
| RSU CAM support | `rsuContainerHighFrequency` decoding | 611 RSU CAMs decoded on the bench |
| Verification methodology | independent ETSI oracle, golden bytes, real captures | three encoding bugs found that self-consistent tests structurally cannot catch |
## Open items
Ranked by what a reviewer is most likely to probe.
1. **11.6 Phase A success criteria** — needs a real ride. The bench proves reception; it cannot
prove the use case behaves correctly with two genuinely moving stations. This is the main
remaining evidence gap for the central claim.
2. **4.4 Security** — no message signing. Pre-write the answer.
3. **2.3 Backend & login** — not implemented; state as a scope boundary.
4. **13.6 Adaptive CAM rate** — fixed 1 Hz.
5. **8.2 / 13.9 Bluetooth** — not implemented; the requirements leave it open.
6. **12.2 remainder** — signal-group-to-lane association needs MAPEM.
## Known limitations carried deliberately
Documented decisions, not oversights. Each has its reasoning recorded in the commit history and in
`05-obu-bench-test-2026-08-25.md` .
- **512-byte serial payload cap.** ~70% of *road* RSU SPATEMs would be dropped. Accepted: the
intersection use case is CAM-driven and needs none of it, and raising the cap would put a
measured, zero-failure chain at risk for an add-on. CAM 26– 211 B and DENM 402 B both fit.
- **No MAPEM decoder.** Nothing on air transmits it; it exists only in recorded drive data.
- **Secured messages rejected**, not mis-parsed.
- **No auto-reconnect** after USB re-enumeration; requires a manual Connect.
- **Station IDs rotate** (observed twice within one session), so they cannot identify a physical
unit over time.