GNSS算法进阶(二)- kalman滤波单点定位算法代码实现

状态预测

kalman滤波与前面实现的最小二乘最大的区别就在于,kalman滤波用到了历史状态信息,即进行状态预测。

公式中BU(k)(控制输入)在我们定位模型中用不到。

从(k-1)时刻将状态转移到(k)时刻的转移矩阵,其实就是我们初中学的位置、速度、加速度之间的关系,只是初中学的是一维的,现在是ecef框架下的三维。

除了预测的状态量,我们还需要知道预测的状态量的方差协方差信息。学过平差中的误差传播定律,那么预测的协方差更新也很容易理解。

只是需要多加一个过程噪声矩阵Q,来放大预测状态的方差协方差信息。

直观上也很容易理解,任何模型都有误差,为了防止预测的状态权重过大,增加过程噪声以降低后续加权平均中预测状态的影响。

状态以及其相应方差协方差的预测在以下函数中实现

/* temporal update of position/velocity/acceleration */
static void udpos_spp(rtk_t *rtk, double tt)

我们实现的是PVA模型,也即位置/速度/加速度模型。

函数的输入tt是相邻两次状态转移的时间间隔,主要是过程噪声的计算需要依赖tt。直观上也很容易理解,外推时间越长,过程噪声设置应该越大。


测量更新

①残差计算

kalman滤波残差计算和最小二乘的类似,最小二乘中计算的是基于概略位置的修正值,kalman滤波也一样,参考公式(4),也是相对于预测状态的更新量。区别在于kalman滤波算法的状态量多了速度和加速度,虽然并没有观测值对他们进行更新。

设计矩阵和残差阵依然采用最小二乘的rescode函数,只是将其中接收机所在位置进行了更新,并重新命名为

/* pseudorange residuals -----------------------------------------------------*/ 
static int rescode_mulfreq_filter(int iter, const obsd_t *obs, int n, const double *rs, const double *dts, const double *vare, const int *svh, const nav_t *nav, const double *x, const prcopt_t *opt, double *v, double *H, double *var, double *azel, int *vsat, double *resp, int *ns)

函数中并未考虑速度和加速度状态量,所以在此函数之后,增加了一个专门插入这俩状态量的函数。

static void insert_vel_acc_colums(const int nv, double *H)

原先考虑与最小二乘公用一个函数,后续有机会再统一吧。

②滤波

kalman滤波算法逻辑,与rtk算法中完全一样。直接复用filter函数,filter函数中调用filter_,调用之前做了一步处理,即仅状态值非0且方差大于0的状态参与滤波。这样处理,是因为在rtk中默认的状态量包含了所有卫星的模糊度,对于没有观测值更新的模糊度明显是不需要参与滤波的。 所以在使用该filter时,注意各状态量的初值不要设置为0。或者直接调用filter_函数。

将滤波结果更新回rtk_t->x_spp和rtk_t->P_spp中,便于下历元滤波。同时将滤波存储到sol_t中。


/* kalman filter ---------------------------------------------------------------
* kalman filter state update as follows:
*
*   K=P*H*(H'*P*H+R)^-1, xp=x+K*v, Pp=(I-K*H')*P
*
* args   : double *x        I   states vector (n x 1)
*          double *P        I   covariance matrix of states (n x n)
*          double *H        I   transpose of design matrix (n x m)
*          double *v        I   innovation (measurement - model) (m x 1)
*          double *R        I   covariance matrix of measurement error (m x m)
*          int    n,m       I   number of states and measurements
*          double *xp       O   states vector after update (n x 1)
*          double *Pp       O   covariance matrix of states after update (n x n)
* return : status (0:ok,<0:error)
* notes  : matirix stored by column-major order (fortran convention)
*          if state x[i]==0.0, not updates state x[i]/P[i+i*n]
*-----------------------------------------------------------------------------*/
static int filter_(const double *x, const double *P, const double *H,
                   const double *v, const double *R, int n, int m,
                   double *xp, double *Pp)

结果分析

为了防止采样时间过久,导致状态预测权重过低没有滤波效果,特意选了一个采样频率1s的数据。该数据下载自香港cors数据。(ftp://ftp.geodetic.gov.hk/rinex3

相关的数据配置以及代码,已经在以下两个commit更新

55df872b4de9362e1166bb46ab9a6b2df131e8d0

7569205e5f6df464e10fa12a29f569e672cb7b44

如在上上推文中最后所描述的,加上kalman滤波的结果并没有想象中的平滑,初步怀疑是状态预测的精度太低。

考虑到静态的基站数据,速度均为零,所以在代码中直接增加三方向速度为0的约束,约束代码如下,非常简单

        /* add velocity constrain of static mode */
        for (j = 3; j < 6; j++)
        {
            for (k = 0; k < NX_F; k++) {
                H[k + nv * NX_F] = 0.0;
            }
            H[j + nv * NX_F] = 1.0;
            v[nv] = 0.0 -x[j] ;
            var[nv] = SQR(0.001);
            nv++;
        }

增加零速约束前后对比如下,其中噪声较大的结果为无零速约束的kalman滤波结果,平滑结果为增加零速约束结果。

增加零速约束的结果相当平滑,定位精度在分米量级,精度超出预期。这也从层面在一定层度上表明我们增加的kalman滤波代码没有问题。

公众号

有时会将代码 或者资源放在个人公众号上,有问题,在公众号后台回复,也回答的比较快一些,欢迎关注 GNSS和自动驾驶

其他相关文章链接汇总

GNSS算法学习系列教程 - 文章列表_梧桐Fighting的博客-CSDN博客

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: GNSS(全球导航卫星系统)单点定位算法是一种利用卫星信号进行定位的方法,主要通过接收多颗卫星的信号进行测量和计算来确定用户的位置。下面是一个示例的GNSS单点定位算法代码: ```python import numpy as np def gnss_single_point_positioning(satellite_data, receiver_data): # 卫星数据:卫星的位置和伪距 satellite_positions = satellite_data['positions'] pseudo_ranges = satellite_data['pseudo_ranges'] # 接收机数据:接收机的位置 receiver_position = receiver_data['position'] # 预设接收机位置 estimated_position = np.array([0, 0, 0]) # 对每个可见卫星进行迭代 for i in range(len(satellite_positions)): # 计算接收机到卫星的几何距离 geometric_distance = np.linalg.norm(receiver_position - satellite_positions[i]) # 通过几何距离和卫星传输的伪距计算估计的接收机位置 estimated_position += (receiver_position - satellite_positions[i]) * (pseudo_ranges[i] - geometric_distance) / geometric_distance return estimated_position # 示例数据 satellite_data = { 'positions': np.array([[1000, 2000, 3000], [4000, 5000, 6000], [7000, 8000, 9000]]), 'pseudo_ranges': np.array([900, 1200, 1500]) } receiver_data = {'position': np.array([10000, 20000, 30000])} # 调用单点定位算法 estimated_position = gnss_single_point_positioning(satellite_data, receiver_data) print("Estimated Receiver Position:", estimated_position) ``` 以上是一个简单的GNSS单点定位算法代码示例,其中通过迭代计算,使用卫星信号的位置和伪距来估计接收机的位置。这只是一个简单的示例,实际中还需要考虑更多的误差源如钟差、大气延迟等,以及更复杂的算法和数据处理。 ### 回答2: GNSS单点定位算法代码是用于实现全球导航卫星系统(GNSS)接收机的定位功能。该算法代码通过接收多颗卫星发射的信号,利用接收机内部的时钟和测量值,计算出接收机在地球上的位置。 代码实现的基本步骤如下: 1. 初始化接收机参数,包括接收机的位置、时钟误差、卫星的轨道信息等。 2. 接收卫星信号,测量接收机与卫星之间的距离。这可以通过计算信号传播时间或者测量信号的相位差来实现。 3. 根据接收到的卫星信号,计算接收机与每颗卫星之间的几何距离。这个距离是接收机与卫星之间的直线距离,考虑了信号在大气中传播的延迟效应。 4. 利用接收到的多颗卫星信号,计算接收机的位置。有多种方法可以实现这一步骤,其中一个常用的方法是通过解算位置的方程组,其中方程组的未知数是接收机的位置。 5. 修正接收机的时钟误差。由于接收机内部的时钟可能存在误差,需要对接收到的卫星信号进行时间校准。 6. 输出定位结果。将计算得到的接收机位置信息输出,以提供给应用程序或者用户使用。 通过以上步骤,GNSS单点定位算法代码可以实现对接收机位置的定位。这样,用户就可以根据卫星信号进行定位,从而得到精确的位置信息。该代码的应用范围广泛,包括车辆导航、精确定位等领域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值