2% For LICENSE / TERMS OF USE, see the file LICENSE in the root directory of the repository.
9datapath = fullfile(datapath,
"ETH_Data/SonE_36/RawData/ZM");
13% manually find start and stop movement phases
14idx_tug_post = [999486, 1001570];
15idx_walk = [605943, 731541];
17%% Zero velocity detection
19zv_tug_post = zv(idx_tug_post(1):idx_tug_post(2));
20zv_walk = zv(idx_walk(1):idx_walk(2));
26ekf.
sigma_w_p = ekf.sigma_w_p * 5; % as not many zv points are available, trust in accel measurements must be bigger.
30ekf.z_acc = data.tt.acc(idx_tug_post(1):idx_tug_post(2),:)
';
31ekf.z_vel = zeros(size(ekf.z_acc));
32ekf.z_gyr = data.tt.gyr(idx_tug_post(1):idx_tug_post(2),:)' * pi/180; % convert to rad/s
33ekf.z_pos = zeros(size(ekf.z_acc));
34ekf.z_pos(1:2,:) = nan;
35ekf.z_pos(1:2,end-100:end) = 0;
36ekf.z_pos(1:2,1:100) = 0;
37ekf.z_yaw = nan(1, size(ekf.z_acc,2));
43a_x = mean(data.tt.acc(idx_tug_post(1):idx_tug_post(1)+200,1));
44a_y = mean(data.tt.acc(idx_tug_post(1):idx_tug_post(1)+200,2));
45a_z = mean(data.tt.acc(idx_tug_post(1):idx_tug_post(1)+200,3));
47% calculate initial orientation
48roll = atan2(a_y, a_z);
49pitch = atan2(-a_x, sqrt(a_y^2 + a_z^2));
50ekf.q_0 = quaternion([0, pitch, roll],
"eulerd",
"ZYX",
"frame").normalize.compact;
53smoothed = ekf.run(plot=
true);
58load(
"C:\Users\moss\OneDrive - ZHAW\MT\Measurements\ETH_Data\SonE_36\Processed\Vicon\matfiles\TUG_Post.mat")
59GT = VD.Marker.LTO3 / 1000;
60%GT = GT(240:2941,:); % trim away the jump
63smoothed_cld = pointCloud(smoothed(8:10,:)');
64tform = rigidtform3d([180,0,0], [0,0,0]);
65smoothed_cld = pctransform(smoothed_cld, tform);
67GT_cld = pointCloud(GT);
68[~, GT_cld] = pcregistericp(GT_cld, smoothed_cld, "Metric","pointToPoint", "MaxIterations", 200, "Verbose",false);
71GT_cld.Color = [0,1,0];
72GT_cld.Intensity = 10 * ones(GT_cld.Count,1);
73smoothed_cld.Color = [1,0,0];
77pcshow(GT_cld,"BackgroundColor","white");
79pcshow(smoothed_cld, "MarkerSize", 5);
90% initial gyroscope bias
91ekf.b_w_0 = [mean(data.tt.gyr(zv_walk(1:4000),1));mean(data.tt.gyr(zv_walk(1:4000),2));mean(data.tt.gyr(zv_walk(1:4000),3))] * pi / 180;
94ekf.P_0_b_w = 1e-6; % original 5e-3, trust the initial bias much
96ekf.var_gyr = 1e-4; % opriginal 12e-4, less trust in zero rotation
98% tune measurement noise
99%ekf.var_vel_ZUPT = 1e-1;
100ekf.var_acc_xy = 0.5e-3; %original: 45e-3
101ekf.var_acc_z = 1e-3; %original: 70e-3
102ekf.var_pos_pseudo = 1e-3; % very low trust, only a slight nudging
106ekf.sigma_w_p = ekf.sigma_w_p * 2; % as not many zv points are available, trust in accel measurements must be bigger.
110ekf.z_acc = data.tt.acc(idx_walk(1):idx_walk(2),:)';
111ekf.z_vel = zeros(size(ekf.z_acc));
112ekf.z_gyr = data.tt.gyr(idx_walk(1):idx_walk(2),:)' * pi/180; % convert to rad/s
113ekf.z_pos = zeros(size(ekf.z_acc));
114speed = 3.2/3.6; % m/s;
116% pseudo position update
117ekf.z_pos(1,92:end) = cumsum(speed * dt * ones(size(ekf.z_pos(1,92:end))));
118%ekf.z_pos(1:2,:) = nan;
121ekf.z_yaw = deg2rad(10) * ones(1, size(ekf.z_acc,2));
122%ekf.z_yaw = nan(1, size(ekf.z_acc,2));
127% mean accelerations during stance
128a_x = mean(data.tt.acc(zv_walk,1));
129a_y = mean(data.tt.acc(zv_walk,2));
130a_z = mean(data.tt.acc(zv_walk,3));
132% calculate initial orientation
133roll = atan2(a_y, a_z);
134pitch = atan2(-a_x, sqrt(a_y^2 + a_z^2));
136ekf.q_0 = quaternion([yaw, pitch, roll], "euler", "ZYX", "frame").normalize.compact;
139smoothed = ekf.run(plot=true);
143load("C:\Users\moss\OneDrive - ZHAW\MT\Measurements\ETH_Data\SonE_36\Processed\Vicon\matfiles\WN35.mat")
144GT = VD.Marker.LTO3 / 1000;
146v = diff(GT(:,2))/0.005;
150GT(:,2) = GT(:,2) - cumsum(speed * dt * ones(1,height(GT)))';
156%% show the Problem to Yong
158plot(data.tt.t, vecnorm(data.tt.acc,2,2))
159title("SonEMS 36 - TUG Pre (partially)")
161ylabel("||a||_2 [m/s^2]", Interpreter="tex")
163xlim([datetime("01.11.2022 10:25:38"), datetime("01.11.2022 10:25:43")])
165title("SonEMS 36 - Treadmill (partially)")
166xlim([datetime("01.11.2022 10:47:00"), datetime("01.11.2022 10:47:05")])
168test = vecnorm(data.tt.acc,2,2);
169TUG_test = test(254555:256260);
170WALK_test= test(649824:651544);
EKF1 is an implementation of a state estimator for JUMP sensors.
Property sigma_w_p
angular velocity standard deviation (default 876e-6 rad/s)
function jumpReadData(in filePath, in options)
function jumpZeroVelocityDetection(in data, in options)