Расчет импульса / крутящего момента для обоих тел в фиксированной трехмерной зависимости соединения

У меня есть 2 твердых тела (a & b) и 1 фиксированное ограничение сустава (с относительной трансформацией rela).

Мои цели - достичь: -

Нет. 1. b.transform = a.transform * rela
Нет. 2. Центр масс (_5 _ + _ 6_) не меняется.
Нет. 3. (3-е правило Ньютона) Скорость всей системы (_7 _ + _ 8_) не меняется.
Нет. 4. (3-е правило Ньютона) Угловая скорость всей системы (_9 _ + _ 10_) не меняется.
Нет. 5. Перемещение / вращение обоих объектов для решения этой задачи должно быть минимизировано.

Я хочу применить импульс / крутящий момент к обоим телам, чтобы они постепенно соответствовали требованиям.
Это видео может показать то, что я хочу - (ссылка на YouTube).

Как определить значение импульса / крутящего момента для каждого тела?
Мне нужна приблизительная идея / алгоритм.
Это может быть текст описания без какого-либо кода.

Пример

Вот пример проблемы и ее правильное решение (то есть конечное состояние покоя): -

введите описание изображения здесь

Кодекс (черновик)

Вот мой текущий фрагмент, на всякий случай: -

class Transform {
    Vec3 pos;
    Matrix33 basis;
};

Каждое твердое тело имеет следующие поля: -

class RigidBody {
    float mass;
    Matrix33 inertiaTensor;
    Transform transform;
    Vec3 velocity;
    Vec3 angularVelocity;
};

Исправить ограничение соединения: -

class FixConstraint {
    Transform rela;
    RigidBody* a;
    RigidBody* b;
};

Черновик моего плохого решения

Короче говоря, мне нужно изменить 12 переменных.

  • положение a и b (xyz - 6 переменных)
  • ориентация a и b (угол xyz - 6 переменных)

Затем я могу использовать «Мои цели» № 1 и 2 для создания некоторых уравнений.
Затем, в лучшем случае, я должен решить 12 линейных уравнений с 12 неизвестными переменными.
Я сомневаюсь, что это должно быть так сложно.

Мой предыдущий поиск в Интернете

Я просмотрел различные источники, но в основном они:

  • просто войдите в решатель итераций.
  • попробуйте диагонализовать матрицу + якобиан: понять может только специалист.
  • "Почему бы вам не заглянуть в (вставьте здесь название Physic Engine) исходный код?" без понятных для новичков объяснений.
  • покажите, как использовать (имя Physic Engine) для создания фиксированного ограничения соединения.

Вот некоторые из самых полезных: -

(отредактировал некоторые формулировки и правила, спасибо fafl и Нико Шертлер.)


(отредактировано-добавлено, через несколько дней)
Я считаю, что если я смогу взломать "Point2PointConstraint.cpp" (из Bullet Physics), я полностью пойму алгоритм и принцип.

Я также скопирую его сюда, на всякий случай.
Вот первая часть: -

SimdVector3 normal(0,0,0);
for (int i=0;i<3;i++)
{
    normal[i] = 1;
    new (&m_jac[i]) JacobianEntry(
        m_rbA.getCenterOfMassTransform().getBasis().transpose(),
        m_rbB.getCenterOfMassTransform().getBasis().transpose(),
        m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(),
        m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(),
        normal,
        m_rbA.getInvInertiaDiagLocal(),
        m_rbA.getInvMass(),
        m_rbB.getInvInertiaDiagLocal(),
        m_rbB.getInvMass());
    normal[i] = 0;
}

Вот вторая часть: -

SimdVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA;
SimdVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_pivotInB;
SimdVector3 normal(0,0,0);
for (int i=0;i<3;i++)
{       
    normal[i] = 1;
    SimdScalar jacDiagABInv = 1.f / m_jac[i].getDiagonal();

    SimdVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); 
    SimdVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
    //this jacobian entry could be re-used for all iterations

    SimdVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1);
    SimdVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2);
    SimdVector3 vel = vel1 - vel2;

    SimdScalar rel_vel;
    rel_vel = normal.dot(vel);

    //positional error (zeroth order error)
    SimdScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal

    SimdScalar impulse = depth*m_setting.m_tau/timeStep  * jacDiagABInv -  m_setting.m_damping * rel_vel * jacDiagABInv;

    SimdVector3 impulse_vector = normal * impulse;
    m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition());
    m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition());

    normal[i] = 0;
}

person javaLover    schedule 03.04.2019    source источник
comment
Чтобы прояснить, у вас есть два движущихся и вращающихся тела, и вы хотите установить их расстояние друг от друга на постоянное значение? Если они будут дальше друг от друга, телепортируете ли вы их ближе? Должно ли вращаться получившееся тело? Будет ли каждое из тел вращаться после фиксации (как колеса на машине) или они будут вращаться как одно (как колеса на машине, но с включенными тормозами)?   -  person fafl    schedule 03.04.2019
comment
@fafl Да, постоянный или, по крайней мере, почти постоянный (это мягкое ограничение). На самом деле, мне бы хотелось, чтобы они двигались близко друг к другу, используя импульс и вращающий момент, с правильным третьим законом Ньютона о действии / противодействии (между a и b). Однако это довольно сложно, поэтому телепортироваться не так уж и плохо. О вращении: если a находится слева и движется вверх, а b - справа и движется вниз, если они могут соединиться вместе, общий результат должен примерно вращаться как единое целое по часовой стрелке. (Я немного отредактировал вопрос, спасибо.)   -  person javaLover    schedule 03.04.2019
comment
В момент присоединения тела перестанут крутиться индивидуально? Всегда ли соединение находится в центре каждого тела?   -  person fafl    schedule 03.04.2019
comment
@fafl 1. Да, он должен постепенно перестать вращаться индивидуально. Насколько это постепенно, зависит от силы ограничения. (Но если это слишком сложно, можно прекратить вращение по отдельности резко.) 2. Нет.   -  person javaLover    schedule 03.04.2019
comment
@fafl Эта ссылка может отображать то, что я хочу: youtube.com/watch? v = b4k2Q0i39fY & feature = youtu.be & t = 23. Обратите внимание, что ограничение иногда немного нарушается. XD   -  person javaLover    schedule 03.04.2019
comment
Вот некоторые из моих мыслей перед дальнейшим анализом (обратите внимание, что я не физик): Вращение обоих объектов не должно влиять на угловую или линейную скорость всей системы. Следовательно, вы можете рассматривать оба объекта как массовые точки, и вам нужно только решить, чтобы переводы применялись к обоим объектам. Правило 2 подразумевает, что оба перевода связаны и в некоторой степени дополняют друг друга. Следовательно, если вы знаете одно, вы знаете и другое. Правило 2 должно автоматически подразумевать правило 3. Правило 4 является еще одним ограничением скорости и, вероятно, подразумевает, что оно указывает на общий центроид ...   -  person Nico Schertler    schedule 03.04.2019
comment
Единственное, что осталось решить, - это величина одного перевода, которую вы можете просто определить, предложив вес ограничения. Все остальные неизвестные должны следовать оттуда.   -  person Nico Schertler    schedule 03.04.2019
comment
@Nico Schertler Это полезно. Я постараюсь его закрепить. Спасибо.   -  person javaLover    schedule 05.04.2019
comment
@javaLover Я бы обработал два объекта как один. Итак, единый центр масс, приложите все силы к этому центру масс ... который должен управлять общим относительным вращением тел и движением. А также приложить те же силы к телам, но игнорировать их для движения, использовать их только для локальных вращений. Если такое вращение создает другой импульс силы (либо из-за трения, либо из-за несферической поверхности), вместо этого примените его к центру масс объекта a+b.   -  person Spektre    schedule 11.04.2019
comment
@Spektre 1. Как? Если я приложу силу к CM, как это обработает общую относительную трансформацию? 2. Меня не волнует реакция / обнаружение столкновения (и любое трение). 3. Мне нравится ваш комментарий (как разделение проблемы), но я не могу его понять. 4. Спасибо!   -  person javaLover    schedule 11.04.2019
comment
@javaLover Вы знаете, что такое репер (подвижный трехугольник)? В основном это матрица преобразования 4x4, описывающая трехмерную систему координат вашего a+b объекта. Исходная точка - это центр масс объединенных объектов, а оси выровнены таким образом, чтобы объекты располагались на одной линии / оси (например, x) в каждом обновлении, применяя вращения и движение к этому реперу и вычисляя глобальное положение подобъектов на его основе. . поскольку их локальные координаты всегда будут одинаковыми ... так что это просто вопрос умножения на прямую или обратную матрицу (в зависимости от используемых обозначений)   -  person Spektre    schedule 11.04.2019
comment
@javaLover важны трения, иначе вращающийся шар не будет двигаться по плоскости ... кстати, репер похож на матрицу TBN (тангенс, би-нормальный, нормальный), но в TBN отсутствует позиция ...   -  person Spektre    schedule 11.04.2019
comment
@Spektre Я использую 4x4 и TBN в Opengl, но никогда не слышал о репер / трехстороннем. Благодарю за объяснение. :) Я часто использую эту формулу absoluteTransformChild = absoluteTransformParent*relativeTransformOfThatChild. (на всякий случай, если вы это объясняете); Хм, я до сих пор не верю, что трение связано с этим вопросом. Я согласен с тем, что трение заставляет вращающийся шар двигаться по полу.   -  person javaLover    schedule 11.04.2019
comment
@javaLover, если ваши шары не вращаются (вокруг собственных локальных осей), тогда вам действительно не нужно трение ... да, матрицы преобразования 4x4 из OpenGL такие же, как репер ... вы также можете использовать их для физических вычислений ... это также распространено в робототехнике для прямого и обратного представления кинематики в алгебраической форме, но это уже другая тема ....   -  person Spektre    schedule 11.04.2019


Ответы (1)


Как следует из названия, ограничение - это ограничение, накладываемое на движение двух тел. Следовательно, чтобы успешно смоделировать ограничение, нужно полностью понимать, какие ограничения это ограничение накладывает на два тела, и представлять эти ограничения в виде уравнения импульса или силы. Решатели, основанные на импульсах, используются почти постоянно, а не решатели, основанные на силе, поскольку уравнения первого порядка (скорости) (и соответствующие числа) легче вычислять и обрабатывать, чем уравнения второго порядка (ускорение). Таким образом, мы рассмотрим моделирование импульсов для общих одномерных ограничений (n-мерные ограничения могут быть представлены как одно или несколько одномерных ограничений).

Моделирование ограничения первого порядка (скорости) одномерного ограничения

Первым шагом в моделировании ограничения с помощью импульсов является представление ограничения (ограничений) в виде уравнений первого порядка (скорость / импульс). Рассматриваемое фиксированное ограничение (далее именуемое просто «ограничение») имеет простое позиционное ограничение (нулевого порядка): линейное и угловое положения в пространстве ограничений должны оставаться неизменными (как указано относительным преобразованием rela). Мы можем преобразовать это в ограничение первого порядка, установив тот факт, что для того, чтобы сделать относительное положение двух тел постоянным, их относительная скорость должна быть равна нулю. Таким образом, ограничение можно интерпретировать как гарантию того, что относительные линейные и угловые скорости двух тел в пространстве ограничений равны нулю.

Теперь ограничение можно смоделировать как импульс, который необходимо приложить к системе, чтобы относительная скорость стала нулевой. Если v1 и v2 - начальная и конечная относительные скорости системы, m - масса системы, а j - импульс, приложенный для удовлетворения ограничения, тогда

v2 = v1 + j/m    (1)
v2 = 0           (2)

Первое уравнение справедливо для любого ограничения (это второй закон Ньютона), но второе уравнение (далее именуемое уравнением ограничения) справедливо только для данного ограничения.

Моделирование ограничения нулевого порядка (положения) одномерного ограничения

Наша модель теперь гарантирует, что относительное положение остается постоянным (ограничение первого порядка), но мы по-прежнему не применяем ограничение нулевого порядка, то есть относительное положение B по отношению к A должно быть таким, которое задано относительным преобразованием rela. Если x1 является «ошибкой» в позиции системы ограничений, то это может быть «введено» в импульс с помощью члена Баумгарте beta * x1/h, где h - временной шаг, а beta - параметр, обычно от 0 до 1. Можно считать beta равным быть долей позиционной ошибки, которую решатель должен разрешать в каждом кадре.

Наше уравнение ограничений теперь становится

v2 + beta*x1/h = 0

Примечание. Если решающая программа использует полунеявное интегрирование, тогда x1 является начальной позиционной ошибкой, но если решающая программа использует неявное интегрирование, на самом деле ошибка составляет x2 = x1 + v2*h.

Демпфирование / смягчение ограничения

Как вы указали, ограничение, которое вы ищете, является мягким (или затухающим) ограничением, поскольку вы хотите, чтобы движение происходило постепенно. Чтобы ослабить ограничение экспоненциально, мы моделируем дифференциальное уравнение экспоненциального затухания и добавляем значение, пропорциональное j (которое пропорционально производной скорости dv = v2 - v1, поскольку временной шаг становится бесконечно малым).

Наше уравнение ограничений теперь становится

v2 + beta * x1/h + gamma * j = 0

Где gamma >= 0 - другой параметр (также называемый коэффициентом демпфирования). Если gamma = 0, ограничение будет незатухающим или жестким.

Исключение v2 из двух уравнений и решение полученного уравнения для j дает нам

j = -(v1 + beta * x1/h) * (1/(gamma + 1/m))
                         | equivalent mass |

Решающая программа применяет этот импульс и его отрицательное значение в направлении оси (обычно называемой нормалью) ограничения.

Адаптация и использование общего одномерного мягкого ограничения

Этот общий одномерный импульс мягкого ограничения можно использовать для создания множества различных соединений, таких как фиксированные соединения, пружинные соединения и т. Д. Для фиксированного сустава мы хотим, чтобы ограничение ограничивало положение B и вращение в пространстве A, чтобы они были положением и вращением относительного преобразования. Таким образом, в пространстве A x1 = B.position - rela.origin и v1 = relative velocity of A and B along x1. Однако, поскольку мы хотим ограничить позицию в трех измерениях (т.е. x1 является трехмерным вектором, а не скаляром), мы можем решить ограничение одномерности по каждой из трех осей индивидуально. Затем этот процесс можно повторить для угловых положений и скоростей с использованием того же ограничения. Таким же образом можно получить импульс для любого одномерного ограничения.

Применение ограничения

После вычисления импульс j должен быть приложен к обоим телам в противоположных направлениях, чтобы общий импульс системы ограничений был равен нулю. В положительном состоянии этот импульс должен оттолкнуть два тела, а в отрицательном - сблизить их. Следовательно, если нормаль ограничения указывает от тела A к телу B (согласно соглашению), -j * normal применяется к телу A, а +j * normal применяется к телу B.

При необходимости ограничение 1-D может быть расширено до n-D. Некоторые ограничения, такие как ограничение пружины / расстояния, расположены вдоль линии и, следовательно, являются одномерными ограничениями по своей природе в n мерном пространстве и не требуют многократных итераций решения для разных осей.

Вы также можете изменить уравнение ограничения, чтобы учесть накопленные импульсы при демпфировании для стабильности, если ваш решатель использует теплый пуск. Демпфирующий член становится gamma * (j + j0), где j0 - это накопленный импульс, который прикладывается во время горячего пуска.

Отличия от решателей ограничений Bullet 1.5

Следует отметить, что фиксированное ограничение, которое вы ищете, на самом деле является _ 33_ (с ограничением всех 6 степеней свободы), а не Point2PointConstraint (шарнирный шарнир) в Bullet 1.5. Вы можете посмотреть его реализацию для справки. Решатели ограничений Bullet 1.5 используют немного другое (и немного более сложное) уравнение затухающего импульса (в котором относительная скорость умножается на коэффициент затухания, но не прибавляется к величине, обратной эквивалентной массе), что немного ослабляет ограничение. более. Выбор зависит от предпочтений, но я считаю, что тот, который здесь используется, более оправдан, а также его гораздо легче адаптировать к другим естественным мягким ограничениям (например, параметризация ограничения в терминах частоты пружины и коэффициента демпфирования для имитации демпфированная пружина).

Вы также можете взглянуть на код демпфированной пружины, который, надеюсь, не требует пояснений (мягкое ограничение расстояния) solver в моем 2D физическом движке.

person EvilTak    schedule 14.04.2019
comment
Опс, согласен ... Я ошибся на Point2PointConstraint. Спасибо +1. Я прочту остальную часть ответа позже. XD - person javaLover; 14.04.2019
comment
Не беспокойтесь, это очень много :) - person EvilTak; 14.04.2019
comment
Немного подправили ответ и добавили раздел о применении импульса к телам. Я скоро добавлю раздел о массе связи (также называемой якобианом) и ее значении. - person EvilTak; 15.04.2019
comment
Я неправильно назвал массу ограничения якобианом в комментарии выше - якобиан - это вектор коэффициентов линейной и угловой скоростей в дифференцированном ограничении первого порядка. - person EvilTak; 16.04.2019
comment
Все ясно, пока не дошел до фразы can be "injected" into the impulse using a Baumgarte term. Я предполагаю, что это какое-то предубеждение, но я не могу найти никакой хорошей математической формулы / принципа, подтверждающей это. (Я из тех, кто любит доказывать, прежде чем верить.) Ближайшая ссылка, которую я нашел, - это биография вики Баумгарта. - person javaLover; 21.04.2019
comment
Между прочим, я заметил, что эксперты много говорят о полинявном / неявном, особенно box2d.org/ files / GDC2011 / GDC2011_Catto_Erin_Soft_Constraints.pdf (стр. 15–16) и en.wikipedia. org / wiki / Semi-implicit_Euler_method (скорее справочник, чем учебный материал). Я постараюсь прочитать их еще раз после того, как вы объясните инъекцию Баумгарте. XD - person javaLover; 21.04.2019
comment
Вы можете думать о позиционной коррекции Баумгарте как о применении скорости для исправления ошибки в следующем кадре. Если позиционная ошибка должна быть исправлена ​​в следующем кадре, применяется скорость x1 / h. Мы исправляем часть этой ошибки, а не всю ее в каждом кадре, чтобы предотвратить дрожание и позволить системе легко достичь естественного равновесия. Параметр beta является результатом экспериментов и устанавливается в значение (обычно между 0,05-0,2) после тестирования. Обратите внимание, что ошибка положительная, когда тела должны быть стянуты вместе, и отрицательная, когда тела должны быть оттолкнуты. - person EvilTak; 21.04.2019