#c #vector #angle #quaternions #euler-angles
#c #вектор #угол #кватернионы #углы Эйлера
Вопрос:
Поскольку это сложный вопрос, который обычно приводит к большой путанице (я задавал варианты этого вопроса ранее, но никогда не задавал вопрос правильно и никогда не получал ответа), я постараюсь сделать это как можно более понятным.
Факты:
- Я использую Unity.
- Я могу легко получить векторы вперед, вверх и вправо из любого вращения кватерниона.
- Я не могу просто записать свои собственные углы Эйлера, изменить их и применить вращение через новый кватернион, потому что объект управляется физикой.
- Я вообще не очень хорошо разбираюсь в математике, если она не написана в коде (или псевдокоде), так что это было бы наиболее полезно для меня.
- Мне было бы проще всего понять ответ в стиле C , но я могу разработать практически любой код.
- Я НЕ пытаюсь заставить кого-либо писать код за меня! Я прошу ответа только в коде или псевдокоде, потому что я никогда не учился читать обычные математические закорючки; Я программист, а не математик.
- Unity использует левостороннюю систему координат. X = вправо, Y = вверх, Z = вперед.
Что я пытаюсь сделать:
Я пытаюсь воспроизвести анимацию на гуманоидной костной структуре и, используя крутящий момент (силу вращения), подтолкнуть физическую тряпичную куклу примерно в ту же позу, что и костная структура.
Проблема:
Я могу полностью работать в кватернионах вплоть до того момента, когда мне нужно применить крутящий момент к жестким телам. AddTorque
Функция эффективно работает в углах Эйлера, что означает, что я не могу использовать кватернионы. Я могу легко извлечь углы Эйлера из кватернионов, но они ненадежны и приводят к тому, что тряпичная кукла сильно расшатывается.
Что мне нужно:
Мне нужно рассчитать надежные 3D-углы Эйлера (например, те, которые не переключаются с на — «случайным образом») из векторов вперед, вверх и вправо. Я понимаю, что это немного сложно, но именно поэтому я спрашиваю здесь: мне не хватает знаний и опыта, чтобы самостоятельно решить эту проблему.
Учитывая, что сами векторы надежны, я не вижу причин, по которым было бы невозможно вычислить из них надежные углы Эйлера. Кроме того, я не знаю, какой порядок вращения я хотел бы или нужен для углов Эйлера, но я считаю, что это было бы довольно легко изменить позже.
Любая помощь будет высоко оценена!
Комментарии:
1. Я уже отвечал на подобные вопросы раньше; Я не думаю, что вы сможете реализовать решение, не понимая математики. Извините, но физика такая.
2. Может быть, вы могли бы попробовать меня. Я понимаю изрядное количество математики, но только когда написано на языке кода.
3. В видео на YouTube говорится, что вы эффективно задаете вектор крутящего момента в локальной системе отсчета твердого тела . Это не имеет никакого отношения к углам Эйлера!
4. Хорошо, у вас есть аккуратный приемочный тест для функции преобразования?
5. Я никогда этого не делал. Но вот как это выглядит для меня: вы можете соединить два заданных кватерниона с помощью Slerp. Поиск courses.cms.caltech.edu/cs171/quatut.pdf для
Slerp
. Вы можете параметризоватьt
его,t(tSmooth)
чтобы получить плавную кривую в зависимости от вашего сглаженного времениtSmooth
, для которого вы можете рассчитать угловое ускорение (формула для угловой скорости приведена в документе). Угловое ускорение, выраженное в локальных координатах, — это то, что вам нужноAddTorque
.
Ответ №1:
Во-первых, я хотел бы сказать, что я решил свою проблему полностью благодаря усилиям @Tobias. Большое, большое спасибо! Все это время я подходил к проблеме не с того конца. Я предположил, что мне нужно использовать AddTorque
определенным образом (с углами Эйлера) и работал оттуда, но @Tobias (и @JarkkoL чуть позже) указали, что мне нужно использовать AddTorque
по-другому.
Итак, это то, что я сделал в UnityScript (фактически JavaScript):
var quat0:Quaternion;
var quat1:Quaternion;
var quat10:Quaternion;
quat0=transform.rotation;
quat1=target.transform.rotation;
quat10=quat1*Quaternion.Inverse(quat0);
rigidbody.AddTorque(quat10.x,quat10.y,quat10.z,ForceMode.Force);
И, вопреки всем ожиданиям, это РАБОТАЕТ!! Это просто… работает! Конечно, кубу твердого тела требуется много времени, чтобы успокоиться, но это потому, что мне нужен ПИД-контроллер. Или, может quat10
быть, нуждается в нормализации, не уверен. Я разберусь с этим 🙂
Я понятия не имел, что вы действительно можете использовать эту часть quat сама по себе.
Комментарии:
1. Да, если вы посмотрите на некоторую литературу о единичных кватернионах для представления 3D-поворотов, вы обнаружите, что q = [v * sin (угол / 2), cos (угол / 2)], где v = 3D ось вращения (единичный вектор) и угол = угол поворота вокруг оси.
2. @JarkkoL Итак … то, что я никогда не понимал в отношении кватернионов, почему они лучше, чем просто простое старое представление угла наклона оси (которое, похоже, не вызывает у меня проблем)? Они просто лучше для вычислений или что-то в этом роде?
3. Да, существует целый класс математических операций, которые вы можете применить к кватернионам. Например, если вам нужно объединить вращения (например, для выполнения иерархических преобразований), вы просто умножаете два кватерниона, как вы делаете с матрицами.
4. В документации пишут, что тело начнет вращаться вокруг глобальной оси, в то время как на youtube говорится, что крутящий момент прикладывается к локальной оси. Версия для YouTube будет означать, что вам нужно преобразовать вектор крутящего момента в локальные координаты. Подробнее об этом в следующем комментарии. Обе версии согласуются для поворота вокруг одной оси поворота. Они различаются для конкатенированных вращений по нескольким осям.
5. q0 — это ориентация рамки в момент времени, когда вы хотите применить крутящий момент. Чтобы преобразовать вектор крутящего момента q10 в координаты w.r.t. q0, вы можете умножить обратное (q0) * q10 * q0. Предыстория: представьте представление q10 с помощью q0 как вращение q10 назад с обратным (q0), которое просто дает обратный (q0) * q1 * Обратный (q0) * q0 = Обратный (q0) * q1 . ( Кватернионы как вращения и однородные координаты )
Ответ №2:
Во-первых, я думаю, вам больше повезло бы на форумах Unity для вопросов, связанных с Unity (: Тем не менее, я думаю, что вы неправильно интерпретируете интерфейс AddTorque(), если вы используете именно этот: http://docs.unity3d.com/ScriptReference/Rigidbody .AddTorque.html
Вместо передачи углов Эйлера вы передаете вектор функции, которая является осью вращения. Я не знаком с Unity, но я считаю, что длина вектора определяет, сколько крутящего момента нужно добавить. Углы Эйлера по своей сути являются плохим представлением для поворотов, поэтому вы всегда должны предполагать (если не задокументировано иное), что хорошо зарекомендовавшие себя API работают с кватернионами, парами осей / углов или матрицами, когда дело доходит до поворотов. Углы Эйлера — это более удобное представление для конечных пользователей.
Комментарии:
1. На самом деле я не верю, что мне больше повезло бы с ответами Unity — культура там даже близко не подходит к SO, и, похоже, экспертов очень мало. По
AddTorque()
функции: вы правы. Функция действительно работает с вектором. Проблема заключалась в том, как определить, что это за вектор. Я собираюсь ответить на свой собственный вопрос, так что вы увидите, что я сделал в конце 🙂