基于RSSI的室内定位系统设计——使用PythonWeb开发
一、室内定位系统功能:
设计一种基于移动智能终端的室内定位系统,系统训练阶段,通过在用户随身携带的移动智能终端自动采集室内无线信号强度信息,数据经预处理后建立信号强度和位置的指纹库;定位阶段,用户移动智能终端实时采集到的信号强度数据和指纹库中的信息进行相关性匹配来完成定位。在部署实验场景采集数据的基础上,设计建立指纹库,并编程实现HTML界面,构建室内定位系统。系统能够快速且较准确实现用户室内定位。
二、RSSI及KNN算法简介:
RSSI简介
RSSI是一种基于测距的定位技术,其测距原理为接收机通过测量射频信号的能量来确定与发送机的距离。该方法实现简答,因此被广泛应用,但使用时需要注意遮盖或者折射现象会引起接收端产生严重的测量误差,导致精度降低。
KNN算法
在本文中使用到KNN算法(K = 3时)的目的是:根据输入的信号值,在指纹库中找到对应的三个位置信息后,依据KNN算法思想,将三个位置信息中出现次数最多的位置信息输出为最终的定位信息。可以参考下图进行理解:

三、系统的详细设计:
(1)后端
设计一个主页面,实现RSSI室内定位的功能:输入一个data信号值,在指纹库中进行查找数据,找到离该信号值最近的三个点,然后使用KNN算法得到最后的定位信息:
@app.route('/', methods=['GET', 'POST'])
def issa():place = "暂无" # 第一次进入系统时,GET方式访问,直接给place等变量赋值,然后输出即可place_01 = "暂无"place_02 = ""place_03 = ""data_dict = {'place_01': place_01, 'place_02': place_02, 'place_03': place_03, 'place': place}if request.method == 'GET': # 首次访问页面,没有输入值,直接显示默认界面return render_template("issa.html", data_dict = data_dict)data = int(request.form.get("index")) # POST方式访问页面,用data来接收输入的信号值# 1.连接数据库index:conn = pymysql.connect(host="127.0.0.1", port=3306, user='root', passwd="******", charset='utf8', db="index")cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)# 2.取得数据sql = "select * from informations"cursor.execute(sql)data_list = cursor.fetchall()# 3.关闭数据库:cursor.close()conn.close()map_data = []for item in data_list: # 将距离输入值 2 以内的所有存储值,放到 map_data 中if ((item["data_median"] >= data - 2) & (item["data_median"] <= data + 2)):k = [item["data_median"], item["place"]]map_data.append(k)if ((item["data_average"] >= data - 2) & (item["data_average"] <= data + 2)):k = [item["data_average"], item["place"]]map_data.append(k)if ((item["data_weightAvg"] >= data - 2) & (item["data_weightAvg"] <= data + 2)):k = [item["data_weightAvg"], item["place"]]map_data.append(k)if ( len(map_data) < 3):place = "无法获取定位信息!"else: # 查找到了三个或者超过三个的已存储信息,可以继续使用KNN算法for issa in map_data:issa[0] = abs(issa[0] - data) # 得到差的绝对值map_data = sorted(map_data,key=lambda x:x[0] ) # 排序place_01 = map_data[0][1] # 获取三个点的位置信息place_02 = map_data[1][1]place_03 = map_data[2][1]if (place_01 == place_02) & (place_01 == place_03): # 三个地址信息相等place = place_01elif (place_01 == place_02) | (place_01 == place_03):place = place_01elif (place_02 == place_03):place = place_02else:place = "位置不确定!"data_dict = {'place_01': place_01, 'place_02': place_02, 'place_03': place_03, 'place': place}return render_template("issa.html", data_dict = data_dict)
设计一个展示数据库的页面,使用户可以直观的看到指纹库中存储的数据:
@app.route("/information", methods=['GET', 'POST'])
def information():# 1.连接数据库index:conn = pymysql.connect(host="127.0.0.1", port=3306, user='root', passwd="******", charset='utf8', db="index")cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)# 2.取得数据sql = "select * from informations"cursor.execute(sql)data_list = cursor.fetchall()# 3.关闭数据库:cursor.close()conn.close()return render_template("information.html", data_list = data_list)
设计一个页面,可以向指纹库中输入新的数据信息。由于输入的信息需要经过一定的处理,我还另外定义了三个函数来求取16个数的平均值、中值、加权移动平均值,然后在add_details函数中进行引用,并将计算结果存储到数据库中:
def getAvg(signal_data): # 使用平均值方法,求得一个值并返回total = 0.0for item in signal_data: # 将所有列表数据累加起来total = total + float(item)return total / 16def getMedian(signal_data): # 使用中值法,求得一个值并返回signal_data = list(map(float, signal_data))signal_data.sort() # 将列表进行排序data_median = (signal_data[int(len(signal_data) / 2)] + signal_data[int(len(signal_data) / 2 - 1)]) / 2.0return data_mediandef getWeightMovingAvg(signal_data): # 使用加权移动平均法,求得一个值并返回length = len(signal_data)signal_data = list(map(float, signal_data))while True:s = 0.0 # 保存计算得到值for k in range(length):s += (k + 1) * signal_data[k] # s = 1*signal_data + 2*signal_data + ...s /= (length * (length + 1) / 2.0)for k in range(length - 1): # 将后一个值赋值给前面signal_data[k] = signal_data[k + 1]signal_data[length - 1] = s # 将 s 赋值给最后一个数nd = signal_data[length - 1] # 获取数组最后一个值js = 0 # 计数for j in range(length - 1):if (nd == signal_data[j]):js = js + 1if (js == length - 1): # 所有的数据都一样,停止迭代breakdata_weightAvg = round(s, 4) # 保留 4 位小数return data_weightAvg
@app.route('/add_details', methods=['GET', 'POST'])
def add_details():if request.method == 'GET':return render_template("add_details.html")place = request.form.get("place") # 拿到用户在网页输入的信息signal_01 = request.form.get("signal_01")signal_02 = request.form.get("signal_02")signal_03 = request.form.get("signal_03")signal_04 = request.form.get("signal_04")signal_05 = request.form.get("signal_05")signal_06 = request.form.get("signal_06")signal_07 = request.form.get("signal_07")signal_08 = request.form.get("signal_08")signal_09 = request.form.get("signal_09")signal_10 = request.form.get("signal_10")signal_11 = request.form.get("signal_11")signal_12 = request.form.get("signal_12")signal_13 = request.form.get("signal_13")signal_14 = request.form.get("signal_14")signal_15 = request.form.get("signal_15")signal_16 = request.form.get("signal_16")signal_data = [signal_01, signal_02, signal_03, signal_04, signal_05, signal_06, signal_07, signal_08, signal_09, signal_10, signal_11, signal_12, signal_13, signal_14, signal_15, signal_16]# 1.连接数据库index:conn = pymysql.connect(host="127.0.0.1", port=3306, user='root', passwd="******", charset='utf8', db="index")cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)# 2.将16个测量值存储到information_details中,将三个计算值存储到informations中:sql_1 = "insert into information_details(place, signal_01, signal_02, signal_03, signal_04, signal_05, signal_06, signal_07, signal_08, signal_09, signal_10, signal_11, signal_12, signal_13, signal_14, signal_15, signal_16) values(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"cursor.execute(sql_1, [place, signal_01, signal_02, signal_03, signal_04, signal_05, signal_06, signal_07, signal_08, signal_09, signal_10, signal_11, signal_12, signal_13, signal_14, signal_15, signal_16])conn.commit()data_average = getAvg(signal_data) # 调用三个函数,进行计算三个估计值data_median = getMedian(signal_data)data_weightAvg = getWeightMovingAvg(signal_data)sql_2 = "insert into informations(place, data_median, data_weightAvg, data_average) values(%s, %s, %s, %s)"cursor.execute(sql_2, [place, data_median, data_weightAvg, data_average])# 3.关闭数据库:cursor.close()conn.close()return "添加测量数据成功!"
至此,后端的设计完成!
(2)前端
设计一个页面,来进行RSSI室内定位系统的使用。需要一个输入信号值的窗口,还有两个面板,来展示KNN算法输出的三个位置信息,以及最后的定位信息:
ISSA定位技术的实现
你所在的大致位置是:{{ data_dict.place }}
KNN算法返回的三个临界位置信息{{ data_dict.place_01 }}
{{ data_dict.place_02 }}
{{ data_dict.place_03 }}
设计一个页面,用以展示当前指纹库中的数据,直接使用一个table即可:
添加信息
序号 信号强度指标(中值法) 信号强度指标(均值法) 信号强度指标(加权移动平均法) 所在位置 {% for item in data_list %} {{ item.id }} {{ item.data_median }} {{ item.data_average }} {{ item.data_weightAvg }} {{ item.place }} {% endfor %}
设计一页面,向指纹库中添加新的数据信息,需要一个输入text的文本框来接收位置信息,以及16个输入number的输入框来接收16个测量值:
添加指纹库信息
至此,前端的设计完成!
(3)数据库
数据库的设计,主要包括两个table:information_details 和 informations 的创建,前者用来保存输入的16个测量值以及他们的地理位置,后者用来保存由16个测量值计算出的平均值、中值、带权移动平均值以及他们对应的地理位置。它们的结构如图:
information_details:

informations( information是不可数的,写完才发现,但是不想改了 )

数据库的构建完成!
四、系统的测试使用
(1)向数据库中添加数据,构建指纹库:
运行系统,进入127.0.0.1:5000打开系统,然后点击编辑指纹库进入指纹库展示页面,再点击添加指纹库信息,即可进行测量数据的输入:


进行多次添加操作后,即可构建出本系统的指纹库:

(2)指纹库构建完成后,在系统主页输入一个信号值,单击获取定位,即可使用RSSI室内定位系统来获得该信号值对应的地理位置。如果指纹库中查找不到,则输出无法定位:
输入信号值:-60

输入信号值:-27

五、系统运行说明
本人使用vscode来运行app.py文件,数据库使用的是wampserver中的MYSQL,同时使用了sqlyog来对数据库实行可视化操作(创建新的数据库,新建table等操作)。运行本系统时,推荐使用vscode(或pycharm),数据库可以使用MySQL(或wampserver)以及sqlyog。同时也要将后端Python代码里面,连接数据库的语句中的密码、数据库名称等相关信息进行修改。
系统运行展示:
基于RSSI的室内定位技术
六、源码
百度网盘:百度网盘
提取码:iuxp
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
