空间变换与计算_03_四元数

四元数介绍:

单位四元数(Unit quaternion)可以用于表示三维空间里的旋转]。它与常用的另外两种表示方式(三维正交矩阵和欧拉角)是等价的,但是避免了欧拉角表示法中的万向锁问题。比起三维正交矩阵表示,四元数表示能够更方便地给出旋转的转轴与旋转角。

Quaternion:

四元数可以表示成:(w, x, y, z),其中w位实数,x, y, z为复数,在三维空间中,四元数可以表示空间旋转,这时:w和x,y,z的平方和一定为1,且,w = cos(a/2),vec = sin(a/2)(x*i + y*j + z*k)。

可以理解为,其代表的旋转为,在世界坐标系的的基础上,绕(x, y, z)旋转的角度为a = 2*acos(w)。

四元数的构造和析构函数如下:

    public:
        /// constructor, m_w:1.0, m_vec:[0.0, 0.0, 0.0] default.
        quaternion();
        /// construct from another quaternion.
        quaternion(const quaternion& q);
        /// move constructor.
        quaternion(quaternion&& q) noexcept;
        /// construct from w and vector.
        quaternion(const real w, const vector& vec);
        /// construct from w and x,y,z.
        quaternion(const real w, const real x, const real y, const real z);
        /// construct from matrix3x3.
        quaternion(const matrix3x3& mat);
        /// destructor.
        virtual ~quaternion();

默认情况下,四元数的四个值为(1, 0, 0, 0),当然,为(0, 0, 0, 1)也是可以的,前者可以代表不旋转,后者可以代表绕Z轴旋零度。对于移动构造,实际上是没什么用的,这个类没有成员指针,写上仅仅为了统一风格。

在构造函数中,整个库没有使用欧拉角,因此也没提供欧拉角的转换。其他几个构造函数如注释所说,功能很明确。

与3x3矩阵的接口类似,由于3x3矩阵的接口中,有一大部分是基于数学矩阵的算法,因此四元数的空间计算实际上更少,四元数的接口如下:

    public:
        /// return true if not equal.
        bool operator!=(const quaternion& q) const;
        /// return true if equal, all values equal.
        bool operator==(const quaternion& q) const;
        /// operator=, from another quaternion.
        quaternion& operator=(const quaternion& q);
        /// move operator=.
        quaternion& operator=(quaternion&& q) noexcept;
        /// operator=, from matrix3x3.
        quaternion& operator=(const matrix3x3& mat);
        /// operator*=, return *this, *this * q.
        quaternion& operator*=(const quaternion& q);
        /// operator*, return *this * q, non change in *this.
        [[nodiscard]] quaternion operator*(const quaternion& q) const;
    public:
        /// print on console.
        void print() const;
        /// is real, is available.
        bool isReal();
        /// rotate around axis.
        void rotateAxis(const real radians, const vector& vec);
        /// rotate around axis
        void rotateAxis(const real radians, Axis axis);
        /// rotate around self axis
        void rotateSelfAxis(const real radians);

下面在测试程序中,将介绍部分接口功能。

 

测试:

一、构造函数与析构函数:

    qytk::quaternion q0;
    q0.print();
    q0.set(std::cos(PI / 4), qytk::vector(0.0, 0.0, 1.0) * std::sin(PI / 4));
    q0.print();

    qytk::quaternion q1(q0);
    q1.print();

其打印结果如下:

在q0的设置中,可以看出,我们需要的是绕Z轴旋转PI/2,也就是90度。q1是调用拷贝构造的结果,两者完全一样。

    qytk::matrix3x3 mat0;
    mat0.rotateAxis(PI / 2, qytk::Axis::Z);
    qytk::quaternion q4(mat0);
    q4.print();

如上面测试程序,是使用3x3的矩阵旋转生成的,使用构造函数构造后,打印结果如下:

可以看出,计算结果与上面四元数计算的结果完全一样。

二、旋转函数:

    q7.rotateSelfAxis(PI * 3 / 2);
    q7.print();

    mat0 = q7;
    mat0.print();

    q7.rotateSelfAxis(PI * 2);
    q7.print();

    qytk::quaternion q8;
    q8.set(std::cos(PI / 4), qytk::vector(0.0, 0.0, 1.0) * std::sin(PI / 4));
    std::cout << q8.getW() << std::endl;
    q8.getVec().print();

其打印结果如下:

q7绕自己的轴旋转1.5PI的角度,相当于反向旋转的0.5PI,由于默认是(1, 0, 0, 0),所以旋转默认绕着Z轴的,可以从转化后的矩阵看出,其旋转,就是绕Z轴旋转-90度得到的结果。

后面的q8,测试了四元数内部数据读取。

总结:

四元数与3x3的矩阵类似,都可以表示三维空间的旋转,但是同样的,不能表示空间移动等,无法用来完全描述我们锁熟知的三维空间,但四元数也能避免万向节锁死的问题,甚至,在空间旋转中,其计算量也远比3x3的矩阵小,所表示的内容也足够直观。因此,在很多设备中(GPS定位,结构光定位等)都在使用四元数。

qySpace下载地址(github):qySpace

qySpace下载地址(csdn):qySpace

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值