Code Monkey home page Code Monkey logo

altitudeestimation's Introduction

AltitudeEstimation

A hardware-independent, header-only, C++ arduino library to perform vertical position estimation using an IMU-Barometer system via a two-step Kalman/Complementary filter.

This work is an implementation of the algorithm explained in this paper written in 2016 by Jung Keun Lee. Although the original is in Korean you can find an English version of it here thanks to Simon D. Levy.

Setup

Hardware

The current setup used for testing consists in the Butterfly STM32L433 Development Board plus the MPU9250 Mini Add-On connected through USB to the computer.

Yo can see it in the images below:

Setup

Usage

This library is extremely easy to use. Go to the releases page of the library and download the latest release. Once downloaded, uncompress it in your Arduino/libraries folder. Alternatively, clone this respository in your Arduino/libraries folder by opening a terminal session there and typing:

git clone https://github.com/juangallostra/AltitudeEstimation.git

Clonning/Downloading the library in your Arduino/libraries folder is the only step that has to be performed before getting into the actual coding. To be able to use the library in your code add the following line at the beginning of your file:

#include "altitude.h"

We are ready now to instantiate the estimator where needed. This can be done by:

// Altitude estimator
AltitudeEstimator altitude = AltitudeEstimator(0.0005, 	// sigma Accel
                                               0.0005, 	// sigma Gyro
                                               0.018,   // sigma Baro
                                               0.5, 	// ca
                                               0.1);	// accelThreshold

Note that here we are specifying the value of the parameters that will be used to perform the estimations. These can be tuned to achieve higher accuracy. A more in-detail description of the parameters is provided below.

Once we have our estimator the only thing we have to do to estimate the current vertical position, velocity and acceleration is to call its estimate method. Since one of the aims of this library is to be hardware-independent, this method expects to receive the latest acceleremoter, gyrometer and barometer readings as well as the timestamp they were obtained as parameters. Jump to the Available methods section if you wish to know more about these parameters and their expected values.

altitude.estimate(accelData, gyroData, baroHeight, timestamp);

The call to the previous method will not return anything. Instead, it will perform the estimation and store the results. To access the results of the latest estimation you just have to call the following methods:

altitude.getAltitude()	// get estimated altitude in meters
altitude.getVerticalVelocity() // get estimated vertical velocity in meters per second
altitude.getVerticalAcceleration() // get estimated vertical acceleration in m/s^2

A fully working example can be found at AltitudeEstimation.ino under examples/AltitudeEstimation. The provided code assumes that the hardware used is an MPU9250 IMU and a MS5637 barometer. Arduino libraries for both them are available here (MPU9250) and here (MS5637).

There is another example thanks to Simon D. Levy, making use of the EM7180 SENtral sensor hub. The sketch is SENtralAltitude.ino and can be fund under examples/SENtralAltitude. The drivers for the EM7180 can be downloaded from here.

Available methods

estimate

Each time this method is called the estimation of the vertical position, velocity and acceleration will be updated. To update the estimation you must provide the latest available readings from the accelerometer (in g-s), the gyrometer (in rad/s) and the baro (in meters) as well as the timestamp in which the readings were obtained. Currently the library assumes the timestamp is measured in microseconds.

Calling this method will update the estimations and store the results internally but it will not return anything. There are specific methods provided to get the estimated values.

Method signature:

void estimate(float accel[3], float gyro[3], float baroHeight, uint32_t timestamp)

Parameters:

  • float accel[3]: length 3 array of floats with acceleration readings in g-s. The order in which the estimator expects the readings is ax, ay and az.

  • float gyro[3]: length 3 array of floats with gyrometer readings in rad/s. The order in which the estimator expects the readings is gx, gy and gz.

  • float baroHeight: vertical height in meters as estimated from the barometer signal. The conversion from pressure to height can be easily achieved with a small helper function. This is the formula I used in the provided example to achieve so (see lines 29-33). Since the algorithm requires the altitude estimated from the baro and not the pressure reading itself I prefer to let the user choose freely how he wants to map pressure to altitude.

  • uint32_t timestamp: The timestamp at which the readings were obtained. Currently the library expects it to be in microseconds.

getAltitude

This method can be called to obtain the latest vertical position estimation. The estimated altitude is measured in meters.

Method signature:

float getAltitude()

getVerticalVelocity

This method can be called to obtain the latest vertical velocity estimation. The estimated velocity is measured in meters per second.

Method signature:

float getVerticalVelocity()

getVerticalAcceleration

This method can be called to obtain the latest vertical acceleration estimation. The estimated vertical acceleration is measured in meters per second^2.

Method signature:

float getVerticalAcceleration()

Parameter tunning

There are a few parameters that can be tuned to try to achieve higher accuracy. These paremeters are:

  1. sigmaAccel: standard deviation of the accelerometer
  2. sigmaGyro: standard deviation of the gyroscope
  3. sigmaBaro: standard deviation of the barometer
  4. ca: constant value for the markov chain acceleration model: a(k) = ca * a(k-1) + e
  5. accelThreshold: vertical acceleration threshold. If 12 consecutive vertical acceleration values are below the threshold the vertical velocity will be set to 0.

The value of this parameters must be specified when calling the constructor of AltitudeEstimator. The order is the one listed above. Below one can see the signature of the constructor:

AltitudeEstimator(float sigmaAccel, float sigmaGyro, float sigmaBaro, float ca, float accelThreshold)

Results

Legend:

  • Yellow: Estimated vertical acceleration (m/s^2).
  • Green: Estimated vertical velocity (m/s).
  • Blue: Estimated altitude from barometer pressure readings (m).
  • Red: Two step Kalman/Complementary filter estimated altitude (m).

Test 1

Setup at rest the whole time.

test_1

Test 2

Lift to full cable length, hold, and lower it back to the initial position.

test_2

Extras

There is a Python implementation of the algorithm under the folder extras. You can read about it here.

altitudeestimation's People

Contributors

juangallostra avatar pascal66 avatar radiohound avatar simondlevy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

altitudeestimation's Issues

cmath.h ?

Seems (for me) that i cant find the cmath library needed by filter.h

Strange values for altitude estimation

I'am working with you library with 6 dof captor gyro+accel and one BME280. But I have very strange value for the altitude, my bme captor return to me a value between 287and 288meter but getAltitude()return to me a value between 1460``and 3450` meters. After few minutes altitude block around 3450 and 3460

All values coming from my captor are good m/s for accelerometer and rad/s for gyro and meters for bme and I sent micros() for timestamp

Axis orientation for estimation

I'm a bit confused about the axis orientation used to estimate the altitude. Different IMU libraries use different orientations, and some tend to translate axes into a common frame.

Could someone clarify what the expected orientation this should work with?

Accuracy test

The algorithm seems to work quite well but it has not been tested whether the estimated altitude is, in fact, the real altitude at which the board is hovering. Therefore, it would be nice to perform some accuracy tests.

Negative moving

Filters not working when going down.
altitude is added each time.

ie: when moving 1m and going back to 0m, result is 2m instead 0m

Comment code

Add some comments in the source code that help to understand what's going on at each step and also the purpose of each method.

Updated tags in order to reflect latest changes in PlatformIO

Hi @juangallostra ,

Thanks a lot for your great work, thanks @simondlevy I also read your absolutely incredible tutorial on Kalman and complementary filters. Just so much better than any white paper or tutorial I could find anywhere else. The Matlab guys have good videos but still lose people in maths, because they love it, but for an average developer understanding the concepts and having the jigsaw together, before looking into deconstructing it piece by piece is just what matters, the rest usually follows using libs and detailed tutorials.

Anyhow, PlatformIO is a great tool to expose your work and i got to know about it thanks to this great platform. However it does not seem to download the latest version of your Altitude estimator since the last tag v0.2 is 14 commits behind the master head and it does not seem to pull the master head by default but the latest tag.

Because of this the old version using i.e. the #include is still the default, the examples are also behind.

I thought I'd let you know as i got caught, but being familiar with git this was not an issue finding out, but many IOT hobbyist will bump into it.

Regards
Romain developer at Flightcell International (Rescue, police, firefighter helicopters and fixed wing flight tracking solutions)

image

Kalman Filter always outputs negative acceleration and velocity

Hello!

I am extremely interested in this Kalman Filter but unfortunately I am unable to let it calculate a positive acceleration, regardless of the Inputs (and signs) I provide.
Here is a very simple sample code with two variations but the result is always the same, the Kalman filter returns always negative velocity and negative acceleration :(

float accelData[3];
accelData[0] = 0;
accelData[1] = 0;
accelData[2] = -0.1;

float gyroData[3];
gyroData[0] = 0;
gyroData[1] = 0;
gyroData[2] = 0;

altitude.estimate(accelData, gyroData, 0, micros());

altitude.getAltitude(), altitude.getVerticalVelocity() and altitude.getVerticalAcceleration() return always negative values, regardless of sign of value assigned to accelData[2], i.e. accelData[2] = -0.1; and accelData[2] = 0.1; lead always to the same results.

Can you please help?

PS: I previously tried with real IMU and pressure sensor data from BNO085 and BMP390 but since that didn't work I tried the basic example above and still I get the same results: always negative acceleration, negative velocity, decreasing altitude, regardless of the signs of the IMU signals

Can't get Positive Velocity

No matter which direction I move my IMU, I can't get the velocity (in green) to go above zero. I am using a BNO055 and BMP280 with a Teensy 4.0.

Screen Shot 2021-02-18 at 12 30 42 AM

No issue but more a question?

I am trying to understand the output of the kalman filter.

Essentially it looks like the kalman filter is providing the vertical acceration:

float verticalAccel = kalman.estimate(pastGyro,
pastAccel,
deltat);

But given the output of the Sentral, the linear acceleration can easily be calculated.

To quote the USFS wiki:

image

So if using EM7180 library from Simon Levy, and the above calculations, couldn't the Kalman filter be bypassed?

Thanks

Bruce

Include rangefinder in the estimation

A possible approach:
Start by simply substituting the rangefinder for the baro, then see whether all three (rangefinder, baro, accel) could be incorporated. One thing worth looking into is the AGL (Above Ground Level) versus ASL (Above Sea Level) issue. An optimal solution would probably compute ASL, and would have some conditional like "If rangefinder reading changes suddenly (faster than some threshold) while baro remains constant (or gradual), vehicle is above a ground obstacle, and ASL is unchanged"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.