You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Python的树莓派GPS位置半径范围校验需求

嘿,我刚好在树莓派上做过类似的GPS范围判断项目,给你一步步拆解实现方法,代码都是亲测能用的,应该能帮到你!

树莓派GPS位置范围判断实现方案

一、前期准备

  • 先搞定串口权限和依赖:
    1. 释放串口:树莓派默认会把/dev/ttyS0用作控制台,得先关掉。执行sudo raspi-config,进入Interface Options > Serial Port,选择「No」关闭login shell,「Yes」启用硬件串口,重启生效。
    2. 安装依赖库:用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:21:44