Zelfstudie: Elektrische voertuigen routeren met behulp van Azure Notebooks (Python)
Azure Maps is een portfolio met georuimtelijke service-API's die zijn geïntegreerd in Azure, zodat ontwikkelaars locatiebewuste toepassingen kunnen maken voor verschillende scenario's, zoals IoT, mobiliteit en assettracking.
Azure Maps REST API's ondersteunen talen zoals Python en R voor georuimtelijke gegevensanalyse en machine learning, met robuuste routerings-API's voor het berekenen van routes op basis van voorwaarden zoals het voertuigtype of het bereik.
In deze zelfstudie worden gebruikers begeleid bij het routeren van elektrische voertuigen met behulp van Azure Maps-API's, samen met Jupyter Notebooks in VS Code en Python om het dichtstbijzijnde laadstation te vinden wanneer de batterij laag is.
In deze zelfstudie leert u het volgende:
- Een Jupyter Notebook maken en uitvoeren in VS Code.
- REST API's van Azure Maps aanroepen in Python.
- Een bereik zoeken op basis van het verbruiksmodel van het elektrische voertuig.
- Zoek naar laadstations voor elektrische voertuigen binnen het bereik of isochrone.
- De bereikgrens en laadstations op een kaart weergeven.
- Op basis van de rijtijd een route naar het dichtstbijzijnde laadstation voor elektrische voertuigen zoeken en visualiseren.
Vereisten
- Een Azure Maps-account
- Een abonnementssleutel
- Visual Studio Code
- Een werkende kennis van Jupyter Notebooks in VS Code
- Omgeving die is ingesteld voor gebruik met Python in Jupyter Notebooks. Zie Uw omgeving instellen voor meer informatie.
Notitie
Zie Verificatie beheren in Azure Maps voor meer informatie over verificatie in Azure Maps.
Pakketten op projectniveau installeren
Het ev-routerings- en bereikproject heeft afhankelijkheden van de python-bibliotheken aiohttp en IPython . U kunt deze installeren in de Visual Studio-terminal met behulp van pip:
pip install aiohttp
pip install ipython
Jupyter Notebook openen in Visual Studio Code
Download vervolgens het notebook dat in deze zelfstudie wordt gebruikt:
Open het bestand EVrouting.ipynb in de opslagplaats AzureMapsJupyterSamples in GitHub.
Selecteer de knop Onbewerkt bestand downloaden in de rechterbovenhoek van het scherm om het bestand lokaal op te slaan.
Open het gedownloade notebook in Visual Studio Code door met de rechtermuisknop op het bestand te klikken en Open met > Visual Studio Code of via de VS Code-Bestandenverkenner te selecteren.
De vereiste modules en frameworks laden
Zodra de code is toegevoegd, kunt u een cel uitvoeren met behulp van het pictogram Uitvoeren links van de cel en wordt de uitvoer onder de codecel weergegeven.
Voer het volgende script uit om alle vereiste modules en frameworks te laden.
import time
import aiohttp
import urllib.parse
from IPython.display import Image, display
De bereikgrens opvragen
Een pakketleveringsbedrijf heeft een vloot met een aantal elektrische voertuigen. Deze voertuigen moeten overdag worden opgeladen zonder terug te keren naar het magazijn. Wanneer de resterende kosten lager zijn dan een uur, wordt een zoekopdracht uitgevoerd om laadstations binnen een bereik te vinden. De grensinformatie voor het bereik van deze laadstations wordt vervolgens verkregen.
Het aangevraagde routeType
is eco om de economie en snelheid te verdelen. Met het volgende script wordt de Get Route Range-API van de Azure Maps-routeringsservice aangeroepen met behulp van parameters die betrekking hebben op het verbruiksmodel van het voertuig. Het script parseert vervolgens het antwoord om een veelhoekobject in GeoJSON-indeling te maken, dat het maximale bereik van de auto vertegenwoordigt.
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
]
}
}
Zoeken naar laadstations voor elektrische voertuigen binnen het bereik
Na het bepalen van het bereik van het elektrische voertuig (isochrone), kunt u zoeken naar laadstations binnen dat gebied.
In het volgende script wordt gebruikgemaakt van de Azure Maps Post Search Inside Geometry-API om laadstations te vinden binnen het maximale bereik van het voertuig. Vervolgens wordt het antwoord geparseerd in een matrix met bereikbare locaties.
# 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)
De laadstations en het bereik weergeven op een kaart
Roep de Azure Maps Get Map Image-service aan om de laadpunten en maximale bereikbare grens op de statische kaartafbeelding weer te geven door het volgende script uit te voeren:
# 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))
Het optimale laadstation zoeken
Identificeer eerst alle mogelijke laadstations binnen het bereik van het voertuig. Bepaal vervolgens in de kortst mogelijke tijd welke van deze stations toegankelijk zijn.
Met het volgende script wordt de API Matrixroutering van Azure Maps aangeroepen. Het retourneert de locatie van het voertuig, de reistijd en de afstand tot elk laadstation. Het volgende script parseert deze reactie om het dichtstbijzijnde laadstation te identificeren dat in de minste tijd kan worden bereikt.
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)
De route naar het dichtstbijzijnde laadstation berekenen
Nadat u het dichtstbijzijnde laadstation hebt gezocht, gebruikt u de API Routebeschrijving ophalen om gedetailleerde aanwijzingen te verkrijgen van de huidige locatie van de voertuigen. Voer het script uit in de volgende cel om een GeoJSON-object te genereren en te parseren dat de route vertegenwoordigt.
# 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
}
De route visualiseren
Als u de route wilt visualiseren, gebruikt u de GET Map Image-API om deze weer te geven op de kaart.
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))
In deze zelfstudie hebt u geleerd hoe u rechtstreeks REST API's van Azure Maps aanroept en Azure Maps-gegevens visualiseert met behulp van Python.
Zie voor meer informatie over de Azure Maps-API's die in deze zelfstudie worden gebruikt:
- Routebeschrijving ophalen
- Routebereik ophalen
- Post-routematrix
- Post-zoekopdracht binnen geometrie
- Weergeven - Kaartafbeelding ophalen
Zie REST API's van Azure Maps voor een volledige lijst met REST API's van Azure Maps.