← 主页 胡洋的博客
← 返回博客首页

ESKF 观测误差与 H 矩阵:从观测模型到 Jacobian

这是 ESKF 系列的第三篇。上一篇文章已经在固定的坐标系和右侧姿态扰动下推导了 IMU 误差动力学矩阵 FF、噪声输入矩阵 GG,并把它们接到了协方差传播。本文继续处理观测更新:一个传感器读数怎样变成残差,残差怎样对 15 维误差状态线性化,最后又怎样通过 HH 矩阵回到名义状态。

摘要

ESKF 里的观测更新常被压缩成几行代码:计算残差,构造 HH,计算 Kalman gain,更新误差状态。真正容易出错的地方藏在这几行的前面:观测到底测量了什么,残差采用哪一个方向,姿态误差位于哪个坐标系,某个观测对 15 维状态中的哪些分量敏感。

本文固定上一篇文章的约定。RWBR_{WB} 把机体系 BB 的向量变换到世界系 WW,姿态使用右侧扰动

RWB=R^WBExp([δθ]×),R_{WB}=\hat R_{WB}\operatorname{Exp}([\delta\theta]_\times),

误差状态排列为

δx=[δθδpδvδbgδba].\delta x= \begin{bmatrix} \delta\theta\\ \delta p\\ \delta v\\ \delta b_g\\ \delta b_a \end{bmatrix}.

文章先从一般观测模型 z=h(X)+nz=h(\mathcal X)+n 推导残差和 HH 的定义,再逐项推导位置、速度、姿态、世界重力和静止加速度计观测。最后用 LiDAR 点到平面约束做一个几何例子,并说明观测更新、误差注入和 reset 如何组成完整闭环。

读完之后,看到一个新的传感器模型,可以按同一套步骤自己写出 HH,而不是从某篇论文或代码中复制一个看起来相似的 block 矩阵。

关键词: ESKF;观测模型;观测残差;H 矩阵;误差状态;姿态 Jacobian;LiDAR 点到平面

1. 先回答:下一篇为什么是观测误差和 HH

上一篇推导了误差状态怎样随 IMU 传播:

δx˙=Fδx+Gw.\dot{\delta x}=F\delta x+Gw.

它回答的是:在两次外部观测之间,误差会怎样变大、怎样互相影响。

当相机、GNSS、轮速计或 LiDAR 的新数据到来时,滤波器需要回答另一个问题:

当前这条观测,对误差状态中的哪些方向敏感?

这个问题由观测 Jacobian HH 描述。若观测维度为 mm,误差状态维度为 1515,那么

HRm×15.H\in\mathbb R^{m\times15}.

它的每一列对应一个误差方向,每一行对应一个观测分量。某个 block 为零,表示在当前观测模型和当前线性化点附近,该观测对相应误差的一阶变化不敏感;某个 block 非零,表示这个误差会改变预测观测。

可以把 FFHH 放在一起比较:

矩阵 它回答的问题 典型形式
FF 误差怎样随时间传播 δx˙=Fδx+Gw\dot{\delta x}=F\delta x+Gw
HH 观测怎样感受到误差 rHδx+nr\approx H\delta x+n

FF 是动力学的局部线性化,HH 是观测模型的局部线性化。两者都不是凭记忆填写的表格,都是对非线性模型求一阶导数的结果。

2. 先把约定固定下来

2.1 状态、坐标系和姿态误差

本文使用的完整状态为

X=(RWB,pW,vW,bg,ba).\mathcal X=(R_{WB},p_W,v_W,b_g,b_a).

其中 pWp_WvWv_W 在世界系中表达,bgb_gbab_a 在 IMU 机体系中表达。姿态矩阵的方向是

qW=RWBqB,qB=RWBqW.q_W=R_{WB}q_B, \qquad q_B=R_{WB}^{\top}q_W.

姿态采用右侧小扰动:

RWB=R^WBExp([δθ]×).R_{WB}=\hat R_{WB}\operatorname{Exp}([\delta\theta]_\times).

因为误差在名义姿态右侧,δθ\delta\theta 的坐标表达位于名义机体系。其余状态采用加性误差:

pW=p^W+δp,vW=v^W+δv,bg=b^g+δbg,ba=b^a+δba.\begin{aligned} p_W&=\hat p_W+\delta p,\\ v_W&=\hat v_W+\delta v,\\ b_g&=\hat b_g+\delta b_g,\\ b_a&=\hat b_a+\delta b_a. \end{aligned}

因此,后文所有观测 Jacobian 都按以下列顺序排列:

H=[HθHpHvHbgHba].H=\begin{bmatrix}H_\theta&H_p&H_v&H_{b_g}&H_{b_a}\end{bmatrix}.

每个 block 的列数都是 33,但行数取决于观测维度。

2.2 观测噪声不要和旋转矩阵混用同一个符号

观测模型写成

z=h(X)+n,z=h(\mathcal X)+n,

其中 zRmz\in\mathbb R^m 是传感器读数,h(X)h(\mathcal X) 是给定状态后预测的读数,nn 是观测噪声。为避免和旋转矩阵 RWBR_{WB} 混淆,本文用 Σz\Sigma_z 表示噪声协方差:

nN(0,Σz).n\sim\mathcal N(0,\Sigma_z).

例如,GNSS 位置观测的 Σz\Sigma_z3×33\times3 矩阵;点到平面约束的观测是一个标量,Σz\Sigma_z 就是一个 1×11\times1 的方差。

2.3 “观测误差”到底指什么

工程代码中,观测误差可能指两件不同的事:传感器自身的物理测量误差,或者实际测量和预测测量之间的差。本文把后者称为观测残差,也称 innovation:

rzh(X^).r\triangleq z-h(\hat{\mathcal X}^-).

这里 X^\hat{\mathcal X}^- 是融合当前观测之前的预测名义状态。传感器噪声 nn 则属于观测模型的一部分,不和残差混为一谈。

这一区分很有用。滤波器并不直接问“这次传感器误差是多少”,因为真实状态未知;它能计算的是“实际读数和当前状态预测出的读数相差多少”。

3. 一般观测模型如何得到 HH

3.1 从真实状态到预测状态

非线性观测模型为

z=h(X)+n.z=h(\mathcal X)+n.

实际滤波器手里只有预测名义状态 X^\hat{\mathcal X}^-,先计算预测观测:

z^=h(X^).\hat z=h(\hat{\mathcal X}^-).

真实状态写成预测名义状态加上误差:

X=X^δx.\mathcal X=\hat{\mathcal X}^-\boxplus\delta x.

于是实际测量可以写成

z=h(X^δx)+n.z=h(\hat{\mathcal X}^-\boxplus\delta x)+n.

残差为

r=zh(X^)=h(X^δx)h(X^)+n.\begin{aligned} r &=z-h(\hat{\mathcal X}^-)\\ &=h(\hat{\mathcal X}^-\boxplus\delta x)-h(\hat{\mathcal X}^-)+n. \end{aligned}

3.2 一阶展开

δx=0\delta x=0 附近做一阶 Taylor 展开:

h(X^δx)h(X^)+Hδx.h(\hat{\mathcal X}^-\boxplus\delta x) \approx h(\hat{\mathcal X}^-)+H\delta x.

其中

Hh(X^δx)δxδx=0\boxed{ H\triangleq \left. \frac{\partial h(\hat{\mathcal X}^-\boxplus\delta x)} {\partial\delta x} \right|_{\delta x=0} }

就是观测模型对误差状态的 Jacobian。代回残差:

rHδx+n.\boxed{ r\approx H\delta x+n.}

这就是 ESKF 观测更新使用的线性观测方程。

这里有一个经常被忽略的细节:HH 是对误差状态 δx\delta x 求导,不是简单地对完整状态中的 RRppvvbgb_gbab_a 做普通偏导。对位置和速度来说,两者看起来一样;对姿态来说,必须先把右侧扰动放进 R=R^Exp([δθ]×)R=\hat R\operatorname{Exp}([\delta\theta]_\times),再求导。

3.3 残差方向和 HH 的符号

本文采用

r=zz^.r=z-\hat z.

如果你改用相反的残差

r=z^z=r,r'=\hat z-z=-r,

那么线性模型必须同时改成

rHδxn.r'\approx -H\delta x-n.

这时如果把残差取反,却继续使用原来的 HH,滤波器的修正方向会反过来。代码可以选择任意一种残差方向,但残差、HH 和噪声项必须保持同一套约定。

3.4 从 HH 进入 Kalman 更新

有了残差模型

rHδx+n,r\approx H\delta x+n,

以及预测误差协方差 PP^-,先计算残差协方差:

S=HPH+Σz.S=HP^-H^\top+\Sigma_z.

Kalman gain 为

K=PHS1.K=P^-H^\top S^{-1}.

滤波器更新的是局部误差状态均值:

δx^=Kr.\delta\hat x=Kr.

可以把这三步理解为:HH 先把状态误差投影到观测空间,SS 衡量这个投影加上噪声后的不确定性,KK 再把观测残差送回状态空间。

此时不要把 δx^\delta\hat x 直接加到完整状态上。它还要经过后文的误差注入与 reset。

3.5 从概率模型推导 Kalman 更新

前面的公式说明了更新怎么写,下面解释这些公式为什么是这个形式。推导只使用一个线性高斯模型,因此不依赖 ESKF 的具体传感器。ESKF 的作用是先把非线性观测在误差状态附近变成这个模型。

3.5.1 先写出先验和观测的概率模型

在当前观测到来之前,ESKF 已经通过 IMU 传播得到了预测误差协方差 PP^-。reset 后误差状态的均值被重新定义为零,所以先验可以写成

δxN(0,P).\delta x\sim\mathcal N(0,P^-).

刚才得到的线性观测模型是

r=Hδx+n,nN(0,Σz).r=H\delta x+n, \qquad n\sim\mathcal N(0,\Sigma_z).

给定某个候选误差 δx\delta x,残差的条件分布为

rδxN(Hδx,Σz).r\mid\delta x \sim \mathcal N(H\delta x,\Sigma_z).

滤波器要做的事情可以表述为:看到残差 rr 之后,求误差状态的后验分布 p(δxr)p(\delta x\mid r)

3.5.2 由 Bayes 公式得到代价函数

Bayes 公式给出

p(δxr)p(rδx)p(δx).p(\delta x\mid r) \propto p(r\mid\delta x)p(\delta x).

把两个高斯分布的指数部分代入,负对数后验等价于最小化下面的代价函数:

J(δx)=δx(P)1δx+(rHδx)Σz1(rHδx).\begin{aligned} J(\delta x)= {}& \delta x^\top(P^-)^{-1}\delta x\\ &+(r-H\delta x)^\top \Sigma_z^{-1}(r-H\delta x). \end{aligned}

这里采用的概率假设是:预测误差 δx\delta x 和观测噪声 nn 都是零均值高斯向量,并且通常假设二者相互独立:

δxN(0,P),nN(0,Σz),Cov(δx,n)=0.\delta x\sim\mathcal N(0,P^-), \qquad n\sim\mathcal N(0,\Sigma_z), \qquad \operatorname{Cov}(\delta x,n)=0.

第一项来自先验。它惩罚误差状态偏离 IMU 传播给出的零均值预测;PP^- 越小,偏离的代价越大。第二项来自观测。它惩罚候选误差无法解释当前残差;Σz\Sigma_z 越小,观测约束越强。

这就是一个带先验的加权最小二乘问题。Kalman Filter 可以看成在线递推地求解这类问题,并把历史数据压缩在当前的均值和协方差中。

3.5.3 对代价函数求导

先把第二项展开:

(rHδx)Σz1(rHδx)=rΣz1rrΣz1HδxδxHΣz1r+δxHΣz1Hδx.\begin{aligned} &(r-H\delta x)^\top\Sigma_z^{-1}(r-H\delta x)\\ ={}&r^\top\Sigma_z^{-1}r -r^\top\Sigma_z^{-1}H\delta x\\ &-\delta x^\top H^\top\Sigma_z^{-1}r +\delta x^\top H^\top\Sigma_z^{-1}H\delta x. \end{aligned}

因为 Σz1\Sigma_z^{-1} 是对称矩阵,中间两个标量相等,可以合并为两倍的一次项:

J(δx)=δx((P)1+HΣz1H)δx2δxHΣz1r+rΣz1r.\begin{aligned} J(\delta x)= {}& \delta x^\top \left((P^-)^{-1}+H^\top\Sigma_z^{-1}H\right) \delta x\\ &-2\delta x^\top H^\top\Sigma_z^{-1}r +r^\top\Sigma_z^{-1}r. \end{aligned}

δx\delta x 求梯度:

Jδx=2((P)1+HΣz1H)δx2HΣz1r.\begin{aligned} \frac{\partial J}{\partial\delta x} ={}&2\left((P^-)^{-1}+H^\top\Sigma_z^{-1}H\right)\delta x\\ &-2H^\top\Sigma_z^{-1}r. \end{aligned}

令梯度为零,得到正规方程:

((P)1+HΣz1H)δx^=HΣz1r.\left((P^-)^{-1}+H^\top\Sigma_z^{-1}H\right) \delta\hat x =H^\top\Sigma_z^{-1}r.

于是误差状态的后验均值首先可以写成信息形式:

δx^=((P)1+HΣz1H)1HΣz1r.\boxed{ \delta\hat x =\left((P^-)^{-1}+H^\top\Sigma_z^{-1}H\right)^{-1} H^\top\Sigma_z^{-1}r. }

这个形式很能说明信息是如何累加的:先验信息矩阵是 (P)1(P^-)^{-1},当前观测提供的信息矩阵是 HΣz1HH^\top\Sigma_z^{-1}H,两者相加后再求解误差。

3.5.4 把正规方程改写成 Kalman gain 形式

直接定义 Kalman gain

为简化记号,令

A(P)1+HΣz1H.A\triangleq (P^-)^{-1}+H^\top\Sigma_z^{-1}H.

信息形式已经写成

δx^=A1HΣz1r.\delta\hat x =A^{-1}H^\top\Sigma_z^{-1}r.

观察这个式子:右边是一个矩阵乘以残差 rr。前面的矩阵负责把观测残差转换成误差状态修正,因此我们直接把它定义为 Kalman gain:

KA1HΣz1.\boxed{ K\triangleq A^{-1}H^\top\Sigma_z^{-1}. }

于是更新公式马上变成

δx^=Kr.\boxed{ \delta\hat x=Kr. }

因此,KK 表示从观测残差到误差状态修正的线性映射。它的数值由先验协方差、观测 Jacobian 和观测噪声共同决定。

利用求逆引理得到观测空间形式

前面已经定义了信息形式下的 Kalman gain:

KA1HΣz1,A=(P)1+HΣz1H.K\triangleq A^{-1}H^\top\Sigma_z^{-1}, \qquad A=(P^-)^{-1}+H^\top\Sigma_z^{-1}H.

这个定义直接对应

δx^=Kr.\delta\hat x=Kr.

为了得到更适合工程计算的形式,使用矩阵求逆引理(Woodbury identity)的下面这个形式:

(Q1+CR1C)1CR1=QC(CQC+R)1.\boxed{ \left(Q^{-1}+C^\top R^{-1}C\right)^{-1}C^\top R^{-1} =QC^\top\left(CQC^\top+R\right)^{-1}. }

在当前问题中令

Q=P,C=H,R=Σz.Q=P^-, \qquad C=H, \qquad R=\Sigma_z.

那么求逆引理的左侧正好是信息形式中的 KK

(Q1+CR1C)1CR1=((P)1+HΣz1H)1HΣz1=A1HΣz1=K.\begin{aligned} \left(Q^{-1}+C^\top R^{-1}C\right)^{-1}C^\top R^{-1} &=\left((P^-)^{-1}+H^\top\Sigma_z^{-1}H\right)^{-1} H^\top\Sigma_z^{-1}\\ &=A^{-1}H^\top\Sigma_z^{-1}\\ &=K. \end{aligned}

求逆引理的右侧则变为

QC(CQC+R)1=PH(HPH+Σz)1.QC^\top\left(CQC^\top+R\right)^{-1} =P^-H^\top\left(HP^-H^\top+\Sigma_z\right)^{-1}.

因此,KK 可以直接改写为

K=PH(HPH+Σz)1.\boxed{ K =P^-H^\top\left(HP^-H^\top+\Sigma_z\right)^{-1}. }

记残差协方差为

SHPH+Σz,S\triangleq HP^-H^\top+\Sigma_z,

则上式就是熟悉的 Kalman gain 形式:

K=PHS1.\boxed{ K=P^-H^\top S^{-1}. }

这里的关键是:求逆引理没有改变 KK,只是把原来 15×1515\times15 矩阵 AA 的求逆,改写成了观测空间中 m×mm\times m 矩阵 SS 的求逆。像素观测通常为 m=2m=2,点到平面观测通常为 m=1m=1。数值实现中也不需要显式形成 S1S^{-1},而是通过线性方程求解器计算 PHS1P^-H^\top S^{-1}

求逆引理的一个证明

为了证明上面的求逆引理,记

LQ1+CR1C,MCQC+R,L\triangleq Q^{-1}+C^\top R^{-1}C, \qquad M\triangleq CQC^\top+R,

并定义

XQCM1.X\triangleq QC^\top M^{-1}.

XX 左乘 LL,逐步展开:

LX=(Q1+CR1C)QCM1=(C+CR1CQC)M1=C(I+R1CQC)M1=CR1(R+CQC)M1=CR1MM1=CR1.\begin{aligned} LX &=\left(Q^{-1}+C^\top R^{-1}C\right) QC^\top M^{-1}\\ &=\left(C^\top+C^\top R^{-1}CQC^\top\right)M^{-1}\\ &=C^\top\left(I+R^{-1}CQC^\top\right)M^{-1}\\ &=C^\top R^{-1}\left(R+CQC^\top\right)M^{-1}\\ &=C^\top R^{-1}MM^{-1}\\ &=C^\top R^{-1}. \end{aligned}

由于 LL 可逆,两边左乘 L1L^{-1},得到

X=L1CR1.X=L^{-1}C^\top R^{-1}.

再代回 LLMMXX 的定义:

QC(CQC+R)1=(Q1+CR1C)1CR1.QC^\top\left(CQC^\top+R\right)^{-1} =\left(Q^{-1}+C^\top R^{-1}C\right)^{-1}C^\top R^{-1}.

这就证明了前面使用的矩阵求逆引理。

最终,误差状态更新仍然是

δx^=Kr.\delta\hat x=Kr.

信息形式适合从概率模型推导更新,观测空间形式适合实际计算;二者通过求逆引理完全等价。

3.5.5 SS 为什么是残差协方差

Kalman gain 中的矩阵

S=HPH+ΣzS=HP^-H^\top+\Sigma_z

也可以直接从残差的随机变量表达式看出来:

r=Hδx+n.r=H\delta x+n.

由于先验误差和观测噪声相互独立,且二者均值为零,

Cov(r)=Cov(Hδx+n)=HCov(δx)H+Cov(n)=HPH+Σz.\begin{aligned} \operatorname{Cov}(r) &=\operatorname{Cov}(H\delta x+n)\\ &=H\operatorname{Cov}(\delta x)H^\top +\operatorname{Cov}(n)\\ &=HP^-H^\top+\Sigma_z. \end{aligned}

所以 SS 不是为了让公式看起来完整而添加的中间量。它就是当前残差实际具有的不确定性:一部分来自预测状态误差投影到观测空间,另一部分来自传感器本身的噪声。

如果 SS 很大,说明当前残差本身不确定,单次残差对状态的修正会变小;如果 SS 较小,说明这条残差更值得信任。

3.5.6 后验协方差从哪里来

代价函数的二次项矩阵就是注入前的后验信息矩阵:

(P~+)1=(P)1+HΣz1H.(\widetilde P^+)^{-1} =(P^-)^{-1}+H^\top\Sigma_z^{-1}H.

因此,误差注入前的后验协方差在信息形式下为

P~+=((P)1+HΣz1H)1.\widetilde P^+ =\left((P^-)^{-1} +H^\top\Sigma_z^{-1}H\right)^{-1}.

利用和上面相同的矩阵恒等式,可以把它改写成 Kalman 形式:

P~+=PPHS1HP.\boxed{ \widetilde P^+ =P^--P^-H^\top S^{-1}HP^-. }

这里用 P~+\widetilde P^+ 表示误差注入之前的后验协方差。它描述的还是预测名义状态附近那套误差坐标;注入之后还需要通过 reset Jacobian 转换。

还可以从更新后的估计误差直接验证这个结果。定义

e+=δxδx^.e^+=\delta x-\delta\hat x.

由于 δx^=Kr\delta\hat x=Krr=Hδx+nr=H\delta x+n,有

e+=(IKH)δxKn.e^+=(I-KH)\delta x-Kn.

因此

P~+=(IKH)P(IKH)+KΣzK.\boxed{ \widetilde P^+ =(I-KH)P^-(I-KH)^\top +K\Sigma_zK^\top. }

这就是 Joseph 形式。现在把

S=HPH+Σz,K=PHS1S=HP^-H^\top+\Sigma_z, \qquad K=P^-H^\top S^{-1}

代入并逐项展开:

P~+=(IKH)P(IKH)+KΣzK=PKHPPHK+K(HPH+Σz)K=PKHPPHK+KSK.\begin{aligned} \widetilde P^+ &=(I-KH)P^-(I-KH)^\top+K\Sigma_zK^\top\\ &=P^- -KHP^- -P^-H^\top K^\top +K\left(HP^-H^\top+\Sigma_z\right)K^\top\\ &=P^- -KHP^- -P^-H^\top K^\top+KSK^\top. \end{aligned}

关键的一步是利用 Kalman gain 的定义:

KS=PHS1S=PH.KS =P^-H^\top S^{-1}S =P^-H^\top.

因此

KSK=PHK,KSK^\top=P^-H^\top K^\top,

上式中的两项正好抵消:

P~+=PKHP=PPHS1HP.\begin{aligned} \widetilde P^+ &=P^- -KHP^-\\ &=P^- -P^-H^\top S^{-1}HP^-. \end{aligned}

所以,下面三种写法在标准 Kalman gain 条件下是同一个后验协方差:

P~+=(IKH)P=PPHS1HP=(IKH)P(IKH)+KΣzK.\boxed{ \begin{aligned} \widetilde P^+ &=(I-KH)P^-\\ &=P^- -P^-H^\top S^{-1}HP^-\\ &=(I-KH)P^-(I-KH)^\top+K\Sigma_zK^\top. \end{aligned} }

这里的等价关系依赖于

K=PHS1,S=HPH+Σz.K=P^-H^\top S^{-1}, \qquad S=HP^-H^\top+\Sigma_z.

如果 KK 是任意矩阵,而不是这个 Kalman gain,上面的 Joseph 形式一般不能直接简化为 (IKH)P(I-KH)P^-。此外,在精确数学中通常假设 PP^-Σz\Sigma_z 对称、SS 可逆,因此减法形式也保持对称性。

在数学上这些形式等价;在浮点计算中,Joseph 形式通常更适合保持协方差的对称性和半正定性。因此实际实现常用

P~+=(IKH)P(IKH)+KΣzK\widetilde P^+ =(I-KH)P^-(I-KH)^\top +K\Sigma_zK^\top

而不是直接使用化简后的表达式。

3.5.7 用一维例子理解 Kalman gain

把所有矩阵暂时换成标量。设先验误差方差为 pp,观测模型为

r=δx+n,Var(n)=σ2.r=\delta x+n, \qquad \operatorname{Var}(n)=\sigma^2.

此时

K=pp+σ2,δx^=Kr.K=\frac{p}{p+\sigma^2}, \qquad \delta\hat x=Kr.

如果先验很不确定,pσ2p\gg\sigma^2,则

K1,K\approx1,

滤波器更相信观测残差;如果传感器噪声很大,σ2p\sigma^2\gg p,则

K0,K\approx0,

滤波器主要保留 IMU 预测。

多维情况下,PHP^-H^\top 还会把残差传播回相关的状态方向,S1S^{-1} 则按照观测空间中的不确定性进行加权。于是 Kalman gain 不是一个固定的“观测权重”,而是由预测协方差、观测 Jacobian 和观测噪声共同决定的矩阵。

4. 位置观测:最简单的 HH

4.1 观测模型

假设外部传感器直接给出 IMU 原点在世界系中的位置:

zp=pW+np.z_p=p_W+n_p.

这是一个三维观测,zpR3z_p\in\mathbb R^3。预测观测是

z^p=p^W.\hat z_p=\hat p_W.

残差为

rp=zpp^W.r_p=z_p-\hat p_W.

4.2 代入误差状态

真实位置为

pW=p^W+δp.p_W=\hat p_W+\delta p.

所以

zp=p^W+δp+np,rp=zpp^Wδp+np.\begin{aligned} z_p &=\hat p_W+\delta p+n_p,\\ r_p &=z_p-\hat p_W\\ &\approx\delta p+n_p. \end{aligned}

因此

Hp=[0I000].\boxed{ H_p= \begin{bmatrix} 0&I&0&0&0 \end{bmatrix}. }

这里的 00II 都是 3×33\times3 block,因此 HpH_p3×153\times15

这个结果很直观:位置观测对位置误差敏感,对姿态、速度和两个 bias 没有直接的一阶敏感性。

4.3 “没有直接敏感”不等于“永远不影响”

HpH_p 中姿态和 bias block 为零,不代表位置观测无法间接修正姿态或 bias。预测协方差 PP^- 中通常有交叉协方差,例如位置和姿态、位置和加速度计 bias 之间的相关性:

Ppθ0,Ppba0.P^-_{p\theta}\neq0, \qquad P^-_{p b_a}\neq0.

Kalman gain 使用的是

K=PHpS1.K=P^-H_p^\top S^{-1}.

即使 HpH_p 只直接读取位置,PHpP^-H_p^\top 仍然可能在姿态、速度和 bias 行上非零。因此外部位置观测可以通过传播过程中形成的相关性修正其他状态。

这也是读 HH 矩阵时要注意的地方:HH 描述当前观测的直接敏感性,KK 决定这条信息最终会修正哪些状态。

5. 速度观测:把 pp 换成 vv

5.1 观测模型和残差

如果轮速计或外部速度估计器给出世界系速度观测:

zv=vW+nv,z_v=v_W+n_v,

z^v=v^W,rv=zvv^W.\hat z_v=\hat v_W, \qquad r_v=z_v-\hat v_W.

代入

vW=v^W+δv,v_W=\hat v_W+\delta v,

得到

rvδv+nv.r_v\approx\delta v+n_v.

所以

Hv=[00I00].\boxed{ H_v= \begin{bmatrix} 0&0&I&0&0 \end{bmatrix}. }

同样,HvH_v3×153\times15

5.2 速度坐标系必须先说清楚

上面的模型假设观测是世界系速度。如果轮速计给出的是机体系前向速度,观测模型就不是 zv=vW+nvz_v=v_W+n_v

例如,假设传感器测量机体系中的速度:

zvB=RWBvW+nvB.z_{v_B}=R_{WB}^{\top}v_W+n_{v_B}.

预测值为

z^vB=R^WBv^W.\hat z_{v_B}=\hat R_{WB}^{\top}\hat v_W.

把真实状态代入:

RWBvW=Exp([δθ]×)R^WB(v^W+δv)(I[δθ]×)(v^B+R^WBδv)v^B[δθ]×v^B+R^WBδv,\begin{aligned} R_{WB}^{\top}v_W &=\operatorname{Exp}(-[\delta\theta]_\times) \hat R_{WB}^{\top}(\hat v_W+\delta v)\\ &\approx ( I-[\delta\theta]_\times ) (\hat v_B+\hat R_{WB}^{\top}\delta v)\\ &\approx \hat v_B-[\delta\theta]_\times\hat v_B +\hat R_{WB}^{\top}\delta v, \end{aligned}

其中

v^BR^WBv^W.\hat v_B\triangleq\hat R_{WB}^{\top}\hat v_W.

利用

[δθ]×v^B=[v^B]×δθ,-[\delta\theta]_\times\hat v_B =[\hat v_B]_\times\delta\theta,

可得

rvB[v^B]×δθ+R^WBδv+nvB.r_{v_B} \approx [\hat v_B]_\times\delta\theta +\hat R_{WB}^{\top}\delta v+n_{v_B}.

所以机体系速度观测的 Jacobian 是

HvB=[[v^B]×0R^WB00].\boxed{ H_{v_B}= \begin{bmatrix} [\hat v_B]_\times&0&\hat R_{WB}^{\top}&0&0 \end{bmatrix}. }

同一个“速度观测”,只因为输出坐标系不同,HH 就从一个只含速度 block 的矩阵变成了同时含姿态和速度 block 的矩阵。写 Jacobian 前先确认传感器给的是哪个坐标系中的量。

6. 姿态观测:不能用矩阵相减

6.1 一个适合旋转的观测模型

假设视觉、磁力计或其他外部模块给出姿态观测 zRSO(3)z_R\in SO(3)。采用右侧旋转噪声模型:

zR=RWBExp([ηR]×),z_R=R_{WB}\operatorname{Exp}([\eta_R]_\times),

其中 ηRR3\eta_R\in\mathbb R^3 是小角度观测噪声。

旋转没有普通向量意义下的减法,因此残差不能写成

zRR^WB.z_R-\hat R_{WB}.

可以把两者相乘得到相对旋转,再取对数映射:

ρRLog(R^WBzR).\rho_R \triangleq \operatorname{Log}\left(\hat R_{WB}^{\top}z_R\right)^\vee.

这里 \vee 把反对称矩阵转换为对应的三维向量。

6.2 代入右侧姿态误差

RWB=R^WBExp([δθ]×)R_{WB}=\hat R_{WB}\operatorname{Exp}([\delta\theta]_\times)

和观测模型,得到

R^WBzR=R^WBRWBExp([ηR]×)=Exp([δθ]×)Exp([ηR]×).\begin{aligned} \hat R_{WB}^{\top}z_R &=\hat R_{WB}^{\top}R_{WB} \operatorname{Exp}([\eta_R]_\times)\\ &=\operatorname{Exp}([\delta\theta]_\times) \operatorname{Exp}([\eta_R]_\times). \end{aligned}

在两个量都足够小时,Baker-Campbell-Hausdorff 展开的一阶结果是

Log(Exp([δθ]×)Exp([ηR]×))δθ+ηR.\operatorname{Log} \left(\operatorname{Exp}([\delta\theta]_\times) \operatorname{Exp}([\eta_R]_\times)\right)^\vee \approx\delta\theta+\eta_R.

因此

ρRδθ+ηR.\rho_R\approx\delta\theta+\eta_R.

姿态观测的 Jacobian 为

HR=[I0000].\boxed{ H_R= \begin{bmatrix} I&0&0&0&0 \end{bmatrix}. }

6.3 乘法顺序改变,结果也会改变

上面的简单结果依赖三个约定:右侧姿态误差、右侧观测噪声,以及残差

Log(R^zR).\operatorname{Log}(\hat R^{\top}z_R)^\vee.

如果观测噪声改放到左侧,或者残差改成

Log(zRR^),\operatorname{Log}(z_R^{\top}\hat R)^\vee,

误差向量的坐标系和符号都会变化。不能看到两个旋转矩阵,就直接把 HθH_\theta 填成 II。正确做法是把具体的乘法顺序写出来,再在单位元附近线性化。

7. 重力观测:姿态误差 Jacobian 的一个典型来源

重力观测很适合练习右侧姿态扰动,因为它只观测一个世界系方向。设世界系重力加速度为 gWg_W,外部模块给出机体系重力向量:

zg=RWBgW+ng.z_g=R_{WB}^{\top}g_W+n_g.

这里的 ngn_g 是观测噪声,不是上一篇 IMU 误差动力学中的陀螺仪噪声;符号相同可能造成混淆,实际代码中应使用更具体的命名。

7.1 预测观测

定义名义姿态下的重力投影:

g^BR^WBgW.\hat g_B\triangleq\hat R_{WB}^{\top}g_W.

预测观测是

z^g=g^B.\hat z_g=\hat g_B.

7.2 展开真实重力投影

由右侧姿态误差

RWB=Exp([δθ]×)R^WB,R_{WB}^{\top} =\operatorname{Exp}(-[\delta\theta]_\times) \hat R_{WB}^{\top},

RWBgW=Exp([δθ]×)g^B(I[δθ]×)g^B=g^B[δθ]×g^B.\begin{aligned} R_{WB}^{\top}g_W &=\operatorname{Exp}(-[\delta\theta]_\times)\hat g_B\\ &\approx (I-[\delta\theta]_\times)\hat g_B\\ &=\hat g_B-[\delta\theta]_\times\hat g_B. \end{aligned}

利用叉乘交换关系:

[δθ]×g^B=[g^B]×δθ,-[\delta\theta]_\times\hat g_B =[\hat g_B]_\times\delta\theta,

因此

RWBgWg^B+[g^B]×δθ.R_{WB}^{\top}g_W \approx \hat g_B+[\hat g_B]_\times\delta\theta.

代回残差:

rg=zgg^B[g^B]×δθ+ng.\begin{aligned} r_g &=z_g-\hat g_B\\ &\approx[\hat g_B]_\times\delta\theta+n_g. \end{aligned}

所以

Hg=[[g^B]×0000].\boxed{ H_g= \begin{bmatrix} [\hat g_B]_\times&0&0&0&0 \end{bmatrix}. }

这个 HgH_g3×153\times15,但 [g^B]×[\hat g_B]_\times 的秩最多为 22。沿重力方向旋转不会改变重力向量,所以纯重力方向观测不能约束绕重力的 yaw 误差:

[g^B]×g^B=0.[\hat g_B]_\times\hat g_B=0.

这不是数值实现的缺陷,而是观测模型本身的几何退化。

7.3 静止加速度计不是同一个符号

上一篇文章使用的加速度计模型为

a~=RWB(aWgW)+ba+na.\tilde a =R_{WB}^{\top}(a_W-g_W)+b_a+n_a.

静止时 aW=0a_W=0,所以理想加速度计读数是

za=RWBgW+ba+na.z_a=-R_{WB}^{\top}g_W+b_a+n_a.

注意这里是 RWBgW-R_{WB}^{\top}g_W,因为加速度计测量比力,不是重力加速度本身。

定义

a^gR^WBgW.\hat a_g\triangleq-\hat R_{WB}^{\top}g_W.

真实观测的一阶展开为

za=Exp([δθ]×)R^WBgW+b^a+δba+naR^WBgW[g^B]×δθ+b^a+δba+na.\begin{aligned} z_a &=-\operatorname{Exp}(-[\delta\theta]_\times) \hat R_{WB}^{\top}g_W +\hat b_a+\delta b_a+n_a\\ &\approx -\hat R_{WB}^{\top}g_W -[\hat g_B]_\times\delta\theta +\hat b_a+\delta b_a+n_a. \end{aligned}

因此

ra[g^B]×δθ+δba+na,r_a \approx -[\hat g_B]_\times\delta\theta +\delta b_a+n_a,

对应的 Jacobian 是

Ha=[[g^B]×000I].\boxed{ H_a= \begin{bmatrix} -[\hat g_B]_\times&0&0&0&I \end{bmatrix}. }

这两个矩阵很容易写反:纯重力向量观测的姿态 block 是 +[g^B]×+[\hat g_B]_\times,静止比力观测的姿态 block 是 [g^B]×-[\hat g_B]_\times,并且后者还多了加速度计 bias block II

这也解释了为什么静止时不能仅凭加速度计均值同时精确得到姿态和加速度计 bias。两者都进入同一个观测通道,线性化后会产生耦合。

7.4 如果只使用重力方向

有些系统不使用加速度计的幅值,只使用归一化方向:

zˉa=zaza.\bar z_a=\frac{z_a}{\lVert z_a\rVert}.

此时不能直接把未归一化观测的 HaH_a 当成方向观测的 Jacobian。对归一化函数

ν(x)=xx\nu(x)=\frac{x}{\lVert x\rVert}

其 Jacobian 为

νx=1x(Iνν).\frac{\partial\nu}{\partial x} =\frac{1}{\lVert x\rVert} \left(I-\nu\nu^\top\right).

Ha,rawH_{a,\mathrm{raw}} 是原始比力观测的 Jacobian,则方向观测的 Jacobian 近似为

Ha,dir=1a^g(Iu^u^)Ha,raw,H_{a,\mathrm{dir}} =\frac{1}{\lVert\hat a_g\rVert} \left(I-\hat u\hat u^\top\right)H_{a,\mathrm{raw}},

其中

u^=a^ga^g.\hat u=\frac{\hat a_g}{\lVert\hat a_g\rVert}.

投影矩阵 Iu^u^I-\hat u\hat u^\top 会去掉沿向量自身的幅值变化,只保留方向变化。因此归一化后的观测通常只提供两个独立约束。

8. LiDAR 点到平面观测:把几何关系写成 HH

前面的例子直接读取状态中的位置、速度或重力投影。LiDAR 点到平面约束更接近实际 LIO:观测不是状态的某一个分量,而是由姿态、位置和点坐标共同组成的几何量。

8.1 几何模型

设一个 LiDAR 点已经转换到 IMU 机体系,坐标为 qBq_B。它在世界系中的位置为

qW=pW+RWBqB.q_W=p_W+R_{WB}q_B.

设该点对应的世界系平面满足

nWxW=d,n_W^\top x_W=d,

其中 nWn_W 是单位法向量,dd 是平面到世界原点的有符号距离。

理想情况下,点落在平面上:

nWqW=d.n_W^\top q_W=d.

把它写成标量观测模型:

zπ=d+nπ,z_\pi=d+n_\pi,hπ(X)=nW(pW+RWBqB).h_\pi(\mathcal X)=n_W^\top(p_W+R_{WB}q_B).

残差采用本文统一的“实际观测减预测观测”:

rπ=zπhπ(X^).r_\pi=z_\pi-h_\pi(\hat{\mathcal X}).

如果实现中习惯使用点到平面的代数残差 hπzπh_\pi-z_\pi,只需要把整个残差和整个 Jacobian 同时取反。

8.2 位置部分

先展开位置:

pW=p^W+δp.p_W=\hat p_W+\delta p.

位置引起的预测观测变化为

nWpW=nWp^W+nWδp.n_W^\top p_W =n_W^\top\hat p_W+n_W^\top\delta p.

因此位置 block 是 nWn_W^\top

8.3 姿态部分

再处理旋转后的点。由

RWB=R^WBExp([δθ]×)R_{WB}=\hat R_{WB}\operatorname{Exp}([\delta\theta]_\times)

和一阶近似,

RWBqBR^WB(I+[δθ]×)qB=R^WBqB+R^WB[δθ]×qB.\begin{aligned} R_{WB}q_B &\approx\hat R_{WB}(I+[\delta\theta]_\times)q_B\\ &=\hat R_{WB}q_B+\hat R_{WB}[\delta\theta]_\times q_B. \end{aligned}

利用

[δθ]×qB=[qB]×δθ,[\delta\theta]_\times q_B =-[q_B]_\times\delta\theta,

得到

RWBqBR^WBqBR^WB[qB]×δθ.R_{WB}q_B \approx \hat R_{WB}q_B-\hat R_{WB}[q_B]_\times\delta\theta.

定义名义世界系点坐标

q^WR^WBqB.\hat q_W\triangleq\hat R_{WB}q_B.

则点到平面预测值的一阶展开为

hπ(X)nW(p^W+q^W)+nWδpnWR^WB[qB]×δθ.\begin{aligned} h_\pi(\mathcal X) &\approx n_W^\top(\hat p_W+\hat q_W)\\ &\quad+n_W^\top\delta p -n_W^\top\hat R_{WB}[q_B]_\times\delta\theta. \end{aligned}

因此,按照 r=zh(X^)r=z-h(\hat{\mathcal X}) 的约定,残差满足

rπnWR^WB[qB]×δθ+nWδp+nπ.r_\pi \approx -n_W^\top\hat R_{WB}[q_B]_\times\delta\theta +n_W^\top\delta p+n_\pi.

对应的 1×151\times15 Jacobian 为

Hπ=[nWR^WB[qB]×nW000].\boxed{ H_\pi= \begin{bmatrix} -n_W^\top\hat R_{WB}[q_B]_\times &n_W^\top &0 &0 &0 \end{bmatrix}. }

8.4 这个 Jacobian 的几何意义

姿态 block

nWR^WB[qB]×-n_W^\top\hat R_{WB}[q_B]_\times

表示:机体绕一个小角度转动时,点的位置如何移动,以及这个移动在平面法向方向上有多少分量。

位置 block nWn_W^\top 表示:沿平面法向移动一点,点到平面的距离就会改变;沿平面切向移动,一阶距离不变。确实,如果 tWt_W 是平面内的切向量,满足 nWtW=0n_W^\top t_W=0,那么

HptW=nWtW=0.H_p t_W=n_W^\top t_W=0.

这说明单个平面约束不能约束沿平面切向的平移。多个方向不同的平面,或者连续帧中的运动,才能逐渐消除这些退化方向。

8.5 外参不能被悄悄省略

上面把 qBq_B 当作已知的 IMU 系点坐标。实际 LiDAR 点通常首先位于 LiDAR 系 LL,需要通过外参变换:

qB=tBL+RBLqL.q_B=t_{BL}+R_{BL}q_L.

这里的具体下标含义必须由定义确认。若外参固定,qBq_B 可以在构造观测时先算好;若外参也在状态中估计,HH 还要增加对应的外参 block。

最容易出错的做法是:法向量用世界系、点用 LiDAR 系、旋转矩阵却按 IMU 到世界系套公式。每一项放入点到平面方程前,都必须已经在同一个坐标系中。

8.6 视觉重投影误差:从世界点到像素坐标

视觉观测是 ESKF 中最经典的一类观测。相机并不直接测量位置或姿态,而是测量一个世界点在图像上的像素位置。这个观测模型包含坐标变换和透视除法,正好可以把前面的姿态误差、位置误差和链式求导串起来。

下面先使用一个简化但完整的模型:地图点在世界系中已知,相机内参和 IMU-相机外参已知,状态中暂时不估计地图点和外参。最后再说明这些假设改变后 HH 如何扩展。

8.6.1 相机观测模型

设世界系中的地图点为 PWP_W。相机坐标系记为 CC,从 IMU 系 BB 到相机系 CC 的固定外参为

pC=RCBpB+tCB,p_C=R_{CB}p_B+t_{CB},

其中 RCBR_{CB} 把机体系向量变换到相机系,tCBt_{CB} 是 IMU 原点在相机系中的坐标。

先把世界点变换到 IMU 系。由于 RWBR_{WB} 是 body-to-world 旋转,

B=RWB(PWpW).\ell_B=R_{WB}^{\top}(P_W-p_W).

再变换到相机系:

C=RCBB+tCB.\ell_C=R_{CB}\ell_B+t_{CB}.

C=[XCYCZC],ZC>0.\ell_C= \begin{bmatrix} X_C\\Y_C\\Z_C \end{bmatrix}, \qquad Z_C>0.

采用理想针孔模型,像素预测为

π(C)=[fxXC/ZC+cxfyYC/ZC+cy].\pi(\ell_C)= \begin{bmatrix} f_xX_C/Z_C+c_x\\ f_yY_C/Z_C+c_y \end{bmatrix}.

实际相机观测为

zu=π(C)+nu,z_u=\pi(\ell_C)+n_u,

其中 zu=[u,v]z_u=[u,v]^\top 是二维像素观测,nun_u 是像素噪声。预测名义状态下的点坐标和像素为

^B=R^WB(PWp^W),\hat\ell_B=\hat R_{WB}^{\top}(P_W-\hat p_W),^C=RCB^B+tCB,\hat\ell_C=R_{CB}\hat\ell_B+t_{CB},z^u=π(^C).\hat z_u=\pi(\hat\ell_C).

本文继续采用实际观测减预测观测的残差:

ru=zuz^u.r_u=z_u-\hat z_u.

8.6.2 先求相机系点坐标对状态误差的导数

这一步先不做像素投影,只研究 C\ell_C 如何变化。将真实状态代入 IMU 系点坐标:

B=RWB(PWpW)=Exp([δθ]×)R^WB(PWp^Wδp).\begin{aligned} \ell_B &=R_{WB}^{\top}(P_W-p_W)\\ &=\operatorname{Exp}(-[\delta\theta]_\times) \hat R_{WB}^{\top}(P_W-\hat p_W-\delta p). \end{aligned}

定义名义 IMU 系点坐标

^BR^WB(PWp^W).\hat\ell_B\triangleq \hat R_{WB}^{\top}(P_W-\hat p_W).

于是

B=Exp([δθ]×)(^BR^WBδp).\ell_B =\operatorname{Exp}(-[\delta\theta]_\times) \left(\hat\ell_B-\hat R_{WB}^{\top}\delta p\right).

使用

Exp([δθ]×)I[δθ]×,\operatorname{Exp}(-[\delta\theta]_\times) \approx I-[\delta\theta]_\times,

得到

B(I[δθ]×)(^BR^WBδp)^B[δθ]×^BR^WBδp.\begin{aligned} \ell_B &\approx \left(I-[\delta\theta]_\times\right) \left(\hat\ell_B-\hat R_{WB}^{\top}\delta p\right)\\ &\approx \hat\ell_B -[\delta\theta]_\times\hat\ell_B -\hat R_{WB}^{\top}\delta p. \end{aligned}

最后一项中的

[δθ]×R^WBδp[\delta\theta]_\times\hat R_{WB}^{\top}\delta p

包含两个误差量,是二阶项,需要舍去。再使用叉乘交换关系

[δθ]×^B=[^B]×δθ,-[\delta\theta]_\times\hat\ell_B =[\hat\ell_B]_\times\delta\theta,

可得

B^B+[^B]×δθR^WBδp.\boxed{ \ell_B \approx \hat\ell_B +[\hat\ell_B]_\times\delta\theta -\hat R_{WB}^{\top}\delta p. }

因此,IMU 系点坐标的一阶变化为

δB=[^B]×δθR^WBδp.\delta\ell_B =[\hat\ell_B]_\times\delta\theta -\hat R_{WB}^{\top}\delta p.

接着通过固定外参变到相机系:

C=RCBB+tCB^C+RCB[^B]×δθRCBR^WBδp.\begin{aligned} \ell_C &=R_{CB}\ell_B+t_{CB}\\ &\approx \hat\ell_C +R_{CB}[\hat\ell_B]_\times\delta\theta -R_{CB}\hat R_{WB}^{\top}\delta p. \end{aligned}

所以

δC=RCB[^B]×δθRCBR^WBδp.\boxed{ \delta\ell_C =R_{CB}[\hat\ell_B]_\times\delta\theta -R_{CB}\hat R_{WB}^{\top}\delta p. }

先得到这一步很重要。透视投影只是把三维相机点再映射到二维像素;如果坐标变换的 Jacobian 已经写错,后面的投影矩阵再正确也没有用。

8.6.3 再求像素对相机点的导数

对针孔投影

π(C)=[fxXC/ZC+cxfyYC/ZC+cy]\pi(\ell_C)= \begin{bmatrix} f_xX_C/Z_C+c_x\\ f_yY_C/Z_C+c_y \end{bmatrix}

求一阶导数。对第一行分别求 XCX_CYCY_CZCZ_C 的偏导:

uXC=fxZC,uYC=0,uZC=fxXCZC2.\frac{\partial u}{\partial X_C}=\frac{f_x}{Z_C}, \qquad \frac{\partial u}{\partial Y_C}=0, \qquad \frac{\partial u}{\partial Z_C}=-\frac{f_xX_C}{Z_C^2}.

对第二行:

vXC=0,vYC=fyZC,vZC=fyYCZC2.\frac{\partial v}{\partial X_C}=0, \qquad \frac{\partial v}{\partial Y_C}=\frac{f_y}{Z_C}, \qquad \frac{\partial v}{\partial Z_C}=-\frac{f_yY_C}{Z_C^2}.

在名义相机点 ^C=[X^C,Y^C,Z^C]\hat\ell_C=[\hat X_C,\hat Y_C,\hat Z_C]^\top 处,投影 Jacobian 为

Jπ(^C)=[fxZ^C0fxX^CZ^C20fyZ^CfyY^CZ^C2].\boxed{ J_\pi(\hat\ell_C) =\begin{bmatrix} \dfrac{f_x}{\hat Z_C}&0&-\dfrac{f_x\hat X_C}{\hat Z_C^2}\\[6pt] 0&\dfrac{f_y}{\hat Z_C}&-\dfrac{f_y\hat Y_C}{\hat Z_C^2} \end{bmatrix}. }

它是一个 2×32\times3 矩阵,把相机系中的三维点误差转换为像素误差:

δzu=Jπ(^C)δC.\delta z_u =J_\pi(\hat\ell_C)\delta\ell_C.

这里出现的 1/Z^C1/\hat Z_C1/Z^C21/\hat Z_C^2 来自透视除法。点越靠近相机,像素对三维位置变化越敏感;当 Z^C\hat Z_C 接近零时,线性化会变得非常不稳定,这也是投影前必须检查点在相机前方且深度足够的原因。

8.6.4 用链式法则组装 HH

将相机点对误差状态的导数和投影 Jacobian 相乘:

δzu=Jπ(^C)(RCB[^B]×δθRCBR^WBδp)=Jπ(^C)RCB[^B]×δθJπ(^C)RCBR^WBδp.\begin{aligned} \delta z_u &=J_\pi(\hat\ell_C) \left( R_{CB}[\hat\ell_B]_\times\delta\theta -R_{CB}\hat R_{WB}^{\top}\delta p \right)\\ &=J_\pi(\hat\ell_C)R_{CB}[\hat\ell_B]_\times\delta\theta\\ &\quad-J_\pi(\hat\ell_C)R_{CB}\hat R_{WB}^{\top}\delta p. \end{aligned}

因为当前假设下像素观测不直接依赖速度和两个 IMU bias,所以

Hu=[Jπ(^C)RCB[^B]×Jπ(^C)RCBR^WB000].\boxed{ H_u =\begin{bmatrix} J_\pi(\hat\ell_C)R_{CB}[\hat\ell_B]_\times &-J_\pi(\hat\ell_C)R_{CB}\hat R_{WB}^{\top} &0 &0 &0 \end{bmatrix}. }

矩阵尺寸为

HuR2×15.H_u\in\mathbb R^{2\times15}.

将它代回观测残差:

ruHuδx+nu.\boxed{ r_u\approx H_u\delta x+n_u. }

这就是固定路标点的视觉重投影观测 Jacobian。它由两段组成:

JπRCB[^B]×姿态误差到像素误差JπRCBR^WB位置误差到像素误差.\underbrace{J_\pi R_{CB}[\hat\ell_B]_\times}_{\text{姿态误差到像素误差}} \qquad \underbrace{-J_\pi R_{CB}\hat R_{WB}^{\top}}_{\text{位置误差到像素误差}}.

姿态误差先让点在 IMU 系中发生旋转位移,位置误差则先通过 R^WB\hat R_{WB}^{\top} 转到 IMU 系;两者最后都经过外参和针孔投影到像素平面。

8.6.5 为什么没有速度和 bias block

在这个观测时刻,单个图像像素由当前相机位姿和地图点决定。给定位姿不变,速度、陀螺仪 bias、加速度计 bias 不会直接改变当前像素预测,因此 HuH_u 的后三个 block 为零。

这和位置观测的情况相同:HH 中某个 block 为零,只表示当前观测没有直接的一阶敏感性。经过 IMU 传播后,姿态、位置、速度和 bias 之间会形成交叉协方差,视觉残差仍然可以通过

K=PHu(HuPHu+Σu)1K=P^-H_u^\top \left(H_uP^-H_u^\top+\Sigma_u\right)^{-1}

间接修正速度和 bias。

8.6.6 如果地图点也在状态中

上面的 PWP_W 被当作已知地图点。如果地图点也需要估计,真实点写成

PW=P^W+δPW.P_W=\hat P_W+\delta P_W.

B=RWB(PWpW)\ell_B=R_{WB}^{\top}(P_W-p_W)

可得新增的一阶项

δCRCBR^WBδPW.\delta\ell_C \supset R_{CB}\hat R_{WB}^{\top}\delta P_W.

因此,若扩展状态包含地图点,视觉观测 Jacobian 还要增加

HPW=Jπ(^C)RCBR^WB.H_{P_W} =J_\pi(\hat\ell_C)R_{CB}\hat R_{WB}^{\top}.

完整的视觉 SLAM 系统通常还会处理地图点参数化、逆深度、滑动窗口边缘化和相机外参。那些内容会改变状态维度和 Jacobian 的列,但不会改变这里的推导顺序。

8.6.7 相机外参和畸变模型

如果 RCBR_{CB}tCBt_{CB} 也作为状态估计,δC\delta\ell_C 对外参误差的导数需要继续计算,HuH_u 会增加外参对应的列。若相机使用径向畸变或切向畸变,针孔投影 π\pi 应替换为带畸变的投影函数,链式法则仍然是

Hu=πCCδx.H_u =\frac{\partial\pi}{\partial\ell_C} \frac{\partial\ell_C}{\partial\delta x}.

工程实现中可以先用无畸变模型验证坐标和符号,再把畸变 Jacobian 接到投影部分。不要同时改变坐标变换、外参方向和畸变公式,否则很难判断误差来自哪一层。

8.6.8 重投影误差中最容易错的三个符号

第一,世界点到 IMU 系使用的是

RWB(PWpW),R_{WB}^{\top}(P_W-p_W),

不是 RWB(PWpW)R_{WB}(P_W-p_W)。第二,右侧姿态扰动产生

δB=[^B]×δθR^WBδp.\delta\ell_B =[\hat\ell_B]_\times\delta\theta -\hat R_{WB}^{\top}\delta p.

第三,本文残差是实际像素减预测像素。如果代码使用预测减实际,整个 HuH_u 也要取反。把这三个地方逐一写在纸上,通常比直接检查最终的 2×152\times15 矩阵更容易发现问题。

9. 这些例子可以归纳成一个写 HH 的流程

面对一个新观测,可以按下面的顺序操作。

第一步:写出物理观测模型

先不要考虑 Kalman Filter,直接写传感器理想情况下应该读到什么:

z=h(X)+n.z=h(\mathcal X)+n.

例如:

如果这一步的坐标系或符号没有说清楚,后面很难得到可靠的 Jacobian。

第二步:写出预测观测和残差

用预测名义状态计算

z^=h(X^),\hat z=h(\hat{\mathcal X}^-),

再固定残差方向

r=zz^.r=z-\hat z.

姿态等流形观测需要选择合适的 \boxminus,不能强行使用普通减法。

第三步:把真实状态替换成名义状态加误差

统一代入

R=R^Exp([δθ]×),p=p^+δp,v=v^+δv,bg=b^g+δbg,ba=b^a+δba.\begin{aligned} R&=\hat R\operatorname{Exp}([\delta\theta]_\times),\\ p&=\hat p+\delta p,\\ v&=\hat v+\delta v,\\ b_g&=\hat b_g+\delta b_g,\\ b_a&=\hat b_a+\delta b_a. \end{aligned}

对旋转至少记住两条一阶公式:

Exp([δθ]×)I+[δθ]×,\operatorname{Exp}([\delta\theta]_\times) \approx I+[\delta\theta]_\times,Exp([δθ]×)xx+[x]×δθ.\operatorname{Exp}(-[\delta\theta]_\times)x \approx x+[x]_\times\delta\theta.

第四步:只保留误差的一阶项

展开后,保留只含一个误差量的项,舍去

δθδp,δθδba,δθ2\delta\theta\,\delta p, \quad \delta\theta\,\delta b_a, \quad \delta\theta^2

等二阶项。

第五步:按状态排列组装 block

最后把残差写成

rHθδθ+Hpδp+Hvδv+Hbgδbg+Hbaδba+n.r\approx H_\theta\delta\theta +H_p\delta p +H_v\delta v +H_{b_g}\delta b_g +H_{b_a}\delta b_a+n.

将五个 block 横向拼接,才得到完整的 HH。很多代码中的 bug 不是导数算错,而是 block 顺序和协方差的状态顺序不一致。

9.1 视觉重投影误差完整走一遍流程

视觉重投影误差可以把上面的五步完整串起来。假设世界系地图点 PWP_W 已知,相机内参和 IMU-相机外参也已知,状态中暂时不估计地图点和外参。

9.1.1 写观测模型、预测观测和残差

世界点先从世界系变到 IMU 系,再变到相机系:

B=RWB(PWpW),\ell_B=R_{WB}^{\top}(P_W-p_W),C=RCBB+tCB.\ell_C=R_{CB}\ell_B+t_{CB}.

C=[XCYCZC],\ell_C= \begin{bmatrix} X_C\\Y_C\\Z_C \end{bmatrix},

理想针孔投影为

π(C)=[fxXC/ZC+cxfyYC/ZC+cy].\pi(\ell_C)= \begin{bmatrix} f_xX_C/Z_C+c_x\\ f_yY_C/Z_C+c_y \end{bmatrix}.

因此观测模型是

zu=π(C)+nu.z_u=\pi(\ell_C)+n_u.

用预测名义状态计算

^B=R^WB(PWp^W),\hat\ell_B=\hat R_{WB}^{\top}(P_W-\hat p_W),^C=RCB^B+tCB,z^u=π(^C),\hat\ell_C=R_{CB}\hat\ell_B+t_{CB}, \qquad \hat z_u=\pi(\hat\ell_C),

并采用实际像素减预测像素的残差:

ru=zuz^u.r_u=z_u-\hat z_u.

9.1.2 代入误差状态并展开坐标变换

按照本文的右侧姿态误差和加性位置误差:

RWB=R^WBExp([δθ]×),pW=p^W+δp.R_{WB}=\hat R_{WB}\operatorname{Exp}([\delta\theta]_\times), \qquad p_W=\hat p_W+\delta p.

真实的 IMU 系点坐标为

B=RWB(PWpW)=Exp([δθ]×)R^WB(PWp^Wδp)=Exp([δθ]×)(^BR^WBδp).\begin{aligned} \ell_B &=R_{WB}^{\top}(P_W-p_W)\\ &=\operatorname{Exp}(-[\delta\theta]_\times) \hat R_{WB}^{\top}(P_W-\hat p_W-\delta p)\\ &=\operatorname{Exp}(-[\delta\theta]_\times) \left(\hat\ell_B-\hat R_{WB}^{\top}\delta p\right). \end{aligned}

使用

Exp([δθ]×)I[δθ]×\operatorname{Exp}(-[\delta\theta]_\times) \approx I-[\delta\theta]_\times

并舍去姿态误差与位置误差的乘积,得到

B^B[δθ]×^BR^WBδp=^B+[^B]×δθR^WBδp.\begin{aligned} \ell_B &\approx \hat\ell_B -[\delta\theta]_\times\hat\ell_B -\hat R_{WB}^{\top}\delta p\\ &=\hat\ell_B +[\hat\ell_B]_\times\delta\theta -\hat R_{WB}^{\top}\delta p. \end{aligned}

经过固定外参变换:

δC=C^C=RCB[^B]×δθRCBR^WBδp.\begin{aligned} \delta\ell_C &=\ell_C-\hat\ell_C\\ &=R_{CB}[\hat\ell_B]_\times\delta\theta -R_{CB}\hat R_{WB}^{\top}\delta p. \end{aligned}

这一步给出三维相机点对误差状态的 Jacobian:

Cδx=[RCB[^B]×RCBR^WB000].\frac{\partial\ell_C}{\partial\delta x} =\begin{bmatrix} R_{CB}[\hat\ell_B]_\times &-R_{CB}\hat R_{WB}^{\top} &0&0&0 \end{bmatrix}.

9.1.3 展开透视投影并用链式法则组装

针孔投影对相机点的 Jacobian 为

Jπ(^C)=[fxZ^C0fxX^CZ^C20fyZ^CfyY^CZ^C2].J_\pi(\hat\ell_C) =\begin{bmatrix} \dfrac{f_x}{\hat Z_C}&0&-\dfrac{f_x\hat X_C}{\hat Z_C^2}\\[6pt] 0&\dfrac{f_y}{\hat Z_C}&-\dfrac{f_y\hat Y_C}{\hat Z_C^2} \end{bmatrix}.

于是像素误差的一阶项为

δzu=Jπ(^C)δC=Jπ(^C)RCB[^B]×δθJπ(^C)RCBR^WBδp.\begin{aligned} \delta z_u &=J_\pi(\hat\ell_C)\delta\ell_C\\ &=J_\pi(\hat\ell_C)R_{CB}[\hat\ell_B]_\times\delta\theta -J_\pi(\hat\ell_C)R_{CB}\hat R_{WB}^{\top}\delta p. \end{aligned}

因此,按

δx=[δθδpδvδbgδba]\delta x= \begin{bmatrix} \delta\theta\\\delta p\\\delta v\\\delta b_g\\\delta b_a \end{bmatrix}

排列,视觉重投影观测的 Jacobian 为

Hu=[Jπ(^C)RCB[^B]×Jπ(^C)RCBR^WB000].\boxed{ H_u=\begin{bmatrix} J_\pi(\hat\ell_C)R_{CB}[\hat\ell_B]_\times &-J_\pi(\hat\ell_C)R_{CB}\hat R_{WB}^{\top} &0&0&0 \end{bmatrix}. }

因此,视觉残差的线性化形式为

ruHuδx+nu.r_u\approx H_u\delta x+n_u.

它是一个 2×152\times15 矩阵。这里的两个非零 block 分别来自:姿态误差改变世界点在 IMU 系中的方向,位置误差改变世界点相对 IMU 原点的位置;JπJ_\pi 再把三维相机点变化映射为二维像素变化。

如果地图点也在状态中,只需继续对

C=RCBRWB(PWpW)+tCB\ell_C=R_{CB}R_{WB}^{\top}(P_W-p_W)+t_{CB}

δPW\delta P_W 求导,并在 HuH_u 后面增加对应的地图点 block:

HPW=Jπ(^C)RCBR^WB.H_{P_W}=J_\pi(\hat\ell_C)R_{CB}\hat R_{WB}^{\top}.

相机外参或畸变参数进入状态时,也沿着同一条链式法则继续增加对应 block。由此可见,复杂观测并没有改变写 HH 的流程,只是中间函数更多:坐标变换、姿态扰动、透视投影和可能的畸变函数依次求导,再按状态顺序拼接。

10. 观测更新之后:误差注入和 reset

10.1 先更新局部误差

使用残差和 HH 得到

δx^=Kr.\delta\hat x=Kr.

把它展开为

δx^=[δθ^δp^δv^δb^gδb^a].\delta\hat x= \begin{bmatrix} \delta\hat\theta\\ \delta\hat p\\ \delta\hat v\\ \delta\hat b_g\\ \delta\hat b_a \end{bmatrix}.

这些量仍然属于预测名义状态附近的局部坐标。

10.2 注入名义状态

对于右侧姿态误差,姿态注入为

R^+=R^Exp([δθ^]×).\hat R^+ =\hat R^- \operatorname{Exp}([\delta\hat\theta]_\times).

其余状态直接相加:

p^+=p^+δp^,v^+=v^+δv^,b^g+=b^g+δb^g,b^a+=b^a+δb^a.\begin{aligned} \hat p^+&=\hat p^-+\delta\hat p,\\ \hat v^+&=\hat v^-+\delta\hat v,\\ \hat b_g^+&=\hat b_g^-+\delta\hat b_g,\\ \hat b_a^+&=\hat b_a^-+\delta\hat b_a. \end{aligned}

不能把 HH 的某一行直接加到状态,也不能把旋转的三维误差直接和旋转矩阵相加。HH 是灵敏度矩阵,δx^\delta\hat x 才是需要注入的局部修正。

10.3 为什么还需要 reset

误差注入后,名义状态已经移动。误差状态的零点也随之改变。对加性状态,一阶近似下有

δxnewδxoldδx^.\delta x_{\mathrm{new}} \approx \delta x_{\mathrm{old}}-\delta\hat x.

姿态则需要使用旋转复合:

Exp([δθnew]×)=Exp([δθ^]×)Exp([δθold]×).\operatorname{Exp}([\delta\theta_{\mathrm{new}}]_\times) = \operatorname{Exp}(-[\delta\hat\theta]_\times) \operatorname{Exp}([\delta\theta_{\mathrm{old}}]_\times).

因此

δθnew=Log(Exp([δθ^]×)Exp([δθold]×)).\delta\theta_{\mathrm{new}} =\operatorname{Log}\left( \operatorname{Exp}(-[\delta\hat\theta]_\times) \operatorname{Exp}([\delta\theta_{\mathrm{old}}]_\times) \right)^\vee.

对小角度,常见的一阶近似是

δθnewδθoldδθ^.\delta\theta_{\mathrm{new}} \approx \delta\theta_{\mathrm{old}}-\delta\hat\theta.

10.4 协方差也要换坐标

Kalman 更新得到的协方差通常对应注入前的误差坐标,记为 P~+\widetilde P^+。reset 后的新误差坐标需要通过 reset Jacobian 转换:

P+=JresetP~+Jreset.\boxed{ P^+=J_{\mathrm{reset}}\widetilde P^+J_{\mathrm{reset}}^\top. }

对普通加性状态,相关 Jacobian 常近似为单位矩阵;旋转部分则取决于误差定义、注入方式和采用的近似阶数。不能因为当前的 δθ^\delta\hat\theta 很小,就默认所有实现中的 reset 都可以完全省略。

这一步和 HH 有直接关系:下一次观测更新的 HH 是在新的名义状态和新的误差坐标附近重新计算的。如果注入了状态却没有同步转换协方差,PPHH 描述的就不是同一个局部坐标系统。

11. 用三个数值检查发现大多数符号错误

推导完成后,不妨用有限差分检查 HH。这比盯着一长串叉乘矩阵更可靠。

11.1 有限差分检查

对误差状态的第 jj 个方向取一个很小的 ϵ\epsilon,构造单位向量 eje_j。分别计算

h+=h(X^ϵej),h=h(X^(ϵej)).h_+=h(\hat{\mathcal X}\boxplus\epsilon e_j), \qquad h_-=h(\hat{\mathcal X}\boxplus(-\epsilon e_j)).

则数值 Jacobian 的第 jj 列可以近似为

H:,jnumh+h2ϵ.H_{:,j}^{\mathrm{num}} \approx \frac{h_+-h_-}{2\epsilon}.

姿态观测不能直接对旋转矩阵做减法。需要先把两个预测观测转换为同一个观测残差坐标,再做中心差分。对于普通向量观测,上式可以直接使用。

比较解析 Jacobian 和数值 Jacobian:

HanalyticHnum\lVert H^{\mathrm{analytic}}-H^{\mathrm{num}}\rVert

应该在合理的数值误差范围内较小。ϵ\epsilon 太大时会混入高阶项,太小时又会受到浮点误差影响,可以测试一组不同量级的 ϵ\epsilon

11.2 重力观测的 yaw 检查

对于纯重力向量观测,应该满足

[g^B]×g^B=0.[\hat g_B]_\times\hat g_B=0.

如果代码声称重力观测能够约束绕重力方向的旋转,通常说明观测模型或可观性判断出了问题。

11.3 点到平面的切向检查

对平面内切向量 tWt_W,应该有

nWtW=0.n_W^\top t_W=0.

因此点到平面观测对沿平面切向平移的一阶 Jacobian 为零。这个检查可以快速发现法向量是否被错误地转到了别的坐标系,或者点到平面的残差符号是否混乱。

11.4 维度和单位检查

每次构造观测 Jacobian 时至少检查:

  1. HH 是否为 m×15m\times15
  2. 残差维度是否为 mm
  3. Σz\Sigma_z 是否为 m×mm\times m
  4. S=HPH+ΣzS=HP^-H^\top+\Sigma_z 是否为 m×mm\times m
  5. 残差的单位是否和观测噪声协方差一致。

例如,点到平面残差是米,姿态残差是弧度,不能把它们混在一个残差向量中却不给出相应的噪声尺度。

12. 最容易混淆的几件事

12.1 把 HH 当成状态转移矩阵

FF 描述时间传播,HH 描述当前观测。FF 通常是 15×1515\times15HH 的行数取决于观测维度。二者都叫 Jacobian,但物理含义不同。

12.2 只看观测名称,不看输出坐标系

“速度观测”可能是世界系速度,也可能是机体系前向速度;“位置观测”可能是 IMU 原点,也可能是相机或 LiDAR 原点。传感器名称不能替代观测模型。

12.3 对旋转做普通减法

姿态残差应先构造相对旋转,再通过 Log\operatorname{Log} 映射到局部三维坐标。使用哪一边乘逆、噪声放在哪一侧,都必须和姿态误差定义一致。

12.4 把静止加速度计读数当成重力加速度

加速度计测量的是比力。按照本文模型,静止时理想读数为

RWBgW+ba,-R_{WB}^{\top}g_W+b_a,

而不是 RWBgWR_{WB}^{\top}g_W。符号取决于世界系重力向量和加速度计测量定义,但不能不看模型就套用“加速度计指向重力”的口头说法。

12.5 忘记 bias 是否在观测模型中出现

纯位置观测的 HH 没有 bias block;静止加速度计观测的 HHHba=IH_{b_a}=I。一个 bias 是否可观,不是由它“属于 IMU”决定的,而是由当前观测模型、运动激励和协方差相关性共同决定的。

12.6 用错误的残差方向,却只修改一处

如果残差从 zz^z-\hat z 改为 z^z\hat z-zHH、噪声符号以及后续修正方向必须一起检查。只在代码里对残差加一个负号,通常会留下一个隐蔽的系统性错误。

12.7 忘记 reset 协方差

误差注入改变了姿态误差的切空间。只更新名义状态、不转换 PP,会让下一轮的协方差和误差定义不匹配。小角度系统可能一段时间内看不出问题,但长期运行时会出现不稳定或一致性变差。

13. 把一轮观测更新串起来

现在可以把 ESKF 的观测阶段完整写出来。

第一步:IMU 传播到观测时刻

上一篇得到的 FFGG 用于传播预测协方差:

PΦP+Φ+Qd.P^-\approx\Phi P^+\Phi^\top+Q_d.

同时,名义状态按照非线性 IMU 方程传播到 X^\hat{\mathcal X}^-

第二步:根据当前传感器写 hh

例如位置观测:

hp(X^)=p^.h_p(\hat{\mathcal X}^-)=\hat p^-.

点到平面观测:

hπ(X^)=nW(p^+R^qB).h_\pi(\hat{\mathcal X}^-) =n_W^\top(\hat p^-+\hat R^-q_B).

第三步:计算残差和 HH

r=zh(X^),r=z-h(\hat{\mathcal X}^-),H=h(X^δx)δx0.H=\left. \frac{\partial h(\hat{\mathcal X}^-\boxplus\delta x)} {\partial\delta x} \right|_0.

HH 必须在当前预测名义状态处重新计算。姿态、点坐标、法向量和外参的当前值都会进入 Jacobian。

第四步:更新误差状态

S=HPH+Σz,S=HP^-H^\top+\Sigma_z,K=PHS1,K=P^-H^\top S^{-1},δx^=Kr.\delta\hat x=Kr.

第五步:注入并 reset

X^+=X^δx^,\hat{\mathcal X}^+=\hat{\mathcal X}^-\boxplus\delta\hat x,

再把注入前的后验协方差转换到新的误差坐标:

P+=JresetP~+Jreset.P^+=J_{\mathrm{reset}}\widetilde P^+J_{\mathrm{reset}}^\top.

这样,下一次 IMU 到来时,新的名义状态和新的协方差正好位于同一个局部坐标约定下。

14. 从一条新观测到一块正确的 HH

本文最值得留下的不是某个单独的矩阵,而是下面这条推导路线:

  1. 明确状态和所有坐标系的方向;
  2. 写出理想观测模型 z=h(X)+nz=h(\mathcal X)+n
  3. 用预测名义状态计算 z^=h(X^)\hat z=h(\hat{\mathcal X}^-)
  4. 选定残差方向,例如 r=zz^r=z-\hat z
  5. R=R^Exp([δθ]×)R=\hat R\operatorname{Exp}([\delta\theta]_\times) 和其他加性误差代入 hh
  6. 舍去二阶小量,保留误差的一阶项;
  7. [δθ,δp,δv,δbg,δba][\delta\theta,\delta p,\delta v,\delta b_g,\delta b_a] 拼出 HH
  8. 用有限差分、秩和几何退化检查结果;
  9. 更新局部误差,注入名义状态,再 reset 协方差。

位置观测给出

Hp=[0I000],H_p=\begin{bmatrix}0&I&0&0&0\end{bmatrix},

世界系速度观测给出

Hv=[00I00],H_v=\begin{bmatrix}0&0&I&0&0\end{bmatrix},

纯重力向量观测给出

Hg=[[g^B]×0000],H_g=\begin{bmatrix}[\hat g_B]_\times&0&0&0&0\end{bmatrix},

静止加速度计比力观测给出

Ha=[[g^B]×000I],H_a=\begin{bmatrix}-[\hat g_B]_\times&0&0&0&I\end{bmatrix},

点到平面观测给出

Hπ=[nWR^WB[qB]×nW000].H_\pi= \begin{bmatrix} -n_W^\top\hat R_{WB}[q_B]_\times &n_W^\top &0&0&0 \end{bmatrix}.

这些矩阵的形式看起来不同,但来源完全相同:先让误差状态改变预测观测,再读取预测观测的一阶变化。

下一步如果继续写 ESKF 系列,可以在这套观测 Jacobian 的基础上推导具体的视觉重投影误差,或者把 LiDAR 的点到平面观测扩展到 IESKF 的迭代更新。无论观测来自相机还是 LiDAR,先把观测模型和误差坐标写清楚,后面的矩阵就不会只剩下记忆。

参考文章

  1. ESKF 误差动力学推导:从 IMU 模型到 FFGG
  2. Joan Solà, Quaternion kinematics for the error-state Kalman filter, arXiv:1711.02508, 2017. https://arxiv.org/abs/1711.02508
  3. Joan Solà, Jérémie Deray, and Dinesh Atchuthan, A micro Lie theory for state estimation in robotics, arXiv:1812.01537, 2018. https://arxiv.org/abs/1812.01537
  4. Wei Xu, Yixi Cai, Dongjiao He, Jiarong Lin, and Fu Zhang, FAST-LIO2: Fast Direct LiDAR-inertial Odometry, IEEE Transactions on Robotics, 38(4):2053–2070, 2022. https://arxiv.org/abs/2107.06829