[wpilib][sim] Add Onboard IMU Sim (#8855)

This provides the ability to simulate parts of the Onboard IMU at the
HAL level. This allows team to use and simulate the IMU in code, and a
follow up PR could be made to the halsim_gui to add a new widget to view
and modify the data graphically.

Since the C++ IMU uses radians for angles that is what I did for the
simulator.

Partially deals with #8845
This commit is contained in:
PJ Reiniger
2026-05-07 13:01:26 -04:00
committed by GitHub
parent 3d4cabfbc9
commit 4c07aedd91
23 changed files with 713 additions and 15 deletions

View File

@@ -0,0 +1,59 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "wpi/hardware/imu/OnboardIMU.hpp"
#include <gtest/gtest.h>
#include "wpi/simulation/OnboardIMUSim.hpp"
using namespace wpi;
TEST(OnboardIMUTest, SimDevices) {
OnboardIMU imu{OnboardIMU::FLAT};
EXPECT_EQ(0.0, imu.GetAngleX().value());
EXPECT_EQ(0.0, imu.GetAngleY().value());
EXPECT_EQ(0.0, imu.GetAngleZ().value());
EXPECT_EQ(0.0, imu.GetGyroRateX().value());
EXPECT_EQ(0.0, imu.GetGyroRateY().value());
EXPECT_EQ(0.0, imu.GetGyroRateZ().value());
EXPECT_EQ(0.0, imu.GetAccelX().value());
EXPECT_EQ(0.0, imu.GetAccelY().value());
EXPECT_EQ(0.0, imu.GetAccelZ().value());
EXPECT_EQ(0.0, imu.GetYaw().value());
sim::OnboardIMUSim sim{};
sim.SetAngleX(wpi::units::radian_t{1});
sim.SetAngleY(wpi::units::radian_t{2});
sim.SetAngleZ(wpi::units::radian_t{3});
sim.SetGyroRateX(wpi::units::radians_per_second_t{3.504});
sim.SetGyroRateY(wpi::units::radians_per_second_t{1.91});
sim.SetGyroRateZ(wpi::units::radians_per_second_t{22.9});
sim.SetAccelX(wpi::units::meters_per_second_squared_t{-1});
sim.SetAccelY(wpi::units::meters_per_second_squared_t{-2});
sim.SetAccelZ(wpi::units::meters_per_second_squared_t{-3});
sim.SetYaw(wpi::units::radian_t{1.234});
EXPECT_EQ(1.0, imu.GetAngleX().value());
EXPECT_EQ(2.0, imu.GetAngleY().value());
EXPECT_EQ(3.0, imu.GetAngleZ().value());
EXPECT_EQ(3.504, imu.GetGyroRateX().value());
EXPECT_EQ(1.91, imu.GetGyroRateY().value());
EXPECT_EQ(22.9, imu.GetGyroRateZ().value());
EXPECT_EQ(-1.0, imu.GetAccelX().value());
EXPECT_EQ(-2.0, imu.GetAccelY().value());
EXPECT_EQ(-3.0, imu.GetAccelZ().value());
EXPECT_EQ(1.234, imu.GetYaw().value());
}

View File

@@ -0,0 +1,41 @@
from wpilib import OnboardIMU
from wpilib.simulation import OnboardIMUSim
def test_sim_device() -> None:
imu = OnboardIMU(OnboardIMU.MountOrientation.FLAT)
sim = OnboardIMUSim()
assert 0.0 == imu.getAngleX()
assert 0.0 == imu.getAngleY()
assert 0.0 == imu.getAngleZ()
assert 0.0 == imu.getGyroRateX()
assert 0.0 == imu.getGyroRateY()
assert 0.0 == imu.getGyroRateZ()
assert 0.0 == imu.getAccelX()
assert 0.0 == imu.getAccelY()
assert 0.0 == imu.getAccelZ()
sim.setAngleX(1)
sim.setAngleY(2)
sim.setAngleZ(3)
sim.setGyroRateX(3.504)
sim.setGyroRateY(1.91)
sim.setGyroRateZ(22.9)
sim.setAccelX(-1)
sim.setAccelY(-2)
sim.setAccelZ(-3)
assert 1.0 == imu.getAngleX()
assert 2.0 == imu.getAngleY()
assert 3.0 == imu.getAngleZ()
assert 3.504 == imu.getGyroRateX()
assert 1.91 == imu.getGyroRateY()
assert 22.9 == imu.getGyroRateZ()
assert -1.0 == imu.getAccelX()
assert -2.0 == imu.getAccelY()
assert -3.0 == imu.getAccelZ()