| 参数 | 值 | 说明 |
|---|---|---|
| enableHighAccuracy | true | 高精度模式,使用GPS而非网络定位 |
| timeout | 3000ms (3秒) | 单次定位超时时间 |
| maximumAge | 0ms | 不使用缓存,每次获取最新位置 |
| 目标频率 | ~500ms (2次/秒) | 实际频率由浏览器自动调整 |
| 精度过滤阈值 | > 50米 | 超过此精度的点将被丢弃 |
原理:使用最近N个位置点的加权平均值来平滑GPS数据,消除随机噪声。
// 滑动平均滤波实现
const FILTER_WINDOW_SIZE = 5; // 窗口大小
function smoothPosition(newPos) {
// 1. 添加到历史记录
positionHistory.push({
lat: newPos.latitude,
lng: newPos.longitude,
accuracy: newPos.accuracy,
timestamp: Date.now()
});
// 2. 保持窗口大小
if (positionHistory.length > FILTER_WINDOW_SIZE) {
positionHistory.shift();
}
// 3. 加权平均计算(精度越高权重越大)
let totalWeight = 0;
let weightedLat = 0;
let weightedLng = 0;
for (let pos of positionHistory) {
const weight = 1 / pos.accuracy; // 精度越高权重越大
weightedLat += pos.lat * weight;
weightedLng += pos.lng * weight;
totalWeight += weight;
}
return {
latitude: weightedLat / totalWeight,
longitude: weightedLng / totalWeight,
accuracy: Math.min(...positionHistory.map(p => p.accuracy))
};
}
效果:将GPS漂移从±20米降低到±5米以内。
触发条件(必须同时满足):
| 参数 | 默认值 | 说明 |
|---|---|---|
| radius(半径) | 80米 | 进站判定范围 |
| tolerance(容忍度) | 45° | 方向偏差允许范围 |
| consecutiveCount | 2次 | 连续确认次数 |
| accuracyFilter | >50米 | 精度过滤阈值 |
触发条件(必须同时满足):
设计说明:出站阈值高于进站阈值(80m → 96m),防止在边界反复触发进/出站事件。
// 计算两点之间的方位角(度数)
function calculateHeading(lat1, lng1, lat2, lng2) {
const dLng = toRad(lng2 - lng1);
const y = Math.sin(dLng) * Math.cos(toRad(lat2));
const x = Math.cos(toRad(lat1)) * Math.sin(toRad(lat2)) -
Math.sin(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.cos(dLng);
return (Math.atan2(y, x) * 180 / Math.PI + 360) % 360;
}
// 判断方向是否匹配
const directionDiff = Math.abs(currentHeading - station.direction);
const directionOk = directionDiff <= 45 || directionDiff >= (360 - 45);
作用:防止反向经过站点时误报(例如返程时不会重复报站)。