尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

从高斯分布到协方差矩阵:RoboMaster电控卡尔曼滤波概率基础

从高斯分布到协方差矩阵:RoboMaster电控卡尔曼滤波概率基础 在RoboMaster电控这个圈子里卡尔曼滤波几乎是一个绕不过去的坎。你去看任何一支强队的开源代码从云台的自稳解算到底盘的里程计融合从视觉的目标预测到能量机关的时序估计背后多多少少都压着一层卡尔曼或者它的变种。可很多刚进队的朋友一上手就懵了代码能抄参数能试但心里始终没底——为什么P矩阵是这么更新的为什么Q和R调大调小会带来完全相反的收敛表现为什么状态量多了以后协方差矩阵会“跑飞”说到底这些问题都不是编程问题而是概率统计基础没打牢。这篇内容我想换个角度聊不急着上卡尔曼的五大公式而是把前面那块最容易被跳过的地基——概率统计基础——单独拎出来讲透。它适合刚接触RM电控、准备啃卡尔曼的在校同学也适合代码能跑但说不清的“调参型选手”。我会从为什么RM里必须引入概率、随机变量和高斯分布怎么用、协方差矩阵到底是什么玩意儿、条件概率怎么导向贝叶斯思想这几条线讲下来中间穿插能直接跑的最小例子和我在实机上踩过的坑。读完你未必立刻写出卡尔曼但再看那些公式时至少知道每一行在“替谁说话”。顺带提一句搜索热词里冒出来的“rm -rf”是Linux里的删除命令跟RoboMaster的缩写RM完全不是一回事别在查资料的时候把自己带偏了至于“中科大RM电控合集”里提到概率统计前瞻也正是因为圈内普遍发现跳过这块直接上算法最后基本都要回头补课。1. 为什么搞RM电控绕不开概率统计1.1 从一次云台抖动说起确定性思维顶到哪里我刚进队那年写代码的思路特别“物理”陀螺仪给你角速度我乘个dt积分就是角度编码器给你转速我乘个轮径就是位移。这套确定性思维在理想世界里没毛病可一上真机就原形毕露。云台在静止的时候角度会缓慢漂移底盘跑一圈回到原点坐标却对不上视觉框住的装甲板一到快速机动就会“拖影”然后丢目标。你盯着数据看半天会发现传感器读数从来不是一条干净曲线它永远在一个值附近“毛茸茸”地抖。这时候如果还抱着“传感器应该给我真值”的执念你就会陷入疯狂加滤波器的死循环——均值滤波、中值滤波、一阶低通一个接一个往上堆结果要么延迟大到云台跟不上手要么滤完还是抖。问题的根源在于传感器的输出本质上是一个随机过程不是一个确定函数。加速度计有零偏噪声陀螺仪有角度随机游走编码器有量化误差视觉有像素级抖动。你没法用一个确定的公式去“抵消”随机性只能去描述它、估计它。概率统计就是干这件事的语言。所以RM电控里引入概率统计不是数学老师硬塞的课外拓展而是当你的系统里同时存在“不确定的观测”和“不确定的模型”时唯一能自洽处理的手段。你承认噪声存在才有可能最优地利用它你假装噪声不存在就只能靠手感和玄学调参。1.2 卡尔曼滤波在RM的战车上到底管哪几摊事把话说具体点卡尔曼滤波及其实用变体在RM赛场上至少承担四类核心任务理解了这四类任务你就知道概率统计基础要铺在哪。第一类是姿态解算。陀螺仪积分短期准、长期漂加速度计测量长期稳、短期被振动污染两者融合出稳定姿态角这是卡尔曼最经典的舞台状态量通常是角度和角速度零偏。第二类是目标跟踪与预测。视觉给出装甲板的像素坐标和距离帧率可能只有几十赫兹还有延迟卡尔曼把位置、速度甚至加速度作为状态既平滑观测又外推出“未来几十毫秒目标会在哪”让云台提前量打得准。这就是所谓“前瞻”的一部分。第三类是里程计融合。底盘用编码器推算位移但打滑、轮径误差、地面摩擦都会让它偏融合一个IMU或者激光测距就能把轨迹拉回来典型如扩展卡尔曼的里程计模型。第四类是能量机关与时序估计。打符时叶片转速有规律但测量受反光干扰用滤波器估计相位和角速度能让击打更稳。这四类任务有个共同点都存在“过程有噪声、观测也有噪声”的双不确定性。而概率统计正是把这两种噪声统一到同一个数学框架里进行比较和加权的工具。谁的噪声小、谁的置信度高滤波器就更多听谁的这就是它比单一低通高级的地方。1.3 概率统计这块地基到底要铺多厚很多人一看到“概率统计”四个字就头皮发麻觉得要把整本教材啃完。其实针对RM电控方向你真正需要吃透的也就那么几块随机变量与其分布、期望与方差、高斯分布的性质、协方差与协方差矩阵、条件概率与贝叶斯公式、以及最小二乘与递推估计的直觉。这几块串起来刚好构成通向卡尔曼滤波的一条最短路径。我个人的建议是分三个阶段。第一阶段把直觉建起来能对着传感器数据说清“均值是什么、方差在描述什么”第二阶段把多变量的语言拿下理解协方差矩阵为什么能同时表达“每个量的不确定度”和“量与量之间的关联”这是卡尔曼里P矩阵的本体第三阶段理解贝叶斯递推明白“预测—更新”这两个动作本质上是在不断用新证据修正信念。做完这三步你再回看卡尔曼的状态方程和观测方程会发现它们不过是把这三件事写成了矩阵形式。这里我要强调一个我踩过的坑别指望一次学到位。我当初硬啃公式推导每个符号都认识但连不成画面调参照样靠蒙。后来我反过来先把滑动平均、低通滤波这些“土办法”写出来跑通亲眼看到它们各自的短板再回头看卡尔曼为什么能补上这些短板理解速度一下快了很多。概率统计基础不是背定义而是要让你在数据面前产生一种“我知道它为什么这样抖”的直觉。2. 随机变量与高斯分布把“不确定”算成数2.1 随机变量从掷骰子到陀螺仪读数随机变量的定义看起来抽象——把随机试验的结果映射成一个数。放到RM场景里就特别好理解你在云台静止时连续采样陀螺仪的角速度每一次采样的结果都是一个“随机试验”而它输出的那个浮点数就是随机变量的一次取值。离散的场合像掷骰子结果只有六种连续的场合像陀螺仪噪声理论上可以取到某区间内任意实数。区分离散和连续很重要因为它们的描述工具不同。离散用概率质量函数比如掷出每个点的概率都是六分之一连续用概率密度函数单个点的概率为零有意义的是“落在某个区间内的概率”也就是密度函数在那段区间下的面积。陀螺仪的噪声通常被建模成连续型随机变量我们关心的不是“它恰好等于0.0132的概率”而是“它落在±0.01范围内的概率有多大”。我特别建议初学者做一件小事拿一块RM常用的IMU静止平放录三到五分钟原始数据用Python或者Matlab画个直方图再叠加一条理论高斯曲线。你会直观看到两件事——噪声确实是随机散布的且往往以零偏为中心、两边对称衰减。这个亲手画图的过程比看十页公式都管用它把你脑子里的“噪声”从一个模糊概念变成了一个有形状、有参数的实体。import numpy as np import matplotlib.pyplot as plt # 假设gyro_data是静止采集的陀螺仪角速度序列单位deg/s gyro_data np.loadtxt(gyro_static.csv) mu gyro_data.mean() sigma gyro_data.std() plt.hist(gyro_data, bins60, densityTrue, alpha0.6, label实测分布) x np.linspace(mu - 4*sigma, mu 4*sigma, 400) plt.plot(x, 1/(sigma*np.sqrt(2*np.pi))*np.exp(-(x-mu)**2/(2*sigma**2)), r, label拟合高斯) plt.legend() plt.xlabel(角速度 deg/s) plt.show()2.2 高斯分布凭什么当主角翻遍RM电控的开源代码只要涉及滤波的噪声建模九个里有九个用的是高斯分布。这不是偷懒而是有充分理由的。首先大量独立的微小扰动叠加在一起其和的分布会趋近高斯——这就是中心极限定理的直观含义。陀螺仪的噪声往往是无数微小热噪声、量化误差、机械振动叠加的结果天然接近高斯。其次高斯分布只需要均值和方差两个参数就能完全确定形状数学上极其友好许多积分能求出闭式解。第三高斯分布在加法、线性变换下依然保持高斯也就是“高斯进、高斯出”这让卡尔曼能在每一帧都用最简单的两个矩——均值和方差——来描述整个信念状态。这三点合起来造就了卡尔曼滤波的核心前提过程和观测都用高斯近似。你在调参时填进Q和R的本质上就是给过程和观测各设定一个高斯分布方差越大表示“越不确定”。所以当你把R调大等于对视觉观测说“我不太信你”自然就更依赖模型预测反过来把Q调大等于对模型说“我对自己也没底”自然就更多听观测的。理解了这层调参就不再是玄学试数而是有物理意义地“分配信任”。2.3 期望与方差描述噪声的两个核心量期望描述分布的中心位置对于陀螺仪噪声就是零偏你可以在标定时减掉它方差描述分布的离散程度就是噪声的“能量”它决定了滤波器该给这个传感器多大的信任权重。这两个量是概率统计里最重要的两个数字特征也是卡尔曼里反复出现的源头。有个细节值得单独说方差开根号就是标准差量纲和原变量一致所以看数据时我更习惯看标准差。比如某陀螺仪标称噪声密度0.01 deg/s/√Hz采样率1kHz时单次采样的标准差大致要按带宽折算不能直接把密度当标准差用。这类量纲和单位的换算是新手最容易翻车的地方我在3.3节和6节的排查表里还会专门列出来。另外期望和方差都是对“分布”而言的统计量需要大量样本才能估计准。实机上如果你只采几百个点估出来的方差波动会很大进而影响Q、R的初值。我的经验是静止标定至少采一到两万点去掉明显的异常值后再算否则滤波器初值就带着偏差出生后面很难收敛好。3. 协方差与协方差矩阵多维噪声的关联语言3.1 协方差到底在描述什么如果系统里只有一个随机变量方差就够了。但RM里的状态几乎都是多个量打包的姿态解算里同时有角度和角速度零偏目标跟踪里同时有位置和速度。这时候除了各自的方差还要关心它们之间的关联程度这就是协方差。协方差的定义是两个随机变量各自减去期望后的乘积的期望正值表示“一个变大时另一个倾向变大”负值表示反向接近零表示基本无关。拿姿态解算举例角度估计偏高的时候角速度零偏估计往往也偏高两者正相关而速度和位置之间在现代控制里也常呈现相关性。协方差捕捉的正是这种“牵一发而动全身”的关联。如果忽略它滤波器就会把本来关联的状态当成彼此独立来更新结果就是收敛变慢甚至震荡。这解释了为什么状态量取多了以后协方差矩阵不能随便设为单位阵对角。3.2 协方差矩阵为什么是卡尔曼的P多个随机变量两两求协方差排成一个方阵就是协方差矩阵。它的对角线元素是各个变量的方差非对角元素是两两的协方差。这个矩阵对称且半正定物理含义是“在当前信念下每个状态有多不确定以及它们如何一起变化”。卡尔曼滤波里的P矩阵就是这个协方差矩阵它随着“预测—更新”循环不断被更新记录着滤波器对整个状态估计的置信度。理解P的演化是理解卡尔曼的关键。预测步骤里P会因为过程噪声Q而“膨胀”意思是随着时间推进、没有新观测我们对状态的把握变差更新步骤里P会因为观测而“收缩”意思是有新信息进来不确定性减小。你看整个卡尔曼不过是让这个“不确定度的账本”一涨一缩地滚动。所谓滤波收敛本质就是P趋于稳定账本收支平衡。3.3 独立性假设与矩阵对角化那些事工程实践中我们经常假设噪声各分量相互独立也就是协方差矩阵是对角阵。这个假设让计算简化很多但也埋着隐患——真实噪声常常是相关的。我踩过一次坑底盘里程计融合时我图省事把过程噪声设成对角结果横摆角速度和横向位移的估计出现耦合偏差转弯时轨迹明显外甩。后来在Q里补上横向与横摆的相关项轨迹才贴合。所以对角阵是起点不是终点。除此之外还要注意协方差矩阵的数值健康长时间运行后由于浮点误差和持续的加减操作P可能失去对称性甚至变成非正定导致滤波器发散。我在嵌入式端通常做两件小事保护它——每次更新后强制对称化取P和P转置的平均必要时加一个极小的对角修正保持正定。这些技巧在后面问题排查部分会更详细说。概念在卡尔曼中的对应在RM里的直观含义方差Q、R的对角元素、P的对角单个状态或观测的不确定度协方差P和Q、R的非对角元素状态量之间的关联程度协方差矩阵P、Q、R本身整体“不确定度账本”正定性滤波稳定的前提账本不能出现“负的不确定度”4. 条件概率与贝叶斯卡尔曼的思想内核4.1 条件概率已知部分信息后如何更新判断条件概率描述的是“在事件B已经发生的条件下事件A发生的概率”。放RM里它回答的问题是我已经观测到传感器这一帧的读数那么此刻系统真实状态是多少这恰恰是滤波每一步都在解的问题。观测前我有一个先验判断观测后我结合证据得到一个后验判断这个“用证据修正判断”的过程就是贝叶斯思想的骨架。举个特别接地气的例子。假设你看到云台角度读数偏了3度你真的相信状态偏了3度吗不一定。如果这个传感器的方差小、你信任它你就信如果它平时就爱抖你就会打折接受更多地维持上一帧的预测。条件概率和贝叶斯公式正是把这套“打折接受”的直觉变成可以计算的东西。4.2 从贝叶斯递推到卡尔曼的两步舞标准贝叶斯公式把后验正比于似然乘先验。放到连续状态、高斯假设下这一过程有两个自然的动作一是根据系统模型把上一时刻的信念往前推得到先验——这叫预测二是用当前观测修正先验得到后验——这叫更新。卡尔曼的“预测—更新”两步就是贝叶斯递推在高斯和线性条件下唯一确定的结果。理解了这一点你就能回答一个常见疑问为什么卡尔曼的更新里要算卡尔曼增益KK其实就是在“信模型”和“信观测”之间做最优配比的比例系数它由先验协方差P和观测噪声R共同决定。观测噪声越小K越大越偏向观测先验不确定度越大K也越大同样越偏向观测。这跟贝叶斯“证据强就多改信念”的逻辑完全一致只不过被写成了矩阵运算。4.3 高斯假设下的闭式解为什么这么优雅在人眼看来贝叶斯更新一般是需要求积分、算归一化常数的麻烦事。但当先验和似然都是高斯时后验仍然是高斯而且均值和方差有闭式解。这意味着卡尔曼每一帧只需要几次矩阵乘法加求逆计算量在STM32这类MCU上也能承受。这就是为什么RM电控特别偏爱高斯的深层原因——它把连续的贝叶斯推理压缩成了可以实时执行的代数运算。但优雅是有代价的。现实中系统可能非线性比如姿态解算涉及三角函数此时高斯假设下模型变换后不再是严格高斯就要退而求其次用扩展卡尔曼或者无迹卡尔曼做近似。这不是说概率统计基础没用了恰恰相反非线性滤波的起点仍然是这套“用高斯刻画信念、用贝叶斯更新信念”的思路只是把线性变换换成了局部近似。5. 实操打底先用滑动平均和低通把直觉跑出来5.1 手写滑动平均与一阶低通真正上手前我强烈建议先亲手写两个“土滤波器”不是为了用它们而是为了建立对噪声和滤波的体感。滑动平均是取最近N个采样求平均实现简单能明显压掉高频抖动代价是引入约N/2个采样周期的延迟。一阶低通则是指数加权新值权重alpha旧滤波值权重1−alpha计算量极小嵌入式里特别常用。// 一阶低通滤波alpha∈(0,1)越大越信新值 float low_pass(float new_val, float last_val, float alpha) { return alpha * new_val (1.0f - alpha) * last_val; } // 滑动平均窗口长度N的环形缓冲sum保存当前窗口和 #define N 8 float buf[N]; int idx 0; float sum 0.0f; float moving_average(float new_val) { sum - buf[idx]; buf[idx] new_val; sum new_val; idx (idx 1) % N; return sum / N; }把这两段代码烧进板子对着陀螺仪角度跑一跑你会亲身体会到alpha越小越平滑但越迟钝N越大越平滑但相位滞后越明显。这就是经典的“平滑与延迟不可兼得”。而卡尔曼的聪明之处在于它不是一个固定权重的滤波器它会根据当前不确定度动态调整对观测和模型的信任机动时更信观测、平稳时更信模型这正是它相对固定低通的根本优势。5.2 固定权重不够用卡尔曼赢在哪低通和滑动平均的问题在于权重固定。你设成一个折中值就意味着在静止和快速机动两种极端工况下都只能用同一个权重顾此失彼。而卡尔曼的增益是时变的它随P和R自动伸缩。当系统快速机动、过程噪声相对凸显时预测不确定度P增大增益K增大滤波器更信观测跟得就快当系统平稳时P收缩增益减小滤波器更信模型输出就平滑。这个“自适应信任分配”是我认为卡尔曼最有价值的地方也是它配得上“概率统计基础”这个前置的理由——没有概率你没法定义“不确定度”也就没法动态分配权重。理解到这一层你在调Q和R时就有了方向感Q描述“模型漂多快”R描述“观测多脏”两者比较的结果决定了滤波器行为。5.3 一个能对比的完整小实验我建议做这样一个实验拿云台静止的陀螺仪数据人为叠加一段机动分别用低通和卡尔曼哪怕是最简单的角度零偏两状态模型处理把三条曲线画在一张图上。你会看到静止段卡尔曼和低通都平滑机动段低通明显跟不上而卡尔曼能咬住。这个对比图贴在笔记里比记十个公式都深刻。# 极简两状态卡尔曼角度、零偏示意说明“时变增益”的存在 import numpy as np dt 0.001 A np.array([[1, -dt], [0, 1]]) H np.array([[1, 0]]) Q np.array([[0.001*dt, 0], [0, 0.003*dt]]) R np.array([[0.03]]) x np.zeros((2, 1)) # [角度; 零偏] P np.eye(2) def kalman_step(z): global x, P x A x # 预测 P A P A.T Q y z - H x # 新息 S H P H.T R K P H.T np.linalg.inv(S) # 增益随时变 x x K y # 更新 P (np.eye(2) - K H) P return x[0, 0]跑这个例子时别急着优化参数先观察K是怎么随P和R变化的。看到K在机动段变大、平稳段变小你就真正摸到了卡尔曼“活”的那一面也就自然明白概率统计里的方差、协方差在实机上到底在干什么活。6. 上手前的排查清单与实测心得6.1 高频踩坑与对应做法学习概率统计基础、往卡尔曼过渡的路上重复出现的坑其实就那么几个我整理成表方便对照。现象可能原因处理方向滤波器输出跟着噪声乱跳R设得过小过度信任脏观测用实测噪声方差定R初值再微调输出迟钝、机动跟不上Q设得过小过度信任模型适当增大Q或检查模型是否漏项长时间运行后发散P失去正定或对称性强制对称化加微小对角修正状态估计出现常值偏差未做零偏标定期望没减掉静止标定求均值并在测量中扣除多状态耦合异常忽略协方差误设为对角在Q、R里补相关项检查量纲单位/量纲混乱角度弧度混用、密度当标准差统一量纲注意采样率折算6.2 我个人的参数整定与验证习惯我在实机上整参有个固定流程分享出来你可能少走弯路。第一步永远是先测后调让机器人分别保持静止、匀速、急机动三种状态录下原始传感器数据各自算均值和方差把这些实测值填进R和Q当起点而不是凭感觉填1或者0.1。第二步是单变量试一次只动Q或R其中一个观察曲线怎么变建立因果关系别两个一起乱动。第三步是看残差卡尔曼的残差观测减预测如果长期均值不为零说明模型或零偏有问题如果残差方差远大于理论值说明噪声建模偏乐观。还有一点很多同学忽略验证阶段要留一段没参与调参的数据做交叉验证。我见过太多人把一段数据反复调到完美换段路况立刻崩这就是过拟合。概率统计天然带着“用样本估计总体”的警惕你在调参时也要有这种心态——你调的是一段数据的脾气要验证的是整体规律。最后再回到那个搜索热词带来的提醒“卡尔曼滤波的数学思想”和“卡尔曼滤波原理”这些词看着高大上但真到赛场决定成败的往往是你对噪声的理解是否扎实。我个人的体会是把概率统计这几块地基反复咀嚼比多背十个滤波变种都值等你在实机上亲眼看到P矩阵一涨一缩、K随时变增益工作起来那种“原来如此”的感觉才是从照抄代码到真正掌握算法的那道分水岭。后面再往扩展卡尔曼、无迹卡尔曼走时你会发现它们换的只是外壳内核还是今天这套用均值和协方差描述信念、用贝叶斯更新信念的老路子。
返回列表