地図ソフトは便利です。

これなしには日々送れないという方もいらっしゃるでしょう。

かくいう当サイトもGoogle Mapsにはお世話になりっぱなしです。

が、いつも地図を使っていて、ふと「地図なしで目的地にいく方法も必要なんじゃあるまいか?」と思ってしまいました。

で何かないかと探しましたが、これは!というのが見つからず、しようがないので作ってみました....。
(かつてKDDIが出すと言ってたスマフォスイング、あれどうなったんだろう?iPhone向けならDGRadarってのがあったね)

まあ、こんなもん作ろうかと思うのは当サイト管理人ぐらいじゃないか?という気もする。

地図を表示できない位の小さなデバイスでも、道案内できるかも...。
クソ広い駐車場で初期位置を記録出来るようにすれば、帰ってきて駐車場が満杯になっていてもたどり着けるかも....。
P2PやJADEのようなネットワーク内で位置共有すれば、複数間でドラゴンレーダーような使い方もできるでしょう。
(調べてみたら、Androidはデフォルトでアドホックモードが使えないようになっているもよう。初めて知った!Root権限で解除できるようだが...尚、Android 4.0以上ならWiFi Directという手もあります)

考え方は単純で、目的地の方にカメラを向ければ大体の方向と距離を教えてくれる、というものです。
(別にカメラは必須というわけじゃないです、その方が気分が出るというだけの理由です)

こんなんで行けるのかと思いましたが、やってみると.....結構たどりつけるもんです。

使う機能はGPSとコンパスのみです。
(屋内やトンネル内、地下街、住宅密集地などでは測位できないか誤差が大きすぎる場合があって注意が必要です)

目的地に行くには道路の上を歩けばよい!という原理原則(?)が助けになります。

コンセプトはこんな感じです。



というわけで、このアプリは将来的にも「地図」を表示することはないです。

目的地がカメラの視角の「ある範囲」内にあるかどうかだけ判断します。

判断基準は3つ。

1:だいたい前方にある(F)
2:だいたい右(左)前方にある(R,L)
3:カメラの視角から外れている(B)

カメラの向きを変えてみて、

3なら「背後にある」

2なら「そちらにカメラを向ける」

1なら「その方向に進む」

交差点でこれらを行うことで、進むべき方向が分かります。

目的地に着いたかどうかは「距離(D)」でわかります。



追加項目は随時ページの下に記述していきます。

New
レーダーの画像を外部読み込みからCanvaへの描画に変更しました。
これでアンチエイリアスがかけられるようになったので、従来のギザギザ感がなくなりました。
半透明の塗りつぶしをしたので、モーショントラッカーの感じにグッと近づきました(^^)。






アプリを使ってみます。

端末は地面に対して水平にし、横向きで使います。

北の方向に対しては横向きで使うように補正しています。

起動すると、GPS機能を使って現在地の測位を開始します。

こういうメッセージがしばらく出ます。

このアプリは現在地を測位することから始まります。



現在地の測位が終了するとレーダー画面になります。目的地選択をしてください。

目的地の設定のしかたはこのページの下にあります。



メニュキーを押します。





現バージョンで仮実装されている目的地は以下のとおり。

あまり目立たないものを選んでみました。

京都の史跡ですが、京都ネイティブの方でも知らないんじゃないか?という場所です。

羅城門遺址
冷然院跡
土御門内裏跡
ぬえ池跡
化粧水
一条戻り橋

これら以外の目的地を作成する場合は、目的地の設定のしかたを参照してください。

目的地を選ぶと、方向に関するメッセージが出ます。

選ばれたデータはストレージに保存され、再起動時に読み込まれます。

カメラの方向を変えて、おおむねその方向に向いている場合

目的地が400m~100m圏内にある場合は、緑のレーダー上で青い丸で表示

目的地が100m以内にある場合は、赤のレーダー上で青い丸で表示

メッセージの意味
大事なのは方向と距離だけ、括弧内のLはLandscape、それに続くアルファベットと数字は方向と相対角です。
方向がすべて「だいたい」なのは測位された緯度・経度の精度が「絶対」ではないからです。

400m圏外に目的地がある場合

小さな緑色の点がレーダーの圏外の位置をふらふら漂っています。

距離に関係なく方向の目安を示しているだけです。



だいたい前方400m~100m圏内に目的地がある場合



目的地が100m以内に入った場合



交差点なんかで時々スマホの向きを変えて方向を確認します。



チェックは、方位が変わった時とGPSの測位位置が変わったときに行っています。

これを繰り返して距離を縮めていけば、目的地にたどり着けます(たぶん)。

カメラがあさっての方を向いている場合や100m圏外にある場合、青い丸は消えます。





ソースの基本コードはこんな感じ(抜粋)。

【現在地を基準にして北に対して目的地の取る角度】



double dummy_north_lat = current_lat + 0.01;
double dummy_north_lon = current_lon;

double theta_deg = 0;

double ramda_lat = target_lat - current_lat;
double ramda_lon = target_lon - current_lon;



double x2 = current_lon;
double y2 = current_lat;


double x3 = target_lon;
double y3 = target_lat;

double ax = x3 - x2;
double ay = y3 - y2;
double bx = dummy_north_lon - x2;
double by = dummy_north_lat - y2;

double theta_rad = Math.acos(((ax * bx) + (ay * by))/(Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by)));

double temp_theta_deg = Math.round(theta_rad * (180 / Math.PI));

if ((ramda_lat > 0)&&(ramda_lon > 0)||(ramda_lat < 0)&&(ramda_lon > 0)){
    
    theta_deg = temp_theta_deg;


}else if ((ramda_lat > 0)&&(ramda_lon < 0)||(ramda_lat < 0)&&(ramda_lon < 0)){
    
    theta_deg = 360 - temp_theta_deg;
    
}

if ((ramda_lat > 0)&&(ramda_lon == 0)){
    
    theta_deg = 0;
    
}else if ((ramda_lat == 0)&&(ramda_lon < 0)){
    
    theta_deg = 270;
    
}else if ((ramda_lat < 0)&&(ramda_lon == 0)){
    
    theta_deg = 180;
    
}else if ((ramda_lat == 0)&&(ramda_lon > 0)){
    
    theta_deg = 90;
    
}
            


【距離の簡易計算】


double ido_1 = current_lat * Math.PI / 180;
double ido_2 = target_lat * Math.PI / 180;

double keido_1 = current_lon * Math.PI / 180;
double keido_2 = target_lon * Math.PI / 180;


double globe_radius = 6378137;

double ramuda_keido = keido_1 - keido_2;

double cos_d = Math.sin(ido_1) * Math.sin(ido_2) + Math.cos(ido_1) * Math.cos(ido_2) * Math.cos(ramuda_keido);

double temp_cos2=cos_d * cos_d;
double temp_param = (1 / temp_cos2) - 1;
double tangent_d = Math.sqrt(temp_param);
double d = Math.atan(tangent_d);
double distance = d * globe_radius;





トラッカーを追加
管理人が深夜映画で「エイリアン」を観ていた時にモーショントラッカーが出てきて「ああ、これいいなあ」 と思ったんで、似たようなものを追加しました。

以前は外部画像を読み込んでいましたが、カメラ画面と重ねるとジャギーが目立ってました....ので、Canvasにアンチエイリアスをかけて描くことにしました。
グリッドももっともらしく描いてますが、これに関しては何の意味もないです、あったほうが「らしい」くらいの程度。

レーダーが半楕円で目盛りが不等分になっていますが、目的地の点の位置は簡易補正して表示しています。

目的地が400m~100m圏内にある場合は、緑のレーダー上で青い丸で表示

目的地が100m以内にある場合は、赤のレーダー上で青い丸で表示

目的地が圏外の場合やカメラの視角外の場合、青い丸は消えます。







目的地を設定する機能を追加

目的地は3つのやり方で設定できます。

1:SDカードにリストを作って置いておく。リストは編集出来ますので直接データを入力できます。
2:目的地を住所で指定する(ジオコーディング)。住所以外にも著名な施設や場所なら名称で指定できます。
3:測位した現在地の位置を目的地としてリストに追加する。





目的地のリストを編集
Web連携サービスまでのつなぎ機能です。

SDカードに以下のような書式のテキストファイルを置いておけば、既存のリストに続けて読み込みます。

ファイル名:dg_list.txt

文字コード:UTF-8

書式

名前,緯度,経度
名前,緯度,経度
名前,緯度,経度
     ・
     ・
     ・

例:羅城門遺址,34.97935196206374,135.74258364737034


まだリストのデータが無い場合は、こんな感じ。

書式に合わせて作成すれば、SDカードに保存されます。




目的地を住所で指定する







現在地を目的地にする


測位終了後に使用できます。



rec_posという名前でsdcard/dg_list.txtに記録されます。dg_list.txtはprivateモードではないので後でエディターで編集できます。









インストール

Target:Android 2.3.3 or later

動作確認実機:Xperia acro(docomo) Android 2.3.4

インストール・実行は自己責任でお願いします。

またアンドロイドの「設定」->「現在地情報とセキュリティ」を以下のようにしておきましょう。「無線ネットワークを使用」にチェックをいれておくと、精度が上がります。



GPS Status & Toolboxというアプリを使って、A-GPSの補助情報をダウンロードすれば精度が向上するそうです。



アプリをQRコードからインストールする方法はコチラを参照





Bluetoothを使ったものならこんなのもある。面白い。

StickNFind

Bluetooth間の電波強度を使って距離と方向を測位しているようだ。45m内で使え、90mなら相手がいるかどうか推定できるらしい。

方向に関しては、さほど精度は出せていないみたい。

でも、こういう論文もあることだし、将来的にはいけるかも。

Bluetoothの電波強度を用いた位置推定方式の検討

こんな感じで使います。



SDKも用意されているようです。 フォームに必要事項を書いて送信すると、後でメールでSDKが送られてきます。
ただし、iOS版のみですが。

SDKはAndroidにも対応したようです。サムスンは4.2.2で、それ以外は4.3。ただし、4.3にはまだバグが残ってるようです。(2013/10/30)

Androidの場合でも、Bluetooth対応の小型デバイスを使ってRSSIを取得すれば似たようなもんができるんじゃあるまいか?

SONYのSmartWatch MN2ならそこそこ小さいし...。

あるいは、RFIDのアクティブタグを使うという手はどうなんだろう?調べてみよう。





サブGHz帯を使ったもの

Wi-FiやBluetoothの場合、どうしても狭い範囲になってしまう。

もっと広域の場合どうするか、の解決になりそうなのがSigFoxのWhistle

これの新バージョン「WhistleGPS」を使えば、1.6~4.8kmの範囲で、3角測量の原理で緯度・経度を割り出せるようだ。

このデバイスの通信で使われているのがサブGHz帯(920MHz帯近距離無線)。この通信帯域は日本では、2012/7/25に解禁されている。

でも、日本でこの種のものが発売される話はまだ聞かない。基地局が整備されているという話も聞かない。

需要はあるはずだがなぁ。

SigFoxは、これをワンちゃん追跡用に使うつもりのようだけど....。