Time normalize kinematic data for gait analyses
12 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Neil Mcdonald
am 2 Apr. 2023
Kommentiert: Star Strider
am 29 Aug. 2023
Hello, I am having a bit of a problem with implementing my code. I have a set of data for determining the angles of the hip and the knee. its a lot of data and i need to time normalise it in order to graph it and analize. I have tried doing it 2 ways but my angle graph doesnt look right.
I would really apreciate if someody could check my code and point at any mistakes im making and suggest a better way of coding, any tips, any help.
Here is code n1
clear all
close all
[filename,folder]= uigetfile('*.xlsx');
cd(folder);
%f=1;
t=0:0.01:36.13;
%y=sin(2*pi*f*t);
Marker_trajectories=readmatrix(filename,'Sheet','BE302 Walk trajectories','Range','B6:AW3619');
A=readmatrix(filename,'sheet','anthropometrics','range','A1:A8');
p1 = Marker_trajectories(:,46:48);
p2 = Marker_trajectories(:,43:45);
p3 = Marker_trajectories(:,40:42);
p4= Marker_trajectories(:,37:39);
p5= Marker_trajectories(:,34:36);
p6= Marker_trajectories(:,31:33);
p8= Marker_trajectories(:,28:30);
p9= Marker_trajectories(:,25:27);
p10= Marker_trajectories(:,22:24);
p11= Marker_trajectories(:,19:21);
p12 = Marker_trajectories(:,16:18);
p13 = Marker_trajectories(:,13:15);
p7a = Marker_trajectories(:,10:12);
p14a = Marker_trajectories(:,7:9);
p7b = Marker_trajectories(:,4:6);
p14b = Marker_trajectories(:,1:3);
p7=(p7a+p7b)/2;
p14=(p14a+p14b)/2;
p15=(p14a+p7b)/2;
y=p2(:,2)-p15(:,1);
u_foot = (p1-p2)./vecnorm(p1-p2);
w_foot = cross(p1-p3,p2-p3)./vecnorm(cross(p1-p3,p2-p3));
v_foot= w_foot.*u_foot;
v_calf = (p3-p5)./vecnorm(p3-p5);
u_calf = cross(p4-p5,p3-p5)./vecnorm(cross(p4-p5,p3-p5));
w_calf= u_calf.*v_calf;
v_pelvis = (p14-p7)./vecnorm(p14-p7);
w_pelvis = cross(p7-p15,p14-p15)./vecnorm(cross(p7-p15,p14-p15));
u_pelvis= v_pelvis.*w_pelvis;
p_ankle= p3+ 0.0164*A(5)*u_foot+0.392*A(5)*v_foot+0.478*A(7)*w_pelvis;
p_knee=p5+0.5*A(4)*w_calf;
p_hip=p15+0.598*A(1)*u_pelvis-0.29*A(1)*w_pelvis;
i_pelvis=-v_pelvis;
j_pelvis=u_pelvis;
k_pelvis=w_pelvis;
k_thigh = (p_hip-p_knee)./vecnorm(p_hip-p_knee);
j_thigh = cross(p6-p_hip,p_knee-p_hip)./vecnorm(cross(p6-p_hip,p_knee-p_hip));
i_thigh=j_thigh.*k_thigh;
k_calf = (p_knee-p_ankle)./vecnorm(p_knee-p_ankle);
j_calf = cross(p5-p_knee,p_ankle-p_knee)./vecnorm(cross(p5-p_knee,p_ankle-p_knee));
i_calf=j_calf.*k_calf;
a_hip=-atan(norm(dot(k_thigh,j_pelvis,2))./(dot(k_thigh,k_pelvis,2)))*180/pi;
b_hip=asin(dot(k_thigh,i_pelvis,2));
y_hip=-atan(dot(j_thigh,i_pelvis,2)./dot(i_thigh,i_pelvis,2));
a_knee=-atan(dot(k_calf,j_thigh,2)./dot(k_calf,k_thigh,2));
b_knee=asin(dot(k_calf,i_thigh,2));
y_knee=-atan(dot(j_calf,i_thigh,2)./dot(i_calf,i_thigh,2));
[peaks,i_peaks]=findpeaks((-y),'MinPeakDistance',100);
%1. % points of the gait cycle
gc_perc=0:1:100;
% 3.i_peaks- heel strikes. number of full gait cycles i_peaks-1
%heel_strikes=size(i_peaks);
%gait_cycle=heel_strikes-1;
for i=1:size(i_peaks,2)-1
i_gc=i_peaks(i):i_peaks(i+1);
% 4b) number of rows
num_rows=size(i_gc,2);
gc=0:1/num_rows:100;
gait_cycle=y(1,i_gc);
end
for j=1:size(i_peaks,2) -1
new_angle(:,ci) =interp1(a_hip,gc_perc,gc);
end
figure(1);
plot(new_angle,gc_perc);
I used findpeaks to seperate the gait cycles and there are 33 cycles in my data. to separate the gait cycles we use a formula provided
y=p2(:,2)-p15(:,1);
I am not sure how to apply the same principle to the rest of my data, i need to find the angles of hip and knee and i need to separate it into the gait cycles. But im getting an error Error in BE302_kinematics (line 86)
plot(new_angle,gc_perc); the program doesnt recognise the new_angle variable. I am not able to find what im doing wrong. So a wrote another code below:
F=a_hip;
x = linspace(0, 99, length(y));
z = 0:99;
y_z_normed = spline(x, y, z);
d=linspace(0,99,length(F));
a_hip_n=spline(d,F,z);
figure
subplot(2,1,1)
plot(y, 'b', 'LineWidth', 2)
xlim([0 length(y)])
title('Original Signal')
xlabel('Frames')
ylabel('a Hip')
subplot(2,1,2)
plot(y_z_normed, 'b', 'LineWidth', 2)
xlim([0 100])
title('Normalized Signal')
xlabel('Normalized Time (0-100%)')
ylabel('a Hip')
figure(3);
subplot(2,1,1)
plot(a_knee, 'b', 'LineWidth', 2)
xlim([0 length(a_knee)])
title('Original Signal')
xlabel('Frames')
ylabel('a Knee')
subplot(2,1,2)
plot(a_hip_n, 'b', 'LineWidth', 2)
xlim([0 100])
title('Normalized Signal')
xlabel('Normalized Time (0-100%)')
ylabel('a Knee')
with this i am getting a graph but it doesnt look right to me,
I also need all of the gait cycles to be graphed together from 0 to 100% on top of each other. I tried doing it this way:
I also need all of the gait cycles to be graphed together from 0 to 100% on top of each other. I tried doing it this way:[pks, locs] = findpeaks(y, 'MinPeakDist',50); % Determine Peaks & Indices
figure(1)
plot(a_hip, t)
hold on
plot(a_hip(locs), pks, '+r')
hold off
grid
for k1 = 1:numel(locs)-1
apc{k1} = a_hip(locs(k1)-10:locs(k1+1)-10); % Define MUAP Frames
tvc{k1} = t(locs(k1)-10:locs(k1+1)-10);
end
figure(2)
hold all
for k1 = 1:numel(apc)
plot(tvc{k1}-tvc{k1}(1), apc{k1}) % Plot MUAP Frames
end
hold off
grid

I got this graph which is not right I also plotted it againced time not the gait cycle. My main issue i dont know how to tie the gait cycles i found from findpeaks to the rest of the data for finding the angles of the hip and the knee. I need to time normalise it for each gait cycle and graph the hip and knee angles for the average gait cycle.
0 Kommentare
Akzeptierte Antwort
Star Strider
am 2 Apr. 2023
Note that ‘i_peaks’ is a (33x1) column vector, That means that:
for j=1:size(i_peaks,2) -1
new_angle(:,ci) =interp1(a_hip,gc_perc,gc);
end
iterates from 1 to 0, with an implied increment of +1, so essentially does not iterate at all. That results in ‘new_angle’ being empty, and the error being thrown.
The next problem (after replacing the 2 with a 1, or using numel instead) is that ‘gc’ is not defined. A potential problem is that the interp1 function interpolates the first argument corresponding to the third argument, returning the interpolated value of the second argument. So if ‘gc’ is supposed to interpolate ‘gc_perc’, and return a corresponding value for ‘a_hip’, the first two arguments need to be reversed from their current placement.
.
23 Kommentare
Afet
am 29 Aug. 2023
Hey,
I have a related question to this. I already have kinematic data calculated in OpenSim. I have 5 trials per subject and comparing simultanously recorded markerless and Vicon data. I have synchronized the systems however there is still a shift in the data and I need to time normalize it. This code is super helpful but I got a bit confused on which part exactly normalizes and finds the intances of the gait cycle. In my data there is two gait cycles and I will use only the first one. Is there a more simplified version of this code? Or any advice on how I can do it?
Star Strider
am 29 Aug. 2023
@Afet — I believe the part that finds the instances of the gait cycle is the is the last findpeaks call and the code following it. (That seems to be adapted from code I wrote for a different problem about calculating the ensembles and ensemble average of an EMG problem, since it refers to MUAPs.) The rest is not code I wrote and my involvement here (about five months ago) was limited to solving this particular problem (the details of which I do not now remember).
If you have a specific problem with your data, it would be best to post it as a new Question, including the necessary code and the relevant data files.
Weitere Antworten (0)
Siehe auch
Kategorien
Mehr zu 2-D and 3-D Plots finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!


