PHPで携帯電話の位置情報を調べる

(1/1)
最近の携帯電話にはGPS レシーバが搭載されている。これを使って、現在位置を表示するプログラムをつくる。
あわせて、日本測地系(tokyo)と世界測地系(wgs84)について考える。

各社携帯電話のGET変数の内容

DoCoMo、au、SoftBank, Willcom 各社の GPS 対応携帯電話は、特定のタグをクリックすると、GPS衛星から情報を取得し、それをサーバに送信する。送信データは GET 変数の形でサーバに渡される。各社の使用は下記の通りだ。
DoCoMoの場合
<a href="GPS を処理するスクリプトの URL" lcs>
変数名 内 容
lat 緯度(全て±dd.mm,ss.sssの度分秒表記)
lon 経度(全て±dd.mm,ss.sssの度分秒表記)
geo 測地系(wgs84 / tokyo )
x-acc 測位レベル(3:水平誤差<50m 2:50m≦水平誤差<300m 1:300m≦水平誤差)
auの場合
<a href="device:gpsone?url=GPS を処理するスクリプトの URL&ver=1&datum=0&unit=1">
変数名 内 容
verGPSのバージョン
datum測地系(0:WGS84 1:tokyo)
unit経度緯度の表記方法( 0:dd.mm.ss.sssの度分秒表記 1:dd.dddの度表記)
lat緯度
lon経度
alt高度
time時間 YYYYMMDDHHiiss
smaj長軸半径誤差
smin短軸半径誤差
vert高度誤差
majaa誤差楕円長軸角度
fm測位方法(数値が少ないほど精度が高い)
SoftBankの場合
<a href="location:auto?url=GPS を処理するスクリプトの URL">
変数名 内 容
posN**.**.**.**E***.**.**.** 座標値(1/100秒単位で度分秒表記 N は北緯、Sは南緯、Eは東経、Wは西経)
geo測地系(wgs84 / tokyo / itrf)
x-acr精度(1:簡易位置情報(300m以上) 2:S!GPSナビ(50m~300m) 3:S!GPSナビ(50m以内))
Willcomの場合
<a href="http://location.request/dummy.cgi?my=GPS を処理するスクリプトの URL&pos=$location">
変数名 内 容
posN**.**.**.**E***.**.**.** 座標値(1/100秒単位で度分秒表記 N は北緯、Sは南緯、Eは東経、Wは西経)

サンプル・プログラム

サンプル・プログラムの流れ

このプログラムは NTT DoCoMo の GPS レシーバ搭載携帯電話専用である。前述の情報を使えば、簡単に他社キャリアに対応できる。

携帯電話の識別

プライバシー保護の観点から、あらかじめ設定された携帯電話の情報だけ拾うことにした。
そのために、携帯電話のシリアル番号判定を行うユーザー関数 isCellPhone を用意した。判定ロジックは、「PHP でユーザー・アクセス情報を表示する」を参照のこと。
また、あらかじめ登録しておく携帯電話のシリアル番号(HTTP USER AGENT で示される文字列)は、グローバル変数 $CellSerials に配列の形で用意しておく。

0013: /**
0014:  * 登録携帯電話のシリアル番号リスト
0015:  * @global bool $CellSerials
0016: */
0017: $CellSerials = array(
0018:     'DoCoMo/2.0 xxx(xxxxx)'
0019: );
0020: 
0021: /**
0022:  * 登録している携帯電話以外かどうかを調べる
0023:  * @param string $serials シリアル番号テーブル
0024:  * @return bool TRUE/FALSE
0025: */
0026: function isCellPhone($serials) {
0027:     //登録シリアルがなければ無条件でTRUE
0028:     if (count($serials) == 0)       return TRUE;
0029: 
0030:     //登録シリアルと合致するかどうかチェック
0031:     foreach ($serials as $val) {
0032:         if ($_SERVER['HTTP_USER_AGENT'] == $val)   return TRUE;
0033:     }
0034:     return FALSE;
0035: }

測地系の違い

携帯電話が返す緯度・経度には 2種類の座標系がある。いわゆる「日本測地系」と「世界測地系」である。同じ地点でも、測地系が違うと、緯度・経度にして 12秒ほど異なる。これは大きな違いだ。
そこで今回は、表示する緯度・経度を世界測地系(WGS-84)に統一することにした。

明治初期、当時の東京天文台(東京都港区麻布台 2-18-1)で行った観測によって日本経緯度原点が定められた。ここを基準にした三角測量によって全国の緯度・経度が測定された。これが日本測地系である。
一方、GPS衛星で測量している世界測地系の一種を WGS-84 と呼ぶ。
日本測地系では、1841 年に定められたベッセル楕円体の地球の長半径(6,377,397.155m)を用いてきた。一方の世界措置系では、1980 年(昭和 55 年)に定められたGRS80 地球楕円体の長半径(6,378,137m)を利用している。同じ地点でも、測地系が違うと、緯度・経度にして 12秒の差が生じするのである。

携帯電話が日本測地系を返す場合には、ユーザー関数 tokyo_wgs84 によって世界測地系に変換する。
今回は使わないが、世界測地系を日本測地系に変換するユーザー関数 wgs84_tokyo も用意した。
いずれも近似式なので、日本以外で使うと誤差が発生することがある。

0046: /**
0047:  * 日本測地系を世界測地系に変換する
0048:  * @param double $long 経度(日本測地系)
0049:  * @param double $lat  緯度(日本測地系)
0050:  * @return double array(経度,緯度)(世界測地系)
0051: */
0052: function tokyo_wgs84($long$lat) {
0053:     $glong = $long - $lat * 0.000046038 - $long * 0.000083043 + 0.010040;
0054:     $glat  = $lat  - $lat * 0.00010695  + $long * 0.000017464 + 0.0046017;
0055:     return array($glong$glat);
0056: }
0057: 
0058: /**
0059:  * 世界測地系を日本測地系に変換する
0060:  * @param double $long 経度(世界測地系)
0061:  * @param double $lat  緯度(世界測地系)
0062:  * @return double array(経度,緯度)(日本測地系)
0063: */
0064: function wgs84_tokyo($long$lat) {
0065:     $glong = $long + $lat * 0.000046047 + $long * 0.000083049 - 0.010041;
0066:     $glat  = $lat  + $lat * 0.00010696  - $long * 0.000017467 - 0.0046020;
0067:     return array($glong$glat);
0068: }

参考サイト

(この項おわり)
header