详解IMU标定经典论文:A Robust and Easy to Implement Method for IMU Calibration without External Equipments

在这里插入图片描述
本文介绍一篇 关于IMU 标定的经典论文,论文收录于 ICRA14,在论文中作者介绍了如何不适用外部设备标定 IMU 加速度和角速度偏差、尺度系数、轴偏移参数

论文链接:https://readpaper.com/paper/2021503353、https://readpaper.com/paper/2211578699

项目链接:https://github.com/JzHuai0108/imu_tk_matlab


1. Sensor Error Model

首先介绍传感器误差模型,令 aO\mathbf{a}^{O}aO 表示为理想情况下的加速度数据,aS\mathbf{a}^{S}aS 表示为实际的加速度数据,Ta=[1−αyzαzy01−αzx001]\mathbf{T}^{a}=\left[\begin{array}{ccc}1 & -\alpha_{y z} & \alpha_{z y} \\ 0 & 1 & -\alpha_{z x} \\ 0 & 0 & 1\end{array}\right]Ta=100αyz10αzyαzx1 表示从 aS\mathbf{a}^{S}aSaO\mathbf{a}^{O}aO 的旋转变换。ba=[bxabyabza]\mathbf{b}^{a}=\left[\begin{array}{l}b_{x}^{a} \\ b_{y}^{a} \\ b_{z}^{a}\end{array}\right]ba=bxabyabza 为加速度偏差,Ka=[sxa000sya000sza]\mathbf{K}^{a}=\left[\begin{array}{ccc}s_{x}^{a} & 0 & 0 \\ 0 & s_{y}^{a} & 0 \\ 0 & 0 & s_{z}^{a}\end{array}\right]Ka=sxa000sya000sza 为加速度尺度系数,νa\boldsymbol{\nu}^{a}νa 为加速度测量噪声,则可以得到加速度误差模型
aO=TaKa(aS+ba+νa)\mathbf{a}^{O}=\mathbf{T}^{a} \mathbf{K}^{a}\left(\mathbf{a}^{S}+\mathbf{b}^{a}+\boldsymbol{\nu}^{a}\right) aO=TaKa(aS+ba+νa)

同样也可以得到角速度误差模型,令 Tg=[1−γyzγzyγxz1−γzx−γxyγyx1]\mathbf{T}^{g}=\left[\begin{array}{ccc}1 & -\gamma_{y z} & \gamma_{z y} \\ \gamma_{x z} & 1 & -\gamma_{z x} \\ -\gamma_{x y} & \gamma_{y x} & 1\end{array}\right]Tg=1γxzγxyγyz1γyxγzyγzx1Kg=[sxg000syg000szg]\mathbf{K}^{g}=\left[\begin{array}{ccc}s_{x}^{g} & 0 & 0 \\ 0 & s_{y}^{g} & 0 \\ 0 & 0 & s_{z}^{g}\end{array}\right]Kg=sxg000syg000szgbg=[bxgbygbzg]\mathbf{b}^{g}=\left[\begin{array}{l}b_{x}^{g} \\ b_{y}^{g} \\ b_{z}^{g}\end{array}\right]bg=bxgbygbzgνg\boldsymbol{\nu}^{g}νg 为角速度测量噪声,则角速度误差模型为:

ωO=TgKg(ωS+bg+νg)\boldsymbol{\omega}^{O}=\mathbf{T}^{g} \mathbf{K}^{g}\left(\boldsymbol{\omega}^{S}+\mathbf{b}^{g}+\boldsymbol{\nu}^{g}\right) ωO=TgKg(ωS+bg+νg)


2. Basic Calibration Framework

加速度标定我们需要估计的未知参数为:
θacc=[αyz,αzy,αzx,sxa,sya,sza,bxa,bya,bza]\theta^{a c c}=\left[\alpha_{y z}, \alpha_{z y}, \alpha_{z x}, s_{x}^{a}, s_{y}^{a}, s_{z}^{a}, b_{x}^{a}, b_{y}^{a}, b_{z}^{a}\right]θacc=[αyz,αzy,αzx,sxa,sya,sza,bxa,bya,bza]

此时我们可以忽略测量噪声,则加速度误差模型简化为:
aO=TaKa(aS+ba)\mathbf{a}^{O}=\mathbf{T}^{a} \mathbf{K}^{a}\left(\mathbf{a}^{S}+\mathbf{b}^{a}\right) aO=TaKa(aS+ba)

正如在传统的多位置策略中,我们将 IMU 置于 MMM 个不同的位置,在每一个静止周期内读取加速度测量值 akS\mathbf{a}^{S}_{k}akS,我们可以使用以下损失函数来估计加速度误差模型参数:
L(θacc)=∑k=1M(∥g∥2−∥h(akS,θacc)∥2)2\mathbf{L}\left(\boldsymbol{\theta}^{a c c}\right)=\sum_{k=1}^{M}\left(\|\mathbf{g}\|^{2}-\left\|h\left(\mathbf{a}_{k}^{S}, \boldsymbol{\theta}^{a c c}\right)\right\|^{2}\right)^{2} L(θacc)=k=1M(g2h(akS,θacc)2)2

其中,∣∣g∥||\mathbf{g}\|g当地重力加速度幅值。损失函数程序为:

function [res_vector] = accCostFunctLSQNONLIN(E, a_hat, magnitude)misalignmentMatrix = [1, -E(1), E(2); 0, 1, -E(3); 0, 0, 1];scalingMtrix = diag([E(4), E(5), E(6)]);a_bar = misalignmentMatrix*scalingMtrix*(a_hat + (diag([E(7), E(8), E(9)])*ones(3, size(a_hat,2))));% Magnitude taken from tables if(nargin<3)magnitude = 9.81744;endresiduals = zeros(length(a_bar(1,:)), 1);for i = 1:length(a_bar(1,:))residuals(i,1) = (magnitude^2 - (a_bar(1,i)^2 + a_bar(2,i)^2 + a_bar(3,i)^2))^2;endres_vector = residuals;end

我们使用同样的静止周期来标定陀螺仪。在这里我们通过对初始静止时刻角速度值求平均来得到角速度偏差。这样我们需要求解的参数简化为:
θgyro=[γyz,γzy,γxz,γzx,γxy,γyx,sxg,syg,szg]\boldsymbol{\theta}^{g y r o}=\left[\gamma_{y z}, \gamma_{z y}, \gamma_{x z}, \gamma_{z x}, \gamma_{x y}, \gamma_{y x}, s_{x}^{g}, s_{y}^{g}, s_{z}^{g}\right] θgyro=[γyz,γzy,γxz,γzx,γxy,γyx,sxg,syg,szg]

我们使用标定后的加速度数据作为参考,给定一个初始的重力向量,对角速度数据进行积分,我们可以估计最终的重力向量,则损失函数可以写为:
L(θgyro)=∑k=2M∥ua,k−ug,k∥2\mathbf{L}\left(\boldsymbol{\theta}^{g y r o}\right)=\sum_{k=2}^{M}\left\|\mathbf{u}_{a, k}-\mathbf{u}_{g, k}\right\|^{2} L(θgyro)=k=2Mua,kug,k2

其中,ua,k\mathbf{u}_{a, k}ua,k 是标定后的加速度向量,ug,k\mathbf{u}_{g, k}ug,k 是估计后的重力向量。角速度积分这里使用的是 RK4,不过目前 IMU 的采样频率都很高了,一般很少再使用了。


3. Calibration Procedure

A. Static Detector

IMU 标定的准确性非常依赖于静止和运动时间间隔的准确区分,为了标定加速度计我们使用静止周期,标定陀螺仪我们使用两个静态周期之间的动态时间间隔。我们这里使用基于方差的静止检测器,对于时间周期长度 twaitt_{wait}twait 秒,我们有加速度 (axt,ayt,azt)\left(\mathbf{a}_{x}^{t}, \mathbf{a}_{y}^{t}, \mathbf{a}_{z}^{t}\right)(axt,ayt,azt),然后我们计算标准差:
ς(t)=[var⁡tw(axt)]2+[var⁡tw(ayt)]2+[var⁡tw(azt)]2\varsigma(t)=\sqrt{\left[\operatorname{var}_{t_{w}}\left(\mathbf{a}_{x}^{t}\right)\right]^{2}+\left[\operatorname{var}_{t_{w}}\left(\mathbf{a}_{y}^{t}\right)\right]^{2}+\left[\operatorname{var}_{t_{w}}\left(\mathbf{a}_{z}^{t}\right)\right]^{2}} ς(t)=[vartw(axt)]2+[vartw(ayt)]2+[vartw(azt)]2

我们通过比较方标准差ς(t)\varsigma(t)ς(t) 是否大于某一阈值来区分静止和运动状态。我们将初始方差 ςinit\varsigma_{init}ςinit 扩大整数倍来作为阈值。下图是静止检测器的检测结果,这里整数倍为6倍。

在这里插入图片描述


B. Runge-Kutta Integration

下面简单介绍下四阶龙格库塔法,这里主要用在陀螺仪的标定。四元数微分方程为:
f(q,t)=q˙=12Ω(ω(t))q\mathbf{f}(\mathbf{q}, t)=\dot{\mathbf{q}}=\frac{1}{2} \boldsymbol{\Omega}(\boldsymbol{\omega}(t)) \mathbf{q} f(q,t)=q˙=21Ω(ω(t))q

其中,Ω(ω)\Omega(\boldsymbol{\omega})Ω(ω) 是一个反对称矩阵,形式为:
Ω(ω)=[0−ωx−ωy−ωzωx0ωz−ωyωy−ωz0ωxωzωy−ωx0]\boldsymbol{\Omega}(\boldsymbol{\omega})=\left[\begin{array}{cccc} 0 & -\omega_{x} & -\omega_{y} & -\omega_{z} \\ \omega_{x} & 0 & \omega_{z} & -\omega_{y} \\ \omega_{y} & -\omega_{z} & 0 & \omega_{x} \\ \omega_{z} & \omega_{y} & -\omega_{x} & 0 \end{array}\right] Ω(ω)=0ωxωyωzωx0ωzωyωyωz0ωxωzωyωx0

四阶龙格库塔法原理为:
qk+1=qk+Δt16(k1+2k2+2k3+k4)ki=f(q(i),tk+ciΔt),for i=1q(i)=qk,for i>1q(i)=qk+Δt∑j=1i−1aijkj,\begin{array}{ll} \mathbf{q}_{k+1}=\mathbf{q}_{k}+\Delta t \frac{1}{6}\left(\mathbf{k}_{1}+2 \mathbf{k}_{2}+2 \mathbf{k}_{3}+\mathbf{k}_{4}\right) \\ \mathbf{k}_{i}=\mathbf{f}\left(\mathbf{q}^{(i)}, t_{k}+c_{i} \Delta t\right), & \text { for } i=1 \\ \mathbf{q}^{(i)}=\mathbf{q}_{k}, & \text { for } i>1 \\ \mathbf{q}^{(i)}=\mathbf{q}_{k}+\Delta t \sum_{j=1}^{i-1} a_{i j} \mathbf{k}_{j}, & \end{array} qk+1=qk+Δt61(k1+2k2+2k3+k4)ki=f(q(i),tk+ciΔt),q(i)=qk,q(i)=qk+Δtj=1i1aijkj, for i=1 for i>1

各个参数为:
c1=0,c2=12,c3=12,c4=1a21=12,a31=0,a41=0a32=12,a42=0,a43=1\begin{gathered} c_{1}=0, \quad c_{2}=\frac{1}{2}, \quad c_{3}=\frac{1}{2}, \quad c_{4}=1 \\ a_{21}=\frac{1}{2}, \quad a_{31}=0, \quad a_{41}=0 \\ a_{32}=\frac{1}{2}, \quad a_{42}=0, \quad a_{43}=1 \end{gathered} c1=0,c2=21,c3=21,c4=1a21=21,a31=0,a41=0a32=21,a42=0,a43=1

最终得到积分后的四元数,还需要再转化为单位四元数,整个RK4 程序为:

function [R] = rotationRK4(omega, dt)omega_x = omega(1,:);omega_y = omega(2,:);omega_z = omega(3,:);num_samples = length(omega_x);q_k = fromOmegaToQ([omega_x(1); omega_y(1); omega_z(1)], [dt])';q_next_k = q_k; % was [0; 0; 0; 0]; changed by Huaifor i = 1:num_samples - 1% first Runge-Kutta coefficientq_i_1 = q_k;OMEGA_omega_t_k = ...[0           -omega_x(i)  -omega_y(i)  -omega_z(i);omega_x(i)   0            omega_z(i)   -omega_y(i);omega_y(i)   -omega_z(i)  0            omega_x(i);omega_z(i)   omega_y(i)   -omega_x(i)  0          ];k_1 = (1/2)*OMEGA_omega_t_k*q_i_1;% second Runge-Kutta coefficientq_i_2 = q_k + dt*(1/2)*k_1;OMEGA_omega_t_k_plus_half_dt = ...[0                                -(omega_x(i) + omega_x(i + 1))/2   -(omega_y(i) + omega_y(i + 1))/2  -(omega_z(i) + omega_z(i + 1))/2;(omega_x(i) + omega_x(i + 1))/2   0                                  (omega_z(i) + omega_z(i + 1))/2   -(omega_y(i) + omega_y(i + 1))/2;(omega_y(i) + omega_y(i + 1))/2   -(omega_z(i) + omega_z(i + 1))/2   0                                 (omega_x(i) + omega_x(i + 1))/2;(omega_z(i) + omega_z(i + 1))/2   (omega_y(i) + omega_y(i + 1))/2    -(omega_x(i) + omega_x(i + 1))/2  0                              ];k_2 = (1/2)*OMEGA_omega_t_k_plus_half_dt*q_i_2;% third Runge-Kutta coefficientq_i_3 = q_k + dt*(1/2)*k_2;OMEGA_omega_t_k_plus_half_dt = ...[0                                -(omega_x(i) + omega_x(i + 1))/2   -(omega_y(i) + omega_y(i + 1))/2  -(omega_z(i) + omega_z(i + 1))/2;(omega_x(i) + omega_x(i + 1))/2   0                                  (omega_z(i) + omega_z(i + 1))/2   -(omega_y(i) + omega_y(i + 1))/2;(omega_y(i) + omega_y(i + 1))/2   -(omega_z(i) + omega_z(i + 1))/2   0                                 (omega_x(i) + omega_x(i + 1))/2;(omega_z(i) + omega_z(i + 1))/2   (omega_y(i) + omega_y(i + 1))/2    -(omega_x(i) + omega_x(i + 1))/2  0                              ];k_3 = (1/2)*OMEGA_omega_t_k_plus_half_dt*q_i_3;% forth Runge-Kutta coefficientq_i_4 = q_k + dt*1*k_3;OMEGA_omega_t_k_plus_dt = ...[0               -omega_x(i + 1)  -omega_y(i + 1)  -omega_z(i + 1);omega_x(i + 1)   0                omega_z(i + 1)   -omega_y(i + 1);omega_y(i + 1)   -omega_z(i + 1)  0                omega_x(i + 1);omega_z(i + 1)   omega_y(i + 1)   -omega_x(i + 1)  0          ];k_4 = (1/2)*OMEGA_omega_t_k_plus_dt*q_i_4;q_next_k = q_k + dt*((1/6)*k_1 + (1/3)*k_2 + (1/3)*k_3 + (1/6)*k_4);q_next_k = q_next_k/norm(q_next_k);q_k = q_next_k;endR = inv(fromQtoR(q_next_k));end

C. Complete Procedure

为了避免标定参数估计中的不可观察性,至少需要收集IMU9个不同姿态的数据,姿态数越多,标定结果越准确。整个标定算法如下,需要知道采集好的加速度数据 aS\mathbf{a}^{S}aS 和角速度数据 ωS\boldsymbol{\omega}^{S}ωS,初始静止时间 TinitT_{init}Tinit,以及运动后的静止时间 twaitt_{wait}twait

  • 首先根据初始时间计算陀螺仪偏差 bg\boldsymbol{b}^gbg
  • 根据计算后的陀螺仪偏差得到无偏角速度数据 ωbiasfreeS\boldsymbol{\omega}^{S}_{biasfree}ωbiasfreeS
  • 计算初始协方差 ςinit\varsigma_{init}ςinit ;
  • i=1:ki=1:ki=1:k ,根据等待时间 twaitt_{wait}twait 和阈值计算静止间隔、再根据静止间隔 twaitt_{wait}twait 和加速度数据得到估计参数;
  • 最后选取残差最小对应的参数为加速度标定参数,然后再使用同样的静止周期计算陀螺仪标定参数;
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/439543.shtml

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

相关文章

重读经典:《Momentum Contrast for Unsupervised Visual Representation Learning》

MoCo 论文逐段精读【论文精读】这次论文精读李沐博士继续邀请了亚马逊计算机视觉专家朱毅博士来精读 Momentum Contrast&#xff08;MoCo)&#xff0c;强烈推荐大家去看本次的论文精读视频。朱毅博士和上次一样讲解地非常详细&#xff0c;几乎是逐词逐句地讲解&#xff0c;在讲…

【HRBUST - 1623】Relation(思维模拟,拆解字符串)

题干&#xff1a; 一天&#xff0c;ikki在看书的时候发现书上有个类似于家谱状的插图&#xff0c;突然ikki想到了一个有趣的现象&#xff1a;有时候用某个人一连串 的关系描述另一个人的时候&#xff0c;最后可能还是他本身。例如&#xff1a;小明的爸爸的爸爸和小明的爷爷是同…

一步步编写操作系统 67 系统调用的实现1-2 68

接上文&#xff1a; 系统调用的子功能要用eax寄存器来指定&#xff0c;所以咱们要看看有哪些系统调用啦&#xff0c;在linux系统中&#xff0c;系统调用是定义在/usr/include/asm/unistd.h文件中&#xff0c;该文件只是个统一的入口&#xff0c;指向了32位和64位两种版本。在a…

【HDU - 6662】Acesrc and Travel(树形dp,博弈dp)

题干&#xff1a; Acesrc is a famous tourist at Nanjing University second to none. During this summer holiday, he, along with Zhang and Liu, is going to travel to Hong Kong. There are nnspots in Hong Kong, and n−1n−1 bidirectional sightseeing bus routes …

一步步编写操作系统 69 汇编语言和c语言共同协作 70

由于有了上一节的铺垫&#xff0c;本节的内容相对较少&#xff0c;这里给大家准备了两个小文件来实例演示汇编语言和c语言相互调用。 会两种不同语言的人&#xff0c;只是掌握了同一件事物的两种表达方式。人在学习一种新语言时&#xff0c;潜意识里是建立了语言符号与事物形象…

一步步编写操作系统 71 直接操作显卡,编写自己的打印函数71-74

一直以来&#xff0c;我们在往屏幕上输出文本时&#xff0c;要么利用bios中断&#xff0c;要么利用系统调用&#xff0c;这些都是依赖别人的方法。咱们还用过一个稍微有点独立的方法&#xff0c;就是直接写显存&#xff0c;但这貌似又没什么含量。如今我们要写一个打印函数了&a…

【CodeForces - 208C 】Police Station(单源最短路条数,起点终点建图,枚举顶点)

题干&#xff1a; The Berland road network consists of n cities and of m bidirectional roads. The cities are numbered from 1 to n, where the main capital city has number n, and the culture capital — number 1. The road network is set up so that it is possi…

【Chrome浏览器】常用快捷键整理

标签页和窗口快捷键 1. Ctrl n 打开新窗口 2. Ctrl t 打开新的标签页&#xff0c;并跳转到该标签页 3. Ctrl Shift t 重新打开最后关闭的标签页&#xff0c;并跳转到该标签页 4. Ctrl Tab 跳转到下一个打开的标签页 5. Ctrl Shift Tab 跳转到上一个打开的标签页 6.…

【人工智能课程实验】 - 利用贝叶斯分类器实现手写数字 的识别

读入数据与预处理 因为老师给的文件无法直接读取&#xff0c;故从官网导入数据&#xff1a; 官网链接&#xff1a;http://www.cs.nyu.edu/~roweis/data.html 导入数据之后要对MATLAB文件进行读入&#xff1a; datasio.loadmat(trainfile) 对文件type一下&#xff1a; ty…

一步步编写操作系统 77 内联汇编与ATT语法简介

内联汇编 之前和大家介绍过了一种汇编方法&#xff0c;就是C代码和汇编代码分别编译&#xff0c;最后通过链接的方式结合在一起形成可执行文件。 另一种方式就是在C代码中直接嵌入汇编语言&#xff0c;强大的GCC无所不能&#xff0c;咱们本节要学习的就是这一种&#xff0c;它…

【Python学习】内置函数(不断更新)

关于常用在for循环中的range函数 python range() 函数可创建一个整数列表&#xff0c;一般用在 for 循环中。 函数语法 range(start, stop[, step]) 参数说明&#xff1a; start: 计数从 start 开始。默认是从 0 开始。例如range&#xff08;5&#xff09;等价于range&#…

【Python学习】 简单语法与常见错误(持续更新)

关于单引号和双引号 当输出的字符串内部没有单引号的时候&#xff0c;外面可以用单引号&#xff0c; 但是如果内部有了单引号&#xff0c;那么外部只能用双引号。 dict {Name: Zara, Age: 7, Class: First} print(dict) print (dict[Name]: , dict[Name]) print ("dic…

一步步编写操作系统 78 intel汇编与ATT汇编语法区别

本节咱们介绍下intel汇编语法和at&t汇编语法的区别。 以上表中未列出这两种语法在内存寻址方面的差异&#xff0c;个人觉得区别还是很大的&#xff0c;下面单独说说。 在Intel语法中&#xff0c;立即数就是普通的数字&#xff0c;如果让立即数成为内存地址&#xff0c;需要…

重读经典:《Masked Autoencoders Are Scalable Vision Learners》

MAE 论文逐段精读【论文精读】这一次李沐博士给大家精读的论文是 MAE&#xff0c;这是一篇比较新的文章&#xff0c;2021年11月11日才上传到 arXiv。这篇文章在知乎上的讨论贴已经超过了一百万个 view&#xff0c;但是在英文社区&#xff0c;大家反应比较平淡一点&#xff0c;R…

【Python学习日志】 - Numpy包

NumPy是什么&#xff1f; 使用Python进行科学计算的基础包&#xff0c;在数据分析的时候比较常用到矩阵计算。这时太多的Np属性不记得&#xff0c;所以方便自己使用把一些常用的Np属性汇总记录一下使用的时候方便查找。 ndarray.ndim 阵列的轴数&#xff08;尺寸&#xff09;…

详解协同感知数据集OPV2V: An Open Benchmark Dataset and Fusion Pipeline for Perception with V2V Communication

在《详解自动驾驶仿真框架OpenCDA: An Open Cooperative Driving Automation Framework Integrated with Co-Simulation》 一文中介绍了自动驾驶仿真框架 OpenCDA。本文将介绍论文作者另一篇最新工作 OPV2V&#xff0c;论文收录于 ICRA2022。 OPV2V 数据集主要 feature 有&…

【Python学习】 - 如何在Spyder中弹出plot绘图窗口而不是在Console中绘图

依次选择这几项&#xff1a; 点击ok确认。 注意&#xff1a;点击ok之后不会立即生效&#xff0c;重启Spyder之后才会生效

mysql系列:加深对脏读、脏写、可重复读、幻读的理解

关于相关术语的专业解释&#xff0c;请自行百度了解&#xff0c;本文皆本人自己结合参考书和自己的理解所做的阐述&#xff0c;如有不严谨之处&#xff0c;还请多多指教。 **不可重复读的重点是修改: **同一事务&#xff0c;两次读取到的数据不一样。 幻读的重点在于新增或者…

重读经典(点云深度学习开山之作):《Deep learning on point clouds for 3D scene understanding》(持续更新中)

本文介绍的是 PointNet 作者的博士论文&#xff1a;3D场景理解中的点云深度学习。从上图可以看到&#xff0c;整个博士论文主要贡献有两块&#xff1a;一是点云深度学习的网络架构&#xff08;PointNet 和 PointNet&#xff09;&#xff1b;二是在3D场景理解中的应用&#xff0…

Coursera自动驾驶课程第17讲:An Autonomous Vehicle State Estimator

在第16讲《Coursera自动驾驶课程第16讲&#xff1a;LIDAR Sensing》我们学习了自动驾驶目前常用的3D 传感器&#xff0c;激光雷达&#xff0c;了解了激光雷达的工作原理&#xff0c;掌握了对点云数据的操作以及如何使用点云配准方法来进行汽车定位。 回顾一下&#xff0c;在本…