n = len(qd) - 1 # number of links == number of joints - 1
v = [np.empty((6,)) for i in range(n + 1)]
a = [np.empty((6,)) for i in range(n + 1)]
f = [np.empty((6,)) for i in range(n + 1)]
tau = [np.empty(qd[i].shape) for i in range(n + 1)]
v[0] = np.zeros((6,))
a[0] = -np.array([0.0, 0.0, -9.81])
我们继续前向传递,范围从链接 i=1 到树的最后一个链接 i=n:
for i in range(1, n + 1):
p = lambda_[i] # p for "parent"
X_p_to_i[i], S[i], I[i] = compute_joint(joint_type[i], q[i])
v[i] = X_p_to_i[i] * v[p] + S[i] * qd[i]
a[i] = X_p_to_i[i] * a[p] + S[i] * qdd[i] + spatial_cross(v[i], S[i] * qd[i])
f[i] = I[i] * a[i] + spatial_cross_dual(v[i], I[i] * v[i]) - f_ext[i]
向后传递以相反的顺序遍历相同的范围:
for i in range(n, 0, -1):
p = lambda_[i]
tau[i] = S[i].T * f[i]
f[p] += X_p_to_i[i].T * f[i]
最终,我们得到:
def rnea(q, qd, qdd, f_ext):
n = len(qd)
v = [np.empty((6,)) for i in range(n + 1)]
a = [np.empty((6,)) for i in range(n + 1)]
f = [np.empty((6,)) for i in range(n + 1)]
tau = [np.empty(qd[i].shape) for i in range(n + 1)]
v[0] = np.zeros((6,))
a[0] = -np.array([0.0, 0.0, -9.81])
for i in range(1, n + 1):
p = lambda_[i]
X_p_to_i[i], S[i], I[i] = compute_joint(joint_type[i], q[i])
v[i] = X_p_to_i[i] * v[p] + S[i] * qd[i]
a[i] = X_p_to_i[i] * a[p] + S[i] * qdd[i] + spatial_cross(v[i], S[i] * qd[i])
f[i] = I[i] * a[i] + spatial_cross_dual(v[i], I[i] * v[i]) - f_ext[i]
for i in range(n, 0, -1):
p = lambda_[i]
tau[i] = S[i].T * f[i]
f[p] += X_p_to_i[i].T * f[i]
return tau