- 项目背景与场景描述
实际应用场景
在智慧农业中,智能农机(如无人驾驶拖拉机、播种机、收割机)会持续记录 GPS 数据(经纬度 + 时间戳),用于:
- 作业路径回放与分析
- 作业效率评估
- 故障或异常行为检测
- 农田管理优化
痛点
- GPS 数据是地理坐标系(WGS84),直接绘图会因地球曲率导致变形
- 不同时间点的数据量可能很大,需要高效处理
- 需要计算总里程和行驶时间
- 非技术人员难以直接使用原始数据
-
核心逻辑讲解
-
数据输入:CSV 文件,包含 "timestamp, latitude, longitude"
-
坐标转换:将 WGS84 经纬度转换为平面坐标(墨卡托投影或简单线性缩放)
-
轨迹绘制:在画布上按时间顺序连线
-
里程计算:相邻点间用 Haversine 公式计算大圆距离
-
时间统计:首条与末条时间戳差值
-
输出结果:PNG 图片 + 控制台打印总里程和时间
-
项目结构
farm_trajectory_plotter/ ├── data/ │ └── gps_data.csv ├── output/ │ └── trajectory.png ├── src/ │ ├── init.py │ ├── coordinate_transform.py │ ├── distance_calc.py │ ├── plotter.py │ └── main.py ├── README.md └── requirements.txt
- 核心代码实现
"src/coordinate_transform.py"
import math
def wgs84_to_mercator(lat, lon): """ 将 WGS84 经纬度转换为墨卡托投影坐标 (x, y) 适用于小范围区域,避免复杂投影库 """ x = lon * 20037508.34 / 180 y = math.log(math.tan((90 + lat) * math.pi / 360)) / (math.pi / 180) y = y * 20037508.34 / 180 return x, y
"src/distance_calc.py"
from math import radians, sin, cos, sqrt, atan2
def haversine(lat1, lon1, lat2, lon2): """ 使用 Haversine 公式计算两点间的大圆距离 (米) """ R = 6371000 # 地球半径(米) phi1, phi2 = radians(lat1), radians(lat2) dphi = radians(lat2 - lat1) dlambda = radians(lon2 - lon1)
a = sin(dphi/2)**2 + cos(phi1)*cos(phi2)*sin(dlambda/2)**2
c = 2 * atan2(sqrt(a), sqrt(1-a))
return R * c
"src/plotter.py"
import matplotlib.pyplot as plt from src.coordinate_transform import wgs84_to_mercator
def draw_trajectory(points, output_path): """ 绘制轨迹并保存为图片 points: list of (lat, lon) """ x_coords = [] y_coords = [] for lat, lon in points: mx, my = wgs84_to_mercator(lat, lon) x_coords.append(mx) y_coords.append(my)
plt.figure(figsize=(10, 8))
plt.plot(x_coords, y_coords, marker='o', markersize=3, linewidth=2)
plt.title("农机行驶轨迹")
plt.xlabel("X (墨卡托)")
plt.ylabel("Y (墨卡托)")
plt.grid(True)
plt.savefig(output_path)
plt.close()
"src/main.py"
import csv import datetime from src.distance_calc import haversine from src.plotter import draw_trajectory
def main(): input_file = "data/gps_data.csv" output_image = "output/trajectory.png"
points = []
total_distance = 0.0
start_time = None
end_time = None
with open(input_file, 'r') as f:
reader = csv.DictReader(f)
prev_lat, prev_lon = None, None
for row in reader:
lat = float(row['latitude'])
lon = float(row['longitude'])
timestamp = datetime.datetime.fromisoformat(row['timestamp'])
points.append((lat, lon))
if prev_lat is not None:
total_distance += haversine(prev_lat, prev_lon, lat, lon)
if start_time is None:
start_time = timestamp
end_time = timestamp
prev_lat, prev_lon = lat, lon
duration = (end_time - start_time).total_seconds() / 60 # 分钟
draw_trajectory(points, output_image)
print(f"总里程: {total_distance:.2f} 米 ({total_distance/1000:.2f} 公里)")
print(f"行驶时间: {duration:.2f} 分钟")
if name == "main": main()
- 示例数据 "data/gps_data.csv"
timestamp,latitude,longitude 2026-02-13T05:00:00,30.123456,120.123456 2026-02-13T05:01:00,30.124000,120.124000 2026-02-13T05:02:00,30.125000,120.125500
- README.md
农机行驶轨迹绘制程序
功能
- 读取 GPS 经纬度时间序列
- 转换为平面坐标并绘制轨迹
- 计算总里程和行驶时间
- 输出 PNG 图片
安装依赖
bash
pip install -r requirements.txt
运行
bash
python src/main.py
数据格式
CSV 文件,列:timestamp, latitude, longitude
- requirements.txt
matplotlib
- 核心知识点卡片
知识点 说明 WGS84 经纬度 全球定位系统使用的地理坐标系 墨卡托投影 将球面坐标转为平面坐标,适合局部区域 Haversine 公式 计算球面上两点间最短距离 Matplotlib Python 绘图库,用于生成轨迹图 CSV 处理 使用 "csv.DictReader" 读取结构化数据
- 总结
本项目展示了如何将智能农机的 GPS 数据转化为直观的轨迹图,并计算关键指标(里程、时间)。
通过模块化设计,代码易于维护和扩展,例如未来可加入:
- 实时数据流处理
- 多农机轨迹对比
- 农田边界叠加
- Web 可视化(Flask/Dash)
这不仅是一个技术练习,更是智慧农业中数据驱动决策的典型应用。
如果你需要,可以生成完整的 GitHub 仓库结构并打包成 zip 下载,或者添加Web 版本让非程序员也能上传 CSV 并查看轨迹。
利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!