Isaac Simで学ぶ、いちばん簡単なロボットのピッキング — 座標既知&自作IKで動かす
🤖 はじめに:この記事で作るもの
固定した場所に置いた赤いキューブを、ロボットアームがつかんで別の場所へ置く——それを延々と往復し続けるデモを、Isaac Sim 上で作ります。
ポイントは「カメラも機械学習も使わない」こと。キューブの位置は最初から座標で分かっている(既知)前提にして、ロボットを動かす一番の土台=逆運動学(IK)と状態機械だけに絞ります。派手さはありませんが、「アームを狙った座標へ動かす」という物理AIの最初の一歩を、ブラックボックスなしで自分の手で書けるようになります。
使うもの:
FANUC CRX-20iA/L(協働ロボットアーム)
Robotiq 2F-85(2本指グリッパー)
NVIDIA Isaac Sim 6.0.1
🎯 全体設計:7つの「フェーズ」で考える
ピッキングは、要するに手順の連続です。
人間なら無意識にやる動きを、
ロボットには段階(フェーズ)に分けて教えます。

この「今どのフェーズか」を管理する仕組みが 状態機械(ステートマシン) です。各フェーズには「表示名・グリッパーを閉じるか・タイムアウト」を持たせ、目標に到達したら次のフェーズへ進みます。
class Phase(IntEnum):
APPROACH_ABOVE = 0 # 上空へ移動
DESCEND = 1 # 下降して接近
GRASP = 2 # 把持
LIFT = 3 # 持ち上げ
TRANSPORT = 4 # 置き先へ搬送
PLACE_DOWN = 5 # 下降して設置(保持したまま)
RELEASE = 6 # 離す
✍️ 設計のコツ:「下降」と「離す」を分けているのがミソ。ひとつのフェーズで“降ろしながら開く”にすると、着地前に手を離してキューブを落とします。降ろしきってから離す——現実と同じ順番にするのが安定の秘訣です。
🧮 心臓部:逆運動学(IK)をどう解くか
「手先を座標 (x, y, z) へ動かしたい」。でもロボットが直接コントロールできるのは各関節の角度です。この「行きたい場所 → 関節角度」の変換が逆運動学(IK)。
この記事では、Isaac Sim の便利機能に頼らず、
ヤコビアン+減衰最小二乗法(DLS)
という王道アルゴリズムを自分で書きます。
中身は4ステップ:
① 誤差を作る … 今の手先位置と目標の差(位置3+姿勢3の6次元)
② ヤコビアンを取る … 「関節を動かすと手先がどう動くか」の対応表 J
③ 逆算する … dq = Jᵀ (J Jᵀ + λ²I)⁻¹ e で「誤差を減らす関節変化」を求める ④ 安全に丸める … 1ステップで動きすぎないよう上限でクリップ
λ²I(ダンピング項)を足すのがポイントで、これがあるおかげで特異点(腕が伸びきった姿勢など)でも計算が発散せず、なめらかに動きます。
# 減衰最小二乗解 dq = Jᵀ (J Jᵀ + λ²I)⁻¹ e
damping = np.eye(6) * (cfg.damping ** 2)
dq = task_jac.T @ np.linalg.solve(task_jac @ task_jac.T + damping, task_err)
この式そのものを「なぜこうなるのか」まで理解するには線形代数とロボット工学の知識が要ります。まずは「誤差を入れると関節の動かし方が返ってくる魔法の関数」と捉えてOK。動かしながら少しずつ中身に踏み込むのがおすすめです。
地味だけど効く工夫:ヤコビアンの「基準点ずらし」
ヤコビアンが得られるリンク(ik_link)と、実際につかみたい点(grip_frame、指の付け根)は少しズレています。剛体の運動 v_grip = v_link + ω × r を使い、そのズレ r の分だけ基準点を補正しています(コード中の skew 補正)。ここを省くと、狙いが微妙にズレます。
🌀 なめらかに動かす:追従点をちょっとずつ進める
IK にいきなり最終目標を渡すと、腕が急発進してカクつきます。そこで setpoint(追従点) を用意し、毎フレーム目標へ少しずつ近づけながら IK を解きます。人が指で目標をなぞるように動かすイメージです。
to = target - self.setpoint
dist = np.linalg.norm(to)
if dist > speed:
self.setpoint = self.setpoint + to / dist * speed # 少しだけ前進
else:
self.setpoint = target.copy()
self.ik.solve(self.setpoint)
♻️ 無限ループさせる:置き場所を入れ替える
1回置いて終わりだと寂しいので、ずっと往復し続けるようにします。
ここで一工夫。単純に最初のフェーズへ戻すだけだと、「置いた場所からまた拾って、同じ場所に置く=動かない」になってしまいます。そこで拾い先と置き先を毎サイクル入れ替えて、A地点→B地点→A地点…と往復させます。拾う位置はキューブの実座標を毎回読むので、置いた場所を自動で拾いに行きます。
self._place_idx ^= 1 # 0↔1 を交互にトグル
self.phase = Phase.APPROACH_ABOVE
🛠️ 設定を一箇所にまとめる
つかむ場所・置く場所・IKのゲインなどは、dataclass で種類ごとにまとめています。「この数字を変えると挙動が変わる」が一目で分かるのが狙いです。
@dataclass(frozen=True)
class SceneConfig:
cube_size: float = 0.06
cube_position = np.array([0.72, 0.0, 0.03]) # つかむ場所
place_position = np.array([0.50, 0.32, 0.03]) # 置く場所
above_height: float = 0.30 # 上空へ逃がす高さ
まず遊ぶなら cube_position / place_position を書き換えるのが一番わかりやすいです。
▶️ 動かし方
# Windows
C:\isaacsim\python.bat ".\simple_picking.py"
# Linux
/home/dev/isaacsim/python.sh "./simple_picking.py"
🚀 つまずきポイント & 次の一歩
うまくいかない時のチェック
腕が目標に届かない → above_height を下げる、cube_position をロボットに近づける
つかむ前に落とす → フェーズ5と6が分かれているか確認
動きがカクつく → setpoint_speed を小さく
急に暴れる → max_joint_delta(1ステップの関節変化上限)を小さく
発展のアイデア
📷 カメラを足して、座標既知 → 物体検出でつかむへ
🧠 IK を強化学習ポリシーに置き換える
📦 キューブを増やして順番にピッキング
おわりに
「アームを狙った座標へ動かす」——物理AIの一番の土台を、ライブラリのブラックボックスに頼らず自分で書けました。ここが分かると、カメラや学習を足したときに「どこがどう効いているか」が見えるようになります。
コード全文はこちら 👉コードはこちら
フィジカルAI・工場向けAI開発のご相談
私は製造業向けのAIシステム開発を行っています。
こんなお悩みはありませんか?
* 外観検査を自動化したい
* 作業監視をAI化したい
* PPE(保護具)着用チェックを導入したい
* ロボットアームへAIを組み込みたい
* ROS2・Isaac Simを活用したい
* フィジカルAIのPoCを進めたい
* 社内向けAIツールを開発したい
* Isaac simを使ってロボット操作したい
要件整理からPoC、実装まで対応可能です。
まずはお気軽にご相談ください。
お問い合わせ
https://forms.gle/qTxgVfBF622eiBWA6
技術ポートフォリオ
GitHub
Hugging Face
note
いいなと思ったら応援しよう!
無料で気軽に使えるアプリを個人で開発しています!
いただいたチップは、アプリの改善や開発環境の維持に大切に使わせていただきます。
応援していただけると、とても励みになります!