diff --git a/conf/modules/mag_hmc58xx.xml b/conf/modules/mag_hmc58xx.xml
index c368aea194..1e5e8bc5ef 100644
--- a/conf/modules/mag_hmc58xx.xml
+++ b/conf/modules/mag_hmc58xx.xml
@@ -5,6 +5,7 @@
HMC58xx magnetometer.
Module for standalone operation/logging of a HMC58xx magnetometer.
+ An arbitrary rotation between the sensor frame and the IMU frame can be compensated with a MAG_TO_IMU rotation (defined by three euler angles). The three angles must be defined to enable this correction. Otherwise it is assumed that the axis are aligned.
@@ -15,6 +16,11 @@
+
diff --git a/sw/airborne/modules/sensors/mag_hmc58xx.c b/sw/airborne/modules/sensors/mag_hmc58xx.c
index d1b26aa25d..0c1c179a98 100644
--- a/sw/airborne/modules/sensors/mag_hmc58xx.c
+++ b/sw/airborne/modules/sensors/mag_hmc58xx.c
@@ -29,6 +29,7 @@
#include "mcu_periph/uart.h"
#include "pprzlink/messages.h"
#include "subsystems/datalink/downlink.h"
+#include "generated/airframe.h"
#ifndef HMC58XX_CHAN_X
#define HMC58XX_CHAN_X 0
@@ -52,6 +53,13 @@
#if MODULE_HMC58XX_UPDATE_AHRS
#include "subsystems/imu.h"
#include "subsystems/abi.h"
+
+#if defined HMC58XX_MAG_TO_IMU_PHI && defined HMC58XX_MAG_TO_IMU_THETA && defined HMC58XX_MAG_TO_IMU_PSI
+#define USE_MAG_TO_IMU 1
+static struct Int32RMat mag_to_imu; ///< rotation from mag to imu frame
+#else
+#define USE_MAG_TO_IMU 0
+#endif
#endif
struct Hmc58xx mag_hmc58xx;
@@ -59,6 +67,15 @@ struct Hmc58xx mag_hmc58xx;
void mag_hmc58xx_module_init(void)
{
hmc58xx_init(&mag_hmc58xx, &(MAG_HMC58XX_I2C_DEV), HMC58XX_ADDR);
+
+#if MODULE_HMC58XX_UPDATE_AHRS && USE_MAG_TO_IMU
+ struct Int32Eulers mag_to_imu_eulers = {
+ ANGLE_BFP_OF_REAL(HMC58XX_MAG_TO_IMU_PHI),
+ ANGLE_BFP_OF_REAL(HMC58XX_MAG_TO_IMU_THETA),
+ ANGLE_BFP_OF_REAL(HMC58XX_MAG_TO_IMU_PSI)
+ };
+ int32_rmat_of_eulers(&mag_to_imu, &mag_to_imu_eulers);
+#endif
}
void mag_hmc58xx_module_periodic(void)
@@ -81,8 +98,17 @@ void mag_hmc58xx_module_event(void)
HMC58XX_CHAN_Y_SIGN(int32_t)(mag_hmc58xx.data.value[HMC58XX_CHAN_Y]),
HMC58XX_CHAN_Z_SIGN(int32_t)(mag_hmc58xx.data.value[HMC58XX_CHAN_Z])
};
+ // only rotate if needed
+#if USE_MAG_TO_IMU
+ struct Int32Vect3 imu_mag;
+ // rotate data from mag frame to imu frame
+ int32_rmat_vmult(&imu_mag, &mag_to_imu, &mag);
+ // unscaled vector
+ VECT3_COPY(imu.mag_unscaled, imu_mag);
+#else
// unscaled vector
VECT3_COPY(imu.mag_unscaled, mag);
+#endif
// scale vector
imu_scale_mag(&imu);