【问题标题】:Precedence in Eigen transformations and difference between pretranslate and translate特征变换中的优先级以及预翻译和翻译之间的区别
【发布时间】:2018-07-12 23:35:02
【问题描述】:

我对 Eigen 在组合转换时使用的顺序有点困惑。

translate()pretranslate() 有什么区别?

因为在实践中我这样做时会得到不同的结果:

  Eigen::Affine3d t_res = Eigen::Affine3d::Identity();
  t_res.pretranslate(t1)
      .translate(t2)
      .rotate(t3);

...还有这个:

  Eigen::Affine3d t_res = Eigen::Affine3d::Identity();
  t_res.translate(t1)
      .translate(t2)
      .rotate(t3);

另外,对于最后一个代码 sn-p,Eigen 是否这样做

t_res = (t1 * ( t2 * t3 ))

或者这个

t_res = ((t1 *  t2) * t3 )

?

【问题讨论】:

  • C++ 执行操作数的顺序有时是神秘的或根本没有定义,但在这种情况下它是从左到右的。每个函数的输出是执行下一个函数的对象。由于每个函数的输出都是对*this 的引用,因此该对象正在从左到右的链中修改自己。

标签: c++ matrix linear-algebra eigen


【解决方案1】:

pretranslatetranslate 的区别在于它们是从右侧应用参数还是从左侧应用参数

A.pretranslate(B)

在左起应用B,返回B*A,而

A.translate(B)

从右边应用它,返回A*B

关于顺序,A.translate(B)返回一个对结果矩阵的引用,所以它会迭代调用translate/rotate上一个操作的结果,做

t_res = (((t_res* t1) *  t2) * t3 )

但由于矩阵乘法是关联的,因此运算的顺序仅在涉及浮点表示导致的数值错误时才重要。

然而,矩阵的顺序确实会影响结果(因为乘法不是可交换的),这就是pretranslatetranslate 给出不同结果的原因。


编辑:正如ggael 指出的那样,t_res 是身份,两个版本应该给出相同的结果

【讨论】:

  • 谢谢,我现在明白,在我的 OP 的第一个代码 sn-p 中,幕后发生的事情是 t_res = (((t1 * Identity()) * t2) * t3 ),而不是在 OP 中执行 t_res = (((Identity() * t1) * t2) * t3 ) 的第二个 sn-p .
  • 没错,但是由于您从身份开始,因此对于这种特殊情况,您应该得到相同的结果,这就是我所观察到的。
  • 如果矩阵真的很大,浮点运算的数值错误可能会搞砸,但你是对的,在这种情况下,我希望两者产生相同的结果。
【解决方案2】:

Kai 已经回答了你的问题,但我强烈建议避免使用这些函数并编写显式代码:

Vector3d t1, t2;
Matrix3d mat_rot;
Affine3d t_res = Translation3f(t2) * mat_rot * Translation3f(t1);

【讨论】:

  • 感谢您的建议!在您的示例中,计算t_res 的优先级是什么?
  • 默认情况下它遵循 c++ 规则,所以a*b*c (a*b)*c 如果这是你问的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-07
  • 2015-09-09
  • 1970-01-01
  • 1970-01-01
  • 2019-12-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多