classdef quaternion < handle
% 四元數 qa qx qy qz
properties
data = zeros(4, 1);%列向量
end
methods %普通函數塊--開始
function obj = quaternion(varargin)
% 構造函數,支持“4x1向量” 、“1x4向量”、“4個單變量axyz”進行構造
% q=[qa qx qy qz]
if 1 == nargin
arg = varargin{1};
obj.data(1) = arg(1);
obj.data(2) = arg(2);
obj.data(3) = arg(3);
obj.data(4) = arg(4);
elseif 4 == nargin
obj.data(1) = varargin{1};
obj.data(2) = varargin{2};
obj.data(3) = varargin{3};
obj.data(4) = varargin{4};
else
%error('quaternion類 僅支持“4x1向量” 、“1x4向量”、“4個單變量axyz”進行構造');%注意,轉C語言時,不要出現打印語句
end
end
function [] = setValue(obj, in4x1)
%賦值
obj.data = in4x1;
end
function [] = set.data(obj, in4x1)
%賦值,當寫出q.data = xxxx;語句時,該函數會被自動調用,一般可用於右值合法檢測
obj.data = in4x1;
%disp('quaternion set.data is called');
end
function [] = normalize(obj)
%把本四元數歸一化
obj.data = obj.data / norm(obj.data);
end
function res = mtimes(q1, q2)
% 乘法*運算符重載
p = [ q1.data(1) -q1.data(2) -q1.data(3) -q1.data(4);
q1.data(2) q1.data(1) -q1.data(4) q1.data(3);
q1.data(3) q1.data(4) q1.data(1) -q1.data(2);
q1.data(4) -q1.data(3) q1.data(2) q1.data(1)] ...
* [ q2.data(1) q2.data(2) q2.data(3) q2.data(4)]';
res = quaternion(p(1), p(2), p(3), p(4));
end
function [ret] = rotateVec(obj, vec)
%四元數對三維向量進行旋轉,注意,請保證輸入的q爲單位四元數
%形參:默認本類的對象q,要被旋轉的三維向量vec(行列均可)
%返回三維列向量
qv = quaternion(0, vec(1), vec(2), vec(3)); %[0 vec(1) vec(2) vec(3)]';
qi = conjugate(obj);
qvqi = obj * qv * qi;
ret = [qvqi.data(2) qvqi.data(3) qvqi.data(4)]';
end
end %普通函數塊--結束
methods(Static) %靜態函數塊---開始
%這裏寫靜態函數
end %靜態函數塊---結束
end %類定義結束
以上給出了簡單的幾個示例,挨個說明:
1、類聲明與繼承
聲明形如 classdef quaternion < handle,其中<代表繼承handle類,
若繼承多個類,可寫成形如:classdef quaternion < base1 & base2 &base3
這裏繼承的handle需要強調一下,matlab有兩個超類,handle和value,關於這兩者的區別,請自行搜索學習,一般我們自己寫的類都要繼承者=這兩者之一。
2、構造函數
構造函數與類名同名,必須有一個返回值,返回值的名稱必須是obj,由於matlab不支持函數重載,因此只能有一個構造函數,不過我們可以通過可變參數表變相近似實現以下構造函數的重載,varargin這是matlab內置的形參,代表輸入的參數數目是可變的,在函數內部可通過nargin來判斷實參的數目(number of argument input),來區別不同的實參。這一技巧也可用在普通的函數中。
3、成員變量
如例子所示,被 properties xxxxx end標籤包裹的部分爲成員變量。
在成員函數中訪問成員變量,必須要加obj.前綴(需要注意的是,這個前綴並不固定是obj,這取決於成員函數第一參的命名),示例代碼中的很多成員函數已經展示瞭如何讀寫成員變量。
4、無參成員函數
無參函數指的是在調用時無參,一般聲明和定義函數時,matlab默認把第一參數當做this指針,所以,幾乎的成員函數都至少帶有一個形參。第一參數的名字可隨意取,一般慣例是取做obj,但不是絕對的,例如例子中重載的乘法運算符,我把第一參取名爲q1,也是可以的。
上例中,normalize函數有一個形參obj,但在調用時是無參的:
q= quaternion([1 2 3 4]');
q.normalize();
disp(q.data');%結果爲: 0.1826 0.3651 0.5477 0.7303
5、有參成員函數
真正的參數是從第二個參數開始的,例如例子中的rotateVec函數,聲明時他有兩個參數,但在調用時,只有一個參數,因爲真正的第一參被隱式用作this指針了。
q= quaternion([0.1826 0.3651 0.5477 0.7303]');
q.rotateVec([1 2 3]);