Матрица допуска в GenericJoint: свободные и зафиксированные степени свободы

GenericJoint в библиотеке Oimo.js предоставляет гибкий способ соединения двух тел с произвольной конфигурацией ограничений на их движение. Ключевым аспектом является управление степенями свободы (DoF, Degrees of Freedom) в каждой оси, как линейной, так и угловой. Эти ограничения позволяют создавать как полностью зафиксированные соединения, так и частично подвижные механизмы.

Свободные и зафиксированные степени свободы

Каждая степень свободы может быть:

  • Свободной (free) — движение по соответствующей оси не ограничено, тело может перемещаться или вращаться без сопротивления.
  • Зафиксированной (locked) — движение или вращение полностью заблокировано, тела остаются фиксированными относительно друг друга по этой оси.
  • Ограниченной диапазоном (limited) — движение допускается только в пределах заданного минимального и максимального значения.

В GenericJoint эти степени свободы задаются через свойства:

  • linearLowerLimit и linearUpperLimit — минимальные и максимальные смещения вдоль осей X, Y, Z.
  • angularLowerLimit и angularUpperLimit — минимальные и максимальные угловые отклонения вокруг осей X, Y, Z.

Пример конфигурации:

const joint = new OIMO.GenericJoint(bodyA, bodyB, {
    position: [0, 1, 0],
    rotation: [0, 0, 0],
    linearLowerLimit: [0, 0, 0],   // X, Y, Z
    linearUpperLimit: [0, 0, 0],   // блокировка перемещений
    angularLowerLimit: [-Math.PI/4, 0, 0], // минимальный угол вокруг X
    angularUpperLimit: [Math.PI/4, 0, 0]   // максимальный угол вокруг X
});

В этом примере все линейные движения заблокированы, а вращение разрешено только вокруг оси X в диапазоне ±45°.

Матрица допуска: представление степеней свободы

Внутри GenericJoint используется матрица допуска (constraint matrix), которая определяет, какие движения разрешены, а какие ограничены. Она состоит из 6 компонент для каждой из осей:

  • первые три — линейные степени свободы по X, Y, Z
  • последние три — угловые степени свободы вокруг X, Y, Z

Каждая компонента может быть представлена числом:

  • 0 — зафиксировано
  • 1 — свободно
  • значение между 0 и 1 — частично ограничено (например, при использовании мягких ограничений или силы пружины)

Матрица позволяет библиотеке эффективно вычислять силы, необходимые для соблюдения ограничений при симуляции.

Настройка свободных и зафиксированных осей

Линейные ограничения:

  • Для полного закрепления позиции тела относительно другого устанавливаются одинаковые значения нижнего и верхнего предела:
joint.linearLowerLimit = [0, 0, 0];
joint.linearUpperLimit = [0, 0, 0];
  • Для разрешения движения по одной оси:
joint.linearLowerLimit = [-Infinity, 0, 0];
joint.linearUpperLimit = [Infinity, 0, 0];

Угловые ограничения:

  • Полная фиксация вращения:
joint.angularLowerLimit = [0, 0, 0];
joint.angularUpperLimit = [0, 0, 0];
  • Ограничение вращения в диапазоне:
joint.angularLowerLimit = [-Math.PI/6, -Math.PI/6, -Math.PI/6];
joint.angularUpperLimit = [Math.PI/6, Math.PI/6, Math.PI/6];

Примеры распространённых конфигураций

  1. Полностью зафиксированный шарнир (rigid connection): Все линейные и угловые ограничения совпадают по верхней и нижней границе, создавая жёсткое соединение.

  2. Шарнир с одной осью вращения (hinge-like): Линейные степени свободы зафиксированы, только одна угловая ось свободна:

joint.angularLowerLimit = [0, -Infinity, 0];
joint.angularUpperLimit = [0, Infinity, 0];
  1. Поршневое соединение (slider-like): Одна линейная ось свободна, вращения зафиксированы:
joint.linearLowerLimit = [-Infinity, 0, 0];
joint.linearUpperLimit = [Infinity, 0, 0];
joint.angularLowerLimit = [0, 0, 0];
joint.angularUpperLimit = [0, 0, 0];

Управление степенями свободы во время симуляции

Oimo.js позволяет динамически изменять ограничения после создания соединения, изменяя матрицу допуска. Это позволяет реализовать механизмы с переменной жесткостью или режимами работы:

// Разблокировать вращение вокруг Z
joint.angularLowerLimit[2] = -Math.PI/2;
joint.angularUpperLimit[2] = Math.PI/2;

// Заблокировать движение по Y
joint.linearLowerLimit[1] = 0;
joint.linearUpperLimit[1] = 0;

При каждом обновлении матрицы библиотека пересчитывает силы, применяемые к телам, чтобы соблюсти новые ограничения без нарушения физической стабильности сцены.

Практические советы

  • Минимизация численных ошибок: полностью фиксированные оси лучше задавать через одинаковые верхние и нижние пределы, чем через очень малые диапазоны.
  • Комбинация свободных и ограниченных степеней свободы позволяет моделировать сложные механизмы — подвески, рычажные системы, трансмиссии.
  • Использование матрицы допуска облегчает визуализацию и отладку механики соединения: по сути, она является картой доступных движений.

GenericJoint в Oimo.js — инструмент тонкой настройки кинематики, который через точное управление степенями свободы позволяет создавать как полностью жесткие соединения, так и сложные механизмы с ограниченными движениями.