我正在摆弄我不久前买的 GPS,“GlobalSat GPS 接收器”型号 BU-S353S4。而且看起来效果很好!
在“Cody Wilsons”出色解释的帮助下,我已经能够从设备读取 GPS 信号!并借助优秀的 python 包“Pynmea2”将 GPGGA 输出转换为经度和纬度坐标。
但是我如何从两个位置计算我当前的速度?我发现这个线程指的是这个线程如何使用半正弦公式计算距离。
我的代码如下所示:
from math import radians, cos, sin, asin, sqrt
import serial
import pynmea2
ser = serial.Serial('/dev/ttyUSB0', 4800, timeout = 5)
def haversine(lon1, lat1, lon2, lat2):
"""
Calculate the great circle distance in kilometers between two points
on the earth (specified in decimal degrees)
"""
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
# haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * asin(sqrt(a))
r = 6371 # Radius of earth in kilometers. Use 3956 for miles. Determines return value units.
return c * r
counter = 0
while 1:
line = ser.readline().decode('UTF-8')
splitline = line.split(',')
if splitline[0] == '$GPGGA':
counter += 1
msg = line
data = pynmea2.parse(msg)
lat1 = data.latitude
lon1 = data.longitude
if counter % 2:
distance = haversine(lon1, lat1, data.longitude, data.latitude)
print(distance)
这会输出我走过的大约每个距离。但问题就在这里,它总是返回
0.0
。我可能还没有走够远?
我应该如何计算速度?
我知道公式速度=距离/时间。 Pynmea2 有时间属性 (
msg.timestamp
)。但坦率地说,我不知道该怎么做。
from math import radians, cos, sin, asin, sqrt, atan2, degrees
import serial
import pynmea2
ser = serial.Serial('/dev/ttyUSB0', 4800, timeout = 5)
def haversine(lon1, lat1, lon2, lat2):
"""
Calculate the great circle distance in kilometers between two points
on the earth (specified in decimal degrees)
"""
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
# haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * asin(sqrt(a))
r = 6371 # Radius of earth in kilometers. Use 3956 for miles. Determines return value units.
return c * r
prev_data = None
while 1:
line = ser.readline().decode('UTF-8')
splitline = line.split(',')
if splitline[0] == '$GPGGA':
msg = line
data = pynmea2.parse(msg)
if prev_data is not None:
distance = haversine(data.longitude, data.latitude, prev_data.longitude, prev_data.latitude)
print('distance', distance)
print('speed', round(distance*3600, 2))
prev_data = data
界面每秒更新一次,因此有速度公式。
你的半正矢公式是正确的。
您的程序中有一个错误,您将
lat1
和lon1
设置为data.longtitude
和data.latitude
,然后立即使用它们来测试与data.longitude
和data.latitude
的距离。 当然,您的距离将为零。 您需要将“当前”经度和纬度与“先前”经度和纬度分开。
(尽管有一点小问题。您不是在计算半正弦,而是使用半正弦计算距离。您可能只想将函数命名为
distance
。hav(x) = sin(x/2)**2
'
prev_data = None
while True:
....
if prev_data is not None:
distance = haversine(data.longitude, data.latitude,
prev_data.longitude, prev_data.latitude)
pre_data = data
....
GPGGA
具有位置和时间,但 GPRMC
消息具有直接来自 GPS 接收器的地面速度(以节为单位)。
您可以在此处查看大多数 GPS NMEA 字符串描述的内容,包括 RMC 消息。
在
pnmea2
中创建一个单独的部分来解析 GPRMC
消息以获取以节为单位的速度。
内置 GPS 速度比基于位置的方法能更好地估计。