Introducing Electric Vehicle Routing to the HERE Developer Portfolio

By Raymond Camden | 25 January 2021

Try HERE Maps

Create a free API key to build location-aware apps and services.

Get Started

We have an exciting update to our Routing API with the addition of powerful and versatile electric vehicle (EV) routing. This new feature provides rich support for EV fleet management. This support goes way beyond just mapping charging points: it can be configured with your individual EV properties to meet the requirements of your service or app. It can also take into account time to charge as well as optimal times and suggest routes best suited for your particular EV needs. To get started using this new feature, begin by taking a look at our developer guide introduction to EV routing.

At a high level, you'll need the following arguments to use EV routing. First, to calculate energy consumption, you'll need:

  • freeFlowSpeedTable: A function curve that specifies energy consumption at a particular speed.
  • ascent: The rate of energy consumed per meter rise in elevation.
  • descent: The rate of energy consumed per meter fall in elevation.

On top of these, to calculate reachable routes, you'll need:

  • initialCharge: Charge level of the vehicle's battery at the start of the route.
  • maxCharge: Total capacity of the vehicle's battery.
  • connectorTypes: Comma-separated list of connector types that are compatible with the vehicle. The API docs define supported types.
  • chargingCurve: Function curve describing the maximum battery charging rate at a given charge level.
  • maxChargeAfterChargingStation: Maximum charge to which the battery should be charged at a charging station.
  • makeReachable: This must be set to true.

There are additional EV related attributes as well, and as said above, the API docs are your best friend. It can get pretty complex. Let's consider an example with hard coded values using Node.js:

const fetch = require('node-fetch');

require('dotenv').config();
const API_KEY = process.env.HERE_API_KEY;

(async () => {

    // New York (lat, long)
    let p1 = '40.712,-74.059413';
    // Boston
    let p2 = '42.360,-71.0588801';

    let props = {
        transportMode:'car',
        origin:p1,
        destination:p2,
        'ev[freeFlowSpeedTable]':'0,0.239,27,0.239,45,0.259,60,0.196,75,0.207,90,0.238,100,0.26,110,0.296,120,0.337,130,0.351,250,0.351',
        'ev[trafficSpeedTable]':'0,0.349,27,0.319,45,0.329,60,0.266,75,0.287,90,0.318,100,0.33,110,0.335,120,0.35,130,0.36,250,0.36',
        'ev[auxiliaryConsumption]':1.8,
        'ev[ascent]':9,
        'ev[descent]':4.3,
        'ev[initialCharge]':48,
        'ev[maxCharge]':80,
        'ev[makeReachable]':true,
        'ev[connectorTypes]':'iec62196Type1Combo,iec62196Type2Combo,Chademo,Tesla',
        'ev[chargingCurve]':'0,239,32,199,56,167,60,130,64,111,68,83,72,55,76,33,78,17,80,1',
        'ev[maxChargeAfterChargingStation]':72,
        return:'summary,actions,polyline'
    };

    let route = await getRoute(props);
    // polyline is huge and noisy
    for(let i=0;i<route.sections.length;i++) {
        if(route.sections[i].polyline) route.sections[i].polyline = 'Deleted to make output easier to read.';
    }
    console.log(JSON.stringify(route, null,'\t'));

})();

async function getRoute(props) {
    let url = `https://router.hereapi.com/v8/routes?apikey=${API_KEY}`
    for(let key in props) {
        url += `&${key}=${props[key]}`;
    }
    let resp = await fetch(url);
    let data = await resp.json();
    if(!data.routes) console.log(data);
    return data.routes[0];

}

This script simulates an EV route from New York City to Boston. It includes multiple different ev arguments that specifies the nature of how the vehicle operates, charges, and so forth. In your REST calls, all ev arguments will be of the form ev[something] which can help visually differentiate it from the rest of the call. All of these arguments are passed to a little utility function I wrote that then hits the API and parses the result, returning just the first route (if it exists - like many of the scripts I write to test things out the error handling could be nicer!).

Executing this script will return, as usual, quite a lot of information in regards to the trip, but let me share some interesting portions from the result.

Route results come in "sections" that make up the route, and with EV routing enabled, you are presenting with information related to charging done at the end of the section, including estimated charge and time to complete the charge:

"postActions": [
    {
        "action": "charging",
        "duration": 568,
        "consumablePower": 350,
        "arrivalCharge": 3.8865,
        "targetCharge": 40
    }
],

Arrival information also includes EV data:

"arrival": {
    "time": "2021-01-15T13:13:32-05:00",
    "place": {
        "type": "chargingStation",
        "location": {
            "lat": 41.1980673,
            "lng": -73.1222808
        },
        "id": "2927",
        "name": "Stratford Square",
        "attributes": {
            "power": 350,
            "current": 350,
            "voltage": 1000,
            "supplyType": "dc",
            "connectorType": "iec62196Type1Combo"
        }
    },
    "charge": 3.8865
},

Summary data will also include charging related information:

"summary": {
    "duration": 5860,
    "length": 150224,
    "consumption": 54.0499,
    "baseDuration": 5734
},

All in all, it's a fairly complex new feature. There's a few resources I'd suggest for additional help:

As an example, here's how the Reference Client renders my NYC to Boston route, with notable charging stops.

pic1