S98Player Ver. 0.2を作った

4年ほど前にFM音源のサウンドログを再生するアプリを作ったのですが,最近FM音源づいていてちょっとだけコードを修正したので公開します.機能は全く変わっておらず,使い勝手も悪いままですが.

…そして誰も使わないとは思いますが.

修正点は以下の通り.

  • サンプリング周波数を44100Hzから55466Hzに変更.原音に近くなりました.
  • S98v3のヘッダをもう少しきちんと読むように.UTF8,SJIS両方読めます.
  • しかし基本的にOPNAのみの対応….
  • 10.5SDK上でコンパイルしたので10.5以降でしか動かないかも.

OPNへの対応は,サウンドログファイルをもってないのでチェックできないんですよね.ま,基本的に自分用アプリなので問題ないんですけどね(無駄にiPhone向けに移植して一人楽しんでます).

続・FM音源の仕組みを視覚的に理解する

前回のエントリで簡単なFM音源もどきを作ったわけですが、どうも物足りなく感じたため(というか、なんとなく達成感がないというか…)、並列接続も可能な4オペレータ版を作成しました。

そして、オペレータ接続アルゴリズムも8種類から選べるようにしました。

単音しかなりませんが、機能的には、往年のYM-2203音源などと同じ程度のパラメータをいじれます(多少少ないんですが)。

FM音源って?

という方は、是非前エントリをご一読ください。

ダウンロード

となります。

使い方

まぁ、大したことができないのは相変わらずですが…。

右下のプルダウンメニューでアルゴリズムが選べますので、それを選ぶと各オペレータの接続アルゴリズムが変わります。用意した接続アルゴリズムは8種類で、これはYAMAHAのOPN系音源に準じています。

接続アルゴリズムを選ぶと、プルダウンメニューの下に接続の模式図が現れますので、雰囲気はつかめるはずです。

感想

単純な直列だけだと「ふーん」ってな感じでしたが、並列もできるようになるとかなり音が「それっぽい」感じになりました。

最終の出力の手前部分が並列になっているもの(Algorithm 4など)は特に、直列では聞けなかった音が合成されますので、楽しいです。

まとめ

相変わらず実用性皆無のアプリではありますが、往年のYAMAHA製FM音源であるOPN系音源における音色作成くらいは追体験できるのではないかと思います。

気に入った方がいたら、是非アフィリエイトサイトで本でも買ってやってください(笑)

FM音源の仕組みを視覚的に理解する

FM音源って知ってますか? 今じゃ表立って耳にする機会も少ないですが、つい最近まで携帯電話の着メロなんかはこのFM音源を使ってました。

「機械っぽい音」なんていわれるとまぁその通りではあるんですが、往年のNEC製PCなどで使われていたこともあり、独特な音にファンも少なからずいたりします。

このFM音源、「FM (Frequency Modulation)」と名のつく通り「周波数変調」を利用して音を作っているのですが、これがイマイチよく分かりません。いや、Wikipediaの当該ページを見ると波形を導き出す式も載っていますし、それはそれで分かるんですが、その式をいくら見たところで「どんな音がするか」がよく分からない…。

様々なサイトで「周波数変調は、扇風機の前で声を出すとあ”あ”あ”あ”あ”〜〜〜と音が変わるのと同じ原理です」なんて説明されていたりするのですが、この説明は周波数変調がわかっている人にしか理解できないものだと思うのです。

…というわけで、式を見ても分からないなら手を動かせ、ということで、単純なFM音源を鳴らすプログラムを組んでみました。 各オペレータの波形をリアルタイムに表示させて、パラメータをいじるとどのように波形が変わるのかが分かるようにしてみました。

とりあえずお披露目

Cocoaアプリを作りました。何も考えずに作ったのですが、もしかしたらSnow Leopardでしか動かないかもしれません。 ソースも置いておきます。他人に見せるために書いてないので汚くてコメントないですが…。

ま、適当にいじってみてください。大したことはできませんが…。 頭では原理がわかっていても、パラメータをいじると実際に波形が変わるので、見てるだけで(個人的には)楽しいです。 また、パラメータだけだと想像つかなかった音色も、波形を見ればだいぶ想像しやすくなる気がします。

FM音源のキホン

Wikipediaの説明を読むと、FM音源の基本は周波数を変調することだそうですが、どう変調するか、そこがキモのようです。 昔の数学やら物理やらの授業の記憶を掘り返し、頑張って正弦波(sin波)の基本公式を思い出してください(笑)

y = A sin (2 π f t + φ)

ってやつですね(Aは振幅、fが周波数、φが初期位相、tが時間)。

この中でA, f, φが一定であれば普通の正弦波になるわけですが(tだけ時間に合わせて値が変わる)、FM音源は、ここのφの部分も時間に応じて変化させて複雑な音を作り出します。

φをどうやって時間変化させるか

基本的なFM音源の場合、φを、さらに別の正弦波を使って時間変化させます。 これが、キャリアとモジュレータの関係みたいですね。キャリアがメインとなる正弦波を作るオシレータ、モジュレータがキャリアのφを時間変化させるオシレータです。

キャリアとモジュレータの周波数は同じでなくても構いません。 ただ、モジュレータの周波数がキャリアの周波数の整数倍でないと、音がキャリア周波数の高さに聴こえません。 これは、整数倍でないときに

y = A sin (2 π f t + φ)

のsinの中身が、キャリアの1周期ごとに0にならなくなってしまうからです(ちょっと計算してみるとわかります)。

エンベロープジェネレータを使ってさらに変化させる

エンベロープジェネレータの説明はWikipediaなどを読んでいただくとして。 楽器から音が出始めてから終わるまで、音量は一定ではありません。オルガンなどは鍵盤を押した瞬間に最大音量となり、離すと音がプツリと消えますが、ピアノであれば鍵盤を話しても弦が揺れて少しのあいだ音が鳴り続けますし、バイオリンなどは音の出始めがゆっくりです。

FM音源の場合、キャリアに対してエンベロープ変化をつけると、上記のように「オルガンっぽい音の出だし」から「バイオリンっぽい音の出だし」といったように音量を変化させることができます。

しかしさらに複雑なことに、モジュレータの出力に対してもエンベロープジェネレータを使って変化させることができます。 これによって、キャリアから出力される波形が最初は普通の正弦波なんだけどだんだんφが大きくなって違う音になります。つまり、エンベロープジェネレータをモジュレータの出力にかけることによって、音量だけでなく音色まで変化させることができるようになるわけです。

どうやってコーディングしてるか

FM音源のオペレータは、構造体で以下のように定義されています。

struct _FMInfo{
    double isFB;
    int isEnabled;

    double carrierFreq;
    double freqIndex;
    double modIndex;

    double attack;
    double decay;
    double sustain;
    double release;

    int numOfParents;
    FMInfo** parents;
};

そして、ある時間の波形の高さは、以下の関数で計算しています。ほんとに、上記の公式を愚直に計算してます(笑

double fmGetValue(FMInfo* fm, double sec){

    double parentPhase = 0.0;

    for (int i = 0; i < fm->numOfParents; i++){
        parentPhase += fmGetValue(fm->parents[i], sec);
    }

    if (fm->isFB > 0){
        double value = 0.0;
        double beta = M_PI * fm->isFB / 8.0;

        for (int i = 0; i < 20; i++){
            value = sin(2.0 * M_PI * (fm->carrierFreq * fm->freqIndex) * sec + beta * value);
        }

        return fm->modIndex * value * fmGetPower(fm, sec);

    }

    return fm->modIndex * sin(2 * M_PI * (fm->carrierFreq * fm->freqIndex) * sec + parentPhase) * fmGetPower(fm, sec);
}

fmGetPowerという関数はエンベロープジェネレータでの高さを計算する部分です。 今回は、「鍵盤を離した」部分は「音が鳴り始めたら4秒」と決め打ちにしているので、以下のようなコードになっています。

double fmGetPower(FMInfo* fm, double sec){

    double power = 1.0;

    if (sec < fm->attack){
        power = sec / fm->attack;
    }else if (sec < fm->decay + fm->attack) {
        double t = sec - fm->attack;
        double w = (1.0 - fm->sustain) * t / fm->decay;

        power = 1.0 - w;
    }else if( sec < 4){
        power = fm->sustain;
    }else if (sec > 4 && sec < (4 + fm->release)) {
        double t = sec - 4.0;
        power = fm->sustain * (1.0 - t / fm->release);

    }else if (sec >  + fm->release){
        power = 0;
    }

    return power;
}

興味のある方はソース中にあるOperator.hおよびOperator.cをご覧下さい。綺麗ではありませんが、どうなっているかは理解できるのではないかと思います。

オペレータの並列接続

今回のアプリは、キャリアとモジュレータ2つの3オペレータを直列につないだものしか音が出せないのですが、実際には並列接続のものもあります。 並列接続は、いわゆる波形の合成です。周波数をいじるのではなくて、単純に足し算ですね。

上記のコードを読んだ方はお気づきかもしれませんが、コード内では既に並列接続の計算もできるようになっています。ただアプリのUIが複雑になるため、今回はパスしました。暇があったら作るかもしれません。…作らないかもしれません。

まとめ

FM音源の原理はわかっていてもイマイチどういう音が出てくるのか想像できなかったため、簡単なFM音源もどきを実際に作りました。 パラメータをいじって音色を確かめられるだけではなく、波形がリアルタイムに変わることで、パラメータを意図して変化させることも容易になるかもしれません。

今回のアプリではオペレータの並列接続はサポートしていませんが、いつか暇ができたら(そして興味がつづいていたら)実装するかもしれません。 AudioUnitで動く音源を作るのも面白そうですが、そこまでできるかなー。

蛇足

エントリと直接関係ありませんが、右にある本はiPhoneでCoreAudioをいじくるにはとても良い本です。少々値段が高いのですが、iPhone / iPad / iPod touchで音楽をいじるにはこの本は必須だと思います。どうもCoreAudio系はAppleの技術文書が少ないイメージがあり、このように系統だって(それも日本語で!)まとめられた本があるのは助かります。

実はこの本の中にシンプルなFM音源ドラムマシンの実装があり、最初はこれを参考にiPadアプリを作ろうとしていました(オペレータ間の接続をタッチで行ったりできると楽しいなぁ、と)。

ただiPadよりもまずは慣れたMacでやろうということで、ひとまず上記のアプリになりました。また、波形生成のアルゴリズム部分に関しても、オペレータの並列・直列やフィードバックなどを盛り込んだため、異なった実装になっています。

補足

次のエントリに4オペレータ版で並列配置も可能なものを公開しました。よろしければご覧になってください。

On-vehicle movie overlaying vehicle information using CANUSB

I overlaid various vehicle information (i.e. speed, rpm, and so on) extracted by CANUSB on my on-vehicle movie.

HS-CAN Data

At first, I tried to use information posted by Madox.NET, but unfortunately HS-CAN Data extracted by my RX-8 look totally different from Madox’s one.

I’m not sure why there are big differences. But one possible reason is that Madox’s RX-8 is AT. My RX-8 is 2007 5MT model.

  • RPM: ID 0x201, (data[0] * 256 + data[1]) / 4
  • Vehicle Speed(km/h): ID 0x201, (data[4] * 256 + data[5] – 10000) / 100
  • Accel Throttle Position(0 – 255): ID 0x201, data[6]
  • Hand Brake(on/off): ID 0x212, (data[4] & 0x40)
  • Foot Brake(on/off): ID 0x212, (data[5] & 0x08)
  • Declutching(on/off): ID 0x231, (data[0] & 0xf0)
  • Engine Coolant Temp(degree celsius): ID 0x240, data[3] – 40
  • Intake Air Temp(degree celsius): ID 0x250, data[3] – 40

Here is what I analyzed.

I want to extract some more information such as steering column angle, but I haven’t yet.

Overlaying

I used Apple’s Quartz Composer for overlaying information.

CAN + Quartz Composer + 車載動画 = PS4動画?

CANデータを使った動画、もう少し派手めに…ということで、作ってみました。 といっても、CANのデータからいちいち速度などの情報を手で入力していては日がくれてしまうので、それらを自動でレンダリングする術を考えなければなりません。

今回は、Quartz Composerのカスタムパッチを作ることでCANログをQuartz Composerに取り込むことにしました。

Quartz Composer?

Quartz Composerは、いわゆるビジュアルプログラミング環境です。Mac OS Xの開発環境(無料)に同梱されています。

これを使うと簡単にモーショングラフィクスを作成できるのですが、当然のことながらCANデータログを読み込んでくれるようなパッチはありませんので、それを自作することにしました。

昔はカスタムパッチの作成手順は公開されていなかったので面倒でしたが、今はオフィシャルの情報をたどると簡単に作ることができます。 Objective-C 2.0のプロパティなどを使うことで、パッチのポートの宣言なども煩雑にならずにできるようになりました。

Quartz Composerのオフラインレンダリング

QuickTime 7の時代には、QuickTime PlayerをPro版にするとQuartz Composerのパッチを動画として書きだすことができました。 Mac OS X 10.6になってQuickTimeはQuickTime Xに刷新されましたが、一応オプションでQuickTime 7をインストールすることができます。

最初はこれでなんとかなるかと思っていたのですが、どうやらカスタムパッチを含むコンポジションの場合は、セキュリティなどの問題でQuartz Composer以外では無効にされてしまうようです。

Appleのデベロッパ向けのサイトにQuartz Composer Offline Renderingというサンプルコード(最初の10フレームを書き出す)があるのですが、どうもコードが古いせいか、きちんと静止画を書きだすことができませんでした。色味などがおかしい…。

しかし、Leopard時代から書き出し関係で新しいメソッドが用意されており、そちらに書き換えるとうまく静止画を書き出すことができました。それらを30fpsで全フレームをレンダリングし、最後にフレームをまとめて動画にする、というようにプログラムを書き換えました。

このOffline Renderingに関してはそこそこ需要があるような気がするので(そもそもQuickTime 7を入れたくないですし、Proにするのが無料じゃないですし)、次のエントリでまとめて説明、配布しようと思います。

まとめ

CANデータを車載動画にかぶせるようなものを作るため、Quartz Composerのカスタムパッチを作成してレンダリングしてみました。

今回の動画は、ビデオカメラで撮影した動画を運転終了後にCANのログと重ねあわせましたが、USB接続のWebカメラなどを使えばリアルタイムレンダリングも可能だと思います。

これで生放送とかしても面白そうですね。

CANデータを見るプログラムを動画にしてみた

先般のエントリにてRX-8のCANデータをグラフにしてみましたが、リアルタイム情報を車載動画にピクチャインピクチャとして重ね合わせた動画をつくり、ニコニコ動画にアップロードしました。

今までは見る専門だったので、どの程度の方に見て頂けるかはまったく未知数でしたが、一日経たない間に300人以上の方に見て頂けたようで。 人気動画とは比べものになりませんが、場末のブログにひっそり置いておくよりはよっぽど見て頂けるので嬉しいです。

次はもう少し派手目に作ります。

iPhoneのSafariを使って走行中の道路名をtweetしてみた

というわけで、サーバに展開した国交省のデータを使って、実際にTwitterでつぶやくようなアプリを作ってみました。

といっても、専用アプリを書くのは面倒なので、ひとまずはiPhoneのSafariからGPS情報をサーバに送りつぶやくようにしてみました。

仕組み

iPhoneのSafariは、JavaScriptを利用して現在位置を取得するGeolocation APIに準拠しています。そこで、定期的にiPhoneから現在位置をサーバに投げてやり、サーバ側で道路名を解析してTwitterにツイートさせてやるような仕組みを作りました。 iPhoneのSafariでGPS情報を扱う方法は、Ascii.jpのiPhoneのGPSをJavaScriptで操ろうという記事が参考になります。

…というか、今回やったことはこの6ページ目にあるサンプル03をちょいといじっただけです。

ここのソースコードにupdate関数があり、位置情報が更新された際に呼び出されます。結構これは頻繁に呼び出されるので、たとえば10分おきにサーバに情報を伝えたい、なんてときには、update関数の最後あたりに

var now = new Date();
if ((now.getTime() - before.getTime() ) > (1000 * 60 * 10)){
    before = new Date();
    updateStatus();
}

こんなのを埋め込んで、10分おきにupdateStatus関数が呼ばれるようにすれば良いです。

そして、updateStatus関数内では、lat変数とlng変数を利用してサーバ側にデータを渡してやります。ここではXMLHttpRequestを使います。たとえばこんな感じに。

var url = "http://your_site.com/rest.jsp?lat=" + lat + "&lng=" + lng;
var myRequest = new XMLHttpRequest();
myRequest.open("GET", url);
myRequest.onreadystatechange = function(){ 
    //readyState値は4で受信完了
    if (httpoj.readyState==4){ 
        getServerResponse(httpoj)
    }
}
myRequest.send(null);

そしてまぁ、urlからの返答如何によっては再送したりなんなりをgetServerResponse内で実装してやれば良いです。

サーバ側では、前回までに作ったDBでHibernateを利用しつつ道路名を割り出し、Twitter4Jを使ってツイートをしています。

できばえ

まず大学まで、いつもとは全然違う道をとおって走ってみましたが、うまくいきませんでした。これは単純に道路名割り出しルーチン内で、しきい値がやたらシビアだったためでした。

そのため大学でちょっとプログラムを書き直し、またいつもとは全然違う道を走って動作確認をしたところ、そこそこうまくいっているようです(それが上の図)。 ただまぁ、例によって15年前のデータなので「浦和東村山線」なんて道路名が出てきたりしてますが、現在は「さいたま東村山線」だったりするようです。

最新のデータについては、先日国交省にもらえないのかメールしてみました。担当者に確認の後返事を頂けるようですが、どうも「公開していない理由」を担当者に確認するみたいな雰囲気なので、あまり期待せずに待っています^^;

まとめ

常にツイートし続けるのはどうかと思いますが、どっか遠出するときとかはおもしろいかもしれません。そこそこうまくツイートできてるっぽいですし。 今は一定間隔でツイートしてますが、道路が変わったらツイートする、なんてのも面白いかもしれませんね。

せっかくなので道路をGoogleMaps上にプロットする

前回のエントリで記したとおり、自分が道路上にいるかどうかを調べるためには、そもそも道路のデータを保持していなければなりません。

このデータを使って地図上に高速道路や国道のラインをプロットすることが出来ます。

最初、前回のエントリで作ったデモに組み込もうと思って試しにやってみたんですが、位置データが多すぎるため、blazedsを使って単純にサーバからクライアントにプッシュするとTomcatが落ちてしまいました…(たぶんシリアル化する時に落ちてる)。

GoogleMaps APIを調べてみると位置データをエンコード化して読み込ませるというオプションがあったので、サーバ側でデータをエンコードした上でクライアントにプッシュすることで、そちらを実装してみたらうまくいったので公開します。

あ、そうそう、前回のデモでは関東圏だけしか動きませんでしたが、DBをアップデートしたので、今は日本全国調べられます。

説明

前回のデモに追加で実装したので、前回のサイト(停止しました)を訪れて同じように動かすだけです。

前回は、地図中心点に道路があるかどうかを調べ、道路に名前がついていればその旨表示するだけでしたが、今回はそのあとに表示されている地図の範囲の道路位置データをダウンロードしてGoogleMaps上にプロットします。 ダウンロードするのに最大で10秒くらいかかるかもしれないので、気長にお待ちください。

また、ある程度地図の拡大率が低い場合には、中心付近を一部だけロードするようにしています。DBのロード、データエンコード、クライアントへのプッシュ、クライアント側での描画、ととんでもなく時間がかかるためです。

また、手抜きプログラミングのため、同じ場所を拡大したとしても再度全てのデータを読み込み直します。ほんとはバッファとか用意した方が良いんでしょうが、重複判定するのも面倒だったりします。クライアント側にDB持ってるとそのあたりも柔軟にできるかもですが。

なんでこんなの作ったか

前回の道路名を調べるデモですが、結構条件がシビアで、きちんと場所を合わせているつもりでも道路名が出てこないことがあり、(作った本人が)いらいらしておりました。

まぁ、どこまで判定をシビアにするかというのはパラメータをいじれば済むのですが、あると思っていた道路が95年現在はなかったため道路名が表示されない、とか、そもそも道路名が登録されていないために表示されない、といった場合には、その場では原因がよく分からず「おかしい…」と悩んでしまったのでした。

であれば、DBに登録してある道路を周辺地区だけでもプロットし、そもそもDBに登録されているのか否かを調べられるとよろしい、ということで作ったのでした。

その他

現在は高速から一般道まで全て同じ色で表示していますが、色を変えたり、チェックボックスで表示する道路を選択できたりすると面白いかもしれません。

位置データのエンコードは、エンコード化ポリライン アルゴリズム方式というGoogleのページで説明されているのですが、いまいち日本語がよくわからず…。 検索したら、こちらのサイトにて、まさに合点のいかないところがシンプルに説明されており助かりました。

緯度経度から、その場所を走っている道路名を調べる

うわー、これまたタイトルからしてニッチ(笑

最近、「流行っている」と形容するのも恥ずかしいtwitterですが、「○○なう」などとつぶやいている人が結構見受けられます。「○○」にはその時訪れた場所だったり、その際やっている行動だったりが入るわけなんですが。

これ、車の運転中にはできないですよね、危なくて。なので、つぶやきをそれっぽく自動化できないか考えてみた訳なんですが…。

前回のエントリでは車の中を流れる各種データを取り出すことが出来たので、たとえば、エンジンを切らずに速度0が一定時間続いた回数をして「(ほぼ)信号待ちの回数」としてカウントし、「信号待ち100回目なう」などとつぶやくことは出来そうです。あるいは、制限速度を超えたら「現在XXkm/hで巡航中。○○県警かかってこいや」とつぶやくことも可能でしょう(よい子はまねしちゃいけません)。

…ただまぁ、大がかりなわりにはあまり面白そうなつぶやきのネタにはならなそうですし、第一この設備が一般的ではないので、他の人にとっては「ふーん」程度であまり参考にならないです(自分で運転を解析するにはとても面白い情報なんですけどね)。

そんなわけで、もう少し一般的なGPSから得られる位置情報を利用してなんかできないか考えてみました。それが、このタイトルにあるような技術を利用して「国道○○号線なう」みたいなことをつぶやくというものです。

ひとまずお披露目

とりあえず関東地区だけなのですが、緯度経度から道路名を調べるプログラムを組んでみました。こちらのページ (停止しました)でそれを体験することが出来ますので、ぜひ一度お試しください(適当に立てたTomcatサーバなので、落ちてたらごめんなさい)。ではいってらっしゃいませ。

…あ、おかえりなさい。使い方は分かったでしょうか? 地図の中心部に調べたい道路を合わせると、その地点の道路名を吹き出しに表示するものです。デフォルトの倍率だとうまく道路上に中心があわないので、少し拡大すると良いです。地図上だとあまりずれてないと思っても、拡大率によっては数ピクセルで10m以上ずれていることもあります。それでも現れない場合には別の原因が考えられます(後述します)。

さてさて、今は手動で位置を合わせているわけですが、当然ながら携帯やPCのGPS位置情報を利用して、自動的にその位置の道路名を割り出すこともできます。 なんとなく、定期的に携帯から位置情報を送信し、その都度道路名を調べて「国道○○号から首都高へ」とかつぶやけそう、じゃないですか?

どうやって道路名を調べるか

ちょろっと調べた限りでは、位置情報から道路名に変換する既存のサービスはなさそうでした。

位置情報から住所を割り出すサービスはあります。「逆ジオコーディング」と呼ばれますが、Finds.jpが無料でサービスを公開していますし、最近ではGoogleもGoogleMaps APIにてサービスを提供し始めました。ただ、住所じゃないんですよね、必要なのは…。あくまで道路。

Googleの逆ジオコーディングは、道路上の緯度経度を入力してやると、有名な道路の場合にはそのむね返答をしてくれることがあるようです。ただまぁ、どの程度入っているかわかりませんし、建物名や地名など混ざった状態で返答されてもちょっと…という気がします。

仕方ないので今回は、国土交通省が公開している国土数値情報を使って自分で調べるプログラムを組むことにしました。

国土交通省は、以前から無料で国土数値情報をデータで公開しています。数年前に気づいてブログのエントリにもしているのですが、エントリ先くらいのクオリティのデータはすぐに手に入るわけです。ただ、道路情報に限っては1995年版が最新で、そこは非常に残念なのですが…。 国交省内部では必ずデータはあるはずで、他のデータは新しいモノもあるので、しばらく待てば/担当者にかけあえば新しいデータを閲覧できるかも知れませんが、まぁひとまずはいいでしょう。誰がどのくらい使いたいかも分からないですし^^;

この道路情報には、道路の線分データと、その線分に対応する道路名と種別(高速・国道・県道・…)などが含まれています。 なので、与えられた緯度経度に対して、近い道路の線分データがあればその道路名を返答する、というプログラムを書いてやれば良いということになります(久しぶりに点と直線の距離を求める公式とか思い出した^^;)。

応用

今はGoogleMapsアプリという形になっていますが、WebサービスやiPhoneアプリ化することで実際に自動でつぶやけるようになります。…自分以外にこんなものを使う人がいれば、ですが^^; ひとまず今は乗りかかった船なので、関東以外のデータをDBに突っ込んでいる最中です。

また、いわゆる一般的な逆ジオコーディングを使って、「埼玉県に突入なう」などとつぶやくことも出来るので、組み合わせると面白いかも知れません。

問題点

問題点、あります。

まずは上の方に書きましたが、データが1995年のものということです。首都高は一部開通してませんし、アクアラインもありません。千葉の館山道もないっぽいです。上で紹介したGoogleMapsアプリを使ってどうしても道路名が出なかった方は、もしかしたらその時代にはまだ道路がなかった(あるいは名前が付いてなかった)のかもしれません。 これはまぁ、国交省が新しいものをリリースしてくれるのを待ったり、あるいは自力で最新データに書き換えるしかありませんね。

あとは、道路名が法定名なので、微妙に違和感があります。たとえば池袋や渋谷を走っている通称「明治通り」は、「芝新宿王子線」と出てきます。 国道は全て「国道○○号線」となっているのでまぁ問題ないですが、それより細かい範囲の道路に関しては「??」となる可能性があります。環七は「環状七号線」なんだけどなー。 これも、必要ならば頑張ってデータを加えていく必要があります。

副産物

95年産ではありますが、高速・国道等の線分データが得られます。 下の写真は、首都高のデータを抜き出してプロットしたものです。

GoogleMapsやGoogleEarthにプロットしたり出来るので、もしかしたらそういったものが必要な人には役に立つかも知れません。これらのデータは再配布可能らしいので、自由に使えるようです。

まとめ

国交省が配布しているデータを使って、緯度経度からその地点の道路名を割り出すプログラムを作りました。今のところ関東のみ・GoogleMapsでの動作確認デモプログラムしかありませんが、他の地域も現在DBに突っ込んでいます。また今度遠出したときにでも、PCあるいはiPhoneを利用して実際につぶやいてみようと思います。

データが古く道路の名称もなじみのないもの、と問題点がないわけではないですが、もし使ってみたい・興味があるという方はご連絡ください。このウィンドウの右側に常に出ているtwitterリンクから僕のアカウントに飛べます。

あと、なにかこのデータを使って面白いことができるといったアイディアがあったら教えてください^^;

CANUSBを使ってRX-8の各種データを取り出してみる

前回のエントリまで使っていたELM327チップですが、どうも全てのデータのログを取ろうとするとバッファが溢れてしまうようで…。ただせっかく乗りかかった船なので、CANUSBという代物を購入してRX-8のデータをリアルタイムに取り出してみることにしました。

上記の画像においてグラフの意味は以下の通りです。

  • 赤 線:車速
  • 青 線:エンジン回転数
  • 紫 線:ラジエータ水温
  • 水色線:エアインテーク温度
  • 黄色線:アクセル開度
  • 赤領域:フットブレーキを踏んでいる
  • 青領域:クラッチが切れている
  • 緑領域:(高さに合わせて)ギアポジション

CANはまぁここでは車内LANのようなものだと考えておけばいいと思います。自動車内のコンピュータとその他センサや計器類との間で情報をやり取りするときのプロトコルなのですが、特徴の一つはブロードキャストだということです。 なので、OBD-IIのようにポーリングしてデータを取り出すのと違い、ネットワーク内を流れているデータであれば「盗み聞き」することができるため、車内コンピュータへの負荷が(おそらく)ありません。 コンピュータに負荷がかかった場合にもおそらくフェイルセーフが働くとは思いますが、心理的な負担がこちらのほうが少ないですね。

CANUSBは、LAWICEL社が販売している、CANデータアクセス用のケーブルです。コンピュータからはFTDI社のUSBシリアル変換コネクタが刺さっているように認識され、実際にシリアル接続でデータを取り出すのでMac、Windows、Linuxのどれからでもデータを取り出すことができます(LAWICEL社のページにはWinとLinuxしかドライバへのリンクがありませんが…)。 日本ではcompass lab.で取り扱っているようで、海外で買うのと値段も変わらなかったためこちらを利用しました。

ただこのCANUSB、車へ接続する側のコネクタが、いわゆるシリアル通信で用いるD-SUB9ピンで、実際のOBD互換のコネクタと合いません。そのためコネクタを購入あるいは自作する必要があります。

OBD2CABLES.COMでは片側がOBD-II端子、片側がD-SUB9ピンのケーブルを売っています(たとえばこれとか)。 値段は10ドル程度で、一般的なシリアルケーブルなどとたいして変わらないのですが、これを日本へ送ってもらおうとすると送料が30ドルくらいかかってしまい馬鹿馬鹿しいです。

そのため、自分はこちらのページを参考に自作しました。ただ、こちらもなんだかんだいって2000円くらいかかってしまうので、複数本数を同時に買うのであれば海外から取り寄せた方が安いかもしれません。

さて、ケーブルをつなげば後はシリアル通信なのでデータを解析するだけの簡単なお仕事です。海外には奇特な方がいて、これらのデータを既に解析して公開してくださっている方がいました。 これを先に見つけていたので、ケーブルが自作できれば後は余裕だろうと思っていたのですが…。なんと、自分の車に流れているパケットと雰囲気が違う様子。向こうの車がAT車だからなのか、それとも海外仕様だからなのか分かりませんが、結局自分で全部解析する必要にかられました…。

ま、そんなこんなですが、一応上記のグラフのようなものが書き出せるまでになりました(3日かかってしまった…)。 なお、上記のうちギアに関しては、エンジン回転数と車速から割り出しているものです。こちらもデータが取れるだろうと思っていたのですが、どうも見当たらなかったため、計算によって推定しています。

以下、もしかして自作したい人がいるかもしれないのでメモ(ただし、当然ですがこれを参考に自作アプリを作って、最悪車が暴走しても自分は責任負いませんのであしからず…)。

  • RPMは、ID 0x201の(data[0] * 256 + data[1]) / 4
  • Vehicle Speedは、ID 0x201の(data[4] * 256 + data[5] – 10000) / 100
  • Accel Throttle Positionは、ID 0x201の data[6]
  • Hand Brakeは、ID 0x212の(data[4] & 0x40)
  • Foot Brakeは、ID 0x212の(data[5] & 0x08)
  • Declutchingは、ID 0x231の(data[0] & 0xf0) //4ビット全部立つ
  • Engine Coolant Tempは、ID 0x240の data[3] – 40
  • Intake Air Tempは、ID 0x250のdata[3] – 40

他にもハンドルの回転角度が分かったりすると面白いのですが(海外のものだと分かっているのですが)、右側に舵を切っているか、左側に舵を切っているかは分かりそうなのですがそれ以上に詳しい角度などはちょっと分かりません。あっても良さそうですけどねぇ。

上記の図だといまいち温度まわりの動きが分かりにくいかもしれませんが、エンジンをかけ始めてログをとり、ぐるっと走って戻ってくるまでのデータをグラフにすると、次のようになります(上の図は、その最後の部分)。

この図を見ると、水温がぐんぐん上がっていっているのが分かります。また、スピードを出すと微妙にエアインテークエアの温度が下がり、それによって水温もちょこっと下がることがある、というのも見て取れます。

はてさて、これをどのように加工して使うか、それが問題だ。