What is wrong with my ankle joint moment estimation?
Show older comments
Hi all,
I collected human motion data (kinematics and ground reaction forces) during walking. I am trying to estimate ankle joint moments (3D) and later powers. I segmented (per stance phase on a force plate) 3D ankle joint angles, GRFs, ankle joint centes, foot and shank center of mass postions and accelerations, foot and shank angulat velocities and accelerations. I do not have center of pressure data, I approximate this. Below is my code that I use. However, I am not sure whether ankle moments are calculated correctly beacuse of the atypical spike in the sagital plane moment in the first 20 frames that you can see in tha image below. Can you help please?

% MATLAB Code for 3D Ankle Joint Torques Calculation with Segmented Data Structure
load Data_structure.mat
% Constants
g = 9.81; % m/s^2, gravitational acceleration
%Subject weight/height
mass = 84.6;
height = 1.55;
% segment mass (kg)
massThigh = 0.142*mass;
massShank = 0.043*mass;
massFoot = 0.013*mass;
% segment lenght (meters)
L_thigh = 0.240*height;
L_shank = 0.262*height;
L_foot = 0.144*height;
% Moment of inertia
I_foot = diag(data.FootMoI); % 3x3 matrix
I_shank = diag(data.ShankMoI);
I_thigh = diag(data.ThighMoI);
% Initialize moment arrays
nFrames = 101;
forcePlates = {'fp1', 'fp3', 'fp4'};
limbs = {'L', 'R'};
ankleMoments = struct();
% Loop through force plates
for fp = 1:length(forcePlates)
fpName = forcePlates{fp};
for limb = 1:length(limbs)
limbName = limbs{limb};
% Initialize moment data for each plate and limb
ankleMoments.(fpName).(limbName) = zeros(3, nFrames);
% Check if data exists for the current force plate and limb
if isfield(data.Segmented_Angles, fpName) && isfield(data.Segmented_Angles.(fpName), limbName)
if ~isempty(data.Segmented_Angles.(fpName).(limbName)) && isfield(data.Segmented_Angles.(fpName).(limbName){1, 1}, 'ankle')
% Extract kinematic and GRF data
ankleAngles = data.Segmented_Angles.(fpName).(limbName){1, 1}.ankle;
ankleJC = [data.Segmented_Jointcenteres.(fpName).(limbName){1, 1}.ankle.ap;
data.Segmented_Jointcenteres.(fpName).(limbName){1, 1}.ankle.ml;
data.Segmented_Jointcenteres.(fpName).(limbName){1, 1}.ankle.ver];
% COM positions and accelerations
comFoot = data.Segmented_CoMpos.(fpName).(limbName){1, 1}.foot';
foot_comAcc = data.Segmented_CoMacc.(fpName).(limbName){1, 1}.foot';
% Angular velocities and accelerations
foot_aVel = data.Segmented_aVel.(fpName).(limbName){1, 1}.foot';
foot_aAcc = data.Segmented_aAcc.(fpName).(limbName){1, 1}.foot';
% GRF data
try
GRF_fp = [data.(['Kistler' num2str(fp) '_fx_stance']);
data.(['Kistler' num2str(fp) '_fy_stance']);
data.(['Kistler' num2str(fp) '_fz_stance'])];
catch
GRF_fp = zeros(3, nFrames);
end
% Approximate COP position
r_ankle_to_COP = zeros(3, nFrames);
for i = 1:nFrames
% Get GRF vertical force to detect stance
grfZ = GRF_fp(3, :);
stanceFrames = find(grfZ > 10);
% Skip if not in stance
if isempty(stanceFrames) || ~ismember(i, stanceFrames)
r_ankle_to_COP(:, i) = [0; 0; 0];
continue;
end
% Use alpha based on stance progression
alpha = (i - stanceFrames(1)) / (stanceFrames(end) - stanceFrames(1));
alpha = min(max(alpha, 0), 1); % clamp to [0, 1]
% Assume foot runs anterior along Z (adjust if needed)
heel_to_toe_vector = [0; 0; 1] * L_foot;
% CoP vector from ankle = moving from heel to toe
r_ankle_to_COP(:, i) = -0.5 * heel_to_toe_vector + alpha * heel_to_toe_vector;
end
% Calculate Ankle Moments
for i = 1:nFrames
% Inertial and gravitational forces
footWeight = [0; 0; -massFoot * g];
footInertialForce = -massFoot * foot_comAcc(:, i);
% Dynamic vector from ankle joint to CoM
r_ankle_to_CoM = comFoot(:, i) - ankleJC(:, i);
% Compute Ankle Moments
ankleMoments.(fpName).(limbName)(:, i) = cross(r_ankle_to_COP(:, i), GRF_fp(:, i)) + ...
cross(r_ankle_to_CoM, footWeight + footInertialForce) + ...
I_foot * foot_aAcc(:, i) + ...
cross(foot_aVel(:, i), I_foot * foot_aVel(:, i));
end
end
end
end
end
% Plotting Ankle Moments in the Sagittal Plane from one force plate
figure
plot(ankleMoments.fp1.R(1,:))
xlabel('Frame');
ylabel('Ankle sagital Moment (Nm)');
9 Comments
Tomaszzz
on 29 May 2025
Sam Chak
on 29 May 2025
I see, @Tomaszzz. It is currently unable to upload the .mat file to the server. I'm not an expert in kinesiology. However, Prof. @William Rose may be able to advise on one or two things. Do you apply Euler's equations to compute the ankle moments?
William Rose
on 29 May 2025
Edited: William Rose
on 29 May 2025
@Sam Chak, yes, you do. But the moment M in your equation is the total moment acting on the (foot) segment. In this case we want to find the net moment acting at the ankle joint, which is considered the proximal end of the foot segment. The total moment acting on the foot segment arises from 3 sources: 1. ground reaction force, represented by force acting at a point usually near the toes (although the location varies during the stance phase, and is zero during the swing phase, when the foot is off the ground), 2. force pulling on the segment at the ankle joint, which is due to a combination of muscles and the weight of th body, and 3. torque at the ankle joint, due to muscles in the lower leg that pull on the foot. We measure (1) and we solve for (2) and (3), using the measured linear and rotational acceleraiton of the foot segment. Tomaszz is calculating and plotting (3).
In normal subjects, most linear and angular movement is in the sagittal plane, so we can get fairly accurate results with a 2D analysis (Eng JJ & Winter DA, 1995; McClay I & Manal K, 1999).
Sam Chak
on 30 May 2025
Thank you for your response. The information you provided in the Answer and subsequent comments is not only impressive but also helpful to the OP in understanding the methodologies used in modeling human ankle kinematics. 👍
William Rose
on 31 May 2025
William Rose
on 31 May 2025
Recently you answered a question about design of a feedback block in a control system, root locus analysis, etc. It was a really good answer and it made me wish I remembered more from my one controls course. Your answer prompted me to go back and spend an hour or so with my 1980s copy of Design of Feedback Control Systems by Hostetter.
William Rose
on 31 May 2025
And you did again, tonight!
Accepted Answer
More Answers (0)
Categories
Find more on Multibody Modeling in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!



