CCD IKを捨てた
LOG97R2R2R2026/3/15

CCD IKを捨てた

3日間格闘したCCD IKを捨てた。

捨てた理由は明確だった。ログが「発振」を証明したからだ。

やったこと

link1 Z軸傾き問題の解決

再生のたびにlink1(ベース回転関節)がZ軸方向に倒れる問題から始まった。ログを分析すると、原因はCCD IKの回転軸計算のズレだった。

link1はベース回転関節なので、world空間での回転軸はほぼ純粋なY軸であるべきだ。しかし anchorRotation から計算しようとしたことで、Z成分0.39が混入していた。

// 変更前:anchorRotationから取得(ズレあり)
Vector3 jointAxis = targetJoints[i].anchorRotation * Vector3.right;
jointAxis = jointTransform.TransformDirection(jointAxis);

// 変更後:link1だけworld Y軸を直接指定
if (i == 0)
{
    jointAxis = Vector3.up;
}

1行の修正で倒れが止まった。

CCD IK発振の発見

link1の問題は解決した。しかし次に別の問題が浮かんだ。アームが震えて止まらない。

ログを確認すると、診断グラフに衝撃的な波形が現れた。

drive_target(関節の目標角度)が0から160の間を毎フレーム往復していた。

angle:        +30° → -30° → +30° → -30°(毎フレーム交互)
drive_target: 0 → 160 → 0 → 160(上限と下限を往復)

原因は += による累積だった。

drive.target += angle * speed;  // 毎フレーム累積する

Clampの上限に当たる→次フレームで逆向きに振れる→下限に当たる→また逆向き。この発振は止まらない。速度を変えても、デッドゾーンを追加しても、距離比例速度にしても止まらなかった。構造的な問題だったからだ。

CCD IKはこの時点でLOG90から7日間使い続けてきた制御の中核だった。

方針転換:CSVプレイバック制御

3日間格闘したCCD IKをLOG97で諦めた。

代わりに採用したのがCSVプレイバック制御だ。「リアルタイムに計算して動かす」のではなく、「あらかじめ計算された正解の角度列を、フレームごとに流し込む」アプローチへの転換だ。

Python(5次多項式)→ 軌道CSV → Unity(drive.target)

軌道の生成にはPythonの5次多項式(最小ジャーク)を使った。

def min_jerk(q_from, q_to, n_frames):
    for i in range(n_frames):
        t = i / (n_frames - 1)
        s = 10*t**3 - 15*t**4 + 6*t**5  # 5次多項式
        q = q_from + (q_to - q_from) * s

最小ジャーク軌道とは、加加速度(ジャーク)を最小化する軌道だ。人間の腕の動きに近く、急激な速度変化がない。実機ロボットの軌道計画でも使われる手法を、Pythonで手軽に生成できる。

TrajectoryFollower.csの実装

CSVを読み込んでFixedUpdateで流し込む専用スクリプトを実装した。RobotArmControllerとは独立した新スクリプトとして設計し、監視ログも内蔵させた。

void FixedUpdate()
{
    if (!isReady || isComplete) return;

    float[] targets = trajectory[frameIndex];
    for (int i = 0; i < joints.Length && i < 6; i++)
    {
        var drive = joints[i].xDrive;
        drive.target = targets[i];  // CSVの角度を流し込む
        joints[i].xDrive = drive;
        joints[i].SetDriveTarget(ArticulationDriveAxis.X, drive.target);
    }
    frameIndex++;
}

FixedUpdateで動かすことで物理演算と同期する。LateUpdateでは「高速すぎて物理がついていけない」問題が起きていた。

結果

アームが滑らかに動いた。

震えがない。発振がない。旋回90°、前傾、折り曲げ、初期姿勢への復帰。15秒の動作シーケンスが滑らかに再生された。

CCD IKを捨てた判断は正しかった。

教訓

計算で動かすより、正解を流し込む方が速いことがある。

CCD IKは「目標座標からリアルタイムに関節角度を計算する」アプローチだ。汎用性は高いが、Unityの物理エンジンとの相性問題、累積誤差による発振、パラメータ調整の難しさがある。

CSVプレイバックは「正解の角度列を流し込む」アプローチだ。汎用性は低いが、震えが起きない、デバッグが簡単、軌道の品質がPythonで制御できる、という強みがある。

以降の方針

  • pick and place軌道CSVの生成(把持・リフト・配置の角度列をPythonで作成)

  • カップ把持タイミングの実装(isKinematicによる把持制御をCSVと連動させる)

  • pick and place完全動作の確認

※ プロジェクト名「R2R2R」は、UC Berkeley・Toyota Research Instituteの研究「Real2Render2Real」(Yu, Fu et al., 2025)の概念に触発されています。現実空間をデジタルツイン化し、仮想空間での試行から得た知見を実世界のモーター駆動へ還元する——その設計と実装過程を毎日記録しています。技術アプローチおよび目的は独自のものです。