Skip to content

Commit bbaf770

Browse files
Add kitless OVPhysX IMU pytest suite + check script
Mirror the structure of source/isaaclab_physx/test/sensors/test_imu.py under the kitless launcher pattern established by the rigid-object test: - Wheel gate (importorskip ovphysx.types + RIGID_BODY_POSE hasattr check) before AppLauncher; no AppLauncher needed at runtime. - SimulationContext built directly via build_simulation_context; assets spawned imperatively via _spawn_envs / _spawn_balls / _spawn_cubes / _spawn_anymal helpers; fnmatch-glob prim paths (env_*). - Six tests run on real Nucleus / procedural USD assets: test_constant_velocity, test_constant_acceleration, test_offset_calculation, test_env_ids_propagation, test_attachment_validity, test_sensor_print. - Two URDF-dependent tests (test_single_dof_pendulum, test_indirect_attachment) are skipped pending a USD version of simple_2_link.urdf — URDF-USD conversion requires the Kit URDF importer extension. check_imu.py is a kitless smoke-test script (free-falling sphere + IMU, prints readings for visual inspection). imu.update(dt) is called with force_recompute=True so the kernel fires each step (without InteractiveScene's lazy_sensor_update plumbing, the buffer would otherwise only refresh on imu.data access, leaving prev_lin_vel unseeded on iterations where the test skips data reads). Changelog fragment added under source/isaaclab_ovphysx/changelog.d/ per the new fragment-based workflow (do not edit CHANGELOG.rst directly). Refs isaac-sim#5318.
1 parent c8abc66 commit bbaf770

3 files changed

Lines changed: 513 additions & 0 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Added
2+
^^^^^
3+
4+
* Added :class:`~isaaclab_ovphysx.sensors.Imu` and
5+
:class:`~isaaclab_ovphysx.sensors.ImuData` implementing the
6+
:class:`~isaaclab.sensors.imu.BaseImu` /
7+
:class:`~isaaclab.sensors.imu.BaseImuData` contracts on the OVPhysX
8+
backend. Reports angular velocity and proper linear acceleration in
9+
the sensor body frame using ovphysx tensor bindings on the rigid-body
10+
ancestor of the sensor prim path. Linear acceleration is computed via
11+
numerical differentiation of body velocity (matching the PhysX
12+
backend) and includes a positive gravity bias by default.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
2+
# All rights reserved.
3+
#
4+
# SPDX-License-Identifier: BSD-3-Clause
5+
6+
"""Standalone validation script for the OVPhysX IMU sensor.
7+
8+
Run with:
9+
./scripts/run_ovphysx.sh source/isaaclab_ovphysx/test/sensors/check_imu.py
10+
11+
Spawns a free-falling sphere with an IMU attached, steps the simulation for
12+
100 steps, and prints the angular velocity and linear acceleration in the
13+
IMU body frame. In freefall the proper acceleration is zero (only gravity
14+
acts on the body), so the IMU reading should be approximately ``[0, 0, 0]``
15+
— the finite-difference world-frame acceleration ``(-g)`` cancels the IMU's
16+
gravity bias ``(+g)``.
17+
18+
Runs kitless under ``run_ovphysx.sh`` — no AppLauncher needed.
19+
"""
20+
21+
from __future__ import annotations
22+
23+
import torch
24+
from isaaclab_ovphysx.physics import OvPhysxCfg
25+
26+
import isaaclab.sim as sim_utils
27+
from isaaclab.assets import RigidObject, RigidObjectCfg
28+
from isaaclab.sensors.imu import Imu, ImuCfg
29+
from isaaclab.sim import SimulationCfg, build_simulation_context
30+
31+
32+
def main() -> None:
33+
sim_cfg = SimulationCfg(physics=OvPhysxCfg(), device="cpu", dt=0.005)
34+
with build_simulation_context(sim_cfg=sim_cfg) as sim:
35+
# Spawn one ball per env at /World/envs/env_<i>/ball.
36+
spawn_cfg = sim_utils.SphereCfg(
37+
radius=0.25,
38+
rigid_props=sim_utils.RigidBodyPropertiesCfg(),
39+
mass_props=sim_utils.MassPropertiesCfg(mass=0.5),
40+
collision_props=sim_utils.CollisionPropertiesCfg(),
41+
visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 0.0, 1.0)),
42+
)
43+
sim_utils.create_prim("/World/envs", "Xform")
44+
num_envs = 2
45+
for i in range(num_envs):
46+
sim_utils.create_prim(f"/World/envs/env_{i}", "Xform", translation=(i * 5.0, 0.0, 0.0))
47+
spawn_cfg.func(f"/World/envs/env_{i}/ball", spawn_cfg, translation=(0.0, 0.0, 1.0))
48+
49+
balls = RigidObject(
50+
RigidObjectCfg(
51+
prim_path="/World/envs/env_*/ball",
52+
spawn=None,
53+
init_state=RigidObjectCfg.InitialStateCfg(pos=(0.0, 0.0, 1.0)),
54+
)
55+
)
56+
imu = Imu(ImuCfg(prim_path="/World/envs/env_*/ball"))
57+
sim.reset()
58+
59+
dt = sim.get_physics_dt()
60+
for step in range(100):
61+
balls.write_data_to_sim()
62+
sim.step()
63+
balls.update(dt)
64+
imu.update(dt, force_recompute=True)
65+
66+
if step in (0, 10, 50, 99):
67+
ang = imu.data.ang_vel_b.torch
68+
lin = imu.data.lin_acc_b.torch
69+
print(f"step={step:3d} ang_vel_b={ang[0].cpu().numpy()} lin_acc_b={lin[0].cpu().numpy()}")
70+
71+
# Final sanity check: in freefall the proper acceleration is zero
72+
# (gravity cancels the bias). The norm should be near 0.
73+
final_lin = imu.data.lin_acc_b.torch
74+
magnitude = torch.linalg.norm(final_lin, dim=1).cpu().numpy()
75+
print(f"final |lin_acc_b| per env = {magnitude}")
76+
77+
78+
if __name__ == "__main__":
79+
main()

0 commit comments

Comments
 (0)