11.4 - Kinematic Analysis
Animations
Kinematic Diagram and Link Lengths
Linkage Orientation Throughout Jumping Motion
1. Mechanism at zero configuration (rest), where both servos are at 0°. The vertical slider displacement is also set to zero.
2. Mechanism at full crouch position, where servo 1 is at 22.2° and servo 2 is at -30° orientation. The vertical slider displacement is -82.5mm from zero configuration.
3. Mechanism at takeoff position just before foot leaves the ground, where servo 1 is at 0° and servo 2 is at 45°. The vertical slider displacement is 34.60mm from zero configuration.
4. Mechanism at maximum height of sliding body, where servo 1 is at -15° and servo 2 is at 45° orientation. The vertical slider displacement is 64.60mm from zero configuration.
5. Mechanism orientation around the halfway point back down from maximum height, where servo 1 is at 10° and servo 2 is at -5°. The vertical slider displacement is 49.60mm from zero configuration.
6. Mechanism at landing position, where servo 1 is at 15° and servo 2 is at -15°. The vertical slider displacement is -43.25mm from zero configuration.
Position Analysis
Kinematic analysis was performed using two coordinate frames. The local body frame is fixed at O1- (the primary servo/hip pivot) to describe the relative motion of the links. Joint positions were calculated from link lengths and link orientations in the local frame first. A separate global ground frame was then used to capture the absolute jumping motion. By adding the vertical slider displacement s(t) to the calculated local positions, coordinates of the local body frame are translated into the global ground frame.
For local coordinates fixed at O1 = (0,0):
For global coordinates with ground reference:
All joint positions can be geometrically determined in this manner; however, only joints E and F are required to describe our system’s output motion. The remaining joints serve as internal constraints, and do not directly affect the performance metrics being evaluated.
Plugging our simulated values for link orientation and slider vertical displacement into the equations above for each phase in the jumping motion:
MATLAB-Generated Position Plots
3D plot of the foot’s vertical position as a function of two independent servo inputs. The traectory shows how combined actuation of θ1 and θ2 produces the jumping motion, with minimum height at full crouch and maximum height during the airborne phase. The nonlinear path reflects the coupled, two-input nature of the mechanism.
This 3D plot illustrates how the prismatic joint displacement relative to its rest position varies with θ1 and θ2, converting internal linkage motion into vertical body translation. Maximum upward displacement occurs near the airborne phase, while the lowest position corresponds to full crouch during energy storage.
Velocity Analysis
Moving beyond position analysis, each joint’s velocity was computed from position data using a central difference approximation, which approximates the derivative based on neighboring position values. Rather than assuming uniform time steps to use the simplified equation, the timing of each phase was obtained directly from the Autodesk Fusion motion study, where motion is defined as a perentage of the total cycle. When converted to actual time values, these percentages result in non-uniform time intervals between phases. The central difference method was then applied using these variable time steps, allowing the velocity calculations to accurately reflect our mechanism’s dynamics.
MATLAB-Generated Velocity Plots:
Acceleration Analysis
The acceleration of each point was calculated from the velocity data using a numerical differentiation approach consistent with the non-uniform time stepping extracted from the Fusion 360 motion study. Similar to our velocity analysis, the acceleration of each joint was obtained by applying a central difference formula to the velocity data using the actual time vector, rather than assuming uniform time intervals. This ensures that variations in phase timing are properly captured in the second derivative of position; therefore, the resulting acceleration values reflect the true dynamic behavior of the mechanism, including rapid changes during key events such as take-off and landing. By basing the acceleration calculations directly on the previously computed velocity profiles, consistency is maintained between position, velocity, and acceleration, providing an accurate representation of how the mechanism responds to the prescribed servo inputs.
MATLAB-Generated Acceleration Plots
Force Analysis
The force analysis is directly derived from the previously computed acceleration of the system using Newton’s Second Law. Specifically, the vertical ground reaction force is determined from the acceleration of the body (slider), which represents the mass being accelerated during the jumping motion. By converting the body acceleration into physical units and combining it with gravitational effects, the net ground reaction force can be expressed as F=m(g+a). This establishes a direct relationship between the kinematic analysis and the dynamic response of the system, where rapid changes in acceleration (particularly during take-off and landing) result in corresponding variations in ground reaction force.
MATLAB CODE:
clear; clc; close all
phase = ["Rest","Full Crouch","Take-off","Max Height", ...
"Halfway Down","Landing","Back to Rest"];
n = length(phase);
T_total = 2.2; % total motion time, seconds
% Non-uniform phase timing from Fusion 360 motion study
% These percentages define when each phase occurs in the total jump cycle
motionPercent = [0, 40, 55, 60, 75, 85, 100];
% Convert Fusion motion percentage into actual time values
t = T_total * motionPercent/100;
%% =========================
% LINK LENGTHS, mm
%% =========================
L_O2A = 24;
L_AB = 28.284;
L_O1B = 24;
L_O1C = 30;
L_O1E = 110;
L_CD = 110;
L_ED = 30;
L_EF = 110;
%% =========================
% SERVO INPUT ANGLES, degrees
%% =========================
theta1_deg = [0, 22.2, 0, -15, 10, 15, 0];
theta2_deg = [0, -30, 45, 45, -5, -15, 0];
theta1 = deg2rad(theta1_deg);
theta2 = deg2rad(theta2_deg);
%% =========================
% LINK ORIENTATIONS, degrees
%% =========================
alpha_O1E_deg = [-135, -157.2, -135, -120, -145, -150, -135];
alpha_EF_deg = [-45, -15, -90, -90, -50, -30, -45];
alpha_O1E = deg2rad(alpha_O1E_deg);
alpha_EF = deg2rad(alpha_EF_deg);
%% =========================
% SLIDER DISPLACEMENT, mm
%% =========================
s = [0, -82.5, 34.6, 64.6, 49.6, -43.25, 0];
%% =========================
% POSITION ANALYSIS
%% =========================
xE_rel = L_O1E*cos(alpha_O1E);
zE_rel = L_O1E*sin(alpha_O1E);
xF_rel = xE_rel + L_EF*cos(alpha_EF);
zF_rel = zE_rel + L_EF*sin(alpha_EF);
xE_abs = xE_rel;
zE_abs = zE_rel + s;
xF_abs = xF_rel;
zF_abs = zF_rel + s;
%% =========================
% VELOCITY ANALYSIS
% Non-uniform time stepping using Fusion time vector
%% =========================
vF_x = gradient(xF_abs, t);
vF_z = gradient(zF_abs, t);
vF_mag = sqrt(vF_x.^2 + vF_z.^2);
v_body = gradient(s, t);
omega1 = gradient(theta1, t); % rad/s
omega2 = gradient(theta2, t); % rad/s
%% =========================
% ACCELERATION ANALYSIS
% Non-uniform time stepping using Fusion time vector
%% =========================
aF_x = gradient(vF_x, t);
aF_z = gradient(vF_z, t);
aF_mag = sqrt(aF_x.^2 + aF_z.^2);
a_body = gradient(v_body, t);
alpha1 = gradient(omega1, t); % rad/s^2
alpha2 = gradient(omega2, t); % rad/s^2
%% =========================
% FORCE ANALYSIS
%% =========================
m = 0.250; % kg, change if needed
g = 9.81; % m/s^2
a_body_m = a_body/1000; % convert mm/s^2 to m/s^2
F_ground = m*(g + a_body_m); % N
%% =========================
% RESULTS TABLE
%% =========================
results = table(phase', motionPercent', t', theta1_deg', theta2_deg', s', ...
xF_abs', zF_abs', vF_z', aF_z', v_body', a_body', F_ground', ...
'VariableNames', {'Phase','MotionPercent','Time_s','Theta1_deg','Theta2_deg', ...
'Slider_mm','xF_abs_mm','zF_abs_mm','vFz_mm_s', ...
'aFz_mm_s2','vBody_mm_s','aBody_mm_s2','Fground_N'});
disp(results)
%% =========================
% 3D INPUT-OUTPUT PLOTS
%% =========================
plotInputOutput3D(theta1_deg, theta2_deg, zF_abs, phase, ...
'z_F Absolute (mm)', 'Foot Vertical Position vs Servo Inputs');
plotInputOutput3D(theta1_deg, theta2_deg, s, phase, ...
'Slider Position s(t) (mm)', 'Slider Position vs Servo Inputs');
plotInputOutput3D(theta1_deg, theta2_deg, vF_z, phase, ...
'v_{F,z} (mm/s)', 'Foot Vertical Velocity vs Servo Inputs');
plotInputOutput3D(theta1_deg, theta2_deg, v_body, phase, ...
'v_{body} (mm/s)', 'Body/Slider Velocity vs Servo Inputs');
plotInputOutput3D(theta1_deg, theta2_deg, aF_z, phase, ...
'a_{F,z} (mm/s^2)', 'Foot Vertical Acceleration vs Servo Inputs');
plotInputOutput3D(theta1_deg, theta2_deg, a_body, phase, ...
'a_{body} (mm/s^2)', 'Body/Slider Acceleration vs Servo Inputs');
plotInputOutput3D(theta1_deg, theta2_deg, F_ground, phase, ...
'Ground Reaction Force (N)', 'Ground Reaction Force vs Servo Inputs');
%% =========================
% SERVO INPUT KINEMATICS VS TIME
%% =========================
figure
plot(t, theta1_deg, 'o-', 'LineWidth', 2)
hold on
plot(t, theta2_deg, 'o-', 'LineWidth', 2)
grid on
xlabel('Time (s)')
ylabel('Servo Angle (deg)')
legend('\theta_1','\theta_2')
title('Servo Input Angles vs Time')
figure
plot(t, omega1, 'o-', 'LineWidth', 2)
hold on
plot(t, omega2, 'o-', 'LineWidth', 2)
grid on
xlabel('Time (s)')
ylabel('Angular Velocity (rad/s)')
legend('\omega_1','\omega_2')
title('Servo Angular Velocity vs Time')
figure
plot(t, alpha1, 'o-', 'LineWidth', 2)
hold on
plot(t, alpha2, 'o-', 'LineWidth', 2)
grid on
xlabel('Time (s)')
ylabel('Angular Acceleration (rad/s^2)')
legend('\alpha_1','\alpha_2')
title('Servo Angular Acceleration vs Time')
%% =========================
% LOCAL FUNCTION
%% =========================
function plotInputOutput3D(theta1_deg, theta2_deg, zData, phase, zLabelText, plotTitle)
n = length(theta1_deg);
arrowLen = 8; % adjust between 4 and 12 if arrows look too big/small
figure
plot3(theta1_deg, theta2_deg, zData, 'o-', 'LineWidth', 2)
grid on
hold on
for i = 1:n-1
dx = theta1_deg(i+1) - theta1_deg(i);
dy = theta2_deg(i+1) - theta2_deg(i);
dz = zData(i+1) - zData(i);
mag = sqrt(dx^2 + dy^2 + dz^2);
if mag > 0
quiver3(theta1_deg(i), theta2_deg(i), zData(i), ...
arrowLen*dx/mag, arrowLen*dy/mag, arrowLen*dz/mag, ...
0, 'r', 'LineWidth', 1.5, 'MaxHeadSize', 1.5)
end
end
for i = 1:n
text(theta1_deg(i), theta2_deg(i), zData(i), ...
[' ', char(phase(i))], 'FontSize', 8)
end
xlabel('\theta_1 (deg)')
ylabel('\theta_2 (deg)')
zlabel(zLabelText)
title(plotTitle)
axis tight
view(45,30)
end