Sensor Fusion¶
The sensor_fusion.h header file interfaces with the sensor fusion algorithm running on MetaMotion boards. When using the sensor fusion algorithm, it is important that you do not simultaenously use the Accelerometer, Gyro, and Magnetometer modules; the algorithm configures those sensors internally based on the selected fusion mode.
To activate the sensor fusion algorithm, first set the fusion mode and data ranges, then subscribe to and enable the desired output data, and finally, call mbl_mw_sensor_fusion_start.
Mode¶
The sensor fusion algorithm has 4 fusion modes, listed in the below table:
Mode | Description |
---|---|
NDoF | Calculates absolute roeintation from accelerometer, gyro, and magnetometer |
IMUPlus | Calculates relative orientation in space from accelerometer and gyro data |
Compass | Determines geographic direction from th Earth’s magnetic field |
M4G | Similar to IMUPlus except rotation is detected with the magnetometer |
The mode is set with mbl_mw_sensor_fusion_set_mode and written to the board by calling mbl_mw_sensor_fusion_write_config. Before writing the configuration, you can also set the acceleration and rotation ranges of the accelerometer and gyroscope respectively.
#include "metawear/sensor/sensor_fusion.h"
void configure_sensor_fusion(MblMwMetaWearBoard* board) {
// set fusion mode to ndof (n degress of freedom)
mbl_mw_sensor_fusion_set_mode(board, MBL_MW_SENSOR_FUSION_MODE_NDOF);
// set acceleration rangen to +/-8G, note accelerometer is configured here
mbl_mw_sensor_fusion_set_acc_range(board, MBL_MW_SENSOR_FUSION_ACC_RANGE_8G);
// write changes to the board
mbl_mw_sensor_fusion_write_config(board);
}
Calibration¶
The IMU sensors may need some calibration in order to improve their accuracy. After starting the sensor fusion algorithm, follow the calibration motions outlined in this Bosch tutorial video ( YouTube). and check the calibration state by reading the signal from mbl_mw_sensor_fusion_calibration_state_data_signal.
This signal is only available on boards running firmware v1.4.1 and newer.
#include "metawear/sensor/sensor_fusion.h"
void read_calibration(MblMwMetaWearBoard* board) {
auto signal = mbl_mw_sensor_fusion_calibration_state_data_signal(board);
mbl_mw_datasignal_subscribe(signal, nullptr, [](void* context, const MblMwData* data) {
auto casted = (MblMwCalibrationState*) data->value;
cout << "calibration state: {accelerometer: " << casted->accelerometer
<< ", gyroscope: " << casted->gyroscope
<< ", magnetometer: " << casted->magnetometer
<< "}" << endl;
});
mbl_mw_datasignal_read(signal);
}
Once the calibration state is at high accuracy for the required IMUs, call mbl_mw_sensor_fusion_read_calibration_data to retrieve the IMU calibration state, then mbl_mw_sensor_fusion_write_calibration_data to write it to the board.
#include "metawear/platform/memory.h"
#include "metawear/sensor/sensor_fusion.h"
void handle_imu_calibration_data(MblMwMetaWearBoard* board) {
mbl_mw_sensor_fusion_read_calibration_data(board, nullptr, [](void *context, MblMwMetaWearBoard* board, const MblMwCalibrationData* data) {
// returns null if an error occured, such as using with unsupported firmware
// write to board, or save to local file to always have on hand
if (data != nullptr) {
// calibration data is reloaded everytime mode changes
mbl_mw_sensor_fusion_write_calibration_data(board, data);
// free memory after we're done with the pointer
mbl_mw_memory_free(data);
}
});
}
You can combine the write operation with macro module to store the calibration data in the flash memory.
Data¶
The sensor fusion algorithm provides raw acceleration, rotation, and magnetic field values along with quaternion values and Euler angles. Furthermore, the source of acceleration can be separated into gravity and linear acceleration and both values are also provided. Keep in mind that each sensor fusion mode has different sets of available data and produces it at different rates.
Mode | Acc | Gyro | Mag |
---|---|---|---|
NDoF | 100Hz | 100Hz | 25Hz |
IMUPlus | 100Hz | 100Hz | N/A |
Compass | 25Hz | N/A | 25Hz |
M4G | 50Hz | N/A | 50Hz |
Also note that the units and type casting of the sensor fusion data is different for each type of data..
Data | Units | Casted Data |
---|---|---|
Acceleration | g | MblMwCorrectedCartesianFloat |
Rotation | deg/s | MblMwCorrectedCartesianFloat |
Magnetic Field | uT | MblMwCorrectedCartesianFloat |
Quaternion | None | MblMwQuaternion |
Euler Angles | degrees | MblMwEulerAngles |
Linear Acc | g | MblMwCartesianFloat |
Gravity | g | MblMwCartesianFloat |
#include <cstdio>
#include "metawear/core/datasignal.h"
#include "metawear/core/data.h"
#include "metawear/core/types.h"
void stream_quaternion(MblMwMetaWearBoard* board) {
auto quaternion = mbl_mw_sensor_fusion_get_data_signal(board,
MBL_MW_SENSOR_FUSION_DATA_QUATERION);
mbl_mw_datasignal_subscribe(quaternion, nullptr, [](void* context, const MblMwData* data) {
MblMwQuaternion* quaternion = (MblMwQuaternion*) data->value;
std::printf("{w: %.3f, x: %.3f, y: %.3f, z: %.3f}\n",
quaternion->w, quaternion->x, quaternion->y, quaternion->z);
});
mbl_mw_sensor_fusion_enable_data(board, MBL_MW_SENSOR_FUSION_DATA_QUATERNION);
mbl_mw_sensor_fusion_start(board);
}