mcpField
P
physics-simulation

physics-simulation

github.com/isaac-simその他4.4k58 回インストール6 日前に更新
リポジトリ

physics-simulation について

Isaac Sim 6 と Kit 110 の物理設定を扱う実用スキルです。シーン設定、Prim ごとの構成、材質、ドライブ、センサー、バックエンド選択をスクリプトや例とともに説明します。

主な機能

  1. 01物理シーンとソルバーの設定
  2. 02剛体とコリジョンの構成
  3. 03接触材質とジョイントドライブ
  4. 04Newton と PhysX のバックエンド選択
  5. 05Prim 設定用ヘルパースクリプト

活用シーン

  1. 01剛体とコリジョンの設定
  2. 02接触の多いシーンや高速シーンの調整
  3. 03シミュレーション用バックエンドの選択

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/isaac-sim/isaacsim --skill physics-simulation

インストール後、Claude Code で/physics-simulationを入力して読み込まれたか確認します。

同梱ファイルexamples.mdscripts/prim_physics_setup.py

詳細

Isaac Sim での物理シミュレーション

目的

PhysicsScene と各プリムの剛体、コリジョン、マテリアル、ジョイントドライブ、ソルバーの選択、物理センサーを、実例を交えて設定します。

前提条件

  • スタンドアロンの物理シミュレーションの場合:source/libraries のビルドが完了しているか、対応するインストール済みのホイール/SDK が必要です。ほとんどの単体テストとヘッドレス物理テストでは GPU は不要です。
  • Kit の設定、拡張機能の自動切り替え、タイムライン、ビューポートを扱う場合:ビルド済みの Isaac Sim と、isaac-sim-orchestrator のシェル環境が必要です。

制限事項

  • セクションに別途記載がない限り、Isaac Sim 6 / Kit 110 を対象とします。
  • サポート対象外の特殊なケースについて、NVIDIA の公式ドキュメントに代わるものではありません。

トラブルシューティング

エラー/症状原因解決策
黒いフレーム、または空のフレームライトがない、または非 RTX のレンダーモードドームライト/キーライトを追加し、RTX/PathTracing の設定を確認します
ステージの読み込みまたは初回レンダリング時にハングするMDL のコンパイル、またはステージが大きすぎるisaac-sim-troubleshooting の切り分け手順に従います

スタンドアロンライブラリと Kit アダプターの違い

スタンドアロンの物理シミュレーションの実装、バックエンドの登録、エンティティ、ランタイム制御には、source/libraries/isaacsim/physics/{manager,registration,entities,ovsim} と source/libraries/isaacsim/physics_engines/{ovnewton,ovphysx} のエンジンを使用します。isaacsim.physics_engines.ovstage はプライベートな OVStage ランタイム用のプロセスレベルのセットアップとネイティブハンドルのブリッジであり、物理エンジンではありません。

isaacsim.core.simulation_manager の設定、拡張機能の有効化と自動切り替え動作、Kit のタイムライン、ビューポート、SimulationApp は Kit アダプター経由で扱います。スタンドアロンモジュールのテストにこれらの起動フラグを適用しないでください。また、利用側のワークフローを確認せずに、ライブラリの PhysicsManager を Kit の SimulationManager と単に名前を置き換えれば使えるものと見なさないでください。

インポート時の登録が公開パッケージのドキュメントに記載されているスタンドアロンエンジンでは、そのパッケージを一度インポートし、PhysicsManager を介して選択してください。通常の例に、個別の activate() や shutdown() 呼び出しを追加する必要はありません。セットアップ、初期化、ステップ実行、無効化はマネージャーを通じて行い、マジック値ではなく Stage オブジェクトが返すステージ識別子を渡してください。エンティティファサードが操作をサポートしている場合は、生のシミュレーションビューや手動のテンソル変換よりも、RigidBodyEntity と ArticulationEntity を優先してください。

バックエンドを事前に有効化せず、例の通常の公開エントリポイントを実行するテストにしてください。これにより、登録漏れやライフサイクルの所有権の問題を検出できます。正準となる構文として、チェックアウトしたエンジンの API ドキュメントと対応する source/examples のシリーズを使用してください。古い例の互換性維持用ライフサイクルをコピーしないでください。

Isaac Sim 6.0 以降/Kit 110 を対象とします。両バックエンドは UsdPhysics.* を共有します。バックエンド固有の動作については、各セクションで説明します。

利用可能なスクリプト

スクリプト目的引数
scripts/prim_physics_setup.pyIsaac Sim/USD(Kit 110)向けの各プリムの物理設定ヘルパー--help で確認してください

スクリプトの実行

スキル実行ヘルパーを利用できるエージェントのランタイムでは、run_script() を使ってヘルパーを呼び出します。

run_script("scripts/prim_physics_setup.py", args=["--help"])

ビルド済みの Isaac Sim ツリーからは、_build/*/release 内で ./python.sh(Linux)または python.bat(Windows)を使って同じファイルを実行します。シミュレーターを必要としない場合は、シェルヘルパーを直接実行することもできます。

バックエンドの選択(Kit 110)

isaacsim.core.simulation_manager は物理エンジンを登録し、アクティブなエンジンを選択します。extension.toml の default_engine は "physx" ですが、一方で、isaacsim.physics.newton 拡張機能はデフォルトで auto_switch_on_startup = true になっているため、isaacsim.physics.newton を有効にするアプリ(標準の isaacsim.exp.full.kit も該当します)は、起動時に Newton がアクティブになります。

from isaacsim.core.simulation_manager import SimulationManager

SimulationManager.switch_physics_engine("newton")   # or "physx"
print(SimulationManager.get_active_physics_engine())

# Inspect what is available
from isaacsim.physics.newton import get_available_physics_engines, get_active_physics_engine
print(get_available_physics_engines())

起動時にエンジンを明示的に指定してください。

--/exts/isaacsim.core.simulation_manager/default_engine=newton     # or =physx
--/exts/isaacsim.physics.newton/auto_switch_on_startup=false        # opt out of auto-switch

Newton の設定クラス(拡張機能の Python API。現時点ではユーザーガイドの RST には掲載されていません。拡張機能の API ドキュメントページ、または docs/isaacsim/physics/newton_physics.rst を参照してください)。

クラス役割
isaacsim.physics.newton.NewtonConfigシミュレーションごとの設定(CUDA グラフキャプチャ、Fabric 同期、接触/ジョイントのデフォルト値)
XPBDSolverConfigXPBD ソルバー(剛体+ソフトボディ)
MuJoCoSolverConfigMuJoCo Warp ソルバー
isaacsim.physics.newton.tensorsNumPy/PyTorch/Warp フロントエンド

Newton と PhysX はどちらも標準の UsdPhysics.Scene と PhysxSchema.PhysxSceneAPI を使用します。多くの PhysxSchema.* 属性は Newton でも引き続き適用され、Newton は omni.usd.schema.newton を介してソルバー設定を読み込みます。

スタックと参照順序

  1. このスキル:シーン設定、プリムごとの設定、接触マテリアル、ドライブ、センサー、読み戻し、バックエンドの選択。
  2. usd-articulation:マルチリンクアーティキュレーション+Robot Schema オーバーレイ。
  3. urdf-mjcf-to-usd-conversion:インポーター設定(RL 用ドライブと遠隔操作用ドライブ)。
  4. isaac-sim-troubleshooting:Kit 110 で物理挙動に問題が発生した場合。

メカニズムのレシピ(衝撃、フィーダー、ドミノ、こま、クレードル、振り子波、脱進機)は実例にあります。


パート 1 — シーンレベルの設定

PhysicsScene の設定
from pxr import Usd, UsdGeom, UsdPhysics, PhysxSchema, Gf

ps = UsdPhysics.Scene.Define(stage, "/World/PhysicsScene")
ps.CreateGravityDirectionAttr().Set(Gf.Vec3f(0, 0, -1))
ps.CreateGravityMagnitudeAttr().Set(9.81)

px = PhysxSchema.PhysxSceneAPI.Apply(ps.GetPrim())
px.CreateTimeStepsPerSecondAttr().Set(240)   # see Hz table below
px.CreateEnableCCDAttr().Set(True)
px.CreateEnableStabilizationAttr().Set(True)
px.CreateSolverTypeAttr().Set("TGS")          # TGS or PGS; TGS preferred for articulations
物理 Hz の選択
シナリオHz備考
標準的な剛体シーン60–120倉庫や一般的なシミュレーションのデフォルト
積み重ね/接触が多いシーン240接触を高精度に解決
高速衝突2~4 サブステップで 120CCD と組み合わせます
小型部品の振動(フィーダー)振動周波数の 4 倍以上、通常は 480振動を正しく解決
回転する剛体/ジャイロ480角運動量の数値精度を確保
剛性の高い接触連鎖(クレードル、脱進機)480ソルバーには多数のサブイテレーションが必要

**経験則:**物理のタイムステップは、システム内の最高周波数(振動、回転、接触剛性モード)の 4 倍より大きくする必要があります。

ソルバーの反復回数(剛体ごと)

必要な剛体の PhysxRigidBodyAPI に設定します。値を大きくすると精度が上がりますが、処理は遅くなります。

シナリオ位置反復回数速度反復回数
単純な剛体、転がり164
積み重ね328
複雑なジョイント/アーティキュレーション6416
剛性の高い接触連鎖(クレードル、脱進機)6432
pxrb = PhysxSchema.PhysxRigidBodyAPI.Apply(prim)
pxrb.CreateSolverPositionIterationCountAttr().Set(32)
pxrb.CreateSolverVelocityIterationCountAttr().Set(8)
pxrb.CreateEnableCCDAttr().Set(True)
安定化を無効にする場合

EnableStabilizationAttr はデフォルトで有効になっており、積み重ねた物体の静止を助けます。自由に回転する物体では角運動量を失わせます。次の場合は無効にしてください。

  • 回転するこま、ジャイロ、フライホイール
  • 振り子機構(時計の脱進機、振り子波)
  • 角速度の保存が正しさの条件となるもの
px.CreateEnableStabilizationAttr().Set(False)

パート 2 — プリムごとの物理設定

RigidBody/Collision/Static/Kinematic

動的、静的、キネマティックな剛体の設定には、scripts/prim_physics_setup.py を使用します。RigidBodyAPI、MassAPI、CollisionAPI の適用手順を、実行可能な実装にまとめています。

ルール:RigidBodyAPI と CollisionAPI は同じプリムに適用してください。親と子に分けると、断続的に衝突が失敗する原因になります。

スケールを指定した静的コライダー — 位置を先に指定するパターン

CollisionAPI を直接適用した Cube プリムをスケーリングすると、PhysX が誤った衝突境界を使用します(物体が床をすり抜けます)。位置には親の xform を使用し、スケールには子のメッシュを使用します。

# CORRECT
xf = UsdGeom.Xform.Define(stage, "/World/Ground")
UsdGeom.Xformable(xf.GetPrim()).AddTranslateOp().Set(Gf.Vec3d(0, 0, -0.05))
mesh = UsdGeom.Cube.Define(stage, "/World/Ground/Mesh")
mesh.CreateSizeAttr().Set(1.0)
UsdGeom.Xformable(mesh.GetPrim()).AddScaleOp().Set(Gf.Vec3f(50.0, 50.0, 0.1))
UsdPhysics.CollisionAPI.Apply(mesh.GetPrim())

Cube.size=1.0 は、キューブの半径が 1.0 ではなく 0.5 であることを意味します。「スケール演算の値を半径と一致させたい」場合は、size=2.0 を使用してください。

質量と慣性
mass_api = UsdPhysics.MassAPI.Apply(prim)
mass_api.CreateMassAttr().Set(0.25)                                    # kg
mass_api.CreateCenterOfMassAttr().Set(Gf.Vec3f(0, 0, 0.05))            # local
mass_api.CreateDiagonalInertiaAttr().Set(Gf.Vec3f(1e-4, 1e-4, 2e-4))   # kg·m²

URDF からインポートしたロボットでは、幾何形状から自動計算される慣性よりも、config.yaml で import_inertia_tensor: true を設定することを推奨します(urdf-mjcf-to-usd-conversion を参照)。


パート 3 — 接触マテリアル

def create_contact_material(stage, mat_path, static_friction=0.5,
                            dynamic_friction=0.4, restitution=0.1):
    prim = stage.DefinePrim(mat_path)
    mat = UsdPhysics.MaterialAPI.Apply(prim)
    mat.CreateStaticFrictionAttr().Set(static_friction)
    mat.CreateDynamicFrictionAttr().Set(dynamic_friction)
    mat.CreateRestitutionAttr().Set(restitution)
    return mat
参考値
マテリアルの組み合わせ静摩擦係数 μ動摩擦係数 μ反発係数
コンクリート同士0.60.50.05
鋼材同士0.740.570.6
ゴム同士0.80.70.5
ゴムとコンクリート1.00.80.3
木材同士0.50.30.2
一般的な金属0.40.30.2
プラスチック(サイコロ)0.40.30.3
フェルト(カジノ)0.50.40.2
段ボールと鋼材0.40.30.1

剛性の高い接触が連続する場合(ニュートンのゆりかご、脱進機など)は、各接触で最も高い反発係数が適用されるよう、PhysxMaterialAPI で restitutionCombineMode=max を設定してください。


パート 4 — 関節ドライブ

joint = stage.GetPrimAtPath("/World/Robot/joint_arm")
drive = UsdPhysics.DriveAPI.Apply(joint, "angular")    # "angular" | "linear"
drive.CreateTypeAttr().Set("force")                    # "force" | "acceleration"
drive.CreateStiffnessAttr().Set(1000.0)                # Kp (Nm/rad for angular)
drive.CreateDampingAttr().Set(100.0)                   # Kd (Nm·s/rad)
drive.CreateMaxForceAttr().Set(500.0)                  # torque/force limit
drive.CreateTargetPositionAttr().Set(0.0)              # target (deg or m)

RL トレーニングでは、エージェントがトルクを直接指令します。config.yaml で drive_type を none に設定し、stiffness と damping を 0 にしてください(urdf-mjcf-to-usd-conversion を参照)。有効な PD ドライブは RL エージェントの制御と競合します。

回転振り子関節(時計の脱進機、振り子波など)では、関節の摩擦を 0 に設定してください。

joint_api = PhysxSchema.PhysxJointAPI.Apply(joint)
joint_api.CreateJointFrictionAttr().Set(0.0)

パート 5 — バックエンドの選択(Newton と PhysX)

簡単な選び方
希望する用途使用するもの
数千の環境を使った RL トレーニングNewton(Featherstone または MuJoCo)
微分可能なシミュレーションNewton
Isaac Sim 5.x のレガシー PhysX シーンPhysX
ソフトボディ、布、変形可能オブジェクトNewton(VBD または XPBD)
MuJoCo のベースラインで検証済みNewton SolverMuJoCo
Newton ソルバー
ソルバー座標系微分可能最適な用途
SolverFeatherstone一般化座標系はい(Warp)多関節ロボット(マニピュレーター、脚式ロボットのデフォルト)
SolverMuJoCo一般化座標系はい(mujoco-warp)検証済みの移動動作、MuJoCo ポリシーの移植
SolverXPBD最大座標系部分的ソフト拘束、ケーブル、ロープ
SolverSemiImplicit最大座標系はい(Warp)高速なプロトタイピング、単純な剛体
SolverVBD(変形可能)はいソフトボディ、変形可能オブジェクト

Newton でも実行する必要がある、既存の PhysX 専用 USD アセットについては、physx-to-newton-conversion を参照してください。

Newton と PhysX の違い
項目PhysXNewton
バックエンドクローズドな C++/CUDAWarp/CUDA(オープン、JIT)
座標系最大座標系(剛体ごとに 6DoF)一般化座標系(Featherstone)または最大座標系
微分可能いいえはい(ネイティブの Warp 自動微分)
マルチ GPU制限ありはい(Warp のデバイス抽象化)
USD 統合スキーマ拡張ネイティブ USD ローダー
パフォーマンスの上限4096 環境未満で良好10K 以上の環境向けに設計
Newton + Torch — 初期化順序の重要事項

Newton の物理演算が安定する前に import torch を実行しないでください。CUDA コンテキストの競合により Kit がハングします。timeline.play() と安定化ループの後まで torch のインポートを遅らせてください。VRAM が不足する場合は、ポリシー推論で map_location="cpu" を使用してください。

Newton 固有の設定(Isaac Lab)
# config.yaml for URDF→USD conversion (Isaac Lab)
make_instanceable: true    # CRITICAL for RL parallel envs
fix_base: false            # true for fixed-base arm; false for mobile/legged

スキーマ全体については、urdf-mjcf-to-usd-conversion を参照してください。


パート 6 — 物理センサー

現在の名前空間は isaacsim.sensors.experimental.physics です(作成用クラスとランタイムクラスが対になっています)。従来の isaacsim.sensors.physics インポートパスも引き続き動作しますが、新しいコードでは非推奨です。

移行: 概念の対応関係と更新されたスクリプトについては、isaacsim.sensors.physics から isaacsim.sensors.experimental.physics への移行を参照してください。

接触
from isaacsim.sensors.experimental.physics import Contact, ContactSensor
import isaacsim.core.experimental.utils.app as app_utils

contact = Contact.create(
    path="/World/Robot/foot/contact",
    min_threshold=0.0, max_threshold=1e6, radius=-1,   # -1 = use collision shape
)
sensor = ContactSensor(contact)
app_utils.play(commit=True)            # required before get_data()
reading = sensor.get_data()            # ContactSensorReading
IMU
from isaacsim.sensors.experimental.physics import IMU, IMUSensor

imu = IMU.create(path="/World/Robot/imu", tick_rate=200.0)
sensor = IMUSensor(imu, annotators=["linear_acceleration", "angular_velocity", "orientation"])
app_utils.play(commit=True)
frame = sensor.get_data()                # returns IMUSensorReading
力/関節状態

同じモジュールのランタイム専用クラスです。個別の作成用タイプはなく、パスを指定して既存の関節をラップします。

from isaacsim.sensors.experimental.physics import EffortSensor, JointStateSensor

effort = EffortSensor("/World/Robot/joint_arm_1")
joint  = JointStateSensor("/World/Robot/joint_arm_1")
app_utils.play(commit=True)
reading = effort.get_data()              # EffortSensorReading
state   = joint.get_data()               # JointStateSensorReading
Raycast(シーンのクエリ)
import omni.physics.tensors as physics_tensors

sim_view = physics_tensors.create_simulation_view("cuda:0")
hit = sim_view.raycast_closest(origin, direction, max_dist)

より高精度なセンサーシミュレーション(LiDAR のスキャンパターン、マルチレイ、ベンダー製センサーモデル、深度/レーダー/音響)については、isaac-sim-sensor と isaac-camera を参照してください。これらは最新の isaacsim.sensors.experimental.rtx と .physics 名前空間を使用します。


パート 7 — 物理から USD への読み戻し(重要)

最もよくある、気づきにくいバグは、シミュレーション状態ではなく、作成済みの USD トランスフォームを読み取ることです。

ソース返される値使用するタイミング
UsdGeom.XformCache.GetLocalToWorldTransform()作成済みの USD トランスフォーム(初期姿勢)再生前のエディター時のクエリ
RigidPrim.get_world_pose()シミュレーションされた状態シミュレーション中は常に
Articulation.get_world_poses() (Kit 110)アーティキュレートされた剛体のシミュレーションされた状態アーティキュレートされたロボット
Dynamic Control (DC) dc.get_rigid_body_pose()シミュレーションされた状態レガシー/簡易スクリプト
シミュレーション中に XformCache が誤った値を返す理由

updateToUsd=True は物理状態を USD ステージレイヤーではなく、Fabric に書き込みます。XformCache は USD レイヤーを読み取るため、初期姿勢を返し続けます。

RigidPrim/GeomPrim のパターン(Kit 110)
from isaacsim.core.experimental.prims import RigidPrim
import isaacsim.core.experimental.utils.app as app_utils

rp = RigidPrim(paths="/World/Dice/Die_*")
app_utils.play(commit=True)
pos_wp, quat_wp = rp.get_world_poses()   # warp arrays
positions  = pos_wp.numpy()              # (N, 3)
quaternions = quat_wp.numpy()            # (N, 4) [w, x, y, z]
Articulation のパターン(Kit 110)
from isaacsim.core.experimental.prims import Articulation
import isaacsim.core.experimental.utils.app as app_utils

robot = Articulation("/World/Robot")
app_utils.play(commit=True)        # required for tensor data
pos_wp, quat_wp = robot.get_world_poses()
dof_positions  = robot.get_dof_positions().numpy()    # (N, num_dofs)
dof_velocities = robot.get_dof_velocities().numpy()
J = robot.get_jacobian_matrices().numpy()             # for IK

レガシーの isaacsim.core.api.articulations.Articulation/isaacsim.core.api.prims.RigidPrim も引き続き読み込めますが、isaacsim.core.experimental.* スタックに置き換えられています。

移行: より広範な omni.isaac.* → isaacsim.* の名称変更マップについては、拡張機能の名称変更を参照してください。実験的な Articulation/RigidPrim API については、Python スクリプティングのインデックスを参照してください。

クォータニオンの規約

USD/Isaac は [w, x, y, z] を使用し、scipy は [x, y, z, w] を使用します。次のように変換します。

from scipy.spatial.transform import Rotation
r = Rotation.from_quat([quat[1], quat[2], quat[3], quat[0]])
euler = r.as_euler('xyz', degrees=True)

パート 8 — よくある注意点

  1. CollisionAPI だけでは静的コライダーになります。動的にするには RigidBodyAPI と CollisionAPI が必要です。
  2. 同一 prim の要件:両方の API を同じ primに設定する必要があります。
  3. キネマティックボディ:RigidBodyAPI の有効/無効を切り替えるのではなく、CreateKinematicEnabledAttr().Set(True) を使用します。
  4. Cube.size=1.0 は半径が 0.5 です。スケール操作の値を半径と一致させたい場合は、size=2.0 を使用します。
  5. physics:velocity USD 属性は実行時に PhysX に無視されます。timeline.play() の後に RigidPrim.set_linear_velocities() を使用します。
  6. physics:angularVelocity の単位は度/秒であり、rad/s ではありません。math.degrees() で変換します。
  7. SimulationContext.step(render=True) は、物理をレンダリングとともに進める唯一の信頼できる方法です。app.update() は物理を同期しません。
  8. 実験的なセンサーでは get_data() の前に app_utils.play(commit=True)(または timeline.play())が必要です。レガシーの World フローから initialize() を呼び出さないでください。
  9. Isaac Sim 5.1 以降では get_rigid_body_state() は存在しません。isaacsim.core.experimental.prims の RigidPrim.get_world_poses() を使用してください。
  10. PhysX は、同じアイランド内の接触連鎖における連続的な運動量伝達を解決できません(実例 4:ニュートンのゆりかご — PhysX の同一アイランド接触の制限を参照)。
  11. 高速回転時のすり抜け:複合コライダーは、約 50 rad/s を超えると 5~6 秒後に機能しなくなります。より単純な凸包を使用するか、物理演算の Hz を上げてください。
  12. コントローラーを診断する前に:PhysicsScene、アクティブなタイムライン、想定される Collision API が存在することを確認してください。

実例(衝撃、振動フィーダー、ジャイロ、ゆりかご、脱進機)

詳細は examples.md を参照してください。

コメント