Giter Club home page Giter Club logo

kalmanfilter's People

Contributors

gabrielsa avatar jacksonkr avatar lauszus 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  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  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  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

kalmanfilter's Issues

error: i2cWrite failed: 2 ~~~> why?

hi,
I loaded your MPU6050 example to my Arduino Due
I wired the MPU6050 accordingly:

SCK, SDA,
Vcc 3.3V
GND
A0 --> GND

I didn't find either hint about "Alert" pin (interrupt?) anywhere in your documentation.

the device is found by i2c scanner at addr 0x18.

Why is ths error message
i2cWrite failed: 2
with you code?

enhancement proposals: float instead of double, init_MPU6050() and read_MPU6050() in dedicated functions

hi,
As I got my new MPU6050 (addr 0x68), I have 2 proposals:

1st, in order to make the code quicker by calculation and execution, I would suggest to use float instead of double (on ARM MCUs >2x as fast).

2nd, additionally, I would suggest to put
init_MPU6050() and
read_MPU6050(float &yaw, float &pitch, float &roll)) // yaw: wishful enhancement
into 2 dedicated functions, to make the code more readable and more versatile for arbitrary calls in arbitrary setup() and loop() functions, perhaps even for usage by different IMUs, other than MPU6050:

/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.

 This software may be distributed and modified under the terms of the GNU
 General Public License version 2 (GPL2) as published by the Free Software
 Foundation and appearing in the file GPL2.TXT included in the packaging of
 this file. Please note that GPL2 Section 2[b] requires that all works based
 on this software must also be made publicly available under the terms of
 the GPL2 ("Copyleft").

 Contact information
 -------------------

 Kristian Lauszus, TKJ Electronics
 Web      :  http://www.tkjelectronics.com
 e-mail   :  [email protected]
 */

#include <Wire.h>
#include <Kalman.h> // Source: https://github.com/TKJElectronics/KalmanFilter

//#define RESTRICT_PITCH // Comment out to restrict roll to ±90deg instead - please read: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf

Kalman kalmanX; // Create the Kalman instances
Kalman kalmanY;

/* IMU Data */
float accX, accY, accZ;
float gyroX, gyroY, gyroZ;
int16_t tempRaw;

float gyroXangle, gyroYangle; // Angle calculate using the gyro only
float compAngleX, compAngleY; // Calculated angle using a complementary filter
float kalAngleX, kalAngleY; // Calculated angle using a Kalman filter

uint32_t timer;
uint8_t i2cData[14]; // Buffer for I2C data

// TODO: Make calibration routine


void init_MPU6050() {
   
  i2cData[0] = 7; // Set the sample rate to 1000Hz - 8kHz/(7+1) = 1000Hz
  i2cData[1] = 0x00; // Disable FSYNC and set 260 Hz Acc filtering, 256 Hz Gyro filtering, 8 KHz sampling
  i2cData[2] = 0x00; // Set Gyro Full Scale Range to ±250deg/s
  i2cData[3] = 0x00; // Set Accelerometer Full Scale Range to ±2g
  while (i2cWrite(0x19, i2cData, 4, false)); // Write to all four registers at once
  while (i2cWrite(0x6B, 0x01, true)); // PLL with X axis gyroscope reference and disable sleep mode

  while (i2cRead(0x75, i2cData, 1));
  if (i2cData[0] != 0x68) { // Read "WHO_AM_I" register
    Serial.print(F("Error reading sensor"));
    while (1);
  }

  delay(100); // Wait for sensor to stabilize

  /* Set kalman and gyro starting angle */
  while (i2cRead(0x3B, i2cData, 6));
  accX = (int16_t)((i2cData[0] << 8) | i2cData[1]);
  accY = (int16_t)((i2cData[2] << 8) | i2cData[3]);
  accZ = (int16_t)((i2cData[4] << 8) | i2cData[5]);

  // Source: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf eq. 25 and eq. 26
  // atan2 outputs the value of -π to π (radians) - see http://en.wikipedia.org/wiki/Atan2
  // It is then converted from radians to degrees
#ifdef RESTRICT_PITCH // Eq. 25 and 26
  float roll  = atan2(accY, accZ) * RAD_TO_DEG;
  float pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
#else // Eq. 28 and 29
  float roll  = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;
  float pitch = atan2(-accX, accZ) * RAD_TO_DEG;
#endif

  kalmanX.setAngle(roll); // Set starting angle
  kalmanY.setAngle(pitch);
  gyroXangle = roll;
  gyroYangle = pitch;
  compAngleX = roll;
  compAngleY = pitch;

  timer = micros();
  
}


void read_MPU6050(float &yaw, float &pitch, float &roll) {
  /* Update all the values */
  while (i2cRead(0x3B, i2cData, 14));
  accX = (int16_t)((i2cData[0] << 8) | i2cData[1]);
  accY = (int16_t)((i2cData[2] << 8) | i2cData[3]);
  accZ = (int16_t)((i2cData[4] << 8) | i2cData[5]);
  tempRaw = (int16_t)((i2cData[6] << 8) | i2cData[7]);
  gyroX = (int16_t)((i2cData[8] << 8) | i2cData[9]);
  gyroY = (int16_t)((i2cData[10] << 8) | i2cData[11]);
  gyroZ = (int16_t)((i2cData[12] << 8) | i2cData[13]);;

  float dt = (float)(micros() - timer) / 1000000; // Calculate delta time
  timer = micros();

  // Source: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf eq. 25 and eq. 26
  // atan2 outputs the value of -π to π (radians) - see http://en.wikipedia.org/wiki/Atan2
  // It is then converted from radians to degrees
#ifdef RESTRICT_PITCH // Eq. 25 and 26
  roll  = atan2(accY, accZ) * RAD_TO_DEG;
  pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
#else // Eq. 28 and 29
  roll  = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;
  pitch = atan2(-accX, accZ) * RAD_TO_DEG;
#endif

  float gyroXrate = gyroX / 131.0; // Convert to deg/s
  float gyroYrate = gyroY / 131.0; // Convert to deg/s

#ifdef RESTRICT_PITCH
  // This fixes the transition problem when the accelerometer angle jumps between -180 and 180 degrees
  if ((roll < -90 && kalAngleX > 90) || (roll > 90 && kalAngleX < -90)) {
    kalmanX.setAngle(roll);
    compAngleX = roll;
    kalAngleX = roll;
    gyroXangle = roll;
  } else
    kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt); // Calculate the angle using a Kalman filter

  if (abs(kalAngleX) > 90)
    gyroYrate = -gyroYrate; // Invert rate, so it fits the restriced accelerometer reading
  kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt);
#else
  // This fixes the transition problem when the accelerometer angle jumps between -180 and 180 degrees
  if ((pitch < -90 && kalAngleY > 90) || (pitch > 90 && kalAngleY < -90)) {
    kalmanY.setAngle(pitch);
    compAngleY = pitch;
    kalAngleY = pitch;
    gyroYangle = pitch;
  } else
    kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt); // Calculate the angle using a Kalman filter

  if (abs(kalAngleY) > 90)
    gyroXrate = -gyroXrate; // Invert rate, so it fits the restriced accelerometer reading
  kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt); // Calculate the angle using a Kalman filter
#endif

  gyroXangle += gyroXrate * dt; // Calculate gyro angle without any filter
  gyroYangle += gyroYrate * dt;
  //gyroXangle += kalmanX.getRate() * dt; // Calculate gyro angle using the unbiased rate
  //gyroYangle += kalmanY.getRate() * dt;

  compAngleX = 0.93 * (compAngleX + gyroXrate * dt) + 0.07 * roll; // Calculate the angle using a Complimentary filter
  compAngleY = 0.93 * (compAngleY + gyroYrate * dt) + 0.07 * pitch;

  // Reset the gyro angle when it has drifted too much
  if (gyroXangle < -180 || gyroXangle > 180)
    gyroXangle = kalAngleX;
  if (gyroYangle < -180 || gyroYangle > 180)
    gyroYangle = kalAngleY;
}

 


void setup() {
  Serial.begin(115200);
  Wire.begin();
#if ARDUINO >= 157
  Wire.setClock(400000UL); // Set I2C frequency to 400kHz
#else
  TWBR = ((F_CPU / 400000UL) - 16) / 2; // Set I2C frequency to 400kHz
#endif

  init_MPU6050();

}


void loop() {

  float yaw=0, pitch=0, roll=0; // yaw: wishful enhancement

  read_MPU6050(yaw, pitch, roll);

    /* Print Data */
  #if 0 // Set to 1 to activate
  Serial.print(accX); Serial.print("\t");
  Serial.print(accY); Serial.print("\t");
  Serial.print(accZ); Serial.print("\t");

  Serial.print(gyroX); Serial.print("gyroX\t");
  Serial.print(gyroY); Serial.print("gyroY\t");
  Serial.print(gyroZ); Serial.print("gyroZ\t");

  Serial.print("\t");
#endif

  Serial.print("roll="); Serial.print(roll); Serial.print(" \t");
  //Serial.print(gyroXangle); Serial.print("\t");
  //Serial.print(compAngleX); Serial.print("\t");
  //Serial.print(kalAngleX); Serial.print("\t");

  Serial.print("\t");

  Serial.print("pitch="); Serial.print(pitch); Serial.print(" \t");
  
  //Serial.print(gyroYangle); Serial.print("\t");
  //Serial.print(compAngleY); Serial.print("\t");
  //Serial.print(kalAngleY); Serial.print("\t");

#if 0 // Set to 1 to print the temperature
  Serial.print("\t");

  float temperature = (float)tempRaw / 340.0 + 36.53;
  Serial.print(temperature); Serial.print("\t");
#endif

  Serial.print("\r\n");
  delay(2);
  
}


what would you think?

Full range with MPU

Hi guys,

First time I'm interacting at GitHub so sorry for any mistake.

I read the PDF that the lib is based and understood that it's not possible to use it for a 360 degrees range. I'm intrigued beucase I'm using MPU6050 with some trigonometry (atan2) and complementary filter and I'm able to use it for the full range and the Z-axis as well (of course, the closer to perpendicularity to the floor, worst or cant get the result).

Is there a way to use this library in that way? It really helped me.

How do you fuse encoder and gyro?

I have a four-wheeled robot.
There's an encoder on each side, and a gyroscope.
I use the formula:"(encL - encR) / 2.0 * _turnScale" can get an angle.
Considering the problem of wheel skidding and gyroscope self-increasing, I want to integrate them.
The two values I get are both angular values, not angular velocities. I set a 10MS loop once.

roll angle computed in inverse direction by this MPU6050 lib?

hi,
As I just observed, your roll angle is computed in the inverse direction by this MPU6050 lib.
I compared your values with the values I get from my CMPS11 IMU, and also compared it by this chart:
https://i.stack.imgur.com/ge9sN.png
according to both references,
rolling counter-clockwise (to the left) it's negative,
whilst rolling clockwise (to the right) it's positive there.

By your MPU6050 example it's other way round as far as I see.

Calibration

hello tkj electronics. Well read your good library, it really helped me understand what the kalman filter is.
Anyway, I wanna know how to calibrate mpu6050 accel,gyro offsets using kalman filter. In other IMU like DMP or MAHONY filter, It has a way to calibrate the offsets(accel,gyro). I have no idea how to add calibration code to your example... If you don't mind , Could you let me know the way to calibrate or related links?? Thanks a a lot!

ps.

double accX, accY, accZ;
double gyroX, gyroY, gyroZ;

Would it be proper to use this variables with my own accel&gyro offsets with using my calibration codes?? thank you

MPU6050 example issue with data

I'm using the MPU6050 example and not getting the full range of data for pitch or roll, do you have any ideas?

Here's a processing graph from an earlier commit showing 2 full rolls at a somewhat constant rate - http://imgur.com/LvKMmuu

The same is happening on pitch.

The ranges for compAngleX for example will be about -180 when sitting level.

As I roll to the right for 360 degrees I get:

0 deg: -180 or +180
90 deg : -145 to -150
180 deg: -180 or +180
270 deg: +145 to +150
360 deg: back to -180 or +180

Any ideas? Thanks.

Arduino Specific or General C++?

Hi.
I'm looking at your library and it seems to be in general C++ (doesn't have Arduino specific code). I just wanted to confirm if this is the case, since I want to use it with a different microcontroller and I'm not using the Arduino framework in it.
Your help would be much appreciated.

Values not showing

Hi, i'am trying to run your code but after i uploaded it on my NodeMCU and my question is is the code already been calibrated? how to make it to show values around 0?

i am using arduinoIDE ver.1.8.9
NodeMCU 1.0 esp8266

i2cWrite fail : 4

I sometimes get this error [error info attached in the screeshot] while reading the values of my MPU6050 sensor. I'm using an ESP8266, even after resetting the board it shows the same error, but if I unplug the the power source and put it back on then it works fine. What causes this error and how can I avoid it ???

screenshot 39

Just asking if its just angular position or more.

Does this filter take derivative of angle and second derivative of angle into consideration? I guess its only angular position and angular velocity because the matrix is 2x2? If not, what kind of changes would be needed to add velocity & acceleration too?

Method Kalman.getAngle()

Hello, I'm in doubt when returning the following method:

float Kalman::getAngle(float newAngle, float newRate, float dt);

I understand that by parameter, an angle (degrees), an angular rate (degrees/seconds) and time (seconds) are passed. Is the return of this method an angle estimate in degrees? Or an angular rate in degrees per second?

Thank you!

misleading name of this lib: no general kalman library code, but only targeting to IMU sensors ?!

hi,
as I have observed, your lib is called "KalmanFilter.h" but there is no general kalman example code, instead just an example how to target a MPU IMU sensor,. and also in the lib itself the IMU is addressed specifically, not general sensor types.

But I'm curious how to use this Kalman lib also for gerneral purposes, i.e. fusioning sensors like GPS and odometry and/or some IR distance sensors.
So what would be needed is a guide (and/or well commented example code) how to initialize the Kalman filter by sensor values and perhaps their statistic properties (e.g., range, standard deviation), then just assign the values to the filter and then let the filter work.

How can that be done ?

If this lib is meant only for MPU then the caption pf this lib is misleading!
Then you must not call it Kalman lib but MPU6050 lib !!!

No waiting needed after Wire.requestFrom().

In the file "examples/MPU6050/I2C.ino" there is a complicated way with polling Wire.available() and timeouts and micros() after the call to Wire.requestFrom(). That can be removed, there is nothing to wait for.

When the Wire.requestFrom() returns, the I2C transaction has completely finished and the received data is waiting in a buffer in the Wire library.

The preceding Wire.endTransmission() is already tested for a I2C bus error. If you want, you can add a test for Wire.requestFrom() as well.

  Wire.requestFrom(IMUAddress, nbytes, (uint8_t)true); // Send a repeated start and then release the bus after reading
  if(Wire.available() != nbytes)
  {
    Serial.println(F("i2cRead bus error"));
    return 5; // This error value is not already taken by endTransmission
  }
  else {
    for (uint8_t i = 0; i < nbytes; i++) {
      data[i] = Wire.read();
    }
  }

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.