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

news2024/11/24 14:46:42

低成本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;]

结果:

>> exe
    0.7071
         0
         0
    0.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.999999
	att(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);
else
	att(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:len
    t = 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://www.coloradmin.cn/o/158081.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【学习笔记之Linux】工具之make/Makefile与git

make/Makefile&#xff1a; 背景知识&#xff1a; 一个工程中的源文件不计数&#xff0c;按类型、功能、模块分别放在若干个目录中&#xff0c;Makefile定义了一系列的规则来指定&#xff0c;哪些文件需要先编译&#xff0c;哪些文件需要后编译&#xff0c;那些文件需要重新编…

电源《龙珠超:超级人造人》观后感

上周看了动画电影《龙珠超&#xff1a;超级人造人》&#xff0c;《龙珠》这个系列同《火影》、《死神》、《海贼王》和《名侦探柯南》等都存在了很长时间&#xff0c;不断在更新&#xff0c;都是非常好的IP,伴随着很多人走过童年&#xff0c;也是因为时间太长了&#xff0c;记得…

品牌打假,假货治理,有什么好的方法

品牌打假&#xff0c;清除渠道假货&#xff0c;可以提高消费者对品牌的满意度与忠诚度&#xff0c;增强经销商的经销信心&#xff0c;维护稳定的价格体系及经销体系&#xff0c;树立良好的品牌形象。 但是品牌在打假的过程中&#xff0c;由于经验、时间、方法、技术等方面的局…

测试开发 | 接口测试之HTTP 协议讲解

本文节选自霍格沃兹测试开发学社内部教材HTTP 协议是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP 是万维网的数据通信的基础。客户端向服务端发送 HTTP 请求&#xff0c;服务端则会在响应中返回所请求的数据。了解了 HTTP 协议&#xff0c;才能对接口测试进行更…

sql实现字段分割一行转多行的示例代码

先看一下数据结构&#xff0c;我这里字段比较少&#xff0c;只弄了最重要的部分 根据我们上次学到的LEFT()函数进行分组 SELECT LEFT(provinces,6),COUNT(1) FROM region_map_copy GROUP BY LEFT(provinces,6) 得到的结果如下&#xff1a; 这样的效果并不是我们想要的&#x…

必贝特科创板IPO过会:预计2025年前实现商业化,钱长庚为实控人

2023年1月10日&#xff0c;上海证券交易所披露的信息显示&#xff0c;广州必贝特医药股份有限公司&#xff08;下称“必贝特”&#xff09;获得上市委会议审核通过。据贝多财经了解&#xff0c;必贝特于2022年6月29日在科创板递交上市申请。 公开信息显示&#xff0c;必贝特是一…

SwiftUI之深入解析如何使用组合矩形GeometryReader创建条形(柱状)图

一、图表布局 条形&#xff08;柱状&#xff09;图以矩形条的形式呈现数据的类别&#xff0c;其宽度和高度与它们表示的值成比例。SwiftUI 对探索不同布局和预览实时视图结果是很友好的&#xff0c;很容易将部分内容提取到子视图中&#xff0c;以便每个部分都很小且易于维护。…

给程序提速 | 多进程与多线程

目录 一、背景 1.1、前言 1.2、说明 二、线程与进程 2.1、什么是进程 2.2、什么是线程 2.3、进程与线程的关系 2.4、多进程与多线程的最佳使用条件 2.5、线程与进程的锁 2.6、特别注意 三、第一个线程、线程池 3.1、线程测试 3.2、执行结果 3.3、线程池测试 3.4…

华中科技大学计算机组成原理-计算机数据表示实验(全部通关)

计算机数据表示实验(HUST) 计算机数据表示目录 [建议收藏]计算机数据表示实验(HUST)第1关 汉字国标码转区位码实验第2关 汉字机内码获取实验第3关 偶校验编码设计第4关 偶校验解码电路设计第5关 16位海明编码电路设计第6关 16位海明解码电路设计第7关 海明编码流水传输实验第8关…

Leetcode:700. 二叉搜索树中的搜索(C++)

目录 问题描述&#xff1a; 实现代码与解析&#xff1a; 递归&#xff1a; 原理思路&#xff1a; 迭代&#xff1a; 原理思路&#xff1a; 问题描述&#xff1a; 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和一个整数值 val。 你需要在 BST 中找到节点值…

CHAPTER 4 Docker仓库

docker仓库4.1 Docker Hub公共镜像市场4.2 第三方镜像市场4.2.1 daocloud4.2.2 阿里云4.3 *搭建本地私有仓库仓库&#xff08;Repository&#xff09;是集中存放镜像的地方&#xff0c;又分公共仓库和私有仓库。有时候容易把仓库与注册服务器&#xff08;Registory&#xff09;…

逆向-还原代码之continue (Interl 64)

// source code #include <stdio.h> int main() { int i; for (i 0; i < 10; i) { if (i 5) continue; printf("%d\n", i); } }

那年我双手离桌,被《剑指offer》打的还不了手(第八天)

跟着博主一起刷题 这里使用的是题库&#xff1a; https://leetcode.cn/problem-list/xb9nqhhg/?page1 目录剑指 Offer 55 - II. 平衡二叉树剑指 Offer 56 - I. 数组中数字出现的次数剑指 Offer 56 - II. 数组中数字出现的次数 II剑指 Offer 55 - II. 平衡二叉树 剑指 Offer 55…

缓存一致性问题解决方案(超全超易懂)

文章目录1、缓存模型和思路2、缓存更新策略3、两种解决方案3.1、先删除缓存&#xff0c;再更新数据库3.1.1延时双删&#xff08;解决先删除缓存&#xff0c;再更新数据库产生的缓存不一致问题&#xff09;1、什么是延时双删2、为什么要进行延迟双删&#xff1f;3、如何实现延迟…

【 uniapp - 黑马优购 | 购物车页面(2)】如何实现收货地址区域功能、常见问题解决方案

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大二在校生&#xff0c;讨厌编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;小新爱学习. &#x1f43c;个人WeChat&#xff1a;见文末 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;…

JVM—类加载与字节码技术

目录一、类文件结构1、魔术2、版本3、常量池二、字节码指令1、javap工具2、图解方法执行流程3、通过字节码指令来分析问题4、构造方法5、方法调用6、多态原理——HSDB7、异常处理四、类加载阶段五、类加载器六、运行期优化一、类文件结构 以一个简单的HelloWord.java程序为例 …

聊聊VMware的三种网络模式

聊聊VMware的三种网络模式1.Bridged&#xff08;桥接模式&#xff09;2.NAT&#xff08;地址转换模式&#xff09;3.Host-Only&#xff08;仅主机模式&#xff09;VMware有三种虚拟网络工作方式&#xff0c;即&#xff1a; Briged&#xff08;桥接模式&#xff09;NAT&#xf…

实现内核线程

文章目录前言前置知识实验操作实验一实验二实验三前言 博客记录《操作系统真象还原》第九章实验的操作~ 实验环境&#xff1a;ubuntu18.04VMware &#xff0c; Bochs下载安装 实验内容&#xff1a; 在内核空间实现线程。实现双向链表。实现多线程在调度器的调度下轮流执行。…

【Nginx】Nginx配置实例-反向代理

1. 反向代理实例一 实现过程 1. 启动一个 tomcat&#xff0c;浏览器地址栏输入 127.0.0.1:8080&#xff0c;出现如下界面2. 通过修改本地 host 文件&#xff0c;将 www.123.com 映射到 127.0.0.13. 在 nginx.conf 配置文件中增加如下配置 2. 反向代理实例二 实现过程 1.准备两…

唤醒手腕 Go 语言学习笔记常见包 函数用法(更新中)

1. fmt 包 fmt 包的介绍&#xff1a;fmt format&#xff0c;是一种格式化输出函数汇总包&#xff0c;用于格式化输出。 Println、Print、Printf fmt.Print 原样输出 Print formats using the default formats for its operands and writes to standard output. start : ti…