Почему моя обратная реализация матрицы менее точна? С++

У меня есть матрица преобразования типа Eigen::Matrix4d. И я хотел бы получить его инверсию. Я пишу функцию для себя, чтобы вычислить ее по следующей формуле.

Почему моя обратная реализация матрицы менее точна? С++.

И вот мой код:

Eigen::Matrix4d inverseTransformation(Eigen::Matrix4d T)
{
    Eigen::MatrixX3d R;
    Eigen::Vector3d t;
    R = T.block<3, 3>(0, 0);
    t = T.block<3, 1>(0, 3);
    Eigen::Matrix4d result;
    result.setIdentity();
    result.block<3, 3>(0, 0) = R.transpose();
    result.block<3, 1>(0, 3) = -R.transpose() * t;
    return result;
}



    std::cout<<"Input transformation matrix is:\n" << T << std::endl;
    std::cout << "inverse of T , my implementation:\n" << inverseTransformation(T) << std::endl << std::endl;
    std::cout << "inverse of T , Eigen implementation::\n" << T.inverse() << std::endl << std::endl;
    std::cout << "T * T^(-1), my implementation\n " << T * inverseTransformation(T) << std::endl << std::endl;
    std::cout << "T * T^(-1), eigen's implementation\n " << T * T.inverse() << std::endl << std::endl;

В идеале T * T^(1) должно равняться I. Однако в моем результате есть некоторая ошибка (красная часть на следующем рисунке).

Почему моя обратная реализация матрицы менее точна? С++

Напротив, результат T * T.inverse() намного точнее.

Может кто-нибудь, пожалуйста, скажите мне, почему? Заранее большое спасибо!

Обновлять: Обратной матрицей вращения является ее транспонирование. Результат будет более точным, если я заменю R.tranpose() на R.inverse().

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

Pepijn Kramer 08.12.2022 12:45

в общем, разные алгоритмы дают разные результаты с разной точностью, это не должно быть сюрпризом. Учтите, что у вас будет решение с точностью до 2 цифр, тогда вы можете использовать результат T * T.inverse() для улучшения результата, вы можете делать это итеративно, чтобы постепенно повышать точность. Теперь это зависит только от того, в какой момент вы остановите эту итерацию. И в конечном итоге вы ограничены точностью double

463035818_is_not_a_number 08.12.2022 12:48

Согласно формуле, которую вы опубликовали, верхняя левая часть матрицы должна быть R ^ (-1) (т.е. обратная R), а не транспонированная R, как это сделано в вашем коде. То же самое касается -R^(-1)*d.

wohlstad 08.12.2022 12:48

@wohlstad Может быть, R - это матрица вращения, обратная сторона которой равна ее транспонированию. Но было бы хорошо, если бы это было уточнено в вопросе.

Thomas 08.12.2022 12:53

@ Томас Я вижу, пропустил это. Я считаю, что эти строки кода должны иметь комментарий, указывающий на это, для ясности.

wohlstad 08.12.2022 12:55

@wohlstad, привет, я только что добавил это в вопрос. И я обнаружил, что если я использую R.inverse() вместо R.transpose(), результат будет намного точнее. Теперь я считаю, что матрица вращения, выраженная в плавающей системе, недостаточно точна. Следовательно, я не могу заменить R.inverse() на R.transpose()

KillerBee 08.12.2022 13:02

@PepijnKramer Привет, спасибо за подсказку. Это имеет смысл. Теоретически R.inverse() равно R.tranpose(). Но это неверно в системе с плавающей запятой

KillerBee 08.12.2022 13:05
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Благодаря комментариям. Поскольку я хотел бы закрыть этот вопрос, я отвечу на него сам.

Теоретически R.inverse() равно R.tranpose(). Но это неверно в системе с плавающей запятой. Как только я использую R.inverse(), результат становится более точным.

Другие вопросы по теме