基于Python的树莓派GPS位置半径范围校验需求
嘿,我刚好在树莓派上做过类似的GPS范围判断项目,给你一步步拆解实现方法,代码都是亲测能用的,应该能帮到你!
树莓派GPS位置范围判断实现方案
一、前期准备
- 先搞定串口权限和依赖:
- 释放串口:树莓派默认会把
/dev/ttyS0用作控制台,得先关掉。执行sudo raspi-config,进入Interface Options > Serial Port,选择「No」关闭login shell,「Yes」启用硬件串口,重启生效。 - 安装依赖库:用
pyserial读取串口数据,执行sudo pip3 install pyserial。
- 释放串口:树莓派默认会把
二、核心代码实现
我把功能拆成了几个模块,方便你理解和修改:
1. 计算GPS坐标距离(Haversine公式)
因为地球是球面,不能直接用平面距离计算,这里用Haversine公式算两点间的球面距离,精度足够日常使用:
import math import serial def haversine(lat1, lon1, lat2, lon2): # 把十进制经纬度转成弧度 lat1_rad = math.radians(lat1) lon1_rad = math.radians(lon1) lat2_rad = math.radians(lat2) lon2_rad = math.radians(lon2) dlat = lat2_rad - lat1_rad dlon = lon2_rad - lon1_rad # Haversine公式核心计算 a = math.sin(dlat/2)**2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(dlon/2)**2 c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) # 地球平均半径6371公里,计算出距离(公里) return 6371 * c
2. 读取当前GPS位置
从/dev/ttyS0读取NMEA格式的GPS数据,解析其中的GGA语句(包含有效经纬度的核心语句):
def get_current_gps(): # 初始化串口,波特率根据你的GPS模块调整,常见是9600或115200 ser = serial.Serial('/dev/ttyS0', 9600, timeout=10) while True: # 读取一行数据,忽略编码错误 line = ser.readline().decode('utf-8', errors='ignore').strip() # 筛选GGA语句 if line.startswith('$GPGGA'): parts = line.split(',') # 第6个字段是定位状态:1=有效定位,0=无效 if parts[6] == '1': # 解析纬度:格式是ddmm.mmmm,转成十进制 lat = float(parts[2]) lat_decimal = int(lat // 100) + (lat % 100) / 60 # 南纬转负数 if parts[3] == 'S': lat_decimal = -lat_decimal # 解析经度:格式是dddmm.mmmm,转成十进制 lon = float(parts[4]) lon_decimal = int(lon // 100) + (lon % 100) / 60 # 西经转负数 if parts[5] == 'W': lon_decimal = -lon_decimal ser.close() return (lat_decimal, lon_decimal) # 如果超时没读到有效数据,返回None ser.close() return None
3. 加载目标坐标列表
读取file.txt里的“纬度, 经度”格式坐标:
def load_target_coords(file_path): coords = [] with open(file_path, 'r') as f: for line in f: line = line.strip() if line: # 跳过空行 lat_str, lon_str = line.split(',') coords.append((float(lat_str.strip()), float(lon_str.strip()))) return coords
4. 主逻辑:判断是否在范围内
把上面的模块整合,判断当前位置是否在目标坐标的0.9公里范围内:
def is_in_range(target_coords, current_lat, current_lon, radius_km=0.9): # 遍历所有目标坐标,只要有一个在范围内就返回True for target_lat, target_lon in target_coords: distance = haversine(current_lat, current_lon, target_lat, target_lon) if distance <= radius_km: return True return False if __name__ == '__main__': # 加载目标坐标 target_coords = load_target_coords('file.txt') if not target_coords: print("错误:file.txt中没有有效坐标") exit(1) # 获取当前GPS位置 current_gps = get_current_gps() if not current_gps: print("错误:无法获取有效GPS定位,请确保在户外开阔地等待几分钟") exit(1) current_lat, current_lon = current_gps # 执行判断并输出结果(True/False) print(is_in_range(target_coords, current_lat, current_lon))
三、注意事项
- GPS定位时间:首次启动GPS模块需要3-5分钟(冷启动)才能获取有效定位,测试时一定要在户外无遮挡的地方。
- 波特率调整:如果读不到数据,检查GPS模块的波特率,常见的有9600、115200,修改
serial.Serial里的第二个参数即可。 - 权限问题:如果提示串口访问权限不足,执行
sudo usermod -a -G dialout pi,然后重启树莓派。
内容的提问来源于stack exchange,提问作者logvca
相关产品推荐
相关产品推荐

