У меня есть матрица преобразования типа 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().
в общем, разные алгоритмы дают разные результаты с разной точностью, это не должно быть сюрпризом. Учтите, что у вас будет решение с точностью до 2 цифр, тогда вы можете использовать результат T * T.inverse()
для улучшения результата, вы можете делать это итеративно, чтобы постепенно повышать точность. Теперь это зависит только от того, в какой момент вы остановите эту итерацию. И в конечном итоге вы ограничены точностью double
Согласно формуле, которую вы опубликовали, верхняя левая часть матрицы должна быть R ^ (-1) (т.е. обратная R), а не транспонированная R, как это сделано в вашем коде. То же самое касается -R^(-1)*d.
@wohlstad Может быть, R
- это матрица вращения, обратная сторона которой равна ее транспонированию. Но было бы хорошо, если бы это было уточнено в вопросе.
@ Томас Я вижу, пропустил это. Я считаю, что эти строки кода должны иметь комментарий, указывающий на это, для ясности.
@wohlstad, привет, я только что добавил это в вопрос. И я обнаружил, что если я использую R.inverse() вместо R.transpose(), результат будет намного точнее. Теперь я считаю, что матрица вращения, выраженная в плавающей системе, недостаточно точна. Следовательно, я не могу заменить R.inverse() на R.transpose()
@PepijnKramer Привет, спасибо за подсказку. Это имеет смысл. Теоретически R.inverse() равно R.tranpose(). Но это неверно в системе с плавающей запятой
Благодаря комментариям. Поскольку я хотел бы закрыть этот вопрос, я отвечу на него сам.
Теоретически R.inverse() равно R.tranpose(). Но это неверно в системе с плавающей запятой. Как только я использую R.inverse(), результат становится более точным.
Это связано с точностью с плавающей запятой, которая не так точна. Этому посвящены полные университетские курсы о том, как свести к минимуму ошибки в результатах. Но все начинается здесь: не работает математика с плавающей запятой