Eigen计算三维向量的夹角以及空间变换矩阵

19 篇文章 1 订阅
7 篇文章 0 订阅

写在前面

1、本文内容
使用Eigen计算两个向量之间的刚体变换;
当两个向量是点云平面法向量时,也就知道了这两个平面点云之间的刚体变换

2、平台
windows, linux
3、转载请注明出处:
https://blog.csdn.net/qq_41102371/article/details/130582783

原理

假设有两个空间向量a,b,认为b可由a通过空间变换得到,其旋转轴axis,垂直于a,b,旋转角度可同过向量夹角计算方式得到:
cos ⁡ θ = a ⃗ ⋅ b ⃗ ∣ a ⃗ ∣ ∣ b ⃗ ∣ \cos\theta = \frac{\vec{a}\cdot \vec{b}} {| \vec{a}| |\vec{b}|} cosθ=a ∣∣b a b
θ = arccos ⁡ a ⃗ ⋅ b ⃗ ∣ a ⃗ ∣ ∣ b ⃗ ∣ \theta = \arccos{\frac{\vec{a}\cdot \vec{b}} {| \vec{a}| |\vec{b}|}} θ=arccosa ∣∣b a b

代码

1、手动计算

Eigen::Matrix3d ComputeMatrixFromTwoVector(const Eigen::Vector3d a, const Eigen::Vector3d b){
    std::cout << "\nComputeMatrixFromTwoVector\n"
              << std::endl;
    std::cout << "a: " << a.transpose() << std::endl;
    std::cout << "b: " << b.transpose() << std::endl;
    // 叉乘求旋转轴
    auto axis = a.cross(b);
    // 向量夹角
    auto cos_theta = a.dot(b)/(a.norm() * b.norm());
    auto theta = acos(cos_theta);
    std::cout << "axis:\n"
              << axis.transpose() << std::endl;
    std::cout << "theta: " << theta << std::endl;
	// 使用轴角获取旋转矩阵
    Eigen::Matrix3d mat_rot = Eigen::AngleAxisd(theta, axis.normalized()).matrix();
    return mat_rot;
}

2、利用Eigen函数

// v1 v2是输入的两个向量
Eigen::Matrix3d mat = Eigen::Quaterniond().FromTwoVectors(v1, v2).matrix();

经测试,两个结果一致

参考

https://blog.csdn.net/newbeixue/article/details/124731785
http://eigen.tuxfamily.org/dox/classEigen_1_1Quaternion.html#acdb1eb44eb733b24749bc7892badde64
https://my.oschina.net/u/4290001/blog/3457663

主要做激光/影像三维重建,配准、分割等常用点云算法,技术交流、咨询可私信

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
以下是一个示例程序,该程序演示了如何使用Eigen库进行三维仿射变换: ```cpp #include <iostream> #include <Eigen/Dense> using namespace Eigen; int main() { // 创建一个3x3的旋转矩阵 Matrix3f rotation; float angle = M_PI / 4; //旋转角度为45度 rotation << cos(angle), -sin(angle), 0, sin(angle), cos(angle), 0, 0, 0, 1; // 创建一个3x1的平移向量 Vector3f translation(1, 2, 3); // 创建一个4x4的仿射变换矩阵 Matrix4f transform; transform.setIdentity(); // 初始化为单位矩阵 transform.block(0, 0, 3, 3) = rotation; // 将旋转矩阵赋值给变换矩阵的前三行前三列 transform.block(0, 3, 3, 1) = translation; // 将平移向量赋值给变换矩阵的前三行最后一列 // 创建一个3x1的向量作为待变换向量 Vector3f v(1, 0, 0); // 进行仿射变换 Vector4f v_transformed = transform * v.homogeneous(); // 先将向量转换为齐次坐标形式(添加一维为1的分量),再进行矩阵乘法 // 输出变换后的向量 std::cout << "变换向量:" << v.transpose() << std::endl; std::cout << "变换向量:" << v_transformed.head<3>().transpose() << std::endl; // 齐次坐标形式下,变换向量的前三个分量为变换后的向量 return 0; } ``` 在上面的示例代码中,我们使用Eigen库创建了一个3x3的旋转矩阵和一个3x1的平移向量,并将它们合并为一个4x4的仿射变换矩阵。然后,我们创建了一个3x1的向量,并使用变换矩阵对其进行仿射变换。最后,我们输出了变换前后的向量。 需要注意的是,在进行仿射变换时,需要将向量转换为齐次坐标形式(添加一维为1的分量),再进行矩阵乘法。变换后的向量也需要再次转换为非齐次坐标形式(去掉最后一维分量)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诺有缸的高飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值