Files
matlab-python/Tilt/QuaternioniASE.m

175 lines
4.5 KiB
Matlab
Executable File

function [DNS,DEO,Dz,becc,roll,imba,q,qy]=QuaternioniASE(axb,ayb,azb,mxb,myb,mzb,SP,MEMS,FileName)
% OPERAZIONI PRELIMINARI
% calcola la norma dell'accelerazione e del campo magnetico
Na = (axb^2+ayb^2+azb^2)^0.5;
Nm = (mxb^2+myb^2+mzb^2)^0.5;
% normalizzo l'accelerazione
axbN = axb/Na;
aybN = ayb/Na;
azbN = azb/Na;
% normalizzo il campo magnetico
mxbN = mxb/Nm;
mybN = myb/Nm;
mzbN = mzb/Nm;
if MEMS == 1 % Correggo i segni degli assi
% correggo la direzione degli assi del sistema di coordinate
% aggiornato al 15 febbraio 2016
axsN = axbN;
aysN = aybN;
azsN = -azbN;
% anche per il campo magnetico...
mxsN = -mxbN;
mysN = -mybN;
mzsN = mzbN;
elseif MEMS == 2
% correggo la direzione degli assi del sistema di coordinate
% aggiornato al 09 febbraio 2017
axsN = axbN;
aysN = aybN;
azsN = -azbN;
% anche per il campo magnetico...
mxsN = -mxbN;
mysN = -mybN;
mzsN = mzbN;
elseif MEMS == 3
% correggo la direzione degli assi del sistema di coordinate
% aggiornato al 10 ottobre 2022
axsN = axbN;
aysN = aybN;
azsN = azbN;
% anche per il campo magnetico...
mxsN = mybN;
mysN = mxbN;
mzsN = -mzbN;
end
% trovo i vettori dei campi gravitazionale e magnetico
VaN = [axsN aysN azsN];
VmN = [mxsN mysN mzsN];
% CONTI SECONDO YUN
[qy,~,~] = fqa(VaN',VmN');
qy = qy';
% determino i relativi quaternioni
qaN = [0 VaN];
qmN = [0 VmN];
% calcolo il coseno del beccheggio
% gamma = acos(azsN); gamma non viene mai usato
COSteta = (1-axsN^2)^0.5;
% VERIFICA DELLA SINGOLARITA'
% impongo un epsilon piccolo a piacere
epsilon = 0.1;
if COSteta <= epsilon
% 20 deg espresso in radianti
alpha = 0.3491;
else
alpha = 0;
end
SENalphamezzi = sign(sin(alpha))*((1-cos(alpha))/2)^0.5;
COSalphamezzi = ((1+cos(alpha))/2)^0.5;
%% calcolo il quaternione qalpha e il suo coniugato
qalpha = [COSalphamezzi 0 SENalphamezzi 0];
qalphaC = quatconj(qalpha);
% modifico il vettore accelerazione...
qacc = quatmultiply(qalpha,qaN);
qacc = quatmultiply(qacc,qalphaC);
% ...e quello campo magnetico
qmag = quatmultiply(qalpha,qmN);
qmag = quatmultiply(qmag,qalphaC);
%% CALCOLA IL QUATERNIONE ELEVAZIONE
% NB: il valore di COSteta sarà riscritto
SENteta = qacc(2);
COSteta = (1-SENteta^2)^0.5;
SENtetamezzi = sign(SENteta)*((1-COSteta)/2)^0.5;
COStetamezzi = ((1+COSteta)/2)^0.5;
qe = [COStetamezzi 0 SENtetamezzi 0];
%% CALCOLA IL QUATERNIONE ROLLIO
SENphi = -qacc(3)/COSteta;
COSphi = -qacc(4)/COSteta;
% caso in cui l'asse x sia orientato verticalmente
if COSteta == 0
SENphi = 0;
COSphi = 1;
end
% determinazione degli elementi di qr
if COSphi == -1
SENphimezzi = 1*((1-COSphi)/2)^0.5;
COSphimezzi = 0;
else
SENphimezzi = sign(SENphi)*((1-COSphi)/2)^0.5;
COSphimezzi = ((1+COSphi)/2)^0.5;
if isreal(SENphimezzi)
elseif imag(SENphimezzi)<0.001
SENphimezzi=0;
text = 'SENphi/2 corrected';
fileID = fopen(FileName,'a');
fmt = '%s \r';
fprintf(fileID,fmt,text);
fclose(fileID);
end
end
% scrittura di qr
qr = [COSphimezzi SENphimezzi 0 0];
%% CALCOLA IL QUATERNIONE AZIMUTALE
% Campo magnetico nel sistema di coordinate Earth
qaus = quatmultiply(qe,qr);
qauC = quatconj(qaus);
qEm = quatmultiply(qaus,qmag);
qEm = quatmultiply(qEm,qauC);
% Campo magnetico di riferimento
Nx = 1;
Ny = 0;
% Normalizzazione delle componenti orizzontali del campo magnetico misurato
mxmearot = qEm(2);
mymearot = qEm(3);
Mx = (1/(mxmearot^2+mymearot^2)^0.5)*mxmearot;
My = (1/(mxmearot^2+mymearot^2)^0.5)*mymearot;
% determino coseno e seno dell'angolo di imbardata
COSpsi = Mx*Nx+My*Ny;
SENpsi = -My*Nx+Mx*Ny;
% determinazione degli elementi di qa
SENpsimezzi = sign(SENpsi)*((1-COSpsi)/2)^0.5;
COSpsimezzi = ((1+COSpsi)/2)^0.5;
% scrittura di qa
qa = [COSpsimezzi 0 0 SENpsimezzi];
% QUATERNIONE FINALE
q = quatmultiply(qa,qe);
q = quatmultiply(q,qr);
qINV = [q(:,1) q(:,2).*-1 q(:,3).*-1 q(:,4).*-1];
% RIPERCORRE AL CONTRARIO LA ROTAZIONE IMPOSTA PER EVITARE LA SINGOLARITA'
q = quatmultiply(q,qalpha);
Q0 = q(1);
Q1 = q(2);
Q2 = q(3);
Q3 = q(4);
% CALCOLO GLI ANGOLI DAI QUATERNIONI
roll = atan2(2*(Q0*Q1+Q2*Q3),(1-2*(Q1^2+Q2^2)));
becc = asin(2*(Q0*Q2-Q3*Q1));
imba = atan2(2*(Q0*Q3+Q1*Q2),(1-2*(Q2^2+Q3^2)));
% Calcolo degli spostamenti relativi al nodo
qVett = [0 0 0 SP];
qVettR = quatmultiply(q,qVett);
qVettR = quatmultiply(qVettR,qINV);
DNS = qVettR(2);
DEO = qVettR(3);
Dz = qVettR(4);
end