Charging Stations Example#
In this example, we'll demonstrate how to use RouteE Compass to plan routes that incorporate charging stations for electric vehicles.
This builds off the Open Street Maps Example and assumes that we've already downloaded a road network and charging station data, so be sure to check that one out first.
import folium
from nrel.routee.compass import CompassApp
from nrel.routee.compass.plot import plot_route_folium
import pandas as pd
import matplotlib.pyplot as plt
First, we'll load the application from the pre-built configuration file that includes charging station data and the charging station traversal model.
app = CompassApp.from_config_file("./denver_co/osm_default_charging.toml")
Basic Route Without Charging Considerations#
Let's start with a basic route query for a 2017 Chevrolet Bolt without any special charging considerations and search for the shortest time route.
query = {
"origin_x": -104.969307,
"origin_y": 39.779021,
"destination_x": -104.975360,
"destination_y": 39.693005,
"model_name": "2017_CHEVROLET_Bolt",
"weights": {"trip_distance": 0, "trip_time": 1, "trip_energy": 0},
}
result = app.run(query)
if "error" in result:
print(result["error"])
applying input plugin 1: 100%|██████████| 1/1 [00:00<00:00, 2978.61it/s]
applying input plugin 2: 100%|██████████| 1/1 [00:00<00:00, 1008064.56it/s]
search: 100%|██████████| 1/1 [00:00<00:00, 4.19it/s]
Let's examine the route traversal summary to understand the basic route characteristics.
result["route"]["traversal_summary"]
{'trip_time': 10.161701243869603,
'battery_capacity': 60.0,
'trip_energy': 2.6266860049500207,
'trip_elevation_loss': -0.036753210979326045,
'trip_distance': 8.944297919510314,
'trip_elevation_gain': 0.05117468112201307,
'trip_soc': 0.9562218999174993}
Now we can visualize this basic route on a map.
plot_route_folium(result)
Low State of Charge Scenario#
Next, we'll create a scenario where the vehicle has a low starting state of charge (SOC) and needs to find a charging station along the route.
Note that we'll allow both DC Fast Charging (DCFC) and Level 2 (L2) charging stations but we're also trying to minimize the trip time, so the algorithm should prioritize DCFC charging stations since they provide faster charging.
low_soc_query = {
"origin_x": -104.969307,
"origin_y": 39.779021,
"destination_x": -104.975360,
"destination_y": 39.693005,
"model_name": "2017_CHEVROLET_Bolt",
"weights": {"trip_distance": 0, "trip_time": 1, "trip_energy": 0},
"starting_soc_percent": 2,
"full_soc_percent": 80,
"valid_power_types": ["DCFC", "L2"],
}
low_soc_result = app.run(low_soc_query)
if "error" in low_soc_result:
print(low_soc_result["error"])
applying input plugin 1: 100%|██████████| 1/1 [00:00<00:00, 294464.06it/s]
applying input plugin 2: 100%|██████████| 1/1 [00:00<00:00, 1404494.38it/s]
search: 100%|██████████| 1/1 [00:00<00:00, 5.84it/s]
Let's examine how the route changes when charging is required.
low_soc_result["route"]["traversal_summary"]
{'trip_soc': 0.772758004882395,
'trip_time': 30.926591664979423,
'trip_energy': 2.697727800039604,
'trip_elevation_loss': -0.045868526122872115,
'trip_distance': 9.154555603174025,
'battery_capacity': 60.0,
'trip_elevation_gain': 0.060289996265559136}
Now we'll visualize the route that includes charging stops.
m = plot_route_folium(low_soc_result)
m
Visualizing Charging Infrastructure#
Let's load the charging station data and visualize the available charging infrastructure on our map.
cdf = pd.read_csv("./denver_co/charging-stations.csv.gz")
We'll filter to show only DC Fast Charging (DCFC) stations
cdf = cdf[cdf["power_type"].isin(["DCFC"])].copy()
Now we'll add the charging stations to our map to show the available charging infrastructure.
# plot the charging_stations on the map
for station in cdf.itertuples():
m.add_child(
folium.Marker(
location=[station.y, station.x],
popup=f"{station.power_type}",
icon=folium.Icon(color="blue", icon="bolt"),
)
)
m
Analyzing State of Charge Over the Route#
Let's extract and analyze how the state of charge changes throughout the journey.
socs = []
time = []
distance = []
for feature in low_soc_result["route"]["path"]["features"]:
socs.append(feature["properties"]["state"]["trip_soc"])
time.append(feature["properties"]["state"]["trip_time"])
distance.append(feature["properties"]["state"]["trip_distance"])
Plot the state of charge over time to see when charging occurs.
plt.plot(time, socs)
[<matplotlib.lines.Line2D at 0x7f2a7a99f050>]

Plot the state of charge over distance to understand the spatial distribution of charging needs.
plt.plot(distance, socs)
[<matplotlib.lines.Line2D at 0x7f2a794a85d0>]
