コントローラのアナログスティック入力について

今回はPS4コントローラで手首の回転を制御しようとした時に、どんな方法があるのかを考えてみました。
(おそらく車輪の再発明。ゲーム界隈ならもっと進んでいて便利な手法あるんでしょうね。ゲームのRTAとかでよく見かける√2走法なんかにも関わる内容ですから、きっと深い歴史があるはずです)
先に結論を簡潔にいうと、アナログ値2種からスティックの回転軸&回転角を取得する方法2つを挙げています。
あと座標系とか回転とかは右手系でとってます。

まずアナログスティックとは、2つの回転角を取得するセンサを直交配置させているものを想定しています。
十字キーの派生版のような外見はスティックだけどスイッチ4つ付いただけのものではなく、2軸のアナログ値を一度に得られる入力装置です。
秋月でも取り扱っているRKJXV122400Rの写真とか見るとわかりやすいですね。勝手に写真貼っていいのかよく分からないので各自お調べください…

で、上下方向(ピッチ軸回転)に±100[%]、左右方向(ロール軸回転)に+100[%]なアナログ値を取得できると考えましょう。
使用するライブラリによって諸々の具合は違うかもしれませんが、今回の記事ではそう考えておきます。

アナログスティックの定義

こんな感じでしょうか。
なにもしていないときが青色状態で、スティックを倒したときが赤色状態です。
この赤色状態のときに得られる2つのアナログ値をそれぞれSx[%]とSy[%]と置いてみます。
変数ってなんか暗黙の命名ルールあるらしいですよね。しらんけど。

長々とした前提はこれくらいにして、こうして得られたアナログ値2種からスティックの位置ベクトルCinを取得したいという目的があります。
なぜなら位置ベクトルが得られるということは、スティックが回転した際の回転軸ベクトルと回転量を取得できるということです。
つまりは回転動作の指示に使えるわけですね。具体例は後述。

ではベクトルを得るにはこのアナログ値2種をどうしたらよいか。
A)軸方向距離の変数として捉え、2次元ベクトルとして考える
B)軸中心回転角の変数として捉え、3次元ベクトルとして考える

2次元ベクトルで考えてみる

A)
xy平面があるとして、2値はそれぞれ±100[%]の範囲で動くわけですから正方形の範囲にプロットされることになります。
こうしてまずは

現在のスティック位置ベクトル:Cin=(Sx,Sy)

を取得できました。
次に、初期姿勢からCinへの移動はどのように記述できるのか、
言い換えると、回転軸と回転量はどう考えればよいのかを考えます。

まずは回転軸ですが、Cinに+90[deg]の回転を施せば得られます。
回転軸:λ=Rot(π/2)Cin=(-Sy,Sx)
これはCinが得られるときのスティックの倒れ込みを考えると分かりやすいです。
仮にatan(Sy/Sx)=30[deg]となるようなCinを考えたとき、λはatan(λy/λx)=120[deg]となるでしょう。
(もっと深掘りすると、そもそもCinは3次元ベクトルであると考え直してみて初期姿勢とCinの外積をとってみればよいです。結果として回転軸はxy平面状にしか存在できないので無駄に記述が長ったらしくなるだけと考えて割愛)

また回転量Ω、つまりはスティックの倒し込み量について考えてみると、これはCinの大きさと捉えるとよいでしょう。
回転量:Ω=√(Sx^2+Sy^2)
しかしここで困ったことが起こります。
物理的な入力角と、計算値の回転角が一致しません。
具体的にいうと、Cin_a=(100,0)とCin_b=(100,100)における回転角は同じ値であって欲しいのに、Ωa=100[%]、Ωb=141[%](←√2*100)となってしまいます。
こうしたズレはセンサで得られる値がそもそも機構的には回転であることに起因しています。

この手法はズレがある、つまりは倒し込む向きや量によって分解能が不均一で、直感的な操作からかけ離れる懸念がありますが、なによりも計算が簡単に済むという莫大なメリットがありますね。

3次元ベクトルで考えてみる

B)
ドーム状の表面をなぞる様に移動する、つまりは大きさが一定の3次元ベクトルとして考えて見ます。
ここでは計算の簡易化のため単位ベクトルとして考えていきます。
Sxはx軸中心の回転度合い、Syはy軸中心の回転度合いと捉えます。
ではSxとSyを用いてCinをどのように記述するのか。
まずスティック可動域を±π/2[rad]として
θv[rad]=π/2*Sx[%]
θh[rad]=π/2*Sy[%]
とします。次に
①初期姿勢からy軸回りにθ1だけ回転して、更にx軸回りにθvだけ回転した位置ベクトルCv
②初期姿勢からx軸回りにθ2だけ回転して、更にy軸回りにθhだけ回転した位置ベクトルCh
の2式からなる連立方程式を解けばCinは求められます。

回転軸λは外積から、回転量Ωは内積から導出できます。

長ったらしい計算式

(A)と(B)の手法の比較

(A)2次元ベクトルとして捉えたときの表

(B)3次元ベクトルとして捉えたときの表

※追記(22/5/3)
(A)および(A')の表がぜんっぜん正しくないことに気づきました。正負の方向とり方とか。しかし不誠実ながら(B)採用したいのが前提の記事なのでそのまんまにしておきます。

申し訳程度に追加したすんごい雑な修正概要図

この2つの図は自分が分かれば良いやくらいに雑な表なんですが、
Sx=-33[%]、Sy=50[%]という共通の入力条件としたときに
(A)Ω=54.08[deg](5/3修正)
(B)Ω=49.11[deg]
といった具合に回転量が変わります。
特に注目すべきは(B)の表はどの値も90[deg]を越えない点ですね。

また、(A)であっても少し手を加えて「絶対に90[deg]を超えない」という目的のために一括で√2で割る(イメージ的には正方形の可動域に内接する円)ことで

(A’)2次元ベクトルとして捉えてかつ90°を超えない処理をしたときの表

 

このようなことも出来はします。
ちなみに(A')Ω=38.24[deg](5/3修正)

【結論】
まだ手首を動かすプログラムすら組んでない状況ですがBで進めたいなーと思いました。
以上。