完整项目为《基于机器视觉的行人和路面缺陷检测及其边缘设备部署》
完整功能视频演示地址:本科最后的课设:“车载系统的辅助系统——基于机器视觉的行人和路面缺陷检测”完结撒花*罒▽罒*_哔哩哔哩_bilibili
该博客介绍的功能为:
1:树莓派通过gps+天线读取经纬度坐标(检测出路面缺陷的位置)
2:将经纬度坐标上传至服务器
3:调用高德地图api,读取服务器的经纬度,并在地图上标点。
该博客参考了以下博客和资料:
[1] (74条消息) 树莓派(四):GPS连接并读取_树莓派gps_哦吼吼231的博客-CSDN博客
[2] (74条消息) NMEA经纬度换算_nmea坐标_牧童宇希的博客-CSDN博客
[3] (71条消息) 【高德地图API】Web地图开发系列(一)_生命是有光的的博客-CSDN博客
[4] (74条消息) 十三、JavaScript ajax请求_js ajax请求_HJHO的博客-CSDN博客
[5] (74条消息) HTML读取json文件(传递给变量)_璇焱如柳的博客-CSDN博客
[6] JS API 安全密钥使用-基础-进阶教程-地图 JS API 2.0 | 高德地图API
一、 树莓派通过gps+天线读取经纬度坐标
我们将GPS 模块的串口输出用USB-TTL 进行了转换,因此我们直接在USB 口上读取GPS 模块传入的数据即可。
还需要注意的是GPS 模块读取到的值并非经纬度,而是包含了经纬度信息的字符串。我们的GPS 读入的信息GNRMC_line 的格式为
["b'$GNRMC" , '当天UTC 时间','A表示数据有效','纬度','N- 北','精度', 'E- 东', '对地速度,单位为节', '对地真航向,单位为度', '日期(dd 为日,mm 为月,yy 为年)', '', '', "A*75\\r\\n'" ]
比如:
[“b'$GNRMC”,'132558.000','A','3412.93903','N','11708.08969','E','0.00', '0.00', '081221', '', '', "A*75\\r\\n'" ]
所以我们需要在数据流中找到以”b\’$GNRMC” 开头的数据,并且在该字符串数组的第五个元素和第七个元素。纬度前2 字符表示度,后面的字符表示分,需要转化为小数形式;经度前3 字符表示度,后面的字符表示分,需要转化为小数形式。
具体代码如下:(完整功能可以复制的代码会附在整个模块讲解结束的地方,这里只是一部分)
其中,我们打开串口,存放到ser 中,/dev/ttyUSB0 是端口名,9600 是波特率。while True 表示一直不断检测,readline 为读取整行。我们读取以GNRMC 开头的字符串数组,然后以“,” 逗号作为分隔符把不同的数据分隔开,最后通过计算得到xx 度xx 分正确格式的经纬度,最后打印出来。
如图为测试图片
图:GPS模块经纬度读取测试
二、 将经纬度坐标上传至服务器
我们在自己的服务器上开了上传、读取和删除的接口。该部分用到上传接口。我们向接口发送了POST 请求,并将经纬度作为JSON 格式的数据发送到了该URL 。
其中POST 请求是HTTP 中向服务器提交数据的请求方式。与GET 请求不同,POST 请求将数据作为请求体(request body)发 送到服务器,而不是放在URL 的查询参数中。因此,POST 请求通常用于提交一些敏感数据或者比较大的数据,例如表单数据、文件上传等。
具体代码如下:(requrl='http://124.221.239.172:8080/location'请更换为你自己开的服务器端口,该端口已经关闭不可使用)
我们创建一个名为`rqs_headers` 的字典,这个字典将被用作请求的头部(headers) 参数,告诉服务器发送的数据是JSON 格式的。Requrl 为服务器接口的URL地址。最后我们把经纬度通过json.dumps 命令转化为json 格式通过POST 指令发到服务器。如果服务器收到了,会返回响应结果,完成本次通信协议。
第一第二节完整代码如下:
import serial
import time
import json
import requests
ser = serial.Serial("/dev/ttyUSB0",9600) #9600是GPS的波特率
while True:line = str(str(ser.readline()))# #打印所有串口数据# print(line)GNRMC_line = line# GNGLL_line = line# GNGLL_line = lineif GNRMC_line.startswith("b\'$GNRMC"):print(GNRMC_line)GNRMC_line = str(GNRMC_line).split(',') # 将line以“,”为分隔符#GNRMC_line格式为:["b'$GNRMC", '132558.000', 'A', '3412.93903', 'N', '11708.08969', 'E', '0.00', '0.00', '081221', '', '', "A*75\\r\\n'"]#GNRMC_line格式为:["b'$GNRMC", '当天UTC时间', 'A表示数据有效', '纬度', 'N-北', '精度', 'E-东', '对地速度,单位为节', '对地真航向,单位为度', '日期(dd 为日,mm为月,yy为年)', '', '', "A*75\\r\\n'"]print(GNRMC_line) #查看数据类型# 时间转化省略(需要把UTC转化为北京时间)# Lat ddmm.mmmm 纬度,前2字符表示度,后面的字符表示分,需要转化为小数形式latitude = float(GNRMC_line[3][:2]) + float(GNRMC_line[3][2:])/60# Lon dddmm.mmmm 经度,前3字符表示度,后面的字符表示分,需要转化为小数形式longitude = float(GNRMC_line[5][:3]) + float(GNRMC_line[5][3:])/60print("纬度: " + GNRMC_line[4] + " " + str(latitude))print("经度: " + GNRMC_line[6] + " " + str(longitude))# time.sleep(1)rqs_headers={'content-Type':'application/json'}requrl='请更换为你自己的服务器地址'new_data={"longitude":longitude,"latitude":latitude}test_data = json.dumps(new_data)response = requests.post(url=requrl,headers=rqs_headers,data=test_data)
三、调用高德地图api,读取服务器的经纬度,并在地图上标点
上面两节是要在树莓派自带的python编译器中运行的python代码。下面是用VScode写的html代码。
代码如下:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script type="text/javascript" src="请改成你自己的高德api密钥"></script><style type="text/css">html {height: 100%}body {height: 100%;margin: 0px;padding: 0px}#container {height: 100%}.amap-icon img,.amap-marker-content img{width: 25px;height: 34px;}.marker {position: absolute;top: -20px;right: -118px;color: #fff;padding: 4px 10px;box-shadow: 1px 1px 1px rgba(10, 10, 10, .2);white-space: nowrap;font-size: 12px;font-family: "";background-color: #25A5F7;border-radius: 3px;}</style>
</head><body><div id="container"></div><script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script> <!-- 导入jQuery包--><script type="text/javascript">var map = new AMap.Map('container', {zoom: 11, //级别center: [116.397428, 39.90923], //中心点坐标viewMode: '3D' //使用3D视图});$.ajax({url: "请换为你的服务器端口",//json文件位置,文件名type: "GET",//请求方式为getdataType: "json", //返回数据格式为jsonasync: false,success: function(data) {position_list=$.parseJSON(JSON.stringify(data)); // 将string转换成可操作的objectconsole.log(position_list[0])for (var i=0;i<position_list.length;i++){marker = new AMap.Marker({icon: "\poi-marker-default.png",position: [position_list[i].longitude,position_list[i].latitude],offset: new AMap.Pixel(-13, -30)});marker.setMap(map);}}});
//请求成功完成后要执行的方法 </script>
</body>
</html>
以上的代码可以把服务器的里的经纬度数据遍历一遍并且显示在地图画布上。效果如下:
我们还给每个Marker 对象添加一个事件监听器,以便监听点击操作。在使用者点击marker 后能够用infowindow 对象的open 方法将信息窗口显示在地图上,并将其链接到marker 的位置上。
效果如下图: