MAV'RIC
|
00001 /******************************************************************************* 00002 * Copyright (c) 2009-2016, MAV'RIC Development Team 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright notice, 00009 * this list of conditions and the following disclaimer. 00010 * 00011 * 2. Redistributions in binary form must reproduce the above copyright notice, 00012 * this list of conditions and the following disclaimer in the documentation 00013 * and/or other materials provided with the distribution. 00014 * 00015 * 3. Neither the name of the copyright holder nor the names of its contributors 00016 * may be used to endorse or promote products derived from this software without 00017 * specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00023 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00024 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00025 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00026 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00027 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00029 * POSSIBILITY OF SUCH DAMAGE. 00030 ******************************************************************************/ 00031 00032 /******************************************************************************* 00033 * \file imu.hpp 00034 * 00035 * \author MAV'RIC Team 00036 * \author Felix Schill 00037 * \author Gregoire Heitz 00038 * \author Julien Lecoeur 00039 * 00040 * \brief Inertial measurement unit (IMU) 00041 * 00042 ******************************************************************************/ 00043 00044 00045 #ifndef IMU_HPP_ 00046 #define IMU_HPP_ 00047 00048 #include <cstdint> 00049 #include <cstdbool> 00050 #include <array> 00051 00052 #include "drivers/accelerometer.hpp" 00053 #include "drivers/gyroscope.hpp" 00054 #include "drivers/magnetometer.hpp" 00055 #include "status/state.hpp" 00056 00057 extern "C" 00058 { 00059 #include "util/quaternions.h" 00060 } 00061 00062 #define GYRO_LPF 0.1f ///< The gyroscope linear pass filter gain 00063 #define ACC_LPF 0.05f ///< The accelerometer linear pass filter gain 00064 #define MAG_LPF 0.1f ///< The magnetometer linear pass filter gain 00065 00066 00070 typedef struct 00071 { 00072 std::array<float, 3> bias; 00073 std::array<float, 3> scale_factor; 00074 std::array<float, 3> sign; 00075 std::array<uint8_t, 3> axis; 00076 std::array<float, 3> max_values; 00077 std::array<float, 3> min_values; 00078 std::array<float, 3> mean_values; 00079 } imu_sensor_config_t; 00080 00081 00085 typedef struct 00086 { 00087 imu_sensor_config_t accelerometer; 00088 imu_sensor_config_t gyroscope; 00089 imu_sensor_config_t magnetometer; 00090 std::array<float, 3> magnetic_north; 00091 float lpf_acc; 00092 float lpf_gyro; 00093 float lpf_mag; 00094 float lpf_mean; 00095 float startup_calib_gyro_threshold; 00096 float startup_calib_duration_s; 00097 } imu_conf_t; 00098 00099 00105 static inline imu_conf_t imu_default_config(void); 00106 00107 00117 class Imu 00118 { 00119 public: 00123 Imu(Accelerometer& accelerometer, 00124 Gyroscope& gyroscope, 00125 Magnetometer& magnetometer, 00126 imu_conf_t config = imu_default_config()); 00127 00128 00134 bool update(void); 00135 00136 00142 const float& last_update_us(void) const; 00143 00144 00150 const float& dt_s(void) const; 00151 00152 00158 const std::array<float, 3>& acc(void) const; 00159 00160 00166 const std::array<float, 3>& gyro(void) const; 00167 00168 00174 const std::array<float, 3>& mag(void) const; 00175 00181 const std::array<float, 3>& magnetic_north(void) const; 00182 00183 00189 bool is_ready(void) const; 00190 00198 imu_conf_t* get_config(void); 00199 00200 // ------------------------------------------------------------------------- 00201 // 00202 // TODO implement calibration 00203 // 00204 // ------------------------------------------------------------------------- 00205 00218 bool start_accelerometer_bias_calibration(void); 00219 00220 00233 bool start_gyroscope_bias_calibration(void); 00234 00235 00251 bool start_magnetometer_bias_calibration(void); 00252 00253 00266 bool start_magnetic_north_calibration(void); 00267 00268 00276 bool stop_accelerometer_bias_calibration(void); 00277 00278 00286 bool stop_gyroscope_bias_calibration(void); 00287 00288 00297 bool stop_magnetometer_bias_calibration(void); 00298 00299 00307 bool stop_magnetic_north_calibration(void); 00308 00309 00310 private: 00316 bool is_calibration_ongoing(void) const; 00317 00318 00324 void do_calibration(void); 00325 00326 00327 Accelerometer& accelerometer_; 00328 Gyroscope& gyroscope_; 00329 Magnetometer& magnetometer_; 00330 00331 imu_conf_t config_; 00332 00333 std::array<float, 3> oriented_acc_; 00334 std::array<float, 3> oriented_gyro_; 00335 std::array<float, 3> oriented_mag_; 00336 00337 std::array<float, 3> scaled_acc_; 00338 std::array<float, 3> scaled_gyro_; 00339 std::array<float, 3> scaled_mag_; 00340 float magnetic_inclination_; 00341 float magnetic_norm_; 00342 00343 bool do_startup_calibration_; 00344 bool do_accelerometer_bias_calibration_; 00345 bool do_gyroscope_bias_calibration_; 00346 bool do_magnetometer_bias_calibration_; 00347 bool do_magnetic_north_calibration_; 00348 bool is_ready_; 00349 00350 float dt_s_; 00351 float last_update_us_; 00352 float startup_calibration_start_time_; 00353 }; 00354 00355 00356 00362 static inline imu_conf_t imu_default_config() 00363 { 00364 imu_conf_t conf = {}; 00365 00366 // Accelerometer 00367 // Bias 00368 conf.accelerometer.bias[0] = 0.0f; 00369 conf.accelerometer.bias[1] = 0.0f; 00370 conf.accelerometer.bias[2] = 0.0f; 00371 00372 // Scale 00373 conf.accelerometer.scale_factor[0] = 1.0f; 00374 conf.accelerometer.scale_factor[1] = 1.0f; 00375 conf.accelerometer.scale_factor[2] = 1.0f; 00376 00377 // Axis and sign 00378 conf.accelerometer.sign[0] = +1.0f; 00379 conf.accelerometer.sign[1] = +1.0f; 00380 conf.accelerometer.sign[2] = +1.0f; 00381 conf.accelerometer.axis[0] = 0; 00382 conf.accelerometer.axis[1] = 1; 00383 conf.accelerometer.axis[2] = 2; 00384 00385 // Min and max values 00386 conf.accelerometer.max_values[0] = -10000.0f; 00387 conf.accelerometer.max_values[1] = -10000.0f; 00388 conf.accelerometer.max_values[2] = -10000.0f; 00389 conf.accelerometer.min_values[0] = 10000.0f; 00390 conf.accelerometer.min_values[1] = 10000.0f; 00391 conf.accelerometer.min_values[2] = 10000.0f; 00392 conf.accelerometer.mean_values[0] = 0.0f; 00393 conf.accelerometer.mean_values[1] = 0.0f; 00394 conf.accelerometer.mean_values[2] = 0.0f; 00395 00396 // Gyroscope 00397 // Bias 00398 conf.gyroscope.bias[0] = 0.0f; 00399 conf.gyroscope.bias[1] = 0.0f; 00400 conf.gyroscope.bias[2] = 0.0f; 00401 00402 // Scale 00403 conf.gyroscope.scale_factor[0] = 1.0f; 00404 conf.gyroscope.scale_factor[1] = 1.0f; 00405 conf.gyroscope.scale_factor[2] = 1.0f; 00406 00407 // Axis and sign 00408 conf.gyroscope.sign[0] = +1.0f; 00409 conf.gyroscope.sign[1] = +1.0f; 00410 conf.gyroscope.sign[2] = +1.0f; 00411 conf.gyroscope.axis[0] = 0; 00412 conf.gyroscope.axis[1] = 1; 00413 conf.gyroscope.axis[2] = 2; 00414 00415 // Min and max values 00416 conf.gyroscope.max_values[0] = -10000.0f; 00417 conf.gyroscope.max_values[1] = -10000.0f; 00418 conf.gyroscope.max_values[2] = -10000.0f; 00419 conf.gyroscope.min_values[0] = 10000.0f; 00420 conf.gyroscope.min_values[1] = 10000.0f; 00421 conf.gyroscope.min_values[2] = 10000.0f; 00422 conf.gyroscope.mean_values[0] = 0.0f; 00423 conf.gyroscope.mean_values[1] = 0.0f; 00424 conf.gyroscope.mean_values[2] = 0.0f; 00425 00426 // Magnetometer 00427 // Bias 00428 conf.magnetometer.bias[0] = 0.0f; 00429 conf.magnetometer.bias[1] = 0.0f; 00430 conf.magnetometer.bias[2] = 0.0f; 00431 00432 // Scale 00433 conf.magnetometer.scale_factor[0] = 1.0f; 00434 conf.magnetometer.scale_factor[1] = 1.0f; 00435 conf.magnetometer.scale_factor[2] = 1.0f; 00436 00437 // Axis and sign 00438 conf.magnetometer.sign[0] = +1.0f; 00439 conf.magnetometer.sign[1] = +1.0f; 00440 conf.magnetometer.sign[2] = +1.0f; 00441 conf.magnetometer.axis[0] = 0; 00442 conf.magnetometer.axis[1] = 1; 00443 conf.magnetometer.axis[2] = 2; 00444 00445 // Min and max values 00446 conf.magnetometer.max_values[0] = -10000.0f; 00447 conf.magnetometer.max_values[1] = -10000.0f; 00448 conf.magnetometer.max_values[2] = -10000.0f; 00449 conf.magnetometer.min_values[0] = 10000.0f; 00450 conf.magnetometer.min_values[1] = 10000.0f; 00451 conf.magnetometer.min_values[2] = 10000.0f; 00452 conf.magnetometer.mean_values[0] = 0.0f; 00453 conf.magnetometer.mean_values[1] = 0.0f; 00454 conf.magnetometer.mean_values[2] = 0.0f; 00455 00456 // Magnetic north (default value in Lausanne: 62° inclination) 00457 conf.magnetic_north[0] = 0.46947156f; // cos(62°) 00458 conf.magnetic_north[1] = 0.0f; 00459 conf.magnetic_north[2] = 0.88294759f; // sin(62°) 00460 00461 // Low pass filter 00462 conf.lpf_acc = 0.1f; 00463 conf.lpf_gyro = 0.05f; 00464 conf.lpf_mag = 0.1f; 00465 conf.lpf_mean = 0.01f; 00466 00467 // startup calibration length 00468 conf.startup_calib_gyro_threshold = 0.5f; 00469 conf.startup_calib_duration_s = 10.0f; 00470 00471 return conf; 00472 } 00473 00474 #endif /* IMU_HPP_ */