%append_joint_centres_to_static_trial.m
% this file will open up a static trial.trc file and append the hip, knee,
% and ankle joint centres to this trial
% read in trc file
mkr_data = dlmread(static_trc_fname,'\t',6,0);
[nframes ncolumns] = size(mkr_data);
% arrange all the marker data, based on their order, which is pre-assigned
% from the PECS code 'Export_static_trc.m'
RASI=mkr_data(:,3:5);
LASI=mkr_data(:,6:8);
SACR=mkr_data(:,9:11);
RTH1=mkr_data(:,12:14);
RTH2=mkr_data(:,15:17);
RTH3=mkr_data(:,18:20);
RLFC=mkr_data(:,21:23);
RMFC=mkr_data(:,24:26);
RTB1=mkr_data(:,27:29);
RTB2=mkr_data(:,30:32);
RTB3=mkr_data(:,33:35);
RLMAL=mkr_data(:,36:38);
RMMAL=mkr_data(:,39:41);
RCAL=mkr_data(:,42:44);
RTOE=mkr_data(:,45:47);
RMT5=mkr_data(:,48:50);
LTH1=mkr_data(:,51:53);
LTH2=mkr_data(:,54:56);
LTH3=mkr_data(:,57:59);
LLFC=mkr_data(:,60:62);
LMFC=mkr_data(:,63:65);
LTB1=mkr_data(:,66:68);
LTB2=mkr_data(:,69:71);
LTB3=mkr_data(:,72:74);
LLMAL=mkr_data(:,75:77);
LMMAL=mkr_data(:,78:80);
LCAL=mkr_data(:,81:83);
LTOE=mkr_data(:,84:86);
LMT5=mkr_data(:,87:89);
% preallocate arrays for hip, knee, and ankle centres
LHJC=zeros(nframes,3);
RHJC=zeros(nframes,3);
LKJC=zeros(nframes,3);
RKJC=zeros(nframes,3);
LHA1=zeros(nframes,3);
LHA2=zeros(nframes,3);
new_LHA1=zeros(nframes,3);
new_LHA2=zeros(nframes,3);
RHA1=zeros(nframes,3);
RHA2=zeros(nframes,3);
new_RHA1=zeros(nframes,3);
new_RHA2=zeros(nframes,3);
LHA1_ankle=zeros(nframes,3);
LHA2_ankle=zeros(nframes,3);
RHA1_ankle=zeros(nframes,3);
RHA2_ankle=zeros(nframes,3);
% First, define a Pelvis Coordinate System
% ----------------------------------------------------------
% define the pelvis origin
originPelvis=(LASI+RASI)/2;
%calculate unit vectors of Pelvis segment relative to global
[e1Pelvis,e2Pelvis,e3Pelvis]=segmentorientationV1V3(originPelvis-SACR,RASI-LASI);
% now project HJC back into Global CS
for i=1:nframes
rotationmatrix=[e1Pelvis(i,:);e2Pelvis(i,:);e3Pelvis(i,:)];
rotationmatrix=inv(rotationmatrix);
LHJC(i,:)= rotationmatrix*LHJC_location + originPelvis(i,:)';
RHJC(i,:)= rotationmatrix*RHJC_location + originPelvis(i,:)';
end
% Second, define a Thigh Coordinate System - LEFT LEG
% ----------------------------------------------------------
originThigh=LTH2;
%calculate unit vectors of Thigh segment relative to global
[e1Thigh,e2Thigh,e3Thigh]=segmentorientationV2V1(originThigh-LTH1,LTH3-originThigh);
% now project LKJC back into Global CS
for i=1:nframes
rotationmatrix=[e1Thigh(i,:);e2Thigh(i,:);e3Thigh(i,:)];
rotationmatrix=inv(rotationmatrix);
LHA1(i,:)= rotationmatrix*LHAxes(:,1) + originThigh(i,:)';
LHA2(i,:)= rotationmatrix*LHAxes(:,2) + originThigh(i,:)';
end
% Define a Thigh Coordinate System - RIGHT LEG
% define the thigh origin and yaxis, which lies parallel to the line bisecting TH1 and TH3
originThigh=RTH2;
%calculate unit vectors of Thigh segment relative to global
[e1Thigh,e2Thigh,e3Thigh]=segmentorientationV2V1(originThigh-RTH1,RTH3-originThigh);
% now project LKJC back into Global CS
for i=1:nframes
rotationmatrix=[e1Thigh(i,:);e2Thigh(i,:);e3Thigh(i,:)];
rotationmatrix=inv(rotationmatrix);
RHA1(i,:)= rotationmatrix*RHAxes(:,1) + originThigh(i,:)';
RHA2(i,:)= rotationmatrix*RHAxes(:,2) + originThigh(i,:)';
end
% Define epicondylar axis of the knee
Lepicondylar_axis = (LLFC-LMFC);
Repicondylar_axis = (RLFC-RMFC);
% Define starting knee centre position
Lknee_centre = (LLFC+LMFC)/2;
Rknee_centre = (RLFC+RMFC)/2;
% Define helical axes vectors
Lhelical_axis_vector = LHA1-LHA2;
Rhelical_axis_vector = RHA1-RHA2;
% Define a new knee joint centre, using the helical axes
% -------------------------------------------------------------------------
% given that we have two axes defined, and the centre of the knee joint, we can define a plane perpendicular
% to the Epicondyle axis that intersects the centre of the knee joint. The point that this plane intersects onto
% the helical axis is defined as the new joint centre, and the helical axis can be redefined in body builder using
% two new virtual markers.
% The line of the optimal helical axis defined as:
% x = xo + at
% y = yo + bt Eq(1)
% z = zo + ct
% where xo,yo,zo describe a point along the line (such as Sopt) and describe the unit vector of the line (helical_axis_vector)
%
%The plane perpendicular to the epicondylar axis and running through the centre of the knee is defined by:
% a(x-xo)+b(y-yo)+c(z-zo)=0 Eq(2)
% where xo,yo,zo define a point on the plane (knee_centre) and define the unit vector of the perpendicular plane (epicondylar_axis)
%
% need to join Eq (1) and (2) to solve for t, then substitute this value back into eq (1)
for i=1:nframes
t = (dot(Lepicondylar_axis(i,:),Lknee_centre(i,:))-dot(Lepicondylar_axis(i,:),LHA1(i,:)))/dot(Lepicondylar_axis(i,:),Lhelical_axis_vector(i,:));
new_x = LHA1(i,1)+Lhelical_axis_vector(i,1)*t;
new_y = LHA1(i,2)+Lhelical_axis_vector(i,2)*t;
new_z = LHA1(i,3)+Lhelical_axis_vector(i,3)*t;
LKJC(i,:)=[new_x;new_y;new_z];
% Reposition the Lateral and Medial Femoral Condyles, so that they lie on
% the helical axis, knee width apart
t = (dot(Lepicondylar_axis(i,:),LLFC(i,:))-dot(Lepicondylar_axis(i,:),LHA1(i,:)))/dot(Lepicondylar_axis(i,:),Lhelical_axis_vector(i,:));
new_x = LHA1(i,1)+Lhelical_axis_vector(i,1)*t;
new_y = LHA1(i,2)+Lhelical_axis_vector(i,2)*t;
new_z = LHA1(i,3)+Lhelical_axis_vector(i,3)*t;
LLFC(i,:)=[new_x;new_y;new_z];
t = (dot(Lepicondylar_axis(i,:),LMFC(i,:))-dot(Lepicondylar_axis(i,:),LHA1(i,:)))/dot(Lepicondylar_axis(i,:),Lhelical_axis_vector(i,:));
new_x = LHA1(i,1)+Lhelical_axis_vector(i,1)*t;
new_y = LHA1(i,2)+Lhelical_axis_vector(i,2)*t;
new_z = LHA1(i,3)+Lhelical_axis_vector(i,3)*t;
LMFC(i,:)=[new_x;new_y;new_z];
end
for i=1:nframes
t = (dot(Repicondylar_axis(i,:),Rknee_centre(i,:))-dot(Repicondylar_axis(i,:),RHA1(i,:)))/dot(Repicondylar_axis(i,:),Rhelical_axis_vector(i,:));
new_x = RHA1(i,1)+Rhelical_axis_vector(i,1)*t;
new_y = RHA1(i,2)+Rhelical_axis_vector(i,2)*t;
new_z = RHA1(i,3)+Rhelical_axis_vector(i,3)*t;
RKJC(i,:)=[new_x;new_y;new_z];
t = (dot(Repicondylar_axis(i,:),RLFC(i,:))-dot(Repicondylar_axis(i,:),RHA1(i,:)))/dot(Repicondylar_axis(i,:),Rhelical_axis_vector(i,:));
new_x = RHA1(i,1)+Rhelical_axis_vector(i,1)*t;
new_y = RHA1(i,2)+Rhelical_axis_vector(i,2)*t;
new_z = RHA1(i,3)+Rhelical_axis_vector(i,3)*t;
RLFC(i,:)=[new_x;new_y;new_z];
t = (dot(Repicondylar_axis(i,:),RMFC(i,:))-dot(Repicondylar_axis(i,:),RHA1(i,:)))/dot(Repicondylar_axis(i,:),Rhelical_axis_vector(i,:));
new_x = RHA1(i,1)+Rhelical_axis_vector(i,1)*t;
new_y = RHA1(i,2)+Rhelical_axis_vector(i,2)*t;
new_z = RHA1(i,3)+Rhelical_axis_vector(i,3)*t;
RMFC(i,:)=[new_x;new_y;new_z];
end
% Now define a Tibia Coordinate System - LEFT LEG
% ----------------------------------------------------------
originTibia=LTB2;
%calculate unit vectors of Tibia segment relative to global
[e1Tibia,e2Tibia,e3Tibia]=segmentorientationV2V1(originTibia-LTB1,LTB3-originTibia);
% now project LKJC back into Global CS
for i=1:nframes
rotationmatrix=[e1Tibia(i,:);e2Tibia(i,:);e3Tibia(i,:)];
rotationmatrix=inv(rotationmatrix);
LHA1_ankle(i,:)= rotationmatrix*LAJaxes(:,1) + originTibia(i,:)';
LHA2_ankle(i,:)= rotationmatrix*LAJaxes(:,2) + originTibia(i,:)';
end
% Define a Tibia Coordinate System - RIGHT LEG
% ----------------------------------------------------------
originTibia=RTB2;
%calculate unit vectors of Tibia segment relative to global
[e1Tibia,e2Tibia,e3Tibia]=segmentorientationV2V1(originTibia-RTB1,RTB3-originTibia);
% now project LKJC back into Global CS
for i=1:nframes
rotationmatrix=[e1Tibia(i,:);e2Tibia(i,:);e3Tibia(i,:)];
rotationmatrix=inv(rotationmatrix);
RHA1_ankle(i,:)= rotationmatrix*RAJaxes(:,1) + originTibia(i,:)';
RHA2_ankle(i,:)= rotationmatrix*RAJaxes(:,2) + originTibia(i,:)';
end
% Define malleoli axis of the ankle
Lmalleoli_axis = (LLMAL-LMMAL);
Rmalleoli_axis = (RLMAL-RMMAL);
% Define starting knee centre position
Lankle_centre = (LMMAL+LLMAL)/2;
Rankle_centre = (RMMAL+RLMAL)/2;
% Define helical axes vectors
Lankle_helical_axis_vector = LHA1_ankle-LHA2_ankle;
Rankle_helical_axis_vector = RHA1_ankle-RHA2_ankle;
for i=1:nframes
t = (dot(Lmalleoli_axis(i,:),Lankle_centre(i,:))-dot(Lmalleoli_axis(i,:),LHA1(i,:)))/dot(Lmalleoli_axis(i,:),Lankle_helical_axis_vector(i,:));
new_x = LHA1(i,1)+Lhelical_axis_vector(i,1)*t;
new_y = LHA1(i,2)+Lhelical_axis_vector(i,2)*t;
new_z = LHA1(i,3)+Lhelical_axis_vector(i,3)*t;
LKJC(i,:)=[new_x;new_y;new_z];
% Reposition the Lateral and Medial Malleoli, so that they lie on
% the helical axis, knee width apart
t = (dot(Lmalleoli_axis(i,:),LLMAL(i,:))-dot(Lmalleoli_axis(i,:),LHA1(i,:)))/dot(Lmalleoli_axis(i,:),Lankle_helical_axis_vector(i,:));
new_x = LHA1(i,1)+Lhelical_axis_vector(i,1)*t;
new_y = LHA1(i,2)+Lhelical_axis_vector(i,2)*t;
new_z = LHA1(i,3)+Lhelical_axis_vector(i,3)*t;
LLFC(i,:)=[new_x;new_y;new_z];
t = (dot(Lmalleoli_axis(i,:),LMMAL(i,:))-dot(Lmalleoli_axis(i,:),LHA1(i,:)))/dot(Lmalleoli_axis(i,:),Lankle_helical_axis_vector(i,:));
new_x = LHA1(i,1)+Lhelical_axis_vector(i,1)*t;
new_y = LHA1(i,2)+Lhelical_axis_vector(i,2)*t;
new_z = LHA1(i,3)+Lhelical_axis_vector(i,3)*t;
LMFC(i,:)=[new_x;new_y;new_z];
end
% now append two sets of marker data for OpenSIM scaling.
new_mkr_data=[RASI LASI SACR RTH1 RTH2 RTH3 RLFC RMFC RTB1 RTB2 RTB3 ...
RLMAL RMMAL RCAL RTOE RMT5 LTH1 LTH2 LTH3 LLFC LMFC LTB1 LTB2 LTB3 ...
LLMAL LMMAL LCAL LTOE LMT5 LHJC RHJC LKJC RKJC LAJC RAJC];
mkr_labels ={'RASI' 'LASI' 'SACR' 'RTH1' 'RTH2' 'RTH3' 'RLFC' 'RMFC'...
'RTB1' 'RTB2' 'RTB3' 'RLMAL' 'RMMAL' 'RCAL' 'RTOE' 'RMT5'...
'LTH1' 'LTH2' 'LTH3' 'LLFC' 'LMFC' 'LTB1' ...
'LTB2' 'LTB3' 'LLMAL' 'LMMAL' 'LCAL' 'LTOE' 'LMT5' ...
'LHJC' 'RHJC' 'LKJC' 'RKJC' 'LAJC' 'RAJC'};
[nt, nc] = size(new_mkr_data);
if rem(nc,3)
error('Input trajectories must have 3 components each.');
end
% Also check to make sure the CS is consistent with OpenSIM, which is as follows:
% X-axis positive anterior
% Y-axis positive superior
% Z-axis positive toward the right, as the subject is facing
% note that the coordinate data should have already been rotated from the
% original global coordinate system so that the y-axis is vertical. THis is
% performed in the export.trc functions
if abs((RASI(1,1)-LASI(1,1))) > 150 % then subject is facing along the x-direction of GLobal CS
if RASI(1,1) > LASI(1,1) % then they are facing -z direction
rotationmatrix = [0 0 -1; 0 1 0; 1 0 0]; %rotate 90 deg around the vertical y-axis
else % they are facing the z direction
rotationmatrix = [0 0 1; 0 1 0; -1 0 0]; % rotate -90 deg around the y-axis
end
else % subject must be facing with feet along the z-axis
if RASI(1,3) > LASI(1,3) % then they are facing x direction
rotationmatrix = [1 0 0; 0 1 0; 0 0 1];
else
rotationmatrix = [-1 0 0; 0 1 0; 0 0 -1];
end
end
for I = 1:nc/3
rotated_mkr_data(:,3*I-2:3*I) = [rotationmatrix*new_mkr_data(:,3*I-2:3*I)']';
end
% Print data to a new static joint centre file
% ------------------------------------------------------------
nMarkers=size(mkr_labels,2);
sampleRate = round(1/(mkr_data(2,2)-mkr_data(1,2)));
Time_array=mkr_data(:,2);
new_file = [dat_path '\' subject_name '_OptimalJointCentres.trc'];
fid = fopen(new_file,'w');
% Print header information
fprintf(fid,'PathFileType\t4\t(X/Y/Z)\t%s\n',subject_name);
fprintf(fid,'DataRate\tCameraRate\tNumFrames\tNumMarkers\tUnits\tOrigDataRate\tOrigDataStartFrame\tOrigNumFrames\n');
fprintf(fid,'%d\t%d\t%d\t%d\tmm\t%d\t%d\t%d\n',sampleRate,sampleRate,nt,nMarkers,sampleRate,mkr_data(1,1),mkr_data(end,1))
fprintf(fid,'Frame#\tTime');
for i = 1:length(mkr_labels)
fprintf(fid,'\t%s\t\t',mkr_labels{i});
end
fprintf(fid,'\n\t\t');
for i = 1:length(mkr_labels)
fprintf(fid,'X%d\tY%d\tZ%d\t',i,i,i);
end
fprintf(fid,'\n\n');
% Print data
for i= 1:nt
fprintf(fid,'%d\t%f\t',i,Time_array(i));
for j=1:nc
fprintf(fid,'%f\t',rotated_mkr_data(i,j));
end
fprintf(fid,'\n');
end
fclose(fid);
% Plot marker data to check that the joint centres look ok....
% -------------------------------------------------------------------------
figure(1)
hold on
axis equal
title('3D Positions of markers. Check that black markers resemble joint centres. Hit Enter to finish')
scatter3(RASI(1,1),RASI(1,2),RASI(1,3),'go');
scatter3(LASI(1,1),LASI(1,2),LASI(1,3),'go');
scatter3(SACR(1,1),SACR(1,2),SACR(1,3),'go');
scatter3(LHJC(1,1),LHJC(1,2),LHJC(1,3),'ko');
scatter3(RHJC(1,1),RHJC(1,2),RHJC(1,3),'ko');
scatter3(LTH1(1,1),LTH1(1,2),LTH1(1,3),'ro');
scatter3(LTH2(1,1),LTH2(1,2),LTH2(1,3),'ro');
scatter3(LTH3(1,1),LTH3(1,2),LTH3(1,3),'ro');
scatter3(LMFC(1,1),LMFC(1,2),LMFC(1,3),'ro');
scatter3(LLFC(1,1),LLFC(1,2),LLFC(1,3),'ro');
% scatter3(LHA1(1,1),LHA1(1,2),LHA1(1,3),'ko');
% scatter3(LHA2(1,1),LHA2(1,2),LHA2(1,3),'ko');
scatter3(RTH1(1,1),RTH1(1,2),RTH1(1,3),'bo');
scatter3(RTH2(1,1),RTH2(1,2),RTH2(1,3),'bo');
scatter3(RTH3(1,1),RTH3(1,2),RTH3(1,3),'bo');
scatter3(RLFC(1,1),RLFC(1,2),RLFC(1,3),'bo');
scatter3(RMFC(1,1),RMFC(1,2),RMFC(1,3),'bo');
% scatter3(RHA1(1,1),RHA1(1,2),RHA1(1,3),'ko');
% scatter3(RHA2(1,1),RHA2(1,2),RHA2(1,3),'ko');
scatter3(Lknee_centre(1,1),Lknee_centre(1,2),Lknee_centre(1,3),'go');
scatter3(LKJC(1,1),LKJC(1,2),LKJC(1,3),'ko');
scatter3(Rknee_centre(1,1),Rknee_centre(1,2),Rknee_centre(1,3),'go');
scatter3(RKJC(1,1),RKJC(1,2),RKJC(1,3),'ko');
scatter3(LTB1(1,1),LTB1(1,2),LTB1(1,3),'ro');
scatter3(LTB2(1,1),LTB2(1,2),LTB2(1,3),'ro');
scatter3(LTB3(1,1),LTB3(1,2),LTB3(1,3),'ro');
scatter3(RTB1(1,1),RTB1(1,2),RTB1(1,3),'bo');
scatter3(RTB2(1,1),RTB2(1,2),RTB2(1,3),'bo');
scatter3(RTB3(1,1),RTB3(1,2),RTB3(1,3),'bo');
scatter3(LMMAL(1,1),LMMAL(1,2),LMMAL(1,3),'ro');
scatter3(LLMAL(1,1),LLMAL(1,2),LLMAL(1,3),'ro');
scatter3(LAJC(1,1),LAJC(1,2),LAJC(1,3),'ko');
scatter3(RMMAL(1,1),RMMAL(1,2),RMMAL(1,3),'bo');
scatter3(RLMAL(1,1),RLMAL(1,2),RLMAL(1,3),'bo');
scatter3(RAJC(1,1),RAJC(1,2),RAJC(1,3),'ko');
pause
close all