Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[QUESTION] Granular collision SDF example has changed #409

Open
sxn22012023 opened this issue Dec 27, 2024 · 4 comments
Open

[QUESTION] Granular collision SDF example has changed #409

sxn22012023 opened this issue Dec 27, 2024 · 4 comments
Assignees
Labels
question The issue author requires information

Comments

@sxn22012023
Copy link

Hi! I am re-running granular collision sdf example. But when I imported the calculated usd file into Blender, there is no collision between rock and particles? Can you tell me how I should visualize the calculated result?

These are the results I imported into Blender.
Image

Image

This is the result from the official documentation.

Image
@sxn22012023 sxn22012023 added the question The issue author requires information label Dec 27, 2024
@sxn22012023 sxn22012023 changed the title [QUESTION] <title> Visualize the calculated result [QUESTION] Visualize the calculated result Dec 27, 2024
@shi-eric
Copy link
Contributor

Thanks for reporting this issue. It seems that when 02d8d33 adjusted the scale and orientation of the example assets, the granular collision SDF was not fully updated. This led to the rock collision geometry being a factor of 100x smaller than what's shown in the example gallery image. Try out this updated example:

# Copyright (c) 2022 NVIDIA CORPORATION.  All rights reserved.
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto.  Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.

###########################################################################
# Example Sim Granular Collision SDF
#
# Shows how to set up a particle-based granular material model using the
# wp.sim.ModelBuilder(). This version shows how to create collision geometry
# objects from SDFs.
#
# Note: requires a CUDA-capable device
###########################################################################

import os

import numpy as np

import warp as wp
import warp.examples
import warp.sim
import warp.sim.render


class Example:
    def __init__(self, stage_path="example_granular_collision_sdf.usd"):
        fps = 60
        self.frame_dt = 1.0 / fps

        self.sim_substeps = 64
        self.sim_dt = self.frame_dt / self.sim_substeps
        self.sim_time = 0.0

        self.radius = 0.1

        builder = wp.sim.ModelBuilder()
        builder.default_particle_radius = self.radius

        builder.add_particle_grid(
            dim_x=16,
            dim_y=32,
            dim_z=16,
            cell_x=self.radius * 2.0,
            cell_y=self.radius * 2.0,
            cell_z=self.radius * 2.0,
            pos=wp.vec3(0.0, 20.0, 0.0),
            rot=wp.quat_identity(),
            vel=wp.vec3(2.0, 0.0, 0.0),
            mass=0.1,
            jitter=self.radius * 0.1,
        )
        with open(os.path.join(warp.examples.get_asset_directory(), "rocks.nvdb"), "rb") as rock_file:
            rock_vdb = wp.Volume.load_from_nvdb(rock_file.read())

        rock_sdf = wp.sim.SDF(rock_vdb)

        builder.add_shape_sdf(
            ke=1.0e4,
            kd=1000.0,
            kf=1000.0,
            mu=0.5,
            sdf=rock_sdf,
            body=-1,
            pos=wp.vec3(0.0, 0.0, 0.0),
            rot=wp.quat(0.0, 0.0, 0.0, 1.0),
            scale=wp.vec3(1.0, 1.0, 1.0),
        )

        mins = np.array([-3.0, -3.0, -3.0])
        voxel_size = 0.2
        maxs = np.array([3.0, 3.0, 3.0])
        nums = np.ceil((maxs - mins) / (voxel_size)).astype(dtype=int)
        center = np.array([0.0, 0.0, 0.0])
        rad = 2.5
        sphere_sdf_np = np.zeros(tuple(nums))
        for x in range(nums[0]):
            for y in range(nums[1]):
                for z in range(nums[2]):
                    pos = mins + voxel_size * np.array([x, y, z])
                    dis = np.linalg.norm(pos - center)
                    sphere_sdf_np[x, y, z] = dis - rad

        sphere_vdb = wp.Volume.load_from_numpy(sphere_sdf_np, mins, voxel_size, rad + 3.0 * voxel_size)
        sphere_sdf = wp.sim.SDF(sphere_vdb)

        self.sphere_pos = wp.vec3(3.0, 15.0, 0.0)
        self.sphere_scale = 1.0
        self.sphere_radius = rad
        builder.add_shape_sdf(
            ke=1.0e4,
            kd=1000.0,
            kf=1000.0,
            mu=0.5,
            sdf=sphere_sdf,
            body=-1,
            pos=self.sphere_pos,
            scale=wp.vec3(self.sphere_scale, self.sphere_scale, self.sphere_scale),
        )

        self.model = builder.finalize()
        self.model.particle_kf = 25.0

        self.model.soft_contact_kd = 100.0
        self.model.soft_contact_kf *= 2.0

        self.state_0 = self.model.state()
        self.state_1 = self.model.state()

        self.integrator = wp.sim.SemiImplicitIntegrator()

        if stage_path:
            self.renderer = wp.sim.render.SimRenderer(self.model, stage_path, scaling=20.0)
        else:
            self.renderer = None

        self.use_cuda_graph = wp.get_device().is_cuda
        if self.use_cuda_graph:
            with wp.ScopedCapture() as capture:
                self.simulate()
            self.graph = capture.graph

    def simulate(self):
        for _ in range(self.sim_substeps):
            self.state_0.clear_forces()
            wp.sim.collide(self.model, self.state_0)
            self.integrator.simulate(self.model, self.state_0, self.state_1, self.sim_dt)

            # swap states
            (self.state_0, self.state_1) = (self.state_1, self.state_0)

    def step(self):
        with wp.ScopedTimer("step"):
            self.model.particle_grid.build(self.state_0.particle_q, self.radius * 2.0)
            if self.use_cuda_graph:
                wp.capture_launch(self.graph)
            else:
                self.simulate()

        self.sim_time += self.frame_dt

    def render(self):
        if self.renderer is None:
            return

        with wp.ScopedTimer("render"):
            self.renderer.begin_frame(self.sim_time)

            self.renderer.render_ref(
                name="collision",
                path=os.path.join(warp.examples.get_asset_directory(), "rocks.usd"),
                pos=wp.vec3(0.0, 0.0, 0.0),
                rot=wp.quat(0.0, 0.0, 0.0, 1.0),
                scale=wp.vec3(1.0, 1.0, 1.0),
                color=(0.35, 0.55, 0.9),
            )

            self.renderer.render_sphere(
                name="sphere",
                pos=self.sphere_pos,
                radius=self.sphere_scale * self.sphere_radius,
                rot=wp.quat(0.0, 0.0, 0.0, 1.0),
            )

            self.renderer.render(self.state_0)
            self.renderer.end_frame()


if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.")
    parser.add_argument(
        "--stage_path",
        type=lambda x: None if x == "None" else str(x),
        default="example_granular_collision_sdf.usd",
        help="Path to the output USD file.",
    )
    parser.add_argument("--num_frames", type=int, default=400, help="Total number of frames.")

    args = parser.parse_known_args()[0]

    with wp.ScopedDevice(args.device):
        example = Example(stage_path=args.stage_path)

        for _ in range(args.num_frames):
            example.step()
            example.render()

        if example.renderer:
            example.renderer.save()

@shi-eric shi-eric self-assigned this Dec 30, 2024
@shi-eric shi-eric changed the title [QUESTION] Visualize the calculated result [QUESTION] Granular collision SDF example has changed Dec 30, 2024
@sxn22012023
Copy link
Author

@shi-eric Thank you so much for your patient reply! The new code displays the normal size of the rock. However, when I imported the result into Blender and clicked the play button, nothing happened. The entire result is static, and the granules can’t fall onto the rock. Is there something I did wrong?

Image

@shi-eric
Copy link
Contributor

shi-eric commented Jan 3, 2025

I don't think you did anything wrong; it could be an issue with Blender's USD import. Here's a screenshot from opening the file in usdview:

Image

@christophercrouzet Do you have any insight about the Blender issue?

@christophercrouzet
Copy link
Member

Hi @sxn22012023, I managed to visualize the expected result in USD View, Omniverse, and Houdini, but I can repro your issue in Blender 4.3.2.

From what I can tell, everything is set correctly during the import, and the frame range is correct, so this should work. My first guess would also be some possible shortcomings with Blender's USD importer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question The issue author requires information
Projects
None yet
Development

No branches or pull requests

3 participants