Tutoriel : Router les véhicules électriques avec Azure Notebooks (Python)
Azure Maps est un portefeuille d’API de service géospatial intégré à Azure, ce qui permet aux développeurs de créer des applications prenant en charge les emplacements pour différents scénarios tels que l’IoT, la mobilité et le suivi de ressources.
Les API REST d’Azure Maps prennent en charge des langages tels que Python et R pour l’analyse des données géospatiales et le Machine Learning, offrant des API de routage robustes pour calculer des itinéraires en fonction de conditions telles que le type de véhicule ou la zone accessible.
Ce tutoriel guide les utilisateurs dans le routage de véhicules électriques en utilisant l’API Azure Maps ainsi que Jupyter Notebooks dans VS Code et Python pour trouver la station de recharge la plus proche quand la batterie est faible.
Ce didacticiel présente les procédures suivantes :
- Créer et exécuter un Jupyter Notebook dans VSCode.
- Appeler les API REST Azure Maps en Python.
- Rechercher une zone accessible en fonction du modèle de consommation du véhicule électrique
- Recherchez des stations de recharge de véhicule électrique dans la zone accessible ou isochrone.
- Afficher la limite de la zone accessible et les bornes de recharge sur une carte
- Rechercher et visualiser une route vers la borne de recharge de véhicule électrique la plus proche en temps de conduite.
Prérequis
- Compte Azure Maps
- Clé d’abonnement
- Visual Studio Code
- Une connaissance pratique des Jupyter Notebook dans VS Code
- Environnement configuré pour fonctionner avec Python dans des Jupyter Notebooks. Pour plus d’informations, consultez Configuration de votre environnement.
Remarque
Pour plus d’informations sur l’authentification dans Azure Maps, voir Gérer l’authentification dans Azure Maps.
Installer des packages au niveau du projet
Le projet EV Routing and Reachable Range (Routage et distance atteignable pour des véhicules électriques) a des dépendances vis-à-vis des bibliothèques Python aiohttp et IPython. Vous pouvez les installer dans le terminal Visual Studio en utilisant pip :
pip install aiohttp
pip install ipython
Ouvrir Jupyter Notebook dans Visual Studio Code
Téléchargez puis ouvrez le notebook utilisé dans ce tutoriel :
Ouvrez le fichier EVrouting.ipynb du référentiel AzureMapsJupyterSamples dans GitHub.
Sélectionnez le bouton Télécharger le fichier brut dans le coin supérieur droit de l’écran pour enregistrer le fichier localement.
Ouvrez le notebook téléchargé dans Visual Studio Code en cliquant avec le bouton droit sur le fichier, puis en sélectionnant Ouvrir avec > Visual Studio Code, ou via l’Explorateur de fichiers de VS Code.
Charger les modules et les frameworks nécessaires
Une fois votre code ajouté, vous pouvez exécuter une cellule en utilisant l’icône Exécuter à gauche de la cellule ; la sortie est affichée sous la cellule de code.
Exécutez le script suivant pour charger tous les modules et frameworks requis.
import time
import aiohttp
import urllib.parse
from IPython.display import Image, display
Demander les limites de la zone accessible
Une compagnie de livraison de colis exploite une flotte qui comprend des véhicules électriques. Ces véhicules doivent être rechargés pendant la journée sans retourner à l’entrepôt. Quand la charge restante tombe en dessous d’une heure, une recherche est effectuée pour trouver des stations de recharge à une distance accessible. Les informations de limite pour la distance de ces stations de recharge sont ensuite obtenues.
Le routeType
demandé est eco pour équilibrer l’économie et la vitesse. Le script suivant appelle l’API Get Route Range du service de routage Azure Maps, en utilisant des paramètres pour le modèle de consommation du véhicule. Le script analyse ensuite la réponse pour créer un objet de polygone au format GeoJSON, qui représente la distance maximale accessible par le véhicule.
subscriptionKey = "Your Azure Maps key"
currentLocation = [34.028115,-118.5184279]
session = aiohttp.ClientSession()
# Parameters for the vehicle consumption model
travelMode = "car"
vehicleEngineType = "electric"
currentChargeInkWh=45
maxChargeInkWh=80
timeBudgetInSec=550
routeType="eco"
constantSpeedConsumptionInkWhPerHundredkm="50,8.2:130,21.3"
# Get boundaries for the electric vehicle's reachable range.
routeRangeResponse = await (await session.get("https://atlas.microsoft.com/route/range/json?subscription-key={}&api-version=1.0&query={}&travelMode={}&vehicleEngineType={}¤tChargeInkWh={}&maxChargeInkWh={}&timeBudgetInSec={}&routeType={}&constantSpeedConsumptionInkWhPerHundredkm={}"
.format(subscriptionKey,str(currentLocation[0])+","+str(currentLocation[1]),travelMode, vehicleEngineType, currentChargeInkWh, maxChargeInkWh, timeBudgetInSec, routeType, constantSpeedConsumptionInkWhPerHundredkm))).json()
polyBounds = routeRangeResponse["reachableRange"]["boundary"]
for i in range(len(polyBounds)):
coordList = list(polyBounds[i].values())
coordList[0], coordList[1] = coordList[1], coordList[0]
polyBounds[i] = coordList
polyBounds.pop()
polyBounds.append(polyBounds[0])
boundsData = {
"geometry": {
"type": "Polygon",
"coordinates":
[
polyBounds
]
}
}
Rechercher des bornes de recharge de véhicule électrique dans la zone accessible
Après avoir déterminé la distance accessible (isochrone) par le véhicule électrique, vous pouvez rechercher les stations de recharge dans cette zone.
Le script suivant utilise l’API Post Search Inside Geometry d’Azure Maps pour rechercher des stations de recharge dans la plage de distances maximale accessible par le véhicule. Il analyse ensuite la réponse dans un tableau de lieux accessibles.
# Search for electric vehicle stations within reachable range.
searchPolyResponse = await (await session.post(url = "https://atlas.microsoft.com/search/geometry/json?subscription-key={}&api-version=1.0&query=electric vehicle station&idxSet=POI&limit=50".format(subscriptionKey), json = boundsData)).json()
reachableLocations = []
for loc in range(len(searchPolyResponse["results"])):
location = list(searchPolyResponse["results"][loc]["position"].values())
location[0], location[1] = location[1], location[0]
reachableLocations.append(location)
Afficher les bornes de recharge et la zone accessible sur une carte
Appelez le service Get Map Image d’Azure Maps pour afficher les points de recharge et la limite maximale accessible sur l’image de carte statique en exécutant le script suivant :
# Get boundaries for the bounding box.
def getBounds(polyBounds):
maxLon = max(map(lambda x: x[0], polyBounds))
minLon = min(map(lambda x: x[0], polyBounds))
maxLat = max(map(lambda x: x[1], polyBounds))
minLat = min(map(lambda x: x[1], polyBounds))
# Buffer the bounding box by 10 percent to account for the pixel size of pins at the ends of the route.
lonBuffer = (maxLon-minLon)*0.1
minLon -= lonBuffer
maxLon += lonBuffer
latBuffer = (maxLat-minLat)*0.1
minLat -= latBuffer
maxLat += latBuffer
return [minLon, maxLon, minLat, maxLat]
minLon, maxLon, minLat, maxLat = getBounds(polyBounds)
polyBoundsFormatted = ('|'.join(map(str, polyBounds))).replace('[','').replace(']','').replace(',','')
reachableLocationsFormatted = ('|'.join(map(str, reachableLocations))).replace('[','').replace(']','').replace(',','')
path = "lcff3333|lw3|la0.80|fa0.35||{}".format(polyBoundsFormatted)
pins = "custom|an15 53||{}||https://raw.githubusercontent.com/Azure-Samples/AzureMapsCodeSamples/e3a684e7423075129a0857c63011e7cfdda213b7/Static/images/icons/ev_pin.png".format(reachableLocationsFormatted)
encodedPins = urllib.parse.quote(pins, safe='')
# Render the range and electric vehicle charging points on the map.
staticMapResponse = await session.get("https://atlas.microsoft.com/map/static/png?api-version=2022-08-01&subscription-key={}&pins={}&path={}&bbox={}&zoom=12".format(subscriptionKey,encodedPins,path,str(minLon)+", "+str(minLat)+", "+str(maxLon)+", "+str(maxLat)))
poiRangeMap = await staticMapResponse.content.read()
display(Image(poiRangeMap))
Rechercher la borne de recharge optimale
Tout d’abord, identifiez toutes les stations de recharge potentielles dans la zone accessible par le véhicule. Ensuite, déterminez quelles stations sont accessibles dans la plus courte période possible.
Le script suivant appelle l’API de routage par matrice d’Azure Maps. Elle retourne l’emplacement du véhicule, le temps de trajet et la distance jusqu’à chaque station de recharge. Le script suivant analyse cette réponse pour identifier la station de recharge la plus proche qui peut être atteinte en un minimum de temps.
locationData = {
"origins": {
"type": "MultiPoint",
"coordinates": [[currentLocation[1],currentLocation[0]]]
},
"destinations": {
"type": "MultiPoint",
"coordinates": reachableLocations
}
}
# Get the travel time and distance to each specified charging station.
searchPolyRes = await (await session.post(url = "https://atlas.microsoft.com/route/matrix/json?subscription-key={}&api-version=1.0&routeType=shortest&waitForResults=true".format(subscriptionKey), json = locationData)).json()
distances = []
for dist in range(len(reachableLocations)):
distances.append(searchPolyRes["matrix"][0][dist]["response"]["routeSummary"]["travelTimeInSeconds"])
minDistLoc = []
minDistIndex = distances.index(min(distances))
minDistLoc.extend([reachableLocations[minDistIndex][1], reachableLocations[minDistIndex][0]])
closestChargeLoc = ",".join(str(i) for i in minDistLoc)
Calculer l’itinéraire jusqu’à la borne de recharge la plus proche
Après avoir localisé la station de recharge la plus proche, utilisez l’API Get Route Directions pour obtenir des instructions détaillées à partir de l’emplacement actuel des véhicules. Exécutez le script de la cellule suivante pour générer et analyser un objet GeoJSON représentant l’itinéraire.
# Get the route from the electric vehicle's current location to the closest charging station.
routeResponse = await (await session.get("https://atlas.microsoft.com/route/directions/json?subscription-key={}&api-version=1.0&query={}:{}".format(subscriptionKey, str(currentLocation[0])+","+str(currentLocation[1]), closestChargeLoc))).json()
route = []
for loc in range(len(routeResponse["routes"][0]["legs"][0]["points"])):
location = list(routeResponse["routes"][0]["legs"][0]["points"][loc].values())
location[0], location[1] = location[1], location[0]
route.append(location)
routeData = {
"type": "LineString",
"coordinates": route
}
Visualiser l’itinéraire
Pour visualiser l’itinéraire, utilisez l’API Get Map Image pour l’afficher sur la carte.
destination = route[-1]
#destination[1], destination[0] = destination[0], destination[1]
routeFormatted = ('|'.join(map(str, route))).replace('[','').replace(']','').replace(',','')
path = "lc0f6dd9|lw6||{}".format(routeFormatted)
pins = "default|codb1818||{} {}|{} {}".format(str(currentLocation[1]),str(currentLocation[0]),destination[0],destination[1])
# Get boundaries for the bounding box.
minLon, maxLon = (float(destination[0]),currentLocation[1]) if float(destination[0])<currentLocation[1] else (currentLocation[1], float(destination[0]))
minLat, maxLat = (float(destination[1]),currentLocation[0]) if float(destination[1])<currentLocation[0] else (currentLocation[0], float(destination[1]))
# Buffer the bounding box by 10 percent to account for the pixel size of pins at the ends of the route.
lonBuffer = (maxLon-minLon)*0.1
minLon -= lonBuffer
maxLon += lonBuffer
latBuffer = (maxLat-minLat)*0.1
minLat -= latBuffer
maxLat += latBuffer
# Render the route on the map.
staticMapResponse = await session.get("https://atlas.microsoft.com/map/static/png?api-version=2022-08-01&subscription-key={}&&path={}&pins={}&bbox={}&zoom=16".format(subscriptionKey,path,pins,str(minLon)+", "+str(minLat)+", "+str(maxLon)+", "+str(maxLat)))
staticMapImage = await staticMapResponse.content.read()
await session.close()
display(Image(staticMapImage))
Dans ce tutoriel, vous avez découvert comment appeler les API REST Azure Maps directement et comment visualiser les données Azure Maps avec Python.
Pour plus d’informations sur les API Azure Maps utilisées dans ce tutoriel, consultez :
- Obtenir un itinéraire
- Obtenir une zone d’itinéraire
- Envoyer une matrice d’itinéraire
- Envoyer une recherche dans une géométrie
- Rendu - Obtenir une image de carte
Pour obtenir la liste complète des API REST Azure Maps, consultez API REST Azure Maps.