Oktatóanyag: Elektromos járművek irányítása Jupyter Notebooks (Python) használatával
Az Azure Maps az Azure-ba integrált térinformatikai szolgáltatási API-k portfóliója, amely lehetővé teszi a fejlesztők számára, hogy helyérzékeny alkalmazásokat hozzanak létre különböző forgatókönyvekhez, például az IoT-hez, a mobilitáshoz és az eszközkövetéshez.
Az Azure Maps REST API-k olyan nyelveket támogatnak, mint a Python és az R a térinformatikai adatelemzéshez és a gépi tanuláshoz, és robusztus útválasztási API-kat kínálnak az útvonalak olyan feltételek alapján történő kiszámításához, mint a járműtípus vagy az elérhető terület.
Ez az oktatóanyag végigvezeti a felhasználókat az elektromos járművek útválasztásán az Azure Maps API-kkal, valamint a VS Code-ban és a Pythonban található Jupyter Notebookokkal, hogy megtalálják a legközelebbi töltőállomást, ha az akkumulátor alacsony.
Az oktatóanyag során az alábbi lépéseket fogja végrehajtani:
- Jupyter-jegyzetfüzet létrehozása és futtatása a VS Code-ban.
- Azure Maps REST API-k meghívása Pythonban.
- Keressen egy elérhető tartományt az elektromos jármű fogyasztási modellje alapján.
- Keressen elektromos jármű töltőállomásokat az elérhető tartományon belül, vagy isochrone.
- Térképen ábrázolja az elérhető tartományhatárt és a töltőállomásokat.
- Keresse meg és vizualizálja a legközelebbi elektromos jármű töltőállomására vezető útvonalat a meghajtóidő alapján.
Előfeltételek
- Azure Maps-fiók
- Előfizetési kulcs
- Visual Studio Code
- A Jupyter Notebooks működésének ismerete a VS Code-ban
- A környezet úgy van beállítva, hogy a Pythonnal működjön a Jupyter Notebooksban. További információ: A környezet beállítása.
Feljegyzés
Az Azure Maps hitelesítésével kapcsolatos további információkért tekintse meg a hitelesítés kezelését az Azure Mapsben.
Projektszintű csomagok telepítése
Az EV Routing and Reachable Range projekt függőségekkel rendelkezik az aiohttp és az IPython Python-kódtáraktól. Ezeket telepítheti a Visual Studio terminálba a pip használatával:
pip install aiohttp
pip install ipython
Jupyter Notebook megnyitása a Visual Studio Code-ban
Töltse le, majd nyissa meg az oktatóanyagban használt jegyzetfüzetet:
Nyissa meg az EVrouting.ipynb fájlt a GitHub AzureMapsJupyterSamples adattárában.
A fájl helyi mentéséhez válassza a képernyő jobb felső sarkában található Nyers fájl letöltése gombot.
Nyissa meg a letöltött jegyzetfüzetet a Visual Studio Code-ban. Ehhez kattintson a jobb gombbal a fájlra, majd válassza a Megnyitás a Visual Studio Code-tal >lehetőséget, vagy a VS Code Fájlkezelő.
A szükséges modulok és keretrendszerek betöltése
A kód hozzáadása után futtathat egy cellát a cella bal oldalán található Futtatás ikonnal, és a kimenet a kódcella alatt jelenik meg.
Futtassa a következő szkriptet az összes szükséges modul és keretrendszer betöltéséhez.
import time
import aiohttp
import urllib.parse
from IPython.display import Image, display
Az elérhető tartomány határának kérése
A csomagkézbesítési vállalat olyan flottát üzemeltet, amely elektromos járműveket is tartalmaz. Ezeket a járműveket a nap folyamán fel kell tölteni anélkül, hogy vissza kellene térni a raktárba. Ha a fennmaradó díj egy óra alatt csökken, keresés történik a töltőállomások elérhető tartományon belüli megkereséséhez. Ezután lekértük a töltőállomások tartományára vonatkozó határinformációkat.
A kért routeType
öko a gazdaság és a sebesség egyensúlya érdekében. Az alábbi szkript meghívja az Azure Maps útválasztási szolgáltatás Útvonaltartomány API-jának lekérését a jármű fogyasztási modelljéhez kapcsolódó paraméterek használatával. A szkript ezután elemzi a választ egy GeoJSON formátumú sokszögobjektum létrehozásához, amely az autó maximális elérhető tartományát jelöli.
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
]
}
}
Elektromos járművek töltőállomásainak keresése az elérhető tartományon belül
Az elektromos jármű elérhető tartományának (isochrone) meghatározása után az adott területen található töltőállomásokat is megkeresheti.
Az alábbi szkript az Azure Maps Post Search Inside Geometry API-val keresi meg a töltőállomásokat a jármű maximális elérhető tartományán belül. Ezután a választ egy elérhető helyek tömbjeként elemzi.
# 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)
A töltőállomások és az elérhető tartomány megjelenítése térképen
Az alábbi szkript futtatásával hívja meg az Azure Maps Get Map Image szolgáltatást a töltési pontok és a maximálisan elérhető határ megjelenítéséhez a statikus térképképen:
# 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))
Az optimális töltőállomás megkeresése
Először is azonosítsa az összes lehetséges töltőállomást a jármű elérhető tartományán belül. Ezután határozza meg, hogy ezek közül az állomások közül melyik érhető el a lehető legrövidebb időn belül.
Az alábbi szkript meghívja az Azure Maps Matrix Routing API-t. Visszaadja a jármű helyét, utazási idejét és távolságát az egyes töltőállomásokhoz. A következő szkript elemzi ezt a választ, hogy azonosítsa a legközelebbi töltőállomást, amely a legkisebb idő alatt elérhető.
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)
A legközelebbi töltőállomásra vezető útvonal kiszámítása
A legközelebbi töltőállomás keresése után az Útvonaltervek lekérése API-val részletes útvonalakat szerezhet be a járművek aktuális helyéről. Futtassa a szkriptet a következő cellában az útvonalat képviselő GeoJSON-objektum létrehozásához és elemzéséhez.
# 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
}
Az útvonal megjelenítése
Az útvonal megjelenítéséhez használja a Térkép képe API-t a térképen való megjelenítéshez.
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))
Ebben az oktatóanyagban megtanulta, hogyan hívhatja meg közvetlenül az Azure Maps REST API-kat, és hogyan jelenítheti meg az Azure Maps-adatokat a Python használatával.
Az oktatóanyagban használt Azure Maps API-kkal kapcsolatos további információkért lásd:
- Útvonaltervek lekérése
- Útvonaltartomány lekérése
- Útvonal utáni mátrix
- Keresés közzététele a geometrián belül
- Renderelés – Térkép képének lekérése
Az Azure Maps REST API-k teljes listáját az Azure Maps REST API-kban találja.