Script.m 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. clear;
  2. close all;
  3. clc;
  4. addpath('Quaternions');
  5. addpath('ximu_matlab_library');
  6. % -------------------------------------------------------------------------
  7. % Select dataset (comment in/out)
  8. %
  9. % filePath = 'Datasets/straightLine';
  10. % startTime = 6;
  11. % stopTime = 26;
  12. % filePath = 'Datasets/stairsAndCorridor';
  13. % startTime = 5;
  14. % stopTime = 53;
  15. filePath = 'Datasets/spiralStairs';
  16. startTime = 4;
  17. stopTime = 47;
  18. % -------------------------------------------------------------------------
  19. % Import data
  20. samplePeriod = 1/256;
  21. xIMUdata = xIMUdataClass(filePath, 'InertialMagneticSampleRate', 1/samplePeriod);
  22. time = xIMUdata.CalInertialAndMagneticData.Time;
  23. gyrX = xIMUdata.CalInertialAndMagneticData.Gyroscope.X;
  24. gyrY = xIMUdata.CalInertialAndMagneticData.Gyroscope.Y;
  25. gyrZ = xIMUdata.CalInertialAndMagneticData.Gyroscope.Z;
  26. accX = xIMUdata.CalInertialAndMagneticData.Accelerometer.X;
  27. accY = xIMUdata.CalInertialAndMagneticData.Accelerometer.Y;
  28. accZ = xIMUdata.CalInertialAndMagneticData.Accelerometer.Z;
  29. clear('xIMUdata');
  30. % -------------------------------------------------------------------------
  31. % Manually frame data
  32. % startTime = 0;
  33. % stopTime = 10;
  34. indexSel = find(sign(time-startTime)+1, 1) : find(sign(time-stopTime)+1, 1);
  35. time = time(indexSel);
  36. gyrX = gyrX(indexSel, :);
  37. gyrY = gyrY(indexSel, :);
  38. gyrZ = gyrZ(indexSel, :);
  39. accX = accX(indexSel, :);
  40. accY = accY(indexSel, :);
  41. accZ = accZ(indexSel, :);
  42. % -------------------------------------------------------------------------
  43. % Detect stationary periods
  44. % Compute accelerometer magnitude
  45. acc_mag = sqrt(accX.*accX + accY.*accY + accZ.*accZ);
  46. % HP filter accelerometer data
  47. filtCutOff = 0.001;
  48. [b, a] = butter(1, (2*filtCutOff)/(1/samplePeriod), 'high');
  49. acc_magFilt = filtfilt(b, a, acc_mag);
  50. % Compute absolute value
  51. acc_magFilt = abs(acc_magFilt);
  52. % LP filter accelerometer data
  53. filtCutOff = 5;
  54. [b, a] = butter(1, (2*filtCutOff)/(1/samplePeriod), 'low');
  55. acc_magFilt = filtfilt(b, a, acc_magFilt);
  56. % Threshold detection
  57. stationary = acc_magFilt < 0.05;
  58. % -------------------------------------------------------------------------
  59. % Plot data raw sensor data and stationary periods
  60. figure('Position', [9 39 900 600], 'NumberTitle', 'off', 'Name', 'Sensor Data');
  61. ax(1) = subplot(2,1,1);
  62. hold on;
  63. plot(time, gyrX, 'r');
  64. plot(time, gyrY, 'g');
  65. plot(time, gyrZ, 'b');
  66. title('Gyroscope');
  67. xlabel('Time (s)');
  68. ylabel('Angular velocity (^\circ/s)');
  69. legend('X', 'Y', 'Z');
  70. hold off;
  71. ax(2) = subplot(2,1,2);
  72. hold on;
  73. plot(time, accX, 'r');
  74. plot(time, accY, 'g');
  75. plot(time, accZ, 'b');
  76. plot(time, acc_magFilt, ':k');
  77. plot(time, stationary, 'k', 'LineWidth', 2);
  78. title('Accelerometer');
  79. xlabel('Time (s)');
  80. ylabel('Acceleration (g)');
  81. legend('X', 'Y', 'Z', 'Filtered', 'Stationary');
  82. hold off;
  83. linkaxes(ax,'x');
  84. % -------------------------------------------------------------------------
  85. % Compute orientation
  86. quat = zeros(length(time), 4);
  87. AHRSalgorithm = AHRS('SamplePeriod', 1/256, 'Kp', 1, 'KpInit', 1);
  88. % Initial convergence¼ÆËã³õʼËÄÔªÊý
  89. initPeriod = 2;
  90. indexSel = 1 : find(sign(time-(time(1)+initPeriod))+1, 1);
  91. for i = 1:2000
  92. AHRSalgorithm.UpdateIMU([0 0 0], [mean(accX(indexSel)) mean(accY(indexSel)) mean(accZ(indexSel))]);
  93. end
  94. % For all data
  95. for t = 1:length(time)
  96. if(stationary(t))
  97. AHRSalgorithm.Kp = 0.5;
  98. else
  99. AHRSalgorithm.Kp = 0;
  100. end
  101. AHRSalgorithm.UpdateIMU(deg2rad([gyrX(t) gyrY(t) gyrZ(t)]), [accX(t) accY(t) accZ(t)]);
  102. quat(t,:) = AHRSalgorithm.Quaternion;
  103. end
  104. % -------------------------------------------------------------------------
  105. % Compute translational accelerations
  106. % Rotate body accelerations to Earth frame
  107. acc = quaternRotate([accX accY accZ], quaternConj(quat));
  108. % % Remove gravity from measurements
  109. % acc = acc - [zeros(length(time), 2) ones(length(time), 1)]; % unnecessary due to velocity integral drift compensation
  110. % Convert acceleration measurements to m/s/s
  111. acc = acc * 9.81;
  112. % Plot translational accelerations
  113. figure('Position', [9 39 900 300], 'NumberTitle', 'off', 'Name', 'Accelerations');
  114. hold on;
  115. plot(time, acc(:,1), 'r');
  116. plot(time, acc(:,2), 'g');
  117. plot(time, acc(:,3), 'b');
  118. title('Acceleration');
  119. xlabel('Time (s)');
  120. ylabel('Acceleration (m/s/s)');
  121. legend('X', 'Y', 'Z');
  122. hold off;
  123. % -------------------------------------------------------------------------
  124. % Compute translational velocities
  125. acc(:,3) = acc(:,3) - 9.81;
  126. % Integrate acceleration to yield velocity
  127. vel = zeros(size(acc));
  128. for t = 2:length(vel)
  129. vel(t,:) = vel(t-1,:) + acc(t,:) * samplePeriod;
  130. if(stationary(t) == 1)
  131. vel(t,:) = [0 0 0]; % force zero velocity when foot stationary
  132. end
  133. end
  134. % Compute integral drift during non-stationary periods
  135. velDrift = zeros(size(vel));
  136. stationaryStart = find([0; diff(stationary)] == -1);
  137. stationaryEnd = find([0; diff(stationary)] == 1);
  138. for i = 1:numel(stationaryEnd)
  139. driftRate = vel(stationaryEnd(i)-1, :) / (stationaryEnd(i) - stationaryStart(i));
  140. enum = 1:(stationaryEnd(i) - stationaryStart(i));
  141. drift = [enum'*driftRate(1) enum'*driftRate(2) enum'*driftRate(3)];
  142. velDrift(stationaryStart(i):stationaryEnd(i)-1, :) = drift;
  143. end
  144. % Remove integral drift
  145. vel = vel - velDrift;
  146. % Plot translational velocity
  147. figure('Position', [9 39 900 300], 'NumberTitle', 'off', 'Name', 'Velocity');
  148. hold on;
  149. plot(time, vel(:,1), 'r');
  150. plot(time, vel(:,2), 'g');
  151. plot(time, vel(:,3), 'b');
  152. title('Velocity');
  153. xlabel('Time (s)');
  154. ylabel('Velocity (m/s)');
  155. legend('X', 'Y', 'Z');
  156. hold off;
  157. % -------------------------------------------------------------------------
  158. % Compute translational position
  159. % Integrate velocity to yield position
  160. pos = zeros(size(vel));
  161. for t = 2:length(pos)
  162. pos(t,:) = pos(t-1,:) + vel(t,:) * samplePeriod; % integrate velocity to yield position
  163. end
  164. % Plot translational position
  165. figure('Position', [9 39 900 600], 'NumberTitle', 'off', 'Name', 'Position');
  166. hold on;
  167. plot(time, pos(:,1), 'r');
  168. plot(time, pos(:,2), 'g');
  169. plot(time, pos(:,3), 'b');
  170. title('Position');
  171. xlabel('Time (s)');
  172. ylabel('Position (m)');
  173. legend('X', 'Y', 'Z');
  174. hold off;
  175. % -------------------------------------------------------------------------
  176. % Plot 3D foot trajectory
  177. % % Remove stationary periods from data to plot
  178. % posPlot = pos(find(~stationary), :);
  179. % quatPlot = quat(find(~stationary), :);
  180. posPlot = pos;
  181. quatPlot = quat;
  182. % Extend final sample to delay end of animation
  183. extraTime = 20;
  184. onesVector = ones(extraTime*(1/samplePeriod), 1);
  185. posPlot = [posPlot; [posPlot(end, 1)*onesVector, posPlot(end, 2)*onesVector, posPlot(end, 3)*onesVector]];
  186. quatPlot = [quatPlot; [quatPlot(end, 1)*onesVector, quatPlot(end, 2)*onesVector, quatPlot(end, 3)*onesVector, quatPlot(end, 4)*onesVector]];
  187. % Create 6 DOF animation
  188. SamplePlotFreq = 4;
  189. Spin = 120;
  190. SixDofAnimation(posPlot, quatern2rotMat(quatPlot), ...
  191. 'SamplePlotFreq', SamplePlotFreq, 'Trail', 'All', ...
  192. 'Position', [9 39 1280 768], 'View', [(100:(Spin/(length(posPlot)-1)):(100+Spin))', 10*ones(length(posPlot), 1)], ...
  193. 'AxisLength', 0.1, 'ShowArrowHead', false, ...
  194. 'Xlabel', 'X (m)', 'Ylabel', 'Y (m)', 'Zlabel', 'Z (m)', 'ShowLegend', false, ...
  195. 'CreateAVI', false, 'AVIfileNameEnum', false, 'AVIfps', ((1/samplePeriod) / SamplePlotFreq));