How to Account for Numerical Integration Error?

10 views (last 30 days)
I'm working on a project using an Arduino Uno and an Adafruit gyroscope. I'm collecting gyroscope data, saving the data to a text file, and importing the data into MATLAB to operate on it. The gyroscope provides me with angular velocity data whereas I am interested in angular position. To get angular position from angular velocity, I use cumtrapz to numerically integrate my data. I also have implemented a three-point weighted average filter to smooth my gyro data as well as averaged a portion of the data to correct for the initial gyro offset.
Everything in my script is working as it should, however, I'm noticing that when I bring my gyro back to the starting position at the end of a movement, my integrated angular position data does not return to zero. However, the angular velocity data with the help of my filter and offset correction does return to zero. This makes it clear that my final offset is a result of the integration process.
From what I've read online so far, it seems that using cumtrapz and numerical integration in general results in a small amount of error. I remember from my Calc I class that using trapezoidal integration is, of course, only an approximation, so some error is to be expected.
My question is how can I take this error into account and correct for it in my integrated angular position data? I've attached some screenshots of my raw angular velocity data, filtered angular velocity data, and my integrated angular position data.
Thank you for your help in advance.
  1 Comment
John D'Errico
John D'Errico on 30 Jun 2016
I'm moved Nick's answer into a comment, here as a way to include the code:
clear; clc; close all;
% Import gyroscope data from delimitied text file
gyroData = dlmread('float7.txt',',');
% Convert time from ms to seconds
time = gyroData(:,1) .* .001; % seconds
% Define raw angular velocities (deg/sec) for each axis
xRaw = gyroData(:,2);
yRaw = gyroData(:,3);
zRaw = gyroData(:,4);
% Filter gyro data using filter function
[xFilt, yFilt, zFilt] = filterGyroData(xRaw,yRaw,zRaw);
% Sample first 100 data values to calculate offset
xOff = xFilt(1,1:100);
yOff = yFilt(1,1:100);
zOff = zFilt(1,1:100);
% Average initial offset values
xAvg = mean(xOff);
yAvg = mean(yOff);
zAvg = mean(zOff);
% Correct filtered data initial offset
xCorr = xFilt - xAvg;
yCorr = yFilt - yAvg;
zCorr = zFilt - zAvg;
% Convert values to radians per second
xDataRad = deg2rad(xCorr);
yDataRad = deg2rad(yCorr);
zDataRad = deg2rad(zCorr);
% Use cum. numerical integration to obtain angular position (radians)
xAngPosRad = cumtrapz(time,xDataRad);
yAngPosRad = cumtrapz(time,yDataRad);
zAngPosRad = cumtrapz(time,zDataRad);
% Convert values back to degrees
xAngPosDeg = rad2deg(xAngPosRad);
yAngPosDeg = rad2deg(yAngPosRad);
zAngPosDeg = rad2deg(zAngPosRad);
% Plot raw angular velocity
figure(1);
plot(time,xRaw,time,yRaw,time,zRaw);
title('Raw Angular Velocity');
xlabel('Time (sec)'); ylabel('Angular Velocity (deg/sec)');
legend('x','y','z');
% Plot filtered angular velocity
figure(2);
plot(time,xCorr,time,yCorr,time,zCorr);
title('Filtered Angular Velocity')
xlabel('Time (sec)'); ylabel('Angular Position (degrees)');
legend('x','y','z');
% Plot filtered angular position
figure(3);
plot(time,xAngPosDeg,time,yAngPosDeg,time,zAngPosDeg);
title('Filtered Angular Position');
xlabel('Time (sec)'); ylabel('Angular Position (degrees)');
legend('x','y','z');
end

Sign in to comment.

Accepted Answer

Star Strider
Star Strider on 30 Jun 2016
If you have the Signal Processing Toolbox, use the freqz function to learn what the passband of your weighted-average filter actually is. Don’t assume it’s somehow magickally doing what you want it to do if you’ve not specifically designed its passband to do so.
I would design a bandpass filter that eliminates the d-c component (integrating it may be the source of the baseline wander in your integrated signal) and any high-frequency noise. Do a fft first to determine what frequencies in your data are signals, and what are noise. IIR filters are best for this (in my opinion, at least). There are many ways to design filters in MATLAB, including dfilt and designfilt. My IIR filter design procedure is here: How to design a lowpass filter for ocean wave data in Matlab? Be sure to use the filtfilt function rather than filter, since filtfilt has a maximally-flat phase response, resulting in no phase distortion in your filtered signal.
Signal processing is not difficult with MATLAB, and doing it correctly is always necessary if you want to get the best results from your data.
  14 Comments
NickPK
NickPK on 1 Jul 2016
Edited: NickPK on 1 Jul 2016
Thank you so much! You have really gone above and beyond the help I expected to receive. I'll take some time later to analyze the new code and do some tests with it. I apologize for the faulty data. That's the first time that's happened.
It's worth mentioning that I'm in the process of testing a new sensor. Specifically the one found here. In case you were interested, the original gyro I've been using is this one.
I've just finished programming the new IMU to log and save data and so far it seems that the new sensor is much more accurate from the start. In fact, from what I'm seeing, it doesn't appear to have any initial drift in the angular velocity. However, I'm still seeing final offset in data after integrating.
I'm going to continue to play around and test this new sensor as well as the old one. I'll post questions as I come across them.
Also, why couldn't you download directly from Dropbox? Was it something on my end?
Star Strider
Star Strider on 1 Jul 2016
As always, my pleasure!
I enjoy helping with ‘real world’ data analysis problems, especially when they overlap into an area of my interests.
Not a problem on your end. I just have no reason to create a Dropbox account. It worked regardless, so no problems.
I’ll take a look at the sensor information you linked to. I used to do a fair amount of reading from USB sensors in MATLAB but haven’t needed to in the past few years. It’s probably something I would enjoy getting into again.

Sign in to comment.

More Answers (1)

John D'Errico
John D'Errico on 30 Jun 2016
In order to compute the error of a numerical integration as an approximation, you would need to know the true function, and the true integral.
The fact is, you don't KNOW the true function. You don't KNOW the true integral!
So you cannot account for the unknowable.
That being said, I don't KNOW that you don't have a bug in your code.
  6 Comments
NickPK
NickPK on 30 Jun 2016
Thank you for that. It didn't occur to me that I needed to do it in that order. Now I know.
John D'Errico
John D'Errico on 30 Jun 2016
Ok, I looked at your code. My first inclination is that you filtered it, which must of course introduce some error too. I'll need to look more carefully at what you have done.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!