Share via


Zelfstudie: Elektrische voertuigen routeren met behulp van Azure Notebooks (Python)

Azure Maps is een portfolio met georuimtelijke service-API's die systeemeigen zijn geïntegreerd in Azure. Met deze API's kunnen ontwikkelaars, ondernemingen en ISV's locatiegerichte apps en oplossingen ontwikkelen voor IoT, mobiliteit, logistiek en het bijhouden van assets.

De REST API's van Azure Maps kunnen worden aangeroepen vanuit computertalen zoals Python en R voor het inschakelen van georuimtelijke gegevensanalyse en machine learning-scenario's. Azure Maps biedt een robuuste set routerings-API's waarmee gebruikers routes tussen verschillende gegevenspunten kunnen berekenen. De berekeningen zijn gebaseerd op verschillende voorwaarden, zoals het voertuigtype of het bereikbare gebied.

In deze zelfstudie leert u hoe u een bestuurder helpt van wie de accu van het elektrische voertuig bijna leeg is. De bestuurder moet het laadstation vinden dat zich het dichtst bij de locatie van het voertuig bevindt.

In deze zelfstudie leert u het volgende:

  • Maak een Jupyter Notebook-bestand en voer het uit in Azure Notebooks in de cloud.
  • REST API's van Azure Maps aanroepen in Python.
  • Een bereik zoeken op basis van het verbruiksmodel van het elektrische voertuig.
  • Zoeken naar laadstations voor elektrische voertuigen binnen het bereik, ofwel de isochroon.
  • 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

Notitie

Zie Verificatie beheren in Azure Maps voor meer informatie over verificatie in Azure Maps.

Een Azure Notebooks-project maken

Voor deze zelfstudie moet u een Azure Notebooks-project maken en het Jupyter Notebook-bestand downloaden en uitvoeren. Het Jupyter Notebook-bestand bevat Python-code waarmee het scenario in deze zelfstudie wordt geïmplementeerd. Voer de volgende stappen uit om een Azure Notebooks-project te maken en het Jupyter Notebook-document te uploaden naar dat project:

  1. Ga naar Azure Notebooks en meld u aan. Zie quickstart: Aanmelden en een gebruikers-id instellen voor meer informatie.

  2. Selecteer bovenaan de openbare profielpagina Mijn projecten.

    The My Projects button

  3. Selecteer op de pagina Mijn projecten de optie Nieuw project.

    The New Project button

  4. Voer in het deelvenster Nieuw project maken een projectnaam en project-id in.

    The Create New Project pane

  5. Selecteer Maken.

  6. Nadat uw project is gemaakt, downloadt u dit Jupyter Notebook-documentbestand uit de Jupyter Notebook-opslagplaats van Azure Maps.

  7. Selecteer in de lijst met projecten op de pagina Mijn projecten uw project en selecteer vervolgens Uploaden om het Jupyter Notebook-documentbestand te uploaden.

    upload Jupyter Notebook

  8. Upload het bestand vanaf uw computer en selecteer vervolgens Gereed.

  9. Nadat het uploaden is voltooid, wordt uw bestand weergegeven op uw projectpagina. Dubbelklik op het bestand om het te openen als een Jupyter Notebook.

Probeer de functionaliteit te begrijpen die in het Jupyter Notebook-bestand is geïmplementeerd. Voer de code in het Jupyter Notebook-bestand cel voor cel uit. U kunt de code in elke cel uitvoeren door de knop Uitvoeren aan de bovenkant van de Jupyter Notebook-app te selecteren.

The Run button

Pakketten op projectniveau installeren

Voer de volgende stappen uit om de code in het Jupyter Notebook uit te voeren om pakketten op projectniveau te installeren:

  1. Download het bestand requirements.txt vanuit de Jupyter Notebook-opslagplaats van Azure Maps en upload het vervolgens naar uw project.

  2. Selecteer Projectinstellingen op het projectdashboard.

  3. Selecteer in het deelvenster Projectinstellingen het tabblad Omgeving en selecteer vervolgens Toevoegen.

  4. Ga als volgt te werk onder Stappen voor het instellen van de omgeving: a. Selecteer in de eerste vervolgkeuzelijst Requirements.txt.
    b. Selecteer in de tweede vervolgkeuzelijst uw bestand requirements.txt.
    c. Selecteer in de derde vervolgkeuzelijst Python-versie 3.6 als uw versie.

  5. Selecteer Opslaan.

    Install packages

De vereiste modules en frameworks laden

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 pakketdienst beschikt over enkele elektrische voertuigen. Overdag moeten de elektrische voertuigen opnieuw worden opgeladen zonder terug te keren naar het magazijn. Telkens wanneer de resterende lading onder een uur komt, zoekt u naar een set laadstations die zich binnen het bereik bevinden. U zoekt dus naar een laadstation wanneer de accu bijna leeg is. En u krijgt de grensinformatie voor het laadstationbereik terug.

Omdat het bedrijf bij voorkeur een balans tussen zuinigheid en snelheid hanteert bij het kiezen van routes, is het aangevraagde routeType eco. Met het volgende script wordt de API Routebereik ophalen van de routeringsservice van Azure Maps aangeroepen. Het maakt gebruik van parameters voor het verbruiksmodel van het voertuig. Met het script wordt het antwoord geparseerd om een veelhoekobject in de GeoJSON-indeling te maken, waarmee het maximumbereik van de auto wordt aangegeven.

U kunt de grenzen voor het bereik van het elektrische voertuig bepalen door het script in de volgende cel uit te voeren:

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={}&currentChargeInkWh={}&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

Nadat u het bereik (de isochroon) voor het elektrische voertuig hebt vastgesteld, kunt u zoeken naar laadstations binnen dat bereik.

Met het volgende script wordt de API Post-zoekopdracht binnen de geometrie van Azure Maps aangeroepen. Hiermee wordt gezocht naar laadstations voor elektrische voertuigen binnen de grenzen van het maximale bereik van de auto. Vervolgens wordt het antwoord door het script geparseerd naar een matrix van bereikbare locaties.

Voer het volgende script uit om te zoeken naar laadstations voor elektrische voertuigen binnen het bereik:

# 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)

Het bereik en de laadpunten uploaden

Het is handig om de laadstations en de grens voor het maximale bereik van het elektrische voertuig op een kaart te visualiseren. Volg de stappen die worden beschreven in het artikel Gegevensregister maken om de grensgegevens en laadstationsgegevens als geojson-objecten te uploaden naar uw Azure-opslagaccount en deze vervolgens te registreren in uw Azure Kaarten-account. Noteer de unieke id (udid)-waarde die u nodig hebt. U udid verwijst naar de geojson-objecten die u hebt geüpload naar uw Azure-opslagaccount vanuit uw broncode.

De laadstations en het bereik weergeven op een kaart

Nadat u de gegevens hebt geüpload naar het Azure-opslagaccount, roept u de Azure Kaarten Get Map Image-service aan. Via deze service worden de laadpunten en de maximaal bereikbare grens weergegeven op de statische kaartafbeelding 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)

path = "lcff3333|lw3|la0.80|fa0.35||udid-{}".format(rangeUdid)
pins = "custom|an15 53||udid-{}||https://raw.githubusercontent.com/Azure-Samples/AzureMapsCodeSamples/master/AzureMapsCodeSamples/Common/images/icons/ev_pin.png".format(poiUdid)

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))

A map showing the location range

Het optimale laadstation zoeken

Eerst wilt u alle mogelijke laadstations binnen het bereik bepalen. Vervolgens wilt u weten welke ervan kunnen worden bereikt binnen een minimale tijd.

Met het volgende script wordt de API Matrixroutering van Azure Maps aangeroepen. Hiermee wordt de opgegeven voertuiglocatie, de reistijd en de afstand tot elk laadstation geretourneerd. Met het script in de volgende cel wordt het antwoord geparseerd om het dichtstbijzijnde bereikbare laadstation qua tijd te vinden.

Als u wilt zoeken naar het dichtstbijzijnde laadstation dat kan worden bereikt in de kortste tijd, voert u het script in de volgende cel uit:

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

Nu u het dichtstbijzijnde laadstation hebt gevonden, kunt u de API Routebeschrijving ophalen aanroepen om de gedetailleerde route van de huidige locatie van het elektrische voertuig naar het laadstation op te vragen.

Voer het script in de volgende cel uit om de route naar het laadstation op te halen en het antwoord te parseren om een geoJSON-object te maken 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

Volg de stappen in het artikel Gegevensregister maken om de routegegevens te uploaden als een geojson-object naar uw Azure-opslagaccount en registreer deze vervolgens in uw Azure Kaarten-account om de routegegevens te visualiseren. Noteer de unieke id (udid)-waarde die u nodig hebt. U udid verwijst naar de geojson-objecten die u hebt geüpload naar uw Azure-opslagaccount vanuit uw broncode. Vervolgens roept u de renderingservice, de API Kaartafbeeldingen ophalen, aan om de route op de kaart weer te geven en te visualiseren.

Voer het volgende script uit om een afbeelding voor de weergegeven route op de kaart op te halen:

# Upload the route data to Azure Maps Data service .
routeUploadRequest = await session.post("https://atlas.microsoft.com/mapData?subscription-key={}&api-version=2.0&dataFormat=geojson".format(subscriptionKey), json = routeData)

udidRequestURI = routeUploadRequest.headers["Location"]+"&subscription-key={}".format(subscriptionKey)

while True:
    udidRequest = await (await session.get(udidRequestURI)).json()
    if 'udid' in udidRequest:
        break
    else:
        time.sleep(0.2)

udid = udidRequest["udid"]

destination = route[-1]

destination[1], destination[0] = destination[0], destination[1]

path = "lc0f6dd9|lw6||udid-{}".format(udid)
pins = "default|codb1818||{} {}|{} {}".format(str(currentLocation[1]),str(currentLocation[0]),destination[1],destination[0])


# Get boundaries for the bounding box.
minLat, maxLat = (float(destination[0]),currentLocation[0]) if float(destination[0])<currentLocation[0] else (currentLocation[0], float(destination[0]))
minLon, maxLon = (float(destination[1]),currentLocation[1]) if float(destination[1])<currentLocation[1] else (currentLocation[1], 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))

A map showing the route

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.

Als u meer wilt weten over de Azure Maps API's die in deze zelfstudie worden gebruikt, raadpleegt u:

Resources opschonen

Er zijn geen resources die moeten worden opgeruimd.

Volgende stappen

Voor meer informatie over Azure Notebooks, zie