nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

Так ли страшно 0,99969 вместо 1?

В размышлениях о DMA, о возможных последствиях "смешивания" старых и новых значений при выдаче целевой информации, опять выполз вопрос:

насколько это плохо/некрасиво, если мы вместо кватерниона малого поворота 1+(φx/2)i+(φy/2)j+(φz/2)k возьмём 0,999969+(φx/2)i+(φy/2)j+(φz/2)k? То есть, вместо 1 будет 1-2-15, максимальное число, которое можно представить в формате Q1.15 (в целых числах это 32767).

И внезапно прихожу к выводу: Ещё лучше взять 0,9999084 (в целых числах 32765)


Ведь по большому счёту, мы используем приближение. Допустим, у нас стоял датчик угловой скорости, и он за один период измерения показал поворот на угол α По-хорошему, мы должны были бы записать кватернион поворота



но не делаем этого, решив что cos(x)=1, sin(x)=x для достаточно малых значений, поэтому вполне сойдёт вот так:



Из-за использования приближения у нас может произойти две вещи:
- нарушится норма кватерниона, отклонится от единички,
- нарушится направление.

Нарушение нормы - дело поправимое, я пришёл к выводу, что после каждого обновления кватерниона можно его нормировать. Размышления "а давайте его нормировать на каждый сотый раз, сэкономим кучу вычислительных ресурсов" как-то не работают в системе реального времени, ну нельзя такие дополнительные операции "размазать тонким слоем" - вот есть кватернион, сделай с ним всё что надо - и когда новые показания датчика придут, снова его обновляй!

Главное - направление сохранить как можно точнее!

Вместо поворота на угол α мы таким приближённым кватернионом выражаем поворот на угол:


И ошибка составит:


Изобразим её на графике:


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

Если же у нас не было возможности использовать единицу (она непредставима), и вместо неё поставили 1-2-15, давайте это будет 1-ε, то в действительности мы выразим вот такое направление:


Выглядит очень странно... Но посмотрим графики:


В нуле ошибка нулевая, что не должно удивлять: кватернион (1-ε)+0i спокойно отнормируется до 1+0i и будет выражать нулевой поворот. Затем ошибка сразу же (с ненулевым наклоном) идёт вверх, достигая максимума аж в 0,046 угловой секунды (ужас-то какой :)), выходит снова в ноль и меняет знак. В дальнейшем величина ошибки даже МЕНЬШЕ, чем при нашем "правильном приближении" с единичкой.

Самое забавное, что все эти ошибки вблизи нуля всё равно непредставимы в наших 16-битных числах! Я взял мнимую часть 0/32768, затем 1/32768, 2/32768 и так далее (эти значения как раз можно записать ТОЧНО). Затем, действительную часть построил 3 разными способами:

1. Считая, что мнимая часть это "синус", а поставил в действительную часть "косинус", округлив до ближайшего представимого числа (в том числе и 32768, чтобы никого не обидеть). Полученные при этом значения считаются "эталонными".
2. Поставил в действительную часть 32768 (тем самым изобразив самый очевидный способ) и затем отнормировал.
3. Поставил в действительную часть 32767 (потому что 32768 непредставимо) и отнормировал.

Оказалось, что при углах до 2,75° (мнимая часть до 788/32768) все три метода дают абсолютно одинаковые кватернионы, то есть, дополнительная ошибка вообще не вносится. Затем, на 789/32768, "эталонный" метод даёт 32758+789i, а оба "приближённых" метода: 32759+789i.

А далее, приближённый метод с 32767 вместо 32768 (т.е 0,99969 вместо 1) становится даже немножко предпочтительнее! Это, в принципе, и ясно из графика, ошибка там всегда меньше.

Мало того, на углах до 2,75° точно так же никаких ошибок не получается, если в действительной части поставить 32766, либо 32765. А вот 32764 уже нельзя, его хватает лишь до 0,63°.

Добавим на график угловой ошибки ещё и 32765/32768 вместо единицы:


Если начальный "горбик" оказывается полностью скрыт малой разрядностью нашего кватерниона (по 16 бит на каждую компоненту), то использовать 32765 вместо 32768 выходит однозначно лучше!

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

Хотя я не пробовал рассмотреть все 4 компоненты, может там всё-таки найдутся отдельные точки на малых углах, где 32765 даст ошибку по сравнению с 32768, но заведомо не больше чем на единичку младшего разряда. И то, это будет означать, что значение было "на границе" и чуть не туда его толкнули.

А вот дальше начинается компромисс: в каждой конкретной задаче, зная диапазон входных значений, можно подыскать наиболее подходящую константу для действительной части, от 32765 и ВНИЗ.



Убедил? :)

Poll #2112344 Кватернион малого поворота

Какое приближение вы бы взяли?

1+(a/2)i+(b/2)j+(c/2)k
1(33.3%)
-1-(a/2)i-(b/2)j-(c/2)k
0(0.0%)
32767/32768+(a/2)i+(b/2)j+(c/2)k
2(66.7%)
32765/32768+(a/2)i+(b/2)j+(c/2)k
0(0.0%)


PS. Впрочем, почти завершив это "исследование", я вспомнил, почему в своё время так настаивал на -1 вместо 0,99969, но это заслуживает ещё одной небольшой главки в "ликбезе по кватернионам"...
Tags: кватернионы-это просто (том 1), математика, работа, странные девайсы
Subscribe

Recent Posts from This Journal

  • Тестируем atan1 на QuatCore

    Пора уже перебираться на "железо" потихоньку. Решил начать с самого первого алгоритма, поскольку он уже был написан на ассемблере. В программу внёс…

  • Формулы приведения, что б их... (и atan на ТРЁХ умножениях)

    Формулу арктангенса на 4 умножениях ещё немножко оптимизировал с помощью алгоритма Ремеза: Ошибка уменьшилась с 4,9 до 4,65 угловой секунды, и…

  • Алгоритм Ремеза в экселе

    Вот и до него руки дошли, причина станет ясна в следующем посте. Изучать чужие библиотеки было лениво (в том же BOOSTе сам чёрт ногу сломит), писать…

  • atan на ЧЕТЫРЁХ умножениях

    Мишка такой человек — ему обязательно надо, чтоб от всего была польза. Когда у него бывают лишние деньги, он идёт в магазин и покупает какую-нибудь…

  • Ай да Пафнутий Львович!

    Решил ещё немного поковыряться со своим арктангенсом. Хотел применить алгоритм Ремеза, но начал с узлов Чебышёва. И для начала со своего "линейного…

  • atan(y/x) на двух умножениях!

    Чего-то никак меня не отпустит эта тема, всё кажется, что есть очень простой и эффективный метод, надо только его найти! Сейчас вот такое…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 8 comments