fix: IS 4.1.0 + Blackwell GPU compatibility fixes
- Add scipy Rotation scalar_first monkey-patch for older scipy (<1.11) - Fix SimulationApp import to support both IS 4.x and 5.x - Reuse task object across reset() calls to prevent duplicate prims - Add _scene_initialized guard in set_up_scene() for repeated resets - Cache arena_file_path to survive task_cfg.pop() - Clean up collision groups before re-creating - Switch to PathTracing renderer for clean output on Blackwell GPU Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ load_stage:
|
||||
rendering_dt: 1/30 # Render update rate
|
||||
stage_units_in_meters: 1.0 # Stage unit scale
|
||||
headless: True # Headless mode (no GUI); set false for visual debugging
|
||||
renderer: "PathTracing" # PathTracing: higher quality, less noise on Blackwell
|
||||
anti_aliasing: 0 # Anti-aliasing level
|
||||
layout_random_generator: # Scene randomization
|
||||
type: env_randomizer
|
||||
|
||||
35
launcher.py
35
launcher.py
@@ -5,6 +5,41 @@ from nimbus.utils.utils import init_env
|
||||
|
||||
init_env()
|
||||
|
||||
# Patch scipy.spatial.transform module so that `from_quat` and `as_quat`
|
||||
# accept `scalar_first=` on older scipy (< 1.11).
|
||||
try:
|
||||
from scipy.spatial.transform import Rotation as _R
|
||||
_R.from_quat([1, 0, 0, 0], scalar_first=True)
|
||||
except TypeError:
|
||||
import numpy as _np
|
||||
import scipy.spatial.transform as _sst
|
||||
from scipy.spatial.transform import Rotation as _OrigR
|
||||
|
||||
class Rotation(_OrigR):
|
||||
@classmethod
|
||||
def from_quat(cls, quat, *args, scalar_first=False, **kwargs):
|
||||
quat = _np.asarray(quat, dtype=float)
|
||||
if scalar_first:
|
||||
if quat.ndim == 1:
|
||||
quat = _np.array([quat[1], quat[2], quat[3], quat[0]])
|
||||
else:
|
||||
quat = _np.concatenate([quat[..., 1:], quat[..., :1]], axis=-1)
|
||||
return super().from_quat(quat, *args, **kwargs)
|
||||
|
||||
def as_quat(self, *args, scalar_first=False, **kwargs):
|
||||
q = super().as_quat(*args, **kwargs)
|
||||
if scalar_first:
|
||||
if q.ndim == 1:
|
||||
q = _np.array([q[3], q[0], q[1], q[2]])
|
||||
else:
|
||||
q = _np.concatenate([q[..., 3:], q[..., :3]], axis=-1)
|
||||
return q
|
||||
|
||||
_sst.Rotation = Rotation
|
||||
import sys
|
||||
sys.modules['scipy.spatial.transform._rotation'].Rotation = Rotation
|
||||
sys.modules['scipy.spatial.transform'].Rotation = Rotation
|
||||
|
||||
import argparse
|
||||
|
||||
from nimbus import run_data_engine
|
||||
|
||||
@@ -60,7 +60,10 @@ class EnvLoader(SceneLoader):
|
||||
if isinstance(rendering_dt, str):
|
||||
rendering_dt = float(Fraction(rendering_dt))
|
||||
|
||||
from isaacsim import SimulationApp
|
||||
try:
|
||||
from isaacsim import SimulationApp # IS 5.x
|
||||
except ImportError:
|
||||
from omni.isaac.kit import SimulationApp # IS 4.x
|
||||
|
||||
self.simulation_app = SimulationApp(
|
||||
{
|
||||
|
||||
@@ -63,6 +63,17 @@ class BananaBaseTask(BaseTask):
|
||||
self._defaultFluidPath = Sdf.Path("/World/task_0/fulid")
|
||||
|
||||
def set_up_scene(self, scene: Scene) -> None:
|
||||
# Skip re-initialization if scene is already set up (repeated reset() calls)
|
||||
if getattr(self, '_scene_initialized', False):
|
||||
self._task_objects = {}
|
||||
self._task_objects |= (
|
||||
getattr(self, 'fixtures', {}) |
|
||||
getattr(self, 'objects', {}) |
|
||||
getattr(self, 'robots', {}) |
|
||||
getattr(self, 'cameras', {})
|
||||
)
|
||||
return
|
||||
self._scene_initialized = True
|
||||
super().set_up_scene(scene)
|
||||
self._set_envmap()
|
||||
self.cfg = update_scenes(self.cfg)
|
||||
|
||||
@@ -27,6 +27,11 @@ def filter_collisions(
|
||||
# We invert the collision group filters for more efficient collision filtering across environments
|
||||
physx_scene.CreateInvertCollisionGroupFilterAttr().Set(True)
|
||||
|
||||
# Clean up existing collision groups before re-creating (handles repeated reset() calls)
|
||||
collision_prim = stage.GetPrimAtPath(collision_root_path)
|
||||
if collision_prim.IsValid():
|
||||
stage.RemovePrim(collision_root_path)
|
||||
|
||||
UsdGeom.Scope.Define(stage, collision_root_path)
|
||||
|
||||
with Sdf.ChangeBlock():
|
||||
|
||||
@@ -45,6 +45,7 @@ class SimBoxDualWorkFlow(NimbusWorkFlow):
|
||||
self.scene_info = scene_info
|
||||
self.step_replay = False
|
||||
self.random_seed = random_seed
|
||||
self._arena_file_path = None
|
||||
super().__init__(world, task_cfg_path)
|
||||
|
||||
def parse_task_cfgs(self, task_cfg_path: str) -> list:
|
||||
@@ -76,7 +77,8 @@ class SimBoxDualWorkFlow(NimbusWorkFlow):
|
||||
|
||||
set_camera_view(eye=[1.3, 0.7, 2.7], target=[0.0, 0, 1.5], camera_prim_path="/OmniverseKit_Persp")
|
||||
# Modify config
|
||||
arena_file_path = self.task_cfg.get("arena_file", None)
|
||||
arena_file_path = self.task_cfg.get("arena_file", None) or self._arena_file_path
|
||||
self._arena_file_path = arena_file_path
|
||||
with open(arena_file_path, "r", encoding="utf-8") as arena_file:
|
||||
arena = yaml.load(arena_file, Loader=Loader)
|
||||
|
||||
@@ -113,9 +115,13 @@ class SimBoxDualWorkFlow(NimbusWorkFlow):
|
||||
physx_interface = acquire_physx_interface()
|
||||
physx_interface.overwrite_gpu_setting(1)
|
||||
|
||||
self.task = get_task_cls(self.task_cfg["task"])(self.task_cfg)
|
||||
if not hasattr(self, "task") or self.task is None:
|
||||
self.task = get_task_cls(self.task_cfg["task"])(self.task_cfg)
|
||||
else:
|
||||
self.task.cfg = self.task_cfg
|
||||
self.stage = self.world.stage
|
||||
self.stage.SetDefaultPrim(self.stage.GetPrimAtPath("/World"))
|
||||
self.world._current_tasks.clear()
|
||||
self.world.add_task(self.task)
|
||||
|
||||
# # Add hidden ground plane for physics simulation
|
||||
|
||||
Reference in New Issue
Block a user