3D пружина — как ввести правильную разность углов в растяжение пружины (F = -kx)

#python #angular #spring #quaternions #motion

Вопрос:

Я пытаюсь совершить колебательное движение, используя кватернионы (физика покачивания — точки P, перемещающейся по сфере вокруг начала координат O).

3d угловое вращение

Из моих исследований я знаю, что в 3D я могу рассчитать следующий шаг вращения q[n 1] по предыдущему вращению кватерниона и угловой скорости:

 q[n 1] = q[n]   0.5 * wq * q[n]   #  q[n] - quat rotation at n-th time step.
wq = Quaternion(0, w.x, w.y, w.z) # quaternion from angular velocity w
w = w   acc * dt # angular velocity from euler integration
acc = (-stiff*x   damp*w)/m # damped spring motion  m a =  - stiffness * x   damp * vel
 

x — различия между положением покоя и текущим положением. Мой вопрос в том, что мне подключить к x для 3D-вращения? Я попытался поместить различия во вращении между направлением покоя и текущим направлением как угол оси*(vec3) и как поворот Эйлера (vec3):

 x = rot_diff = rest_dir - current_dir  as  vec3_axis * angle
 

Даже при низкой жесткости и высоком демпфировании система взрывается, когда я поворачиваю rest_dir более чем на одну ось (например, поворот на 90 градусов X — ок,
20 градусов в y — sim становится нестабильным). Это заставляет меня задуматься, возможно, мне придется разделить уравнение ускорения на три компонента — поскольку вращение вокруг одной оси работает нормально… — может быть, относительно вектора rest_dir?
введите описание изображения здесь

Код

 quat_diff = self.rest_dir.rotation_difference(self.current_dir)
axis, angle = quat_diff.to_axis_angle()        
diff_ang_vel = angle*axis


spring_force = - self.stiffness*diff_ang_vel - self.damping * self.ang_vel # F = -kx - bv - g*m
acc = spring_force / self.mass
self.ang_vel  = acc * dt
        
omega_quat = Quaternion((0, self.ang_vel.x, self.ang_vel.y, self.ang_vel.z))
self.current_dir  = 0.5 * omega_quat @ self.current_dir
self.current_dir.normalize()