gpt4 book ai didi

C++ 卡尔曼滤波器库产生 1.#R(NaN) 结果

转载 作者:搜寻专家 更新时间:2023-10-31 01:51:04 28 4
gpt4 key购买 nike

我目前正在尝试使用 Free C++ Extended Kalman Filter Library .我了解卡尔曼滤波器的基础知识,但是我遇到了使用此库生成 NaN 值的问题。 SO 上有没有人有使用卡尔曼滤波器算法来发现我的错误的经验?

这是我的过滤器:

class PointEKF : public Kalman::EKFilter<double,1,false,true,false> {
public:
PointEKF() : Period(0.0) {
setDim(3, 1, 3, 1, 1);
}

void SetPeriod(double p) {
Period = p;
}
protected:
void makeBaseA() {
A(1, 1) = 1.0;
//A(1, 2) = Period;
//A(1, 3) = Period*Period / 2;
A(2, 1) = 0.0;
A(2, 2) = 1.0;
//A(2, 3) = Period;
A(3, 1) = 0.0;
A(3, 2) = 0.0;
A(3, 3) = 1.0;
}
void makeBaseH() {
H(1, 1) = 1.0;
H(1, 2) = 0.0;
H(1, 3) = 0.0;
}
void makeBaseV() {
V(1, 1) = 1.0;
}
void makeBaseW() {
W(1, 1) = 1.0;
W(1, 2) = 0.0;
W(1, 3) = 0.0;
W(2, 1) = 0.0;
W(2, 2) = 1.0;
W(2, 3) = 0.0;
W(3, 1) = 0.0;
W(3, 2) = 0.0;
W(3, 3) = 1.0;
}

void makeA() {
double T = Period;
A(1, 1) = 1.0;
A(1, 2) = T;
A(1, 3) = (T*T) / 2;
A(2, 1) = 0.0;
A(2, 2) = 1.0;
A(3, 3) = T;
A(3, 1) = 0.0;
A(3, 2) = 0.0;
A(3, 3) = 1.0;
}
void makeH() {
double T = Period;
H(1, 1) = 1.0;
H(1, 2) = T;
H(1, 3) = T*T / 2;
}
void makeProcess() {
double T = u(1);
Vector x_(x.size());
x_(1) = x(1) + x(2) * T + (x(3) * T*T / 2);
x_(2) = x(2) + x(3) * T;
x_(3) = x(3);
x.swap(x_);
}
void makeMeasure() {
z(1) = x(1);
}

double Period;
};

我是这样使用的:

void init() {
int n = 3;
static const double _P0[] = {
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0
};
Matrix P0(n, n, _P0);
Vector x(3);
x(1) = getPoint(0);
x(2) = getVelocity(0);
x(3) = getAccleration(0);
filterX.init(x, P0);
}

和,

    Vector measurement(1), input(1), u(1);
u(1) = 0.400;
double start = data2->positionTimeCounter;
double end = data->positionTimeCounter;
double period = (end - start) / (1000*1000);
filterX.SetPeriod(period);
measurement(1) = getPoint(0);
input(1) = period;
filterX.step(input, measurement);
auto x = filterX.predict(u);

注意:我使用的数据是从单位圆生成的 x 点。

最佳答案

如果您使用矩阵的基本版本:

A = [ 1 0 0;
0 1 0;
0 0 1 ];
H = [ 1 0 0 ];

您没有可观测系统,因为您的测量仅捕获第一个状态(位置),并且在 A 矩阵中,位置及其导数(速度、加速度)之间没有耦合。 observability matrix如下:

O = [ H;
H*A;
H*A*A ];
O = [ 1 0 0;
1 0 0;
1 0 0 ];

这显然是单数的,也就是说,你的系统是不可观察的。并且通过 EKF 算法提供它应该会产生错误(算法应该检测到这种情况),但如果未检测到,它将导致估计中的 NaN 结果,正如您所经历的那样。

现在,来自 makeA() 函数的 A 矩阵更合适:

A = [ 1 h h*h/2;
0 1 h;
0 0 1 ];
H = [ 1 0 0 ]; // use this H matrix (not [ 1 h h*h/2 ])

导致可观察性矩阵:

O = [ 1    0      0;
1 h h*h/2;
1 2*h 2*h*h ];

它是满秩的(不是奇异的),因此,您有一个可观察的系统。

卡尔曼滤波算法对 conditioning of the matrices 非常敏感,这意味着如果时间步长非常小(例如 1e-6),您需要使用连续时间版本。此外,NaN 的问题可能来自 KF 算法中所需的线性求解器(求解线性方程组)。如果该库的作者使用了一种朴素的方法(例如,高斯消元法、有或没有主元的 LU 分解、没有主元的 Cholesky 等),那么这将使这个数值调节问题变得更糟。

注意你应该从一个非常高的 P 矩阵开始你的 KF 过滤,因为初始 P 应该反射(reflect)你的初始状态 vector 的不确定性,这通常非常高,所以 P 应该在 1000 * identity 左右。

关于C++ 卡尔曼滤波器库产生 1.#R(NaN) 结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14261667/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com