Kurz: Směrování elektrických vozidel pomocí Azure Notebooks (Python)
Azure Mapy je portfolio rozhraní API geoprostorových služeb, která jsou nativně integrovaná do Azure. Tato rozhraní API umožňují vývojářům, podnikům a výrobcům softwaru vyvíjet aplikace pracující s umístěním, IoT, mobilitu, logistiku a řešení pro sledování aktiv.
Rozhraní AZURE Mapy REST API je možné volat z jazyků, jako je Python a R, a umožnit tak geoprostorové analýzy dat a scénáře strojového učení. Azure Mapy nabízí robustní sadu rozhraní API směrování, která uživatelům umožňují vypočítat trasy mezi několika datovými body. Výpočty vycházejí z různých podmínek, jako je typ vozidla nebo dosažitelná oblast.
V tomto kurzu budete pomáhat řidiče, jehož elektrické vozidlo baterie je nízké. Řidič musí najít nejbližší možnou nabíjecí stanici z místa vozidla.
V tomto kurzu:
- Vytvořte a spusťte soubor Jupyter Notebook v Azure Notebooks v cloudu.
- Volání rozhraní REST API Azure Mapy v Pythonu
- Vyhledejte dosažitelný rozsah na základě modelu spotřeby elektrického vozidla.
- Vyhledejte nabíjecí stanice elektrických vozidel v dosahu nebo isochronu.
- Vykreslení hranice dosažitelného rozsahu a nabíjecích stanic na mapě
- Najděte a vizualizujete trasu k nejbližší nabíjecí stanici pro elektrické vozidlo na základě doby jízdy.
Požadavky
- Účet Azure Mapy
- Klíč předplatného
- Účet úložiště Azure
Poznámka:
Další informace o ověřování v Azure Mapy najdete v tématu správa ověřování v Azure Mapy.
Vytvoření projektu Azure Notebooks
Pokud chcete postupovat podle tohoto kurzu, musíte vytvořit projekt Azure Notebooks a stáhnout a spustit soubor Jupyter Notebook. Soubor Jupyter Notebook obsahuje kód Pythonu, který implementuje scénář v tomto kurzu. Pokud chcete vytvořit projekt Azure Notebooks a nahrát do něj dokument Jupyter Notebook, postupujte takto:
Přejděte do Služby Azure Notebooks a přihlaste se. Další informace najdete v tématu Rychlý start: Přihlášení a nastavení ID uživatele.
V horní části stránky veřejného profilu vyberte Moje projekty.
Na stránce Moje projekty vyberte Nový projekt.
V podokně Vytvořit nový projekt zadejte název projektu a ID projektu.
Vyberte Vytvořit.
Po vytvoření projektu si stáhněte tento soubor dokumentu Jupyter Notebook z úložiště Azure Mapy Jupyter Notebook.
V seznamu projektů na stránce Moje projekty vyberte projekt a pak vyberte Nahrát a nahrajte soubor dokumentu Jupyter Notebook.
Nahrajte soubor z počítače a pak vyberte Hotovo.
Po úspěšném dokončení nahrávání se soubor zobrazí na stránce projektu. Poklikáním na soubor ho otevřete jako Jupyter Notebook.
Pokuste se porozumět funkcím implementovaným v souboru Jupyter Notebook. Spusťte kód v souboru Jupyter Notebook po jedné buňce. Kód v každé buňce můžete spustit výběrem tlačítka Spustit v horní části aplikace Jupyter Notebook.
Instalace balíčků na úrovni projektu
Pokud chcete kód spustit v aplikaci Jupyter Notebook, nainstalujte balíčky na úrovni projektu pomocí následujících kroků:
Stáhněte si soubor requirements.txt z úložiště Azure Mapy Jupyter Notebook a pak ho nahrajte do projektu.
Na řídicím panelu projektu vyberte Project Nastavení.
V podokně Nastavení projektu vyberte kartu Prostředí a pak vyberte Přidat.
V části Kroky nastavení prostředí proveďte následující kroky: a. V prvním rozevíracím seznamu vyberte Requirements.txt.
b. V druhém rozevíracím seznamu vyberte váš soubor requirements.txt .
c. Ve třetím rozevíracím seznamu jako vaši verzi vyberte Python verze 3.6 .Zvolte Uložit.
Načtení požadovaných modulů a architektur
Pokud chcete načíst všechny požadované moduly a architektury, spusťte následující skript.
import time
import aiohttp
import urllib.parse
from IPython.display import Image, display
Vyžádání hranice dosažitelného rozsahu
Společnost pro doručování zásilek má ve své flotile několik elektrických vozidel. Během dne musí být elektrická vozidla dobíjená, aniž by se museli vrátit do skladu. Pokaždé, když zbývající poplatek klesne na méně než hodinu, vyhledáte sadu nabíjecích stanic, které jsou v dosahu. V podstatě hledáte nabíjecí stanici, když je baterie nabitá. A získáte informace o hranicích pro tento rozsah nabíjecích stanic.
Vzhledem k tomu, že společnost preferuje používání tras, které vyžadují rovnováhu ekonomiky a rychlosti, je požadovaný typ trasy eco. Následující skript volá rozhraní API get Route Range služby Azure Mapy routing. Používá parametry pro model spotřeby vozidla. Skript pak parsuje odpověď na vytvoření mnohoúhelníku geojsonového formátu, který představuje maximální dosažitelný rozsah vozu.
Chcete-li určit hranice dosažitelného rozsahu elektrického vozidla, spusťte skript v následující buňce:
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
]
}
}
Vyhledání nabíjecích stanic pro elektrické vozidlo v dosahu
Po určení dosažitelného rozsahu (isochron) pro elektrické vozidlo můžete vyhledat nabíjecí stanice v daném rozsahu.
Následující skript volá rozhraní AZURE Mapy Post Search Inside Geometry API. Hledá nabíjecí stanice pro elektrické vozidlo v rámci hranice maximálního dosažitelného rozsahu auta. Pak skript parsuje odpověď na pole dosažitelných umístění.
Pokud chcete vyhledat nabíjecí stanice elektrických vozidel v dosahu, spusťte následující skript:
# 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)
Nahrání dostupného rozsahu a nabíjecích bodů
Je užitečné vizualizovat nabíjecí stanice a hranici maximálního dosažitelného rozsahu elektrického vozidla na mapě. Postupujte podle kroků uvedených v článku Jak vytvořit registr dat, abyste nahráli data hranic a nabíjecí stanice jako geojsonové objekty do účtu úložiště Azure a pak je zaregistrovali ve svém účtu Azure Mapy. Nezapomeňte si poznamenat jedinečnou hodnotu identifikátoru (udid
) a budete ji potřebovat. Na udid
objekty geojson, které jste nahráli do účtu úložiště Azure, odkazujete ze zdrojového kódu.
Vykreslení nabíjecích stanic a dosažitelného rozsahu na mapě
Po nahrání dat do účtu úložiště Azure zavolejte službu Azure Mapy Get Map Image service. Tato služba slouží k vykreslení nabíjecích bodů a maximální dosažitelné hranice na obrázku statické mapy spuštěním následujícího skriptu:
# 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))
Vyhledání optimální nabíjecí stanice
Nejprve chcete určit všechny potenciální nabíjecí stanice v dosahu. Pak chcete vědět, které z nich lze dosáhnout v minimálním časovém intervalu.
Následující skript volá rozhraní API pro směrování matice Azure Mapy. Vrátí zadanou polohu vozidla, dobu jízdy a vzdálenost do každé nabíjecí stanice. Skript v další buňce analyzuje odpověď a vyhledá nejbližší dosažitelnou nabíjecí stanici s ohledem na čas.
Pokud chcete najít nejbližší dosažitelnou nabíjecí stanici, která se dá dosáhnout v co nejmenším čase, spusťte skript v následující buňce:
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)
Výpočet trasy k nejbližší nabíjecí stanici
Teď, když jste našli nejbližší nabíjecí stanici, můžete zavolat rozhraní API Get Route Directions a požádat o podrobnou trasu z aktuální polohy elektrického vozidla do nabíjecí stanice.
Pokud chcete získat trasu do nabíjecí stanice a parsovat odpověď na vytvoření objektu geojson, který představuje trasu, spusťte skript v následující buňce:
# 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
}
Vizualizace trasy
Pokud chcete trasu vizualizovat, postupujte podle kroků popsaných v článku Vytvoření registru dat a nahrajte směrovací data jako objekt geojson do účtu úložiště Azure a pak je zaregistrujte ve svém účtu Azure Mapy. Nezapomeňte si poznamenat jedinečnou hodnotu identifikátoru (udid
) a budete ji potřebovat. Na udid
objekty geojson, které jste nahráli do účtu úložiště Azure, odkazujete ze zdrojového kódu. Potom zavolejte vykreslovací službu, získejte rozhraní API mapového obrázku, abyste trasu vykreslili na mapě a vizualizovali ji.
Pokud chcete získat obrázek vykreslené trasy na mapě, spusťte následující skript:
# 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))
V tomto kurzu jste se naučili volat rozhraní REST API Azure Mapy přímo a vizualizovat data Mapy Azure pomocí Pythonu.
Pokud chcete prozkoumat rozhraní API azure Mapy, která se používají v tomto kurzu, podívejte se na:
- Získání rozsahu tras
- Post Search Inside Geometry
- Vykreslení – získání obrázku mapy
- Matice po směrování
- Získání navigačních pokynů pro trasu
- Rozhraní REST API služby Azure Mapy
Vyčištění prostředků
Nejsou k dispozici žádné prostředky, které by vyžadovaly vyčištění.
Další kroky
Další informace o službě Azure Notebooks najdete v tématu