Öğretici: Azure Notebooks (Python) kullanarak elektrikli araçları yönlendirme

Azure Haritalar, Azure'a yerel olarak tümleştirilmiş jeo-uzamsal hizmet API'lerinden oluşan bir portföydür. Bu API'ler geliştiricilerin, kuruluşların ve ISV'lerin konum algılamalı uygulamalar, IoT, mobilite, lojistik ve varlık izleme çözümleri geliştirmesini sağlar.

Azure Haritalar REST API'leri, jeo-uzamsal veri analizini ve makine öğrenmesi senaryolarını etkinleştirmek için Python ve R gibi dillerden çağrılabilir. Azure Haritalar, kullanıcıların çeşitli veri noktaları arasındaki yolları hesaplamasına olanak sağlayan güçlü bir yönlendirme API'leri kümesi sunar. Hesaplamalar, araç türü veya ulaşılabilir alan gibi çeşitli koşullara dayanır.

Bu öğreticide, elektrikli araç pili düşük olan bir sürücüye yardım edin. Sürücünün aracın konumundan mümkün olan en yakın şarj istasyonunu bulması gerekiyor.

Bu öğreticide şunları yapacaksınız:

  • Buluttaki Azure Notebook'larda Jupyter Notebook dosyası oluşturun ve çalıştırın.
  • Python'da Azure Haritalar REST API'lerini çağır.
  • Elektrikli aracın tüketim modeline göre ulaşılabilir bir aralık arayın.
  • Ulaşılabilen aralıktaki veya isochrone içindeki elektrikli araç şarj istasyonlarını arayın.
  • Ulaşılabilir aralık sınırını ve şarj istasyonlarını harita üzerinde işleyin.
  • Sürüş süresine göre en yakın elektrikli araç şarj istasyonuna giden bir rota bulun ve görselleştirin.

Önkoşullar

Not

Azure Haritalar kimlik doğrulaması hakkında daha fazla bilgi için bkz. Azure Haritalar kimlik doğrulamasını yönetme.

Azure Notebooks projesi oluşturma

Bu öğreticiyi takip etmek için bir Azure Notebooks projesi oluşturmanız ve Jupyter Notebook dosyasını indirip çalıştırmanız gerekir. Jupyter Notebook dosyası, bu öğreticideki senaryoyu uygulayan Python kodunu içerir. Azure Notebooks projesi oluşturmak ve Jupyter Notebook belgesini buna yüklemek için aşağıdaki adımları uygulayın:

  1. Azure Notebooks'a gidin ve oturum açın. Daha fazla bilgi için bkz . Hızlı Başlangıç: Oturum açma ve kullanıcı kimliği ayarlama.

  2. Genel profil sayfanızın üst kısmında Projelerim'i seçin.

    The My Projects button

  3. Projelerim sayfasında Yeni Proje'yi seçin.

    The New Project button

  4. Yeni Proje Oluştur bölmesinde bir proje adı ve proje kimliği girin.

    The Create New Project pane

  5. Oluştur'u belirleyin.

  6. Projeniz oluşturulduktan sonra bu Jupyter Notebook belge dosyasını Azure Haritalar Jupyter Notebook deposundan indirin.

  7. Projelerim sayfasındaki projeler listesinde projenizi seçin ve ardından Karşıya Yükle'yi seçerek Jupyter Notebook belge dosyasını karşıya yükleyin.

    upload Jupyter Notebook

  8. Dosyayı bilgisayarınızdan karşıya yükleyin ve bitti'yi seçin.

  9. Karşıya yükleme başarıyla tamamlandıktan sonra dosyanız proje sayfanızda görüntülenir. Dosyayı Jupyter Not Defteri olarak açmak için çift tıklayın.

Jupyter Notebook dosyasında uygulanan işlevselliği anlamaya çalışın. Jupyter Notebook dosyasında kodu bir kerede bir hücre olarak çalıştırın. Jupyter Notebook uygulamasının üst kısmındaki Çalıştır düğmesini seçerek kodu her hücrede çalıştırabilirsiniz.

The Run button

Proje düzeyi paketlerini yükleme

Jupyter Notebook'ta kodu çalıştırmak için aşağıdaki adımları uygulayarak paketleri proje düzeyinde yükleyin:

  1. Azure Haritalar Jupyter Notebook deposundan requirements.txt dosyasını indirin ve projenize yükleyin.

  2. Proje panosunda Project Ayarlar'ı seçin.

  3. Proje Ayarlar bölmesinde Ortam sekmesini ve ardından Ekle'yi seçin.

  4. Ortam Kurulum Adımları'nın altında aşağıdakileri yapın: a. İlk açılan listede Gereksinimler.txt dosyasını seçin.
    b. İkinci açılan listede requirements.txt dosyanızı seçin.
    c. Üçüncü açılan listede, sürümünüz olarak Python Sürüm 3.6'yı seçin.

  5. Kaydet'i seçin.

    Install packages

Gerekli modülleri ve çerçeveleri yükleme

Gerekli tüm modülleri ve çerçeveleri yüklemek için aşağıdaki betiği çalıştırın.

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

Ulaşılabilir aralık sınırını isteme

Bir paket teslimat şirketinin filosunda bazı elektrikli araçlar vardır. Gün boyunca, elektrikli araçların depoya dönmek zorunda kalmadan şarj edilmesi gerekir. Kalan ücret bir saatten daha kısa bir süreye düştüğünde, ulaşılabilir bir aralıkta yer alan bir dizi şarj istasyonu ararsınız. Temelde, pil şarjı düşük olduğunda bir şarj istasyonu ararsınız. Ayrıca, bu şarj istasyonu aralığı için sınır bilgilerini alırsınız.

Şirket, ekonomi ve hız dengesi gerektiren rotaları kullanmayı tercih ettiğinden istenen routeType ekodur. Aşağıdaki betik, Azure Haritalar yönlendirme hizmetinin Yol Aralığını Al API'sini çağırır. Aracın tüketim modeli için parametreleri kullanır. Betik daha sonra yanıtı ayrıştırarak aracın maksimum ulaşılabilir aralığını temsil eden geojson biçiminde bir çokgen nesnesi oluşturur.

Elektrikli aracın ulaşılabilir aralığının sınırlarını belirlemek için betiği aşağıdaki hücrede çalıştırın:

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

Ulaşılabilen menzil içindeki elektrikli araç şarj istasyonlarını arayın

Elektrikli araç için ulaşılabilir aralığı (isochrone) belirledikten sonra bu aralıktaki şarj istasyonlarını arayabilirsiniz.

Aşağıdaki betik, Geometri API'sinde Arama Sonrası Azure Haritalar çağırır. Otomobilin maksimum ulaşılabilir aralığı sınırları içinde elektrikli araç için şarj istasyonları arar. Ardından betik, yanıtı ulaşılabilir konumlardan oluşan bir diziye ayrıştırıyor.

Ulaşılabilir aralıktaki elektrikli araç şarj istasyonlarını aramak için aşağıdaki betiği çalıştırı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)

Ulaşılabilir aralığı ve şarj noktalarını karşıya yükleme

Şarj istasyonlarını ve elektrikli aracın maksimum ulaşılabilir aralığı sınırını harita üzerinde görselleştirmek yararlı olur. Sınır verilerini ve şarj istasyonları verilerini Azure depolama hesabınıza geojson nesneleri olarak yüklemek için Veri kayıt defteri oluşturma makalesinde açıklanan adımları izleyin ve bunları Azure Haritalar hesabınıza kaydedin. Benzersiz tanımlayıcı (udid) değerini not edin, buna ihtiyacınız olacaktır. udid Kaynak kodunuzdan Azure depolama hesabınıza yüklediğiniz geojson nesnelerine başvurma yönteminizdir.

Şarj istasyonlarını ve ulaşılabilir aralığı harita üzerinde işleme

Verileri Azure depolama hesabına yükledikten sonra Harita Görüntüsü Al hizmetini Azure Haritalar çağırın. Bu hizmet, aşağıdaki betiği çalıştırarak statik harita görüntüsünde şarj noktalarını ve ulaşılabilen maksimum sınırı işlemek için kullanılır:

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

A map showing the location range

En uygun şarj istasyonunu bulma

İlk olarak, ulaşılabilir aralıktaki tüm olası şarj istasyonlarını belirlemek istiyorsunuz. Ardından, en az bir süre içinde hangisine ulaşabileceğinizi bilmek istiyorsunuz.

Aşağıdaki betik Azure Haritalar Matris Yönlendirme API'sini çağırır. Belirtilen araç konumunu, seyahat süresini ve her şarj istasyonuna olan mesafeyi döndürür. Sonraki hücredeki betik, zamana göre en yakın ulaşılabilir şarj istasyonunu bulmak için yanıtı ayrıştırıyor.

En az sürede ulaşılabilen en yakın şarj istasyonunu bulmak için betiği aşağıdaki hücrede çalıştırın:

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)

En yakın şarj istasyonuna giden yolu hesaplama

Artık en yakın şarj istasyonunu bulduğunuza göre, elektrikli aracın geçerli konumundan şarj istasyonuna ayrıntılı rota istemek için Yol Tariflerini Al API'sini çağırabilirsiniz.

Şarj istasyonuna giden yolu almak ve yanıtı ayrıştırarak yolu temsil eden bir geojson nesnesi oluşturmak için betiği aşağıdaki hücrede çalıştırın:

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

Yolu görselleştirme

Yolu görselleştirmeye yardımcı olmak için Veri kayıt defteri oluşturma makalesinde açıklanan adımları izleyerek yol verilerini Azure depolama hesabınıza geojson nesnesi olarak yükleyin ve ardından Azure Haritalar hesabınıza kaydedin. Benzersiz tanımlayıcı (udid) değerini not edin, buna ihtiyacınız olacaktır. udid Kaynak kodunuzdan Azure depolama hesabınıza yüklediğiniz geojson nesnelerine başvurma yönteminizdir. Ardından harita üzerinde yolu işlemek ve görselleştirmek için harita görüntüsü API'sini alma işleme hizmetini çağırın.

Haritada işlenen yolun görüntüsünü almak için aşağıdaki betiği çalıştırın:

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

A map showing the route

Bu öğreticide, Azure Haritalar REST API'lerini doğrudan çağırmayı ve Python kullanarak Azure Haritalar verileri görselleştirmeyi öğrendiniz.

Bu öğreticide kullanılan Azure Haritalar API'lerini keşfetmek için bkz:

Kaynakları temizleme

Temizleme gerektiren kaynak yok.

Sonraki adımlar

Azure Notebooks hakkında daha fazla bilgi edinmek için bkz.