| 1 | |
|---|
| 2 | %% prepare |
|---|
| 3 | COM_CloseNXT all |
|---|
| 4 | close all |
|---|
| 5 | clear all |
|---|
| 6 | format compact |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | %% open NXT |
|---|
| 10 | h = COM_OpenNXT('bluetooth.ini', 'check'); |
|---|
| 11 | COM_SetDefaultNXT(h); |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | %% settings |
|---|
| 15 | port = MOTOR_B; |
|---|
| 16 | measuringTime = 3; % seconds |
|---|
| 17 | %programName = 'test'; |
|---|
| 18 | %programName = 'TestRampMotorCo'; |
|---|
| 19 | programName = 'ManualMotorRamp'; |
|---|
| 20 | %programName = 'NXTG_Wait1100_M'; |
|---|
| 21 | %programName = 'NXTG_MovePwr60'; |
|---|
| 22 | %programName = 'NXTG_MotorPwr60'; |
|---|
| 23 | |
|---|
| 24 | |
|---|
| 25 | %% precall functions to fill matlab cache |
|---|
| 26 | tic; |
|---|
| 27 | tmp = toc; |
|---|
| 28 | tmp = NXT_GetOutputState(port); |
|---|
| 29 | |
|---|
| 30 | |
|---|
| 31 | |
|---|
| 32 | |
|---|
| 33 | %% initialize vars |
|---|
| 34 | runState = zeros(measuringTime * 1000, 1); |
|---|
| 35 | mode = runState; |
|---|
| 36 | regMode = runState; |
|---|
| 37 | tachoCount = runState; |
|---|
| 38 | power = runState; |
|---|
| 39 | time = runState; |
|---|
| 40 | speed = runState; |
|---|
| 41 | |
|---|
| 42 | |
|---|
| 43 | %% start embedded program |
|---|
| 44 | NXT_StopProgram(); |
|---|
| 45 | pause(1); |
|---|
| 46 | NXT_StartProgram(programName); |
|---|
| 47 | pause(1) |
|---|
| 48 | |
|---|
| 49 | |
|---|
| 50 | |
|---|
| 51 | |
|---|
| 52 | %% record stuff... |
|---|
| 53 | j = 0; |
|---|
| 54 | tic; |
|---|
| 55 | while(toc < measuringTime) |
|---|
| 56 | j = j + 1; |
|---|
| 57 | |
|---|
| 58 | tmp = NXT_GetOutputState(port); |
|---|
| 59 | |
|---|
| 60 | time(j) = toc; |
|---|
| 61 | runState(j) = tmp.RunStateByte; |
|---|
| 62 | mode(j) = tmp.Mode; |
|---|
| 63 | regMode(j) = tmp.RegModeByte; |
|---|
| 64 | tachoCount(j) = tmp.TachoCount; |
|---|
| 65 | power(j) = tmp.Power; |
|---|
| 66 | |
|---|
| 67 | |
|---|
| 68 | end%while |
|---|
| 69 | |
|---|
| 70 | |
|---|
| 71 | %% cut off |
|---|
| 72 | time = time(1:j); |
|---|
| 73 | runState = runState(1:j); |
|---|
| 74 | mode = mode(1:j); |
|---|
| 75 | regMode = regMode(1:j); |
|---|
| 76 | tachoCount = tachoCount(1:j); |
|---|
| 77 | power = power(1:j); |
|---|
| 78 | speed = speed(1:j); |
|---|
| 79 | speed1 = speed; |
|---|
| 80 | speed2 = speed; |
|---|
| 81 | speed3 = speed; |
|---|
| 82 | accel = speed; |
|---|
| 83 | |
|---|
| 84 | %% smooth out tachoCount |
|---|
| 85 | tachoCount = moving_average(tachoCount, 4); |
|---|
| 86 | |
|---|
| 87 | |
|---|
| 88 | %% calculate real speed, simple method |
|---|
| 89 | % central difference, only accurate to order of h (i.e. delta t) |
|---|
| 90 | % also very sensitive to noise |
|---|
| 91 | speed0 = [0; diff(tachoCount) ./ diff(time)]; |
|---|
| 92 | |
|---|
| 93 | %% calculate real speed |
|---|
| 94 | for j = 2 : length(tachoCount) - 1 |
|---|
| 95 | % see http: |
|---|
| 96 | % sheet 18 |
|---|
| 97 | |
|---|
| 98 | % 3 points for lagrangian interpolation |
|---|
| 99 | t0 = time(j-1); |
|---|
| 100 | t1 = time(j); |
|---|
| 101 | t2 = time(j+1); |
|---|
| 102 | % we evaluate at t1... |
|---|
| 103 | t = t1; |
|---|
| 104 | |
|---|
| 105 | speed(j) = ((2*t - (t1 + t2)) / ((t0 - t1) * (t0 - t2))) * tachoCount(j-1); |
|---|
| 106 | speed(j) = speed(j) + ((2*t - (t0 + t2)) / ((t1 - t0) * (t1 - t2))) * tachoCount(j); |
|---|
| 107 | speed(j) = speed(j) + ((2*t - (t0 + t1)) / ((t2 - t0) * (t2 - t1))) * tachoCount(j+1); |
|---|
| 108 | |
|---|
| 109 | end%for |
|---|
| 110 | speed1 = speed; |
|---|
| 111 | |
|---|
| 112 | %% calculate real speed, alternative method... |
|---|
| 113 | for j = 3 : length(tachoCount) - 2 |
|---|
| 114 | % use central differences aka the 5-point-stencil |
|---|
| 115 | % average spacing (the best we can do) |
|---|
| 116 | h = (time(j+2) - time(j-2)) / 5; |
|---|
| 117 | speed2(j) = (tachoCount(j-2) - 8*tachoCount(j-1) + 8*tachoCount(j+1) - tachoCount(j+2)) / (12*h); |
|---|
| 118 | end%for |
|---|
| 119 | |
|---|
| 120 | %% final algo, this time 9-point method... |
|---|
| 121 | coeffs = [3; -32; 168; -672; 0; 672; -168; 32; -3]; |
|---|
| 122 | for j = 5 : length(tachoCount) - 4 |
|---|
| 123 | % use central differences aka the 9-point-stencil |
|---|
| 124 | % average spacing (the best we can do) |
|---|
| 125 | h = (time(j+4) - time(j-4)) / 9; |
|---|
| 126 | for k = 1 : 9 |
|---|
| 127 | speed3(j) = speed3(j) + coeffs(k) * tachoCount(j + k-5); |
|---|
| 128 | end%for |
|---|
| 129 | speed3(j) = speed3(j) / (840*h); |
|---|
| 130 | |
|---|
| 131 | end%for |
|---|
| 132 | |
|---|
| 133 | |
|---|
| 134 | % I finally decided to take speed3 |
|---|
| 135 | n = 4; |
|---|
| 136 | speed = moving_average(speed3, n); |
|---|
| 137 | |
|---|
| 138 | |
|---|
| 139 | %% get acceleration |
|---|
| 140 | coeffs = [3; -32; 168; -672; 0; 672; -168; 32; -3]; |
|---|
| 141 | for j = 5 : length(tachoCount) - 4 |
|---|
| 142 | % use central differences aka the 9-point-stencil |
|---|
| 143 | % average spacing (the best we can do) |
|---|
| 144 | h = (time(j+4) - time(j-4)) / 9; |
|---|
| 145 | accel(j) = 0; |
|---|
| 146 | for k = 1 : 9 |
|---|
| 147 | accel(j) = accel(j) + coeffs(k) * speed(j + k-5); |
|---|
| 148 | end%for |
|---|
| 149 | accel(j) = accel(j) / (840*h); |
|---|
| 150 | |
|---|
| 151 | end%for |
|---|
| 152 | |
|---|
| 153 | |
|---|
| 154 | %% plot position, speeds |
|---|
| 155 | |
|---|
| 156 | |
|---|
| 157 | figure('Name', 'Speed vs. Time') |
|---|
| 158 | hold all |
|---|
| 159 | h1 = plot(time, tachoCount, '.-'); |
|---|
| 160 | h2 = plot(time, power * 10, '.-'); |
|---|
| 161 | |
|---|
| 162 | % n = 4; |
|---|
| 163 | % plot(time, moving_average(speed0, n) .* 0.5, '-'); |
|---|
| 164 | % plot(time, moving_average(speed1 , n) .* 0.5, '-'); |
|---|
| 165 | % plot(time, moving_average(speed2, n) .* 0.5, '-'); |
|---|
| 166 | % plot(time, moving_average(speed3, n) .* 0.5, '-'); |
|---|
| 167 | |
|---|
| 168 | h3 = plot(time, speed .* 0.5, '-'); |
|---|
| 169 | h4 = plot(time, moving_average(accel, 10) .* 0.05, '-'); |
|---|
| 170 | |
|---|
| 171 | %plot(time, runState * 3, '-') |
|---|
| 172 | %plot(time, mode * 3, '-') |
|---|
| 173 | |
|---|
| 174 | offset = true; |
|---|
| 175 | for j = 2 : length(mode) |
|---|
| 176 | if mode(j) ~= mode(j-1) |
|---|
| 177 | x = time(j); |
|---|
| 178 | y = -350; |
|---|
| 179 | offset = ~offset; |
|---|
| 180 | if offset y = y + 50; end |
|---|
| 181 | |
|---|
| 182 | [isMOTORON isBRAKE isREGULATED] = byte2outputmode(mode(j)); |
|---|
| 183 | if isMOTORON; name = 'ON '; else name = 'OFF '; end |
|---|
| 184 | if isBRAKE; name = [name 'BRK ']; end |
|---|
| 185 | if isREGULATED; name = [name 'REG ']; end |
|---|
| 186 | |
|---|
| 187 | c = [191/255 191/255 0]; |
|---|
| 188 | text(time(j), y, name, 'Color', c); |
|---|
| 189 | %set(h5, 'EdgeColor', 'black') |
|---|
| 190 | h5 = line([x; x], [0; y * 1.1], 'Color', c); |
|---|
| 191 | end%if |
|---|
| 192 | end%for |
|---|
| 193 | |
|---|
| 194 | offset = true; |
|---|
| 195 | for j = 2 : length(runState) |
|---|
| 196 | if runState(j) ~= runState(j-1) |
|---|
| 197 | x = time(j); |
|---|
| 198 | y = -200; |
|---|
| 199 | offset = ~offset; |
|---|
| 200 | if offset y = y + 50; end |
|---|
| 201 | |
|---|
| 202 | c = [191/255 0 191/255]; |
|---|
| 203 | text(time(j), y, byte2runstate(runState(j)), 'Color', c); |
|---|
| 204 | %set(h6, 'EdgeColor', 'black') |
|---|
| 205 | h6 = line([x; x], [0; y * 1.1], 'Color', c); |
|---|
| 206 | end%if |
|---|
| 207 | end%for |
|---|
| 208 | |
|---|
| 209 | |
|---|
| 210 | h7 = plot([0; measuringTime], [0; 0], '-k'); |
|---|
| 211 | h8 = plot([0; measuringTime], [1000; 1000], '-k'); |
|---|
| 212 | |
|---|
| 213 | |
|---|
| 214 | |
|---|
| 215 | %legend('TachCount', 'Power * 10', 'Simple Diff', 'Lagrangian 3-point-poly', '5-point-stencil', '9-point-stencil', 'Start: 0', 'Target: 1000') |
|---|
| 216 | legend([h1 h2 h3 h4 h5 h6 h7 h8], 'TachoCount', 'Power * 10', 'Speed (avg.) / 2', 'Acceleration (avg.) / 20', 'MODE', 'RUNSTATE', 'Start: 0', 'Target: 1000') |
|---|
| 217 | |
|---|
| 218 | axis([0 measuringTime -500 1100]) |
|---|
| 219 | xlabel('Time [s]') |
|---|
| 220 | ylabel('TachoCount [degrees]') |
|---|
| 221 | |
|---|
| 222 | text(measuringTime, -570, '(C) Institute of Imaging & Computer Vision, RWTH Aachen University', 'HorizontalAlignment', 'right'); |
|---|
| 223 | text(measuringTime, -610, 'http: |
|---|
| 224 | |
|---|
| 225 | |
|---|
| 226 | |
|---|
| 227 | |
|---|
| 228 | %% Plot everything vs position! |
|---|
| 229 | figure('Name', 'Speed vs. Time') |
|---|
| 230 | hold all |
|---|
| 231 | |
|---|
| 232 | |
|---|
| 233 | tmp = find(tachoCount); |
|---|
| 234 | first = tmp(1); |
|---|
| 235 | [forget last] = max(tachoCount); |
|---|
| 236 | |
|---|
| 237 | |
|---|
| 238 | h1 = plot([tachoCount(first); tachoCount(last)], [0; 0], '-'); |
|---|
| 239 | |
|---|
| 240 | h2 = plot(tachoCount(first:last), power(first:last) * 10, '.-'); |
|---|
| 241 | |
|---|
| 242 | h3 = plot(tachoCount(first:last), speed(first:last) .* 0.5, '-'); |
|---|
| 243 | h4 = plot(tachoCount(first:last), moving_average(accel(first:last), 10) .* 0.05, '-'); |
|---|
| 244 | |
|---|
| 245 | |
|---|
| 246 | %plot(time, runState * 3, '-') |
|---|
| 247 | %plot(time, mode * 3, '-') |
|---|
| 248 | |
|---|
| 249 | offset = true; |
|---|
| 250 | for j = 2 : length(mode) |
|---|
| 251 | if mode(j) ~= mode(j-1) |
|---|
| 252 | x = tachoCount(j); |
|---|
| 253 | y = -350; |
|---|
| 254 | offset = ~offset; |
|---|
| 255 | if offset, y = y + 50; end |
|---|
| 256 | |
|---|
| 257 | [isMOTORON isBRAKE isREGULATED] = byte2outputmode(mode(j)); |
|---|
| 258 | if isMOTORON; name = 'ON '; else name = 'OFF '; end |
|---|
| 259 | if isBRAKE; name = [name 'BRK ']; end |
|---|
| 260 | if isREGULATED; name = [name 'REG ']; end |
|---|
| 261 | |
|---|
| 262 | c = [191/255 191/255 0]; |
|---|
| 263 | text(tachoCount(j), y, name, 'Color', c); |
|---|
| 264 | %set(h5, 'EdgeColor', 'black') |
|---|
| 265 | h5 = line([x; x], [0; y * 1.1], 'Color', c); |
|---|
| 266 | end%if |
|---|
| 267 | end%for |
|---|
| 268 | |
|---|
| 269 | offset = true; |
|---|
| 270 | for j = 2 : length(runState) |
|---|
| 271 | if runState(j) ~= runState(j-1) |
|---|
| 272 | x = tachoCount(j); |
|---|
| 273 | y = -200; |
|---|
| 274 | offset = ~offset; |
|---|
| 275 | if offset, y = y + 50; end |
|---|
| 276 | |
|---|
| 277 | c = [191/255 0 191/255]; |
|---|
| 278 | text(tachoCount(j), y, byte2runstate(runState(j)), 'Color', c); |
|---|
| 279 | %set(h6, 'EdgeColor', 'black') |
|---|
| 280 | h6 = line([x; x], [0; y * 1.1], 'Color', c); |
|---|
| 281 | end%if |
|---|
| 282 | end%for |
|---|
| 283 | |
|---|
| 284 | |
|---|
| 285 | |
|---|
| 286 | %legend('TachCount', 'Power * 10', 'Simple Diff', 'Lagrangian 3-point-poly', '5-point-stencil', '9-point-stencil', 'Start: 0', 'Target: 1000') |
|---|
| 287 | legend([h1 h2 h3 h4 h5 h6], '0-line (x-axis)', 'Power * 10', 'Speed (avg.) / 2', 'Acceleration (avg.) / 20', 'MODE', 'RUNSTATE') |
|---|
| 288 | |
|---|
| 289 | axis([tachoCount(first) tachoCount(last) -500 1100]) |
|---|
| 290 | xlabel('TachoCount [degrees]') |
|---|
| 291 | ylabel('Speed / Acceleration / Power') |
|---|
| 292 | |
|---|
| 293 | text(tachoCount(last), -570, '(C) Institute of Imaging & Computer Vision, RWTH Aachen University', 'HorizontalAlignment', 'right'); |
|---|
| 294 | text(tachoCount(last), -610, 'http: |
|---|