-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathP3_InclineForceProcessing.m
215 lines (171 loc) · 5.91 KB
/
P3_InclineForceProcessing.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
function TrialData = P3_InclineForceProcessing(TrialData,FlatTrial,Mtread,Fthres,PlateOrigin,pltflag)
%This function takes the force data from the local coordinate system into
%the global coordinate system. This is only for trials when the treadmill
%is inclined
% TrialData = data processing structure
% FlatTrial = data processing structure from a flat walking trial, this
% trial must have the same 3 treadmill markers present
% Mtread = labels of the markers on the treadmill, order is origin,
% primary axis and secondary axis
% Fthres = force threshold for computing CoP
% PlateOrigin = 1x2 array with the corner number that the origin of the
% plate is located, use zero if the origin is at the center of the plate
% pltflag = plot flag
% Note the moment added to the trial data is the free moment acting on
% the foot, not the moment measured by the force plate
% FreeMoment = Mz - Fy*CoPx + Fx*CoPx
%Originally Written By: Aaron N. Best (Apr 2023)
%Update Record:
%Aug 2023 - Modidied to require only three markers in the specified order
%(Aaron N. Best)
%% Check to see if pltflag is given
if nargin == 5
pltflag = 0;
end
%% Find the location of the treadmill markers each dataset
Flat_names = fieldnames(FlatTrial.MarkerData.Trajectories);
Incline_names = fieldnames(TrialData.MarkerData.Trajectories);
Flat_ind = NaN(length(Mtread),1);
Incline_ind = NaN(length(Mtread),1);
for i = 1:length(Flat_names)
for j = 1:length(Mtread)
if strcmp(Mtread(1,j),Flat_names{i})
Flat_ind(j,1) = i;
end
end
end
for i = 1:length(Incline_names)
for j = 1:length(Mtread)
if strcmp(Mtread(1,j),Incline_names{i})
Incline_ind(j,1) = i;
end
end
end
%% Pull out the treadmill markers in the first frame
Incline_tmark = NaN(3,3);
Flat_tmark = NaN(3,3);
for i = 1:length(Mtread)
Incline_tmark(i,:) = TrialData.MarkerData.Trajectories.(Incline_names{Incline_ind(i)})(1,:);
Flat_tmark(i,:) = FlatTrial.MarkerData.Trajectories.(Flat_names{Flat_ind(i)})(1,:);
end
%% Setup Flat and Inclined Coordinate Systems
%Inclined Coordinate System
O = Incline_tmark(1,:);
X = Incline_tmark(2,:) - Incline_tmark(1,:);
V = Incline_tmark(3,:) - Incline_tmark(1,:);
Y = cross(X,V);
Z = cross(X,Y);
X = X./norm(X);
Y = Y./norm(Y);
Z = Z./norm(Z);
T_I = [X',Y',Z',O';0 0 0 1];
%Flat coordinate system
O = Flat_tmark(1,:);
X = Flat_tmark(2,:) - Flat_tmark(1,:);
V = Flat_tmark(3,:) - Flat_tmark(1,:);
Y = cross(X,V);
Z = cross(X,Y);
X = X./norm(X);
Y = Y./norm(Y);
Z = Z./norm(Z);
T_F = [X',Y',Z',O';0 0 0 1];
%Rotate the global axis
T_GI = (T_I)*(T_F^-1); %Incline
TrialData.GroundPlane = T_GI;
%% Iterate through the plates
plates = fieldnames(TrialData.ForceData);
for i = 1:length(plates)
%% Rotate the corners of the treadmill
tread_corners = FlatTrial.ForceData.(plates{i}).PlateCorners;
incline_corners = NaN(size(tread_corners));
for j = 1:length(tread_corners(:,1))
p = [tread_corners(j,:)';1];
p = T_GI*p;
incline_corners(j,:) = p(1:3)';
end
FlatTrial.ForceData.(plates{i}).PlateCorners = incline_corners;
%% Create the coordinate systems for the plates
curr_corner = PlateOrigin(i);
%center of the plate
if curr_corner == 0
Oflat = mean(tread_corners);
else
Oflat = tread_corners(curr_corner,:);
end
%% Pull out the forces, moments, and CoP
% need to flip the y to make it right handed
Force = TrialData.ForceData.(plates{i}).Force;
Force = [Force(:,1),-1*Force(:,2),Force(:,3)];
Moment = TrialData.ForceData.(plates{i}).Moment;
Moment = [Moment(:,1),-1*Moment(:,2),Moment(:,3)];
%% Compute the CoP in the flat system
CoP = NaN(size(Force));
for j = 1:length(CoP(:,1))
if Force(j,3) > Fthres
CoP(j,1) = -1*Moment(j,2)/Force(j,3);
CoP(j,2) = Moment(j,1)/Force(j,3);
CoP(j,3) = 0;
else
CoP(j,:) = [0 0 0];
end
end
%% Compute the free Moment
FreeMoment = zeros(size(Moment));
FreeMoment(:,3) = Moment(:,3) - Force(:,2).*CoP(:,1) + Force(:,1).*CoP(:,2);
%% Translate the CoP
CoP(:,1) = CoP(:,1) + Oflat(:,1);
CoP(:,2) = CoP(:,2) + Oflat(:,2);
%% Put the Forces and Moments in the Tilted Global System
for j = 1:length(Force)
F = T_GI*[Force(j,:)';1];
Force(j,:) = F(1:3)';
M = T_GI*[FreeMoment(j,:)';1];
FreeMoment(j,:) = M(1:3)';
C = T_GI*[CoP(j,:)';1];
CoP(j,:) = C(1:3)';
end
%% Rewrite all the data to TrialData
TrialData.ForceData.(plates{i}).Force = Force;
TrialData.ForceData.(plates{i}).Moment = FreeMoment;
TrialData.ForceData.(plates{i}).CoP = CoP;
end
%% Optional Plotting
if pltflag == 1
figure;
subplot(2,4,[1 2]);
hold on;
for i = 1:length(plates)
plot(TrialData.ForceData.(plates{i}).Force(:,3))
end
title('Vertical GRF Force');
xlabel('Frame');
ylabel('Force (N)');
hold off;
subplot(2,4,[5 6]);
hold on;
for i = 1:length(plates)
plot(TrialData.ForceData.(plates{i}).Moment(:,3))
end
title('Free Momemt');
xlabel('Frame');
ylabel('Moment (Nm)');
hold off;
subplot(2,4,[3 4 7 8]);
hold on;
axis equal;
for i = 1:length(plates)
if i == 1
plot3(TrialData.ForceData.(plates{i}).CoP(:,1),TrialData.ForceData.(plates{i}).CoP(:,2),...
TrialData.ForceData.(plates{i}).CoP(:,3),'.r');
else
plot3(TrialData.ForceData.(plates{i}).CoP(:,1),TrialData.ForceData.(plates{i}).CoP(:,2),...
TrialData.ForceData.(plates{i}).CoP(:,3),'.b');
end
plot3(TrialData.ForceData.(plates{i}).PlateCorners(:,1),TrialData.ForceData.(plates{i}).PlateCorners(:,2),...
TrialData.ForceData.(plates{i}).PlateCorners(:,3),'.k','MarkerSize',15);
end
title('CoP');
view([45,45]);
hold off;
end
end