Tutorial: Merutekan kendaraan listrik dengan menggunakan Notebooks (Python)
Azure Maps adalah portofolio API layanan geospasial yang terintegrasi ke Azure, memungkinkan pengembang membuat aplikasi yang sadar lokasi untuk berbagai skenario seperti IoT, mobilitas, dan pelacakan aset.
REST API Azure Maps mendukung bahasa seperti Python dan R untuk analisis data geospasial dan pembelajaran mesin, menawarkan API perutean yang kuat untuk menghitung rute berdasarkan kondisi seperti jenis kendaraan atau area yang dapat dijangkau.
Tutorial ini memandu pengguna melalui perutean kendaraan listrik menggunakan API Azure Maps bersama dengan Jupyter Notebooks di VISUAL Code dan Python untuk menemukan stasiun pengisian daya terdekat ketika baterai rendah.
Dalam tutorial ini, Anda akan:
- Buat dan jalankan Jupyter Notebook di Visual Studio Code.
- Panggil REST API Azure Maps dengan Python.
- Cari jarak yang dapat dijangkau berdasarkan model konsumsi kendaraan listrik.
- Cari stasiun pengisian kendaraan listrik dalam jangkauan yang dapat dijangkau, atau isochrone.
- Render batas jarak yang dapat dijangkau dan stasiun pengisian daya pada peta.
- Temukan dan visualisasikan rute ke stasiun pengisian kendaraan listrik terdekat berdasarkan waktu berkendara.
Prasyarat
- Akun Azure Maps
- Kunci langganan
- Visual Studio Code
- Pengetahuan kerja tentang Jupyter Notebooks di Visual Studio Code
- Lingkungan disiapkan untuk bekerja dengan Python di Jupyter Notebooks. Untuk informasi selengkapnya, lihat Menyiapkan lingkungan Anda.
Catatan
Untuk informasi selengkapnya tentang autentikasi di Azure Maps, lihat mengelola autentikasi di Azure Maps.
Memasang paket tingkat proyek
Proyek Perutean EV dan Rentang yang Dapat Dijangkau memiliki dependensi pada pustaka python aiohttp dan IPython . Anda dapat menginstalnya di terminal Visual Studio menggunakan pip:
pip install aiohttp
pip install ipython
Buka Jupyter Notebook di Visual Studio Code
Unduh lalu buka Notebook yang digunakan dalam tutorial ini:
Buka file EVrouting.ipynb di repositori AzureMapsJupyterSamples di GitHub.
Pilih tombol Unduh file mentah di sudut kanan atas layar untuk menyimpan file secara lokal.
Buka Notebook yang diunduh di Visual Studio Code dengan mengklik kanan file lalu pilih Buka dengan > Visual Studio Code, atau melalui File Explorer Visual Studio Code.
Memuat modul dan kerangka kerja yang diperlukan
Setelah kode ditambahkan, Anda dapat menjalankan sel menggunakan ikon Jalankan di sebelah kiri sel dan output ditampilkan di bawah sel kode.
Jalankan skrip berikut untuk memuat semua modul dan kerangka kerja yang diperlukan.
import time
import aiohttp
import urllib.parse
from IPython.display import Image, display
Meminta batas jarak yang dapat dijangkau
Perusahaan pengiriman paket mengoperasikan armada yang mencakup beberapa kendaraan listrik. Kendaraan ini perlu diisi ulang pada siang hari tanpa kembali ke gudang. Ketika sisa biaya turun di bawah satu jam, pencarian dilakukan untuk menemukan stasiun pengisian daya dalam rentang yang dapat dijangkau. Informasi batas untuk rentang stasiun pengisian daya ini kemudian diperoleh.
Yang diminta adalah eko untuk menyeimbangkan routeType
ekonomi dan kecepatan. Skrip berikut memanggil Get Route Range API dari layanan perutean Azure Maps, menggunakan parameter yang terkait dengan model konsumsi kendaraan. Skrip kemudian mengurai respons untuk membuat objek poligon dalam format GeoJSON, mewakili rentang maksimum mobil yang dapat dijangkau.
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
]
}
}
Mencari stasiun pengisian kendaraan listrik dalam jarak yang dapat dijangkau
Setelah menentukan rentang kendaraan listrik yang dapat dijangkau (isochrone), Anda dapat mencari stasiun pengisian daya di dalam area tersebut.
Skrip berikut menggunakan Azure Maps Post Search Inside Geometry API untuk menemukan stasiun pengisian daya dalam rentang maksimum kendaraan yang dapat dijangkau. Kemudian menguraikan respons ke dalam array lokasi yang dapat dijangkau.
# 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)
Merender stasiun pengisian daya dan jarak yang dapat dijangkau di peta
Panggil layanan Azure Maps Get Map Image untuk merender titik pengisian daya dan batas maksimum yang dapat dijangkau pada gambar peta statis dengan menjalankan skrip berikut:
# 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))
Menemukan stasiun pengisian daya yang optimal
Pertama, identifikasi semua stasiun pengisian daya potensial dalam jangkauan kendaraan yang dapat dijangkau. Selanjutnya, tentukan stasiun mana yang dapat diakses dalam waktu sesingkat mungkin.
Skrip berikut memanggil API Perutean Matriks Azure Maps. Ini mengembalikan lokasi kendaraan, waktu tempuh, dan jarak ke setiap stasiun pengisian daya. Skrip berikutnya mengurai respons ini untuk mengidentifikasi stasiun pengisian daya terdekat yang dapat dicapai dalam jumlah waktu paling sedikit.
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)
Menghitung rute ke stasiun pengisian daya terdekat
Setelah menemukan stasiun pengisian daya terdekat, gunakan GET Route Directions API untuk mendapatkan petunjuk arah terperinci dari lokasi kendaraan saat ini. Jalankan skrip di sel berikutnya untuk menghasilkan dan mengurai objek GeoJSON yang mewakili rute.
# 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
}
Memvisualisasikan rute
Untuk memvisualisasikan rute, gunakan Get Map Image API untuk merendernya di peta.
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))
Dalam tutorial ini, Anda mempelajari cara memanggil REST API Azure Maps secara langsung dan memvisualisasikan data Azure Maps dengan menggunakan Python.
Untuk informasi selengkapnya tentang API Azure Maps yang digunakan dalam tutorial ini, lihat:
- Dapatkan Arah Rute
- Dapatkan Jarak Rute
- Matriks Rute Pos
- Posting Pencarian Dalam Geometri
- Render - Dapatkan Gambar Peta
Untuk mengetahui daftar lengkap REST API Azure Maps, lihat REST API Azure Maps.