Udostępnij za pośrednictwem


Samouczek: kierowanie pojazdów elektrycznych przy użyciu usługi Azure Notebooks (Python)

Usługa Azure Maps to portfolio interfejsów API usług geoprzestrzennych zintegrowanych z platformą Azure, co umożliwia deweloperom tworzenie aplikacji obsługujących lokalizację dla różnych scenariuszy, takich jak IoT, mobilność i śledzenie zasobów.

Interfejsy API REST usługi Azure Maps obsługują języki takie jak Python i R na potrzeby analizy danych geoprzestrzennych i uczenia maszynowego, oferując niezawodne interfejsy API routingu do obliczania tras na podstawie warunków, takich jak typ pojazdu lub dostępny obszar.

Ten samouczek przeprowadzi użytkowników przez routing pojazdów elektrycznych przy użyciu interfejsów API usługi Azure Maps wraz z notesami Jupyter Notebook w programie VS Code i języku Python, aby znaleźć najbliższą stację ładowania, gdy bateria jest niska.

Ten samouczek obejmuje następujące kroki:

  • Tworzenie i uruchamianie notesu Jupyter w programie VS Code.
  • Wywoływanie interfejsów API REST usługi Azure Maps w języku Python.
  • Wyszukaj dostępny zakres na podstawie modelu zużycia pojazdu elektrycznego.
  • Wyszukaj stacje ładowania pojazdów elektrycznych w zasięgu osiągalnym lub isochrone.
  • Renderuj osiągalne stacje granic i ładowania na mapie.
  • Znajdź i wizualizuj trasę do najbliższej stacji ładowania pojazdów elektrycznych na podstawie czasu jazdy.

Wymagania wstępne

Uwaga

Aby uzyskać więcej informacji na temat uwierzytelniania w usłudze Azure Maps, zobacz Zarządzanie uwierzytelnianiem w usłudze Azure Maps.

Instalowanie pakietów na poziomie projektu

Projekt EV Routing i Reachable Range ma zależności od bibliotek aiohttp i IPython python. Te elementy można zainstalować w terminalu programu Visual Studio przy użyciu narzędzia:

pip install aiohttp
pip install ipython

Otwieranie notesu Jupyter w programie Visual Studio Code

Pobierz, a następnie otwórz notes używany w tym samouczku:

  1. Otwórz plik EVrouting.ipynb w repozytorium AzureMapsJupyterSamples w usłudze GitHub.

  2. Wybierz przycisk Pobierz nieprzetworzone pliki w prawym górnym rogu ekranu, aby zapisać plik lokalnie.

    Zrzut ekranu przedstawiający sposób pobierania pliku notesu o nazwie EVrouting.ipynb z repozytorium GitHub.

  3. Otwórz pobrany notes w programie Visual Studio Code, klikając go prawym przyciskiem myszy, a następnie wybierając polecenie Otwórz w > programie Visual Studio Code lub za pośrednictwem Eksplorator plików programu VS Code.

Ładowanie wymaganych modułów i struktur

Po dodaniu kodu możesz uruchomić komórkę przy użyciu ikony Uruchom po lewej stronie komórki, a dane wyjściowe zostaną wyświetlone poniżej komórki kodu.

Uruchom następujący skrypt, aby załadować wszystkie wymagane moduły i struktury.

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

Zrzut ekranu przedstawiający sposób pobierania pierwszej komórki w notesie zawierającej wymagane instrukcje importu z wyróżnionym przyciskiem uruchamiania.

Zażądaj granicy osiągalnego zakresu

Firma dostarczająca pakiety obsługuje flotę, która obejmuje niektóre pojazdy elektryczne. Te pojazdy muszą być ładowane w ciągu dnia bez powrotu do magazynu. Gdy pozostałe opłaty spadną poniżej godziny, wyszukiwanie jest przeprowadzane w celu znalezienia stacji ładowania w zasięgu osiągalnym. Następnie uzyskuje się informacje graniczne dotyczące zakresu tych stacji ładowania.

Wniosek jest ekologicznyrouteType, aby zrównoważyć gospodarkę i szybkość. Poniższy skrypt wywołuje interfejs API Pobierania zakresu tras usługi routingu Azure Maps przy użyciu parametrów związanych z modelem zużycia pojazdu. Następnie skrypt analizuje odpowiedź, aby utworzyć obiekt wielokątny w formacie GeoJSON, reprezentując maksymalny zakres osiągalny samochodu.

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

Wyszukiwanie stacji ładowania pojazdów elektrycznych w zasięgu osiągalnym

Po określeniu zasięgu pojazdu elektrycznego (izochrone) można wyszukać stacje ładowania w tym obszarze.

Poniższy skrypt używa interfejsu API wyszukiwania postów w usłudze Azure Maps wewnątrz geometrii , aby znaleźć stacje ładowania w maksymalnym zasięgu pojazdu. Następnie analizuje odpowiedź w tablicę osiągalnych lokalizacji.

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

Renderowanie stacji ładowania i osiągalny zakres na mapie

Wywołaj usługę Azure Maps Get Map Image , aby renderować punkty ładowania i maksymalną granicę osiągalną na obrazie mapy statycznej, uruchamiając następujący skrypt:

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

Zrzut ekranu przedstawiający zakres lokalizacji.

Znajdowanie optymalnej stacji ładowania

Najpierw zidentyfikuj wszystkie potencjalne stacje ładowania w zasięgu osiągalnego pojazdu. Następnie określ, do których z tych stacji można uzyskać dostęp w najkrótszym możliwym czasie.

Poniższy skrypt wywołuje interfejs API routingu macierzy usługi Azure Maps. Zwraca lokalizację pojazdu, czas podróży i odległość do każdej stacji ładowania. Kolejny skrypt analizuje tę odpowiedź, aby zidentyfikować najbliższą stację ładowania, która może być osiągnięta w najmniejszym czasie.

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)

Obliczanie trasy do najbliższej stacji ładowania

Po zlokalizowaniu najbliższej stacji ładowania użyj interfejsu API Get Route Directions , aby uzyskać szczegółowe wskazówki z bieżącej lokalizacji pojazdów. Uruchom skrypt w następnej komórce, aby wygenerować i przeanalizować obiekt GeoJSON reprezentujący trasę.

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

Wizualizowanie trasy

Aby zwizualizować trasę, użyj interfejsu API pobierania obrazu mapy, aby go renderować na mapie.

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

Zrzut ekranu przedstawiający mapę przedstawiającą trasę.

W tym samouczku przedstawiono sposób bezpośredniego wywoływania interfejsów API REST usługi Azure Maps i wizualizowania danych usługi Azure Maps przy użyciu języka Python.

Aby uzyskać więcej informacji na temat interfejsów API usługi Azure Maps używanych w tym samouczku, zobacz:

Aby uzyskać pełną listę interfejsów API REST usługi Azure Maps, zobacz Interfejsy API REST usługi Azure Maps.

Następne kroki