5

我有一堆等距 [R | t] 变换矩阵,即它们是 3D 刚性变换。目前我将它们存储为Eigen Affine transformations,以紧凑的形式表示,例如Eigen::AffineCompact3d它不存储 [0 0 0 1] 的冗余最后一行。

我也知道有一个Eigen::Isometry3d我猜是 typedef 的Transform<double, 3, AffineCompact, Isometry>

我在等距之后,因为逆变换比一般的仿射逆变换便宜得多(转置)。我也知道我可以传递一个提示,当我使用 inverse() 作为affine_mat.inverse(Eigen::Isometry);

但我想在不每次手动传递提示的情况下获得等距逆行为。换句话说,我想知道,复制Eigen::IsometryCompact3dEigen API 中令人惊讶地不存在的行为的最佳方法是什么?

4

2 回答 2

1

为了表示等距,我目前正在使用twists。这种参数化可以用一个 6 元素向量来描述。

要来回转换为标准齐次矩阵公式,您将需要几个基于 log() 和 exp() 的函数(因此转换将是一个缓慢的操作)。

如果您对在两个公式之间来回切换没有性能限制(或者您很少这样做)或者如果您想利用扭曲的属性(例如在数值优化中),则此解决方案是有利的

于 2013-03-28T14:50:18.940 回答
0

我知道这个问题有点老了,你现在可能已经找到了解决方案。但这可能会让其他有这个问题的人感兴趣。

首先,你写道:

我在等距之后,因为逆变换比一般的仿射逆变换便宜得多(转置)>。

只是为了澄清:你不能只是转置得到逆:

/*
    |  R   t|
T = |0 0 0 1|

    |      0|
T' =|  R'  0| not an affine transformation!
    |      0|
    |  t   1|

// inverse of Isometric matrix without actual matrix inversion
T^(-1) = | R'    -R'*t|
         |0 0 0   1   |
*/

可悲的是,您可以定义自己的功能:

void invertAffineCompact3d(Eigen::AffineCompact3d &m){   
  m.linear() = m.linear().transpose();
  m.translation() = -m.linear()*m.translation();
}

并称它为:

Eigen::AffineCompact3d T1 = ...
invertAffineCompact3d(T1);

或者,如果您想要一种适用于所有类型的解决方案:

template<size_t m, size_t n, size_t x, size_t y, typename Derived>
Eigen::Block<Derived, m, n>
  getSubmatrix(MatrixBase<Derived>& data)
{
  return Eigen::Block<Derived, m, n>(data.derived(), x, y);
}

template<typename Derived>
void invertAffine3d(Eigen::MatrixBase<Derived> &m){
  getSubmatrix<3,3,0,0>(m).transposeInPlace();
  getSubmatrix<3,1,0,3>(m) = -getSubmatrix<3,3,0,0>(m)*getSubmatrix<3,1,0,3>(m);
}

并称它为:

Eigen::AffineCompact3d T2 = ...
invertAffine3d(T2.matrix());

Eigen::Affine3f T3 = ...
invertAffine3d(T3.matrix());


Eigen::Isometry3d T4 = ...
invertAffine3d(T4.matrix());

如果你真的很喜欢你可以使用 EIGEN_MATRIXBASE_PLUGIN 扩展MatrixBase

于 2020-12-29T17:10:41.690 回答