根据两个向量计算它们之间的旋转矩阵

一、简介

本文主要介绍通过给定的两个空间向量,计算出从一个向量旋转到另一个向量的旋转矩阵。

二、步骤

① 假设两个向量分别为vectorBefore(x1,y1,z1), vectorAfter(x2,y2,z2),将这两个向量转为单位向量。

得到 va = normalize(vectorBefore), vb = normalize(vectorAfter)

② vs = vb × va, 叉乘得到旋转轴vs

③ v = normalize(vs), vs转为单位向量得到v

④ ca = vb · va, 点乘得到旋转角的余弦值 ca, 即cos(angle)

⑤ vt = v * scale, 对v进行缩放,方便后面计算, scale = 1 – ca

⑥ 旋转矩阵rm为 [3,3]矩阵, 计算原理为 罗德里格旋转公式(Rodrigues’ rotation formula)

rm[0,0] = vt.x * v.x + ca

rm[1,1] = vt.y * v.y + ca

rm[2,2] = vt.z * v.z + ca

vt.x *= v.y

vt.z *= v.x

vt.y *= v.z

rm[0,1] = vt.x – vs.z

rm[0,2] = vt.z – vs.y

rm[1,0] = vt.x – vs.z

rm[1,2] = vt.y – vs.x

rm[2,0] = vt.z – vs.y

rm[2,1] = vt.y – vs.x

根据两个向量计算它们之间的旋转矩阵

三、效果

红色为旋转前的平面,蓝色为旋转后的实际平面, 绿色是对红色平面应用计算的旋转矩阵后得到的平面,所以绿色与蓝色应在同一平面内。

根据两个向量计算它们之间的旋转矩阵

四、代码

public struct Vec3
        {
            public float x;
            public float y;
            public float z;
            public Vec3(float X, float Y, float Z)
            {
                x = X;
                y = Y;
                z = Z;
            }
        }

float[,] getRotationMatrix(Vec3 vectorBefore, Vec3 vectorAfter)
        {
            Vec3 vb = Normalize(vectorBefore);
            Vec3 va = Normalize(vectorAfter);

            Vec3 vs = CrossProduct(vb, va);
            Vec3 v = Normalize(vs);
            float ca = DotProduct(vb, va);

            float scale = 1 - ca;
            Vec3 vt = new Vec3(v.x * scale, v.y * scale, v.z * scale);

            float[,] rotationMatrix = new float[3,3];

            rotationMatrix[0, 0] = vt.x * v.x + ca;
            rotationMatrix[1, 1] = vt.y * v.y + ca;
            rotationMatrix[2, 2] = vt.z * v.z + ca;
            vt.x *= v.y;
            vt.z *= v.x;
            vt.y *= v.z;

            rotationMatrix[0, 1] = vt.x - vs.z;
            rotationMatrix[0, 2] = vt.z + vs.y;
            rotationMatrix[1, 0] = vt.x + vs.z;
            rotationMatrix[1, 2] = vt.y - vs.x;
            rotationMatrix[2, 0] = vt.z - vs.y;
            rotationMatrix[2, 1] = vt.y + vs.x;

            return rotationMatrix;
        }

        Vec3 CrossProduct(Vec3 a, Vec3 b)
        {
            Vec3 c = new Vec3()
            {
                x = a.y * b.z - a.z * b.y,
                y = a.z * b.x - a.x * b.z,
                z = a.x * b.y - a.y * b.x
            };

            return c;
        }

        float DotProduct(Vec3 a, Vec3 b)
        {
            return a.x * b.x + a.y * b.y + a.z * b.z;
        }

        Vec3 Normalize(Vec3 v)
        {
            float frt = (float)Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
            if (frt == 0.0f)
            {
                return new Vec3(0, 0, 0);
            }
            else
            {
                return new Vec3(v.x / frt, v.y / frt, v.z / frt);
            }
        }

五、调用库

以上是通过自己计算得出结果,其实eigen库中有输入两个向量得出旋转矩阵的接口,非常简单。

Eigen::Matrix3d rotMatrix;
    Eigen::Vector3d vectorBef(vectorBefore[0], vectorBefore[1], vectorBefore[2]);
    Eigen::Vector3d vectorAft(vectorAfter[0], vectorAfter[1], vectorAfter[2]);

    rotMatrix = Eigen::Quaterniond::FromTwoVectors(vectorBef, vectorAft).toRotationMatrix();

Original: https://www.cnblogs.com/Clark-Zhang/p/16495263.html
Author: 朔月の流光
Title: 根据两个向量计算它们之间的旋转矩阵

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/582746/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 通过示例学习PYTORCH

    核心是:PyTorch提供了两个主要的特性: 一个n维的Tensor,与Numpy相似但可以在GPU上运行 构建和训练神经网络的自动微分 我们将使用一个三阶多项式拟合 (y=sin…

    Linux 2023年6月14日
    0110
  • bzoj 1191 特别行动队

    一道不错的斜率优化入门题,传送门:bzoj 1911 题目描述稍微有点不太清楚,先解释一下 将n个士兵分成几个连续的组,每一组的战斗力为f(y),其中:f(x)=ax2+bx+c(…

    Linux 2023年6月6日
    0107
  • vert.x-快速入门

    vert.x是Eclipse软件基金会顶级java开源项目之一,它基于netty的、运行在jvm之上的、支持多种编程语言的高性能异步、非阻塞、响应式全栈java web框架。它在t…

    Linux 2023年6月8日
    0111
  • Tomcat启动乱码

    1、找到安装的tomcat的conf目录2、找到logging.properties配置文件3、在文件中找到 java.util.logging.ConsoleHandler.en…

    Linux 2023年6月7日
    0106
  • 记vs2019 The view ‘xxx’ was not found.

    版本:Visual Studio 2019 16.8.2/16.8.4.net core 3.1 1.检测是否是拼写错误2.检查.csproj为文件中是否包含有下面的content…

    Linux 2023年6月7日
    0120
  • 编程入门之日志聚合系统

    (关心具体部署的同学,可以移步我的另外一篇《Centos部署Loki日志聚合系统 》https://www.cnblogs.com/uncleguo/p/15975647.html…

    Linux 2023年6月13日
    083
  • 十、进程管理

    什么是进程?进程(Process)是一个程序在其自身的虚拟地址空间的一次执行活动。之所以要创建进程,就是为了使多个程序可以并发的执行,从而提高系统的资源利用率和吞吐量。简单来说进程…

    Linux 2023年6月7日
    0142
  • 解决微信Windows客户端无法播放视频问题

    问题描述 我的Windows端微信版本是3.6.0,更新后点开视频,没有播放按钮出现,并且过一会就会卡死,并且整个微信程序崩掉。 问题解决 后来发现,是微信客户端的 播放器插件问题…

    Linux 2023年6月14日
    0375
  • QT资料大全

    本文并非原创,摘自: 一去丶二三里 ,感谢大佬的总结 http://blog.csdn.net/liang19890820 推荐另外一个大神的QT总结,受益匪浅啊 https://…

    Linux 2023年6月13日
    074
  • 开放平台架构指南

    1.前言 2010年前,大型社交网站如腾讯QQ、新浪微博都搭建了开放平台。中小型互联网公司接入开放平台,能够获取社交平台的海量用户,有效的降低获客成本,获得社交平台的其他能力。对于…

    Linux 2023年6月6日
    076
  • Python3.9.5安装

    基础环境:yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-de…

    Linux 2023年6月6日
    096
  • 解决“WARNINGThe remote SSH server rejected X11 forwarding request.“警告

    使用xshell连接服务器时,出现了”WARNING! The remote SSH server rejected X11 forwarding request.&#…

    Linux 2023年5月27日
    092
  • Git 不识别文件名字母大小写变化

    问题 今天为一个项目撰写持续构建计划,撰写 Jenkinsfile 之后进行构建时报错: [2022-05-23 16:54:21] unable to prepare conte…

    Linux 2023年6月7日
    096
  • 投票活动进行中!探讨问题:从互联网大量收集学习资料再包装成产品售卖盈利是否属于侵权违法?

    写在开篇 今天不聊某项技能的知识点,我们聊点别的。那么,到底聊啥好呢?笔者想想… 有了,这两天笔者从一个微信公众号中发现一个非常恶劣的营销行为。事情大概背景是这样的:运…

    Linux 2023年6月7日
    079
  • linux 系统迁移到lvm分区

    对于普通分区磁盘空间不够,而采用lvm分区,原来系统进行迁移或者备份还原。 dd命令用于将整个硬盘进行备份,包括uuid,适用于对对整个物理盘的备份 tar 备份可以对整个系统进行…

    Linux 2023年6月14日
    091
  • Java对象序列化和反序列化

    Java类的序列化和反序列化 序列化:指将对象转换为字节序列的过程,也就是将对象的信息转换成文件保存。 反序列化:将字节序列转换成目标对象的过程,也就是读取文件,并转换为对象。 几…

    Linux 2023年6月14日
    0103
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球