3) Kinematic Analysis and Synthesis - RA
spacer
In this section we analyze the kinematics of the automaton mechanism. It is clear that the mobility of the mechanism is 1. We do not describe the gear train in detail since its design is trivial and for any train junction the gear ratio is 1, assuming that there is no energy loss. Thus, we analyze only the arm and leg mechanisms of the robot. Furthermore, we analyze only right side, since the other one is just the inversion which have completely same kinematics. We can split the whole mechanism in three three main parts: two sub-mechanisms of the leg (upper crank-slider, lower slider-crank) and the arm four-bar linkage.
1. Leg crank-slider
spacer
spacer
2. Leg slider-crank
spacer
spacer
3. Arm four-bar linkage
spacer
Since the four-bar linkage is a mechanism that we have studied in detail throughout the semester, we do not present here the equations for calculating angular positions and velocities, as this would simply be copying formulas from any textbook on the subject. Below, we have provided graphs of all the calculated variables.
spacer
Our mechanism was not aimed at generating any specific speed or force, but simply creating a motion similar to that of a running human. Below you can see graphs of the positions of the end of the arm and leg of the mechanism for a complete revolution of the driven gear.
spacer
We also programmed a full kinematic simulation of the mechanism using the Python language, in order to be able to change design parameters and quickly assess their influence on the motion of the end mechanism. Below, you can see a video of the kinematic simulation of our final design.
Below you can find full listing of the Python program we used to conduct kinematic analysis of our mechanism:
import sys
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def crank_slider(a, d, theta_1, theta_2, omega_2):
theta_4 = np.arctan((a*np.sin(theta_2) + d*np.sin(theta_1)) / ((a*np.cos(theta_2) + d*np.cos(theta_1))))
theta_4[theta_4 < 0] += np.pi
c = (a*np.sin(theta_2) + d*np.sin(theta_1)) / (np.sin(theta_4))
omega_4 = (omega_2*a*np.cos(theta_2 - theta_4)) / c
dc = (omega_4*c*np.sin(theta_4) - omega_2*a*np.sin(theta_2)) / np.cos(theta_4)
return theta_4, omega_4, c, dc
def slider_crank(f, g, l, c, theta_4, dc, omega_4):
h = l + c
theta_6 = np.arccos((g**2 + h**2 - f**2) / (2*g*h)) + theta_4
theta_5 = np.arccos((g**2 - f**2 - h**2) / (2*f*h)) + theta_4
omega_5 = (dc*np.cos(theta_4 - theta_6) - l*omega_4*np.sin(theta_4 - theta_6) \
- c*omega_4*np.sin(theta_4 - theta_6)) / f*np.sin(theta_6 - theta_5)
omega_6 = (dc*np.cos(theta_4 - theta_5) - l*omega_4*np.sin(theta_4 - theta_5) \
- c*omega_4*np.sin(theta_4 - theta_5)) / g*np.sin(theta_5 - theta_6)
return theta_5, theta_6, omega_5, omega_6
def fourbar(a, b, c, d, theta_2, omega_2, delta):
K_1 = d / a
K_2 = d / c
K_3 = (a**2 - b**2 + c**2 + d**2)/ (2*a*c)
A = np.cos(theta_2) - K_1 - K_2*np.cos(theta_2) + K_3
B = - 2*np.sin(theta_2)
C = K_1 - (K_2 + 1)*np.cos(theta_2) + K_3
tan_theta_4 = (-B + delta*np.sqrt(B**2 - 4*A*C)) / (2*A)
theta_4 = 2 * np.arctan(tan_theta_4)
K_4 = d / b
K_5 = (c**2 - d**2 - a**2 - b**2) / (2*a*b)
D = np.cos(theta_2) - K_1 + K_4*np.cos(theta_2) + K_5
E = -2*np.sin(theta_2)
F = K_1 + (K_4 - 1)*np.cos(theta_2) + K_5
tan_theta_3 = (-E + delta*np.sqrt(E**2 - 4*D*F)) / (2*D)
theta_3 = 2 * np.arctan(tan_theta_3)
omega_3 = (a / b) * (np.sin(theta_4 - theta_2) / np.sin(theta_3 - theta_4)) * omega_2
omega_4 = (a / c) * (np.sin(theta_2 - theta_3) / np.sin(theta_4 - theta_3)) * omega_2
return theta_3, theta_4, omega_3, omega_4
def animate(i, ax, ln_l, ln_a, leg, arm):
# UPDATE LEG
A, O4, L_top, L_bot, L_knee, L_A, L_foot = leg
A_x, A_y = A
O4_x, O4_y = O4
L_top_x, L_top_y = L_top
L_bot_x, L_bot_y = L_bot
L_knee_x, L_knee_y = L_knee
L_A_x, L_A_y = L_A
L_foot_x, L_foot_y = L_foot
x_l = [0, A_x[i], O4_x[i], L_top_x[i], L_bot_x[i], L_knee_x[i],
L_A_x[i], L_bot_x[i], L_foot_x[i]]
y_l = [0, A_y[i], O4_y[i], L_top_y[i], L_bot_y[i], L_knee_y[i],
L_A_y[i], L_bot_y[i], L_foot_y[i]]
ln_l.set_xdata(x_l)
ln_l.set_ydata(y_l)
# UPDATE ARM
O5, B, C, O6, D, E = arm
O5_x, O5_y = O5
B_x, B_y = B
C_x, C_y = C
O6_x, O6_y = O6
D_x, D_y = D
E_x, E_y = E
x_a = [O5_x[i], B_x[i], C_x[i], O6_x[i], D_x[i], E_x[i]]
y_a = [O5_y[i], B_y[i], C_y[i], O6_y[i], D_y[i], E_y[i]]
ln_a.set_xdata(x_a)
ln_a.set_ydata(y_a)
return ln_l, ln_a
def main() -> int:
### LEG ANALYSIS
a, d = 5, 15 # mm
omega_2 = 10 # rad / s
leg2pin = 21
leg_long = 60
l = leg_long - leg2pin
f, g = 12, 53
k = 60
theta_1 = np.deg2rad(90)
theta_knee = np.deg2rad(45)
# generate the array of input angles in the global coordinate system
theta_2 = np.linspace(0, 2*np.pi, 360)[::-1]
theta_4, omega_4, c, dc = crank_slider(a, d, theta_1, theta_2, omega_2)
theta_5, theta_6, omega_5, omega_6 = slider_crank(f, g, l, c, theta_4, dc, omega_4)
### LEG FORWARD KINEMATICS
O2_x, O2_y = np.zeros(len(theta_2)), np.zeros(len(theta_2))
O2 = O2_x, O2_y
A_x, A_y = a * np.cos(theta_2), a * np.sin(theta_2)
A = A_x, A_y
O4_x, O4_y = A_x - c * np.cos(theta_4), A_y - c * np.sin(theta_4)
O4 = O4_x, O4_y
L_top_x, L_top_y = O4_x + leg2pin * np.cos(theta_4), O4_y + leg2pin * np.sin(theta_4)
L_top = L_top_x, L_top_y
L_bot_x, L_bot_y = L_top_x - leg_long * np.cos(theta_4), L_top_y - leg_long * np.sin(theta_4)
L_bot = L_bot_x, L_bot_y
L_knee_x, L_knee_y = L_bot_x - f * np.cos(theta_5), L_bot_y - f * np.sin(theta_5)
L_knee = L_knee_x, L_knee_y
L_A_x, L_A_y = L_knee_x + g * np.cos(theta_6), L_knee_y + g * np.sin(theta_6)
L_A = L_A_x, L_A_y
L_foot_x, L_foot_y = L_bot_x + k * np.cos(theta_5 + theta_knee), L_bot_y + k * np.sin(theta_5 + theta_knee)
L_foot = L_foot_x, L_foot_y
### ARM ANALYSIS
m, n, p, q = 5, 51.25, 12, 51.25
t, s = 30 ,35
theta_7 = theta_1
theta_8 = theta_2.copy() + np.pi
theta_arm = np.deg2rad(45)
theta_elbow = np.deg2rad(-60)
omega_8 = omega_2
theta_9, theta_10, omega_9, omega_10 = fourbar(m, n, p, q, theta_8, omega_8, delta=-1)
theta_8 += theta_7
theta_9 += theta_7
theta_10 += theta_7
### ARM FORWARD KINEMATICS
d_gear = 21.25
O5_x, O5_y = np.zeros(len(theta_2)), np.full(len(theta_2), d_gear)
O5 = O5_x, O5_y
B_x, B_y = O5_x + m * np.cos(theta_8), O5_y + m * np.sin(theta_8)
B = B_x, B_y
C_x, C_y = B_x + n * np.cos(theta_9), B_y + n * np.sin(theta_9)
C = C_x, C_y
# O6_x, O6_y = C_x - p * np.cos(theta_10), C_y - p * np.sin(theta_10)
# O6 = O6_x, O6_y
O6_x, O6_y = O5_x + q * np.cos(theta_7), O5_y + q * np.sin(theta_7)
O6 = O6_x, O6_y
D_x, D_y = O6_x + t * np.cos(theta_10 + theta_arm), O6_y + t * np.sin(theta_10 + theta_arm)
D = D_x, D_y
E_x, E_y = D_x + s * np.cos(theta_10 + theta_arm - theta_elbow), D_y + s * np.sin(theta_10 + theta_arm - theta_elbow)
E = E_x, E_y
### PLOTS
fig, ax = plt.subplots()
ax.set_aspect('equal')
# draw the leg gear
inner_r_gear = 5
r_gear = d_gear / 2
inner_leg_circle = plt.Circle((0, 0), radius=inner_r_gear, linewidth=1, fill=False)
ax.add_artist(inner_leg_circle)
leg_circle = plt.Circle((0, 0), radius=r_gear, linewidth=3, fill=False)
ax.add_artist(leg_circle)
# draw arm gear
inner_arm_circle = plt.Circle((0, d_gear), radius=inner_r_gear, linewidth=1, fill=False)
ax.add_artist(inner_arm_circle)
arm_circle = plt.Circle((0, d_gear), radius=r_gear, linewidth=3, fill=False)
ax.add_artist(arm_circle)
# set axis limits
offset = 5
x_min = np.min(np.concatenate([O2_x, A_x, O4_x, L_top_x, L_bot_x, L_knee_x,
L_A_x, L_bot_x, L_foot_x,
O5_x, B_x, C_x, O6_x, D_x, E_x])) - offset
x_max = np.max(np.concatenate([O2_x, A_x, O4_x, L_top_x, L_bot_x, L_knee_x,
L_A_x, L_bot_x, L_foot_x,
O5_x, B_x, C_x, O6_x, D_x, E_x])) + offset
y_min = np.min(np.concatenate([O2_y, A_y, O4_y, L_top_y, L_bot_y, L_knee_y,
L_A_y, L_bot_y, L_foot_y,
O5_y, B_y, C_y, O6_y, D_y, E_y])) - offset
y_max = np.max(np.concatenate([O2_y, A_y, O4_y, L_top_y, L_bot_y, L_knee_y,
L_A_y, L_bot_y, L_foot_y,
O5_y, B_y, C_y, O6_y, D_y, E_y])) + offset
ax.set_xlim([x_min, x_max])
ax.set_ylim([y_min, y_max])
ax.set_xlabel(r'$x$')
ax.set_ylabel(r'$y$')
# plot the mechanism at the initial position
x_l = [O2_x[0], A_x[0], O4_x[0], L_top_x[0], L_bot_x[0], L_knee_x[0],
L_A_x[0], L_bot_x[0], L_foot_x[0]]
y_l = [O2_y[0], A_y[0], O4_y[0], L_top_y[0], L_bot_y[0], L_knee_y[0],
L_A_y[0], L_bot_y[0], L_foot_y[0]]
ln_l, = ax.plot(x_l, y_l, 'ko-', linewidth=3)
x_a = [O5_x[0], B_x[0], C_x[0], O6_x[0], D_x[0], E_x[0]]
y_a = [O5_y[0], B_y[0], C_y[0], O6_y[0], D_y[0], E_y[0]]
ln_a, = ax.plot(x_a, y_a, 'ko-', linewidth=3)
# animate the mechanism
leg = A, O4, L_top, L_bot, L_knee, L_A, L_foot
arm = O5, B, C, O6, D, E
ani = animation.FuncAnimation(fig, animate, fargs=(ax, ln_l, ln_a, leg, arm),
interval=20, frames=len(theta_2), blit=True)
writer = animation.FFMpegWriter(fps=30)
ani.save('./robot.mp4', writer=writer, dpi=300)
plt.show()
plt.plot(np.rad2deg(theta_2), c, 'k-', linewidth=2)
plt.xlabel(r'$\theta_a$, deg')
plt.ylabel(r'$c$, mm')
plt.title(r'Linear position of slider $c$')
plt.grid()
plt.savefig('./figures/c.png', dpi=300)
plt.show()
plt.plot(np.rad2deg(theta_2), dc, 'k-', linewidth=2)
plt.xlabel(r'$\theta_a$, deg')
plt.ylabel(r'$\dot{c}$, mm/s')
plt.title(r'Linear speed of slider $c$')
plt.grid()
plt.savefig('./figures/dc.png', dpi=300)
plt.show()
plt.plot(np.rad2deg(theta_2), np.rad2deg(theta_4), 'k-', linewidth=2)
plt.xlabel(r'$\theta_a$, deg')
plt.ylabel(r'$\theta_c$, deg')
plt.title(r'Angular position of link $c$')
plt.grid()
plt.savefig('./figures/theta_4.png', dpi=300)
plt.show()
plt.plot(np.rad2deg(theta_2), omega_4, 'k-', linewidth=2)
plt.xlabel(r'$\theta_a$, deg')
plt.ylabel(r'$\omega_c$, rad/s')
plt.title(r'Angular velocity of link $c$')
plt.grid()
plt.savefig('./figures/omega_4.png', dpi=300)
plt.show()
plt.plot(np.rad2deg(theta_2), np.rad2deg(theta_5), 'k-', linewidth=2)
plt.xlabel(r'$\theta_a$, deg')
plt.ylabel(r'$\theta_f$, deg')
plt.title(r'Angular position of link $f$')
plt.grid()
plt.savefig('./figures/theta_5.png', dpi=300)
plt.show()
plt.plot(np.rad2deg(theta_2), omega_5, 'k-', linewidth=2)
plt.xlabel(r'$\theta_a$, deg')
plt.ylabel(r'$\omega_f$, rad/s')
plt.title(r'Angular velocity of link $f$')
plt.grid()
plt.savefig('./figures/omega_5.png', dpi=300)
plt.show()
plt.plot(np.rad2deg(theta_2), np.rad2deg(theta_6), 'k-', linewidth=2)
plt.xlabel(r'$\theta_a$, deg')
plt.ylabel(r'$\theta_g$, deg')
plt.title(r'Angular position of link $g$')
plt.grid()
plt.savefig('./figures/theta_6.png', dpi=300)
plt.show()
plt.plot(np.rad2deg(theta_2), omega_6, 'k-', linewidth=2)
plt.xlabel(r'$\theta_a$, deg')
plt.ylabel(r'$\omega_g$, rad/s')
plt.title(r'Angular velocity of link $g$')
plt.grid()
plt.savefig('./figures/omega_6.png', dpi=300)
plt.show()
plt.plot(np.rad2deg(theta_8), np.rad2deg(theta_9), 'k-', linewidth=2)
plt.xlabel(r'$\theta_8$, deg')
plt.ylabel(r'$\theta_n$, deg')
plt.title(r'Angular position of link $n$')
plt.grid()
plt.savefig('./figures/theta_9.png', dpi=300)
plt.show()
plt.plot(np.rad2deg(theta_2), omega_9, 'k-', linewidth=2)
plt.xlabel(r'$\theta_a$, deg')
plt.ylabel(r'$\omega_n$, rad/s')
plt.title(r'Angular velocity of link $n$')
plt.grid()
plt.savefig('./figures/omega_9.png', dpi=300)
plt.show()
plt.plot(np.rad2deg(theta_8), np.rad2deg(theta_10), 'k-', linewidth=2)
plt.xlabel(r'$\theta_8$, deg')
plt.ylabel(r'$\theta_p$, deg')
plt.title(r'Angular position of link $p$')
plt.grid()
plt.savefig('./figures/theta_10.png', dpi=300)
plt.show()
plt.plot(np.rad2deg(theta_2), omega_10, 'k-', linewidth=2)
plt.xlabel(r'$\theta_a$, deg')
plt.ylabel(r'$\omega_p$, rad/s')
plt.title(r'Angular velocity of link $p$')
plt.grid()
plt.savefig('./figures/omega_10.png', dpi=300)
plt.show()
plt.plot(L_foot_x, L_foot_y, 'k-', linewidth=2)
plt.xlabel(r'$X$, mm')
plt.ylabel(r'$Y$, mm')
plt.title(r'Position of the foot tip')
plt.grid()
plt.savefig('./figures/foot.png', dpi=300)
plt.show()
plt.plot(E_x, E_y, 'k-', linewidth=2)
plt.xlabel(r'$X$, mm')
plt.ylabel(r'$Y$, mm')
plt.title(r'Position of the hand tip')
plt.grid()
plt.savefig('./figures/hand.png', dpi=300)
plt.show()
return 0
if __name__ == '__main__':
sys.exit(main())