Skip to content

[Question] How do I rescale a primitive upon reset along with it's collision mesh? #4500

@aaronrockmenezes

Description

@aaronrockmenezes

Question

Hi, I've been trying to non-uniformly rescale my primitives at runtime using the function below:

def randomize_shape_scale(self,
                          prim_path_expr: str | list,
                          is_random: bool = True):
    world = World.instance()
    if world.is_playing():
        world.pause()

    stage = get_current_stage()

    # Resolve paths
    if isinstance(prim_path_expr, str):
        prim_paths = sim_utils.find_matching_prim_paths(prim_path_expr)
    elif isinstance(prim_path_expr, list):
        prim_paths = []
        for expr in prim_path_expr:
            prim_paths.extend(sim_utils.find_matching_prim_paths(expr))

    print(
        f"\n[Randomizing Xform Scale Only] Processing {len(prim_paths)} objects..."
    )
    obj_configs = list(self.cfg.vpt_objects.rigid_objects.values())
    bbox_cache = UsdGeom.BBoxCache(Usd.TimeCode.Default(),
                                   [UsdGeom.Tokens.default_])

    with Sdf.ChangeBlock():
        for prim_path in prim_paths:
            # Only process obs_* prims
            if "/obs_" not in prim_path:
                continue

            root_prim = stage.GetPrimAtPath(prim_path)
            if not root_prim.IsValid():
                continue

            # Parse indices
            try:
                path_str = root_prim.GetPath().pathString
                path_parts = path_str.split("/")
                env_part = next(p for p in path_parts
                                if p.startswith("env_"))
                env_idx = int(env_part.split("_")[-1])
                obs_part = next(p for p in path_parts
                                if p.startswith("obs_"))
                obj_idx = int(obs_part.split("_")[-1])
            except:
                continue

            if obj_idx >= len(obj_configs):
                continue

            obj_cfg = obj_configs[obj_idx]
            spawn_cfg = obj_cfg.spawn

            # Get/Create Xform ops
            xform = UsdGeom.Xformable(root_prim)
            scale_op = None
            translate_op = None

            for op in xform.GetOrderedXformOps():
                if op.GetOpType() == UsdGeom.XformOp.TypeScale:
                    scale_op = op
                elif op.GetOpType() == UsdGeom.XformOp.TypeTranslate:
                    translate_op = op

            if scale_op is None:
                scale_op = xform.AddScaleOp(
                    UsdGeom.XformOp.PrecisionDouble)
            if translate_op is None:
                translate_op = xform.AddTranslateOp(
                    UsdGeom.XformOp.PrecisionDouble)

            if is_random:
                base_dim = self.vpt_base_dims[obj_idx].cpu().numpy()
                final_scale_vec = Gf.Vec3d(1, 1, 1)
                final_z_pos = 0.0
                z_offset_multiplier = 0.0
                shape_name = -1

                # Determine scale based on object type
                if isinstance(spawn_cfg, sim_utils.UsdFileCfg):
                    filename = spawn_cfg.usd_path.split("/")[-1].split(
                        ".")[0]
                    if filename.endswith('X'):
                        shape_name = 0
                        s_xz = random.uniform(0.5, 2.5)
                        s_y = random.uniform(0.5, 2.5)
                        final_scale_vec = Gf.Vec3d(s_xz, s_y, s_xz)
                    elif filename.endswith('L'):
                        shape_name = 1
                        s_factor = random.uniform(0.5, 2.5)
                        final_scale_vec = Gf.Vec3d(s_factor, s_factor,
                                                   s_factor)
                    else:
                        s_xy = random.uniform(0.5, 2.5)
                        s_z = random.uniform(0.5, 2.5)
                        final_scale_vec = Gf.Vec3d(s_xy, s_xy, s_z)

                elif isinstance(spawn_cfg, sim_utils.MeshCuboidCfg):
                    shape_name = 2
                    z_offset_multiplier = 0.5
                    s_x = random.uniform(0.5, 2.5)
                    s_y = random.uniform(0.5, 2.5)
                    s_z = random.uniform(0.5, 2.5)
                    final_scale_vec = Gf.Vec3d(s_x, s_y, s_z)
                    final_z_pos = base_dim[2] * s_z * z_offset_multiplier

                elif isinstance(
                        spawn_cfg,
                    (sim_utils.MeshCylinderCfg, sim_utils.MeshConeCfg)):
                    shape_name = 3 if isinstance(
                        spawn_cfg, sim_utils.MeshCylinderCfg) else 4
                    z_offset_multiplier = 0.5
                    s_r = random.uniform(0.75, 1.0)
                    s_h = random.uniform(0.75, 2.5)
                    final_scale_vec = Gf.Vec3d(s_r, s_r, s_h)
                    final_z_pos = base_dim[2] * s_h * z_offset_multiplier

                # Apply ONLY Xform transformations
                scale_op.Set(final_scale_vec)
                current_trans = translate_op.Get()
                translate_op.Set(
                    Gf.Vec3d(current_trans[0], current_trans[1],
                             final_z_pos))

                # Update internal state
                self.obj_default_state[env_idx, obj_idx,
                                           2] = final_z_pos
                self.z_offset_ratios[env_idx,
                                         obj_idx] = z_offset_multiplier
                self.shapes[env_idx, obj_idx] = shape_name

    world.play()
    self.sim.step(render=False)

I'm able to scale the visual material just fine, but my agent, a MeshCuboid that I control with the keyboard, just passes through the objects. I also see that some objects just float while others sink partially into the ground (see attached images).

All these obstacle objects are part of a RigidObjectCollection and I want to rescale them upon every reset.

Can someone help me out?

Build Info

  • Isaac Lab Version: 0.45.7
  • Isaac Sim Version: 5.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions