你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

华为杯数学建模E题UWB精确定位国家一等奖算法思路

2021/12/28 20:06:16

(之前的草稿。。)上上。。上周五也就是十号的时候,我在玩乒乓球,结束的时候,我打开了手机,发现我qq微信短信超多,原来是获得了数学建模国家一等奖,大家纷纷送来了祝福,第一次参加,从查看论文到设计算法,再到形成代码,再优化,最终完成任务,付出了很大努力,还通宵了一晚上,早上死去活来的难受死了。。。。不过,有付出就有回报!加油!

在这里简单分享一下代码和思路。(代码只发了一点点)

大家首先先看看问题描述

 

 

 

 

 

本文为解决信号干扰下的超宽带(UWB)精确定位问题,首先通过逐步递进的方式将已知场景作为样本,利用UWB的定位技术,采集到锚点与靶点之间的距离,然后通过分别建立有无干扰情况下的定位建模,给出目标物的精确定位。再根据已知正常数据和异常数据的特征对这两类进行分类,学会判断在任何场景下是否受到信号干扰,并根据判断结果代入定位模型,最后由静态过渡到动态靶点运动轨迹的求解。

任务1是对给定数据进行预处理,运用NumPy、高斯分布的3sigma原则以及就近原则等方法对数据进行整理并删除无用数据,将数据最简化,为后面步骤的计算提供便利。

任务2是定位模型的求解过程,对于无干扰数据,利用最小二乘法和泰勒展开协同模型估计靶点的精确位置,根据已知数据对模型检验后得到三维精度为0.02m;对于干扰数据,应用修正粒子群智能优化定位模型预测靶点的精确位置,得到三维精度为0.072m。最后用给数据分别进行定位得到靶点坐标。

任务3是任务2不同场景的应用,修改场景后预测出靶点坐标,说明此模型可以在不同场景下进行应用。

任务4是实际应用中UWB精确定位的重点难点问题,即如何判断信号是否有干扰。

任务5是将前面问题进行实际演练,随机给出的一组数据,我们根据分类模型判定是否有干扰,根据有无干扰运行相应的定位模型,得到相对应的精确定位,并利用卡尔曼滤波算法对所求结果进行处理,最终得到动点运动轨迹。

首先进行任务1的分析:

当初有两种方案,如果按照时间戳分析,确实有缺失数据,按照线性填补,可以对时间戳进行填补数据,但是数据量太大会对之后的数据处理造成很大的干扰,于是决定,不按时间戳看,把相似相同的数据删了即可,大大减少数据处理量

经过分析,任务1包括以下四个问题:

(1)用NumPy进行数据处理,将每4行行为作为一组,将每个数据文件转换成二维表形式,生成的每行矩阵都代表一个样本;

(2)对正常数据和异常数据的648个数据进行预处理,利用高斯分布的3sigma原则将落在以外的数据看作异常删除,通过筛选、程序遍历,删除缺失数据、相同,利用就近原则删除相似数据;

(3)经数据处理以后,观察每个数据文件各保留多少组数据,利用折线图表示;

(4)最后重点列出24、109正常数据和1、100异常数据。(题上要求)

import numpy as np

class dataSolve:
    def getTagData():#数据处理
        tagFile = open("Tag坐标信息.txt", 'r',encoding='utf-8')
        tagArr = np.array([])
        tagIdx = 0
        for strLine in tagFile.readlines():
            tagIdx = tagIdx + 1
            if tagIdx > 2:
                strTmp = strLine.strip()
                strTmp = strTmp.split(':')[1][1:].split(' ')
                if len(strTmp) > 3:
                    strTmp[2] = strTmp[len(strTmp) - 1].strip()
                    for pos in range(len(strTmp) - 3):
                        strTmp.pop(3)
                strTmp[2] = strTmp[2].strip()
                for i in range(len(strTmp)):
                    strTmp[i] = dataSolve.strToInt(strTmp[i] + '0')
                tagArr = np.append(tagArr, strTmp)
        tagArr = tagArr.reshape(tagIdx - 2, 3)
        return tagArr, tagIdx
        #print(len(tagArr))
    def anchorEq(dataSource, dataDes):#判断坐标是否重复
        for i in range(4):
            if(dataSource[i] != dataDes[i]):
                return False
        return True
    def anchorSame(dataSource, dataDes):#判断坐标是否相似
        for i in range(4):
            if(abs(int(dataSource[i]) - int(dataDes[i])) > 10):
                return False
        return True
    def strToInt(str):
        sumNum = 0
        for i in range(len(str)):
            sumNum = sumNum * 10 + (int(str[i]) - int('0'))
        return sumNum
    def threesigma(data, n, idx):#3sigma原则算法实现
        data_x = data[:, 0].tolist()
        data_y = data[:, idx].astype('float32').tolist()
        ymean = np.mean(data_y)
        ystd = np.std(data_y)
        down = ymean - n * ystd
        up = ymean + n * ystd
        outlier = []
        outlier_idx = []
        for i in range(len(data_y)):
            if(data_y[i] < down) | (data_y[i] > up):
                outlier.append(data_y[i])
                outlier_idx.append(i)
        return outlier, outlier_idx
    
    def distance(tag, Ap):#欧氏距离
        return ((tag[0]-Ap[0]) ** 2 + (tag[1]-Ap[1]) ** 2 + (tag[2]-Ap[2]) ** 2) ** 0.5
         
    def solveData(tgIdx, normalArr, typeFile):#获取数据
        if(typeFile == 'zc'):
            anchorFile = open("正常数据/"+ str(tgIdx)+".正常.txt", 'r',encoding='utf-8')
        elif(typeFile == 'yc'):
            anchorFile = open("异常数据/"+ str(tgIdx)+".异常.txt", 'r',encoding='utf-8')
        else:
            return
        anchorIdx = 0
        normalArr = np.array([])
        for strLine in anchorFile.readlines():
            anchorIdx = anchorIdx + 1
            if anchorIdx > 1:
                strTmp = strLine.strip()
                strTmp = strTmp.split(':')
                if anchorIdx % 4 == 2:
                    normalArr = np.append(normalArr, strTmp[1])
                normalArr = np.append(normalArr, strTmp[5])
        normalArr.astype('float32')  
        normalArr = normalArr.reshape(int((anchorIdx - 1) / 4), 5)
        return normalArr
    def getData():
        anchorFile = open("1.txt", 'r',encoding='utf-8')
        anchorIdx = 0
        normalArr = np.array([])
        for strLine in anchorFile.readlines():
            anchorIdx = anchorIdx + 1
            if anchorIdx > 1:
                strTmp = strLine.strip()
                strTmp = strTmp.split(':')
                if anchorIdx % 4 == 2:
                    normalArr = np.append(normalArr, strTmp[1])
                normalArr = np.append(normalArr, strTmp[5])
        normalArr.astype('float32')  
        normalArr = normalArr.reshape(int((anchorIdx - 1) / 4), 5)
        return normalArr
    def saveData(tgIdx, normalArr, typeFile, pos):#保存数据
        if(typeFile == 'zc'):
            anchorFile = open("附件/数据1/"+ pos + "/"+ str(tgIdx)+".正常.txt", 'w',encoding='utf-8')
        elif(typeFile == 'yc'):
            anchorFile = open("附件/数据1/"+ pos + "/" + str(tgIdx)+".异常.txt", 'w',encoding='utf-8')
        else:
            return
        for wd in normalArr:
            anchorFile.write(wd[0] + " " + wd[1] + " " + wd[2] + " " + wd[3] + " " + wd[4] + "\r\n")
        anchorFile.close()
        
    def eqSolve(normalArr):#相等坐标处理方式
        eqList = []
        for i in range(len(normalArr)):
            for j in range(i + 1 ,len(normalArr)):
                if(i == j):
                    continue
                else:
                    if(dataSolve.anchorEq(normalArr[i][1:], normalArr[j][1:])):
                        if str(j) not in eqList:
                            eqList.append(j)
        return eqList
    
    def sameSolve(normalArr):#相似坐标处理方式
        sameList = []
        for i in range(len(normalArr)):
            if i in sameList:
                continue
            for j in range(i + 1 ,len(normalArr)):
                if(dataSolve.anchorSame(normalArr[i][1:], normalArr[j][1:])):
                    if j not in sameList:
                        sameList.append(j)
        return sameList

 

 首先进行任务2的分析:

 看了题后的论文和自己找的论文,发现泰勒级数展开和最小二乘法可以很好的解决问题,于是,看着论文,一步一步形成代码

 以下是最小二乘算法(Z轴精度不高,可结合泰勒级数展开加权使用(研究了好久论文才搞出来))

 

 

class zxecFun:
    def getPoint(Ap, d):
        A = np.array([])
        for i in range(3):
            x = Ap[i+1][0] - Ap[i][0]
            y = Ap[i+1][1] - Ap[i][1]
            z = Ap[i+1][2] - Ap[i][2]
            A = np.append(A, [x, y, z])
        A = A.reshape(3, 3)
        #print(A)
        B = np.array([])
        for i in range(3):
            ds = int(d[i]) * int(d[i]) - int(d[i + 1]) * int(d[i + 1])
            k2 = Ap[i+1][0] * Ap[i+1][0] + Ap[i+1][1] * Ap[i+1][1] + Ap[i+1][2] * Ap[i+1][2]
            k1 = Ap[i][0] * Ap[i][0] + Ap[i][1] * Ap[i][1] + Ap[i][2] * Ap[i][2]
            B = np.append(B, [ds + k2 - k1])
        B = 0.5 * B
        B = B.reshape(3, 1)
        #print(B)
        #最小二乘 X = (ATA)-1ATB
        mat = np.dot(A.T, A)
        mat = np.linalg.inv(mat)
        mat = np.dot(mat, A.T)
        mat = np.dot(mat, B)
        return mat
    def zxecSolve(normalArr):
        xSum = 0
        ySum = 0
        zSum = 0
        zxec = np.array([])
        for d in normalArr:
            tmpd = d[1:]
            tmpd = tmpd.astype('float64')
            result = zxecFun.getPoint(bsLoc, tmpd).flatten()
            xSum = xSum + result[0]
            ySum = ySum + result[1]
            zSum = zSum + result[2]
        xSum = xSum / len(normalArr)
        ySum = ySum / len(normalArr)
        zSum = zSum / len(normalArr)
        zxec = np.append(zxec, [xSum, ySum, zSum])
        return xSum, ySum, zSum, zxec

 篇幅原因,只放三维结果

 泰勒级数展开的代码,需要的私聊,费了好大劲才写出来,我太菜了。

接下来对任务3进行分析

这道题也就相当于,对之前的成果进行一个应用。

改变场景,应用场景2的靶点范围和锚点坐标,对前五组利用最小二乘法和泰勒级数展开模型精准定位,对后五组有信号干扰的数据利用修正粒子群智能优化定位模型进行定位,具体得到如下定位结果,观察可知,此靶点均在给定靶点范围内,可以将我们制定的模型应用到不同场景内。

接下来对任务4进行分析

我们根据泰勒级数所得到的误差值,来进行一个分类,如果误差大,根据聚类算法,可能就是干扰点。最后代入计算。

接下来对任务5进行分析

对之前所有的成果进行一个整合,根据所得坐标,我们可以得到轨迹图,但因为定位模型存在部分误差,所以在这里利用卡尔曼滤波模型,对所得结果进行去噪处理,尽可能还原真实数据,计算后得到如下运动轨迹图。

(PS:其实我之前想最小二乘算法强行跑出来结果,结果。。。。如下图,z轴精度真的不高的,最后加了泰勒级数展开、pso和卡尔曼滤波等等一些优化方式,才得到了 上图)

 

 

 由上图,我们可以看到,根据我们所构建的模型,平面轨迹效果更好,三维动态轨迹图可能存在误差,导致有点的跳跃,但整体运动轨迹仍存在一定规律性。

最后展示一下获奖信息

开心!!