Google Map APIを使ってみる(その2)

せっかくAPIキーを取得したので、Google Map APIを使ってみる(Google Map APIのトップページへのリンク)。

Google Map APIを使ったページを書くには、「Google Map APIを使ってみる(その1)」で紹介した、※2の画面のサンプルをコピペして、改造するのがよい。
サンプルをみると、

      <script src="http://maps.google.com/maps?
                  file=api&v=2&key=ABQIAAAAkb*******************-                      
                  *************************hWCSshiltKG5Yg"
                  type="text/javascript">
      </script> 
(注)keyパラメータはマスクしてある。本当は一行。

となっている。3年くらい前にはV1だったはず(V2への移行とかいう話があったような気がする)なので、正式にv2が「最新リリース」となったのだな、と思う。
RESTfullなwebサービスでは、こんな感じで「呼び出すAPIのバージョンをリクエストパラメータで指定」して、後方互換性(backward compatibility、下位互換ということが多い)の代わりにすることが多い。

ちょっと凝って、携帯(au)で場所を測位して、Google Map上にマップしてみる。

ググってみたが、引っかかるのは旧い情報ばかり。
Google Map APIが出たとき、良く見かけたサンプルの一つだが、今時は、試す人がいないのかなぁ(助手席ナビとかあるし)。

携帯電話(au)で位置情報を取得する(測位する)。

まず、KDDIのHPにいって、携帯端末(携帯電話)のAPIを確認する。
KDDIの技術情報(リンクはこちら)にある、「簡易位置情報」がそれだ。

「簡易位置情報」とは、基地局情報を元に「だいたいこの辺り」と測位測位することをいう。

この「簡易位置情報」のページには、

自分のHP上に

device:location?url=http://server/location.cgi

というURLを(aタグで)置いて、そこにau端末からアクセスすれば、位置が取得できると書いてある。
aタグでリンクした場合、location.cgi(サーバーPGMの総称)で、GETメソッドで送られてきたパラメータを取得する。このリクエスト・パラメータに緯度・経度が含まれる。

device:locationは、そのためのプロトコルの一つで、このスキームに反応して、携帯が位置情報を送出するというやり方になる。

ここまで読んで、「あれ?GPSもあったよなぁ」と思い、昔の本を開いて見ると、スキームが

device:gpsone

と書かれている。
「でばいす:GPSわん」と読むとおり、gpsOneは、GPS(と基地局からの情報)を使う測位のためのスキームである(gpsOneを解説しているページへのリンク)。OneはCDMA Oneののワンである。

ググってみると、こっちのスキームは「精度はよいが、正式には非公開」と書いてあることが多い。

この場合、具体的には

device:gpsone?url=http://server/sokui.php&ver=1&datum=0&unit=0
(注) serverは、ドメイン名と考えればよい

のように、パラメータを指定する。(パラメータに詳しいページへのリンク。device:locationでもパラメータ指定をするのが普通)。

サンプルでは、このスキームを使うことにした。

まず、自分のレンタル・サーバーに、sokui.htmlとして以下のhtmlを置いた。

<HTML>
<HEAD>
</HEAD>
<BODY>
<a href="device:gpsone?url=http://server/sokui.php&ver=1&datum=0&unit=0">
	get GPS Info
</a>
</BODY>
</HTML>

このhtmlに書かれているsokutei.phpは以下の通り。
測位点の情報を(全てのGETメソッドのパラメタを)抽出して、PEAR::LogでLogとして書き出す仕様となっている。

<?php

require_once("PEAR/Log.php");
$p_log=Log::factory("file","logs/log.log",WEBAPP);
$p_log->setMask(Log::UPTO(PEAR_LOG_DEBUG));

$p_log->debug("sokutei: start");

foreach ($_GET as $key => $value) {
	$p_log->debug("key: ".$key." value: ".$value);
}

$p_log->debug("sokutei: start");

?>
携帯電話(au)で位置情報を取得してみる。

関越道でドライブした際に、練馬ICの入り口付近(比丘尼交差点付近)から、川越ICまで上のプログラムで測位をしてみた(注;上のプログラムはレスポンスの処理がないので、送信後にエラーとなるが、測位する分には問題ない;パケット代節約??)。

sokui.htmlにアクセスすると、au端末(携帯電話)が送出確認するので、それに「いいよ」と答えればよい。

上のパラメータだと、unit=0としているので、度分秒での測位結果が返ってくる。
国土地理院のHPにいけば、「度分秒での測位結果から地図上の位置がわかる」ので(リンクはこちら。東経139度35分56秒、北緯35度44分47秒を1/10000で表示。)、これで結果のトレースができる。

だが、上のHPだと一点しか確認できないので、Google Map APIを使って表示することにした。

まずは、度分秒系から、百分率系へ変換をする。
これは以下の式で計算すればよい。

百分率=(度*3600000+分*60000+秒*1000)/3600000

実験では、以下のデータが取得できた。

緯度 経度
35.7564 139.6000
35.7625 139.5917
35.7625 139.5917
35.7645 139.5792
35.7741 139.5678
35.7814 139.5614
35.7867 139.5531
35.7956 139.5431
35.8061 139.5320
35.8061 139.5320
35.8347 139.5056
35.8467 139.5022
35.8595 139.4928
35.8711 139.4819
35.8834 139.4725
35.8925 139.4592
35.9006 139.4664


これをつかって、以下のコードを書いて、APIキーを取得したサーバーに配置。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Google Maps JavaScript API Example</title>
    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;
    	key=ABQIAAAAkb**************-******************shiltKG5Yg"
      type="text/javascript"></script>
    <script type="text/javascript">

    //<![CDATA[

    function createMarker(point,index){
		var msg = "測位("+index+ ");<br/>"
					+"北緯;"+point[0]+"、東経;"+point[1];
		var pos = new GLatLng(point[0],point[1]);
		var mark = new GMarker(pos);
		GEvent.addListener(mark,"click",function(){
			mark.openInfoWindowHtml(msg);
			}
		);		        
		return mark;
    };
    
    function load() {

 	  	if (GBrowserIsCompatible()) {
      	var map = new GMap2(document.getElementById("map"));

    	var posArray = [
            [35.7564,139.6000],
            [35.7625,139.5917],
            [35.7625,139.5917],
            [35.7645,139.5792],
            [35.7741,139.5678],
            [35.7814,139.5614],
      [35.7867,139.5531],
	  [35.7956,139.5431],
	   [35.8061,139.5320],
	   [35.8061,139.5320],
	    [35.8347,139.5056],
	    [35.8467,139.5022],
	    [35.8595,139.4928],
	    [35.8711,139.4819],
	    [35.8834,139.4725],
	    [35.8925,139.4592],
	    [35.9006,139.4664]];

      	var posCtr = new GLatLng(35.8061,139.5320);
    	
        map.setCenter(posCtr, 11);
    	map.addControl(new GLargeMapControl());
    	map.addControl(new GMapTypeControl());

		for(var i=0; i<posArray.length; i++){
			var mark =createMarker(posArray[i],i);
	        map.addOverlay(mark);
		}
        
      }
    }

    //]]>
    
    </script>
  </head>
  <body onload="load()" onunload="GUnload()">
    <div id="map" style="width:500px;height:300px"></div>
  </body>
</html>


これを表示したのが、下の画面である。

この画面では、Google Map APIの「デフォルトのMarker」をつかって、測位結果を表示している。
各Markerには、クリックイベントのハンドラとして、測位点の「index」、「経度」、「緯度」を吹き出し表示するようにした。

携帯電話(au)の位置情報(測位結果)を評価する。

自分のau端末(携帯電話)はTOSHIBA製のW41T。もう2年以上使っている代物。

送出される情報は以下の通り。

GET METHODのparameter key parameter value 意味
lat +35.53.33.46 緯度(度分秒+2桁)
lon +139.27.33.82 経度(度分秒+2桁)
alt 81 高度(m)
time 20081224075140 取得時間(2008/12/24,07:51:40)
smaj 16 長軸半径誤差(m)
smin 7 短軸半径誤差(m)
vert 17 高度誤差(m)
majaa 175 誤差楕円長軸角度
fm 0 精度(測位方法らしい。小さいほどよい??)

誤差については、こちらのページ(ezplusことはじめさん)が詳しい。

簡単にいうと、長軸誤差が「可能性として一番大きい誤差」ということ。
測定結果をみると、7m〜223mの範囲で分布(サンプルサイズ20)している。

以下は、Mapを拡大したときに、あきらかに見た目のおかしいもの。

上は、高架下辺りでの測位、下は、マンションと高速道路高架付近での測位となっている。

これを見る限り、このレベルの拡大となると、誤差が相当に目だってしまうのが分かる。
ルートのトレースレベルで見ると、見た目の粗は目に付かない。

先にも述べたように、私のau端末は旧式のもの。
機種変更をしたら、また、測位してみようと思う。アンテナが進化していると思うので。