惯性测量单元 (IMU)

惯性测量单元 (IMU)#

概述IMU传感器基本力学关系的图示

惯性测量单元 (IMUs) 是一种用于测量物体加速度的传感器。这些传感器传统上设计用于报告线性加速度和角速度,并且基于与数字秤类似的原理工作: 它们报告由 作用在传感器上的净力 所产生的加速度。

一个简单的IMU实现会在传感器静止并处于某个局部引力场时,报告一个负的重力加速度。这在大多数实际应用中通常不需要,因此大多数真实的IMU传感器通常会包括一个 重力偏置 ,并假设设备位于地球表面。我们在Isaac Sim中提供的IMU也包含一个类似的偏置项,默认值为 +g。这意味着,如果你将IMU添加到你的仿真中,并且没有更改此偏置项,你将检测到一个与重力加速度方向相反的加速度,即: \(+ 9.81 m/s^{2}\)

考虑一个简单的环境,其中一个 Anymal 四足机器人配备了一个 IMU,分别安装在其两只前脚上。


@configclass
class ImuSensorSceneCfg(InteractiveSceneCfg):
    """Design the scene with sensors on the robot."""

    # ground plane
    ground = AssetBaseCfg(prim_path="/World/defaultGroundPlane", spawn=sim_utils.GroundPlaneCfg())

    # lights
    dome_light = AssetBaseCfg(
        prim_path="/World/Light", spawn=sim_utils.DomeLightCfg(intensity=3000.0, color=(0.75, 0.75, 0.75))
    )

    # robot
    robot = ANYMAL_C_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")

    imu_RF = ImuCfg(prim_path="{ENV_REGEX_NS}/Robot/LF_FOOT", debug_vis=True)

    imu_LF = ImuCfg(prim_path="{ENV_REGEX_NS}/Robot/RF_FOOT", gravity_bias=(0, 0, 0), debug_vis=True)


def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene):
    """Run the simulator."""
    # Define simulation stepping
    sim_dt = sim.get_physics_dt()

在这里,我们显式地从其中一个传感器中移除了偏差,我们可以通过可视化传感器,查看运行示例脚本时这如何影响报告的值。

IMU 可视化

请注意,右前脚显式地具有 (0,0,0) 的偏差。在可视化中,您应该看到表示右侧 IMU 加速度的箭头随时间快速变化,而表示左侧 IMU 的箭头始终指向垂直轴。

从传感器中检索值是以常规方式进行的

def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene):
  .
  .
  .
  # Simulate physics
  while simulation_app.is_running():
    .
    .
    .
    # print information from the sensors
    print("-------------------------------")
    print(scene["imu_LF"])
    print("Received linear velocity: ", scene["imu_LF"].data.lin_vel_b)
    print("Received angular velocity: ", scene["imu_LF"].data.ang_vel_b)
    print("Received linear acceleration: ", scene["imu_LF"].data.lin_acc_b)
    print("Received angular acceleration: ", scene["imu_LF"].data.ang_acc_b)
    print("-------------------------------")
    print(scene["imu_RF"])
    print("Received linear velocity: ", scene["imu_RF"].data.lin_vel_b)
    print("Received angular velocity: ", scene["imu_RF"].data.ang_vel_b)
    print("Received linear acceleration: ", scene["imu_RF"].data.lin_acc_b)
    print("Received angular acceleration: ", scene["imu_RF"].data.ang_acc_b)

传感器报告的数值波动是传感器如何计算加速度的直接结果,这个计算是通过相邻的地面真实速度值之间的有限差分近似来完成的,这些值是由仿真报告的。我们可以在报告的结果中看到这一点(请注意 线性加速度 ),因为右脚的加速度很小,但明确为零。

Imu sensor @ '/World/envs/env_.*/Robot/LF_FOOT':
        view type         : <class 'omni.physics.tensors.impl.api.RigidBodyView'>
        update period (s) : 0.0
        number of sensors : 1

Received linear velocity:  tensor([[ 0.0203, -0.0054,  0.0380]], device='cuda:0')
Received angular velocity:  tensor([[-0.0104, -0.1189,  0.0080]], device='cuda:0')
Received linear acceleration:  tensor([[ 4.8344, -0.0205,  8.5305]], device='cuda:0')
Received angular acceleration:  tensor([[-0.0389, -0.0262, -0.0045]], device='cuda:0')
-------------------------------
Imu sensor @ '/World/envs/env_.*/Robot/RF_FOOT':
        view type         : <class 'omni.physics.tensors.impl.api.RigidBodyView'>
        update period (s) : 0.0
        number of sensors : 1

Received linear velocity:  tensor([[0.0244, 0.0077, 0.0431]], device='cuda:0')
Received angular velocity:  tensor([[ 0.0122, -0.1360, -0.0042]], device='cuda:0')
Received linear acceleration:  tensor([[-0.0018,  0.0010, -0.0032]], device='cuda:0')
Received angular acceleration:  tensor([[-0.0373, -0.0050, -0.0053]], device='cuda:0')
-------------------------------
imu_sensor.py的代码
  1# Copyright (c) 2022-2025, The Isaac Lab Project Developers.
  2# All rights reserved.
  3#
  4# SPDX-License-Identifier: BSD-3-Clause
  5
  6"""Launch Isaac Sim Simulator first."""
  7
  8import argparse
  9
 10from isaaclab.app import AppLauncher
 11
 12# add argparse arguments
 13parser = argparse.ArgumentParser(description="Tutorial on adding sensors on a robot.")
 14parser.add_argument("--num_envs", type=int, default=1, help="Number of environments to spawn.")
 15# append AppLauncher cli args
 16AppLauncher.add_app_launcher_args(parser)
 17# parse the arguments
 18args_cli = parser.parse_args()
 19
 20# launch omniverse app
 21app_launcher = AppLauncher(args_cli)
 22simulation_app = app_launcher.app
 23
 24"""Rest everything follows."""
 25
 26import torch
 27
 28import isaaclab.sim as sim_utils
 29from isaaclab.assets import AssetBaseCfg
 30from isaaclab.scene import InteractiveScene, InteractiveSceneCfg
 31from isaaclab.sensors import ImuCfg
 32from isaaclab.utils import configclass
 33
 34##
 35# Pre-defined configs
 36##
 37from isaaclab_assets.robots.anymal import ANYMAL_C_CFG  # isort: skip
 38
 39
 40@configclass
 41class ImuSensorSceneCfg(InteractiveSceneCfg):
 42    """Design the scene with sensors on the robot."""
 43
 44    # ground plane
 45    ground = AssetBaseCfg(prim_path="/World/defaultGroundPlane", spawn=sim_utils.GroundPlaneCfg())
 46
 47    # lights
 48    dome_light = AssetBaseCfg(
 49        prim_path="/World/Light", spawn=sim_utils.DomeLightCfg(intensity=3000.0, color=(0.75, 0.75, 0.75))
 50    )
 51
 52    # robot
 53    robot = ANYMAL_C_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")
 54
 55    imu_RF = ImuCfg(prim_path="{ENV_REGEX_NS}/Robot/LF_FOOT", debug_vis=True)
 56
 57    imu_LF = ImuCfg(prim_path="{ENV_REGEX_NS}/Robot/RF_FOOT", gravity_bias=(0, 0, 0), debug_vis=True)
 58
 59
 60def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene):
 61    """Run the simulator."""
 62    # Define simulation stepping
 63    sim_dt = sim.get_physics_dt()
 64    sim_time = 0.0
 65    count = 0
 66
 67    # Simulate physics
 68    while simulation_app.is_running():
 69
 70        if count % 500 == 0:
 71            # reset counter
 72            count = 0
 73            # reset the scene entities
 74            # root state
 75            # we offset the root state by the origin since the states are written in simulation world frame
 76            # if this is not done, then the robots will be spawned at the (0, 0, 0) of the simulation world
 77            root_state = scene["robot"].data.default_root_state.clone()
 78            root_state[:, :3] += scene.env_origins
 79            scene["robot"].write_root_link_pose_to_sim(root_state[:, :7])
 80            scene["robot"].write_root_com_velocity_to_sim(root_state[:, 7:])
 81            # set joint positions with some noise
 82            joint_pos, joint_vel = (
 83                scene["robot"].data.default_joint_pos.clone(),
 84                scene["robot"].data.default_joint_vel.clone(),
 85            )
 86            joint_pos += torch.rand_like(joint_pos) * 0.1
 87            scene["robot"].write_joint_state_to_sim(joint_pos, joint_vel)
 88            # clear internal buffers
 89            scene.reset()
 90            print("[INFO]: Resetting robot state...")
 91        # Apply default actions to the robot
 92        # -- generate actions/commands
 93        targets = scene["robot"].data.default_joint_pos
 94        # -- apply action to the robot
 95        scene["robot"].set_joint_position_target(targets)
 96        # -- write data to sim
 97        scene.write_data_to_sim()
 98        # perform step
 99        sim.step()
100        # update sim-time
101        sim_time += sim_dt
102        count += 1
103        # update buffers
104        scene.update(sim_dt)
105
106        # print information from the sensors
107        print("-------------------------------")
108        print(scene["imu_LF"])
109        print("Received linear velocity: ", scene["imu_LF"].data.lin_vel_b)
110        print("Received angular velocity: ", scene["imu_LF"].data.ang_vel_b)
111        print("Received linear acceleration: ", scene["imu_LF"].data.lin_acc_b)
112        print("Received angular acceleration: ", scene["imu_LF"].data.ang_acc_b)
113        print("-------------------------------")
114        print(scene["imu_RF"])
115        print("Received linear velocity: ", scene["imu_RF"].data.lin_vel_b)
116        print("Received angular velocity: ", scene["imu_RF"].data.ang_vel_b)
117        print("Received linear acceleration: ", scene["imu_RF"].data.lin_acc_b)
118        print("Received angular acceleration: ", scene["imu_RF"].data.ang_acc_b)
119
120
121def main():
122    """Main function."""
123
124    # Initialize the simulation context
125    sim_cfg = sim_utils.SimulationCfg(dt=0.005, device=args_cli.device)
126    sim = sim_utils.SimulationContext(sim_cfg)
127    # Set main camera
128    sim.set_camera_view(eye=[3.5, 3.5, 3.5], target=[0.0, 0.0, 0.0])
129    # design scene
130    scene_cfg = ImuSensorSceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0)
131    scene = InteractiveScene(scene_cfg)
132    # Play the simulator
133    sim.reset()
134    # Now we are ready!
135    print("[INFO]: Setup complete...")
136    # Run the simulator
137    run_simulator(sim, scene)
138
139
140if __name__ == "__main__":
141    # run the main function
142    main()
143    # close sim app
144    simulation_app.close()