carla/sensor/data/
imu_measurement.rs

1use crate::{geom::Vector3D, sensor::SensorData};
2use carla_sys::carla_rust::sensor::data::FfiImuMeasurement;
3use cxx::SharedPtr;
4use derivative::Derivative;
5use static_assertions::assert_impl_all;
6
7/// IMU (Inertial Measurement Unit) sensor measurement data.
8///
9/// This type represents data from an IMU sensor, including accelerometer (linear acceleration),
10/// gyroscope (angular velocity), and compass (orientation) readings. IMU sensors are useful
11/// for vehicle dynamics analysis and state estimation.
12///
13/// Corresponds to [`carla.IMUMeasurement`] in the Python API.
14#[cfg_attr(carla_version_0916, doc = "")]
15#[cfg_attr(
16    carla_version_0916,
17    doc = " [`carla.IMUMeasurement`]: https://carla.readthedocs.io/en/0.9.16/python_api/#carla.IMUMeasurement"
18)]
19#[cfg_attr(carla_version_0915, doc = "")]
20#[cfg_attr(
21    carla_version_0915,
22    doc = " [`carla.IMUMeasurement`]: https://carla.readthedocs.io/en/0.9.15/python_api/#carla.IMUMeasurement"
23)]
24#[cfg_attr(carla_version_0914, doc = "")]
25#[cfg_attr(
26    carla_version_0914,
27    doc = " [`carla.IMUMeasurement`]: https://carla.readthedocs.io/en/0.9.14/python_api/#carla.IMUMeasurement"
28)]
29///
30/// # Examples
31///
32/// ```no_run
33/// use carla::{
34///     client::{ActorBase, Client},
35///     sensor::data::ImuMeasurement,
36/// };
37///
38/// let client = Client::default();
39/// let mut world = client.world();
40///
41/// # let bp_lib = world.blueprint_library();
42/// # let imu_bp = bp_lib.filter("sensor.other.imu").get(0).unwrap();
43/// # let spawn_points = world.map().recommended_spawn_points();
44/// # let imu = world.spawn_actor(&imu_bp, spawn_points.get(0).unwrap()).unwrap();
45/// # let sensor: carla::client::Sensor = imu.try_into().unwrap();
46///
47/// sensor.listen(|sensor_data| {
48///     if let Ok(imu_data) = ImuMeasurement::try_from(sensor_data) {
49///         let accel = imu_data.accelerometer();
50///         let gyro = imu_data.gyroscope();
51///         let heading = imu_data.compass();
52///
53///         println!(
54///             "Acceleration: ({:.2}, {:.2}, {:.2}) m/s²",
55///             accel.x, accel.y, accel.z
56///         );
57///         println!(
58///             "Angular velocity: ({:.2}, {:.2}, {:.2}) rad/s",
59///             gyro.x, gyro.y, gyro.z
60///         );
61///         println!("Compass heading: {:.2}°", heading);
62///     }
63/// });
64/// ```
65#[derive(Clone, Derivative)]
66#[derivative(Debug)]
67#[repr(transparent)]
68pub struct ImuMeasurement {
69    #[derivative(Debug = "ignore")]
70    inner: SharedPtr<FfiImuMeasurement>,
71}
72
73impl ImuMeasurement {
74    /// Returns the accelerometer reading (linear acceleration) in m/s².
75    ///
76    /// The vector components represent acceleration in the sensor's local coordinate system:
77    /// - x: forward/backward
78    /// - y: left/right
79    /// - z: up/down
80    #[cfg_attr(
81        carla_version_0916,
82        doc = " See [carla.IMUMeasurement.accelerometer](https://carla.readthedocs.io/en/0.9.16/python_api/#carla.IMUMeasurement.accelerometer)"
83    )]
84    #[cfg_attr(
85        carla_version_0915,
86        doc = " See [carla.IMUMeasurement.accelerometer](https://carla.readthedocs.io/en/0.9.15/python_api/#carla.IMUMeasurement.accelerometer)"
87    )]
88    #[cfg_attr(
89        carla_version_0914,
90        doc = " See [carla.IMUMeasurement.accelerometer](https://carla.readthedocs.io/en/0.9.14/python_api/#carla.IMUMeasurement.accelerometer)"
91    )]
92    #[cfg_attr(
93        any(carla_version_0916, carla_version_0915, carla_version_0914),
94        doc = " in the Python API."
95    )]
96    pub fn accelerometer(&self) -> Vector3D {
97        // SAFETY: carla::geom::Vector3D and FfiVector3D have identical memory layout
98        unsafe {
99            let cpp_vec = self.inner.GetAccelerometer();
100            Vector3D::from_ffi((&cpp_vec as *const _ as *const crate::geom::FfiVector3D).read())
101        }
102    }
103
104    /// Returns the compass heading in radians.
105    ///
106    /// The compass value represents the orientation relative to north (0 radians).
107    #[cfg_attr(
108        carla_version_0916,
109        doc = " See [carla.IMUMeasurement.compass](https://carla.readthedocs.io/en/0.9.16/python_api/#carla.IMUMeasurement.compass)"
110    )]
111    #[cfg_attr(
112        carla_version_0915,
113        doc = " See [carla.IMUMeasurement.compass](https://carla.readthedocs.io/en/0.9.15/python_api/#carla.IMUMeasurement.compass)"
114    )]
115    #[cfg_attr(
116        carla_version_0914,
117        doc = " See [carla.IMUMeasurement.compass](https://carla.readthedocs.io/en/0.9.14/python_api/#carla.IMUMeasurement.compass)"
118    )]
119    #[cfg_attr(
120        any(carla_version_0916, carla_version_0915, carla_version_0914),
121        doc = " in the Python API."
122    )]
123    pub fn compass(&self) -> f32 {
124        self.inner.GetCompass()
125    }
126
127    /// Returns the gyroscope reading (angular velocity) in rad/s.
128    ///
129    /// The vector components represent rotation rates around the sensor's local axes:
130    /// - x: roll rate (rotation around forward axis)
131    /// - y: pitch rate (rotation around lateral axis)
132    /// - z: yaw rate (rotation around vertical axis)
133    #[cfg_attr(
134        carla_version_0916,
135        doc = " See [carla.IMUMeasurement.gyroscope](https://carla.readthedocs.io/en/0.9.16/python_api/#carla.IMUMeasurement.gyroscope)"
136    )]
137    #[cfg_attr(
138        carla_version_0915,
139        doc = " See [carla.IMUMeasurement.gyroscope](https://carla.readthedocs.io/en/0.9.15/python_api/#carla.IMUMeasurement.gyroscope)"
140    )]
141    #[cfg_attr(
142        carla_version_0914,
143        doc = " See [carla.IMUMeasurement.gyroscope](https://carla.readthedocs.io/en/0.9.14/python_api/#carla.IMUMeasurement.gyroscope)"
144    )]
145    #[cfg_attr(
146        any(carla_version_0916, carla_version_0915, carla_version_0914),
147        doc = " in the Python API."
148    )]
149    pub fn gyroscope(&self) -> Vector3D {
150        // SAFETY: carla::geom::Vector3D and FfiVector3D have identical memory layout
151        unsafe {
152            let cpp_vec = self.inner.GetGyroscope();
153            Vector3D::from_ffi((&cpp_vec as *const _ as *const crate::geom::FfiVector3D).read())
154        }
155    }
156
157    pub(crate) fn from_cxx(ptr: SharedPtr<FfiImuMeasurement>) -> Option<Self> {
158        if ptr.is_null() {
159            None
160        } else {
161            Some(Self { inner: ptr })
162        }
163    }
164}
165
166impl TryFrom<SensorData> for ImuMeasurement {
167    type Error = SensorData;
168
169    fn try_from(value: SensorData) -> Result<Self, Self::Error> {
170        let ptr = value.inner.to_imu_measurement();
171        Self::from_cxx(ptr).ok_or(value)
172    }
173}
174
175assert_impl_all!(ImuMeasurement: Send, Sync);