Isaac Sim version
5.1.0
Operating System
Windows 10
GPU Information
- Model: NVIDIA RTX 2000 Ada Generation Laptop GPU (8GB)
- Driver Version: 581.60
- CUDA Version: 13.0
Topic Description
I am running a standalone Isaac Sim script (Replicator SDG pipeline) to generate a synthetic dataset of stacked RAM modules (CAD converted to USD using Hoops Core Converter). The script spawns ~20 stacks, each containing 2 RAM USD references (≈40 RAM prims total), then randomizes:
-
Camera pose (stereo camera)
-
Visibility of a random subset of RAM modules per frame (to simulate different filling rate of a ram tray)
-
Lighting via Replicator custom event
I then capture per-frame outputs using Replicator annotators:
-
pointcloud -
distance_to_image_plane -
DepthSensorPointCloudColor
Isaac Sim crashes (almost everytime) during rep.orchestrator.step() after a few frames with a native access violation / heap corruption. The number of frames after which crashes can change everytime.
This is my code:
from omni.isaac.kit import SimulationApp
# -------------------------
# Config
# -------------------------
config = {
"launch_config": {
"headless": False
},
"cad_folder": "path_to_my_CAD_folder",
"num_frames": 30,
"resolution": (1024,1024),
"output_dir": "./out_ram_sdg"
}
launch_config = config.get("launch_config", {})
simulation_app = SimulationApp(launch_config=launch_config)
import os
import random
import numpy as np
import asyncio
from pathlib import Path
import carb
import omni.usd
import omni.replicator.core as rep
from pxr import Gf, Sdf, Usd, UsdGeom, UsdShade
from isaacsim.core.utils.stage import add_reference_to_stage
from isaacsim.core.utils.semantics import add_labels
from isaacsim.core.utils.extensions import enable_extension
enable_extension("isaacsim.test.utils")
enable_extension("omni.kit.converter.hoops_core")
from isaacsim.storage.native import get_assets_root_path
from isaacsim.test.utils import save_depth_image, save_rgb_image
# Isaac nucleus assets root path
assets_root_path = get_assets_root_path()
# -------------------------
# Utils
# -------------------------
def set_transform(prim, location=None, orientation=None, scale=None):
if not prim or not prim.IsValid():
raise RuntimeError("Invalid prim passed to set_transform()")
xform = UsdGeom.Xformable(prim)
xform.ClearXformOpOrder()
if location is not None:
xform.AddTranslateOp().Set(location)
if orientation is not None:
xform.AddOrientOp().Set(orientation)
if scale is not None:
xform.AddScaleOp().Set(scale)
# -------------------------
# CAD → USD + Wood Material
# -------------------------
def load_ram(cad_path, usd_out, prim_path):
async def convert(cad_path, usd_out):
"""Convert CAD file to USD using Hoops Core Converter Extension"""
from omni.kit.converter.hoops_core import get_instance
hoops_converter = get_instance()
convert_options = {}
convert_options["instancing"] = "false"
convert_options["instancingStyle"] = "0"
convert_options["convertMetadata"] = "true"
convert_options["convertCurves"] = "true"
convert_options["globalXforms"] = "false"
convert_options["materialType"] = "2"
convert_options["dMetersPerUnit"] = "0.001"
await hoops_converter.create_converter_task(cad_path, usd_out, convert_options)
asyncio.get_event_loop().run_until_complete(convert(cad_path, usd_out))
def spawn_two_ram_stack(stack_path, ram_usd_paths, local_offsets, local_orientations=None):
"""
Creates a stack prim containing 2 RAM references.
ram_usd_paths: list of 2 usd paths
local_offsets: list of 2 (x,y,z) offsets (stack-local)
local_orientations: list of 2 quats or None
Returns stack prim path.
"""
stage = omni.usd.get_context().get_stage()
stage.DefinePrim(stack_path, "Xform")
for j in range(2):
prim_path = f"{stack_path}/ram_{j}"
prim = add_reference_to_stage(ram_usd_paths[j], prim_path)
if local_orientations is None:
set_transform(prim, location=local_offsets[j])
else:
set_transform(prim, location=local_offsets[j], orientation=local_orientations[j])
add_labels(prim, labels=["ram"], instance_name="class")
return stack_path
def spawn_stack_grid(parent_path, ram_usd_paths,
stacks_x=4, stacks_y=2, stacks_z=1,
stack_spacing=(0.01, 0.05, 0),
stack_origin=(0, 0, 0),
local_offsets=None,
local_orientations=None):
"""
Creates many stacks of 3 RAMs.
Returns list of ALL ram prim paths (not just stacks).
"""
stage = omni.usd.get_context().get_stage()
stage.DefinePrim(parent_path, "Xform")
sx, sy, sz = stack_spacing
ox, oy, oz = stack_origin
all_ram_paths = []
idx = 0
for k in range(stacks_z):
for iy in range(stacks_y):
for ix in range(stacks_x):
idx += 1
stack_path = f"{parent_path}/stack_{idx:03d}"
stage.DefinePrim(stack_path, "Xform")
# place the whole stack
stack_pos = (ox + ix * sx, oy + iy * sy, oz + k * sz)
stack_prim = stage.GetPrimAtPath(stack_path)
set_transform(stack_prim, location=stack_pos)
# spawn the 2 RAMs inside this stack
spawn_two_ram_stack(
stack_path=stack_path,
ram_usd_paths=ram_usd_paths,
local_offsets=local_offsets,
local_orientations=local_orientations
)
# collect paths to each ram prim
for j in range(2):
all_ram_paths.append(f"{stack_path}/ram_{j}")
return all_ram_paths
# -------------------------
# Main SDG Pipeline
# -------------------------
# Create a new stage
omni.usd.get_context().new_stage()
stage = omni.usd.get_context().get_stage()
carb.settings.get_settings().set("/rtx/post/aa/op", "off")
carb.settings.get_settings().set("rtx/post/dlss/execMode", 2)
# Set the renderer to Path Traced
rep.settings.set_render_pathtraced(samples_per_pixel=16)
# Add world prim to the empty stage
distant_light = stage.DefinePrim("/World/Lights/DistantLight", "DistantLight")
distant_light.CreateAttribute("inputs:intensity", Sdf.ValueTypeNames.Float).Set(300.0)
# Create a randomizer for lights, manually triggered at custom events
with rep.trigger.on_custom_event(event_name="randomize_lights"):
lights = rep.create.light(
light_type="Sphere",
parent="/World/Lights",
color=rep.distribution.uniform((0, 0, 0), (1, 1, 1)),
temperature=rep.distribution.normal(6500, 500),
intensity=rep.distribution.normal(35000, 5000),
position=rep.distribution.uniform(-10, 10),
rotation=rep.distribution.uniform(0, 180),
scale=rep.distribution.uniform(0.1, 1),
count=3,
)
# Create a plastic grund plane
plane = rep.functional.create.plane(position=(0, 0, 0), scale=(10, 10, 1), semantics={"class": "plane"}, parent="/World", name="Plane")
material_path="https://omniverse-content-production.s3.us-west-2.amazonaws.com/Materials/Base/Plastics/Plastic.mdl"
material_prim = stage.GetPrimAtPath(material_path)
try:
success, result = omni.kit.commands.execute(
"CreateMdlMaterialPrimCommand",
mtl_url=material_path,
mtl_name="Plastic",
mtl_path="/World/Plane/Looks/Plastic"
)
stage =omni.usd.get_context().get_stage()
plastic_material = UsdShade.Material(stage.GetPrimAtPath("/World/Plane/Looks/Plastic"))
except Exception as e:
print(f"Error Occurred, {e}")
# Bind the specific material object
UsdShade.MaterialBindingAPI.Apply(plane).Bind(plastic_material, UsdShade.Tokens.strongerThanDescendants)
simulation_app.update()
# -------------------------
# Load RAM from CAD
# -------------------------
ram_folder = Path(config["cad_folder"])
# CAD extensions to process
cad_exts = {".step", ".stp", ".stl", ".igs"}
ram_usd_paths = [] # list of generated USD paths for the RAMs, to be used for instancing later
for cad_path in ram_folder.iterdir():
if not cad_path.is_file():
continue
if cad_path.suffix.lower() not in cad_exts:
continue
usd_path = cad_path.with_suffix(".usd")
prim_name = cad_path.stem.replace(" ", "_").replace("-", "_")
prim_path = f"/World/RAM_{prim_name}"
print(f"Converting: {cad_path.name} -> {usd_path.name}")
ram_usd_paths.append(str(usd_path))
load_ram(
cad_path=str(cad_path),
usd_out=str(usd_path),
prim_path=prim_path)
local_offsets = [(0.00, 0.00, 0.00), (-0.007, 0.0005, 0.015)]
# extra rotations to make the RAMs upright (depends on how they were modeled)
qx90 = Gf.Quatf(Gf.Rotation(Gf.Vec3d(1, 0, 0), 90).GetQuat())
qy90 = Gf.Quatf(Gf.Rotation(Gf.Vec3d(0, 1, 0), 90).GetQuat())
local_orientations = [qx90, qx90 * qy90]
# Static object → no physics
all_ram_paths = spawn_stack_grid(
parent_path="/World/RAM_STACKS",
ram_usd_paths=ram_usd_paths,
stacks_x=10, stacks_y=2, stacks_z=1, # 40 stacks
stack_spacing=(0.015, 0.15, 0),
stack_origin=(0,0,0),
local_offsets=local_offsets,
local_orientations=local_orientations
)
# Group asset for easy referencing
ram_group = rep.create.group(all_ram_paths, semantics=[('class', 'ram_group')])
# -------------------------
# Stereo-Camera
# -------------------------
camera_positions = [(-1.3, 0, 0.6), (-0.8, -0.2, 0.65), (0, 0, 1.5), (0.15, -1.0, 0.7)]
# Adjust camera parameters to ensure the whole stack is visible, and good depth quality on the RAMs (not too far, not too close)
camera = rep.create.stereo_camera(parent="/World",
name="StereoCam",
stereo_baseline=0.1,
clipping_range=(0.6, 10),
focal_length=60,
focus_distance=1
)
render_product = rep.create.render_product(camera, config["resolution"])
# -------------------------
# Annotators
# -------------------------
pc_anno = rep.annotators.get("pointcloud")
pc_anno.attach(render_product[0])
dist_anno = rep.annotators.get("distance_to_image_plane")
dist_anno.attach(render_product[0])
depth_anno = rep.AnnotatorRegistry.get_annotator("DepthSensorPointCloudColor")
depth_anno.attach(render_product[0])
# -------------------------
# Capture Loop
# -------------------------
N_FRAMES = config["num_frames"]
output_dir = config["output_dir"]
os.makedirs(output_dir, exist_ok=True)
rep.orchestrator.preview()
# Disable capture on play (data generation will be triggered manually)
rep.orchestrator.set_capture_on_play(False)
points_L, rgb_L = [], []
with rep.trigger.on_frame(max_execs=N_FRAMES):
# Make the entire stack visible at the start of each frame
ram_prims = rep.get.prim_at_path(all_ram_paths)
with ram_prims:
rep.modify.visibility(True)
for i in range(N_FRAMES):
simulation_app.update()
# Randomize camera poses every frame, looking at the RAM stack
pos = rep.distribution.sequence(camera_positions)
with camera:
rep.modify.pose(
position=pos,
look_at=ram_group
)
# Randomly select how many ram units hide within the stack to increase variety in the dataset
n_hidden = rep.distribution.choice(choices=list(range(0, len(all_ram_paths)//2)))
# Randomly select which many ram units hide within the stack
hidden = rep.distribution.choice(all_ram_paths,
num_samples=n_hidden,
with_replacements=False)
with hidden:
# Hide the selected ram units
rep.modify.visibility(False)
for i in range(N_FRAMES):
stage = omni.usd.get_context().get_stage()
prim = stage.GetPrimAtPath("/World/StereoCam")
matrix= omni.usd.get_world_transform_matrix(prim)
translate= matrix.ExtractTranslation()
print("Prim world translation: ", translate)
if i % 3 == 0:
print(f"\t Randomizing lights")
rep.utils.send_og_event(event_name="randomize_lights")
# Trigger any on_frame registered randomizers
rep.orchestrator.step(rt_subframes=16)
save_depth_image(dist_anno.get_data(), output_dir, f"dist_{i}.png", normalize=True)
save_rgb_image(depth_anno.get_data(), output_dir, f"depth_color_{i}.png")
pc_data = pc_anno.get_data()
pc = pc_data["data"]
# Robust sanitize
if pc is None:
print("[WARN] None pointcloud")
continue
pc = np.asarray(pc)
# Case 1: already Nx3 → OK
if pc.ndim == 2 and pc.shape[1] == 3 and pc.shape[0] > 0:
points_L.append(pc)
# Case 2: flattened → reshape
elif pc.ndim == 1 and pc.size % 3 == 0 and pc.size > 0:
pc = pc.reshape(-1, 3)
points_L.append(pc)
else:
print(f"[WARN] Skipped malformed pc: shape={pc.shape}")
continue
# RGB always matches pc length
rgb = pc_data["info"]["pointRgb"]
rgb = np.asarray(rgb)
if rgb.ndim == 1 and rgb.size % 4 == 0:
rgb = rgb.reshape(-1,4)[:, :3]
rgb_L.append(rgb)
print(f"[SDG] Frame {i}")
# Merge all views → single pointcloud
pc = np.concatenate(points_L) if len(points_L) else np.empty((0,3))
rgb = np.concatenate(rgb_L)
import open3d as o3d
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(pc)
#pcd.colors = o3d.utility.Vector3dVector(rgb)
o3d.visualization.draw_geometries([pcd])
o3d.io.write_point_cloud(os.path.join(output_dir,"ram_scene.ply"), pcd)
pc_anno.detach()
dist_anno.detach()
depth_anno.detach()
for rp in render_product:
rp.destroy()
rep.orchestrator.wait_until_complete()
print("\n[SDG] Dataset complete")
for _ in range(50):
simulation_app.update()
simulation_app.close()
Error message
Windows fatal exception: access violation
Thread 0x00002614 (most recent call first):
File “C:\isaac-sim\kit\python\Lib\concurrent\futures\thread.py”, line 81 in _worker
File “C:\isaac-sim\kit\python\Lib\threading.py”, line 982 in run
File “C:\isaac-sim\kit\python\Lib\threading.py”, line 1045 in _bootstrap_inner
File “C:\isaac-sim\kit\python\Lib\threading.py”, line 1002 in _bootstrap
The same version of the script also produced:
Windows fatal exception: code 0xc0000374
I am upoloading also the whole crash message
crash.txt (77.0 KB)