Kurz: Směrování elektrických vozidel pomocí poznámkových bloků Jupyter (Python)
Azure Maps je portfolio geoprostorových rozhraní API služeb integrované do Azure, které vývojářům umožňuje vytvářet aplikace pracující s umístěním pro různé scénáře, jako je IoT, mobilita a sledování prostředků.
Rozhraní REST API služby Azure Maps podporují jazyky, jako je Python a R pro analýzu geoprostorových dat a strojové učení, a nabízí robustní rozhraní API směrování pro výpočet tras na základě podmínek, jako je typ vozidla nebo dosažitelná oblast.
Tento kurz provede uživatele směrováním elektrických vozidel pomocí rozhraní API služby Azure Maps spolu s aplikacemi Jupyter Notebooks ve VS Code a Pythonu, aby našli nejbližší nabíjecí stanici, když je baterie nízká.
V tomto kurzu:
- Vytvořte a spusťte poznámkový blok Jupyter v editoru VS Code.
- Volání rozhraní REST API služby Azure Maps 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 Maps
- Klíč předplatného
- Visual Studio Code
- Pracovní znalost poznámkových bloků Jupyter v editoru VS Code
- Prostředí nastavené pro práci s Pythonem v poznámkových blocích Jupyter Další informace najdete v tématu Nastavení prostředí.
Poznámka:
Další informace o ověřování ve službě Azure Maps najdete v tématu správa ověřování v Azure Maps.
Instalace balíčků na úrovni projektu
Projekt SMĚROVÁNÍ EV a dosažitelného rozsahu má závislosti na knihovnách pythonu Aiohttp a IPython . Můžete je nainstalovat do terminálu sady Visual Studio pomocí nástroje pip:
pip install aiohttp
pip install ipython
Otevření poznámkového bloku Jupyter v editoru Visual Studio Code
Stáhněte si poznámkový blok použitý v tomto kurzu:
Otevřete soubor EVrouting.ipynb v úložišti AzureMapsJupyterSamples na GitHubu.
Výběrem tlačítka Stáhnout nezpracovaný soubor v pravém horním rohu obrazovky soubor uložte místně.
Otevřete stažený poznámkový blok v editoru Visual Studio Code tak, že kliknete pravým tlačítkem myši na soubor a pak vyberete Otevřít v > editoru Visual Studio Code nebo v Průzkumník souborů editoru VS Code.
Načtení požadovaných modulů a architektur
Po přidání kódu můžete buňku spustit pomocí ikony Spustit vlevo od buňky a výstup se zobrazí pod buňkou s kódem.
Spuštěním následujícího skriptu načtěte všechny požadované moduly a architektury.
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 provozuje flotilu, která zahrnuje některá elektrická vozidla. Tato vozidla musí být dobíjená během dne bez návratu do skladu. Když zbývající poplatek klesne pod hodinu, provede se hledání a vyhledá nabíjecí stanice v dosažitelné vzdálenosti. Informace o hranicích pro rozsah těchto nabíjecích stanic se pak získávají.
Požadováno routeType
je eco pro vyvážení ekonomiky a rychlosti. Následující skript volá rozhraní API get Route Range služby Azure Maps pomocí parametrů souvisejících s modelem spotřeby vozidla. Skript pak parsuje odpověď na vytvoření mnohoúhelníku ve formátu GeoJSON, který představuje maximální dosažitelný rozsah vozu.
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 elektrického vozidla (isochron) můžete vyhledat nabíjecí stanice v této oblasti.
Následující skript používá rozhraní API služby Azure Maps Post Search Inside Geometry k vyhledání nabíjecích stanic v maximálním dosahu vozidla. Pak parsuje odpověď do pole dosažitelných umístění.
# 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)
Vykreslení nabíjecích stanic a dosažitelného rozsahu na mapě
Voláním služby Azure Maps Get Map Image vykreslíte nabíjecí body a maximální dosažitelnou hranici 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)
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))
Vyhledání optimální nabíjecí stanice
Nejprve identifikujte všechny potenciální nabíjecí stanice v dosahu vozidla. Dále určete, které z těchto stanic lze získat přístup v nejkratší možné době.
Následující skript volá rozhraní API pro směrování matice Azure Maps. Vrátí polohu, dobu jízdy a vzdálenost vozidla do každé nabíjecí stanice. Následující skript analyzuje tuto odpověď tak, aby identifikoval nejbližší nabíjecí stanici, která se dá dosáhnout v nejmenším časovém intervalu.
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
Po vyhledání nejbližší nabíjecí stanice použijte rozhraní API Get Route Directions API k získání podrobných pokynů z aktuální polohy vozidel. Spuštěním skriptu v další buňce vygenerujte a parsujte objekt GeoJSON představující trasu.
# 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 vizualizovat trasu, vykreslíte ji na mapě pomocí rozhraní API Získat mapové obrázky .
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))
V tomto kurzu jste zjistili, jak volat rozhraní REST API služby Azure Maps přímo a vizualizovat data Azure Maps pomocí Pythonu.
Další informace o rozhraních API služby Azure Maps používaných v tomto kurzu najdete tady:
- Získání navigačních pokynů pro trasu
- Získání rozsahu tras
- Matice po směrování
- Post Search Inside Geometry
- Vykreslení – získání obrázku mapy
Úplný seznam rozhraní REST API služby Azure Maps najdete v tématu Rozhraní REST API služby Azure Maps.