新・カーナビ作るぜ!(6)pgRouting:経路表示

経路探索ができるようになったので、それを表示してみることに。tsmapはいろいろライブラリ化してあって、プラグインで機能を追加できるようにしてあるので(この辺については後日書く予定)表示すること自体は、すぐにできたのですが…、表示してみたら、前書いたのものがそのままではいろいろ問題あることに気づきました。

前の日記で取得した座標を元にそのまま経路を表示してみると…

画面ダンプ:経路表示1失敗

たしかに、それっぽくは表示されるのですが…、カーブが直線になってしまいます。

どうやら、pgroutingのwaysテーブルはOSMのwayを交差点ごとに区切って管理しているようです。素晴らしい。で、交差点間のカーブの座標については…、the_geomカラムにMULTILINESTRINGという形式で列挙されている模様。SQLとしては、こんな感じになります。
select source,target,AsText(the_geom) as the_geom FROM shortest_path('SELECT gid as id,  source::integer,  target::integer,  length::double precision as cost FROM ways', 73558, 22575, false, false) as rt join ways on rt.edge_id=ways.gid;
出力はこんな感じ:
 source | target |                                                                                                                                                                                                                                                               the_geom                                                                                                                                                                                                                                                               
--------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  73558 |  73553 | MULTILINESTRING((139.3302867 35.6311181,139.3304202 35.6310724))
  73552 |  73553 | MULTILINESTRING((139.3304403 35.6310447,139.3304107 35.6310534,139.3304202 35.6310724))
  73551 |  73552 | MULTILINESTRING((139.3304603 35.6310361,139.3304403 35.6310447))
  73550 |  73551 | MULTILINESTRING((139.3303607 35.6305254,139.330338 35.6305319,139.3304253 35.630828,139.3305078 35.6310249,139.3304603 35.6310361))
  73550 |  73559 | MULTILINESTRING((139.3303607 35.6305254,139.3301667 35.6300717))
  45306 |  73559 | MULTILINESTRING((139.3299566 35.630008,139.3301667 35.6300717))
  45306 |  45307 | MULTILINESTRING((139.3299566 35.630008,139.3290828 35.6303421,139.3286705 35.6304854))
  45307 |  45313 | MULTILINESTRING((139.3286705 35.6304854,139.328346 35.6305991))
  45313 |  36437 | MULTILINESTRING((139.328346 35.6305991,139.3282432 35.630642))
  36437 |  23838 | MULTILINESTRING((139.3282432 35.630642,139.3277035 35.6307962,139.3270353 35.6309932,139.326684 35.631096,139.3264185 35.6312245,139.3262643 35.631353,139.3261615 35.6315072,139.3260455 35.6317314))
  23837 |  23838 | MULTILINESTRING((139.3243825 35.630895,139.3260455 35.6317314))
  23836 |  23837 | MULTILINESTRING((139.3228822 35.6301538,139.3243825 35.630895))
  36449 |  23836 | MULTILINESTRING((139.3210087 35.631552,139.3213503 35.6315465,139.3216236 35.6314965,139.3219038 35.6313743,139.3221361 35.6312022,139.3223343 35.6309411,139.3228822 35.6301538))
  36449 |  36450 | MULTILINESTRING((139.3210087 35.631552,139.3210318 35.6317295,139.3209622 35.6321642,139.3207449 35.6325294,139.320484 35.6328511))
  36450 |  36451 | MULTILINESTRING((139.320484 35.6328511,139.3203592 35.6329938))
  61597 |  36451 | MULTILINESTRING((139.3165485 35.6305764,139.3172934 35.6312021,139.3183739 35.6319747,139.3189073 35.6322915,139.3203592 35.6329938))
  61597 |  22569 | MULTILINESTRING((139.3165485 35.6305764,139.3161648 35.6301889,139.3159197 35.6299826,139.3156352 35.6297798,139.3153726 35.6296233,139.3150968 35.629481,139.3147423 35.6293316,139.3143397 35.6291893,139.3139633 35.6290826,139.3136427 35.6290631))
  22569 |  22570 | MULTILINESTRING((139.3136427 35.6290631,139.3135398 35.6294058))
  22570 |  22571 | MULTILINESTRING((139.3135398 35.6294058,139.3134855 35.6295375,139.3133996 35.629685,139.3129677 35.6303102,139.3128848 35.6304388,139.3125554 35.6310138,139.3124396 35.6311431))
  22571 |  22572 | MULTILINESTRING((139.3124396 35.6311431,139.3123565 35.631197,139.3122512 35.6312359,139.3121175 35.631276,139.3117396 35.631331))
  22576 |  22572 | MULTILINESTRING((139.2996203 35.6215071,139.3000684 35.6216286,139.3014417 35.6216286,139.3025146 35.6216634,139.30333 35.6217332,139.3039737 35.6220123,139.3047891 35.6223611,139.3065057 35.6231286,139.3081365 35.6238612,139.3087802 35.62421,139.3090806 35.624524,139.309381 35.6249426,139.3095527 35.6253263,139.3095956 35.6259193,139.3096385 35.626896,139.3097244 35.6274541,139.3098102 35.6278727,139.3100677 35.6282913,139.3105397 35.6291285,139.3111406 35.6302447,139.3114839 35.6309074,139.3117396 35.631331))
  22575 |  22576 | MULTILINESTRING((139.2963793 35.6142193,139.2964635 35.6144419,139.2966352 35.6149303,139.2966781 35.6154885,139.2966781 35.6169887,139.2966781 35.6188377,139.2967639 35.6193261,139.2969785 35.6197099,139.2974506 35.6201634,139.2980514 35.6207215,139.2986522 35.6211402,139.2992959 35.6214192,139.2996203 35.6215071))
(22 rows)

the_geomの値をパージングして、座標にしてやればよいはず。と思って表示したのがこちら:

画面ダンプ:経路表示2失敗2

うーむ悪化したというか…。何が起きているのやら。というわけで、交差点に番号をつけてみることに

画面ダンプ:経路表示3失敗3

まずいところが、見えてきました。番号が重なっているところがあります。考えてみれば当たり前ですが、座標の列挙による線には向きがあります。それを考えずに表示しているので、線が行ったり来たりしていたのです。というわけで、どっち向きかを考える必要があります。経路探索のときにあったsourceカラムとtargetカラムがどうやら道の開始点と終了点をあらわしていそうです。基本的に線は全部つながっているはずなので、このsourceとtargetを眺めてみると、確かにとなりあった線では、sourceあるいはtargetが一致します。ということは、次の線のsourceあるいはtargetと一致するものが今の線のtargetになっていれば順方向、sourceになっていれば逆方向ということがわかるので、それを元に線の向きを必要に応じて逆にしてやったのがこちら:

画面ダンプ:経路表示4成功

うまく表示できました。

あとの課題としては、

  • 始点あるいは終点の座標から最寄りの点を選ぶ効果的な方法
  • その際に、線の途中だった場合の処理
  • 始点・終点を選ぶためのUI(現在は、起動時に数値で指定)
  • 経路探索時のコスト(重み)の付け方

などでしょうか。

経路探索のコストは、デフォルトでは距離を重みにしていて、今はいろいろ試している最中ですが、距離を(推定)制限速度で割った値を使ってみています。信号機の量なども入れられればいいかなと思うのですが。

追記:上ふたつはクリア。ちょっとプログラムは複雑になったけど、きちんと線の途中からでも経路表示できるようになった。

Posted by TechStrom on Friday, September 25, 2009