关于RTKLIB中用多普勒检测周跳方法的改进和思考

熟悉RTKLIB中周跳检测方法的同学应该知道,RTKLIB中利用多普勒积分检测周跳的方法,由于存在接收机时间跳变的问题,因此该方法一直没有进行使用。前段时间看到rtklibexplore博主对多普勒积分方法进行了改进(具体参见博客Google Smartphone Decimeter Challenge),因此写博客记录分析下他的主要改进思想以及我的一些思考。

RTKLIB中的周跳检测方法

在之前撰写的关于周跳检测的博客 – RTKlib源码解析:ppp和rtkpost中的周跳检测函数中,介绍了RTKLIB在PPP和RTK中使用的周跳检测函数。

RTKLIB中的周跳检测主要包括了以下几种检测方法:

  • 通过RINEX文件中标注的LLI进行检测。我觉得LLI如果标注得很好,理论上其实其他检测方法不用都行,因为LLI一般是通过锁定时间(lock time)来确定的,不过这取决于各个厂家数据转换软件的优劣程序。
  • 通过MW方法来检测周跳。MW组合中包括了L1,L2的载波相位和伪距,从MW组合的推导中可以看出该组合消除了电离层延迟误差、卫星、接收机钟差、卫星至接收机的几何距离。该组合虽有较高的检测精度,但是如果L1,L2同时发生相同大小的周跳,则不能成功检测。MW组合的噪声与伪距噪声相关: σ M W 2 ≈ 1 2 σ p 2 \sigma_{MW}^2\approx\frac{1}{2}\sigma_p^2 σMW221σp2
  • 通过GF组合检测周跳。GF组合中包括了L1,L2的载波相位,组合噪声只与载波相位噪声相关: σ G F = 2 σ L \sigma_{GF}=\sqrt{2}\sigma_L σGF=2 σL

我感觉目前周跳检测中存在的短板有:

  • 从目前在用的方法可以看出,MW组合和GF组合需要使用双频数据,如果只有单频数据,那么这两种方法都无法使用。
  • 此外,MW组合的噪声和伪距噪声相关,我们都知道伪距噪声比载波的噪声要大得多,因此MW的阈值设定得比较松,比如RTKLIB现在默认是10.0m,但是GF的阈值可以设定得比较紧,比如现在设定的是0.05m。这就导致MW方法对一些比较小的周跳,可能检测效果没有那么好。对于多数接收机,如果发生失锁,重新锁定卫星,载波相位虽然发生了周跳,但是一般都会用伪距去初始化载波相位,所以即使周跳了,其实周跳数也不会太大,MW方法的检测效果可能不会太理想。不过GF方法,我觉得还是非常灵敏的。

多普勒积分检测周跳中存在的问题

理论上,在没有周跳的情况下,历元间多普勒的积分值就等于载波相位的变化值。因此可以对多普勒进行积分计算,并计算前后两个历元的载波相位变化量,将两者进行比较,如果差值超过阈值,则认为有周跳发生。多普勒积分检测周跳的优点在于,只需要单频数据就可以进行周跳检测

但是部分接收机等钟差累积到一定程度后会进行调整,例如septentrio的接收机在钟差达到0.5ms时,会调整1ms,使得钟差成为-0.5ms ,此时伪距和载波相位会跳变0.001*velcity_of_light = 299792.458m,如下图所示【2】。显然,这会造成我们周跳检测出错,将时钟跳变误检测为周跳

从参考【3】来看,大部分接收机调整时钟时都是用的整数ms
在这里插入图片描述

对多普勒积分检测周跳方法的改进和思考

1. rtklibexplore的改进

作者rtklibexplore暂时还没有把这部分代码正式提交到github,不过可以通过这个链接RTKLIB demo5 b34e下载得到源码。

作者的主要改进思想为:

  • 时钟跳变对当前历元所有的(多普勒积分 - 载波相位变化值)影响相同,让它们都增加了一个共同的偏差。
  • 对于每颗卫星、每个频点,计算(多普勒积分 - 载波相位变化值),将不异常的(多普勒积分 - 载波相位变化值)加起来计算平均值,将这个平均值看作时钟跳变带来的偏差。目前的代码中对“不异常”的判定条件是(多普勒积分 - 载波相位变化值)没有超过3倍设定的阈值。然后从每个(多普勒积分 - 载波相位变化值)中减去这个平均值,再和阈值进行比较。

显然,这个改进方法也并不完美,如果时钟跳变很大,那么所有(多普勒积分 - 载波相位变化值)看起来都是异常值,这个周跳检测方法也就不起作用了。

RTKLIB demo5 b34e中rtkpos.c中的detslp_dop函数如下所示,也就是上述改进方法的实现。

/* detect cycle slip by doppler and phase difference -------------------------*/
static void detslp_dop(rtk_t *rtk, const obsd_t *obs, const int *ix, int ns,
                       int rcv, const nav_t *nav)
{
    int i,ii,f,sat,ndop=0;
    double dph,dpt,lam,thres,mdop=0;
    double dopdif[MAXSAT][NFREQ], tt[MAXSAT][NFREQ];

    trace(4,"detslp_dop: rcv=%d\n", rcv);
    if (rtk->opt.thresdop<=0) return;  /* skip test if doppler thresh <= 0 */

    /* calculate doppler differences for all sats and freqs */
    for (i=0;i<ns;i++) {
        ii = ix[i];
        sat=obs[ii].sat;

        for (f=0;f<rtk->opt.nf;f++) {
            dopdif[i][f]=0;tt[i][f]=0.00;
            if (obs[ii].L[f]==0.0||obs[ii].D[f]==0.0||rtk->ssat[sat-1].ph[rcv-1][f]==0.0) continue;
            if (fabs(tt[i][f]=timediff(obs[ii].time,rtk->ssat[sat-1].pt[rcv-1][f]))<DTTOL) continue;
            if ((lam=sat2freq(obs[ii].sat,obs[ii].code[f],nav))<=0.0) continue;

            /* calc phase difference and doppler x time (cycle) */
            dph=obs[ii].L[f]-rtk->ssat[sat-1].ph[rcv-1][f];
            dpt=-obs[ii].D[f]*tt[i][f];
            dopdif[i][f]=dph-dpt;

            /* if not outlier, use this to calculate mean */
            if (fabs(dopdif[i][f])<3*rtk->opt.thresdop*fabs(tt[i][f])) {
                mdop+=dopdif[i][f]/fabs(tt[i][f]);
                ndop++;
            }
        }
    }
    /* calc mean doppler diff, most likely due to clock error */
    mdop=ndop>0?mdop/ndop:0;

    /* set slip if doppler difference with mean removed exceeds threshold */
    for (i=0;i<ns;i++) {
        sat=obs[ix[i]].sat;

        for (f=0;f<rtk->opt.nf;f++) {
            if (dopdif[i][f]==0.00) continue;
            thres=rtk->opt.thresdop*fabs(tt[i][f]);
            errmsg(rtk,"slip detected doppler (sat=%2d rcv=%d dL%d=%.3f thres=%.3f off=%.3f)\n",
                   sat,rcv,f+1,dopdif[i][f]-mdop,thres,mdop);
            if (fabs(dopdif[i][f]-mdop)>thres) {
                rtk->ssat[sat-1].slip[f]|=1;
            }
        }
    }
}

2. 其他博主改进

另外,我也看到博主PhD.Knight,在CSDN发表的博客【干货】提升RTK模糊度固定率的建议之周跳探测中,对RTKLIB的doppler检测周跳方法进行了改进。

在原本的detslp_dop函数上增加以下几行代码,我感觉这种方法针对整ms时钟跳变应该是非常有效的。

int cj;
cj=floor(fabs(dph*lam/CLIGHT)*1000+0.5); // clock jump, integer ms
if(cj!=0) continue;

参考文献

[1] Google Smartphone Decimeter Challenge
[2] asterx-m2a_firmware_v4.8.0_reference_guide
[3] gnss receiver clocks
[4]【干货】提升RTK模糊度固定率的建议之周跳探测

在Python中,检测图像中是否有螺丝可以采用计算机视觉技术,通常结合深度学习和传统的图像处理算法。以下是一个简化的过程: 1. **图像预处理**:首先对图片进行灰度化、二值化或者边缘检测,以便突出螺丝的特征。 2. **目标检测**:可以使用一些现有的库,如`OpenCV`、`Pillow`,或者深度学习框架`TensorFlow`或`PyTorch`中的对象检测模型(例如YOLO、SSD、Faster R-CNN等),来定位疑似螺丝的位置。 3. **特征提取**:针对螺丝的形状特点,比如六边形轮廓、孔洞等,提取特征用于进一步确认。 4. **分类器**:如果仅需判断螺丝存在与否,可以训练一个简单的二分类模型,输入特征并预测结果。这可能涉及到机器学习,特别是支持向量机(SVM)或卷积神经网络(CNN)。 5. **后处理**:对检测到的区域进行过滤,去除误报或非螺丝物体。 **Python示例代码片段**(假设已经安装了相关库): ```python import cv2 from tensorflow.keras.preprocessing.image import img_to_array from sklearn.svm import SVC # 加载预训练模型 model = load_yolo_model() # 假设是YOLO模型 # 加载图片 image = cv2.imread('screw_image.jpg') # 进行目标检测 bboxes = model.detect(image) # 对每个检测框进行分类 for bbox in bboxes: feature_vector = extract_features_from_bbox(bbox) if is_screw(feature_vector): print("螺丝存在") else: print("可能是其他物体") def is_screw(feature): # 自定义的简单分类函数 return classify_with_svm(feature) # ... 定义特征提取和SVM分类等函数 ```
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值