Gyroscope non-constant drift under high acceleration - signal-processing

I am trying to implement a Kalman filter combining an accelerometer and the gyroscope in an IMU.
To my knowledge I would expect the gyro to have a constant drift which we will compensate by bringing in the accelerometer.
However, when analyzing the gyroscope independently I do not always observe a constant drift. If we do not have a lot of fast movement/high acceleration, the drift seems correct as seen in the first plot. On the second plot we get the gyro raw values.
At the beginning it can be seen that we offset the gyro by averaging the first 100 readings.
However, when I move the IMU more aggressively, the gyro does no longer have a constant drift. I do not know where this variation of the drift comes from and what would be a state-of-the-art way of solving this issue. I thought of small movements due to a small mounting issue, but if it would be left still, it should keep integrating the degrees at a same rate.

Even zero-mean noise can cause large random walk excursions from anything being constant. Double integration of this noise will cause your compensation to explode. The only good solution may be to use sensor fusion with another independent source of ground truth (optical, magnetic, audio, etc.)

Related

Track user speed with CoreMotion without GPS

I want to track user's position and update it in the offline map based on his movement without using GPS and having to rely on location updates.
I have tried CMMotionManager and got acceleration in G's. However, this is acceleration rather than valocity. The manager also allows to get gravity, rotation and attitude.
Is there a way to calculate the user's speed in m/s ? If so, how would I go about it? Any formulas / code samples?
The only way to do this is to assume that the phone is at rest when the app starts. With an accelerometer there's no way to tell the difference between being at rest and moving at a constant rate. For example if you were on a jet plane you'd have no way to tell that you were traveling at 800 kph and not sitting still.
If you do assume that you are at rest when you start it's possible to come up with very crude estimates of speed by tracking acceleration, but in practice, the results are prone to large amounts of "drift error", were small measurement errors quickly add up to a completely wrong current speed result, and so your position drifts around hopelessly.
So in practice, the answer to your question is "no, not really."
Edit:
Thinking about this a little more, you might be able to get usable results if you can impose some assumptions.
Say we assume that the user is on foot. We rule out traveling on a bike/in a car/train/plane. On foot, you really don't "drift". You move in fits and starts as the user takes steps. In fact, you could likely use the accelerometer to recognize the characteristic bounce of a person walking. There are pedometer apps that already do that. For walking, you could probably assume that in the absence of acceleration (ignoring gravity, which is constant), the phone is stationary, so zero out the speed and keep it at zero until there is an acceleration above a certain threshold. That would enable you to reduce drift error.

How to decorrelate accelerometer data

Is it possible to decorrelate accelerometer data in real-time? If so, how is it done?
Background:
My application is receiving (X,Y,Z) accelerometer data in real-time (sample rate is 6.75Hz). The sensor is moving in a periodic motion but the motion is not necessarily along only one axis. The 3 signals x(t), y(t) and z(t) are therefore slightly correlated and I would like to know if I can find a rotation matrix (in real time) which can be used to rotate the measured (x,y,z) into a new vector (x*,y*,z*) so that the entire motion is along the z-axis?
I would like to implement the algorithm in C.
Thanks.
What you're trying to do is generally called "principal component analysis". The Wikipedia article is pretty good:
https://en.wikipedia.org/wiki/Principal_component_analysis
For static data you generally use the eigenvectors of the covariance matrix as your new coordinate basis.
PCA in real time is doable, but not super easy. See, for example: http://www.bio-conferences.org/articles/bioconf/pdf/2011/01/bioconf_skills_00055.pdf
I'd like to first of all emphasize that Matt Timmermans' answer has done exactly what people are actually doing when classifying accelerometer data from clinical studies (a project I worked on).
Then: you're observing a sampled signal. In general, if you have a sensor that gives you samples at a rate of 6.75Hz, the highest frequency of a signal you can detect is 6.75Hz/2 = 3.375Hz. Everything that has a frequency higher than that will inherently be aliased back and look like it was something with a frequency f with 0<=f<3.375Hz. If you've not considered this, please go and read up on the Nyquist–Shannon sampling theorem. Especially: shield your sensors (however you do that, e.g. by employing dampeners) from all input above that limit, otherwise your measurements might be worth very little or even nothing. If your sensor does this internally (that's absolutely possible, there are enough accelerometers with analog low pass filters), this has been taken care of. However, document that characteristics of your sensor.
Now, your case is a little bit easier because you know pretty well that your whole observation is going to be periodic, and it's measured along three orthogonal axis.
In this case, just doing three discrete Fourier transforms at once, extracting the "strongest" spectral component over all three channels, and finding the phase of that spectral component (which is but the complex argument of that DFT bin) in the two others would give you something that you can map to a periodic movement around a specific axis in 3D space. If you want to, remove these value (set the bins to 0), and search for strongest component again etc.
Discrete cosine transforms can be done in staggering speed nowadays. with 6.75Hz, no PC in this world will ever get into trouble when you try this while you receive further samples. It's a hilariously low sampling rate.
Another, more elegant (read: you need less samples to compute this) would be using a parametric estimator; in your case, a direction-of-arrival sensor from the world of RF technology with multiple antennas would, as far as I can think, map directly to detection of rotational axis. The classical algorithms here are MUSIC and ESPRIT, and for your case (limited, known amount of oscillating parts), ESPRIT might be the better choice.

IMU Orientation constantly changing

We have XSENS MTi IMU-Device and use the ROS-Framework (Ubuntu / Fuerte).
We subscribe to the IMU-Data and all data looks good except orientation.
In Euler-Outputmode like in Quaternion-Outputmode the values are constantly changing. Not randomly, they increase or decrease slowly at a more or less constant rate, and sometimes I observed the change to flatten out and then change it's direction.
When the Value at Second X may be:
x: 7.79210457616
y: -6.58661204898
z: 41.2841955308
the Z value changes in a range of about 10 within a few seconds (10-20 seconds I think).
What can cause this behaviour? Do we misinterpret the data or is there something wrong with the driver? The strange thing is, this also happend with 2 other drivers, and one other IMU device (we have 2). Same results in each combination.
Feel free to ask for more precise data or whatever you'd like to know that may be able to help us out. We are participating at the Spacebot-Cup in November, so it would be quite a relief to get the IMU done. :)
Perfectly normal if you have no magnetometer to give a corrected heading.
Gyroscope alone measures rate of turn only, and has no idea of orientation at any given time on any axis. Integrating the rate of turn gives the heading if you know the initial heading and the gyro is 100% accurate. It drifts anyway, even if it's perfectly calibrated, as you are sampling at discrete intervals rather than continuously.
Adding an accelerometer will at least fix the downward direction (because it measures gravity, which is towards the Earth's centre). This will keep the Z axis solution aligned with vertical, but it won't fix the horizontal direction (the heading or yaw). That will continue to drift, as you are seeing.
Adding a magnetometer will fix the heading relative to the Earth's magnetic field. This will give you a heading relative to magnetic North. You will need to apply a shift for local magnetic declination to get True North. These are generally available on line and reasonably constant over tens of km. Google ITREF.
Some integrated sensors don't have a magnetometer. That's why the heading drifts. Units like the MPU6050 have firmware built in, and can access a magnetometer, but the usual firmware doesn't use it, so you have to implement Madgwick, etc., on your micro controller or a connected PC anyway. Bosch have a new single module with a processing unit built in. Hopefully, it uses 9 DOF rather than the 6 you get with the DMP on the MPU6050.
Magnetic sensors are accurate to about 2 degrees. Local magnetic declination corrections also have an error. You may be able to perform additional calibrations by using a GPS on a long base line to get better results. It's also worth noting that heading and course made good are often different, due to crosswind / cross currents.
The Madgwick algorithm is fairly stable and easy to implement, and uses fewer resources than a Kalman filter, which needs to perform matrix inversion. It still gives minor jitter, but minor smoothing of results shouldn't induce too much lag.
If you have the IMU version, I assume that no signal processing has been done on the device. (but I don't know the product). So the data you get for the orientation should be only the integral of the gyroscope data.
The drift you can see is normal and can come from the integration of the noise, a bad zero rate calibration, or the bias of the gyroscope.
To correct this drift, we usually use an AHRS or a VRU algorithm (depending the need of a corrected yaw). It's a fusion sensor algorithm which take the gravity from the accelerometer and the magnetometer data (for AHRS) to correct this drift.
The algorithms often used are the Kalman filter and the complementary filter (Madgwick/Mahony).
It's not an easy job and request a bit of reading and experimenting on matlab/python to configure these filters :)

Finding the cardinal direction accelerated with an Algorithm for using the magnetometer, accelerometer, and gyro readings

I want to find the cardinal direction accelerated by an iphone. I thought I could just use the accelerometer to do this, however, as you can see from the picture below the accelerometers axes are defined by the device orientation.
I figured that if i used the gyroscope to correct for yaw, spin, rotation then I could get a more accurate reading and not have to hold the phone in the same orientation during movement.
But this still does not tell me what cardinal direction the iphone is moving in. For that I would also have to use the the magnetometer.
Can anybody tell me how to use a three sensor readings to find the cardinal direction accelerated in? I dont even know where to start. I dont even know if the phone takes these measurements at the same rates of time either.
Taking the cross product of the magnetometer vector with the "down" vector will give you a horizontal magnetic east/west vector; from that, a second cross product gets the magnetic north/south vector. That's the easy part.
The harder problem is tracking the "down" vector effectively. If you integrate the accelerometers over time, you can filter out the motion of a hand-held mobile device, to get the persistent direction of gravity. Or, you could, if your device weren't rotating at the same time...
That's where the rate gyros come in: the gyros can let you compensate for the dynamic rotation of the hand-held device, so you can track your gravity in real-time. The classic way to do this is called a Kalman filter, which can integrate (both literally and figuratively) multiple data sources in order to evaluate the most likely state of your system.
A Kalman filter requires a mathematical model both of your physical system, and of the sensors that observe it; each of these models must be both accurate and "sufficiently linear" for the Kalman filter to work properly. As it happens, the iphone/accelerometer/gyro system is in fact sufficiently linear.
The Kalman filter uses both calculus and linear algebra, so if you're rolling your own, you will need a certain amount of math.
Also, as a practical matter, you should understand that physical sensors typically have offsets that need to be compensated for -- in particular, you need to pay attention to the rate gyro offsets in this kind of inertial navigation system, or your tracker will never stabilize. This means you will need to add your rate gyro offsets to your Kalman state vector and system model.

iOS Calculating the vertical movement distance of the device

I'm looking to create a function for my app which records the distance travelled in the vertical plane. More specifically, I want to record how far the device has been 'dropped' - this could mean dropped at arm's length onto the floor or dropped slowly with the user as they go down ten floors in an elevator. I'm looking for advice on the best way to calculate this with a relatively high level of accuracy.
I've read a little on the difficulty in accurately measuring distance travelled using core motion - especially as I need it to work even if the device rotates during the movement. From what I've researched it seems as though it would be impossible, or at least very difficult, to achieve this using core motion.
Would I be able to achieve this effect with Core Location instead? I've seen posts about calculating lateral distance, as in during a car journey, but nothing about vertical distance.
Is it as simple as 'startingAltitude - endingAltitude = distanceTravelled?
If so - how accurate is the altitude measurement of Core Location and how could I get started with this behaviour? I'm fairly new to iOS programming and would appreciate any pointers on the most appropriate method of achieving the function I want.
Thanks
There are serious limitations to both approaches.
Using an accelerometer to measure distance travelled requires very precise and accurate real-time measurement of acceleration. Any error in acceleration reading leads to error in your velocity calculation, which makes your location reading drift from the real location. Drift gets worse over time, to the point where the error swamps the actual location reading.
Based on my testing the altitude reading in iOS GPS devices is really bad. +/- 100 or more meters is not uncommon. Indoors GPS readings tend to get really bad, and the altitude reading is bad enough to start.

Resources