Genesis
Genesis copied to clipboard
[Bug]: No segmentation maps for MPM objects.
Bug Description
I trying to simulate some data and save the rgb and segmentation mask videos, however i just noticed that all MPM materials don't get visualized in the segmentations masks produced, see attached videos. Wondering why, especially as when i extract out the normal I can see the MPM object.
The demo code below uses entity level segmentation, and when i tried geom I get an assertion error :
Traceback (most recent call last):
File "/simulate/diff_push.py", line 109, in <module>
scene.build()
File "/scram/miniconda3/envs/cosmos-predict1/lib/python3.10/site-packages/genesis/utils/misc.py", line 91, in wrapper
return method(self, *args, **kwargs)
File "/scram/miniconda3/envs/cosmos-predict1/lib/python3.10/site-packages/genesis/engine/scene.py", line 613, in build
self._visualizer.build()
File "/scram/miniconda3/envs/cosmos-predict1/lib/python3.10/site-packages/genesis/vis/visualizer.py", line 140, in build
self._context.build(self._scene)
File "/scram/miniconda3/envs/cosmos-predict1/lib/python3.10/site-packages/genesis/vis/rasterizer_context.py", line 102, in build
self.generate_seg_vars()
File "/scram/miniconda3/envs/cosmos-predict1/lib/python3.10/site-packages/genesis/vis/rasterizer_context.py", line 855, in generate_seg_vars
assert False, "geom level segmentation not supported yet"
AssertionError: geom level segmentation not supported yet
[Genesis] [17:42:50] [ERROR] AssertionError: geom level segmentation not supported yet
[Genesis] [17:42:50] [INFO] 💤 Exiting Genesis and caching compiled kernels...
Steps to Reproduce
import argparse
import pathlib
import numpy as np
import genesis as gs
import cv2
import numpy as np
# ─────────────────── CLI ───────────────────
cli = argparse.ArgumentParser()
cli.add_argument("--velocity", nargs=3, type=float, default=[2.0, 0.0, 0.0],
help="Initial ball velocity (m/s) in X Y Z")
cli.add_argument("--out_dir", default="frames")
args = cli.parse_args()
# ───────── scene constants ───────
TABLE_TOP_Z = 0.0 # height of tabletop (top surface)
BALL_R = 0.05
table_friction = 0.15 # plane + box share the same coeff
PHYS_HZ, SUBSTEPS = 240, 12
VID_FPS, FRAMES = 24, 121
STEP_RATIO = PHYS_HZ // VID_FPS # 10
TOTAL_STEPS = int(((FRAMES * STEP_RATIO)/5) * 2) # 1210
print(f"TOTAL_STEPS: {TOTAL_STEPS}")
def initialization(args, substeps=SUBSTEPS, dt=1/PHYS_HZ, mpm_lower_bound=(-2.0, -2.0, -2.0), mpm_upper_bound=(2.0, 2.0, 2.0), friction=0.15, show_viewer=False):
########################## init ##########################
gs.init(backend=gs.gpu)
scene = gs.Scene(
sim_options=gs.options.SimOptions(
dt=dt,
substeps=substeps,
gravity=(0, 0, -9.81),
),
mpm_options=gs.options.MPMOptions(
lower_bound=mpm_lower_bound,
upper_bound=mpm_upper_bound,
),
show_viewer=show_viewer,
vis_options = gs.options.VisOptions(
show_world_frame = False,
segmentation_level='entity',
world_frame_size = 1.0,
show_link_frame = False,
show_cameras = False,
plane_reflection = True,
),
show_FPS=False,
)
# ─────── ground ────────
ground = scene.add_entity(gs.morphs.Plane(collision=True))
ground.set_friction(friction)
return scene
# ───────── Genesis init ─────────
scene = initialization(args, mpm_lower_bound=(-1.0, -1.0, -1.0), mpm_upper_bound=(1.0, 1.0, 1.0))
# ─────── obstacle ──────
obst_morph = gs.morphs.Sphere(pos=(0.30, 0.0, TABLE_TOP_Z + BALL_R + 1e-3), radius=BALL_R)
obst_surf = gs.surfaces.Default(color=(0.4, 0.55, 0.9))
obst_mat = gs.materials.MPM.ElastoPlastic(
E=1e6, # Young's modulus
nu=0.2, # Poisson's ratio
rho=1000.0, # density (kg/m^3)
)
object_1 = scene.add_entity(
morph=obst_morph,
material=obst_mat, #gs.materials.Rigid(rho=250, friction=0.3),
surface=obst_surf,
)
# ───────────── ball ─────────────
ball_z = TABLE_TOP_Z + BALL_R + 1e-3 # 1 mm clearance
ball = scene.add_entity(
morph=gs.morphs.Sphere(pos=(-0.45, 0, ball_z), radius=BALL_R),
material=gs.materials.Rigid(rho=250, coup_restitution=0, friction=0.3),
surface=gs.surfaces.Default(color=(1, 0, 0)),
)
# ───────────── camera ────────────
cam = scene.add_camera(
pos=(0, -2.0, TABLE_TOP_Z + 0.45),
lookat=(0, 0, TABLE_TOP_Z + 0.02),
fov=35, res=(640, 480), GUI=False,
)
# ─────────── simulate ────────────
scene.build()
ball.set_dofs_velocity(np.array([*args.velocity, 0, 0, 0], dtype=np.float32))
out_dir = pathlib.Path(args.out_dir); out_dir.mkdir(exist_ok=True)
video_file = out_dir / "resource.mp4"
cam.start_recording()
seg_frames = []
for step in range(TOTAL_STEPS):
scene.step()
if step % STEP_RATIO == 0:
rgb_img, depth_img, seg_img, normal_img = cam.render(
rgb=True,
depth=True,
segmentation=True,
colorize_seg=False, # Keep raw object indices
normal=True
)
seg_frames.append(seg_img)
cam.stop_recording(save_to_filename=str(video_file), fps=VID_FPS)
height, width = seg_frames[0].shape[:2]
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(str(out_dir / "resource_seg.mp4"), fourcc, VID_FPS, (width, height), False)
for frame in seg_frames:
if frame.dtype != np.uint8:
if frame.max() <= 1.0: # Normalized float
frame = (frame * 255).astype(np.uint8)
else: # Handle depth maps or other ranges
frame = ((frame - frame.min()) / (frame.max() - frame.min()) * 255).astype(np.uint8)
out.write(frame)
out.release()
print(f"✓ saved {FRAMES}-frame clip → {video_file}")
Make sure to attached any needed assets (here attachement.xml)!
Expected Behavior
I expect the stationary sphere, thats hit to be visible in the segmentation mask as it is in the rgb image.
Screenshots/Videos
https://github.com/user-attachments/assets/b5f17217-918c-4b51-8c74-430ffd019a6d https://github.com/user-attachments/assets/3d3717b1-1e55-4ebb-b696-e96ca90611e5
Relevant log output
Environment
- OS: [Rocky Linux 8.9]
- GPU/CPU [A100 80GB]
- GPU-driver version (565.57.01)
- CUDA / CUDA-toolkit version (12.4)
Release version or Commit ID
0.2.1 commit: https://github.com/Genesis-Embodied-AI/Genesis/commit/ea31abc182b2a7aad2696c15cd24bab141ddb7d7
Additional Context
No response