Skip to content

Commit fde5959

Browse files
Adds IMU projected_gravity_b and IMU computation speed optimizations (#2512)
# Description <!-- Thank you for your interest in sending a pull request. Please make sure to check the contribution guidelines. Link: https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html --> This PR adds projected_gravity_b data stream as well as speeding up computation by during batch rotating of all data streams to base frame in one computation rather than each data stream separately. This PR is dependant on [PR 2129](#2129) and should not be merged until that PR is merged. Fixes # (issue) <!-- As a practice, it is recommended to open an issue to have discussions on the proposed pull request. This makes it easier for the community to keep track of what is being developed or added, and if a given feature is demanded by more than one party. --> ## Type of change <!-- As you go through the list, delete the ones that are not applicable. --> - New feature (non-breaking change which adds functionality) <!-- Example: | Before | After | | ------ | ----- | | _gif/png before_ | _gif/png after_ | To upload images to a PR -- simply drag and drop an image while in edit mode and it should upload the image directly. You can then paste that source into the above before/after sections. --> ## Checklist - [ ] I have run the [`pre-commit` checks](https://pre-commit.com/) with `./isaaclab.sh --format` - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] 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 - [ ] I have added my name to the `CONTRIBUTORS.md` or my name already exists there <!-- As you go through the checklist above, you can mark something as done by putting an x character in it For example, - [x] I have done this task - [ ] I have not done this task --> --------- Co-authored-by: Kelly Guo <kellyg@nvidia.com>
1 parent 75824e8 commit fde5959

File tree

4 files changed

+61
-11
lines changed

4 files changed

+61
-11
lines changed

source/isaaclab/isaaclab/envs/mdp/observations.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,21 @@ def imu_orientation(env: ManagerBasedEnv, asset_cfg: SceneEntityCfg = SceneEntit
270270
return asset.data.quat_w
271271

272272

273+
def imu_projected_gravity(env: ManagerBasedEnv, asset_cfg: SceneEntityCfg = SceneEntityCfg("imu")) -> torch.Tensor:
274+
"""Imu sensor orientation w.r.t the env.scene.origin.
275+
276+
Args:
277+
env: The environment.
278+
asset_cfg: The SceneEntity associated with an Imu sensor.
279+
280+
Returns:
281+
Gravity projected on imu_frame, shape of torch.tensor is (num_env,3).
282+
"""
283+
284+
asset: Imu = env.scene[asset_cfg.name]
285+
return asset.data.projected_gravity_b
286+
287+
273288
def imu_ang_vel(env: ManagerBasedEnv, asset_cfg: SceneEntityCfg = SceneEntityCfg("imu")) -> torch.Tensor:
274289
"""Imu sensor angular velocity w.r.t. environment origin expressed in the sensor frame.
275290

source/isaaclab/isaaclab/sensors/imu/imu.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,11 @@ def reset(self, env_ids: Sequence[int] | None = None):
9696
if env_ids is None:
9797
env_ids = slice(None)
9898
# reset accumulative data buffers
99+
self._data.pos_w[env_ids] = 0.0
99100
self._data.quat_w[env_ids] = 0.0
101+
self._data.quat_w[env_ids, 0] = 1.0
102+
self._data.projected_gravity_b[env_ids] = 0.0
103+
self._data.projected_gravity_b[env_ids, 2] = -1.0
100104
self._data.lin_vel_b[env_ids] = 0.0
101105
self._data.ang_vel_b[env_ids] = 0.0
102106
self._data.lin_acc_b[env_ids] = 0.0
@@ -135,22 +139,24 @@ def _initialize_impl(self):
135139
else:
136140
raise RuntimeError(f"Failed to find a RigidBodyAPI for the prim paths: {self.cfg.prim_path}")
137141

142+
# Get world gravity
143+
gravity = self._physics_sim_view.get_gravity()
144+
gravity_dir = torch.tensor((gravity[0], gravity[1], gravity[2]), device=self.device)
145+
gravity_dir = math_utils.normalize(gravity_dir.unsqueeze(0)).squeeze(0)
146+
self.GRAVITY_VEC_W = gravity_dir.repeat(self.num_instances, 1)
147+
138148
# Create internal buffers
139149
self._initialize_buffers_impl()
140150

141151
def _update_buffers_impl(self, env_ids: Sequence[int]):
142152
"""Fills the buffers of the sensor data."""
143-
# check if self._dt is set (this is set in the update function)
144-
if not hasattr(self, "_dt"):
145-
raise RuntimeError(
146-
"The update function must be called before the data buffers are accessed the first time."
147-
)
153+
148154
# default to all sensors
149155
if len(env_ids) == self._num_envs:
150156
env_ids = slice(None)
151157
# obtain the poses of the sensors
152158
pos_w, quat_w = self._view.get_transforms()[env_ids].split([3, 4], dim=-1)
153-
quat_w = math_utils.convert_quat(quat_w, to="wxyz")
159+
quat_w = quat_w.roll(1, dims=-1)
154160

155161
# store the poses
156162
self._data.pos_w[env_ids] = pos_w + math_utils.quat_apply(quat_w, self._offset_pos_b[env_ids])
@@ -170,12 +176,19 @@ def _update_buffers_impl(self, env_ids: Sequence[int]):
170176
# numerical derivative
171177
lin_acc_w = (lin_vel_w - self._prev_lin_vel_w[env_ids]) / self._dt + self._gravity_bias_w[env_ids]
172178
ang_acc_w = (ang_vel_w - self._prev_ang_vel_w[env_ids]) / self._dt
173-
# store the velocities
174-
self._data.lin_vel_b[env_ids] = math_utils.quat_apply_inverse(self._data.quat_w[env_ids], lin_vel_w)
175-
self._data.ang_vel_b[env_ids] = math_utils.quat_apply_inverse(self._data.quat_w[env_ids], ang_vel_w)
179+
# stack data in world frame and batch rotate
180+
dynamics_data = torch.stack((lin_vel_w, ang_vel_w, lin_acc_w, ang_acc_w, self.GRAVITY_VEC_W[env_ids]), dim=0)
181+
dynamics_data_rot = math_utils.quat_apply_inverse(self._data.quat_w[env_ids].repeat(5, 1), dynamics_data).chunk(
182+
5, dim=0
183+
)
184+
# store the velocities.
185+
self._data.lin_vel_b[env_ids] = dynamics_data_rot[0]
186+
self._data.ang_vel_b[env_ids] = dynamics_data_rot[1]
176187
# store the accelerations
177-
self._data.lin_acc_b[env_ids] = math_utils.quat_apply_inverse(self._data.quat_w[env_ids], lin_acc_w)
178-
self._data.ang_acc_b[env_ids] = math_utils.quat_apply_inverse(self._data.quat_w[env_ids], ang_acc_w)
188+
self._data.lin_acc_b[env_ids] = dynamics_data_rot[2]
189+
self._data.ang_acc_b[env_ids] = dynamics_data_rot[3]
190+
# store projected gravity
191+
self._data.projected_gravity_b[env_ids] = dynamics_data_rot[4]
179192

180193
self._prev_lin_vel_w[env_ids] = lin_vel_w
181194
self._prev_ang_vel_w[env_ids] = ang_vel_w
@@ -186,6 +199,7 @@ def _initialize_buffers_impl(self):
186199
self._data.pos_w = torch.zeros(self._view.count, 3, device=self._device)
187200
self._data.quat_w = torch.zeros(self._view.count, 4, device=self._device)
188201
self._data.quat_w[:, 0] = 1.0
202+
self._data.projected_gravity_b = torch.zeros(self._view.count, 3, device=self._device)
189203
self._data.lin_vel_b = torch.zeros_like(self._data.pos_w)
190204
self._data.ang_vel_b = torch.zeros_like(self._data.pos_w)
191205
self._data.lin_acc_b = torch.zeros_like(self._data.pos_w)

source/isaaclab/isaaclab/sensors/imu/imu_data.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ class ImuData:
2525
Shape is (N, 4), where ``N`` is the number of environments.
2626
"""
2727

28+
projected_gravity_b: torch.Tensor = None
29+
"""Gravity direction unit vector projected on the imu frame.
30+
31+
Shape is (N,3), where ``N`` is the number of environments.
32+
"""
33+
2834
lin_vel_b: torch.Tensor = None
2935
"""IMU frame angular velocity relative to the world expressed in IMU frame.
3036

source/isaaclab/test/sensors/test_imu.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,14 @@ def test_single_dof_pendulum(setup_sim):
353353
if idx < 2:
354354
continue
355355

356+
# compare imu projected gravity
357+
gravity_dir_w = torch.tensor((0.0, 0.0, -1.0), device=scene.device).repeat(2, 1)
358+
gravity_dir_b = math_utils.quat_apply_inverse(imu_data.quat_w, gravity_dir_w)
359+
torch.testing.assert_close(
360+
imu_data.projected_gravity_b,
361+
gravity_dir_b,
362+
)
363+
356364
# compare imu angular velocity with joint velocity
357365
torch.testing.assert_close(
358366
joint_vel,
@@ -495,6 +503,13 @@ def test_offset_calculation(setup_sim):
495503
rtol=1e-4,
496504
atol=1e-4,
497505
)
506+
# check the projected gravity
507+
torch.testing.assert_close(
508+
scene.sensors["imu_robot_base"].data.projected_gravity_b,
509+
scene.sensors["imu_robot_imu_link"].data.projected_gravity_b,
510+
rtol=1e-4,
511+
atol=1e-4,
512+
)
498513

499514

500515
def test_env_ids_propagation(setup_sim):

0 commit comments

Comments
 (0)