🔄

ゴルフスイング計測で詰まって初めて理解した:回転行列って結局何なのか

に公開

ゴルフスイング計測で詰まって初めて理解した:回転行列って結局何なのか

ゴルフコーチングウェアラブルデバイスを開発しています。左腕にIMUセンサを取り付けて、左腕の姿勢(手首の屈曲角度・前腕の回転角度)をリアルタイムで計測するシステムです。

開発を進めるなかで、「回転行列」「方向余弦行列」「クォータニオン」という言葉に何度も出会いました。最初は完全に素通りしていたのですが、センサの値がおかしくなるたびにこれらの概念が絡んでいて、どうしても避けられなくなりました。

この記事は、数学が得意ではない自分が「なんとなく掴んだ」イメージをまとめたものです。厳密さより直感を優先しています。


そもそも何が問題だったか

IMUセンサは「自分がどっちを向いているか」を教えてくれます。でも「どっちを向いているか」を数値で表すとき、どう表現するかが問題になります。

たとえば腕が「まっすぐ前を向いている」状態と「90度回転した」状態。この2つの違いを数値で表すにはどうすればいい?

一番単純なのは「X軸周りに90度回転した」という表現ですが、これだけでは3次元の動きを正確に扱えません。実際に腕を動かすと、複数の軸が同時に絡んできます。

そこで登場するのが回転行列です。


方向余弦:「どっちを向いているか」を3つの数値で表す

まず「方向余弦(ほうこうよげん)」から理解します。

ベクトルとは

矢印のことです。向きと長さを持ちます。「北に5km」とか「右斜め上に2」のように、方向と大きさを同時に表せます。

単位ベクトルとは

長さを1に揃えたベクトルです。「向き」だけを表したいときに使います。長さが1なので、「どっちを向いているか」だけが情報として残ります。

任意のベクトルは、その長さ(ノルム)で各成分を割ることで単位ベクトルにできます。たとえば (3, 4) のノルムは √(3²+4²)=5 なので、(3/5, 4/5) = (0.6, 0.8) が単位ベクトルです。

方向余弦とは

単位ベクトルがある方向を向いているとき、そのベクトルがX軸・Y軸・Z軸それぞれとどれくらい「揃っているか」を表す数値です。具体的には、ベクトルと各軸のなす角度のcos値になります。

X軸となす角度θxのcos → cos(θx)
Y軸となす角度θyのcos → cos(θy)
Z軸となす角度θzのcos → cos(θz)

単位ベクトルの場合、このcos値はそのままベクトルの各軸成分になります。

つまり:

方向余弦 = 単位ベクトルの成分

イメージで掴む

真北を向いているとします。X軸が東、Y軸が北、Z軸が上の座標系で考えると:

方向余弦(cos値) 意味
X軸(東) 0 東方向には全く向いていない
Y軸(北) 1 完全に北を向いている
Z軸(上) 0 上方向には全く向いていない

45度北東を向いたら:

方向余弦 意味
X軸(東) 0.707 東方向に7割向いている
Y軸(北) 0.707 北方向に7割向いている
Z軸(上) 0 上方向には向いていない

この「3つの数値」が方向余弦です。1本のベクトルの向きを3つの数値で表しています。
方向余弦のイメージ


回転行列:3軸分の方向余弦をひとまとめにしたもの

3次元空間の「向き」を完全に表すには、1本のベクトルだけでは足りません。

たとえばスマートフォンの向きを考えると、「前後方向」「上下方向」「左右方向」の3方向がすべて決まって初めて完全な向きが表現できます。

それぞれの方向を単位ベクトルで表し、3本分の方向余弦をまとめたものが回転行列(3×3の行列)です。

         [ |      |      |  ]
R    =   [ X軸    Y軸    Z軸 ]
         [ |      |      |  ]

各列が「その座標軸の向き」を表す単位ベクトルになっています。行列とベクトルの掛け算には「回転行列をベクトルの左側に掛ける(列ベクトル方式)」と「右側に掛ける(行ベクトル方式)」の2通りの流儀があり、どちらを採用するかで行列の並べ方が変わります。この記事ではPython(numpy)やVQFなどのセンサフュージョンライブラリの慣習に合わせて列ベクトル方式を採用しています。コードで書くと v_new = R @ v@はnumpyの行列積演算子、Rは回転行列、vは変換したいベクトル)の形になります。

各要素がすべて方向余弦で構成されているので、「回転行列」と「方向余弦行列」は同じものを指します。名前が2つあって混乱しますが、中身は同じです。

回転行列の役割

IMUを腕に取り付けたとき、センサの座標系(センサのX・Y・Z方向)と重力基準の座標系(地面・重力方向を基準にしたX・Y・Z方向)がずれています。

回転行列はこの「ずれ」を記述する変換表です。

センサ座標系での値
      ↓  × 回転行列
重力基準の座標系での値

回転行列の構造

たとえば腕をまっすぐ前に動かしても、センサを斜めに取り付けていれば「重力基準の座標系でどっちに動いたか」は変わります。回転行列という変換を通すことで、取り付け方向に関係なく正しく解釈できます。

センサ座標系から重力基準の座標系への変換

なお、重力・地面を基準とした座標系のことを「世界座標系」とも呼びます。


回転行列の性質(数式なしで)

回転行列にはいくつか面白い性質があります。実装で役に立つので頭の片隅に。

直交性

行列の各列(X・Y・Z軸を表す3本のベクトル)は互いに垂直です。これはX・Y・Z軸が直交するのと対応しています。

逆変換が簡単

「世界→センサ」の変換を「センサ→世界」に戻したいとき、行列を転置する(行と列を入れ替える)だけでいい。通常の行列の逆行列計算は複雑ですが、回転行列ではこれが一致します。計算コストが低くなります。

行列式とは?

行列式(ぎょうれつしき) とは、行列から1つの数値を計算する操作です。「この行列が空間をどれだけ拡大・縮小するか」を表します。2倍に拡大する変換なら行列式は2、半分に縮小するなら0.5、という具合です。

回転は「大きさを変えずに向きだけ変える」操作なので、純粋な回転を表す回転行列の行列式は必ず1になります。センサフュージョンの計算で数値誤差が蓄積すると、この値が1からずれてきます。ずれてきたら計算が狂い始めているサインです。

VQFやMadgwickなどのセンサフュージョンアルゴリズムが内部で「正規化」処理を行っているのは、このずれを定期的にリセットするためです。


回転行列を知っておく意味

実は開発中のシステムのコードを調べてみると、回転行列は一切使っていませんでした。すべての姿勢演算がクォータニオンで閉じています。

ではなぜ回転行列を学ぶのか。クォータニオンは回転行列と同じ回転を別の形で表現したものです。回転行列の「各軸がどっちを向いているか」というイメージを掴んでいると、クォータニオンが何を表しているのかが腑に落ちやすくなります。

次回はこの「クォータニオン」を取り上げます。なぜ実装ではクォータニオンが使われるのか、そしてジンバルロックという問題も含めて掘り下げます。


まとめ

  • 方向余弦 = 単位ベクトルと各軸のなす角度のcos値(=ベクトルの成分)
  • 回転行列 = 3本の軸の方向余弦をひとまとめにした3×3行列
  • 方向余弦行列 = 回転行列 = 要素がすべて方向余弦で構成されているため、2つの名前で呼ばれる
  • 役割 = センサ座標系と重力基準の座標系の「ずれ」を記述する変換表

このシリーズは、ゴルフコーチングウェアラブルデバイスの開発過程で詰まった数学的概念を、実装者目線で整理したものです。理論的な厳密さより「動くものを作るための理解」を優先しています。

参考資料


このシリーズの記事

GitHubで編集を提案

Discussion