低成本MEMS惯导系统的捷联惯导解算MATLAB仿真

article/2025/9/29 3:03:44

低成本MEMS惯导系统的捷联惯导解算MATLAB仿真

  • 一、姿态角转换为四元数
  • 二、四元数转换为姿态角
  • 三、反对称阵
  • 四、位置更新
  • 五、姿态更新
  • 六、程序及数据
    • 主程序:
    • 子程序:
    • 数据及完整程序

之前将高成本的捷联惯导忽略地球自转、圆锥曲线运动以及划桨运动等化简为可适用低成本的捷联惯导MATLAB程序,但是其中的子程序都是用的严老师的代码,想自己锻炼一下自己的代码能力,所以对低成本的捷联惯导进行重新编写!!

一、姿态角转换为四元数

  对于单位四元数的三角函数表示,有:

Q = q 0 + q v = cos ⁡ ϕ 2 + u sin ⁡ ϕ 2 {\bf{Q}} = {q_0} + {{\bf{q}}_v} = \cos \frac{\phi }{2} + {\bf{u}}\sin \frac{\phi }{2} Q=q0+qv=cos2ϕ+usin2ϕ
(1)航向角 ψ \psi ψ,运载体纵轴在当地水平面上的投影线与当地地理北向的夹角,常取北偏东为正,即若从空中俯视运载体,地理北向顺时针旋转至纵轴水平投影线的角度,角度范围为0~360° ;
(2)俯仰角 θ \theta θ,运载体纵轴与其水平投影线之间的夹角,当运载体抬头时角度定义为正,角度范围-90°~90°;
(3)横滚角 γ \gamma γ,运载体立轴与纵轴所在铅垂面之间的夹角,当运载体向右倾斜时角度定义为正,角度范围-180°~180°。
  虽然航向角 ψ \psi ψ习惯上常定义为北偏东为正,但是当定义导航坐标系为“东-北-天”地理坐标系时,航向角在绕天向轴转动时不符合右手规则。为了符合右手规则和推导公式简洁对称,除非特别说明,本节将航向角定义为北偏西为正,且取值范围为 ( − π , π ] (-\pi,\pi] (ππ],这是在后续阅读相关公式时需要特别注意的。当然,如果要将相关公式应用于北偏东的航向角,只需再增加一个简单的航向角转换过程即可。
“东-北-天312”欧拉角定义下,由欧拉角求解四元数的公式为:
在这里插入图片描述
程序验证:

%***************************************
% 将欧拉角转为四元数:att2que(att)
% input:att=[pitch;roll;yaw];           unit:rad
% output:qnb=[q0;q1;q2;q3];             q0为实部
%***************************************
theta = 0; gamma = 0; psi = 90*pi/180;
att = [theta;gamma;psi];
s1 = sin(theta/2); s2 = sin(gamma/2); s3 = sin(psi/2);
c1 = cos(theta/2); c2 = cos(gamma/2); c3 = cos(psi/2);
qnb= [c3*c1*c2 - s3*s1*s2;c3*s1*c2 - s3*c1*s2;s3*s1*c2 - c3*c1*s2;s3*c1*c2 - c3*s1*s2;]

结果:

>> exe0.7071000.7071

改写为子程序备用:

function att2que qnb = (att);
att = [theta;gamma;psi];
s1 = sin(theta/2); s2 = sin(gamma/2); s3 = sin(psi/2);
c1 = cos(theta/2); c2 = cos(gamma/2); c3 = cos(psi/2);
qnb= [c3*c1*c2 - s3*s1*s2;c3*s1*c2 - s3*c1*s2;s3*s1*c2 - c3*c1*s2;s3*c1*c2 - c3*s1*s2;];

二、四元数转换为姿态角

  由四元数直接求解欧拉角并不容易。实际上,可通过姿态阵作为中间过渡量,先由四元数计算姿态阵,再由姿态阵计算欧拉角,综合一起后其结果为:
在这里插入图片描述

function att = que2att(qnb)
%***************************************
% 四元数转换为姿态角:que2att(qnb)
% input:qnb=[q0;q1;q2;q3];             q0为实部       
% output:att=[pitch;roll;yaw];           unit:rad     
%***************************************
att(1) = asin(2*(qnb(3)*qnb(4) + qnb(1)*qnb(2)));
if abs(2*(qnb(3)*qnb(4) + qnb(1)*qnb(2)) <= 0.999999att(2) = -atan2*(2*(qnb(2)*qnb(4) - qnb(1)*qnb(3))),qnb(1)^2 - qnb(2)^2 - qnb(3)^2 + qnb(4)^2);att(3) = -atan2*(2*(qnb(2)*qnb(3) - qnb(1)*qnb(4))),qnb(1)^2 - qnb(2)^2 + qnb(3)^2 - qnb(4)^2);
elseatt(2) = -atan2*(2*(qnb(2)*qnb(4) + qnb(1)*qnb(3))),qnb(1)^2 + qnb(2)^2 - qnb(3)^2 - qnb(4)^2);att(3) = 0;
end	

三、反对称阵

引入三维向量的反对称阵概念后,两向量之间叉乘运算可等价表示为前一向量的反对称阵与后一向量之间的矩阵乘法运算,亦即:
在这里插入图片描述

funcion ssm = skew(v)
%***************************************
% 求三维向量的反对称阵(skew symmetric matrix):skew(v)
% input:v = [v_x;v_y;v_z];          
% output:ssm = [ssm_x;ssm_y;ssm_z];             
%***************************************
ssm = [0,-v(3),v(2);v(3),0,-v(1);-v(2),v(1),0];

四、位置更新

在这里插入图片描述
在这里插入图片描述

f = 1/298.257223563;
R_e = 6.378136998405e6;
e = sqrt(2f-f^2);
R_N = R_e/(1-e^2*(sin(pos(1)))^2)^0.5;
R_M = R_N*(1-e^2)/(1-e^2*(sin(pos(1)))^2);
R_Mh = R_M + pos(3);
R_Nh = R_N + pos(3);
M_pv = [0,1/R_Mh,0;sec(pos(1))/R_Nh,0,0;0,0,1];vn1 = (vn2+vn1)/2;
pos = pos + M_pv*vn1*nts;	    

五、姿态更新

在这里插入图片描述

wie = 7.2921151467e-5;  
wnie = [0,wie*cos(pos(1)),wie*sin(pos(1))]';
wnen = vn.*[-1/(R_M + pos(3));1/(R_N + pos(3));tan(pos(1))/(R_N + pos(3))];
wnin = wnie + wnen;
% 姿态更新
q_bb = [cos(norm(delta_theta_m)/2);(delta_theta_m/norm(delta_theta_m))'*sin((norm(delta_theta_m)/2))];
qnb = qmul(rv2q(-wnin*nts), qmul(qnb, q_bb));  
qnb = qnormlz(qnb);

六、程序及数据

主程序:

clc;
clear;
imu = load ('imu.mat');                                %imu数据: avp=[wm, vm, tt(2:end)]; gx(rad)  gy  gz ax (m/s)  ay  az time  
trj = load ('trj.mat');                                %trj=[att, vn, pos]; att() vn(米每秒) pos()
deg2rad = pi/180;
att = [0;0;90]*deg2rad; vn = [0;0;0]; pos = [[34;108]*deg2rad;100];
qnb = att2que(att);
n = 1;t = 0;ts = 0.01;len = length(imu.avp);avps = zeros(len,10);
for k = 1:n:lent = t + ts;wm = imu.avp(k,1:3);vm = imu.avp(k,4:6);[qnb,vn,pos] = my_insupdate(qnb,vn,pos,wm,vm,ts);cnb = que2att(qnb);cnb(3) = mod(cnb(3),2*pi);avps(k,:) = [cnb';vn;pos;t]';
end%姿态
tt=length(avps);
tf=length(trj.trj);
figure(1);
subplot(321);
plot(1:tt,(avps(1:tt,1:2)/deg2rad),1:tf,(trj.trj(1:tf,1:2)/deg2rad),'--'); title('俯仰角和横滚角');xlabel('d');ylabel('\theta,\gamma(\circ)');
legend('\it\theta','\it\gamma','\bf\theta','\bf\gamma');grid on;
subplot(322);
plot(1:tt,(avps(1:tt,3)/deg2rad),1:tf,(trj.trj(1:tf,3)/deg2rad),'--'); title('偏航角');xlabel('d');ylabel('\Phi(\circ)');
legend('\it\Phi','\bf\Phi') ;grid on;
subplot(323);
plot(1:tt,(avps(1:tt,4:5)),1:tf,(trj.trj(1:tf,4:5)),'--'); title('速度');xlabel('d');ylabel('Vel/(m.s^{-1})');
legend('\itv\rm_E','\itv\rm_N','\bfv\rm_E','\bfv\rm_N');grid on;
subplot(324);
plot(1:tt,(avps(1:tt,6)),1:tf,(trj.trj(1:tf,6)),'--'); title('速度');xlabel('d');ylabel('Vel/(m.s^{-1})');
legend('\itv\rm_U','\bfv\rm_U');grid on;
subplot(325);
plot(1:tt,deltapos(avps(1:tt,7:9)),1:tf,deltapos(trj.trj(1:tf,7:9)),'--'); title('位置');xlabel('d');ylabel('\DeltaPos / m');
legend('\Delta\itL', '\Delta\it\lambda', '\Delta\ith','\Delta\bfL', '\Delta\bf\lambda', '\Delta\bfh');grid on;  

子程序:

function [qnb,vn2,pos]=my_insupdate(qnb,vn1,pos,delta_theta_m,delta_v_m,ts)
n=1;                                                                  
nts=n*ts;
g0=9.780325333434361;                                                  % 单位;m/s^2
sl = sin(pos(1));                                                      % pos(1)=L
sl2 = sl*sl;  sl4 = sl2*sl2;
gLh = g0*(1+5.27094e-3*sl2+2.32718e-5*sl4)-3.086e-6*pos(3); 
gn = [0;0;-gLh];f = 1/298.257223563;
R_e = 6.378136998405e6;
e = sqrt(2*f-f^2);
R_N = R_e/(1-e^2*sl2)^0.5;
R_M = R_N*(1-e^2)/(1-e^2*sl2);
R_Mh = R_M + pos(3);
R_Nh = R_N + pos(3);
M_pv = [0,1/R_Mh,0;sec(pos(1))/R_Nh,0,0;0,0,1];wie = 7.2921151467e-5;    
wnie = [0,wie*cos(pos(1)),wie*sin(pos(1))]';
wnen = vn1.*[-1/(R_M + pos(3));1/(R_N + pos(3));tan(pos(1))/(R_N + pos(3))];
wnin = wnie + wnen;%速度更新
vsf =q2mat(qnb)*(delta_v_m + 1/2*cross(delta_theta_m,delta_v_m))';      % avp2(4:6) = avp1(4:6) + vsf + gn*Tm;
vn2 = vn1 + vsf + gn*nts;
%位置更新
vn1 = (vn2+vn1)/2;
pos = pos + M_pv*vn1*nts;
% 姿态更新
q_bb = [cos(norm(delta_theta_m)/2);(delta_theta_m/norm(delta_theta_m))'*sin((norm(delta_theta_m)/2))];
qnb = qmul(rv2q(-wnin*nts), qmul(qnb, q_bb));  
qnb = qnormlz(qnb);
end

数据及完整程序

https://download.csdn.net/download/qq_38364548/87380265


http://chatgpt.dhexx.cn/article/7dTVwQgn.shtml

相关文章

捷联惯导更新算法及误差分析汇总

一、捷联惯导数值更新算法 导航坐标系&#xff1a;东-北-天 载体坐标系&#xff1a;右-前-上 1、姿态更新算法&#xff1a; <1>姿态更新微分方程&#xff1a; ,表示导航系相对于惯性系的旋转&#xff1b;包括两部分&#xff1a; (1)地球自转引起的导航系旋转&#x…

捷联惯导系统(SINS)机械编排

目录 前言姿态更新姿态微分方程姿态更新算法 速度更新速度微分方程速度更新算法重力/哥氏积分项比力积分项右端第三积分项右端第二积分项 速度更新方程 位置更新位置微分方程位置更新算法 前言 IMU中的加速度计及陀螺仪测得原始数据为速度增量及角度增量&#xff0c;需要通过机…

捷联惯导基础知识解析之四(粗/精对准和GPS/IMU和GPS/里程计组合导航)

初始对准&#xff08;粗、精对准&#xff09;/组合导航 一、捷联惯导粗对准 目的&#xff1a;寻找、确定参考导航坐标系&#xff1b;结果表现形式&#xff1a;得到姿态矩阵&#xff08;进而可以求出欧拉角、四元数等&#xff09; 前提&#xff1a;在导航坐标系&#xff08;比…

捷联惯导总结--初始对准,位置标定,INS姿态更新,GPS/INS组合

惯导及组合导航回顾 2018.09.16 今天和17系的同学一起把惯导的流程捋了一遍&#xff0c;为了加深自己的记忆&#xff0c;这里在前面把心得大致列出来。 我们这里只考虑捷联式惯导及松组合 首先拿到惯性传感器&#xff08;加速度计和陀螺仪&#xff09;需要对其进行标定&#x…

捷联式惯导系统初始对准

1 初始对准简介 1.1 初始对准任务 所谓对准指的是确定惯导系统各坐标轴相对于参考坐标系指向的过程。 捷联式惯导系统初始对准的任务有两项:第一&#xff0c;机体起飞前将初始速度和初始位置引人惯导系统;第二&#xff0c;机体坐标系与导航坐标系的初始变换短阵。另外&#…

c语言函数指针 的定义方法,C语言 函数指针一(函数指针的定义)

//函数指针 #include #include #include //函数指针类型跟数组类型非常相似 //函数名就是函数的地址&#xff0c;函数的指针&#xff0c;对函数名进行&取地址操作&#xff0c;还是函数名本身&#xff0c;这是C语言编译器的特殊处理 void test(int a){ printf("a%d\n&q…

C语言函数指针调用函数

C语言可以定义指针变量指向函数&#xff0c;通过指针来调用函数。 使用&#xff1a; 1、定义函数指针变量&#xff1a; 函数返回值类型 (*指针变量名)(); 2、将已有函数入口赋值给函数指针变量&#xff1a;fnPt avg; 3、使用指针变量调用函数&#xff1a;(*指针变量名)(参…

C语言函数指针与调用

C语言函数指针与调用 平时我们使用函数传递的参数一般为数据变量&#xff0c;那么是否可以传递函数呢&#xff1f; 答案是不但可以&#xff0c;而且习惯以后&#xff0c;会用上瘾的。通过传递不同的函数指针&#xff0c;我们可以实现在函数中调用不同的子函数。 下面就举个栗子…

C语言函数指针与指针函数

在大家刚开始学习c语言的时候&#xff0c;总是分不清函数指针和指针函数&#xff0c;就算是知道了它们之间的区别&#xff0c;也不了解它们的使用场景&#xff0c; 我写此博客帮大家缕一缕&#xff0c;也帮我自己缕一缕 1、函数指针与指针函数的概念以及区别 指针函数 从名…

C语言 函数指针做函数参数(即回调函数)

文章目录 函数指针做函数参数(回调函数)回调函数概念一般有三种调用方式回调函数的作用回调函数调用时刻回调函数的语法&#xff1a;1.简单的函数类型为&#xff1a;无参数、无返回值的函数。2.完全形式的回调函数注&#xff1a; 代码案例&#xff1a;模拟计算器 函数指针做函数…

C语言 函数指针

一.前言 最近学了一点函数指针的东西 感觉还是比较有意思的 在某先方面用起来也确实会方便些 给大家在这里分享一下。 二.定义 函数指针就是指向代码段中函数入口地址的指针。 从上述这句话就可以看出 函数指针的本质是一个指针&#xff0c;只不过是指向函数的指针。 三.声明形…

C语言函数指针用法

C语言函数指针用法 函数指针本质上是指针&#xff0c;它指向一个函数。 例如int (*p)(int); – 从 p 处开始, 先与指针结合, 说明 p 是一个指针, 然后与()结合, 说明指针指向的是一个函数, 然后再与()里的 int 结合, 说明函数有一个int 型的参数, 再与最外层的 int 结合, 说明…

C语言函数指针详解

1、概念 函数指针就是一个指针&#xff0c;指针指向某个内存区域&#xff0c;函数指针就是指向函数入口地址的这么一个指针变量&#xff0c;在.c文件中编写一个函数&#xff0c;将.c编译为可执行程序后&#xff0c;在.c文件中编写的函数会存放在可执行程序的代码段中&#xff…

C语言——函数指针

函数指针 C语言中的指针类型有很多种&#xff0c;但是函数指针可能有些小伙伴没听过&#xff0c;下面我们引入一段定义。 函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量&#xff0c;只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型…

《信号与系统》小结

参考书目&#xff1a;《信号与系统(第四版) 徐亚宁 苏启常 编著》 信号与系统 信号是消息的表现形式&#xff0c;消息是信号的具体内容。也就是说任何可以承载某种消息的物理量都可以是信号。电信号只是生活中最快捷&#xff0c;也是最常用的一种。我们可以从变化的电流或电压…

信号与系统(一) 信号与系统的基本概念

1.1信号的描述 信号的描述方式采用的有3种——函数、图形和数据 1.2信号的大小 对于一个信号x(t)&#xff0c;它的能量大小为&#xff0c;但是当&#xff0c;而信号的强度不趋向于0时&#xff0c;信号能量为无限大&#xff0c;这时候就需要使用信号的功率来判断大小&#xf…

连续系统分析【信号与系统四】

连续系统分析 一、已知描述连续系统的微分方程&#xff0c;计算该系统的响应并与理论结果比较二、研究具有以下零极点的连续系统2.1 1个极点s-0.1&#xff0c;增益k12.2 1个极点s0&#xff0c;增益k12.3 2个共轭极点 &#xff0c;增益k12.4 2个共轭极点 &#xff0c;增益k12.5 …

信号与系统_第二章 连续系统的时域分析

第二章 连续系统的时域分析 ( 连续系统在时域上进行分析 ) 2.1 引言 2.2 LTI系统的微分方程表示及响应 2.3 零输入响应与零状态响应 2.4 单位冲激响应 2.5 卷积积分 2.6 卷积积分的性质 2.7 奇异函数 2.8 连续时间系统的模拟 习题 2.01_连续系统的描述: 电路图建立微分…

《信号与系统》解读 第1章 信号与系统概述-1:信号与系统的描述和分析方法

目录 1. 什么是广义的信号和系统 2. 什么是狭义的电信号和电系统 3. 两个研究对象&#xff1a;信号系统 4. 两种分析方法&#xff1a;几何图形法数学函数法 5. 两个维度与视角&#xff1a;时域频域 6. 两种坐标&#xff1a;实平面复平面 7. 目标&#xff1a;模拟信号处理…