Självstudie: Dirigera elfordon med hjälp Azure Notebooks (Python)

Azure Kartor är en portfölj med geospatiala tjänst-API:er som är inbyggda i Azure. Dessa API:er gör det möjligt för utvecklare, företag och ISV:er att utveckla platsmedvetna appar, IoT, mobilitet, logistik och tillgångsspårningslösningar.

Azure Kartor REST-API:er kan anropas från språk som Python och R för att möjliggöra geospatial dataanalys och maskininlärningsscenarier. Azure Kartor en robust uppsättning dirigerings-API:er som gör det möjligt för användare att beräkna vägar mellan flera datapunkter. Beräkningarna baseras på olika villkor, till exempel fordonstyp eller nåbart område.

I den här självstudien går du igenom hjälp för en drivrutin vars elbilsbatteri är lågt. Drivrutinen måste hitta den närmaste möjliga debiteringsstation från fordonets plats.

I de här självstudierna får du:

  • Skapa och kör Jupyter Notebook fil Azure Notebooks i molnet.
  • Anropa Azure Kartor REST API:er i Python.
  • Sök efter ett nåbart intervall baserat på elbilens förbrukningsmodell.
  • Sök efter elbilsladdningsstationer inom räckviddsintervallet eller isochrone.
  • Rendera den nåbara intervallgränsen och debiteringsstationerna på en karta.
  • Hitta och visualisera en väg till närmaste elbilsladdningsstation baserat på körtid.

Förutsättningar

  1. Skapa ett Azure Kartor kontooch välj prisnivån Gen 2 eller S1.
  2. Skaffa en primär prenumerationsnyckel, som även kallas primärnyckel eller prenumerationsnyckel.

Mer information om autentisering i Azure Kartor finns i Hantera autentisering i Azure Kartor.

Skapa ett Azure Notebooks projekt

Om du vill följa med i den här självstudien måste du skapa ett Azure Notebooks-projekt och ladda ned och köra Jupyter Notebook filen. Filen Jupyter Notebook Python-kod, som implementerar scenariot i den här självstudien. Skapa ett Azure Notebooks och ladda upp Jupyter Notebook dokument till det genom att göra följande:

  1. Gå till Azure Notebooks och logga in. Mer information finns i Snabbstart: Logga in och ange ett användar-ID.

  2. Längst upp på din offentliga profilsida väljer du Mina projekt.

    Knappen Mina projekt

  3. På sidan Mina projekt väljer du Nytt Project.

    Knappen Project nytt

  4. I fönstret Skapa ny Project anger du ett projektnamn och projekt-ID.

    Fönstret Skapa Project ny

  5. Välj Skapa.

  6. När projektet har skapats laddar du ned den här Jupyter Notebook-dokumentfilen från Azure Kartor Jupyter Notebook-lagringsplatsen.

  7. I projektlistan på sidan Mina projekt väljer du ditt projekt och väljer sedan Upload för att ladda upp Jupyter Notebook dokumentfilen.

    ladda upp Jupyter Notebook

  8. Upload filen från datorn och välj sedan Klar.

  9. När uppladdningen är klar visas filen på projektsidan. Dubbelklicka på filen för att öppna den som en Jupyter Notebook.

Försök att förstå de funktioner som implementeras i Jupyter Notebook fil. Kör koden, i Jupyter Notebook fil, en cell i taget. Du kan köra koden i varje cell genom att välja knappen Kör längst upp i Jupyter Notebook appen.

Knappen Kör

Installera paket på projektnivå

Om du vill köra koden Jupyter Notebook installerar du paketen på projektnivå genom att göra följande:

  1. Ladda ned requirements.txt från Azure Kartor Jupyter Notebook lagringsplatsoch ladda sedan upp den till projektet.

  2. På instrumentpanelen för projektet väljer du Project Inställningar.

  3. I Project Inställningar väljer du fliken Miljö och sedan Lägg till.

  4. Under Miljökonfigurationssteg gör du följande: a. I den första listrutan väljer du Requirements.txt.
    b. I den andra listrutan väljer du requirements.txt fil.
    c. I den tredje listrutan väljer du Python Version 3.6 som version.

  5. Välj Spara.

    Installera paket

Läsa in de moduler och ramverk som krävs

Om du vill läsa in alla nödvändiga moduler och ramverk kör du följande skript.

import time
import aiohttp
import urllib.parse
from IPython.display import Image, display

Begära den nåbara intervallgränsen

Ett paketleveransföretag har några elfordon i sin vagnpark. Under dagen måste elfordon debiteras på nytt utan att behöva gå tillbaka till lagret. Varje gång den återstående avgiften sjunker till mindre än en timme söker du efter en uppsättning debiteringsstationer som är inom ett räckviddsintervall. I princip söker du efter en debiteringsstation när batteriet har låg laddning. Och du får gränsinformation för det intervallet av debiteringsstationer.

Eftersom företaget föredrar att använda vägar som kräver en balans mellan ekonomi och hastighet är den begärda routeType en ekonomi. Följande skript anropar API:et Get Route Range för Azure Kartor routningstjänsten. Den använder parametrar för fordonets förbrukningsmodell. Skriptet parsar sedan svaret för att skapa ett polygonobjekt i geojson-formatet, som representerar bilens maximala nåbara intervall.

Kör skriptet i följande cell för att fastställa gränserna för elbilens nåbara intervall:

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
                   ]
                }
             }

Sök efter laddning av elfordon inom det nåbara intervallet

När du har fastställt det nåbara intervallet (isochrone) för elfordonet kan du söka efter laddstationer inom det intervallet.

Följande skript anropar Azure Kartor Post Search Inside Geometry API. Den söker efter laddning stationer för elfordon, inom gränserna för bilens högsta nåbara intervall. Sedan parsar skriptet svaret till en matris med nåbara platser.

Kör följande skript för att söka efter elbilsladdningsstationer inom det nåbara intervallet:

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

Upload det nåbara intervallet och debiteringspunkterna till Azure-Kartor tjänsten Data

På en karta vill du visualisera laddstationerna och gränsen för det högsta nåbara intervallet för elfordonet. Det gör du genom att ladda upp gränsdata och debiteringsdata för stationer som geojson-objekt till Azure Kartor tjänsten Data. Använd API:et data Upload.

Om du vill ladda upp gräns- och debiteringspunktdata till Azure Kartor tjänsten Data kör du följande två celler:

rangeData = {
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          polyBounds
        ]
      }
    }
  ]
}

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

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

while True:
    getRangeUdid = await (await session.get(rangeUdidRequest)).json()
    if 'udid' in getRangeUdid:
        break
    else:
        time.sleep(0.2)
rangeUdid = getRangeUdid["udid"]
poiData = {
    "type": "FeatureCollection",
    "features": [
      {
        "type": "Feature",
        "properties": {},
        "geometry": {
            "type": "MultiPoint",
            "coordinates": reachableLocations
        }
    }
  ]
}

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

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

while True:
    getPoiUdid = await (await session.get(poiUdidRequest)).json()
    if 'udid' in getPoiUdid:
        break
    else:
        time.sleep(0.2)
poiUdid = getPoiUdid["udid"]

Rendera debiteringsstationerna och det nåbara intervallet på en karta

När du har laddat upp data till datatjänsten anropar du Azure Kartor Get Map Image Service. Den här tjänsten används för att rendera debiteringspunkterna och den maximala nåbara gränsen på den statiska kartbilden genom att köra följande skript:

# 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=1.0&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))

En karta som visar platsintervallet

Hitta den optimala debiteringsstationen

Först vill du fastställa alla potentiella debiteringsstationer inom det nåbara intervallet. Sedan vill du veta vilka av dem som kan nås på kort tid.

Följande skript anropar Azure Kartor Matrix Routing API. Den returnerar den angivna fordonsplatsen, restiden och avståndet till varje laddstation. Skriptet i nästa cell parsar svaret för att hitta närmaste nåbara debiteringsstation med avseende på tid.

Om du vill hitta den närmaste nåbara debiteringsstation som kan nås på minsta tid kör du skriptet i följande cell:

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)

Beräkna vägen till närmaste debiteringsstation

Nu när du har hittat den närmaste debiteringsstationen kan du anropa API:et Get Route Directions för att begära den detaljerade rutten från elbilens aktuella plats till laddningsstationen.

Kör skriptet i följande cell för att hämta vägen till debiteringsstationen och parsa svaret för att skapa ett geojson-objekt som representerar vägen:

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

Visualisera vägen

För att visualisera vägen laddar du först upp vägdata som ett geojson-objekt till Azure Kartor tjänsten Data . Det gör du med Azure Kartor Data Upload API. Anropa sedan renderingstjänsten, GET Map Image API, för att rendera rutten på kartan och visualisera den.

Kör följande skript för att hämta en avbildning för den renderade vägen på kartan:

# 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=1.0&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))

En karta som visar rutten

I den här självstudien har du lärt dig att anropa Azure Kartor REST API:er direkt och visualisera Azure Kartor data med hjälp av Python.

Om du vill utforska Azure Kartor-API:er som används i den här självstudien kan du se:

Rensa resurser

Det finns inga resurser som kräver rensning.

Nästa steg

Mer information om Azure Notebooks finns i