以前、PS4コントローラーをマクロキーボードとして使うという記事を書いた。
thom.hateblo.jp
その中で、アナログスティックをズームイン・ズームアウトに使うコードを書いたが、コントローラーから取得できるアナログスティックのX・Y座標をそのまま判定に使っていたのでかなり無理やり感があった。本当はスティックの角度を判定に使いたかったんだけど、取れるのがX・Y座標だったから仕方なくそうしてたのだ。
ところが最近勉強し始めた材料力学で三角関数を学びなおす機会があり衝撃を受けた。
なんだこの便利なものは!!
サイン・コサイン・タンジェント。名前は聞いたことある。
中学だったか高校だったか忘れた。でも当時はそれを学ぶ意義を1ミリも理解していないので、大人になってもなんだかよく分からないものとして切り捨てていたのだ。
要するに、直角三角形のうち90°以外の角度が一つ分かれば2つの辺の比は求まるということ。
試しにFusion360でスケッチしてみた。確かに角度と底辺の寸法を入力すると、それ以上は過剰拘束だと言われる。つまり「もうサイズ確定したよ、これ以上寸法入れる意味ないよ」というメッセージだ。
ここまでは直感的にまぁそうなんだろうなと分かる部分だけど、この先は円で考えることになる。
ここでは詳しく解説しないけど、基礎から学びなおすにはこちらのYouTube動画がとてもよかったので紹介しておく。
さて、実際のコードはこちら。(関係する部分だけ抜粋)
#include <math.h> #define PI 3.141592653589793 //~中略~ void loop() { //~中略~ degree = atan2( 255 - PS4.getAnalogHat(LeftHatY)-128, PS4.getAnalogHat(LeftHatX)-128) * 180.0 / PI + 180; //~中略~ }
まず、「PS4.getAnalogHat(LeftHatY)」でY座標が取得できるのだが、ジョイスティックの座標軸は次のようになっている。
これだと扱いにくいので、255からYを引いてやることで、座標軸を変換している。
さらにX、Yともに-128することで中点を0とした数学でよくある軸に変換する。
取得できたX・Y座標の値を逆タンジェント関数atan2に引数として渡すと、角度がラジアンとして求まる。
ラジアンについてはきちんと調べてないんだけど、180 / PIを掛けると度数に変換できるということは調べがついている。
そうすると右端3時の方向を0°として反時計回りに0°~180°、時計回りに0°~-180°が取得できる。
最後に180を足すと、左端9時の方向から反時計回りに0°~360°の形式で角度を求めることができる。
以上がジョイステックから取得できるX・Yの値を角度に変換する方法である。
ちなみに、ジョイステックをどれくらい倒しこんでるのかを求めるのはもっと簡単。
上図のrは直角三角形の斜辺ととらえることができるので、xとyが分かれば三平方の定理で求まる。
数式はこんな感じ。
ここからrを求める式をCで書くとこんな感じ。
r = sqrt(pow(x,2) + pow(y,2))
VBAだと累乗は演算子があるのでこんな感じ。
r = sqr(x^2 + y^2)
以上。