All Projects
·3 min read

AIDrivingHelper 2: Driving Coaching with Geographic Context

Evolution of AIDrivingHelper that enriches driving events with real-world geographic context, including nearby schools, hospitals, road names, and traffic infrastructure, for location-aware safety coaching on Android.

AndroidKotlinRAGGemmaGoogle AI EdgeNominatimOverpass APIGeo-EnrichmentOn-Device AIRetrofitVoice

What this is

Same context as AIDrivingHelper: this is an add-on coaching layer for apps that already record trip data. Apps like DriveKit, Zendrive, or Cambridge Mobile Telematics collect the raw events. This adds on-device AI coaching with one extra layer: geographic awareness.

Before a driving event is embedded and stored, it is enriched with the real-world context around it. What road was the driver on? Was there a school or hospital nearby? What traffic features were in the area? This context gets baked into the vector store so the coaching responses become location-aware.

What changes vs AIDrivingHelper

| Feature | AIDrivingHelper | AIDrivingHelper 2 | |---|---|---| | RAG pipeline | Yes | Yes | | Voice I/O | Yes | Yes | | Geographic enrichment | No | Yes | | Nearby schools/hospitals | No | Yes | | Road name in context | No | Yes | | Retrofit HTTP client | No | Yes (Retrofit 2 + Moshi) |

The core RAG chain is identical. The difference is what goes into the vector store before retrieval.

Architecture

Trip events (GPS coordinates per event)
        ↓
GeoContextEnricher
  - Nominatim API → road name, neighborhood, city
  - Overpass API → nearby schools, hospitals, traffic signals
        ↓
EnrichedDrivingEvent (road, city, nearbySchool, nearbyHospital, POI names)
        ↓
GeckoEmbeddingModel → SqliteVectorStore
        ↓
RAG chain → Gemma 3 1B IT → location-aware coaching response

Why geographic context matters

Without enrichment, the coaching response is: "You were doing 45 in a 30 zone."

With enrichment, it becomes: "You were speeding on Oak Street, which is within 200m of Lincoln Elementary School."

That is a different kind of feedback. It is more specific, more actionable, and more likely to stick.

Key Data Class

data class EnrichedDrivingEvent(
    val road: String?,
    val neighbourhood: String?,
    val city: String?,
    val poiNames: List<String>,
    val nearbySchool: Boolean,
    val nearbyHospital: Boolean,
    // ... original event fields
)

Geo-Enrichment APIs

Nominatim (OpenStreetMap Reverse Geocoding):

  • Converts GPS lat/lon to human-readable address
  • Returns road name, neighbourhood, city, postcode
  • Free, no auth required

Overpass API:

  • Queries OpenStreetMap features within 80m radius of each event location
  • Detects traffic signals, pedestrian crossings, and amenity types (school, hospital)
  • Uses OverPass Query Language (OQL) with around:radius filters

Both APIs are called via Retrofit 2 with Moshi JSON conversion and an OkHttp logging interceptor.

Key Screens

TripPOCDemoScreen: Displays trip metadata and the list of driving events, with a button to trigger geo enrichment on demand.

GeoContextInsightsCard: Shows each enriched event with road name and city, proximity warnings (school nearby, hospital nearby), and a list of POIs within radius.

VoiceChatWithInputScreen: Same voice chat interface as AIDrivingHelper. Ask questions about your trips, get location-aware coaching responses.

Tech Stack

Same as AIDrivingHelper, plus:

  • Retrofit 2.9.0 with Moshi JSON 1.14.0
  • OkHttp3 logging interceptor for API debugging
  • Separate Room entities for trips and events (TripEntity, TripEventEntity)

What I Learned

  1. Overpass Query Language is very powerful for radius-based POI detection. The around:radius filter does the heavy lifting. The learning curve is the syntax, not the concept.
  2. Context quality drives response quality. Richer embedding content means more specific retrieval, which means better coaching. The enrichment step directly improves the output.
  3. Nominatim has a 1 request/second rate limit. When enriching many events in a batch, a throttle is required or requests start getting rejected.
  4. Location-aware feedback lands differently. Telling a driver they were speeding near a school changes how they receive that information compared to a bare speed number.