FABRIK(Forward And Backward Reaching Inverse Kinematics)は、逆運動学(Inverse Kinematics)を解くための手法の一つです。従来のジョイント回転を考慮する方法と異なり、FABRIKはセグメントを前方・後方に反復して動かすことで目標位置に収束させるアルゴリズムです。本記事では、FABRIKの基本概念を解説し、Processingでの実装方法を紹介します。

Index

FABRIKアルゴリズム

FABRIKは2011年にAndreas AristidouとJoan Lasenbyによって提案された逆運動学アルゴリズムです。従来の逆運動学アルゴリズムでは、行列計算やジョイントの回転を扱う手法が多く用いられてきましたが、FABRIKはより直感的にセグメントの長さを維持しながら、ターゲットまでの距離に基づいて各セグメントを移動のが特徴です。

FABRIKのアルゴリズム

FABRIKは次の手順で計算を行います。

  1. 前方リーチング(Forward Reaching)
    ・エンドエフェクター(End effector)を目標位置へ移動させる。
    ・セグメントの長さを維持しながら、各ジョイントを順番に調整。
  2. 後方リーチング(Backward Reaching)
    ・基点(Root)を元の位置に固定させる。
    ・セグメントの長さを維持し、位置合わせを微調整するために、ジョイントを逆順に調整。

この2つのステップを繰り返し、エンド エフェクターがターゲットに十分近づくまで、これらの手順を繰り返します。FABRIKのメリットは、計算が直感的で行列計算を必要とせず、一般的なInverse Kinematics手法よりも収束が速いことが特徴です。

類似アルゴリズムとの比較

FABRIKは、以下のような他のInverse Kinematicsアルゴリズムと比較されます。

  • CCD(Cyclic Coordinate Descent)
    ・各ジョイントを1つずつ回転させて目標に近づける方法。
    ・シンプルで高速だが、収束性が必ずしも保証されない。
  • Jacobian Inverse(ヤコビ行列を用いた手法)
    ・行列を使って目標への最適な動きを求める。
    ・非線形最適化の手法であり、計算コストが高くなることがある。

FABRIKは、これらの手法に比べて直感的であり、行列計算を必要としないため、多くのリアルタイムアプリケーションに適しています。

Processingでの実装

Processingを使ってFABRIKを実装していきます。

1. EndEffector クラスの定義

FABRIKでは、各ジョイント間の距離が重要です。まず、EndEffectorを定義するクラスを作成します。各EndEffectorは、運動連鎖内のジョイントを表します。EndEffectorにはポジション(pos)と固定された長さ(leng)があり、これにより、各ジョイントの動きをシステム化します。


class EndEffector {
  PVector pos;
  float leng;

  EndEffector(float x, float y, float len) {
    pos = new PVector(x, y);
    leng = len;
  }
}

2. 複数のEndEffectorを初期設定する。

ArrayList で EndEffector を任意の個数で制作します。


ArrayList effectors = new ArrayList<>();
int numEffectors = 10;

3. Forward Reaching (Inverse Kinematics)

Forward Reachingでは、すべてのセグメントの長さを固定したまま、EndEffectorをターゲットに向かって移動します。

1. エンドエフェクタのポジションをターゲットに設定する
EndEffectorのポジションを設定します。effectors.get(effectors.size() – 1)は最後のジョイントなので、target(mouseの位置)をコピーします。


  EndEffector endEffector = effectors.get(effectors.size() - 1);
  endEffector.pos = target.copy();

2. 各ジョイントを次のジョイントに向かって動かす
各ジョイントを次のジョイントに向かって移動します。最後から 2 番目のジョイントから最初のジョイントまで逆方向に繰り返します。各ジョイントは、長さを維持しながら、次のジョイント (ターゲットに近い側) に向かって移動します。(segments.size()から-2するのは、Listは0から始まり、追従するEndEffectorをもとめるため)。


  for (int i = effectors.size() - 2; i >= 0; i--) {
    EndEffector current = effectors.get(i);
    PVector direction = PVector.sub(endEffector.pos, current.pos); // Calculate direction
    direction.setMag(current.length); // Set vector magnitude to match segment length
    current.pos = PVector.sub(endEffector.pos, direction); // Move joint to new position
    endEffector = current;
  }

setMag() 関数は、移動した距離を決めらて長さ(leng)にベクトルをスケーリングします。

4. Backward Reaching

Forward Reachingの後、基点とするeffectorのポジションが移動している可能性があります。Backward Reachingでは、セグメントの長さを維持しながらルートとなるポジションを元の位置に戻します。

1. ルートのポジションを修正する
ルートの位置を固定する最初のジョイントは、最初の位置に固定されたままなので、previousに最初のEndEffectorを代入し、posに基点(root)を代入します。


  EndEffector previous = effectors.get(0);
  previous.pos = root;

2. 各ジョイントを基点側に移動する。
先ほどとは逆にルートからエンドエフェクタに向かってチェーンを反復し、各effectorsの長さを固定したまま各ジョイントを調整します。


  for (int i = 1; i < effectors.size(); i++) {
    EndEffector current = effectors.get(i);
    PVector direction = PVector.sub(current.pos, previous.pos); // Calculate direction
    direction.setMag(previous.length); // Maintain segment length
    current.pos = PVector.add(previous.pos, direction); // Move joint to new position
    previous = current;
  }

この手順により、チェーンが接続されたままになり、長さの制約が守られながらルートと適切にポジション合わせされます。

5. 各EndEffectorを繋げる

Forward Reaching と Backward Reaching にて得られた各effectorのポジションを線や点で繋ぎます。


  PVector current, next;
  for(int i=0; i < effectors.size()-1; i++){
    current = effectors.get(i).pos;
    next = effectors.get(i+1).pos;
    line(current.x,current.y, next.x,next.y);
  }

FABRIK - Forward And Backward Reaching Inverse Kinematics

FABRIKはシンプルながらも効率的な逆運動学アルゴリズムであり、Processingを用いることで直感的に実装できます。本記事のコードをベースに、EndEffectorの数や長さ、ジョイントの回転制限や3Dへの拡張など、さらなるコード改変ができます。

参考:FABRIK: A fast, iterative solver for the Inverse Kinematics problem (PDF)

Sample Code フリーダウンロード on Patreon

Patreon : barbe_generative_diary(英語) にてSample Codeをフリーダウンロードできます。登録するとその他全ての記事が閲覧可能になります。登録はフリーです。

Sample Code Explanation
キーを押すと、ルート位置の固定と解除を切り替えることができます。(backwardReachingのON・OFF)

FABRIK-final

Recommended Book for Digital arts

book-generative_design

Generative Design / Processingで切り拓く、デザインの新たな地平
-Harmut Bohnacker, Benedikt Groß, Julia Laub

2012年に出版されたGenerative Designの日本語版、プログラミングによる視覚表現の解説本。Generative Designのオリジナルライブラリを利用することで、ビギナーにも優しいプログラムコードと解説でジェネラティブデザインが楽しめます。たくさんの美しい作品例と解説により、インスピレーションやリソースとして役立つだけでなく、プログラマーでない人にとっても新しいデザイン体験を与えてくれます。

ーーーーー
► 『Generative Design / Processingで切り拓く、デザインの新たな地平』(Harmut Bohnacker, Benedikt Groß, Julia Laub)

BGD_SOUNDS on bandcamp

BGD_SOUNDSでは、bandcamp上にて、安価で利用できる膨大な著作権フリーのサウンドライブラリーを目指して日々様々な音源ライブラリーを増やしています。音源のほとんどは、192kHzの32bitの高音質にて録音。音楽制作や映像制作など用途に合わせて利用可能です。また、Sound visualization Penplot artも定期的に販売しています。

BGD_CLUB(月額サブスクリプション)も低価格から始めており、すべてのライブラリーにアクセスし自由にダウンロードすることも可能です。

Link / BGD_SOUNDS on bandcamp