我可以分享我的算法。它是一种辛算法,基于将惯性矩阵拆分为两个惯性矩阵之和,每个惯性矩阵有两个相等的轴,这导致将角动量微分方程(所谓的欧拉方程)的原始系统拆分为两个系统具有两个相等惯性轴的物体的微分方程。每个系统都可以显式求解,然后将两个系统的相流以跳跃式的方式组合起来。因此,该算法与原系统一样保持角动量,准能量守恒,即能量几乎守恒,能量不耗散,因此不存在角速度漂移。这是因为该算法在角动量球面上保留了所谓的辛结构,这在几何上意味着该算法保留了该球面上的面积。
import math
import numpy as np
def Rot_3(m):
cs = math.cos(m)
sn = math.sin(m)
return np.array([
[cs, -sn, 0],
[sn, cs, 0],
[ 0, 0, 1]])
def Rot_1(m):
cs = math.cos(m)
sn = math.sin(m)
return np.array([
[1, 0, 0],
[0, cs, -sn],
[0, sn, cs]])
def vector_to_matrix(Vector):
Matrix = np.array([ 0, - Vector[2], Vector[1]],
[ 0, 0, -Vector[0]],
[ 0, 0, 0 ])
return Matrix - Matrix.T
def Angular_Momentum_step(M_input, k_23, k_21, t_step):
M_step = Rot_3(t_step*k_23 * M_input[2]/2).dot(M_input)
M_step = Rot_1(t_step*k_21 * M_step[0]).dot(M_step)
M_step = Rot_3(t_step*k_23 * M_step[2]/2).dot(M_step)
return M_step
def Rotation_step(M, I_inv, t_step):
O = I_inv*M
angle = math.sqrt(O.dot(O))
O = O / angle
angle = t_step*angle
O = vector_to_matrix(O)
U = np.array([[1,0,0],[0,1,0],[0,0,1]])
U = U + math.sin(angle)*O + (1-math.cos(angle))*(O.dot(O))
return U
def Propagate_Angular_Momentum(M_initial, Inertia, n_iterations, t_step):
I_inv = np.array([1/Inertia[0], 1/Inertia[1], 1/Inertia[2]])
k_23 = I_inv[1]-I_inv[2]
k_21 = I_inv[1]-I_inv[0]
M_evolution = np.empty((3, n_iterations), dtype=float)
M_evolution[:,0] = M_initial.copy()
for i in range((n_iterations-1)):
M_evolution[:,i+1] = Angular_Momentum_step(M_evolution[:,i], k_23, k_21, t_step)
return M_evolution
def Propagate_Rotation(Body_initial, Moment_initial, Inertia, n_iterations, t_step):
I_inv = np.array([1/Inertia[0], 1/Inertia[1], 1/Inertia[2]])
k_23 = I_inv[1]-I_inv[2]
k_21 = I_inv[1]-I_inv[0]
Moment_evolution = np.empty((3, n_iterations), dtype=float)
Moment_evolution[:,0] = Moment_initial.copy()
Body_evolution = np.empty((3, n_iterations+1), dtype=float)
Body_evolution[:,0] = Body_initial.dopy()
for i in range((n_iterations-1)):
Moment_evolution[:,i+1] = Angular_Momentum_step(Moment_evolution[:,i], k_23, k_21, t_step)
Body_evolution[:,i+1] = Rotation_step(Moment_evolution[:,i], I_inv, t_step)
Body_evolution[:,i+1] = Body_evolution[:,i+1].dot(Body_evolution[:,i])
return Body_evolution, Moment_evolution
# a test example, set up the initial angular velocity and the
#
I1 = 2.35
I2 = 2.0
I3 = 1.0
I = np.array([I1, I2, I3])
O = np.array([0, 2, 0.95])
O = Rot_3(-math.pi*(30)/180).dot(O)
M = I*O
dt = 0.3
n_iter=500
# propagate the system
Momenta = Propagate_Angular_Momentum(M, I, n_iter, dt)
# plot
fig = plt.figure()
ax = fig.add_subplot(1,2,1,projection='3d')
ax.set_xlim((-4, 4))
ax.set_ylim((-4, 4))
ax.set_zlim((-4, 4))
ax.plot(Momenta[0,:], Momenta[1,:], Momenta[2,:], 'r-')
plt.show()
观察角动量总是穿过总是在二维球面上的红色曲线。曲线看起来是封闭的,没有任何坐标轴向外盘旋,与车身固定框架中的惯性轴对齐。