当前位置: 首页 > news >正文

通过不同坐标系下的同一向量,求解旋转矩阵

问题
已知坐标系A经过两次旋转(先绕x轴旋转,再绕y轴旋转)得到坐标系B,且已知在坐标系A中的一个向量 a,在坐标系B中对应的向量为 b,那么如何求出从A到B的旋转矩阵?
这个问题在slam中还是算常见的,用于imu通过重力方向估计姿态,并且假设yaw角为0。


一、问题分析

  • 坐标系A → 坐标系B的变换是通过两次旋转实现的:

    1. x轴旋转角度为 α
    2. y轴旋转角度为 β
  • 坐标系的变换可以表示为一个旋转矩阵 R=Ry(β)⋅Rx(α)R = R_y(\beta) \cdot R_x(\alpha)R=Ry(β)Rx(α)

  • 已知向量 a(在A中)和对应的 b(在B中),即:
    a=R⋅b \mathbf{a} = R \cdot \mathbf{b} a=Rb

    B=R⋅A \mathbf{B} = R \cdot \mathbf{A} B=RA

  • 我们的目标是:从a和b出发,解析地求出旋转矩阵 R


二、旋转矩阵定义

标准旋转矩阵如下:

  • 绕x轴旋转α:
    Rx(α)=[1000cos⁡α−sin⁡α0sin⁡αcos⁡α] R_x(\alpha) = \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos\alpha & -\sin\alpha \\ 0 & \sin\alpha & \cos\alpha \end{bmatrix} Rx(α)=1000cosαsinα0sinαcosα

  • 绕y轴旋转β:
    Ry(β)=[cos⁡β0sin⁡β010−sin⁡β0cos⁡β] R_y(\beta) = \begin{bmatrix} \cos\beta & 0 & \sin\beta \\ 0 & 1 & 0 \\ -\sin\beta & 0 & \cos\beta \end{bmatrix} Ry(β)=cosβ0sinβ010sinβ0cosβ

所以总旋转矩阵为:
R=Ry(β)Rx(α) R = R_y(\beta) R_x(\alpha) R=Ry(β)Rx(α)


三、已知向量求旋转矩阵

给定:

  • 向量 a=[ax,ay,az]T\mathbf{a} = [a_x, a_y, a_z]^Ta=[ax,ay,az]T
  • 向量 b=[bx,by,bz]T\mathbf{b} = [b_x, b_y, b_z]^Tb=[bx,by,bz]T
  • 且满足 a=Rb\mathbf{a} = R \mathbf{b}a=Rb

我们要求解的是:
R=Ry(β)Rx(α) R = R_y(\beta) R_x(\alpha) R=Ry(β)Rx(α)

这个是一个旋转估计问题,但只给一个向量对 (a,b)(\mathbf{a}, \mathbf{b})(a,b) 是不足以唯一确定一个三维旋转的(需要至少两个不共线的向量对)。不过我们有先验知识:旋转是先绕x轴,再绕y轴完成的。

我们可以利用这个结构来求解。


四、解析解推导

1. 令:

R=Ry(β)Rx(α) R = R_y(\beta) R_x(\alpha) R=Ry(β)Rx(α)

展开后得到:
R=[cos⁡βsin⁡βsin⁡αsin⁡βcos⁡α0cos⁡α−sin⁡α−sin⁡βcos⁡βsin⁡αcos⁡βcos⁡α] R = \begin{bmatrix} \cos\beta & \sin\beta \sin\alpha & \sin\beta \cos\alpha \\ 0 & \cos\alpha & -\sin\alpha \\ -\sin\beta & \cos\beta \sin\alpha & \cos\beta \cos\alpha \end{bmatrix} R=cosβ0sinβsinβsinαcosαcosβsinαsinβcosαsinαcosβcosα

2. 由 a=Rb\mathbf{a} = R \mathbf{b}a=Rb,即:

[axayaz]=[cos⁡βsin⁡βsin⁡αsin⁡βcos⁡α0cos⁡α−sin⁡α−sin⁡βcos⁡βsin⁡αcos⁡βcos⁡α]⋅[bxbybz] \begin{bmatrix} a_x \\a_y \\ a_z \end{bmatrix} =\begin{bmatrix} \cos\beta & \sin\beta \sin\alpha & \sin\beta \cos\alpha \\ 0 & \cos\alpha & -\sin\alpha \\ -\sin\beta & \cos\beta \sin\alpha & \cos\beta \cos\alpha \end{bmatrix} \cdot \begin{bmatrix} b_x \\ b_y \\ b_z \end{bmatrix} axayaz=cosβ0sinβsinβsinαcosαcosβsinαsinβcosαsinαcosβcosαbxbybz

写成三个方程:

{ax=bxcos⁡β+bysin⁡βsin⁡α+bzsin⁡βcos⁡αay=bycos⁡α−bzsin⁡αaz=−bxsin⁡β+bycos⁡βsin⁡α+bzcos⁡βcos⁡α \begin{cases} a_x = b_x \cos\beta + b_y \sin\beta \sin\alpha + b_z \sin\beta \cos\alpha \\ a_y = b_y \cos\alpha - b_z \sin\alpha \\ a_z = -b_x \sin\beta + b_y \cos\beta \sin\alpha + b_z \cos\beta \cos\alpha \end{cases} ax=bxcosβ+bysinβsinα+bzsinβcosαay=bycosαbzsinαaz=bxsinβ+bycosβsinα+bzcosβcosα


五、求解思路

我们要求的是 α\alphaαβ\betaβ,可以利用第2个方程直接解出 α\alphaα,再代入其他方程求 β\betaβ

步骤1:从 ay=bycos⁡α−bzsin⁡αa_y = b_y \cos\alpha - b_z \sin\alphaay=bycosαbzsinα 解出 α\alphaα

这是一个标准的正弦余弦线性组合:

ay=bycos⁡α−bzsin⁡α a_y = b_y \cos\alpha - b_z \sin\alpha ay=bycosαbzsinα

这可以写成:
ay=by2+bz2⋅cos⁡(α+θ) a_y = \sqrt{b_y^2 + b_z^2} \cdot \cos(\alpha + \theta) ay=by2+bz2cos(α+θ)
其中 tan⁡θ=bzby\tan\theta = \frac{b_z}{b_y}tanθ=bybz

ay=0a_y=0ay=0时(这与重力方向一致的),更简单的方式是使用反正切函数:

令:
tan⁡α=bybz⇒α=arctan⁡2(by,bz) \tan\alpha = \frac{b_y}{b_z} \Rightarrow \alpha = \arctan2(b_y, b_z) tanα=bzbyα=arctan2(by,bz)

注意:这个只在 ay=0a_y = 0ay=0 时成立(因为左边是 aya_yay,不是0)。如果 ay≠0a_y \neq 0ay=0,那就不能直接解出 α\alphaα。因此,这个方法只适用于 ay=0a_y = 0ay=0 的情况


步骤2:代入 α\alphaα 到第一个和第三个方程,解出 β\betaβ

α\alphaα 代入到:
ax=bxcos⁡β+bysin⁡βsin⁡α+bzsin⁡βcos⁡α a_x = b_x \cos\beta + b_y \sin\beta \sin\alpha + b_z \sin\beta \cos\alpha ax=bxcosβ+bysinβsinα+bzsinβcosα

整理得:
ax=bxcos⁡β+sin⁡β(bysin⁡α+bzcos⁡α) a_x = b_x \cos\beta + \sin\beta (b_y \sin\alpha + b_z \cos\alpha) ax=bxcosβ+sinβ(bysinα+bzcosα)

令:
C=bysin⁡α+bzcos⁡α C = b_y \sin\alpha + b_z \cos\alpha C=bysinα+bzcosα

则:
ax=bxcos⁡β+Csin⁡β a_x = b_x \cos\beta + C \sin\beta ax=bxcosβ+Csinβ

这是标准的:

ax=Acos⁡β+Bsin⁡β=A2+B2cos⁡(β−θ),其中 θ=arctan⁡2(B,A) a_x = A \cos\beta + B \sin\beta = \sqrt{A^2 + B^2} \cos(\beta - \theta), \quad \text{其中 } \theta = \arctan2(B, A) ax=Acosβ+Bsinβ=A2+B2cos(βθ),其中 θ=arctan2(B,A)

ax=0a_x=0ax=0时(这与重力方向一致的),更简单的方式是使用反正切函数:

令:
tan⁡β=−bxC⇒β=arctan⁡2(bx,−C) \tan\beta = \frac{-b_x}{C} \Rightarrow \beta = \arctan2(b_x, -C) tanβ=Cbxβ=arctan2(bx,C)
(注求角度时候需要分辨清楚负号的位置)


六、最终旋转矩阵表达式

一旦求出 α\alphaαβ\betaβ,就可以代入下面的旋转矩阵:

R=Ry(β)Rx(α)=[cos⁡βsin⁡βsin⁡αsin⁡βcos⁡α0cos⁡α−sin⁡α−sin⁡βcos⁡βsin⁡αcos⁡βcos⁡α] R = R_y(\beta) R_x(\alpha) =\begin{bmatrix} \cos\beta & \sin\beta \sin\alpha & \sin\beta \cos\alpha \\ 0 & \cos\alpha & -\sin\alpha \\ -\sin\beta & \cos\beta \sin\alpha & \cos\beta \cos\alpha \end{bmatrix} R=Ry(β)Rx(α)=cosβ0sinβsinβsinαcosαcosβsinαsinβcosαsinαcosβcosα


七、总结

已知:

  • 向量 a=(ax,ay,az)\mathbf{a} = (a_x, a_y, a_z)a=(ax,ay,az)
  • 对应的 b=(bx,by,bz)\mathbf{b} = (b_x, b_y, b_z)b=(bx,by,bz)
  • 坐标系变换顺序:先绕x轴旋转α,再绕y轴旋转β

解法步骤:

  1. 计算:
    α=arctan⁡2(−bz,by) \alpha = \arctan2(-b_z, b_y) α=arctan2(bz,by)
  2. 计算中间量:
    C=bysin⁡α+bzcos⁡α C = b_y \sin\alpha + b_z \cos\alpha C=bysinα+bzcosα
  3. 解出:
    β=arctan⁡2(bx,−C) \beta = \arctan2(b_x, -C) β=arctan2(bx,C)
  4. 构造旋转矩阵:
    R=Ry(β)Rx(α) R = R_y(\beta) R_x(\alpha) R=Ry(β)Rx(α)

八、注意事项

  • 这个方法在 by2+bz2≠0b_y^2 + b_z^2 \neq 0by2+bz2=0 时有效
  • 如果 by=bz=0b_y = b_z = 0by=bz=0,则 α\alphaα 无法唯一确定
  • 如果 ay≠0a_y \neq 0ay=0ax≠0a_x \neq 0ax=0,则上面的 α\alphaα 求解方式不适用,需要使用更通用的最小二乘旋转估计方法(如SVD)

九、提供对应代码

适用于imu通过重力方向估计姿态,并且假设yaw角为0。因此 a=[0,0,−9.8]a=[0 , 0, -9.8]a=[0,0,9.8]bbb是imu测的重力方向

    Eigen::Matrix3d ImuReader::computeRotationMatrix(const Eigen::Vector3d &a, const Eigen::Vector3d &b, double &alpha, double &beta){// Step 1: 计算 alphaif (b.y() == 0 && b.z() == 0){std::cerr << "Error: a_y and a_z cannot both be zero!" << std::endl;exit(EXIT_FAILURE);}alpha = std::atan2(b.y(), b.z()); // 大概是abs(90)// Step 2: 计算中间量 Cdouble ca = std::cos(alpha);double sa = std::sin(alpha);double C = b.y() * sa + b.z() * ca;// Step 3: 计算 betabeta = std::atan2(b.x(), -C);if (std::abs(beta) < 1){beta = std::atan2(-b.x(), C);}// Step 4: 构造旋转矩阵 R = Ry(beta) * Rx(alpha)Eigen::Matrix3d Rx = Eigen::Matrix3d::Identity();Rx.block<2, 2>(1, 1) << std::cos(alpha), -std::sin(alpha), std::sin(alpha), std::cos(alpha);Eigen::Matrix3d Ry = Eigen::Matrix3d::Identity();Ry.block<2, 2>(0, 0) << std::cos(beta), std::sin(beta), -std::sin(beta), std::cos(beta);Ry(0, 2) = std::sin(beta);Ry(2, 0) = -std::sin(beta);Ry(0, 0) = std::cos(beta);Ry(2, 2) = std::cos(beta);return Ry * Rx;}
http://www.lryc.cn/news/600319.html

相关文章:

  • 企业级 AI 工具选型报告:9 个技术平台的 ROI 对比与部署策略
  • 【教程】无需迁移IDE!Augment原生插件实现Cursor无缝平替 Claude-4无限用
  • C++学习之深入学习模板(进阶)
  • 详解力扣高频SQL50题之1084. 销售分析 III【简单】
  • C#编程基础:运算符与结构详解
  • iOS 26,双版本更新来了
  • TCP/IP 网络编程面试题及解答
  • Flutter开发 BUG 记录 (持续更新)
  • VTK交互——ClientData
  • 【CTF-Web】dirsearch寻找download.php进行?path=flag.txt任意文件下载
  • C#与C++交互开发系列(二十四):WinForms 应用中嵌入C++ 原生窗体
  • Caffeine 缓存库的常用功能使用介绍
  • 【GaussDB】构建一个GaussDB的Docker镜像
  • 【CTF-WEB-SQL】SQL注入基本流程-错误注入(sql-labs的Less5)(updatexml)
  • 【GaussDB】如何从GaussDB发布包中提取出内核二进制文件
  • 【每天一个知识点】GAN(生成对抗网络,Generative Adversarial Network)
  • C++核心编程学习--对象特性--友元
  • ICMPv4报文类型详解表
  • GRE及MGRE应用综合实验
  • Spring AI 项目实战(二十):基于Spring Boot + AI + DeepSeek的智能环境监测与分析平台(附完整源码)
  • SpringMVC——请求
  • 常见代码八股
  • 0基础法考随手笔记 03(刑诉05 刑事证据与证明+06 强制措施)
  • Kafka MQ 消费者应用场景
  • 【web应用】基于Vue3和Spring Boot的课程管理前后端数据交互过程
  • DAY31 整数矩阵及其运算
  • 【C++】位运算符
  • 解锁反向海淘独立站:国内电商平台 API 接口全解析
  • LeetCode 1074:元素和为目标值的子矩阵数量
  • OGG同步Oracle到Kafka不停库,全量加增量