2012年1月1日日曜日

位置情報取得について調べてみた(その1)

Androidに関する位置情報についての下回りをちょっと調べてみようかと思っています。GPSやその他の位置情報取得に関する記事なんてそれこそ山のようにあるため、あえてエントリにする必要もないのですが、自分用メモということで。

位置情報取得というと、すぐに思い浮かぶのはGPSや基地局情報だったりするのですが、現在はそれらの組み合わせや、Wi-Fiの位置データベースを使った方法など、多くの方法が存在するようです。Androidと直接関係が無いものもあるでしょうが、まずは基礎知識を知らなければ駄目でしょうということで調べてみました。まぁ、仕様書を読んだわけではなく、いろいろなサイトを眺めて歩いただけなので、間違いもあるかもしれませんけど。

位置情報取得方法


・GPS測位
複数のGPS衛星から送信されている電波を受信することで、位置を特定する技術です。
GPS衛星からは、2種類のデータが30秒周期で送信されています。
  - アルマナックデータ (すべての衛星の軌道データ)
  - エフェメリスデータ (自身の正確な位置データとこのデータ発送時の正確な時刻データ)
GPS受信機は、初期状態ではアルマナックデータを使い、位置測定に利用できる衛星を確認し、最初のエフェメリスデータの時刻情報で時刻を設定後、次のデータでデータ受信の遅延を計測することで、衛星までの距離を計算します。
これを最低3つの衛星で繰り返すと、三角交差法を使い、経度と緯度を導きだす事ができます。4つの衛星で行えば高度も出せるという仕組みです。。
アルマナックデータはだいたい1週間程度、エフェメリスデータは1時間半程度は有効なため、2つのデータの有効時間中は、時刻情報から距離を割り出すだけで、位置情報を取得できますが、データの存在しない初期処理からの測位では数分、その後の位置情報収集は最低でも30秒程度はかかるようですね。

・DGPS(Differential GPS)
もともとGPSは軍事目的の衛星で、軍用に使う正確な位置を割り出せる暗号データとあえてノイズを含めた若干不正確なGPSデータを送信していたそうです。
このため、一般の利用では、100m程度の誤差がでていたものを補正するために考案された手法で、位置のわかっている地上の基地局との比較で誤差補正を行い制度を高める技術です。

・A-GPS(Assisted GPS)
GPSは、情報の取得を開始してから最低でも30秒程度、最悪数分間は位置を特定できません。また、起動データや位置データの受信は建物内にいるとノイズによりデータ受信は難しく、位置の特定が困難になります。
携帯電話は、例えば基地局情報などで、携帯端末のおおざっぱな位置が特定できています。そこで3G回線等別の経路で全衛星軌道データと、衛星位置情報を取得し、GPSからは比較的ノイズに強い時刻情報だけを取得することで、位置情報をGPSより高速に、建物内でもわりと正確に特定できるようにする技術がA-GPSです。


・セルベース測位
現行の携帯電話は、セル方式というものをとり、無線基地局を多数設置し、ある一定の範囲に留めることで、同じ周波数帯域をできるだけ再利用するように設計されているそうです。セルというのは、無線基地局の電波が届く範囲の事になります。携帯電話に通知を行うために、携帯電話が最後に確認できたセルIDが記録されており、定期的に更新されています。このセルIDを元にどの位置に居るのかを特定するという技術です。
携帯でGPSサービスと言われるものが出始めた初期の頃は、実際にGPS受信をしておらず、このおおよその位置情報を使った機種も多かったようですよね。
位置に関する誤差については、セルの広さによりますので、狭い範囲に設置されている都市部は小さく、田園部とか湾岸部等の場合は誤差が大きくなるようです。

・基地局測位
この辺りからキャリアによっていろいろ変わってたりするようで、いまいちつかめていません。
KDDIでは、3つ以上の基地局との同期信号を使って、位置を計算するようです。GPSの衛星からの時刻データの代わりに、基地局との同期信号を使うことで測定するようですね。
DoCoMoさんでは、基地局に同期された時間情報を持っていないため、何か別の方法で測位しているようですが。
ウィルコムは、アンテナの受信強度等から特定しているような記載をみかけましたし、
ソフトバンクはどうなんだろう。もうちょっと調べてみたいなと思っていますが、とりあえずおいておきましょう。

・Wi-Fiアクセスポイントによる測位
Wi-FiのアクセスポイントのMACアドレスと位置情報のデータベースを使って、現在の位置を特定する方法
ローリングで都市を回り、Wi-Fiのアンテナ情報を一気に収集したものと位置情報をあわせて保持している企業のデータを使って特定するようなので。そういえば、僕のHTC AriaのWi-Fiの位置が、自宅に登録されていそうなんですよね。外出先でAria経由で接続すると自宅に居る事になるし・・・・。


とまぁ、こんなあたりが、ざっと主要な位置情報取得技術となるでしょうか。


Android Frameworkでの実装
さて、ようやく本題のAndroidについてです。
いきなり下回りのコードを読むにもあたりがつかないとならないので、クライアント側でおこなうサンプルをみながら、キーになる所を抜粋してみてみました。

(1) LocationManagerの取得
LocationManager locMgr  = (LocationManager)getSystemService(LOCATION_SERVICE);

(2) 最適なLocationProviderを選択
Criteria criteria = new Criteria();
String provider = locMgr.getBestProvider(criteria, true);

(3) 最後にわかっている位置情報を取得
Location location = locMgr.getLastKnownLocation(provider);

(4) 定期的に位置の変化を取得するためのListner登録

LocationListener listener = new LocationListener() {
    @Override
    public void onLocationChanged(Location location) {
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }
};

long minTime = 15000;
float minDistance = 1.0;
locMge.requestLocationUpdates(provider, minTime, minDistance, listener);

とすると、minTime[msec]以上の間隔で、minDistance[m]以上の変化があれば情報が取得される事になります。


(5) 経度、緯度、高度等の情報から住所情報への変換
Geocoder geocoder = new Geocoder(context, Locale.JAPAN);
List<Address> addressList = geocoder.getFromLocation(latitude, longitude, 5);

(6) GPSの状態取得/衛星情報の取得
GpsStatus gpsStat = locMgr.getGpsStatus(null);
Iterable<GpsSatellite> satellites = gpsStat.getSatellites();

(7) GPSの状態変化イベント取得方法

GpsStatus.Listener statListner = new GpsStatus.Listener() {
    @Override
    public void onGpsStatusChanged(int event) {
        switch(event){
        case GpsStatus.GPS_EVENT_STARTED:
            break;
        case GpsStatus.GPS_EVENT_STOPPED:
            break;
        case GpsStatus.GPS_EVENT_FIRST_FIX:
            break;
        case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
            break;
        }
    }
}
locMgr.addGpsStatusListener(statListner);


とまぁ、位置情報周りの主要なクラスの使い方というのはこんな所でしょうか。

アプリ側は、管理クラス LocationManagerから位置情報を提供するLocationProviderを選択し、Locationを取得するという流れとなっています。ここまで見た感じだと、Frameworkの実装としては、位置情報はGPSに限らずProviderから取得できるように設計されており、アプリケーションは、Criteriaを使ってProviderの条件を取得して、適切なProviderを選択させる事が可能です。もちろん、getBestProvider()を使わずに、providerにLocationManager.GPS_PROVIDERを指定することで、GPSの情報だけを使うようにも実装できるわけですが。

どんなProviderが実装されているのかについては、List<String> getProviders(boolean enabledOnly); を呼び出せば、取得できるようですね。あとで、自分の端末で試してみようかな。

各クラスの詳細やその先の実装はまた次回ということで。

2011年12月31日土曜日

無事暮れまして、お疲れさまでした。

しばらくブログを放置しておりました。ごめんなさい。12月に1個技術な記事を書こうとしたのですが、なんだかアクセス数がすごい事になっていて、怖くなったので、落ち着くまで待とうとか思ってみたりして。ようやくアクセス数も落ち着いてきましたが、もう正直どうなることかとヒヤヒヤものでした。とりあえず、技術のエントリは年明け後落ち着いてから書き直すということで。

さて、今年もあと1日を残すばかりとなりました。

3月の震災では、人生の3分の1を過ごした東北の地に多くの被害があり、連絡のつかない友人も。今もその爪痕が残っており、今年は出だしから心の痛む辛い始まりでした。
このブログにも募金のリンクをはったり、災害情報のリンクをはったりしつつ、心を痛めている余裕も失わせる頻繁な計画停電。23区では全く関係なかったそうなのですが、対象地区でシフト制のため、朝5時起きとか、仕事の途中に4時間抜けて時間つぶしとか、厳しい日々もありました。



また非常に親しくさせていただいた、ある会社の社長さんが42歳で急逝。前日にジンギスカンを食べたいとおっしゃっていて誘いを受けたのですが、ハードな計画停電生活で疲れもあって参加をお断りしたところ、翌朝におおきな鼾をかきはじめ、眠ったまま、逝ってしまわれたそうで。最後の一日にご一緒できなかった事が、今も悔やまれてなりません。
いつも一緒に飲む仲間内だと、危ない下ネタ話に花を咲かせて場を和ませる方でしたが、二人で話す機会があった折、某社の愚痴をこぼしてしまった際には、技術者というもの、仲間というもの、会社というものについて、いろいろご意見やアドバイスをいただきました。特に今在籍している?会社の社長と非常に仲がよく、全くタイプが違うこの二人が組んだら面白い会社になりそうだと思っていたのですが、非常に残念でなりません。

その後、少し間をあけて初の海外出張。読む方は兎も角、英会話には全く自信がなかったものの、退職のためにこちらから契約終了をお願いする形となり、お客様にお詫びと今までの感謝の気持ちもあって引き受けました。無理を言ってすいませんとお客様はおっしゃってくださいましたが、なんとなく、海外でも片言でなんとかなるという驚きと、肌で感じる文化の違いなど、とても良い経験をさせていただきました。まぁ、結果として、ABC 2011 Summerでは、突然の発表キャンセルで、PF部の部長さんには大変ご迷惑をおかけしてしまったことだけが、心残りでしたが。

帰国直後には、待っていてくださったかのような伯母の死。長い事、ガンを煩っていたこともあり、そろそろ危ないとの連絡も入っていたので、どこか覚悟していたことでしたが、人の死には慣れる事ができませんね。急遽生まれ故郷へと伺いました。父と年がだいぶはなれており、戦後の辛く貧しい中を生きてきた逞しい方でした。きつい事をはっきりという方で、幼い頃からちょっと苦手でしたが、何かというときに「がんばんなさい」と背をたたいてくれる、そんな姉御肌の素敵な方でした。葬儀の後、執筆されていた句集等の書籍を数冊頂いて読んだ中には、そんな辛い中で生きてきた思いが綴られており、つまらない事で、くじけたり負けていられないなと決意を新たにさせていただきました。

そして9月末の退職。5年間、辞めたい、辞めるといっては、同僚や上司役の人に引き止められ、お客さんへの迷惑を考えてタイミングを逸し続けながら、粘りに粘ってようやくこぎ着けた決別。まぁ、本当は、紙を1通出せば良いのは知っていたのですが、先に辞めた人達にあきれられながら、お客様や残る人に迷惑をかけないタイミングを探していたらこんなにかかった訳で・・・。

この不景気に、また個人事業主へと逆戻り、ほとんどフリーランスのような立場で、仲間内の小さな会社の名前での再出発です。厳しい綱渡りながらも、充実した日々へと踏み出しました。こういう危ない橋を突っ走る時には、独り身で良かったと思います。クリスマスなんかでうかれやがって、リア充爆・・・なんでもないです。

12月はというと、退職後に忙しくて放置していたのに、誰がはじめたのか、退職エントリーが2ヶ月後にいきなり大ブレイク・・・会う人にはその話をされるし、かなり恥ずかしかったです。2ヶ月もたったら勢いで書いた気持ちも収まって忘れかけてたというのに、蒸し返されてもねぇ・・・。だいたい、一応似非とはいえプログラマ。技術について調べた内容を書いたエントリよりも、よく経営をわかっていないエンジニアの与太話と一刀両断されてもしょうがないエントリの方が人気がでるって・・・。

もともと、某社に残った方で目を通してる物好きさんと、新しく一緒にやっていきましょうという話になっている数名とのために、どこかで同じところにハマりこまないようにエラー処理を考えましょうね、くらいのつもりで書いたんですが。

はてぶやtwitterやGoogle+でいろいろな方がコメントしたりして下さっていたようなのですが、そんなに大仰にするつもりで書いた訳でもないので、ひっそりと見なかった事にしています。ごめんなさい。

強いて挙げるなら

・成長にかかる時間が長すぎない?
・時間ではなく人数で変わると思う
・技術者を一括りに一種類しかいないようにするのは間違っている(俺は変態ではない?)
という意見が、その通りかもしれないなと思いました。

身近で見て、知っている、受託や人売りが中心の、わりとよくある技術系の会社だと、だいたいはあの程度の時間がかかっていて、僕が技術者に区分している周りの技術者は、たいてい変態なので、ああいう記述になったわけで。僕自身、すべての技術者の統計を取っている訳でも、すべての技術会社の推移の調査をしているわけでもないので、この意見はごもっともです。時間軸についてなどは、斬新なアイディアや商品のあてがあり、大きくお金が借りられるような本格的な技術会社だったら、あの時間軸でやってたら、絶対に駄目でしょう。

だから、おそらく、人の数で変遷を見るという意見が正しいです。ま、一応、周囲の例とか、関わった組織の変遷や、今まで読んだ書物、この目で見てきた人とのつきあい方の移り変わりを考えて、なんとか破綻せずに長過ぎず、短すぎずに変遷していける時間軸だとは思っているのですけど。


せっかくだからこのエントリも読んでおこうと、ただ長いだけのこの駄文をここまで読んだという物好きさんにアドバイス。前のエントリにも書いたはずなのですが、あれは「違った未来があったかもしれない」レベルの、会社が育つ時にたぶんエラーチェックをすべき小さなif文のお話しで、間違えなければ成功しただろうという話ではないのです。そこだけは忘れないでくださいね。
ファイルを書き込み権ありでopenできたからといって、writeがすべて成功して無事にファイルができるなんて考えたら、それこそ大事なデータを保存できずに気がつかない深刻なバグが入り込むわけで。

まぁ、ぶっちゃけてしまえば、孟子に天の時、地の利、人の和とはあるけれど、所詮、天の時だけでも勝つ時は勝つし、人の和だけあっても負ける時は負けますよ。たぶん。
ま、天地人のすべてを揃えれば、良い線いけるんじゃないかとも思いますが。

あまり具体的に何があり、どう失敗したのかなんて、実際書くといろいろ問題あるわけではしょって書いていますし、かなり大雑把に人の和を忘れて突き進んだら失敗したね。それじゃ駄目じゃない?という、昔からある、人の和は大事だよねという確認を、ちょっと会社というものの成長を交えて書いただけで、特別な事でもなんでもないはずなんです。それこそ、そんなエントリーに興味をもつような、経営にまで手をだそうかと思う人なら、人の理は、己の道を隠す霧なりということで、自らの信念をもって、どうか自らの理想の形で、生き残りをかけた戦いに出かけてください。

え、僕の理想の形ですか?個人事業主でこの自分の身一つ支えられるかも不安なんですが。第一、経営なんてつまらない事に力を割く時間があるのなら、がしがしコードを書きたいよね?というのが本音です。

まぁ、経営に口を出しはじめたなら、技術者に甘い事ばかりを言う駄目な経営者になりそうだなぁ。技術者には、せめてプロジェクト単位の準個室とか、仕事の速さや顧客の満足度によっては完全な個室を与えて、電話は受付事務の人を必ず通して技術者部屋には音を漏らさない。椅子は20万しようが腰の痛くなりにくい良いものを使い、常に、できるだけ早くコンパイルできるPCと、さくさくWebの見れるネットワーク環境を揃える。各個室には窓があって外を見る事もでき、仮眠室も用意する。いや駄目だ。あっという間に資金つきますねぇ。無理です。

何ともまとまりの無い記事になってきましたので、いい加減ここまでにしましょう。一年を振り返りつつ、どうでも良い話が長くなりすぎました。

そんなこんなで、僕にとっては激動の一年でした。親しい方、憧れていた方を失いながら、涙の多い一年でした。今年心に刻んだのは、一期一会。今までであった出会いも、これから出会う出会いも、その時々をできるだけ大事にして、来年もまたがんばって行きたいなと思います。

という、無駄に長い雑記を、とりあえず奇麗な言葉でまとめたあたりで、この一年の終わりとさせていただきます。それでは、皆様良いお年を。


2011年10月1日土曜日

退職しました

皆様大変お久しぶりです。日本に帰国後、色々と忙しくしていた隠者でございます。
まぁ、ツイートをごらんになった皆様はご存知のように、昨日、常駐先での業務を完了し、同時に退職となりました。

当時、十数人の創業10年目の技術者集団に、2年以上にもわたり勧誘を受け、ぜひ一緒に仕事をしたいという言葉に誘われて、入社を決意したのが2002年末。当時は、「会社なんかいつ無くなっても仕方ない」といい続けてきた技術集団を、きちんとした会社にしなければと感じた最年長の経営にいた技術者が、「ビジョンがある」という営業出身者に代表権が移ってから10年。

結局、会社への変革はできず、技術者の稼ぎから行った投資が実らず、いつの間にか当時の技術者が一人、また一人と去り、かつての技術者が育ててきた親会社の信用を生贄に子会社に従業員全員強制転籍なんて荒業まで行われました。そんな会社で、去り行く人たちを寂しく見送りながら、友のため、お客様のためにと、無駄にあがいてきましたが、ようやく一区切りをつけ自分自身を送り出す事ができました。

そんな流れに身をおきながら、とある経営者の人となんとなく語りあった内容を少し思い出しながら書いてみようかと思います。大して面白い話でもないので、適当に読み捨ててください。