京都バスのGTFS-RT(VehiclePosition)のデータ構造

プログラミング

7月下旬あたりにGTFS-JP/GTFS-RTという公共交通機関の運行情報等をまとめたデータ形式を知りました。

それから3ヶ月ほど経ち、自作版京都バスナビの製作を通じて、GTFS-RTにだいぶ理解が進んできたということで備忘録的に書いていきます。

GTFS-RT(リアルタイム情報)には①VehiclePosition(車両の位置情報)②TripUpdate(時刻など、運行情報)③Alert(迂回情報など、お知らせ的な?)の3種類がありますが、今回は①VehiclePositionについて。

基本京都バスのデータしか見ていないので、他の事業者とは項目の有無で若干違いがあるかもしれません。

なお、京都バスのGTFS-RTはバージョン2.0です。

では早速全データを。

2023年11月3日13時2分に取得したデータです。

header {
  gtfs_realtime_version: "2.0"
  incrementality: FULL_DATASET
  timestamp: 1698984155
}
entity {
  id: "VE_153"
  vehicle {
    trip {
      trip_id: "0002_3_300012252"
      route_id: "10063"
      direction_id: 0
      start_time: "12:50:00"
      start_date: "20231103"
      schedule_relationship: SCHEDULED
    }
    vehicle {
      id: "153"
    }
    position {
      latitude: 34.9995918
      longitude: 135.759674
      bearing: 4
      speed: 4.44444466
    }
    current_stop_sequence: 5
    stop_id: "55_4"
    current_status: INCOMING_AT
    timestamp: 1698984142
    congestion_level: UNKNOWN_CONGESTION_LEVEL
    occupancy_status: MANY_SEATS_AVAILABLE
  }
}
entity {
  id: "VE_118"
  vehicle {
    trip {
      trip_id: "0001_3_300024111"
      route_id: "10008"
      direction_id: 1
      start_time: "12:26:00"
      start_date: "20231103"
      schedule_relationship: SCHEDULED
    }
    vehicle {
      id: "118"
    }
    position {
      latitude: 35.0430336
      longitude: 135.78067
      bearing: 128
      speed: 0
    }
    current_stop_sequence: 12
    stop_id: "6161_1"
    current_status: STOPPED_AT
    timestamp: 1698983015
    congestion_level: UNKNOWN_CONGESTION_LEVEL
    occupancy_status: MANY_SEATS_AVAILABLE
  }
}
~省略~

このデータを例にして解説していきます。本文中では上のentityの方の値で説明してます。

header

header {
  gtfs_realtime_version: "2.0"
  incrementality: FULL_DATASET
  timestamp: 1698984155
}

これはVehiclePosition、TripUpdate、Alertの全てに共通する項目のようです。

gtfs_realtime_version

gtfs_realtime_version: "2.0" は、GTFS-RTのバージョンを表しています。

全国でも早期にGTFS導入が進んだ広島県の広電バスでは、”1.0″でしたが、京都バスは最新の2.0のようです。

incrementality

incrementality: FULL_DATASET は、Googleの公式ドキュメントを見るまで分かりませんでした。

ドキュメントによると、このデータの配信によって更新された差分だけ配信されているのか、全てのデータが配信されているのかを示すもののようです。

ドキュメントではFULL_DATASETに加えてDIFFERENTIALが定義されていますが、サポートされていない旨の記述があるので基本的にFULL_DATASETが入るものと思っています。

timestamp

timestamp: 1698984155 は、タイムスタンプ(データの生成時間)を示しています。

UNIX時間なので人間が読みやすい形式にするには変換作業が要りますね。

entity

ここから各車両のデータです。

entity {
  id: "VE_153"
  vehicle {
    trip {
      trip_id: "0002_3_300012252"
      route_id: "10063"
      direction_id: 0
      start_time: "12:50:00"
      start_date: "20231103"
      schedule_relationship: SCHEDULED
    }
    vehicle {
      id: "153"
    }
    position {
      latitude: 34.9995918
      longitude: 135.759674
      bearing: 4
      speed: 4.44444466
    }
    current_stop_sequence: 5
    stop_id: "55_4"
    current_status: INCOMING_AT
    timestamp: 1698984142
    congestion_level: UNKNOWN_CONGESTION_LEVEL
    occupancy_status: MANY_SEATS_AVAILABLE
  }
}

id

entityのidは事業者によって異なるはずですが、京都バスではVE_XXX(XXXは車両番号)が付けられています。

id: "VE_153" の場合、153号車です。

trip

trip_id

時刻表に掲載されている(=定期便)場合、便を区別するためのtrip_idが存在します。

trip_idはこれ単体では意味をなさない文字列ですが、GTFS-JPのtrips.txtファイルにて参照すると、どの便なのか特定することが可能です。

trip_id: "0002_3_300012252" の場合、trips.txtを参照すると・・・

route_id,service_id,trip_id,trip_headsign,trip_short_name,direction_id,block_id,shape_id,wheelchair_accessible,bikes_allowed,jp_trip_desc,jp_trip_desc_symbol,jp_office_id,jp_pattern_id
~中略~
10064,O_0002_3,0002_3_300012252,,,0,,,,,,,0002,7311_2

route_id10064service_id0_0002_3direction_id0jp_office_id2jp_pattern_id7311_2と分かります。

それぞれ、

  • route_id(後述) → 路線番号
  • service_id → 運行条件番号
  • direction_id → 往路か復路か
  • jp_office_id → 担当営業所
  • jp_pattern_id → (日本で言う)系統番号

です。

これらのidはさらに他のテキスト(実際にはcsv形式ですが)ファイルを参照していけば、最終的に「何曜日の何時何分に始発を出発する何系統どこ行き」という情報に繋がります。

route_id

前項ではtrip_idから参照し出てきたroute_idですが、VehiclePositionでは参照せずともそのまま取得できます。

route_id: "10063" の場合、路線番号を保存しているroutes.txtを参照すると・・・

route_id,agency_id,route_short_name,route_long_name,route_desc,route_type,route_url,route_color,route_text_color,jp_parent_route_id
~中略~
10063,8130001002355,72快速,清滝→京都駅前,,3,,8F3937,FFFFFF,清滝→京都駅前(朝のみ)
10064,8130001002355,73,京都駅前→苔寺・すず虫寺,,3,,3886A2,FFFFFF,京都駅前→苔寺・すず虫寺

清滝と京都駅前を結ぶ、72快速(系統)であることが分かります。

※前項で参照した時は10064と書きましたが、これは現在京都バスがリアルタイムで配信している方(この項目における10063)の値が正しくないデータになっているためで、実際には同じ値になります。

direction_id

direction_idは0か1しかない(はず)。

0が往路、1が復路です。

start_time

始発のバス停における出発時間です。

HH:MM:SS で表されます。

start_time: "12:50:00" の場合、12時50分0秒です。

start_date

こちらは始発のバス停での出発時の年月日です。

YYYYMMDDで表されます。

start_date: "20231103" の場合、2023年11月3日に始発バス停を出発する便です。

schedule_relationship

schedule_relationshipは、この運行が予定されているものかどうかを示します。

Google公式ドキュメントでは、以下の4種類が存在するようです。

  • SCHEDULED
    • 時刻表通りまたはそれに近い運行(つまりtrip_idが存在する)
  • ADDED
    • 時刻表にない便です。京都バスでは時刻表にない臨時便、車両交換時などに適用されているようです。
  • UNSCHEDULED
    • 京都バスではこのデータが配信されているところを目撃したことがないので詳細不明。
  • CANCELED
    • こちらも不明ですが、おそらく運行途中に運行を取り止めにした時に使われるのではないかと思います。

schedule_relationship: SCHEDULED の場合、時刻表に掲載されている定期便と判断することができます。

私はSCHEDULEDの場合は定期便、ADDEDの場合は臨時便と解釈してサイトに表示しています。

ちなみに、schedule_relationshipがADDEDのとき、trip_id、start_time、start_dateの値は空で配信されています。

vehicle

車両についての情報を含むフィールドです。

id

Google公式ドキュメントでは社内向けの車両番号として定義されています。

京都バスでは、車両前・横・後に表記された番号(車番)がここにそのまま使われているようです。

id: "153" の場合、153号車が使用されていると分かります。

position

車両の位置関係のフィールドです。

latitude

緯度です。

longitude

経度です。

latitude(緯度)と合わせれば車両の位置を特定できます。

bearing

車両が向いている方角が0度から360度で表されます。

0度が真北、90度が真東と、時計回りに増えていきます。

bearing: 4 の場合、微妙に東寄りのほぼ北ですね。(語彙力)

speed

スピード、つまり速度です。単位はm/s(メートル毎秒)のようです。

これを書くために確認するまで単位をキロメートル毎時だと思ってました・・・

speed: 4.44444466 の場合、秒速4.4メートル(時速16キロ)です。

(vehicleフィールドに戻ります)

current_stop_sequence

現在の(もしくは次に停車する)バス停の順番です。

current_stop_sequence: 5 であれば、5番目のバス停に接近もしくは停車しています。

・・・

これだけだと「どこだよ?」となりますが、こちらもバス停の名前を特定するにはGTFS-JPのstop_times.txtを参照します。

trip_idは0002_3_300012252なので・・・

trip_id,arrival_time,departure_time,stop_id,stop_sequence,stop_headsign,pickup_type,drop_off_type,shape_dist_traveled,timepoint
~中略~
0002_3_300012252,12:50:00,12:50:00,61_2,1,嵐山・苔寺・すず虫寺(四条烏丸・西大路四条・太秦天神川駅前・太秦広隆寺前(映画村)),0,1,,1
0002_3_300012252,12:54:00,12:54:00,59_4,2,嵐山・苔寺・すず虫寺(四条烏丸・西大路四条・太秦天神川駅前・太秦広隆寺前(映画村)),0,0,,1
0002_3_300012252,12:56:00,12:56:00,57_2,3,嵐山・苔寺・すず虫寺(四条烏丸・西大路四条・太秦天神川駅前・太秦広隆寺前(映画村)),0,0,,1
0002_3_300012252,12:57:00,12:57:00,56_2,4,嵐山・苔寺・すず虫寺(四条烏丸・西大路四条・太秦天神川駅前・太秦広隆寺前(映画村)),0,0,,1
0002_3_300012252,12:59:00,12:59:00,55_4,5,嵐山・苔寺・すず虫寺(西大路四条・太秦天神川駅前・太秦広隆寺前(映画村)),0,0,,1
0002_3_300012252,13:04:00,13:04:00,69_2,6,嵐山・苔寺・すず虫寺(西大路四条・太秦天神川駅前・太秦広隆寺前(映画村)),0,0,,1
0002_3_300012252,13:05:00,13:05:00,68_2,7,嵐山・苔寺・すず虫寺(西大路四条・太秦天神川駅前・太秦広隆寺前(映画村)),0,0,,1

stop_times.txtではそれぞれのtrip_idについて、どのバス停(stop_id)にいつ着いて(arrival_time)いつ発車する(departure_time)かなど、まとめられています。

0002_3_300012252かつ5のstop_idは、55_4ですね。

バス停情報はstops.txtにまとめられているので、調べます。

stop_id,stop_code,stop_name,stop_desc,stop_lat,stop_lon,zone_id,stop_url,location_type,parent_station,stop_timezone,wheelchair_boarding,platform_code
~中略~
55_4,,四条烏丸,,35.003557,135.758452,,,0,55,,,

ということで、四条烏丸(の番乗り場)ということが分かりました。

例示おわり。

stop_id

stop_idは次に停車する(もしくは現在停車している)バス停のidです。

実は次のバス停を調べるだけなら、前項で例示したように参照しまくらなくてもここを見るだけで済みます。

stop_id: "55_4" の場合、先程と同じようにstops.txtを参照して四条烏丸だと分かります。

current_status

current_statusはstop_id(バス停)に対する接近状況を示します。

Googleの公式ドキュメントでは、3種類定義されています。

  • INCOMING_AT
    • 「間もなく到着」
  • STOPPED_AT
    • 「停車中」→京都バスでは、ドアを開けている時かと思われます。
  • IN_TRANSIT_TO
    • 前のバス停を発車してすぐ、もしくはINCOMING_ATより前に使われるはずです。京都バスでは、停車していない限りほとんどINCOMING_ATが使用されているためどのような状況でIN_TRANSIT_TOの扱いになるのか未だによく分かっていません。

current_status: INCOMING_AT の場合、四条烏丸に「間もなく到着する」ことが分かります。

congestion_level

バスが走行している道路の渋滞状況を示します。

京都バスでは渋滞状況を配信していませんが、項目自体は存在します。そのためcongestion_level: UNKNOWN_CONGESTION_LEVEL(渋滞状況不明)となっています。

他の値を知りたければGoogle公式ドキュメントを見てくれ。

occupancy_status

congestion_levelは道路の渋滞でしたが、occupancy_statusはバス車内の混雑度を示すものです。

京都バスは4段階+データ無しを配信しているようです。

  • EMPTY
    • (多分)誰も乗ってないか数人の場合
  • MANY_SEATS_AVAILABLE
    • 直訳すれば「多くの席が空いている状況」ですが、利用している体感では満席になるまではこの値の場合が多いですね。京都バスナビでは青色で表されます。
  • STANDING_ROOM_ONLY
    • 「立ち席しかない」です。体感ではかなり乗客が多くてもこの値の場合が時々あります。京都バスナビではオレンジ色で表されます。
  • FULL
    • 文字通り、「満員」です。本当に乗れない時が多いです。京都バスナビでは赤色で表されます。
  • NO_DATA_AVAILABLE
    • データが無い場合に使われます。始発で乗車が始まる前や、教習車でもこの値が使われている時があります。

Googleの定義ではもう少しバリエーションがあるみたいです。

おわり

基本的に、京都バスのVehiclePositionのデータはこんな感じです。京都バスのと強調するのは、事業者によってデータ項目の有無や配列の違いが多々あるみたいなので・・・。

同じ京都バスでも、ときどき欠損しているデータが配信されることがあり、正直まだ完璧に理解しているわけではないです。

とりあえず秋の紅葉シーズンまでに大体は自作のバスロケウェブアプリが組み上がったということで。

コメント

タイトルとURLをコピーしました