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

Adds IMU sensor #619

Open
wants to merge 47 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
bd2eb53
add imu sensor outdated version
pascal-roth Dec 11, 2023
530ab8a
update to physix prim view and update init
pascal-roth Dec 11, 2023
2bcf653
add check for sensor
pascal-roth Dec 11, 2023
e11defb
run formatter
pascal-roth Dec 11, 2023
cbd47fa
adjust changelog
pascal-roth Dec 11, 2023
baf5132
change frame of vel and acc, only accept rigid body prim, typo
pascal-roth Dec 19, 2023
50135d3
Merge branch 'devel' into feature/imu
pascal-roth Dec 19, 2023
6394262
remove outdated call as made in latest PR for other sensors
pascal-roth Dec 19, 2023
4f30a56
run formatter
pascal-roth Dec 19, 2023
914a39b
Merge branch 'devel' into feature/imu
pascal-roth Dec 21, 2023
c5ace7a
Merge branch 'main' into feature/imu
pascal-roth Mar 17, 2024
ec7da0d
start update
pascal-roth Mar 17, 2024
ef4c544
fixes
pascal-roth Mar 17, 2024
d90a7f1
run formatter
pascal-roth Mar 17, 2024
b88bf40
fix check imu sensor
pascal-roth Mar 17, 2024
3d5bceb
Merge branch 'main' into feature/imu
pascal-roth Apr 23, 2024
39594de
Merge branch 'feature/imu' of github.com:isaac-orbit/orbit into featu…
pascal-roth Apr 23, 2024
b966d04
run formatter
pascal-roth Apr 23, 2024
a040b72
Merge branch 'main' into feature/imu
pascal-roth Jul 2, 2024
45c0add
move to new sensor location
pascal-roth Jul 2, 2024
e168ee4
cleanup changelog, update imu sensor to isaaclab
pascal-roth Jul 2, 2024
6cb55fc
visualization fix
pascal-roth Jul 2, 2024
8d2f272
fixes and move utils to math utils
pascal-roth Jul 3, 2024
c76ca6d
add unittest, move utils to math.utils
pascal-roth Jul 3, 2024
d17fbeb
formatter
pascal-roth Jul 3, 2024
10759fa
wip
pascal-roth Jul 7, 2024
4fdb670
add doc and formatter
pascal-roth Jul 7, 2024
3399e3a
Apply suggestions from code review
pascal-roth Jul 24, 2024
3acd014
Apply suggestions from code review
pascal-roth Jul 24, 2024
869287b
started fix imu offset
pascal-roth Jul 24, 2024
28aab42
add offset test and compare with isaac sim imu
pascal-roth Jul 25, 2024
0cc85e2
add test for convention transform, small changes to code
pascal-roth Jul 25, 2024
1bd896d
renaming from all captial letters
pascal-roth Jul 25, 2024
cba977b
wip
pascal-roth Aug 2, 2024
b952d63
fix tests
pascal-roth Aug 9, 2024
18fc6d5
formatter
pascal-roth Aug 9, 2024
e01b6bf
use new physx api and store everything in world frame
pascal-roth Aug 13, 2024
f4f92e2
Merge branch 'feature/imu' of https://github.com/isaac-sim/IsaacLab i…
pascal-roth Aug 13, 2024
7068197
bugfix
pascal-roth Aug 13, 2024
f024f66
Merge branch 'main' into feature/imu
pascal-roth Aug 13, 2024
33e22a1
update test, physx bug detected
pascal-roth Aug 13, 2024
9ff23bc
com compensation
pascal-roth Aug 15, 2024
a0be30a
increasing spawn height
pascal-roth Aug 16, 2024
e34922e
add pendulum test and switch to numerical derivative of acceleration
jtigue-bdai Aug 16, 2024
cbb96bf
fix ground truth pendulum Z linear acceleration
jtigue-bdai Aug 19, 2024
0115b2c
add imu observations
jtigue-bdai Aug 26, 2024
ac3886a
clean up imu observation doc strings
jtigue-bdai Aug 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions source/extensions/omni.isaac.lab/docs/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Changelog
---------

* Added IMU sensor implementation that directly accessess the physx view :class:`omni.isaac.lab.sensors.IMU`. The
pascal-roth marked this conversation as resolved.
Show resolved Hide resolved
sensor comes with a configuration class :class:`omni.isaac.lab.sensors.IMUCfg` and data class
:class:`omni.isaac.lab.sensors.IMUData`.


0.18.6 (2024-07-01)
~~~~~~~~~~~~~~~~~~~

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@
+---------------------+---------------------------+---------------------------------------------------------------+
| Frame Transformer | /World/robot/base | Leaf exists and is a physics body (Articulation / Rigid Body) |
+---------------------+---------------------------+---------------------------------------------------------------+
| IMU | /World/robot/base | Leaf exists and is a physics body (Rigid Body) |
+---------------------+---------------------------+---------------------------------------------------------------+

"""

from .camera import * # noqa: F401, F403
from .contact_sensor import * # noqa: F401, F403
from .frame_transformer import * # noqa: F401
from .imu import * # noqa: F401, F403
from .ray_caster import * # noqa: F401, F403
from .sensor_base import SensorBase # noqa: F401
from .sensor_base_cfg import SensorBaseCfg # noqa: F401
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@
import omni.isaac.lab.sim as sim_utils
from omni.isaac.lab.utils import to_camel_case
from omni.isaac.lab.utils.array import convert_to_torch
from omni.isaac.lab.utils.math import quat_from_matrix
from omni.isaac.lab.utils.math import convert_orientation_convention, create_rotation_matrix_from_view, quat_from_matrix

from ..sensor_base import SensorBase
from .camera_data import CameraData
from .utils import convert_orientation_convention, create_rotation_matrix_from_view

if TYPE_CHECKING:
from .camera_cfg import CameraCfg
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from tensordict import TensorDict
from typing import Any

from .utils import convert_orientation_convention
from omni.isaac.lab.utils.math import convert_orientation_convention


@dataclass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,11 @@
# needed to import for allowing type-hinting: torch.device | str | None
from __future__ import annotations

import math
import numpy as np
import torch
import torch.nn.functional as F
from collections.abc import Sequence
from typing import Literal

import omni.isaac.core.utils.stage as stage_utils
import warp as wp
from pxr import UsdGeom

import omni.isaac.lab.utils.math as math_utils
from omni.isaac.lab.utils.array import TensorData, convert_to_torch
Expand Down Expand Up @@ -262,143 +257,6 @@ def create_pointcloud_from_rgbd(
return points_xyz, points_rgb


def convert_orientation_convention(
orientation: torch.Tensor,
origin: Literal["opengl", "ros", "world"] = "opengl",
target: Literal["opengl", "ros", "world"] = "ros",
) -> torch.Tensor:
r"""Converts a quaternion representing a rotation from one convention to another.

In USD, the camera follows the ``"opengl"`` convention. Thus, it is always in **Y up** convention.
This means that the camera is looking down the -Z axis with the +Y axis pointing up , and +X axis pointing right.
However, in ROS, the camera is looking down the +Z axis with the +Y axis pointing down, and +X axis pointing right.
Thus, the camera needs to be rotated by :math:`180^{\circ}` around the X axis to follow the ROS convention.

.. math::

T_{ROS} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} T_{USD}

On the other hand, the typical world coordinate system is with +X pointing forward, +Y pointing left,
and +Z pointing up. The camera can also be set in this convention by rotating the camera by :math:`90^{\circ}`
around the X axis and :math:`-90^{\circ}` around the Y axis.

.. math::

T_{WORLD} = \begin{bmatrix} 0 & 0 & -1 & 0 \\ -1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} T_{USD}

Thus, based on their application, cameras follow different conventions for their orientation. This function
converts a quaternion from one convention to another.

Possible conventions are:

- :obj:`"opengl"` - forward axis: -Z - up axis +Y - Offset is applied in the OpenGL (Usd.Camera) convention
- :obj:`"ros"` - forward axis: +Z - up axis -Y - Offset is applied in the ROS convention
- :obj:`"world"` - forward axis: +X - up axis +Z - Offset is applied in the World Frame convention

Args:
orientation: Quaternion of form `(w, x, y, z)` with shape (..., 4) in source convention
origin: Convention to convert to. Defaults to "ros".
target: Convention to convert from. Defaults to "opengl".

Returns:
Quaternion of form `(w, x, y, z)` with shape (..., 4) in target convention
"""
if target == origin:
return orientation.clone()

# -- unify input type
if origin == "ros":
# convert from ros to opengl convention
rotm = math_utils.matrix_from_quat(orientation)
rotm[:, :, 2] = -rotm[:, :, 2]
rotm[:, :, 1] = -rotm[:, :, 1]
# convert to opengl convention
quat_gl = math_utils.quat_from_matrix(rotm)
elif origin == "world":
# convert from world (x forward and z up) to opengl convention
rotm = math_utils.matrix_from_quat(orientation)
rotm = torch.matmul(
rotm,
math_utils.matrix_from_euler(
torch.tensor([math.pi / 2, -math.pi / 2, 0], device=orientation.device), "XYZ"
),
)
# convert to isaac-sim convention
quat_gl = math_utils.quat_from_matrix(rotm)
else:
quat_gl = orientation

# -- convert to target convention
if target == "ros":
# convert from opengl to ros convention
rotm = math_utils.matrix_from_quat(quat_gl)
rotm[:, :, 2] = -rotm[:, :, 2]
rotm[:, :, 1] = -rotm[:, :, 1]
return math_utils.quat_from_matrix(rotm)
elif target == "world":
# convert from opengl to world (x forward and z up) convention
rotm = math_utils.matrix_from_quat(quat_gl)
rotm = torch.matmul(
rotm,
math_utils.matrix_from_euler(
torch.tensor([math.pi / 2, -math.pi / 2, 0], device=orientation.device), "XYZ"
).T,
)
return math_utils.quat_from_matrix(rotm)
else:
return quat_gl.clone()


# @torch.jit.script
def create_rotation_matrix_from_view(
eyes: torch.Tensor,
targets: torch.Tensor,
device: str = "cpu",
) -> torch.Tensor:
"""
This function takes a vector ''eyes'' which specifies the location
of the camera in world coordinates and the vector ''targets'' which
indicate the position of the object.
The output is a rotation matrix representing the transformation
from world coordinates -> view coordinates.

The inputs camera_position and targets can each be a
- 3 element tuple/list
- torch tensor of shape (1, 3)
- torch tensor of shape (N, 3)

Args:
eyes: position of the camera in world coordinates
targets: position of the object in world coordinates

The vectors are broadcast against each other so they all have shape (N, 3).

Returns:
R: (N, 3, 3) batched rotation matrices

Reference:
Based on PyTorch3D (https://github.com/facebookresearch/pytorch3d/blob/eaf0709d6af0025fe94d1ee7cec454bc3054826a/pytorch3d/renderer/cameras.py#L1635-L1685)
"""
up_axis_token = stage_utils.get_stage_up_axis()
if up_axis_token == UsdGeom.Tokens.y:
up_axis = torch.tensor((0, 1, 0), device=device, dtype=torch.float32).repeat(eyes.shape[0], 1)
elif up_axis_token == UsdGeom.Tokens.z:
up_axis = torch.tensor((0, 0, 1), device=device, dtype=torch.float32).repeat(eyes.shape[0], 1)
else:
raise ValueError(f"Invalid up axis: {up_axis_token}")

# get rotation matrix in opengl format (-Z forward, +Y up)
z_axis = -F.normalize(targets - eyes, eps=1e-5)
x_axis = F.normalize(torch.cross(up_axis, z_axis, dim=1), eps=1e-5)
y_axis = F.normalize(torch.cross(z_axis, x_axis, dim=1), eps=1e-5)
is_close = torch.isclose(x_axis, torch.tensor(0.0), atol=5e-3).all(dim=1, keepdim=True)
if is_close.any():
replacement = F.normalize(torch.cross(y_axis, z_axis, dim=1), eps=1e-5)
x_axis = torch.where(is_close, replacement, x_axis)
R = torch.cat((x_axis[:, None, :], y_axis[:, None, :], z_axis[:, None, :]), dim=1)
return R.transpose(1, 2)


def save_images_to_file(images: torch.Tensor, file_path: str):
"""Save images to file.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright (c) 2022-2024, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

"""
IMU Sensor
"""

from __future__ import annotations

from .imu import IMU
from .imu_cfg import IMUCfg
from .imu_data import IMUData

__all__ = ["IMU", "IMUCfg", "IMUData"]
pascal-roth marked this conversation as resolved.
Show resolved Hide resolved
Loading
Loading