二维匀速 Kalman:完整协方差传播
题目
状态为位置和速度 ,初值 ,。 每步先预测再位置观测更新;用 Joseph 形式更新协方差。 本题假设每个采样区间内加速度为独立随机常量 ,均值为零,方差 ,单位为 ;因此 ,。观测噪声参数 是位置测量方差,单位为 。这不是连续白加速度噪声谱密度模型:若采用谱密度 (单位 ),应使用另一离散化 ,不可混用两种参数。
输入
,然后 个位置观测。,,。 位置采用 m,时间采用 s; 是每区间常加速度方差而非连续噪声谱密度, 是位置观测方差。
输出
每步 ,共 个实数。
示例
输入
12 1 0 0.3
0 0 0 0 0 0 0 0 0 0 0 0
期望输出
0.0 0.0 0.2608695652173913 0.13043478260869565 0.5652173913043478 0.0 0.0 0.23510971786833856 0.15047021943573666 0.2163009404388715 0.0 0.0 0.21447721179624665 0.10455764075067024 0.08847184986595173 0.0 0.0 0.18917134367778143 0.07131066358534169 0.04258831297457906 0.0 0.0 0.1665442796299016 0.050668233220737255 0.023351446614774556 0.0 0.0 0.14777554214173932 0.03755868544600938 0.01408450704225352 0.0 0.0 0.1323951871435114 0.028852158707689736 0.009117781756109748 0.0 0.0 0.11971778128049239 0.02281768370487127 0.0062298281167905145 0.0 0.0 0.10915341641598625 0.018478727975934677 0.004440624552356398 0.0 0.0 0.10024480971608432 0.015260865418243093 0.0032747273709979995 0.0 0.0 0.09264644481720494 0.012811403540899071 0.002483170840688844 0.0 0.0 0.08609748836626295 0.010905159581968884 0.001927204926123813
在线 C++17 练习
在浏览器编译运行,代码不上传;首次下载约 28 MB。
尚未运行
运行环境
Clang 22 / C++17 / WASI,支持本题所需标准库;不支持线程、C++ 异常或任意宿主系统访问。每例 2 秒、256 MiB 线性内存、64 KiB 输出;编译器另占浏览器内存,不适合低内存设备。初次加载最多等待 120 秒,可随时停止。
草稿保存在本浏览器。测试公开,属于本地自测而非防作弊竞赛判题;参考解答不参与运行。所有运行资产均由本站提供。
编译器来源与开源许可参考实现(完成后再展开)
对照自己的推导,检查状态更新顺序、边界条件与单位,而不只比较最终输出。
// q: variance of independent, constant acceleration per sample interval [m^2/s^4].
// r: position measurement variance [m^2]; NOT continuous acceleration PSD.
#include <iostream>
#include <iomanip>
#include <cmath>
#include <algorithm>
#include <vector>
#include <array>
#include <queue>
#include <tuple>
#include <limits>
using namespace std;
// Reference implementation: optional; solve the starter before opening.
int main() {
cout << setprecision(17);
int n;
double dt,q,r;
cin>>n>>dt>>q>>r;
double x=0,v=0,p00=1,p01=0,p11=1;
while(n--) {
double z;
cin>>z;
x+=dt*v;
double a=p00+2*dt*p01+dt*dt*p11+q*pow(dt,4)/4,b=p01+dt*p11+q*pow(dt,3)/2,c=p11+q*dt*dt,k0=a/(a+r),k1=b/(a+r),e=z-x;
x+=k0*e;
v+=k1*e;
p00=(1-k0)*(1-k0)*a+k0*k0*r;
p01=(1-k0)*(b-k1*a)+k0*k1*r;
p11=c-2*k1*b+k1*k1*a+k1*k1*r;
cout<<x<<" "<<v<<" "<<p00<<" "<<p01<<" "<<p11<<"\n";
}
}