All projects

Case study · A* routing for electric vehicles, with live charging stops

EV Route Optimizer

An Android app that plans multi-stop EV road trips end-to-end — real-time charging station insertion via OpenChargeMap, GraphHopper road routing, Open-Meteo weather effects, OBD-II Bluetooth SoC reading, and turn-by-turn MapLibre navigation. Built with Jetpack Compose and a custom A* engine over a (waypoint × SoC) state space.

Kotlin 2.2 Jetpack Compose Material 3 MapLibre Room Koin Retrofit WorkManager
EV Route Optimizer

01

The problem

Every popular EV navigation app treats charging stops as an afterthought — they slot in a single stop along the fastest road, ignoring your current battery level, your charger type, real-time station availability, ambient temperature effects on range, and the compound cost of going above 80% SoC on a tapered charge curve. The result is routes that look fast on paper but leave you range-anxious on the motorway.

02

The approach

Built a custom A* search engine over a two-dimensional state space: (waypoint index × state-of-charge). Each node is a (location, SoC) pair; edges are road segments whose energy cost comes from a physics model accounting for speed-dependent aerodynamic drag, rolling resistance, elevation gradient, temperature derating, and HVAC overhead. The charging model applies a non-linear taper above 80% SoC. Four optimisation modes (Fastest, Fewest Stops, Balanced, Eco) weight the heuristic differently. The engine dominance-prunes states, so it never expands a node if a cheaper path to the same location at higher SoC already exists.

03

My contribution

Sole developer — A* engine, energy and charging models, all four API integrations (GraphHopper, OpenChargeMap, Open-Meteo, Photon), OBD-II Bluetooth SoC reader, Room caching, WorkManager prefetch, calendar integration, and the full Compose UI with MapLibre navigation.

04

What I learned

The routing problem is harder than it looks because SoC is not just a constraint — it is part of the search state. Treating it that way (rather than post-processing a road route) is what allows the engine to find routes that would never emerge from a road-distance-only search: a slightly longer road segment that bypasses a detour to a slow charger, or a route that arrives at a fast charger with exactly enough margin to charge quickly and press on. The other hard lesson was the energy model: an overly aggressive speed-consumption curve caused the engine to over-insert stops on motorways. Calibrating it against real-world EV consumption data (80% rolling resistance, 20% aerodynamic drag growing with v²) brought the stop count in line with what drivers actually experience.


Screenshots

Plan Route — origin, destination, battery parameters and connector type Route Itinerary — charging stops, durations, arrival SoC, and quality score Turn-by-turn Navigation — MapLibre map with route line and speed/ETA HUD

A multi-stop EV route planner that treats charging as a first-class citizen of the search — not a post-processing step bolted onto a road-distance result.

EV Route Optimizer plans electric-vehicle road trips end-to-end: you enter origin, destination, battery parameters, and connector type; the engine finds the optimal sequence of charging stops and returns a full itinerary with charge durations, arrival SoC at each stop, and a quality score versus the unconstrained baseline.

The app integrates four live APIs — GraphHopper for road segments and elevation, OpenChargeMap for real-time charging station data, Open-Meteo for temperature and weather, and Photon for geocoding — and reads current state-of-charge directly from the vehicle via an OBD-II ELM327 Bluetooth adapter.

How the routing engine works

The A* search operates over a (waypoint, SoC) state space. Every node is a (location, battery%) pair. Edges are road segments whose cost is computed from a physics-based energy model:

  • Speed-dependent drag — rolling resistance (~80%) plus aerodynamic drag (~20%) growing with v². Calibrated to real EV consumption curves so the engine doesn’t over-insert stops on motorways.
  • Elevation factor — net gravitational work per segment, signed (uphill costs, downhill recovers).
  • Temperature derating — cold-battery and HVAC overhead extracted from Open-Meteo forecasts at the departure time.
  • Charging model — non-linear taper above 80% SoC reflects real fast-charger behaviour; cold-battery derate applies to charging speed.

Dominance pruning ensures the engine never re-expands a (location, SoC) pair if it has already found a path to the same location at equal or higher SoC for equal or lower cost.

Four optimisation modes

ModeWhat it optimises
FastestMinimise total trip time including charge sessions
Fewest StopsMinimise number of charging stops
BalancedWeighted blend of time and comfort margin
EcoMinimise energy cost; prefers lower speeds and gentler charge profiles

Key features

  • Live charging station insertion — OpenChargeMap filtered by connector type, minimum power, and a 6-hour freshness TTL.
  • OBD-II SoC reading — ELM327 Bluetooth adapter; non-blocking I/O with a 3.5s timeout; circuit-breaker after 5 consecutive failures.
  • Offline fallback — Room-cached routes (55m coordinate tolerance) and stations serve results when the network is unavailable.
  • WorkManager prefetch — background job pre-warms station and route caches for saved trips before departure.
  • Calendar integration — reads upcoming events with location fields and surfaces them as one-tap trip suggestions.
  • Turn-by-turn navigation — MapLibre map with route polyline, location tracking, and a speed/ETA heads-up display.
  • Sensor calibration — persistent efficiency calibration from real trips to refine the energy model over time.

Engineering highlights

  • Custom A* over a two-dimensional state space — not a wrapper around any existing routing library.
  • Physics energy model calibrated to real EV consumption data, not a lookup table.
  • Non-blocking OBD serial I/O (available() polling + deadline loop) to avoid indefinite blocking on InputStream.read().
  • Room coordinate matching at 0.0005° (~55 m) to avoid serving cached routes for wrong locations.
  • Dispatchers.Default for CPU-bound JSON serialisation; Dispatchers.IO for all network and database work.
  • MVVM + Repository + Koin DI throughout; WorkManager try-finally ensures DB handles are always closed.

ESC
  • Home

    The hero & featured

    Page
  • About

    Bio + bento + education journey

    Page
  • Experience

    Timeline of every role

    Page
  • Projects

    Filterable project grid

    Page
  • Certifications

    17 certs in 5 categories

    Page
  • Wine — Sommelier

    33-dish pairing tool

    Page
  • Water — Lifeguard

    Emergency-scenario tool

    Page
  • Language — Interpreter

    Bulgarian phrasebook

    Page
  • Gallery

    Lightbox

    Page
  • Now

    What I'm doing this month

    Page
  • Uses

    Tools & gear

    Page
  • Contact

    Send a message

    Page
  • Junior Sommelier

    Adare Manor

    Role
  • Senior Food and Beverage Assistant

    Adare Manor

    Role
  • Software Development Student

    AMCS Group

    Role
  • Temporary Associate Software Developer

    AMCS Group

    Role
  • Temporary Associate Software Engineer

    AMCS Group

    Role
  • Duty Manager

    Askeaton Pool & Leisure

    Role
  • Lifeguard and Swim Teacher

    Askeaton Pool & Leisure

    Role
  • Food and Beverage Assistant

    The Devon Inn Hotel

    Role
  • Food and Beverage Assistant

    The Mustard Seed

    Role
  • Student Professional

    National Building Control Office (NBCO) & National Market Surveillance Office (NMSO)

    Role
  • Interpreter

    translation.ie

    Role
  • Interpreter

    TRANSLIT

    Role
  • Delivery Driver

    Uber Eats

    Role
  • Hub Staff

    First 7 Weeks, University of Limerick

    Role
  • ICT Learning Centre Tutor

    ICTLC, University of Limerick

    Role
  • ICT Learning Centre Tutor

    ICTLC, University of Limerick

    Role
  • Temporary Computing Assistant

    Information Technology Division, University of Limerick

    Role
  • Orientation Guide

    Academic Registry, University of Limerick

    Role
  • Peer Advisor

    Glucksman Library, University of Limerick

    Role
  • Peer Advisor

    Glucksman Library, University of Limerick

    Role
  • Peer Advisor

    Glucksman Library, University of Limerick

    Role
  • PSLG Tutor

    University of Limerick

    Role
  • Creative Crew

    UL Student Life

    Role
  • Lifeguard

    West Lake Aqua Park

    Role
  • Lifeguard Supervisor

    West Lake Aqua Park

    Role
  • Waiter

    WrkWrk

    Role
  • Automated External Defibrillation (AED)

    Royal Life Saving Society UK (RLSS UK)

    Certification
  • Basic Concepts of AMCS Platform

    AMCS Group

    Certification
  • Assistant Swimming Teacher

    Water Safety Ireland

    Certification
  • National Vocational Beach Lifeguard Qualification

    Royal Life Saving Society UK (RLSS UK)

    Certification
  • Cardiac First Response - Advanced

    PHECC

    Certification
  • Introductory Sommelier

    Court of Master Sommeliers Europe

    Certification
  • CPR and First Aid Update 2026

    Royal Life Saving Society UK (RLSS UK)

    Certification
  • Customer Service: Managing Payments & Invoicing

    AMCS Group

    Certification
  • EFSET English Certificate 76/100 (C2 Proficient)

    EF SET

    Certification
  • Emergency First Response

    PHECC

    Certification
  • First Aid Responder

    PHECC

    Certification
  • Certificate of Language Ability - C2

    Language Certification

    Certification
  • Building Regulation Requirements for Works to Existing Dwellings

    National Building Control Office (NBCO) & National Market Surveillance Office (NMSO)

    Certification
  • Pool Lifeguarding

    Royal Life Saving Society UK (RLSS UK)

    Certification
  • Practical First Aid

    Irish Red Cross

    Certification
  • Safeguarding 1

    Swim Ireland

    Certification
  • Level 2 Swimming Teacher (Virtual — Askeaton)

    Swim Ireland

    Certification
  • WSET Level 2 Award in Wines — Merit (82%)

    Wine & Spirit Education Trust

    Certification
  • EduCoach

    An educational coaching marketplace, re-engineered solo

    Project
  • EV Route Optimizer

    A* routing for electric vehicles, with live charging stops

    Project
  • Monkey Rescue

    A conservation nonprofit site, rebuilt accessibility-first

    Project
  • Personal Portfolio

    This site — Astro, Tailwind, editorial design

    Project
  • Ballingarry National School

    6th class (final year of primary)

    Education
  • Colàiste na Tròcaire

    Leaving Certificate (Established, incl. Transition Year)

    Education
  • SOU "Panayot Volov"

    Primary education (1st – 6th class)

    Education
  • University of Limerick

    Bachelor of Science — Computer Systems

    Education
  • University of Limerick

    Master of Science — AI & Machine Learning

    Education
  • Aged cheddar

    → Vintage Port

    Pairing
  • Beef bourguignon

    → Red Burgundy, village level

    Pairing
  • Blue cheese (Stilton, Roquefort)

    → Sauternes

    Pairing
  • Bolognese / ragù

    → Chianti Classico

    Pairing
  • Brie or Camembert

    → Champagne

    Pairing
  • Caesar salad

    → Sancerre

    Pairing
  • Spaghetti carbonara

    → Frascati

    Pairing
  • Charcuterie board

    → Beaujolais-Villages or dry Lambrusco

    Pairing
  • Dark chocolate dessert

    → Banyuls or vintage Port

    Pairing
  • Baked or pan-fried cod

    → Pinot Grigio

    Pairing
  • Coq au vin

    → Red Burgundy

    Pairing
  • Crème brûlée

    → Sauternes

    Pairing
  • Dover sole or other flat fish

    → Chablis

    Pairing
  • Duck (confit or roasted)

    → Pinot Noir or Alsace Pinot Gris

    Pairing
  • Indian curry (medium spice)

    → Gewürztraminer or rosé

    Pairing
  • Lobster with butter

    → White Burgundy or vintage Champagne

    Pairing
  • Margherita pizza

    → Chianti or Barbera d'Alba

    Pairing
  • Fresh oysters

    → Muscadet sur lie

    Pairing
  • Pad Thai

    → Off-dry Riesling

    Pairing
  • Seafood paella

    → Dry rosado (Spanish rosé)

    Pairing
  • Pesto pasta

    → Vermentino

    Pairing
  • Pork belly

    → Off-dry Mosel Riesling

    Pairing
  • Rack of lamb

    → Northern Rhône Syrah

    Pairing
  • Mushroom risotto

    → Barbera or aged Nebbiolo

    Pairing
  • Roast chicken

    → White Burgundy

    Pairing
  • Roast pork

    → White Burgundy

    Pairing
  • Grilled salmon

    → Light Pinot Noir or dry rosé

    Pairing
  • Pan-seared scallops

    → Chablis Premier Cru

    Pairing
  • Pan-seared sea bass

    → Albariño

    Pairing
  • Ribeye or sirloin steak

    → Bold Cabernet Sauvignon

    Pairing
  • Sushi & sashimi

    → Off-dry German Riesling or junmai sake

    Pairing
  • Seared tuna steak

    → Cru Beaujolais

    Pairing
  • Venison

    → Barolo or Northern Rhône Syrah

    Pairing
  • Anaphylaxis (severe allergic reaction)

    critical

    Scenario
  • Choking adult (conscious)

    urgent

    Scenario
  • Drowning casualty (recently removed from water)

    critical

    Scenario
  • Heat exhaustion progressing to heat stroke

    urgent

    Scenario
  • Hypothermia (cold-water immersion)

    urgent

    Scenario
  • Tonic-clonic seizure

    urgent

    Scenario
  • Severe external bleeding

    critical

    Scenario
  • Suspected spinal injury (pool diving)

    critical

    Scenario
  • Suspected stroke (FAST positive)

    critical

    Scenario
  • Sudden cardiac arrest (adult)

    critical

    Scenario
  • The airport

    Летището · leh-TEESH-teh-toh

    Phrase
  • I am allergic to...

    Алергичен съм към... · ah-ler-GEE-chen suhm kuhm

    Phrase
  • I need an ambulance

    Имам нужда от линейка · EE-mam NOOZH-dah ot lee-NEY-kah

    Phrase
  • Call the police

    Извикайте полицията · eez-vee-KAI-teh poh-LEE-tsee-yah-tah

    Phrase
  • Could I get a coffee, please?

    Едно кафе, моля · ED-noh kah-FEH, MOH-lyah

    Phrase
  • Cheers!

    Наздраве! · nahz-DRAH-veh

    Phrase
  • This is delicious

    Това е много вкусно · toh-VAH eh MNOH-goh VKOOS-noh

    Phrase
  • I don't understand

    Не разбирам · neh rahz-BEE-ram

    Phrase
  • There's a fire

    Има пожар · EE-mah poh-ZHAR

    Phrase
  • A glass / A bottle

    Чаша / Бутилка · CHAH-shah / boo-TEEL-kah

    Phrase
  • Good evening

    Добър вечер · DOH-bar VEH-cher

    Phrase
  • Good morning

    Добро утро · DOH-broh OO-troh

    Phrase
  • Goodbye

    Довиждане · do-VEEZH-dah-neh

    Phrase
  • Hello

    Здравейте · zdrah-VEY-teh

    Phrase
  • Help!

    Помощ! · poh-MOSHT

    Phrase
  • The hospital

    Болницата · BOHL-nee-tsah-tah

    Phrase
  • How are you?

    Как сте? · kahk steh

    Phrase
  • How much does it cost?

    Колко струва? · KOHL-koh STROO-vah

    Phrase
  • I'm from Ireland

    От Ирландия съм · ot eer-LAHN-dee-yah suhm

    Phrase
  • Could I see the menu?

    Може ли менюто? · MOH-zheh lee men-YOO-toh

    Phrase
  • This pairs well with...

    Това върви добре с... · toh-VAH vuhr-VEE doh-BREH suh

    Phrase
  • Please

    Моля · MOH-lyah

    Phrase
  • Red wine / White wine

    Червено вино / Бяло вино · cher-VEH-noh VEE-noh / BYAH-loh VEE-noh

    Phrase
  • Sorry / Excuse me

    Извинете · eez-vee-NEH-teh

    Phrase
  • A table for two, please

    Маса за двама, моля · MAH-sah zah DVAH-mah, MOH-lyah

    Phrase
  • Thank you

    Благодаря · bla-go-dar-YAH

    Phrase
  • The bill, please

    Сметката, моля · SMET-kah-tah, MOH-lyah

    Phrase
  • The train station

    Жп гарата · zhuh-puh GAH-rah-tah

    Phrase
  • A glass of water, please

    Чаша вода, моля · CHA-shah voh-DAH, MOH-lyah

    Phrase
  • What do you recommend?

    Какво препоръчвате? · kahk-VOH preh-poh-RUHCH-vah-teh

    Phrase
  • What's your name?

    Как се казвате? · kahk seh kahz-VAH-teh

    Phrase
  • Where is the bathroom?

    Къде е тоалетната? · KUH-deh eh toh-ah-LET-nah-tah

    Phrase
  • Yes / No

    Да / Не · dah / neh

    Phrase
  • LinkedIn

    todoraleksandrov

    External
  • GitHub

    todor147

    External
  • Email

    todor_147@abv.bg

    External
↑↓ to navigate to open