Интерполяция движений на плоскости через матр. экспоненту

Aug 27, 2024 03:56

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

Сейчас покажу, как того же самого можно добиться в формализме матриц 3х3 и векторов 3х1 вида (x;y;1), через матричную экспоненту.



Формализм достаточно распространённый. Хотя у нас в задаче и два измерения, но матрица 2х2 может выражать лишь поворот. Для описания произвольного движения надо ещё добавить вектор параллельного переноса, но тогда движение будет записываться аж ДВУМЯ операциями: умножить на матрицу и прибавить вектор. Чтобы свести движение к одной операции матричного умножения, добавляют "фиктивную" третью координату, которая всегда равна единице, и тогда матрица произвольного движения выглядит так:



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

Когда мы разбирались с некомм. дуал. компл. числами, мы стали находить экспоненту от числа с нулевой действительной частью, по той причине, что действительная часть всё равно коммутирует с любой другой, и потому мы знали, что можем наш ответ (где есть мнимая и дуальная часть, но нет действительной) помножить на экспоненту от действительной части - это и будет экспонента В ОБЩЕМ ВИДЕ.

А вот брать матричную экспоненту от матрицы, указанной выше, мы НЕ БУДЕМ, слишком сложно, да и не нужно! Нам нужно взять её лишь от "генератора произвольного движения". Пусть у нас есть произвольный вектор r вида (x;y;1). Применив к нему бесконечно малое движение, а именно, поворот на угол α и сдвиг на (Δx; Δy), мы получим новый вектор:



(E - единичная матрица 3х3)

Матрица G и будет генератором произвольного движения. Получить её можно, заменив в обычной матрице движения на плоскости cos(α) единицей, sin(α) просто на α, и затем вычесть из получившегося единичную матрицу.

Собственно, E+G - это начало разложения в ряд матрицы exp(G). Для малых движений такого разложения достаточно, а ежели мы хотим перейти уже к "крупным" движениям, нужна честная экспонента.

Легко, к примеру, иллюстрируется матрица 2х2, генерирующую поворот на угол α (назовём её R - rotation). Умножая её на вектор (x;y), получим:



Из вектора мы получили касательную к нему, идущую против часовой стрелки (если α положительный), длина которой равна длине дуги, которую этот вектор должен будет описать при повороте на α. В первом приближении, чтобы изобразить этот поворот, нам достаточно прибавить касательную к вектору - вот мы и получим обновлённый вектор.

А если нужно повысить точность, мы можем разбить α на N частей, и применить N последовательных преобразований, т.е найти матрицу:



Что как раз напоминает предел, которым можно определить exp(x), надо лишь N устремить к бесконечности. Ещё один способ показать, как экспонента порождает повороты, у меня приведён в ликбезе по кватернионам, глава " запись вращения через кватернионы". Там мы пришли и к ряду, также мы можем сделать и здесь:



Для такой простой матрицы 2х2 можно найти результат прямо "в лоб", почленно. Возведём её в квадрат:



И дальше уже соображаем: при возведении матрицы R в чётную степень 2n будем получать единичную матрицу, помноженную на (-1)nα2n, а при возведении в нечётную степень 2n+1 - исходную R, дополнительно помноженную на (-1)nα2n. И получится:



Первую скобку тут же опознаём как разложение cos(α) в ряд, а вторую скобку - как разложение sin(α), так что:



Обычная матрица поворота, кто бы мог подумать!

А теперь, наконец, посчитаем матричную экспоненту из нашего генератора произвольных движений на плоскости, матрицы G.

Тут я поначалу испугался подхода "в лоб", полагая, что при последовательном возведении в степень начнётся какой-то лютый песец. И оттого решил сделать "как учили", через Жорданову форму. Первым делом нужно найти собственные значения:



Если α=0, получим собственное значение 0 с кратностью 3. Тут, согласно теории, начинается что-то страшное в виде "жордановой клетки 3х3" и хитро находимых корневых векторов, но, по счастью, при α=0 мы и "в лоб" сообразим. Ведь тогда G2=0, следовательно, exp(G)=1+G (все последующие слагаемые нулевые), а значит,



Кто бы сомневался: чистый параллельный перенос (без поворотов) работает одинаково хоть на малых значениях, хоть на сколько угодно больших!

Так что разберёмся с "основным" вариантом, когда α≠0. Тогда имеем 3 различных собственных значения: 0 и ±iα. Это очень хорошо: наша Жорданова форма свелась к простой диагональной матрице и базиса из собственных векторов! Для каждого собственного значения надо найти собственный вектор. Для начала, для λ1=0:



Применяем метод Гаусса, причём преобразуем исключительно матрицу 3х3, без добавочки в виде вектора 3х1, поскольку он всё равно нулевой, и как эти нули между с собой не складывай и на константы не умножай - так и останутся нули!



(верхние строки поменяли местами и поделили на α)

Нули в нижней строке означают, что мы можем произвольно выбрать значение z. Постановим его равным α, тогда x,y найдём по верхним строчкам, в итоге:



Теперь найдём собственный вектор для собственного значения +iα:



Неприятные выкладки в правом столбце, на самом деле, "уничтожаются" прибавлением к верхним строкам нижней с нужными коэффициентами. Тупо всё над ней зануляем:



На этот раз у нас произвольная вторая компонента вектора, пусть это будет единичка. Третья компонента - строго НОЛЬ, решение уравнения z=0 (кто бы мог подумать), а первая выражается через вторую. Получаем вектор:



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



Теперь мы можем построить матрицу из собственных значений по главной диагонали, именно её мы загоним под экспоненту:



Давайте и экспоненту сразу возьмём:



И ещё нам нужна матрица из собственных векторов:



На неё мы домножим результат слева. Но ещё надо найти обратную от неё... Увы, я не музыкант, в дополнительных минорах теряюсь напрочь, все посчитать и ни разу в знаке не ошибиться - просто невыполнимая для меня задача... Так что по-старинке, через элементарные преобразования, лучше посчитаю:



(каждую строку поделил на первый элемент, чтобы в первом столбце были единички)



(вычли первую строчку из двух других, затем две нижние строки поменяли местами, и среднюю поделили на i/y)



(к первой строчке прибавили вторую, домноженную на i/y, а из третьей вычли вторую, домноженную на 1/x+i/y, затем третью строчку поделили на 2/x и прибавили к второй)

Фух, в правой части мы получили обратную матрицу...

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

Осталось перемножить 3 матрицы - и мы получим ответ. Сначала диагональную матрицу, от которой уже взяли экспоненту, помножим слева на матрицу собственных векторов:



И теперь этот результат справа на матрицу, обратную матрицу собственных векторов:



Это и есть ответ, только его надо немного причесать. Экспоненты мы по известным формулам превращаем в синус и косинус, т.е верхний квадрат 2х2 - это снова самая обычная матрица поворота, которую мы вывели таким вот извращённым способом. А справа пока что слегка поменяем местами слагаемые:



Это уже вполне сойдёт за ответ!

Ровно так я его находил в эту субботу. Надо же было развеяться и отдохнуть от работы... А сегодня решил попробовать всё-таки посчитать В ЛОБ, т.е возводить исходную матрицу G в квадрат, затем в куб, и потом найти закономерности и найти каждый компонент итоговой матрицы по отдельности. Оказывается, В ДВЕ СТРОЧКИ делается! Вот G2:



Далее, G3:



И, для порядку, G4:



Ещё раз убеждаемся, что верхний квадрат 2х2 - всё та же матрица поворота (её мы уже выводили), в нижней строке получится 0;0;1 (единица - из единичной матрицы E), то есть надо лишь два правых элемента посчитать. Для верхнего из них:



Первая скобка - как синус, только все степени на единичку ниже, то бишь sin(α)/α. А вторая - почти косинус, только знак другой и единицы нет, и тоже степени на единицу ниже. Короче, (1-cos(α)/α.

Ну и то же самое со вторым, ответ получается тот же, что и через Жорданову форму. Ещё и надёжней: там мы при нахождении обратной матрицы собственных векторов очень вольно обращались с обратными величинами, а ведь по-хорошему надо было отдельно рассмотреть x=0 или y=0... И перед этим пришлось два разных варианта посмотреть, с α=0 либо нет, и потом их "склеивать". А тут "из коробки" всё склеено, надо просто помнить, что ряды для sin(α)/α и подобных соответствуют функциям, где особые точки уже устранены.

Небольшая проверка на вшивость.
При α стремящемся к нулю, sin(α)/α стремится к единичке, тогда как (1-cos(α))/α - к нулю, так что на α=0 у нас не возникает "ступеньки" с ранее найденной матрицей. Само по себе появление "синус икс на икс" обнадёживает: ведь два этих формализма (матричная экспонента и некомм. дуал. компл. числа) должны в итоге дать идентичные результаты! Но там синус был от половинного угла, а здесь - от полного. Ещё и "косинус икс на икс" некий выполз...

Кроме того, если мы хотим научиться и логарифм находить, нам нужно научиться обращать выражения в последней колонке: зная их значения и зная α, находить исходные икс с игреком.

Давайте запишем два этих числа в матричной форме:



1-cos(α) можно сразу заменить на 2sin2(α/2), ну а sin(α), за компанию - на 2sin(α/2)cos(α/2). И потом синус вместе со знаменателем выносим общим множителем перед матрицей:



Вот это поворот!
Теперь и здесь у нас один-единственный "синус икс на икс", с половинным углом в аргументе, а впридачу к нему поворот на половинный угол! Казалось бы, причём здесь кватернионы и некомм. дуал. компл. числа!

Зато теперь найти обратное преобразование, "матричный логарифм" - вообще раз плюнуть! sin(α/2)/(α/2) просто обращаем, получая (α/2)/sin(α/2), а матрицу половинного поворота - транспонируем, чтобы развернуться назад.

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

Нда, аналитическая геометрия и линейная алгебра были моим самым нелюбимым предметом в институте. Вот и не знаю, то ли Стокгольмский синдром, то ли весёлый икигай.

кватернионы-это просто (том 1), странные девайсы, математика, работа

Previous post Next post
Up