-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlint.m
139 lines (112 loc) · 4.13 KB
/
lint.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
function errors = lint(episode)
checks = {
'sensor rates' @sensor_rates
'sensor magnitudes' @sensor_mags
'motion track' @motion_track
'images' @images
};
errors = {};
for i = 1:size(checks,1)
fprintf('Checking %s...\n', checks{i,1});
errors = [errors
checks{i,2}(episode)];
end
end
function check(msg, val, err)
fprintf('\tChecking %s...\n', msg);
if ~val
assignin('caller', 'errors', [evalin('caller', 'errors'); err]);
end
end
function errors = sensor_rates(episode)
rates = {
'v' 15
'int' 3000
'acc' 3000
'imu.acc' 1340
'imu.gyro' 750
'imu.mic' 3000
'bvei' 3000
'biws' 3000
'bai' 3000
};
if strcmp(episode.flow, 'optocam')
rates(end+1,:) = {'sensor.opto' 1000};
elseif strcmp(episode.flow, 'biocam')
rates(end+1,:) = {'sensor.bio' 100 };
end
errors = {};
for i = 1:size(rates,1)
k = rates{i,1};
if strfind(k, '.')
kk = strsplit(k, '.');
rate = 1/mean(diff(episode.(kk{1}).(kk{2})(:,1)));
else
rate = 1/mean(diff(episode.(k)(:,1)));
end
check(sprintf('sensor rate of %s', k), ...
abs(rates{i,2} - rate)/rates{i,2} <= 0.05, ...
sprintf('Sensor rate of %s is %g but it should be %g!', k, rate, rates{i,2}));
end
end
function errors = sensor_mags(episode)
errors = {};
check('force', ...
all(episode.biws(:,4) > 0), ...
'Rectified Z force should be all positive!');
if strcmp(episode.flow, 'stickcam')
mic_freq = abs(fft(episode.imu.mic(:,2) - mean(episode.imu.mic(:,2))));
check('sound', ...
max(mic_freq(10:round(end/4))) / max(mic_freq(round(end/4):round(end/2))) < 2, ...
'Microphone frequency content is too uneven!');
end
dacc = bsxfun(@minus, episode.bai(:,2:4), mean(episode.bai(:,2:4)));
check('digital acceleration magnitude', ...
all(std(dacc) > 0.1), ...
'End-effector accelerometer data should be nonzero!');
aacc = bsxfun(@minus, episode.imu.acc(:,2:4), mean(episode.imu.acc(:,2:4)));
check('analog acceleration', ...
all(std(aacc) > 0.1), ...
'Analog accelerometer data should be nonzero!');
agyro = bsxfun(@minus, episode.imu.gyro(:,2:4), mean(episode.imu.gyro(:,2:4)));
check('analog gyroscope', ...
all(std(agyro) > 0.1), ...
'Analog gyroscope data should be nonzero!');
end
function errors = motion_track(episode)
errors = {};
% FIXME why are there any NaNs at all
first_nan = min([...
find(isnan(episode.bvei(:,2)),1) ...
find(isnan(episode.bvei(:,3)),1) ...
find(isnan(episode.bvei(:,4)),1) ...
]);
check('position NaN', ...
first_nan/size(episode.bvei, 1) > 0.98, ...
'Position should not be NaN until the very end!');
p = RANSAC(episode.bvei(1:first_nan-1,2:4)', ...
struct('sigma', 0.5, ...
'est_fun', @estimate_plane, ...
'man_fun', @error_plane, ...
'verbose', false));
normal = p.Theta(1:3)/sqrt(sum(p.Theta(1:3).^2));
check('position in plane', ...
nnz(p.CS)/first_nan > 0.5, ...
'Motion should be in-plane!');
check('plane orientation', ...
abs(dot(normal, [0 0 1])) > 0.98, ...
'Motion track should in the horizontal plane!');
plane = fitPlane(episode.bvei(p.CS,2:4));
inplane = planePosition(episode.bvei(p.CS,2:4), plane);
check('exploration area', ...
nth(2, 2, @convhull, inplane) > 50^2, ...
'Exploration area should be at least 50 mm^2!');
end
function errors = images(episode)
errors = {};
frames = episode.april.keys;
img = imread(fullfile(episode.datadir, episode.date, episode.flow, episode.i, 'bluefox', sprintf('bluefox%d.png', frames{1})));
check('image brightness', ...
mean(img(:)) > 80, ...
'Image is too dark!');
end