Unverified Commit f7e23806 authored by David Hoeller's avatar David Hoeller Committed by GitHub

Fixes the rigid body tests (#1345)

# Description

Fixes the commented out tests in the rigid body test

## Type of change

- Bug fix (non-breaking change which fixes an issue)

## Checklist

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./isaaclab.sh --format`
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [ ] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there
parent 1491572b
...@@ -426,175 +426,177 @@ class TestRigidObject(unittest.TestCase): ...@@ -426,175 +426,177 @@ class TestRigidObject(unittest.TestCase):
cube_object.data.root_lin_vel_w, initial_velocity[:, :3], rtol=1e-5, atol=tolerance cube_object.data.root_lin_vel_w, initial_velocity[:, :3], rtol=1e-5, atol=tolerance
) )
# def test_rigid_body_with_static_friction(self): def test_rigid_body_with_static_friction(self):
# """Test that static friction applied to rigid object works as expected. """Test that static friction applied to rigid object works as expected.
# This test works by applying a force to the object and checking if the object moves or not based on the This test works by applying a force to the object and checking if the object moves or not based on the
# mu (coefficient of static friction) value set for the object. We set the static friction to be non-zero and mu (coefficient of static friction) value set for the object. We set the static friction to be non-zero and
# apply a force to the object. When the force applied is below mu, the object should not move. When the force apply a force to the object. When the force applied is below mu, the object should not move. When the force
# applied is above mu, the object should move. applied is above mu, the object should move.
# """ """
# for num_cubes in (1, 2): for num_cubes in (1, 2):
# for device in ("cuda:0", "cpu"): for device in ("cuda", "cpu"):
# with self.subTest(num_cubes=num_cubes, device=device): with self.subTest(num_cubes=num_cubes, device=device):
# with build_simulation_context(device=device, add_ground_plane=True, auto_add_lighting=True) as sim: with build_simulation_context(
# cube_object, _ = generate_cubes_scene(num_cubes=num_cubes, height=0.03125, device=device) device=device, dt=0.01, add_ground_plane=False, auto_add_lighting=True
) as sim:
# # Create ground plane with no friction cube_object, _ = generate_cubes_scene(num_cubes=num_cubes, height=0.03125, device=device)
# cfg = sim_utils.GroundPlaneCfg(
# physics_material=materials.RigidBodyMaterialCfg( # Create ground plane
# static_friction=0.0, static_friction_coefficient = 0.5
# dynamic_friction=0.0, cfg = sim_utils.GroundPlaneCfg(
# ) physics_material=materials.RigidBodyMaterialCfg(
# ) static_friction=static_friction_coefficient,
# cfg.func("/World/GroundPlane", cfg) dynamic_friction=static_friction_coefficient, # This shouldn't be required but is due to a bug in PhysX
)
# # Play sim )
# sim.reset() cfg.func("/World/GroundPlane", cfg)
# # Set static friction to be non-zero # Play sim
# static_friction_coefficient = 0.5 sim.reset()
# static_friction = torch.Tensor([[static_friction_coefficient]] * num_cubes)
# dynamic_friction = torch.zeros(num_cubes, 1) # Set static friction to be non-zero
# restitution = torch.FloatTensor(num_cubes, 1).uniform_(0.0, 0.2) # Dynamic friction also needs to be zero due to a bug in PhysX
static_friction = torch.Tensor([[static_friction_coefficient]] * num_cubes)
# cube_object_materials = torch.cat([static_friction, dynamic_friction, restitution], dim=-1) dynamic_friction = torch.Tensor([[static_friction_coefficient]] * num_cubes)
restitution = torch.zeros(num_cubes, 1)
# indices = torch.tensor(range(num_cubes), dtype=torch.int)
cube_object_materials = torch.cat([static_friction, dynamic_friction, restitution], dim=-1)
# # Add friction to cube
# cube_object.root_physx_view.set_material_properties(cube_object_materials, indices) indices = torch.tensor(range(num_cubes), dtype=torch.int)
# # 2 cases: force applied is below and above mu # Add friction to cube
# # below mu: block should not move as the force applied is <= mu cube_object.root_physx_view.set_material_properties(cube_object_materials, indices)
# # above mu: block should move as the force applied is > mu
# for force in "below_mu", "above_mu": # let everything settle
# with self.subTest(force=force): for _ in range(100):
# external_wrench_b = torch.zeros((num_cubes, 1, 6), device=sim.device) sim.step()
cube_object.update(sim.cfg.dt)
# if force == "below_mu": cube_object.write_root_velocity_to_sim(torch.zeros((num_cubes, 6), device=sim.device))
# external_wrench_b[:, 0, 0] = static_friction_coefficient * 0.999 cube_mass = cube_object.root_physx_view.get_masses()
# else: gravity_magnitude = abs(sim.cfg.gravity[2])
# external_wrench_b[:, 0, 0] = static_friction_coefficient * 1.001 # 2 cases: force applied is below and above mu
# below mu: block should not move as the force applied is <= mu
# cube_object.set_external_force_and_torque( # above mu: block should move as the force applied is > mu
# external_wrench_b[..., :3], for force in "below_mu", "above_mu":
# external_wrench_b[..., 3:], with self.subTest(force=force):
# ) # set initial velocity to zero
cube_object.write_root_velocity_to_sim(torch.zeros((num_cubes, 6), device=sim.device))
# # Get root state
# initial_root_state = cube_object.data.root_state_w external_wrench_b = torch.zeros((num_cubes, 1, 6), device=sim.device)
if force == "below_mu":
# # Simulate physics external_wrench_b[..., 0] = (
# for _ in range(10): static_friction_coefficient * cube_mass * gravity_magnitude * 0.99
# # perform rendering )
# sim.step() else:
# # update object external_wrench_b[..., 0] = (
# cube_object.update(sim.cfg.dt) static_friction_coefficient * cube_mass * gravity_magnitude * 1.01
)
# if force == "below_mu":
# # Assert that the block has not moved cube_object.set_external_force_and_torque(
# torch.testing.assert_close( external_wrench_b[..., :3],
# cube_object.data.root_state_w, initial_root_state, rtol=1e-5, atol=1e-5 external_wrench_b[..., 3:],
# ) )
# else:
# torch.testing.assert_close( # Get root state
# cube_object.data.root_state_w, initial_root_state, rtol=1e-5, atol=1e-5 initial_root_pos = cube_object.data.root_pos_w.clone()
# ) # Simulate physics
for _ in range(200):
# def test_rigid_body_with_restitution(self): # apply the wrench
# """Test that restitution when applied to rigid object works as expected. cube_object.write_data_to_sim()
sim.step()
# This test works by dropping a block from a height and checking if the block bounces or not based on the # update object
# restitution value set for the object. We set the restitution to be non-zero and drop the block from a height. cube_object.update(sim.cfg.dt)
# When the restitution is 0, the block should not bounce. When the restitution is 1, the block should bounce if force == "below_mu":
# with the same energy. When the restitution is between 0 and 1, the block should bounce with less energy. # Assert that the block has not moved
torch.testing.assert_close(
# """ cube_object.data.root_pos_w, initial_root_pos, rtol=1e-3, atol=1e-3
# for num_cubes in (1, 2): )
# for device in ("cuda:0", "cpu"): if force == "above_mu":
# with self.subTest(num_cubes=num_cubes, device=device): self.assertTrue(
# with build_simulation_context(device=device, add_ground_plane=True, auto_add_lighting=True) as sim: (cube_object.data.root_state_w[..., 0] - initial_root_pos[..., 0] > 0.02).all()
# cube_object, _ = generate_cubes_scene(num_cubes=num_cubes, height=1.0, device=device) )
# # Create ground plane such that has a restitution of 1.0 (perfectly elastic collision) def test_rigid_body_with_restitution(self):
# cfg = sim_utils.GroundPlaneCfg( """Test that restitution when applied to rigid object works as expected.
# physics_material=materials.RigidBodyMaterialCfg(
# restitution=1.0, This test works by dropping a block from a height and checking if the block bounces or not based on the
# ) restitution value set for the object. We set the restitution to be non-zero and drop the block from a height.
# ) When the restitution is 0, the block should not bounce. When the restitution is between 0 and 1, the block
# cfg.func("/World/GroundPlane", cfg) should bounce with less energy.
"""
# indices = torch.tensor(range(num_cubes), dtype=torch.int) for num_cubes in (1, 2):
for device in ("cuda:0", "cpu"):
# # Play sim for expected_collision_type in "partially_elastic", "inelastic":
# sim.reset() with self.subTest(
expected_collision_type=expected_collision_type, num_cubes=num_cubes, device=device
# # 3 cases: inelastic, partially elastic, elastic ):
# # inelastic: resitution = 0, block should not bounce with build_simulation_context(
# # partially elastic: 0 <= restitution <= 1, block should bounce with less energy device=device, add_ground_plane=False, auto_add_lighting=True
# # elastic: restitution = 1, block should bounce with same energy ) as sim:
# for expected_collision_type in "inelastic", "partially_elastic", "elastic": cube_object, _ = generate_cubes_scene(num_cubes=num_cubes, height=1.0, device=device)
# root_state = torch.zeros(1, 13, device=sim.device)
# root_state[0, 3] = 1.0 # To make orientation a quaternion # Set static friction to be non-zero
# root_state[0, 2] = 0.1 # Set an initial drop height if expected_collision_type == "inelastic":
# root_state[0, 9] = -1.0 # Set an initial downward velocity restitution_coefficient = 0.0
elif expected_collision_type == "partially_elastic":
# cube_object.write_root_state_to_sim(root_state=root_state) restitution_coefficient = 0.5
# prev_z_velocity = 0.0 # Create ground plane such that has a restitution of 1.0 (perfectly elastic collision)
# curr_z_velocity = 0.0 cfg = sim_utils.GroundPlaneCfg(
physics_material=materials.RigidBodyMaterialCfg(
# with self.subTest(expected_collision_type=expected_collision_type): restitution=restitution_coefficient,
# # cube_object.reset() )
# # Set static friction to be non-zero )
# if expected_collision_type == "inelastic": cfg.func("/World/GroundPlane", cfg)
# restitution_coefficient = 0.0
# elif expected_collision_type == "partially_elastic": indices = torch.tensor(range(num_cubes), dtype=torch.int)
# restitution_coefficient = 0.5
# else: # Play sim
# restitution_coefficient = 1.0 sim.reset()
# restitution = 0.5 root_state = torch.zeros(num_cubes, 13, device=sim.device)
# static_friction = torch.zeros(num_cubes, 1) root_state[:, 3] = 1.0 # To make orientation a quaternion
# dynamic_friction = torch.zeros(num_cubes, 1) for i in range(num_cubes):
# restitution = torch.Tensor([[restitution_coefficient]] * num_cubes) root_state[i, 1] = 1.0 * i
root_state[:, 2] = 1.0 # Set an initial drop height
# cube_object_materials = torch.cat( root_state[:, 9] = -1.0 # Set an initial downward velocity
# [static_friction, dynamic_friction, restitution], dim=-1
# ) cube_object.write_root_state_to_sim(root_state=root_state)
# # Add friction to cube static_friction = torch.zeros(num_cubes, 1)
# cube_object.root_physx_view.set_material_properties(cube_object_materials, indices) dynamic_friction = torch.zeros(num_cubes, 1)
restitution = torch.Tensor([[restitution_coefficient]] * num_cubes)
# curr_z_velocity = cube_object.data.root_lin_vel_w[:, 2]
cube_object_materials = torch.cat([static_friction, dynamic_friction, restitution], dim=-1)
# while torch.all(curr_z_velocity <= 0.0):
# # Simulate physics # Add restitution to cube
# curr_z_velocity = cube_object.data.root_lin_vel_w[:, 2] cube_object.root_physx_view.set_material_properties(cube_object_materials, indices)
# # perform rendering curr_z_velocity = cube_object.data.root_lin_vel_w[:, 2].clone()
# sim.step()
for _ in range(100):
# # update object sim.step()
# cube_object.update(sim.cfg.dt)
# if torch.all(curr_z_velocity <= 0.0): # update object
# # Still in the air cube_object.update(sim.cfg.dt)
# prev_z_velocity = curr_z_velocity curr_z_velocity = cube_object.data.root_lin_vel_w[:, 2].clone()
# # We have made contact with the ground and can verify expected collision type if expected_collision_type == "inelastic":
# # based on how velocity has changed after the collision # assert that the block has not bounced by checking that the z velocity is less than or equal to 0
# if expected_collision_type == "inelastic": self.assertTrue((curr_z_velocity <= 0.0).all())
# # Assert that the block has lost most energy by checking that the z velocity is < 1/2 previous
# # velocity. This is because the floor's resitution means it will bounce back an object that itself if torch.all(curr_z_velocity <= 0.0):
# # has restitution set to 0.0 # Still in the air
# self.assertTrue(torch.all(torch.le(curr_z_velocity / 2, abs(prev_z_velocity)))) prev_z_velocity = curr_z_velocity
# elif expected_collision_type == "partially_elastic": else:
# # Assert that the block has lost some energy by checking that the z velocity is less # collision has happened, exit the for loop
# self.assertTrue(torch.all(torch.le(abs(curr_z_velocity), abs(prev_z_velocity)))) break
# elif expected_collision_type == "elastic":
# # Assert that the block has not lost any energy by checking that the z velocity is the same if expected_collision_type == "partially_elastic":
# torch.testing.assert_close(abs(curr_z_velocity), abs(prev_z_velocity)) # Assert that the block has lost some energy by checking that the z velocity is less
self.assertTrue(torch.all(torch.le(abs(curr_z_velocity), abs(prev_z_velocity))))
self.assertTrue((curr_z_velocity > 0.0).all())
def test_rigid_body_set_mass(self): def test_rigid_body_set_mass(self):
"""Test getting and setting mass of rigid object.""" """Test getting and setting mass of rigid object."""
......
...@@ -9,6 +9,7 @@ Any tests not listed here will use the default timeout. ...@@ -9,6 +9,7 @@ Any tests not listed here will use the default timeout.
""" """
PER_TEST_TIMEOUTS = { PER_TEST_TIMEOUTS = {
"test_articulation.py": 200, "test_articulation.py": 200,
"test_deformable_object.py": 200,
"test_environments.py": 1200, # This test runs through all the environments for 100 steps each "test_environments.py": 1200, # This test runs through all the environments for 100 steps each
"test_environment_determinism.py": 200, # This test runs through many the environments for 100 steps each "test_environment_determinism.py": 200, # This test runs through many the environments for 100 steps each
"test_env_rendering_logic.py": 300, "test_env_rendering_logic.py": 300,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment