UnityシミュレーションフェーズからmechArm 270実機フェーズへ|R2R2Rの転換点
数字が並んだ。success=True × 12。これで第一フェーズを閉じる。
このプロジェクトについて
iPhoneで撮影した現実空間をUnityでデジタルツイン化し、ロボットアームの動作をシミュレーションで最適化してから実機に展開するパイプラインを個人で構築している。
ターゲットはシンプルだ。ロボットアームがコーヒーカップを掴み、台座の上に置く。その一連の動作を、iPhoneとUnityだけで設計できることを証明する。
この記録は「一つの答えが出た日」の話だ。
検出ロジックの修正
LOG100で「全12パターン失敗」と見えたsummary.csvの誤検知を修正した。
問題は3つあった。
問題1:GRASP_MISS誤検知 isGrasping フラグではなく endEffectorとカップの物理距離 で判定していた。把持が成立しているのに「距離が遠い」という理由でFailが記録されていた。
修正前:dist = Vector3.Distance(endEffector, cup) > 0.05m → GRASP_MISS
修正後:isGrasping == false → GRASP_MISS問題2:JOINT_LAG閾値が厳しすぎた 15度設定に対してfastパターンが21〜23度に達していた。動作は完走しているのに失敗扱いになっていた。
修正前:JOINT_LAG_THRESHOLD = 15度
修正後:JOINT_LAG_THRESHOLD = 20度問題3:fast速度が速すぎた 閾値を20度に緩和してもfastが18〜19度に収まるよう、速度を20%落とした(セグメント時間を×1.25倍に延長)。
修正前:fast base_sec = 1.5秒
修正後:fast base_sec = 1.875秒(20%延長)3つの修正を順番に入れてbatch02→03→04と確認した。最終結果:
batch04 / success=True × 12
high_fast: True j_lag_max=18.06° place_err=0.0001m
high_normal: True j_lag_max=12.38° place_err=0.0002m
high_slow: True j_lag_max= 8.58° place_err=0.0000m
low_fast: True j_lag_max=18.06° place_err=0.0001m
low_normal: True j_lag_max=12.38° place_err=0.0002m
low_slow: True j_lag_max= 8.58° place_err=0.0000m
side_fast: True j_lag_max=19.78° place_err=0.0001m
side_normal: True j_lag_max=13.61° place_err=0.0002m
side_slow: True j_lag_max= 8.69° place_err=0.0000m
standard_fast: True j_lag_max=19.37° place_err=0.0001m
standard_normal:True j_lag_max=12.68° place_err=0.0002m
standard_slow: True j_lag_max= 8.58° place_err=0.0000mplace_err は全パターンで0.0〜0.2mm。実質ゼロだ。
シミュレーションフェーズで確立したこと
このプロジェクトで確立してきたことを整理する。
iPhoneスキャン(LOG1〜LOG30台) 3Dpressoによるターンテーブルスキャンでコーヒーカップの3Dモデルを生成した。スケール合わせ(小鉢直径10.5cm = Unity Scale 0.105)を確立した。
デジタルツイン構築(LOG30台〜LOG70台) mecharm_270_m5のURDFをUnityにインポートし、ArticulationBodyベースの物理シミュレーションを動かした。Stiffness 20,000 / Damping 2,000の物理パラメータを確立した。
CCD IK実装(LOG89〜LOG91) anchorRotation による真の回転軸導出と平面投影SignedAngle計算で6軸制御を実現した。5mm目標到達精度を達成した。
FixedJointグラスピング(LOG92) EndEffectorにRigidbody(IsKinematic=ON)を追加してFixedJoint把持を確立した。4ステートループ(REACH_CUP → GRASP → REACH_PLACE → PLACE)が完成した。
軌道設計とCSV化(LOG99〜LOG100) 5次多項式補間によるスムーズな軌道生成。4アプローチ × 3速度 = 12パターンのCSVを自動生成するパイプラインを構築した。
ログ診断インフラ(LOG100〜LOG101) フレームログ + サマリーの2層ログ構造を確立した。失敗検出4種(GRASP_MISS / GRASP_DRIFT / PLACE_MISS / JOINT_LAG)の計測ロジックを完成させた。
何が証明されたか
iPhoneとUnityだけで、
ロボットアームがカップを掴んで台座に置く動作を
個人が設計できることが証明された。これがこのプロジェクトのコアメッセージだった。シミュレーション上では成立した。
追加機材は使っていない。エンジニアリングチームもない。秋田の自宅で、iPhoneとMacとUnityだけで到達した。
次のフェーズへ:シミュレーションと実機の差分を埋める
シミュレーションでは cup_x/y/z がUnityの物理エンジンからフレームごとに取れる。実機では取れない。
この差分を埋めることがフェーズ2の課題だ。
フェーズ2a:
関節完走フラグ + iPhone LiDAR前後スナップ比較
→ 「カップが台座に乗っているか」を数値で確認
フェーズ2b:
iPhone ARKitリアルタイムストリーミング
→ シミュレーションと同じログ構造で実機データを取得パイプラインの入り口はiPhoneだった。出口もiPhoneになる。
実装コード(TrajectoryFollower.cs・修正後のGRASP_MISS判定)
// GRASP_MISS判定:isGraspingフラグで判定する
// (物理距離ではなく、把持が成立したかどうかで判定)
if (prevSegment == "to_grasp" && segment != "to_grasp" && !failDetected)
{
if (!isGrasping)
{
failDetected = true;
failState = "to_grasp";
failFrame = frameIndex;
failReason = FAIL_GRASP_MISS;
}
// isGrasping == true なら成功。何もしない。
}# generate_motions.py:fast速度を20%延長
SPEEDS = {
"slow": {"base_sec": 5.0, "fps": 50},
"normal": {"base_sec": 3.0, "fps": 50},
"fast": {"base_sec": 1.875, "fps": 50}, # 1.5 × 1.25 (20%延長)
}