Войти
Физика для игрСтатьи

О смысле cfm, о пружине и о дэмпере

Автор:

Этот текст был написан FD aka SoRRoW, и выкладывается здесь с его разрешения.

О смысле cfm, о пружине и дэмпере

Условие каждой связи (математической, кончено) имеет такой вид:

joint.j1[0] * Obj1->velocity + joint.j1[1] * Obj1->omega + joint.j2[0] * Obj2->velocity + joint.j2[1] * Obj2->omega + joint.cfm * lambda[joint] = joint.rhs

где lambda[joint] - это лагранжев множитель для данной связи, который в явном виде если и будет присутствовать вообще, то только на этапе солвинга, и то не в каждом солвере. А математический смысл этой лямбды - это чувствительность целевой функции (напомню, это функция работы сил связей, которая должна быть 0 и потому минимизируется) к данному джойнту, или, говоря по-русски, это сила, с которой мы давим в этом джойнте, чтобы джойнт не разрушился.

В условии:

ExternalForces = InvMass * Acceleration + Jacobian.Trasposed * Lambda

где Лямбда - вектор лямбд всех джойнтов, т.е. каждый джойнт давит на силы и торки своих двух объектов с силой:

(0, ..., 0, j1[0], j1[1], 0, ..., 0, j2[0], j2[1], 0, ..., 0) * lambda[joint]

То есть лямбда - это сила джойнта, заданная в его пространстве. Так вот, получается при не нулевом cfm из условия нашего джойнта можно вывести:

lambda[joint] = (-1/joint.cfm) * (joint.j1[0] * Obj1->velocity + joint.j1[1] * Obj1->omega + joint.j2[0] * Obj2->velocity + joint.j2[1] * Obj2->omega) + (1/joint.cfm) * joint.rhs

Причём вторая скобка - это скорость движения в пространстве джойнта (слетается он или разлетается или стоит неподвижно, не зря без пост-стабилизации Баумграте всё условие джойнта сводится к приравниванию этой скобки к нулю - джойнт должен быть неподвижен). Замечу, что имеются ввиду искомые скорости, скорости следующего кадра, а не скорости предыдущего кадра, которая на самом деле на момент создания джойнта лежат в объектах.

Получается:

joint_force = (1/cfm) * (rhs – joint_velocity)

Если у нас cfm = 1/(time * spring + damper), a rhs = -spring * diff/(time * spring + damper), то условие будет таким:

joint_force = -spring * diff - (time * spring + damper) * joint_velocity

или

joint_force = -spring * (diff + time * joint_velocity) - damper * joint_velocity

Очевидно, что joint_velocity * time - это расстояние, которое пройдёт джойнт-пружина с новыми скоростями до следующего кадра (в смысле, в пространстве джойнта объекты разойдутся или сойдутся на столько), а (diff + time * joint_velocity) - это diff следующего кадра. Получается, что джойнт будет давить обратно пропорционально расстоянию в джойнте к следующему кадру и обратно пропорционально скорости в джойнте, с известными коэффициентами пропорциональности, а это есть обычный закон Гука, поведение обыкновенной пружины.

А теперь читаем в обратном порядке формулы, и понимаем, как вставлять пружины в джойнты.

18 марта 2006