「コンパス(2次元の場合)」では水平にスマホを置いたときに磁北がどっちに向いているかを計算できるようにした。でも常にスマホを水平に保つことを気にかけていないといけないという点でまだ未完成だなと思う。世の中には球型のコンパスがあるし、それを模したコンパスアプリもあるので、そこまで行ったら完成かなと。そこでコンパスアプリ(3次元の場合)を考えてみた。
といっても結構複雑なので、方針編と実践編に分けようと思う。
おおよその流れは以下だ。
①スマホの磁気センサーの出力からゼロ点のずれを差し引いて地磁気Bcを求める。
②スマホの座標系Xで観測した磁場BcをXY面を水平にした座標系X'での磁場B'cに変換する。
③B'c = (B'cx , B'cy , B'cz)のうち水平方向の成分B'ch = (B'cx , B'cy , 0)をスマホの座標系Xでの磁場Bchに変換してやる。
このBchのベクトルの向きこそがスマホから見た磁北の向きである。
以下でもう少し具体的に説明していく。
計算の方針を語る前に地磁気についておさらいが必要だ。
「コンパス(2次元の場合)」では水平方向に置いたスマホのX方向とY方向の磁場を使って北の方向を算出した。これは方位磁針が北を向くという小学校で習った知識を暗黙のうちに使ったからだ。でも実際には地磁気は水平を向いているわけではない。(地磁気を知る(国土地理院)) 日本付近では地面に向かって斜め45度くらいに潜り込んだ方向に磁力線が向いている。これが地磁気の全磁力で、全磁力の水平成分がほぼ北(磁北)を指すことをコンパスで利用している。
上に書いたようにスマホを水平に置けば、地磁気の水平成分はスマホのX方向とY方向の磁場からわかる。ではスマホを水平面に対して斜めに傾けた場合は?こうなるとスマホの磁気センサーで全磁力は簡単にわかるが、地磁気の水平成分はすぐにはわからない。コンパスとしては地磁気の水平成分を知りたいので、なんとかして水平成分を抜き出してやらないといけなく、これが3次元版の大きな課題である。
まずは「コンパス(2次元の場合)」でもやったようにスマホの磁気センサーの出力からゼロ点のずれを差し引く。2次元の時はスマホを水平にくるくる回したときのX、Yのそれぞれの出力を使ってゼロ点のズレを計算した。これは例えばX軸が磁北(全磁力の水平成分)方向に向いたときに最大の出力になり、磁北とは反対側に向けば最小の出力になることから、出力の(最大値+最小値)/2でゼロ点がどれだけずれているかが計算できるからだ。くるくる回していればY軸も同じように計算できるのは自明だろう。一方で3次元の場合で同じような考えでやろうとすると、全磁力に沿った向きにスマホの軸を合わせる必要が出てくる。全磁力がどっちに向いているかなんてわからない(わかっていたらコンパスなんていらない)ので、"なるべく"いろんな向きにスマホを傾けて、出力の(最大値+最小値)/2からゼロ点のズレを計算し、出力からズレを差し引くことで補正された磁場Bcを求める。
※"なるべく"というのが厳密でない感じがして気持ち悪いかもしれないが、これで妥協しても大きな問題にはならないだろうと考えている。なぜなら、全磁力Bとスマホの軸のズレをθとしたとき磁気センサーの出力はBcosθ+α(αはゼロ点のずれ)になるのだが、cosというのはグラフにすると頂点付近はなだらかなので、多少角度θがずれていてもcosθ~1だからだ。因みに25°くらいずれるとおおよそ1割ずれる。このくらいの精度でいいなら、"なるべく"でもいいだろう。
※水平面でくるくる回した後に、例えばX軸周りに回すでもいいのだが、そもそも水平面でくるくる回すことができるのであれば2次元の場合のコンパスで十分だ。
次は①で補正した磁場BcをXY平面を水平にした座標系でみたときの磁場に変換する。地磁気の水平成分を求めるためだ。
まず、磁場Bcはスマホの座標系(X )から見た時のものである。これだけではどこが水平面かわからないので、地磁気の水平成分がどっちの方向に向いているのかわからない。
そこでXY平面を水平にした座標系(X')に座標変換して、その座標系から見たときの磁場B'cを算出する。(このX'というのは、言い換えるとZ軸を鉛直方向と一致させた座標系である。)
ちなみにZ軸は鉛直方向にする必要があるが、わざわざX軸とY軸を東西南北と合わせる必要はない。なぜなら地磁気の水平成分を抜き出すために必要なのは水平面に座標系を合わせることだけなので。
ではどうやってX → X'へ座標変換するのかというと、XY平面上にある軸を中心に回転させればいい。なぜXY平面上の軸でいいかというと、それを説明するにはまず逆パターンを考えてみた方が想像しやすいのではないかと思う。水平に置いたスマホの上に棒をおいて、その棒を軸に回転させよう。棒をいろんな角度に変えれば、スマホはどんな向きにも傾けられるだろう。そして傾けたあとも当然棒はXY平面上にあるはずだ。これを逆回転させれば水平に戻るので、水平にすることのできる回転軸がXY平面上にあることが言える。
その回転軸の単位ベクトルをnとする。もうひとつ、回転させる角度をθとする。この2つがわかればロドリゲスの回転公式を使って座標変換することができるという算段だ。nとθはあとで説明するが加速度センサーを使って求めることができる。
ロドリゲスの回転公式というのは3次元空間内の点を原点を通る軸周りに回転させる公式だ。(例えば金沢工業大学のサイトが詳しい)この公式自体は空間内のある点を回転移動させるものなので座標変換の式ではない。しかし元の座標系にある点Pを回転させた新しい座標系で見たときの座標は、元の座標でPを逆に回転させた時の座標と同じになるはずだ。
つまりロドリゲスの回転公式でθを-θにすれば座標変換ができる。
ではロドリゲスの回転公式で使うθとnはどうやって求めるか?
まずはθから。θはスマホのz軸と鉛直方向が何度(θ)傾いているかである。この計算のために加速度センサーを使う。加速度の絶対値をg = √(gx2 + gy2 +gz2)とすれば、cosθ = gz /g が成り立つので、逆関数でθが求まる。
次にn。この計算でも加速度センサーを使う。XY平面上の加速度の成分gx-y = √(g 2 - gz2)は回転軸nに直角になるだろう。(傾けた方向に向いてるはずなので)
そうすると
gy / gx-y = sinφ
- gx / gx-y = cosφ
が成り立つ。
※符号が逆のように見えるのには訳があって、加速度センサーは加速度そのものを計測しているわけではなく、スマホの中にある錘にかかっている荷重を計測しているからだ。重力加速度で引っ張られるからあたかも反対方向に加速しているような出力になる。
一方でnの成分は、
n = (-sinφ , -cosφ , 0)
なので、二つ合わせて
n = ( - gy / gx-y , gx / gx-y , 0)
となり、加速度から回転軸nが求められる。
これでようやく座標変換できる。回転行列をRn(θ)とすると、
B'c = Rn(-θ) Bc
と計算すればよいのだ。
B'c が求まったのでB'c = (B'cx , B'cy , B'cz)のうち水平方向の成分B'ch = (B'cx , B'cy , 0)をスマホの座標系Xでの磁場Bchに変換してやる。
どうやって変換するのかというと②とは逆に回転させればいい。つまり、
Bch = Rn(θ)B'ch
と計算すればよいのだ。(②では-θとなっていたところがここではθとなっている。)Bchはスマホの座標系で見たときの地磁気の水平成分であるので、スマホの画面に対してどっち向きに磁北が向いているかわかったことになるというわけだ。
あとはスマホ画面上にうまく表示させてやればコンパスアプリの完成である。(元々やりたかったのはどうやって計算するかなので、どうやって表示するかは省略する。)
計算の大まかな方針は以上である。次回は実際のデータを使って計算してみる。