2020年9月13日 (日)

100日後にMMDで踊るドールロボ舞ちゃん 0x10日目 VMDConverterの表示回転角(YXZ?)から、舞ちゃん肩関節形式(XZY)への角度変換式を導出2

YXZの順で表されている、MMD上のオイラー角表示。

図はおさらいです

72

これを、舞ちゃんの関節構造XZYの順にのオイラ―角表示に換える変換式。

52_20200913021801

 

前回の式は間違っていたようです。

 

回転行列(変換行列)から、回す順番の違う場合のオイラー角の式のリスト。

三日月館

変換行列からオイラー角の求め方

この順序ですが、γ→β→αの順が正しいようです。

(あるいは、回転行列の表し方が転置で表しているかのどちらかっぽい?)

 

というわけで4番目の式を適用して

84   

(Y=±90°でcosY=0となるのでそこの考慮は必要・・・追記予定)

(追記:cosβ=0つまりβ=±90°のときαとγが同じ軸(ジンバルロック)となり、

αが0割りになるので条件分岐がありますね。

これも上表にに反映しました。)

 

エクセルで、変換式に値を代入して計算してみます。単位は度です。

71

変換式が合っていそうなことを確認しました。

 

これで肩関節の変換式が出ました。

このやり方で、IK以外の関節はXYZの並びが違っても変換式を導けそうです。

 

肩関節に関しては、

MMD上で、変換前のXが90度を超えて動くとY,Zが180度変化する動作をする点と、

Zが初期状態で45度オフセットしている点を考慮すればうまくいきそう。

 

2020年9月11日 (金)

100日後にMMDで踊るドールロボ舞ちゃん E日目 VMDConverterの表示回転角(YXZ?)から、舞ちゃん肩関節形式(XZY)への角度変換式を導出

 

YXZの順で表されている、MMD上のオイラー角表示。

これを、舞ちゃんの関節構造XZYの順にのオイラ―角表示に換える変換式はどうなるのか。

 

まずC日目で、MMD上でこの値が左手系なのだけど、回転方向だけYとZが一般的な取り方と逆っぽいということがわかっています。

そのため計算上は、YとZの回転を、マイナスと扱って考えます。

 

まず、YXZの順に回転した場合の、回転行列(変換行列)というものを求めてみます。→①

このサイトをを参考に計算してみました。

3次元CGと座標系

 

結果はこちら。YとZをマイナスとして計算しています。

82

 

 

そして、同様にXZYの順に回転した場合の回転行列(変換行列)も求めて、上の場合と同じ結果になる場合が同じ回転、ということになります。

なのでこの9パラメータについて連立方程式を解けば、変換式が求まる、→⓶

はずなのですが、

 

かなり大変で挫折しました。

 

一方、回転行列(変換行列)から、回す順番の違う場合のオイラー角の式のリストを見つけました。

三日月館

変換行列からオイラー角の求め方

(疑問としては、この式が左手系かというのはあるけどCG系なので左手系っぽい?)

①の回転行列の要素から拾っていくと、

MMD表示の「角度」(YXZの順と推測)(Y,Z,X)からXZYの順のオイラー角表示(α,β,γ)への変換式として、次の結果を得ました。

60 

数式の中のX,Y,ZはMMDでの「回転」表示角度(°)になります。

Xは、MMD上で-90<X<90の範囲に制限されています。そのためcosX>0となりαにつく条件は、-180<Z<180となります。

通常はモーターもこの範囲しか回れません。

 

この変換が正しいか検証してみたいと思います。

直感的には、αにもβにもYが入ってこないところが、ほんとに合ってるのかな?感あり

間違ってました(次のエントリ)

2020年9月 9日 (水)

100日後にMMDで踊るドールロボ舞ちゃん C日目2 VMDConverterの表示座標系と回転角の向き

MMD及びVMDConverterが変換するCSVデータ上では・・・

「ボーン位置」は左手系で表示される(動画)

初期位置のモデル正面に向かって、右がX正、上がY正、奥がZ正

 

「回転」の方向は

X回転だけ、軸方向に右ねじが進む回転方向が負に表示される。→左手系ではふつうはそう取るっぽい?
Y回転とZ回転は、軸方向に右ねじが進む回転方向が正に表示される。→これは左手系の普通と逆っぽい

(動画)

 

ググった限りでは、(内部形式と言っている)VMDのバイナリ値は異なるのかも?

100日後にMMDで踊るドールロボ舞ちゃん C日目 VMDConverterの角度表示基準2

VMDConverterの角度表示基準について

9日目の考えが、違いました

>「X、Yがグローバル座標系でZだけボーンのローカル座標系」っぽい

現時点での理解は、

「自分までのすべての親ボーンが初期状態にあるとき、(親ボーンに対して)グローバル座標系から対象ボーンをどのように回転させるかを表示。

回転の順序はY→X→Zと回転させたとき、X,Y,Zの各軸をどれだけ回すかを表示する。」

 

こう考える理由としては、親ボーンを動かしても該当ボーンの回転の数値は変わらない(→単純なグローバル座標ではなかった。たまたま自分までのすべての親ボーンが初期状態にあるとき、一致する)
またX→Y、Y→Xと回した時の変化(動画)(X→YはY動かしたときX動かないが、Y→XはX動かしたときY動く・・・Yを動かした時点で、角度表示基準のX軸が動いている)

ことと、

Z回転がローカル座標に一致したことです。

 

さて、先の結論に戻ると、このX,Y,Z回転表示角からサーボモータへの指示は、親ボーンまで遡って計算する必要はないことがわかります。

しかし一方で、舞ちゃんの肩→腕の関節構造が(MMD世界でいう)Y→X→Zではない。舞ちゃんはX→Z→Yなのです。

52

なのでこの順序の違いによる、X,Y,Zの各角度の回転を変換計算すればよさそう、という結論に。

 

また一方、親ボーンからY→X→Zとなるような肩関節構造にすると、肩関節に関してはそのままデータが使えるんですけど

51_20200909010401

ただそうすると、タイトルが入れ替わって、「MMDで踊れるドールロボを作る」になり、手段が目的化の逆(目的が手段によってなくなる)が起きます。

また今度はひじの演算がややこしくなる面もあるので、順序変換を考えたいと思います。

2020年9月 6日 (日)

100日後にMMDで踊るドールロボ舞ちゃん 9日目 VMDConverterの角度表示基準

「グローバル、お前もか」

昨日に続いて、今日もMMDモデルをいろいろ回していて、

VMDConverterの角度表示基準がわかりました。

 

まず、VMDConverterGraphicalが出力するCSVデータの角度。

これはMMD上の、ボーン角度指定テキストボックスと同じ値が入っているようだということが5日目にわかっています。

 

ところがこのボーン角度指定テキストボックスの値の変化が、モデルをいろいろ回しているとどうも直感と違う動きをする

ローカル座標系でもグローバル座標系でもないような。

 

ということでいろいろ動かした結果、

「X、Yがグローバル座標系でZだけボーンのローカル座標系」っぽい

ということがわかりました。

51 50

動画

 

これで、5日目の疑問が解消します。

>・ボーンの回転は、他のボーンの数値は変化しない。このポーズの変化で、頭や腕も動いているが、それらはVMDデータには反映されない

これは正しいですね。正確に言うと今見てるのはVMDデータでなくVMDConverterで変換したCSVなのですが。

>->ワールド座標や「センター」ボーンに対してではなく、一つ親のボーンを基準に、それに対する回転で記載している?

これはそうでなく。

「親ボーンの現在姿勢に対して、該当ボーンのモデル初期角度と同じ相対角度」となった場合を(x,y,z)=(0,0,0)とします。

ここからX,Y,Zの回転角を表します。

ただしX,Y回転ははグローバル座標系での角度。Z回転はボーンのローカル座標系での角度を表す。

 

ということになっているようです。

 

そうなると、これはやはり単純に、ロボのサーボモータ角度(ボーンのローカル座標に近い)に簡単に変換とはいきません。

 

サーボモータへの指示角度は、 X,Y回転がグローバル基準で表されているので、これを該当ボーン上のローカル座標系に変換する必要があります。

そのためには該当ボーンがどういう向きなのか、Z回転がローカル座標系なので結局親ボーンを大元までたどってグローバル座標系で表す計算をする必要があります。

 

というわけでこのVMD変換CSV=MMD上表示フォーマットの角度から演算していくか、VMDデータのクオータニオンで計算するか

どちらが簡単?くらいの感じになってきました。

 

それから、足について。

(IK対応とするとそこまで考える必要がないのかもしれませんが)親との関係、という点で

「センター」ボーンと「左足」「右足」ボーンの間に「下半身」ボーンがある(動画)

ために、この「下半身」ボーンの設定によって「左足」「右足」 の回転と位置は変わります。

(「左足」「右足」がIK対象のボーンでは一番親に近いが、

その一階層上にIK対象でない「下半身」ボーンがあります。)

 

というかんじで、理屈は分かった感じ(作れるとは言っていない)

 

 

2020年9月 5日 (土)

100日後にMMDで踊るドールロボ舞ちゃん 8日目 MMDの腕ボーンと足IK

今日はひたすらMMDでボーンのハンドルを回したり角度入力をしてみましたが

わりとなんもわからん。


昨日の、MMDのボーン角度からサーボ角度への変換、という課題がありましたが

これは手付かず。

 

腕ボーン(肩)の角度が、0のときどんな角度なのだろうという疑問があったのですが

40

これは上の画像のように左腕を真下にしたときZ回転45度で、X,Yは回転なしの様でした。

(画像ではYが少し動いてしまってますが、基準は0度でしょう)

なので計算時はその分加算/減算すれば良さそうで問題なさそう。

 

そして、昨日はOFFにしたIKについて調べました。

まずMMD標準モデルは、左足IK、右足IK、左つま先IK、右つま先IK、の4つのIKボーンを持っていました。

41

配布されている、有名なMMDモーションの多くはこの4点のIKを使っているようです。

IKボーンは、回転XYZと移動(位置)XYZ両方の、6個のパラメータを持っています。

動画をリンクで上げたので見るとわかりやすいです。(このブログ、今時3MBしか貼れないって・・・twitter以下・・・)

https://twitter.com/beam8000/status/1301930566267224064

このIK4点と、センターボーンの位置をを決めるだけでおおよその下半身ポーズが決定できます。

そしてIKにより算出された足、ひざのボーン回転を、さらに追加で設定(調整)することができます。

https://twitter.com/beam8000/status/1301930907721375745

 

ただ、このIKを使った時のVMDデータは、足IK状態のとき、IK自動算出に任せる場合が、回転0。

手動操作をした場合は。IK自動算出から手動操作した差分が、角度として記載されます。

(VMDConverterで変換した、IK制約と矛盾する手動ボーン回転情報のNMDを読み込むととどうなるかは不明)

 

なので、IK使用のVMDデータから、舞ちゃんのサーボモーター角を出すには。自前でIKを解く(角度に)必要がありそうです。

大変そう・・・

 

さらにその上。配布されている多くのIK使用のVMDモーションを、そのまま現実の二足ホビーロボットに入れて、

立つのか、コケないのかという点に関しても、データそのままではまず無理と思われます。

 

MMD用のモーションデータというのは、あくまでバーチャル世界での鑑賞用データ。

重心が合っていなくても指定の座標で静止します。足裏が接地していないとか地面にめり込んでいても問題ないのです。

バーチャル世界では重量もエネルギー(筋力)設定も自由、剛性は無限大、反応時間は無限小。

 

そこのところの辻褄もどうやって取るか?っていうのも課題点です。

 

後モーションのキーフレーム間の補間曲線な・・・VNDConverter情報もクオータニオンのバイナリですよね・・・

この辺り、直線で妥協か

 

そんなかんじでとりあえず、今回まではMMDを触ってみながら

あーでもないこーでもない言っていますが

 

あと一回、関節についての課題点があるのでそれを書いてから

実装に入っていけたらいいなぁ

 

 

 

2020年9月 4日 (金)

100日後にMMDで踊るドールロボ舞ちゃん 7日目 VMDデータを生成して調べる3

昨日までのあらすじ。

ボーンのXYZの回転角がCSVに出ている!

じゃあそのままサーボモーターに入れればOK?

というと、そんなことはなさそう、という話

 

とりあえずまず昨日まで勘違いしていたのですが、コンピュータグラフィックの世界では、前後方向の軸(モデルでいうとロール軸)がZ軸で上下方向の軸(モデルでいうとヨー軸)がY軸なんですね。

実空間だと高さ方向Zが多いかなって(多分グラフィックは2Dのx,yから3Dのx,y,zに拡張した経緯ですよね)

 

で、本編です。

例えばですが、左足(股関節)のボーンを考えてみます。

(ここを選んだのは、ボーンのツリーでセンターのすぐ下になり、かつ回転0,0,0で真下に向いているため説明しやすいからです。

あとミクさんだとスカートでわかりにくいのでリンちゃんのモデルで見てみます。)

31

まずは足、つま先のIKをOFFにして、

左足(股関節)のボーンを選択、X(軸周りの)回転を45度、Z(軸周りの)回転を45度で数値入力します。

回転がわかりやすいように左ひざをX(軸周りの)回転を-90度曲げています。そうすると画像のような中段蹴りの構えになります。

 

ここで視点を動かし、左足のボーンを真下から見ます。

32

この状態でボーン操作を回転に。

緑のハンドルをつかんで回すと、左足ボーンの向きは変わらず、ボーンが軸を中心に回転します。

 

 

ちょっと内股になるように回してみると・・・

33

これはこれで下段まわし蹴りがきそうなポーズですが

最初の状態とボーンの向いている方向はほぼ同じなのに、

X回転、Y回転、Z回転の数値が大きく異なります。

 

たとえば舞ちゃんの場合、サーボモーターが胴体から(MMD世界でいう)Z軸回りの回転(ロール)、X軸周りの回転(ピッチ)で、

組み替えによってはその先にY軸回り(ヨー)となります。

この場合、先の2つの状態(中段蹴りと内股)でZ軸周りのサーボモータ回転角(とX軸周りのサーボモータ回転角)は同一となるはずです。

 

 

というわけで、MMDのボーン回転角のX,Y,Z(軸回りの)角度表示を、そのままサーボモーターに入れればok、

という単純な話ではないんですね。

MMDモデルはボーンのX,Y,Z3軸が順序なく直交して自由に動かせますが、

現実の機構でそのように作ることはかなり複雑になってしまい、舞ちゃんの機構のように、広義のジンバルとでもいうか、

親ボーンから順番に軸がある形になります。

 

そして、MMDデータには更に、

腕には更に基準ポーズによる問題がありそう。

 

というところで、今日はここまで

 

だんだん3次元空間なんもわからん状態になってきました・・・

2020年9月 1日 (火)

100日後にMMDで踊るドールロボ舞ちゃん 6日目 VMDデータを生成して調べる2

昨日の結果をもう一度考えてみました。

 

まず、気付いたことがあって、MMD上でボーンの(回転)角度がオイラー角で、位置もx,y,zで数値入力できるんですね。

11

まずは、このように上半身ボーンのX回転を-45度に設定したモーションデータVMDを保存します。

で、このVMDを、VMDConverterGraphicalでCSVにすると。

13

このX回転、Y回転、Z回転って、先ほど数値入力した「度」で表されてますね・・・

 

MMD内部で一旦度からクォータニオンに変換してVMDデータにするけど、

VMDConverterGraphicalがCSVにする際に、再度「度」変換してくれているようです。

Y回転、Z回転が完全に0度にならないのは、演算誤差ですね。

なーんだ、クォータニオンなんて全然知らなくても角度出るじゃん!

ということで、回転が3パラメーターの疑問も解決。

 

あれ、でも昨日の

15

これ、Y回転が180度、Z回転が-180度になってるんですよね。

16

これ、X方向回転のハンドルを回して、-90度以上回してるんですね、-102度くらい。

X方向回転のハンドルを回して、-90度以上回すと、Xの値が-90度を超えると、数値入力ボックスのところが

Y回転が0->180度、Z回転が0->-180度に瞬時に入れ替わり、Xの値は、今度は逆に-90度から0度へ向かっていきます。

要はx回転,y回転,z回転=-102,0,0=-78,180,-180だと。

数値入力でXに-90度以下、90度以上の値を入れても同様に-90度~90度の範囲になるよう自動で書き換わり、Y,Zが入れ替わります。

Y,Zはこのような動作はしません。-180度~180度の範囲になります。

-180度~180度の範囲を超えたときは、n回回転したということで-180度~180度の範囲に自動で書き換わります。

これはMMDの仕様のようです。確かにこうすることで、同じ回転状態に2つのオイラ―角表現が発生することを防げます。

 

MMD自体にもう少し慣れたほうがいいかも?

 

とまあそれは良いんですが、舞ちゃんのというか人間の場合、関節のX(ピッチ)方向って、だいたい90度くらいしか回らないので関係ないんですが、

肩ピッチは

17

180度くらい回るんですよね。そしてMMDではこんなポーズで前に水平にした状態で、その上下でX,Yが入れ替わる挙動をするので、

これをサーボモーター指令角に変換するにはちょっと考える必要あるかも。

あ、あとバレエとかハイキックとかしたら股関節も90度以上上がりますけどね。リアルロボットやホビーロボットではあまりしないですよね。

 

と、今日はここまで。

 

 

 

100日後にMMDで踊るドールロボ舞ちゃん 5日目 VMDデータを生成して調べる

今日は、MMDでモデルを動かして、どんなVMDが生成されるのか見てみます。

 

VPVP Wikiに紹介のある、VMDConverterGraphicalを使うと、VMDデータをCSVに変換できて手軽に見れることがわかりましたのでこれを使います。

ただ、VPVP Wikiのリンクは切れていました。入手は探してみてください。

 

まずは、フレーム0(番)でポーズはモデルロード直後の状態。

0

 

そこからフレーム5(番)で上半身のボーンを前にほぼ90度に倒してみます。補完曲線は直線。

1

 

これをVMD出力したデータはこのようになりました。

 

(参考)MMDでVNDデータを保存するときは、画面右のフレームツリー画面で選択したポイントのデータしか書き出されません。ボーン、時間両方指定する。ここではとりあえず全選択します。以下のデータは抜粋です。

最初に紹介のアプリでCSVに変換して、見てみます。

 

上半身ボーンのデータがこちら。

上半身 0 0 0 0 0 0 0 0x14140000141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B001414141414146B6B6B6B6B6B6B6B000014141414146B6B6B6B6B6B6B6B000000
上半身 5 0 0 0 -77.7251 179.999 -179.999 0x14140000141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B001414141414146B6B6B6B6B6B6B6B000014141414146B6B6B6B6B6B6B6B000000

そのほかのボーンは、すべて次と同じデータが入っていました。

右つま先 0 0 0 0 0 0 0 0x14140000141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B001414141414146B6B6B6B6B6B6B6B000014141414146B6B6B6B6B6B6B6B000000



1日目の調査から行くと、1レコードの順番はフレーム番号、ボーンの位置x,y,z、ボーンの回転(クオータニオン)、そして最後が時間方向の補間情報mの並びです。


ここからわかることは、

・フレーム番号はそのまま入っている。(1フレーム1/60=16.6ミリ秒?)

・ボーンの位置は、とりあえずこの状態ではすべて0・・・モデルロード時の状態は、全ボーンで0,0,0っぽい

・ボーンの回転は、クォータニオンといいつつ3パラメーター。モデルロード時の状態は、全ボーンで0,0,0っぽい。

前にだいたい90度傾けた状態で-71,180,-180暗いという数値。

・ボーンの回転は、他のボーンの数値は変化しない。このポーズの変化で、頭や腕も動いているが、それらはVMDデータには反映されない

->ワールド座標や「センター」ボーンに対してではなく、一つ親のボーンを基準に、それに対する回転で記載している?

(「上半身」の1つ親は「センター」?)

・時間方向の補間が直線の場合の値は、0x1414000014141・・・になるようだ

 

今日はここまでです。

2020年8月30日 (日)

100日後にMMDで踊るドールロボ舞ちゃん 3日目 クォータニオンを調べる

1日目に書いたように、MMDのモーションデータVMDは、ボーンの回転をクォータニオンで保持しています。

そこで、このクォータニオンというものを理解する必要があります。

知っている人にとっては、この記事は何の意味もないので読み飛ばしてください。

(コメントいただけるとありがたいです)

 

ビームさんにとって線形代数は本当にとっかかりがないというか

数学の教科書的なの見てもなんもわからん・・・(数学才能なし・・・)

しかし何とかしないとドールロボ舞ちゃんはMMDで踊りません。

ググってみます。

Qiita @drken
クォータニオン (Quaternion) を総整理! ~ 三次元物体の回転と姿勢を鮮やかに扱う ~
https://qiita.com/drken/items/0639cf34cce14e8d58a5

Qiita @mebiusbox2
CGのためのクォータニオン
https://qiita.com/mebiusbox2/items/2fa0f0a9ca1cf2044e82

物理のかぎしっぽ
四元数
http://hooktail.sub.jp/mathInPhys/quaternion/

かみのメモ
回転ベクトル・回転行列・クォータニオン・オイラー角についてまとめてみた
https://kamino.hatenablog.com/entry/rotation_expressions


いかがでしたか。

なんもわからんなりに、

・3次元空間での回転を表すには、ロールピッチヨーの角度3パラメータで表すオイラー角、
四元数(クォータニオン)4パラメータで表す、回転行列 3x3の9パラメータで表す、の3つの方法がある。
・複素数が三角関数を使わずに平面上の回転を表せるように、
四元数で三角関数を使わずに3次元空間の回転を表せる。

という理解をしました。

とにかく、やりたいことは

MMDのモーションデータは、ボーンの回転向き)をクォータニオンで表している。
対して舞ちゃんを動かすには、サーボに関節の角度つまりオイラー角でデータを渡す必要があります。
つまりクォータニオンからオイラー角への変換ができればよいわけです。

そのものずばりがありました。

[kaze's test] プログラミングメモ
オイラー角とクォータニオン間の変換とベクトルの回転
https://www.kazetest.com/vcmemo/quaternion/quaternion.htm

この中の
3.クォータニオン(四元数)からオイラー角へ変換
roll = atan2(2.0 * (q2q3 + q0q1), q0q0 - q1q1 - q2q2 + q3q3);
pitch = asin(2.0 * (q0q2 - q1q3));
yaw = atan2(2.0 * (q1q2 + q0q3), q0q0 + q1q1 - q2q2 - q3q3);

とりあえずはこれでできそうです。

複素数(a+bi)から極座標(r,Θ)への変換が
Θ=arctan(b/a)なのでそこからの拡張と考えれば納得?

 

今回はここまでです。

次回は、実際のVMDデータを見ながら、クオータニオンで保持されてるVMDデータが、どういう座標系を基準にしているか?などを見ていきたいと思います。

«100日後にMMDで踊るドールロボ舞ちゃん 1日目