http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTFusionKalman4.cpp ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTFusionKalman4.cpp b/thirdparty/RTIMULib/RTIMULib/RTFusionKalman4.cpp new file mode 100644 index 0000000..78c099f --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTFusionKalman4.cpp @@ -0,0 +1,238 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#include "RTFusionKalman4.h" +#include "RTIMUSettings.h" + +// The QVALUE affects the gyro response. + +#define KALMAN_QVALUE 0.001f + +// The RVALUE controls the influence of the accels and compass. +// The bigger the value, the more sluggish the response. + +#define KALMAN_RVALUE 0.0005f + +#define KALMAN_QUATERNION_LENGTH 4 + +#define KALMAN_STATE_LENGTH 4 // just the quaternion for the moment + + +RTFusionKalman4::RTFusionKalman4() +{ + reset(); +} + +RTFusionKalman4::~RTFusionKalman4() +{ +} + +void RTFusionKalman4::reset() +{ + m_firstTime = true; + m_fusionPose = RTVector3(); + m_fusionQPose.fromEuler(m_fusionPose); + m_gyro = RTVector3(); + m_accel = RTVector3(); + m_compass = RTVector3(); + m_measuredPose = RTVector3(); + m_measuredQPose.fromEuler(m_measuredPose); + m_Rk.fill(0); + m_Q.fill(0); + + // initialize process noise covariance matrix + + for (int i = 0; i < KALMAN_STATE_LENGTH; i++) + for (int j = 0; j < KALMAN_STATE_LENGTH; j++) + m_Q.setVal(i, i, KALMAN_QVALUE); + + // initialize observation noise covariance matrix + + + for (int i = 0; i < KALMAN_STATE_LENGTH; i++) + for (int j = 0; j < KALMAN_STATE_LENGTH; j++) + m_Rk.setVal(i, i, KALMAN_RVALUE); + } + +void RTFusionKalman4::predict() +{ + RTMatrix4x4 mat; + RTQuaternion tQuat; + RTFLOAT x2, y2, z2; + + // compute the state transition matrix + + x2 = m_gyro.x() / (RTFLOAT)2.0; + y2 = m_gyro.y() / (RTFLOAT)2.0; + z2 = m_gyro.z() / (RTFLOAT)2.0; + + m_Fk.setVal(0, 1, -x2); + m_Fk.setVal(0, 2, -y2); + m_Fk.setVal(0, 3, -z2); + + m_Fk.setVal(1, 0, x2); + m_Fk.setVal(1, 2, z2); + m_Fk.setVal(1, 3, -y2); + + m_Fk.setVal(2, 0, y2); + m_Fk.setVal(2, 1, -z2); + m_Fk.setVal(2, 3, x2); + + m_Fk.setVal(3, 0, z2); + m_Fk.setVal(3, 1, y2); + m_Fk.setVal(3, 2, -x2); + + m_FkTranspose = m_Fk.transposed(); + + // Predict new state estimate Xkk_1 = Fk * Xk_1k_1 + + tQuat = m_Fk * m_stateQ; + tQuat *= m_timeDelta; + m_stateQ += tQuat; + +// m_stateQ.normalize(); + + // Compute PDot = Fk * Pk_1k_1 + Pk_1k_1 * FkTranspose (note Pkk == Pk_1k_1 at this stage) + + m_PDot = m_Fk * m_Pkk; + mat = m_Pkk * m_FkTranspose; + m_PDot += mat; + + // add in Q to get the new prediction + + m_Pkk_1 = m_PDot + m_Q; + + // multiply by deltaTime (variable name is now misleading though) + + m_Pkk_1 *= m_timeDelta; +} + + +void RTFusionKalman4::update() +{ + RTQuaternion delta; + RTMatrix4x4 Sk, SkInverse; + + if (m_enableCompass || m_enableAccel) { + m_stateQError = m_measuredQPose - m_stateQ; + } else { + m_stateQError = RTQuaternion(); + } + + // Compute residual covariance Sk = Hk * Pkk_1 * HkTranspose + Rk + // Note: since Hk is the identity matrix, this has been simplified + + Sk = m_Pkk_1 + m_Rk; + + // Compute Kalman gain Kk = Pkk_1 * HkTranspose * SkInverse + // Note: again, the HkTranspose part is omitted + + SkInverse = Sk.inverted(); + + m_Kk = m_Pkk_1 * SkInverse; + + if (m_debug) + HAL_INFO(RTMath::display("Gain", m_Kk)); + + // make new state estimate + + delta = m_Kk * m_stateQError; + + m_stateQ += delta; + + m_stateQ.normalize(); + + // produce new estimate covariance Pkk = (I - Kk * Hk) * Pkk_1 + // Note: since Hk is the identity matrix, it is omitted + + m_Pkk.setToIdentity(); + m_Pkk -= m_Kk; + m_Pkk = m_Pkk * m_Pkk_1; + + if (m_debug) + HAL_INFO(RTMath::display("Cov", m_Pkk)); +} + +void RTFusionKalman4::newIMUData(RTIMU_DATA& data, const RTIMUSettings *settings) +{ + if (m_enableGyro) + m_gyro = data.gyro; + else + m_gyro = RTVector3(); + m_accel = data.accel; + m_compass = data.compass; + m_compassValid = data.compassValid; + + if (m_firstTime) { + m_lastFusionTime = data.timestamp; + calculatePose(m_accel, m_compass, settings->m_compassAdjDeclination); + m_Fk.fill(0); + + // init covariance matrix to something + + m_Pkk.fill(0); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + m_Pkk.setVal(i,j, 0.5); + + // initialize the observation model Hk + // Note: since the model is the state vector, this is an identity matrix so it won't be used + + // initialize the poses + + m_stateQ.fromEuler(m_measuredPose); + m_fusionQPose = m_stateQ; + m_fusionPose = m_measuredPose; + m_firstTime = false; + } else { + m_timeDelta = (RTFLOAT)(data.timestamp - m_lastFusionTime) / (RTFLOAT)1000000; + m_lastFusionTime = data.timestamp; + if (m_timeDelta <= 0) + return; + + if (m_debug) { + HAL_INFO("\n------\n"); + HAL_INFO1("IMU update delta time: %f\n", m_timeDelta); + } + + calculatePose(data.accel, data.compass, settings->m_compassAdjDeclination); + + predict(); + update(); + m_stateQ.toEuler(m_fusionPose); + m_fusionQPose = m_stateQ; + + if (m_debug) { + HAL_INFO(RTMath::displayRadians("Measured pose", m_measuredPose)); + HAL_INFO(RTMath::displayRadians("Kalman pose", m_fusionPose)); + HAL_INFO(RTMath::displayRadians("Measured quat", m_measuredPose)); + HAL_INFO(RTMath::display("Kalman quat", m_stateQ)); + HAL_INFO(RTMath::display("Error quat", m_stateQError)); + } + } + data.fusionPoseValid = true; + data.fusionQPoseValid = true; + data.fusionPose = m_fusionPose; + data.fusionQPose = m_fusionQPose; +}
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTFusionKalman4.h ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTFusionKalman4.h b/thirdparty/RTIMULib/RTIMULib/RTFusionKalman4.h new file mode 100644 index 0000000..245ae6f --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTFusionKalman4.h @@ -0,0 +1,79 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef _RTFUSIONKALMAN4_H +#define _RTFUSIONKALMAN4_H + +#include "RTFusion.h" + +class RTFusionKalman4 : public RTFusion +{ +public: + RTFusionKalman4(); + ~RTFusionKalman4(); + + // fusionType returns the type code of the fusion algorithm + + virtual int fusionType() { return RTFUSION_TYPE_KALMANSTATE4; } + + // reset() resets the kalman state but keeps any setting changes (such as enables) + + void reset(); + + // newIMUData() should be called for subsequent updates + // deltaTime is in units of seconds + + void newIMUData(RTIMU_DATA& data, const RTIMUSettings *settings); + + // the following two functions can be called to customize the covariance matrices + + void setQMatrix(RTMatrix4x4 Q) { m_Q = Q; reset();} + void setRkMatrix(RTMatrix4x4 Rk) { m_Rk = Rk; reset();} + +private: + void predict(); + void update(); + + RTVector3 m_gyro; // unbiased gyro data + RTFLOAT m_timeDelta; // time between predictions + + RTQuaternion m_stateQ; // quaternion state vector + RTQuaternion m_stateQError; // difference between stateQ and measuredQ + + RTMatrix4x4 m_Kk; // the Kalman gain matrix + RTMatrix4x4 m_Pkk_1; // the predicted estimated covariance matrix + RTMatrix4x4 m_Pkk; // the updated estimated covariance matrix + RTMatrix4x4 m_PDot; // the derivative of the covariance matrix + RTMatrix4x4 m_Q; // process noise covariance + RTMatrix4x4 m_Fk; // the state transition matrix + RTMatrix4x4 m_FkTranspose; // the state transition matrix transposed + RTMatrix4x4 m_Rk; // the measurement noise covariance + + // Note: SInce Hk ends up being the identity matrix, these are omitted + +// RTMatrix4x4 m_Hk; // map from state to measurement +// RTMatrix4x4> m_HkTranspose; // transpose of map +}; + +#endif // _RTFUSIONKALMAN4_H http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTFusionRTQF.cpp ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTFusionRTQF.cpp b/thirdparty/RTIMULib/RTIMULib/RTFusionRTQF.cpp new file mode 100644 index 0000000..3842d6e --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTFusionRTQF.cpp @@ -0,0 +1,163 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#include "RTFusionRTQF.h" +#include "RTIMUSettings.h" + + +RTFusionRTQF::RTFusionRTQF() +{ + reset(); +} + +RTFusionRTQF::~RTFusionRTQF() +{ +} + +void RTFusionRTQF::reset() +{ + m_firstTime = true; + m_fusionPose = RTVector3(); + m_fusionQPose.fromEuler(m_fusionPose); + m_gyro = RTVector3(); + m_accel = RTVector3(); + m_compass = RTVector3(); + m_measuredPose = RTVector3(); + m_measuredQPose.fromEuler(m_measuredPose); + m_sampleNumber = 0; + } + +void RTFusionRTQF::predict() +{ + RTFLOAT x2, y2, z2; + RTFLOAT qs, qx, qy,qz; + + if (!m_enableGyro) + return; + + qs = m_stateQ.scalar(); + qx = m_stateQ.x(); + qy = m_stateQ.y(); + qz = m_stateQ.z(); + + x2 = m_gyro.x() / (RTFLOAT)2.0; + y2 = m_gyro.y() / (RTFLOAT)2.0; + z2 = m_gyro.z() / (RTFLOAT)2.0; + + // Predict new state + + m_stateQ.setScalar(qs + (-x2 * qx - y2 * qy - z2 * qz) * m_timeDelta); + m_stateQ.setX(qx + (x2 * qs + z2 * qy - y2 * qz) * m_timeDelta); + m_stateQ.setY(qy + (y2 * qs - z2 * qx + x2 * qz) * m_timeDelta); + m_stateQ.setZ(qz + (z2 * qs + y2 * qx - x2 * qy) * m_timeDelta); + m_stateQ.normalize(); +} + + +void RTFusionRTQF::update() +{ + if (m_enableCompass || m_enableAccel) { + + // calculate rotation delta + + m_rotationDelta = m_stateQ.conjugate() * m_measuredQPose; + m_rotationDelta.normalize(); + + // take it to the power (0 to 1) to give the desired amount of correction + + RTFLOAT theta = acos(m_rotationDelta.scalar()); + + RTFLOAT sinPowerTheta = sin(theta * m_slerpPower); + RTFLOAT cosPowerTheta = cos(theta * m_slerpPower); + + m_rotationUnitVector.setX(m_rotationDelta.x()); + m_rotationUnitVector.setY(m_rotationDelta.y()); + m_rotationUnitVector.setZ(m_rotationDelta.z()); + m_rotationUnitVector.normalize(); + + m_rotationPower.setScalar(cosPowerTheta); + m_rotationPower.setX(sinPowerTheta * m_rotationUnitVector.x()); + m_rotationPower.setY(sinPowerTheta * m_rotationUnitVector.y()); + m_rotationPower.setZ(sinPowerTheta * m_rotationUnitVector.z()); + m_rotationPower.normalize(); + + // multiple this by predicted value to get result + + m_stateQ *= m_rotationPower; + m_stateQ.normalize(); + } +} + +void RTFusionRTQF::newIMUData(RTIMU_DATA& data, const RTIMUSettings *settings) +{ + if (m_debug) { + HAL_INFO("\n------\n"); + HAL_INFO2("IMU update delta time: %f, sample %d\n", m_timeDelta, m_sampleNumber++); + } + m_sampleNumber++; + + if (m_enableGyro) + m_gyro = data.gyro; + else + m_gyro = RTVector3(); + m_accel = data.accel; + m_compass = data.compass; + m_compassValid = data.compassValid; + + if (m_firstTime) { + m_lastFusionTime = data.timestamp; + calculatePose(m_accel, m_compass, settings->m_compassAdjDeclination); + + // initialize the poses + + m_stateQ.fromEuler(m_measuredPose); + m_fusionQPose = m_stateQ; + m_fusionPose = m_measuredPose; + m_firstTime = false; + } else { + m_timeDelta = (RTFLOAT)(data.timestamp - m_lastFusionTime) / (RTFLOAT)1000000; + m_lastFusionTime = data.timestamp; + if (m_timeDelta <= 0) + return; + + calculatePose(data.accel, data.compass, settings->m_compassAdjDeclination); + + predict(); + update(); + m_stateQ.toEuler(m_fusionPose); + m_fusionQPose = m_stateQ; + + if (m_debug) { + HAL_INFO(RTMath::displayRadians("Measured pose", m_measuredPose)); + HAL_INFO(RTMath::displayRadians("RTQF pose", m_fusionPose)); + HAL_INFO(RTMath::displayRadians("Measured quat", m_measuredPose)); + HAL_INFO(RTMath::display("RTQF quat", m_stateQ)); + HAL_INFO(RTMath::display("Error quat", m_stateQError)); + } + } + data.fusionPoseValid = true; + data.fusionQPoseValid = true; + data.fusionPose = m_fusionPose; + data.fusionQPose = m_fusionQPose; +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTFusionRTQF.h ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTFusionRTQF.h b/thirdparty/RTIMULib/RTIMULib/RTFusionRTQF.h new file mode 100644 index 0000000..854db34 --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTFusionRTQF.h @@ -0,0 +1,62 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef _RTFUSIONRTQF_H +#define _RTFUSIONRTQF_H + +#include "RTFusion.h" + +class RTFusionRTQF : public RTFusion +{ +public: + RTFusionRTQF(); + ~RTFusionRTQF(); + + // fusionType returns the type code of the fusion algorithm + + virtual int fusionType() { return RTFUSION_TYPE_RTQF; } + + // reset() resets the state but keeps any setting changes (such as enables) + + void reset(); + + // newIMUData() should be called for subsequent updates + // deltaTime is in units of seconds + + void newIMUData(RTIMU_DATA& data, const RTIMUSettings *settings); + +private: + void predict(); + void update(); + + RTVector3 m_gyro; // unbiased gyro data + RTFLOAT m_timeDelta; // time between predictions + + RTQuaternion m_stateQ; // quaternion state vector + RTQuaternion m_stateQError; // difference between stateQ and measuredQ + + int m_sampleNumber; +}; + +#endif // _RTFUSIONRTQF_H http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTIMUAccelCal.cpp ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTIMUAccelCal.cpp b/thirdparty/RTIMULib/RTIMULib/RTIMUAccelCal.cpp new file mode 100644 index 0000000..20f4ec1 --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTIMUAccelCal.cpp @@ -0,0 +1,103 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "RTIMUAccelCal.h" + +// ACCEL_ALPHA control the smoothing - the lower it is, the smoother it is + +#define ACCEL_ALPHA 0.1f + +RTIMUAccelCal::RTIMUAccelCal(RTIMUSettings *settings) +{ + m_settings = settings; + for (int i = 0; i < 3; i++) + m_accelCalEnable[i] = false; +} + +RTIMUAccelCal::~RTIMUAccelCal() +{ + +} + +void RTIMUAccelCal::accelCalInit() +{ + if (m_settings->m_accelCalValid) { + m_accelMin = m_settings->m_accelCalMin; + m_accelMax = m_settings->m_accelCalMax; + } else { + m_accelMin = RTVector3(RTIMUCALDEFS_DEFAULT_MIN, RTIMUCALDEFS_DEFAULT_MIN, RTIMUCALDEFS_DEFAULT_MIN); + m_accelMax = RTVector3(RTIMUCALDEFS_DEFAULT_MAX, RTIMUCALDEFS_DEFAULT_MAX, RTIMUCALDEFS_DEFAULT_MAX); + } +} + +void RTIMUAccelCal::accelCalReset() +{ + for (int i = 0; i < 3; i++) { + if (m_accelCalEnable[i]) { + m_accelMin.setData(i, RTIMUCALDEFS_DEFAULT_MIN); + m_accelMax.setData(i, RTIMUCALDEFS_DEFAULT_MAX); + } + } +} + +void RTIMUAccelCal::accelCalEnable(int axis, bool enable) +{ + m_accelCalEnable[axis] = enable; +} + +void RTIMUAccelCal::newAccelCalData(const RTVector3& data) +{ + + for (int i = 0; i < 3; i++) { + if (m_accelCalEnable[i]) { + m_averageValue.setData(i, (data.data(i) * ACCEL_ALPHA + m_averageValue.data(i) * (1.0 - ACCEL_ALPHA))); + if (m_accelMin.data(i) > m_averageValue.data(i)) + m_accelMin.setData(i, m_averageValue.data(i)); + if (m_accelMax.data(i) < m_averageValue.data(i)) + m_accelMax.setData(i, m_averageValue.data(i)); + } + } +} + +bool RTIMUAccelCal::accelCalValid() +{ + bool valid = true; + + for (int i = 0; i < 3; i++) { + if (m_accelMax.data(i) < m_accelMin.data(i)) + valid = false; + } + return valid; +} + +bool RTIMUAccelCal::accelCalSave() +{ + if (!accelCalValid()) + return false; + + m_settings->m_accelCalValid = true; + m_settings->m_accelCalMin = m_accelMin; + m_settings->m_accelCalMax = m_accelMax; + m_settings->saveSettings(); + return true; +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTIMUAccelCal.h ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTIMUAccelCal.h b/thirdparty/RTIMULib/RTIMULib/RTIMUAccelCal.h new file mode 100644 index 0000000..1595712 --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTIMUAccelCal.h @@ -0,0 +1,74 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef _RTIMUACCELCAL_H +#define _RTIMUACCELCAL_H + +#include "RTIMUCalDefs.h" +#include "RTIMULib.h" + +// RTIMUAccelCal is a helper class for performing accelerometer calibration + +class RTIMUAccelCal +{ + +public: + RTIMUAccelCal(RTIMUSettings *settings); + virtual ~RTIMUAccelCal(); + + // This should be called at the start of the calibration process + // Loads previous values if available + void accelCalInit(); + + // This should be called to clear enabled axes for a new run + void accelCalReset(); + + // accelCalEnable() controls which axes are active - largely so that each can be done separately + void accelCalEnable(int axis, bool enable); + + // newAccalCalData() adds a new sample for processing but only the axes enabled previously + void newAccelCalData(const RTVector3& data); // adds a new accel sample + + // accelCalValid() checks if all values are reasonable. Should be called before saving + bool accelCalValid(); + + // accelCalSave() should be called at the end of the process to save the cal data + // to the settings file. Returns false if invalid data + bool accelCalSave(); // saves the accel cal data for specified axes + + // these vars used during the calibration process + + bool m_accelCalValid; // true if the mag min/max data valid + RTVector3 m_accelMin; // the min values + RTVector3 m_accelMax; // the max values + + RTVector3 m_averageValue; // averaged value actually used + + bool m_accelCalEnable[3]; // the enable flags + + RTIMUSettings *m_settings; + +}; + +#endif // _RTIMUACCELCAL_H http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTIMUCalDefs.h ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTIMUCalDefs.h b/thirdparty/RTIMULib/RTIMULib/RTIMUCalDefs.h new file mode 100644 index 0000000..54a7003 --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTIMUCalDefs.h @@ -0,0 +1,57 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef RTIMUCALDEFS_H +#define RTIMUCALDEFS_H + +#define RTIMUCALDEFS_DEFAULT_MIN 1000 // a large min +#define RTIMUCALDEFS_DEFAULT_MAX -1000 // a small max + +#define RTIMUCALDEFS_MAX_MAG_SAMPLES 20000 // max saved mag records + +#define RTIMUCALDEFS_OCTANT_MIN_SAMPLES 200 // must have at least this in each octant + +#define RTIMUCALDEFS_ELLIPSOID_MIN_SPACING 0.1f // min distnace between ellipsoid samples to be recorded + +// Octant defs + +#define RTIMUCALDEFS_OCTANT_COUNT 8 // there are 8 octants of course + +#define RTIMUCALDEFS_OCTANT_NNN 0 // x, y, z all negative +#define RTIMUCALDEFS_OCTANT_PNN 1 // x positive - y, z neagtive +#define RTIMUCALDEFS_OCTANT_NPN 2 // y positive - x, z negative +#define RTIMUCALDEFS_OCTANT_PPN 3 // x, y positive - z negative +#define RTIMUCALDEFS_OCTANT_NNP 4 // z positive - x, y negative +#define RTIMUCALDEFS_OCTANT_PNP 5 // x, z positive - y negative +#define RTIMUCALDEFS_OCTANT_NPP 6 // y, z positive - x negative +#define RTIMUCALDEFS_OCTANT_PPP 7 // x, y, z all positive + +// File name for Octave processing + +#define RTIMUCALDEFS_MAG_RAW_FILE "magRaw.dta" // the raw sample file - input to ellispoid fit code +#define RTIMUCALDEFS_MAG_CORR_FILE "magCorr.dta" // the output from the ellipsoid fit code + +#define RTIMUCALDEFS_OCTAVE_CODE "RTEllipsoidFit.m" +#define RTIMUCALDEFS_OCTAVE_COMMAND "octave RTEllipsoidFit.m" + +#endif // RTIMUCALDEFS_H http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTIMUHal.cpp ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTIMUHal.cpp b/thirdparty/RTIMULib/RTIMULib/RTIMUHal.cpp new file mode 100644 index 0000000..e70d916 --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTIMUHal.cpp @@ -0,0 +1,407 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// The MPU-9250 and SPI driver code is based on code generously supplied by +// stasl...@gmail.com (www.clickdrive.io) + +#include "IMUDrivers/RTIMU.h" + +#if !defined(WIN32) && !defined(__APPLE__) + +#include <linux/spi/spidev.h> + +RTIMUHal::RTIMUHal() +{ + m_I2CBus = 255; + m_currentSlave = 255; + m_I2C = -1; + m_SPI = -1; + m_SPISpeed = 500000; +} + +RTIMUHal::~RTIMUHal() +{ + HALClose(); +} + +bool RTIMUHal::HALOpen() +{ + char buf[32]; + unsigned char SPIMode = SPI_MODE_0; + unsigned char SPIBits = 8; + uint32_t SPISpeed = m_SPISpeed; + + if (m_busIsI2C) { + if (m_I2C >= 0) + return true; + + if (m_I2CBus == 255) { + HAL_ERROR("No I2C bus has been set\n"); + return false; + } + sprintf(buf, "/dev/i2c-%d", m_I2CBus); + m_I2C = open(buf, O_RDWR); + if (m_I2C < 0) { + HAL_ERROR1("Failed to open I2C bus %d\n", m_I2CBus); + m_I2C = -1; + return false; + } + } else { + if (m_SPIBus == 255) { + HAL_ERROR("No SPI bus has been set\n"); + return false; + } + + sprintf(buf, "/dev/spidev%d.%d", m_SPIBus, m_SPISelect); + m_SPI = open(buf, O_RDWR); + if (m_SPI < 0) { + HAL_ERROR2("Failed to open SPI bus %d, select %d\n", m_SPIBus, m_SPISelect); + m_SPI = -1; + return false; + } + + if (ioctl(m_SPI, SPI_IOC_WR_MODE, &SPIMode) < 0) { + HAL_ERROR1("Failed to set WR SPI_MODE0 on bus %d", m_SPIBus); + close(m_SPIBus); + return false; + } + + if (ioctl(m_SPI, SPI_IOC_RD_MODE, &SPIMode) < 0) { + HAL_ERROR1("Failed to set RD SPI_MODE0 on bus %d", m_SPIBus); + close(m_SPIBus); + return false; + } + + if (ioctl(m_SPI, SPI_IOC_WR_BITS_PER_WORD, &SPIBits) < 0) { + HAL_ERROR1("Failed to set WR 8 bit mode on bus %d", m_SPIBus); + close(m_SPIBus); + return false; + } + + if (ioctl(m_SPI, SPI_IOC_RD_BITS_PER_WORD, &SPIBits) < 0) { + HAL_ERROR1("Failed to set RD 8 bit mode on bus %d", m_SPIBus); + close(m_SPIBus); + return false; + } + + if (ioctl(m_SPI, SPI_IOC_WR_MAX_SPEED_HZ, &SPISpeed) < 0) { + HAL_ERROR2("Failed to set WR %dHz on bus %d", SPISpeed, m_SPIBus); + close(m_SPIBus); + return false; + } + + if (ioctl(m_SPI, SPI_IOC_RD_MAX_SPEED_HZ, &SPISpeed) < 0) { + HAL_ERROR2("Failed to set RD %dHz on bus %d", SPISpeed, m_SPIBus); + close(m_SPIBus); + return false; + } + } + return true; +} + +void RTIMUHal::HALClose() +{ + I2CClose(); + SPIClose(); +} + +void RTIMUHal::I2CClose() +{ + if (m_I2C >= 0) { + close(m_I2C); + m_I2C = -1; + m_currentSlave = 255; + } +} + +void RTIMUHal::SPIClose() +{ + if (m_SPI >= 0) { + close(m_SPI); + m_SPI = -1; + } +} + +bool RTIMUHal::HALWrite(unsigned char slaveAddr, unsigned char regAddr, + unsigned char const data, const char *errorMsg) +{ + return HALWrite(slaveAddr, regAddr, 1, &data, errorMsg); +} + +bool RTIMUHal::HALWrite(unsigned char slaveAddr, unsigned char regAddr, + unsigned char length, unsigned char const *data, const char *errorMsg) +{ + int result; + unsigned char txBuff[MAX_WRITE_LEN + 1]; + char *ifType; + + if (m_busIsI2C) { + if (!I2CSelectSlave(slaveAddr, errorMsg)) + return false; + ifType = (char *)"I2C"; + } else { + ifType = (char *)"SPI"; + } + + if (length == 0) { + result = ifWrite(®Addr, 1); + + if (result < 0) { + if (strlen(errorMsg) > 0) + HAL_ERROR2("%s write of regAddr failed - %s\n", ifType, errorMsg); + return false; + } else if (result != 1) { + if (strlen(errorMsg) > 0) + HAL_ERROR2("%s write of regAddr failed (nothing written) - %s\n", ifType, errorMsg); + return false; + } + } else { + txBuff[0] = regAddr; + memcpy(txBuff + 1, data, length); + + result = ifWrite(txBuff, length + 1); + + if (result < 0) { + if (strlen(errorMsg) > 0) + HAL_ERROR3("%s data write of %d bytes failed - %s\n", ifType, length, errorMsg); + return false; + } else if (result < (int)length) { + if (strlen(errorMsg) > 0) + HAL_ERROR4("%s data write of %d bytes failed, only %d written - %s\n", ifType, length, result, errorMsg); + return false; + } + } + return true; +} + +bool RTIMUHal::ifWrite(unsigned char *data, unsigned char length) +{ + struct spi_ioc_transfer wrIOC; + + if (m_busIsI2C) { + return write(m_I2C, data, length); + } else { + memset(&wrIOC, 0, sizeof(wrIOC)); + wrIOC.tx_buf = (unsigned long) data; + wrIOC.rx_buf = 0; + wrIOC.len = length; + return ioctl(m_SPI, SPI_IOC_MESSAGE(1), &wrIOC); + } +} + + +bool RTIMUHal::HALRead(unsigned char slaveAddr, unsigned char regAddr, unsigned char length, + unsigned char *data, const char *errorMsg) +{ + int tries, result, total; + unsigned char rxBuff[MAX_READ_LEN + 1]; + struct spi_ioc_transfer rdIOC; + + if (m_busIsI2C) { + if (!HALWrite(slaveAddr, regAddr, 0, NULL, errorMsg)) + return false; + + total = 0; + tries = 0; + + while ((total < length) && (tries < 5)) { + result = read(m_I2C, data + total, length - total); + + if (result < 0) { + if (strlen(errorMsg) > 0) + HAL_ERROR3("I2C read error from %d, %d - %s\n", slaveAddr, regAddr, errorMsg); + return false; + } + + total += result; + + if (total == length) + break; + + delayMs(10); + tries++; + } + + if (total < length) { + if (strlen(errorMsg) > 0) + HAL_ERROR3("I2C read from %d, %d failed - %s\n", slaveAddr, regAddr, errorMsg); + return false; + } + } else { + rxBuff[0] = regAddr | 0x80; + memcpy(rxBuff + 1, data, length); + memset(&rdIOC, 0, sizeof(rdIOC)); + rdIOC.tx_buf = (unsigned long) rxBuff; + rdIOC.rx_buf = (unsigned long) rxBuff; + rdIOC.len = length + 1; + + if (ioctl(m_SPI, SPI_IOC_MESSAGE(1), &rdIOC) < 0) { + if (strlen(errorMsg) > 0) + HAL_ERROR2("SPI read error from %d - %s\n", regAddr, errorMsg); + return false; + } + memcpy(data, rxBuff + 1, length); + } + return true; +} + +bool RTIMUHal::HALRead(unsigned char slaveAddr, unsigned char length, + unsigned char *data, const char *errorMsg) +{ + int tries, result, total; + unsigned char rxBuff[MAX_READ_LEN + 1]; + struct spi_ioc_transfer rdIOC; + + if (m_busIsI2C) { + if (!I2CSelectSlave(slaveAddr, errorMsg)) + return false; + + total = 0; + tries = 0; + + while ((total < length) && (tries < 5)) { + result = read(m_I2C, data + total, length - total); + + if (result < 0) { + if (strlen(errorMsg) > 0) + HAL_ERROR2("I2C read error from %d - %s\n", slaveAddr, errorMsg); + return false; + } + + total += result; + + if (total == length) + break; + + delayMs(10); + tries++; + } + + if (total < length) { + if (strlen(errorMsg) > 0) + HAL_ERROR2("I2C read from %d failed - %s\n", slaveAddr, errorMsg); + return false; + } + } else { + memset(&rdIOC, 0, sizeof(rdIOC)); + rdIOC.tx_buf = 0; + rdIOC.rx_buf = (unsigned long) rxBuff; + rdIOC.len = length; + + if (ioctl(m_SPI, SPI_IOC_MESSAGE(1), &rdIOC) < 0) { + if (strlen(errorMsg) > 0) + HAL_ERROR1("SPI read error from - %s\n", errorMsg); + return false; + } + memcpy(data, rxBuff, length); + } + return true; +} + + +bool RTIMUHal::I2CSelectSlave(unsigned char slaveAddr, const char *errorMsg) +{ + if (m_currentSlave == slaveAddr) + return true; + + if (!HALOpen()) { + HAL_ERROR1("Failed to open I2C port - %s\n", errorMsg); + return false; + } + + if (ioctl(m_I2C, I2C_SLAVE, slaveAddr) < 0) { + HAL_ERROR2("I2C slave select %d failed - %s\n", slaveAddr, errorMsg); + return false; + } + + m_currentSlave = slaveAddr; + + return true; +} + +void RTIMUHal::delayMs(int milliSeconds) +{ + usleep(1000 * milliSeconds); +} + +#else +// just dummy routines for Windows + +RTIMUHal::RTIMUHal() +{ +} + +RTIMUHal::~RTIMUHal() +{ +} + + +bool RTIMUHal::HALOpen() +{ + return true; +} + +void RTIMUHal::HALClose() +{ +} + +void RTIMUHal::I2CClose() +{ +} + +bool RTIMUHal::HALWrite(unsigned char , unsigned char , + unsigned char const , const char *) +{ + return true; +} + +bool RTIMUHal::HALWrite(unsigned char , unsigned char , + unsigned char , unsigned char const *, const char *) +{ + return true; +} + + +bool RTIMUHal::HALRead(unsigned char , unsigned char , unsigned char , + unsigned char *, const char *) +{ + return true; +} + +bool RTIMUHal::HALRead(unsigned char slaveAddr, unsigned char length, + unsigned char *data, const char *errorMsg) +{ + return true; +} + + +bool RTIMUHal::I2CSelectSlave(unsigned char , const char *) +{ + return true; +} + +void RTIMUHal::delayMs(int milliSeconds) +{ +} +#endif + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTIMUHal.h ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTIMUHal.h b/thirdparty/RTIMULib/RTIMULib/RTIMUHal.h new file mode 100644 index 0000000..c3e4d75 --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTIMUHal.h @@ -0,0 +1,116 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// The MPU-9250 and SPI driver code is based on code generously supplied by +// stasl...@gmail.com (www.clickdrive.io) + +#ifndef _RTIMUHAL_H +#define _RTIMUHAL_H + +#include <stdio.h> +#include <math.h> +#include <stdint.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +#ifndef HAL_QUIET +#define HAL_INFO(m) { printf("%s", m); fflush(stdout); } +#define HAL_INFO1(m, x) { printf(m, x); fflush(stdout); } +#define HAL_INFO2(m, x, y) { printf(m, x, y); fflush(stdout); } +#define HAL_INFO3(m, x, y, z) { printf(m, x, y, z); fflush(stdout); } +#define HAL_INFO4(m, x, y, z, a) { printf(m, x, y, z, a); fflush(stdout); } +#define HAL_INFO5(m, x, y, z, a, b) { printf(m, x, y, z, a, b); fflush(stdout); } +#define HAL_ERROR(m) fprintf(stderr, m); +#define HAL_ERROR1(m, x) fprintf(stderr, m, x); +#define HAL_ERROR2(m, x, y) fprintf(stderr, m, x, y); +#define HAL_ERROR3(m, x, y, z) fprintf(stderr, m, x, y, z); +#define HAL_ERROR4(m, x, y, z, a) fprintf(stderr, m, x, y, z, a); + +#else + +#define HAL_INFO(m) +#define HAL_INFO1(m, x) +#define HAL_INFO2(m, x, y) +#define HAL_INFO3(m, x, y, z) +#define HAL_INFO4(m, x, y, z, a) +#define HAL_INFO5(m, x, y, z, a, b) +#define HAL_ERROR(m) +#define HAL_ERROR1(m, x) +#define HAL_ERROR2(m, x, y) +#define HAL_ERROR3(m, x, y, z) +#define HAL_ERROR4(m, x, y, z, a) + +#endif + +#if !defined(WIN32) && !defined(__APPLE__) +#include <sys/ioctl.h> +#include <linux/i2c-dev.h> +#endif + +#if !defined(WIN32) +#include <unistd.h> +#include <sys/time.h> +#endif + +#define MAX_WRITE_LEN 255 +#define MAX_READ_LEN 255 + +class RTIMUHal +{ +public: + RTIMUHal(); + virtual ~RTIMUHal(); + + bool m_busIsI2C; // true if I2C bus in use, false if SPI in use + unsigned char m_I2CBus; // I2C bus of the imu (eg 1 for Raspberry Pi usually) + unsigned char m_SPIBus; // SPI bus of the imu (eg 0 for Raspberry Pi usually) + unsigned char m_SPISelect; // SPI select line - defaults to CE0 + unsigned int m_SPISpeed; // speed of interface + + bool HALOpen(); + void HALClose(); + bool HALRead(unsigned char slaveAddr, unsigned char regAddr, unsigned char length, + unsigned char *data, const char *errorMsg); // normal read with register select + bool HALRead(unsigned char slaveAddr, unsigned char length, + unsigned char *data, const char *errorMsg); // read without register select + bool HALWrite(unsigned char slaveAddr, unsigned char regAddr, + unsigned char length, unsigned char const *data, const char *errorMsg); + bool HALWrite(unsigned char slaveAddr, unsigned char regAddr, + unsigned char const data, const char *errorMsg); + + void delayMs(int milliSeconds); + +protected: + void I2CClose(); + bool I2CSelectSlave(unsigned char slaveAddr, const char *errorMsg); + void SPIClose(); + bool ifWrite(unsigned char *data, unsigned char length); + +private: + int m_I2C; + unsigned char m_currentSlave; + int m_SPI; +}; + +#endif // _RTIMUHAL_H http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTIMULIB LICENSE ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTIMULIB LICENSE b/thirdparty/RTIMULib/RTIMULib/RTIMULIB LICENSE new file mode 100644 index 0000000..cb4ed27 --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTIMULIB LICENSE @@ -0,0 +1,26 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// The MPU-9250 and SPI driver code is based on code generously supplied by +// stasl...@gmail.com (www.clickdrive.io) + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTIMULib.h ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTIMULib.h b/thirdparty/RTIMULib/RTIMULib/RTIMULib.h new file mode 100644 index 0000000..cf851bb --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTIMULib.h @@ -0,0 +1,54 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef _RTIMULIB_H +#define _RTIMULIB_H + +#include "RTIMULibDefs.h" + +#include "RTMath.h" + +#include "RTFusion.h" +#include "RTFusionKalman4.h" + +#include "RTIMUHal.h" +#include "IMUDrivers/RTIMU.h" +#include "IMUDrivers/RTIMUNull.h" +#include "IMUDrivers/RTIMUMPU9150.h" +#include "IMUDrivers/RTIMUGD20HM303D.h" +#include "IMUDrivers/RTIMUGD20M303DLHC.h" +#include "IMUDrivers/RTIMULSM9DS0.h" + +#include "IMUDrivers/RTPressure.h" +#include "IMUDrivers/RTPressureBMP180.h" +#include "IMUDrivers/RTPressureLPS25H.h" +#include "IMUDrivers/RTPressureMS5611.h" + +#include "IMUDrivers/RTHumidity.h" +#include "IMUDrivers/RTHumidityHTS221.h" + +#include "RTIMUSettings.h" + + +#endif // _RTIMULIB_H http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTIMULib.pri ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTIMULib.pri b/thirdparty/RTIMULib/RTIMULib/RTIMULib.pri new file mode 100644 index 0000000..70b1da3 --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTIMULib.pri @@ -0,0 +1,90 @@ +#//////////////////////////////////////////////////////////////////////////// +#// +#// This file is part of RTIMULib +#// +#// Copyright (c) 2014-2015, richards-tech, LLC +#// +#// Permission is hereby granted, free of charge, to any person obtaining a copy of +#// this software and associated documentation files (the "Software"), to deal in +#// the Software without restriction, including without limitation the rights to use, +#// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +#// Software, and to permit persons to whom the Software is furnished to do so, +#// subject to the following conditions: +#// +#// The above copyright notice and this permission notice shall be included in all +#// copies or substantial portions of the Software. +#// +#// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +#// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +#// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +#// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +#// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD + +HEADERS += $$PWD/RTIMULib.h \ + $$PWD/RTIMULibDefs.h \ + $$PWD/RTMath.h \ + $$PWD/RTIMUHal.h \ + $$PWD/RTFusion.h \ + $$PWD/RTFusionKalman4.h \ + $$PWD/RTFusionRTQF.h \ + $$PWD/RTIMUSettings.h \ + $$PWD/RTIMUMagCal.h \ + $$PWD/RTIMUAccelCal.h \ + $$PWD/RTIMUCalDefs.h \ + $$PWD/IMUDrivers/RTIMU.h \ + $$PWD/IMUDrivers/RTIMUDefs.h \ + $$PWD/IMUDrivers/RTIMUMPU9150.h \ + $$PWD/IMUDrivers/RTIMUMPU9250.h \ + $$PWD/IMUDrivers/RTIMUGD20HM303D.h \ + $$PWD/IMUDrivers/RTIMUGD20M303DLHC.h \ + $$PWD/IMUDrivers/RTIMUGD20HM303DLHC.h \ + $$PWD/IMUDrivers/RTIMULSM9DS0.h \ + $$PWD/IMUDrivers/RTIMULSM9DS1.h \ + $$PWD/IMUDrivers/RTIMUBMX055.h \ + $$PWD/IMUDrivers/RTIMUBNO055.h \ + $$PWD/IMUDrivers/RTIMUNull.h \ + $$PWD/IMUDrivers/RTPressure.h \ + $$PWD/IMUDrivers/RTPressureDefs.h \ + $$PWD/IMUDrivers/RTPressureBMP180.h \ + $$PWD/IMUDrivers/RTPressureLPS25H.h \ + $$PWD/IMUDrivers/RTPressureMS5611.h \ + $$PWD/IMUDrivers/RTPressureMS5637.h \ + $$PWD/IMUDrivers/RTHumidity.h \ + $$PWD/IMUDrivers/RTHumidityDefs.h \ + $$PWD/IMUDrivers/RTHumidityHTS221.h \ + $$PWD/IMUDrivers/RTHumidityHTU21D.h \ + +SOURCES += $$PWD/RTMath.cpp \ + $$PWD/RTIMUHal.cpp \ + $$PWD/RTFusion.cpp \ + $$PWD/RTFusionKalman4.cpp \ + $$PWD/RTFusionRTQF.cpp \ + $$PWD/RTIMUSettings.cpp \ + $$PWD/RTIMUMagCal.cpp \ + $$PWD/RTIMUAccelCal.cpp \ + $$PWD/IMUDrivers/RTIMU.cpp \ + $$PWD/IMUDrivers/RTIMUMPU9150.cpp \ + $$PWD/IMUDrivers/RTIMUMPU9250.cpp \ + $$PWD/IMUDrivers/RTIMUGD20HM303D.cpp \ + $$PWD/IMUDrivers/RTIMUGD20M303DLHC.cpp \ + $$PWD/IMUDrivers/RTIMUGD20HM303DLHC.cpp \ + $$PWD/IMUDrivers/RTIMULSM9DS0.cpp \ + $$PWD/IMUDrivers/RTIMULSM9DS1.cpp \ + $$PWD/IMUDrivers/RTIMUBMX055.cpp \ + $$PWD/IMUDrivers/RTIMUBNO055.cpp \ + $$PWD/IMUDrivers/RTIMUNull.cpp \ + $$PWD/IMUDrivers/RTPressure.cpp \ + $$PWD/IMUDrivers/RTPressureBMP180.cpp \ + $$PWD/IMUDrivers/RTPressureLPS25H.cpp \ + $$PWD/IMUDrivers/RTPressureMS5611.cpp \ + $$PWD/IMUDrivers/RTPressureMS5637.cpp \ + $$PWD/IMUDrivers/RTHumidity.cpp \ + $$PWD/IMUDrivers/RTHumidityHTS221.cpp \ + $$PWD/IMUDrivers/RTHumidityHTU21D.cpp \ + + + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTIMULibDefs.h ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTIMULibDefs.h b/thirdparty/RTIMULib/RTIMULib/RTIMULibDefs.h new file mode 100644 index 0000000..0157258 --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTIMULibDefs.h @@ -0,0 +1,64 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// The MPU-9250 and SPI driver code is based on code generously supplied by +// stasl...@gmail.com (www.clickdrive.io) + +#ifndef _RTIMULIBDEFS_H +#define _RTIMULIBDEFS_H + +#include "RTMath.h" +#include "IMUDrivers/RTIMUDefs.h" + +// these defines describe the various fusion filter options + +#define RTFUSION_TYPE_NULL 0 // just a dummy to keep things happy if not needed +#define RTFUSION_TYPE_KALMANSTATE4 1 // kalman state is the quaternion pose +#define RTFUSION_TYPE_RTQF 2 // RT quaternion fusion + +#define RTFUSION_TYPE_COUNT 3 // number of fusion algorithm types + +// This is a convenience structure that can be used to pass IMU data around + +typedef struct +{ + uint64_t timestamp; + bool fusionPoseValid; + RTVector3 fusionPose; + bool fusionQPoseValid; + RTQuaternion fusionQPose; + bool gyroValid; + RTVector3 gyro; + bool accelValid; + RTVector3 accel; + bool compassValid; + RTVector3 compass; + bool pressureValid; + RTFLOAT pressure; + bool temperatureValid; + RTFLOAT temperature; + bool humidityValid; + RTFLOAT humidity; +} RTIMU_DATA; + +#endif // _RTIMULIBDEFS_H http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTIMUMagCal.cpp ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTIMUMagCal.cpp b/thirdparty/RTIMULib/RTIMULib/RTIMUMagCal.cpp new file mode 100644 index 0000000..d61e021 --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTIMUMagCal.cpp @@ -0,0 +1,260 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#include "RTIMUMagCal.h" + +RTIMUMagCal::RTIMUMagCal(RTIMUSettings *settings) +{ + m_settings = settings; +} + +RTIMUMagCal::~RTIMUMagCal() +{ + +} + +void RTIMUMagCal::magCalInit() +{ + magCalReset(); +} + +void RTIMUMagCal::magCalReset() +{ + m_magMin = RTVector3(RTIMUCALDEFS_DEFAULT_MIN, RTIMUCALDEFS_DEFAULT_MIN, RTIMUCALDEFS_DEFAULT_MIN); + m_magMax = RTVector3(RTIMUCALDEFS_DEFAULT_MAX, RTIMUCALDEFS_DEFAULT_MAX, RTIMUCALDEFS_DEFAULT_MAX); + + m_magCalCount = 0; + for (int i = 0; i < RTIMUCALDEFS_OCTANT_COUNT; i++) + m_octantCounts[i] = 0; + m_magCalInIndex = m_magCalOutIndex = 0; + + // throw away first few samples so we don't see any old calibrated samples + m_startCount = 100; +} + +void RTIMUMagCal::newMinMaxData(const RTVector3& data) +{ + if (m_startCount > 0) { + m_startCount--; + return; + } + + for (int i = 0; i < 3; i++) { + if (m_magMin.data(i) > data.data(i)) { + m_magMin.setData(i, data.data(i)); + } + + if (m_magMax.data(i) < data.data(i)) { + m_magMax.setData(i, data.data(i)); + } + } +} + +bool RTIMUMagCal::magCalValid() +{ + bool valid = true; + + for (int i = 0; i < 3; i++) { + if (m_magMax.data(i) < m_magMin.data(i)) + valid = false; + } + return valid; + +} + +void RTIMUMagCal::magCalSaveMinMax() +{ + m_settings->m_compassCalValid = true; + m_settings->m_compassCalMin = m_magMin; + m_settings->m_compassCalMax = m_magMax; + m_settings->m_compassCalEllipsoidValid = false; + m_settings->saveSettings(); + + // need to invalidate ellipsoid data in order to use new min/max data + + m_magCalCount = 0; + for (int i = 0; i < RTIMUCALDEFS_OCTANT_COUNT; i++) + m_octantCounts[i] = 0; + m_magCalInIndex = m_magCalOutIndex = 0; + + // and set up for min/max calibration + + setMinMaxCal(); +} + +void RTIMUMagCal::newEllipsoidData(const RTVector3& data) +{ + RTVector3 calData; + + // do min/max calibration first + + for (int i = 0; i < 3; i++) + calData.setData(i, (data.data(i) - m_minMaxOffset.data(i)) * m_minMaxScale.data(i)); + + // now see if it's already there - we want them all unique and slightly separate (using a fuzzy compare) + + for (int index = m_magCalOutIndex, i = 0; i < m_magCalCount; i++) { + if ((abs(calData.x() - m_magCalSamples[index].x()) < RTIMUCALDEFS_ELLIPSOID_MIN_SPACING) && + (abs(calData.y() - m_magCalSamples[index].y()) < RTIMUCALDEFS_ELLIPSOID_MIN_SPACING) && + (abs(calData.z() - m_magCalSamples[index].z()) < RTIMUCALDEFS_ELLIPSOID_MIN_SPACING)) { + return; // too close to another sample + } + if (++index == RTIMUCALDEFS_MAX_MAG_SAMPLES) + index = 0; + } + + + m_octantCounts[findOctant(calData)]++; + + m_magCalSamples[m_magCalInIndex++] = calData; + if (m_magCalInIndex == RTIMUCALDEFS_MAX_MAG_SAMPLES) + m_magCalInIndex = 0; + + if (++m_magCalCount == RTIMUCALDEFS_MAX_MAG_SAMPLES) { + // buffer is full - pull oldest + removeMagCalData(); + } +} + +bool RTIMUMagCal::magCalEllipsoidValid() +{ + bool valid = true; + + for (int i = 0; i < RTIMUCALDEFS_OCTANT_COUNT; i++) { + if (m_octantCounts[i] < RTIMUCALDEFS_OCTANT_MIN_SAMPLES) + valid = false; + } + return valid; +} + +RTVector3 RTIMUMagCal::removeMagCalData() +{ + RTVector3 ret; + + if (m_magCalCount == 0) + return ret; + + ret = m_magCalSamples[m_magCalOutIndex++]; + if (m_magCalOutIndex == RTIMUCALDEFS_MAX_MAG_SAMPLES) + m_magCalOutIndex = 0; + m_magCalCount--; + m_octantCounts[findOctant(ret)]--; + return ret; +} + +bool RTIMUMagCal::magCalSaveRaw(const char *ellipsoidFitPath) +{ + FILE *file; + char *rawFile; + + if (ellipsoidFitPath != NULL) { + // need to deal with ellipsoid fit processing + rawFile = (char *)malloc(strlen(RTIMUCALDEFS_MAG_RAW_FILE) + strlen(ellipsoidFitPath) + 2); + sprintf(rawFile, "%s/%s", ellipsoidFitPath, RTIMUCALDEFS_MAG_RAW_FILE); + if ((file = fopen(rawFile, "w")) == NULL) { + HAL_ERROR("Failed to open ellipsoid fit raw data file\n"); + return false; + } + while (m_magCalCount > 0) { + RTVector3 sample = removeMagCalData(); + fprintf(file, "%f %f %f\n", sample.x(), sample.y(), sample.z()); + } + fclose(file); + } + return true; +} + +bool RTIMUMagCal::magCalSaveCorr(const char *ellipsoidFitPath) +{ + FILE *file; + char *corrFile; + float a[3]; + float b[9]; + + if (ellipsoidFitPath != NULL) { + corrFile = (char *)malloc(strlen(RTIMUCALDEFS_MAG_CORR_FILE) + strlen(ellipsoidFitPath) + 2); + sprintf(corrFile, "%s/%s", ellipsoidFitPath, RTIMUCALDEFS_MAG_CORR_FILE); + if ((file = fopen(corrFile, "r")) == NULL) { + HAL_ERROR("Failed to open ellipsoid fit correction data file\n"); + return false; + } + if (fscanf(file, "%f %f %f %f %f %f %f %f %f %f %f %f", + a + 0, a + 1, a + 2, b + 0, b + 1, b + 2, b + 3, b + 4, b + 5, b + 6, b + 7, b + 8) != 12) { + HAL_ERROR("Ellipsoid corrcetion file didn't have 12 floats\n"); + fclose(file); + return false; + } + fclose(file); + m_settings->m_compassCalEllipsoidValid = true; + m_settings->m_compassCalEllipsoidOffset = RTVector3(a[0], a[1], a[2]); + memcpy(m_settings->m_compassCalEllipsoidCorr, b, 9 * sizeof(float)); + m_settings->saveSettings(); + return true; + } + return false; +} + + +void RTIMUMagCal::magCalOctantCounts(int *counts) +{ + memcpy(counts, m_octantCounts, RTIMUCALDEFS_OCTANT_COUNT * sizeof(int)); +} + +int RTIMUMagCal::findOctant(const RTVector3& data) +{ + int val = 0; + + if (data.x() >= 0) + val = 1; + if (data.y() >= 0) + val |= 2; + if (data.z() >= 0) + val |= 4; + + return val; +} + +void RTIMUMagCal::setMinMaxCal() +{ + float maxDelta = -1; + float delta; + + // find biggest range + + for (int i = 0; i < 3; i++) { + if ((m_magMax.data(i) - m_magMin.data(i)) > maxDelta) + maxDelta = m_magMax.data(i) - m_magMin.data(i); + } + if (maxDelta < 0) { + HAL_ERROR("Error in min/max calibration data\n"); + return; + } + maxDelta /= 2.0f; // this is the max +/- range + + for (int i = 0; i < 3; i++) { + delta = (m_magMax.data(i) -m_magMin.data(i)) / 2.0f; + m_minMaxScale.setData(i, maxDelta / delta); // makes everything the same range + m_minMaxOffset.setData(i, (m_magMax.data(i) + m_magMin.data(i)) / 2.0f); + } +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/9dbad3bd/thirdparty/RTIMULib/RTIMULib/RTIMUMagCal.h ---------------------------------------------------------------------- diff --git a/thirdparty/RTIMULib/RTIMULib/RTIMUMagCal.h b/thirdparty/RTIMULib/RTIMULib/RTIMUMagCal.h new file mode 100644 index 0000000..463fdf4 --- /dev/null +++ b/thirdparty/RTIMULib/RTIMULib/RTIMUMagCal.h @@ -0,0 +1,98 @@ +//////////////////////////////////////////////////////////////////////////// +// +// This file is part of RTIMULib +// +// Copyright (c) 2014-2015, richards-tech, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef _RTIMUMAGCAL_H +#define _RTIMUMAGCAL_H + +#include "RTIMUCalDefs.h" +#include "RTIMULib.h" + +class RTIMUMagCal +{ + +public: + RTIMUMagCal(RTIMUSettings *settings); + virtual ~RTIMUMagCal(); + + void magCalInit(); // inits everything + void magCalReset(); // clears everything + + // newMinMaxData() is used to submit a new sample for min/max processing + void newMinMaxData(const RTVector3& data); + + // newEllipsoidData is used to save data to the ellipsoid sample array + void newEllipsoidData(const RTVector3& data); + + // magCalValid() determines if the min/max data is basically valid + bool magCalValid(); + + // magCalEllipsoidValid() determines if enough samples have been collected for a valid ellipsoid fit + bool magCalEllipsoidValid(); + + // magCalSaveMinMax() saves the current min/max values to settings + void magCalSaveMinMax(); + + // magCalSaveRaw saves the ellipsoid fit data and then + // saves data to the .ini file. + // + // Returns true if everything worked correctly. + + bool magCalSaveRaw(const char *ellipsoidFitPath); + + // magCalSaveCorr loads the correction data from the ellipsoid fit program and saves it in the + // .ini + + bool magCalSaveCorr(const char *ellipsoidFitPath); + + // magCalSaveEllipsoid retrieves the ellipsoid fit calibration data + // and saves it in the .ini file. + + void magCalOctantCounts(int *counts); // returns a count for each of the 8 octants + + // these vars used during the calibration process + + RTVector3 m_magMin; // the min values + RTVector3 m_magMax; // the max values + + RTIMUSettings *m_settings; + +private: + RTVector3 removeMagCalData(); // takes an entry out of the buffer + int findOctant(const RTVector3& data); // works out which octant the data is in + void setMinMaxCal(); // get ready for the ellipsoid mode + + int m_startCount; // need to throw way first few samples + RTVector3 m_magCalSamples[RTIMUCALDEFS_MAX_MAG_SAMPLES];// the saved samples for ellipsoid fit + int m_magCalInIndex; // current in index into the data + int m_magCalOutIndex; // current out index into the data + int m_magCalCount; // how many samples in the buffer + + RTVector3 m_minMaxOffset; // the min/max calibration offset + RTVector3 m_minMaxScale; // the min/max scale + + int m_octantCounts[RTIMUCALDEFS_OCTANT_COUNT]; // counts in each octant + +}; + +#endif // _RTIMUMAGCAL_H