特征将旋转和平移组合成一个矩阵

Dae*_*pha 9 c++ matrix eigen

我有一个旋转矩阵rot(Eigen :: Matrix3d)和一个平移向量transl(Eigen :: Vector3d),我想在4x4变换矩阵中将它们放在一起.我只是因为我的生活无法弄清楚如何在Eigen中做到这一点.我认为Affine可以以某种方式使用,但我不明白它是如何工作的.

基本上我想要一个如何在Eigen中转换矩阵(4x4)的组合变换相乘和特征矩阵类型

我的代码(由于我不理解Affine如何工作而无法编译)如下所示:

Eigen::Affine3d r(rot);
Eigen::Affine3d t(transl);
Eigen::Matrix4d m = t.matrix();
m *= r.matrix();
Run Code Online (Sandbox Code Playgroud)

Bla*_*nic 9

您没有发布编译错误,也没有发布rottransl.下面是一个工作示例,显示了如何创建4x4转换矩阵.

#include <Eigen/Geometry>

Eigen::Affine3d create_rotation_matrix(double ax, double ay, double az) {
  Eigen::Affine3d rx =
      Eigen::Affine3d(Eigen::AngleAxisd(ax, Eigen::Vector3d(1, 0, 0)));
  Eigen::Affine3d ry =
      Eigen::Affine3d(Eigen::AngleAxisd(ay, Eigen::Vector3d(0, 1, 0)));
  Eigen::Affine3d rz =
      Eigen::Affine3d(Eigen::AngleAxisd(az, Eigen::Vector3d(0, 0, 1)));
  return rz * ry * rx;
}

int main() {
  Eigen::Affine3d r = create_rotation_matrix(1.0, 1.0, 1.0);
  Eigen::Affine3d t(Eigen::Translation3d(Eigen::Vector3d(1,1,2)));

  Eigen::Matrix4d m = (t * r).matrix(); // Option 1

  Eigen::Matrix4d m = t.matrix(); // Option 2
  m *= r.matrix();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,正是我一直在寻找的!我遇到的唯一问题是,如果我将翻译向量直接输入到 `Eigen::Translation3d()` 中,它就不起作用(t.matrix() 无法编译),所以我必须编写更复杂的 ` Eigen::Translation3d(Eigen::Vector3d(transl(0), transl(1), transl(2)))`。我想这是由于本征模板的黑暗巫毒造成的。 (2认同)

Tim*_*phy 5

另一种方法是执行以下操作:

Eigen::Matrix3d R;
// Find your Rotation Matrix
Eigen::Vector3d T;
// Find your translation Vector
Eigen::Matrix4d Trans; // Your Transformation Matrix
Trans.setIdentity();   // Set to Identity to make bottom row of Matrix 0,0,0,1
Trans.block<3,3>(0,0) = R;
Trans.block<3,1>(0,3) = T;
Run Code Online (Sandbox Code Playgroud)

此方法从字面上将Rotation矩阵复制到前3行和第3列,并将转换向量复制到第4列。然后将右下角的矩阵条目设置为1。最终矩阵如下所示:

R R R T
R R R T
R R R T
0 0 0 1
Run Code Online (Sandbox Code Playgroud)

其中R是来自旋转矩阵的对应值,T是来自平移矢量的值。

  • 很好的简单解决方案。我认为甚至可以使用 `Trans.setIdentity();` 而不是 `Trans.setZero(4,4);` 并且能够跳过最后一个 `Trans(3,3) = 1;` 行。 (2认同)
  • 正是我所需要的,但是我使用了Trans.block &lt;3,1&gt;(0,3)= T;而不是Trans.rightCols &lt;1&gt;()= T;`以避免`YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES`错误 (2认同)
  • 你也可以写出更直观的IMO `Trans.linear() = R; Trans.translation() = T;`。另外,如果您使用 Eigen::Transform&lt;..., Eigen::AffineCompact&gt; 作为转换类型,则不需要使用 setIdentity() 进行初始化,因为没有最低行。尽管如此,您可能想要保留它,因为 a) 编译器很智能(即没有运行时成本),b) 在忘记这种“优化”很久之后,您可能想在某个时候更改类型。 (2认同)

Yan*_*Xie 5

另一种方法是使用Eigen::Transform

让我们举一个例子来实现仿射变换,

#include <Eigen/Dense>
#include <Eigen/Geometry>
using namespace Eigen;

Matrix4f create_affine_matrix(float a, float b, float c, Vector3f trans)
{
    Transform<float, 3, Eigen::Affine> t;
    t = Translation<float, 3>(trans);
    t.rotate(AngleAxis<float>(a, Vector3f::UnitX()));
    t.rotate(AngleAxis<float>(b, Vector3f::UnitY()));
    t.rotate(AngleAxis<float>(c, Vector3f::UnitZ()));
    return t.matrix();
}
Run Code Online (Sandbox Code Playgroud)

您还可以按照以下方式实现

Matrix4f create_affine_matrix(float a, float b, float c, Vector3f trans)
{
    Transform<float, 3, Eigen::Affine> t;
    t = AngleAxis<float>(c, Vector3f::UnitZ());
    t.prerotate(AngleAxis<float>(b, Vector3f::UnitY()));
    t.prerotate(AngleAxis<float>(a, Vector3f::UnitX()));
    t.pretranslate(trans);
    return t.matrix();
}
Run Code Online (Sandbox Code Playgroud)

第一个实现和第二个实现的区别就像Fix AngleEuler Angle之间的区别,你可以参考这个视频