未开始
⚠️ 非HTTPS环境警告
当前使用的是非加密连接(HTTP),浏览器可能会阻止位置权限请求。
解决方案:请部署到支持HTTPS的服务器,或使用本地测试(localhost)。
📍 实时位置信息
⏸️ GPS未启动
纬度
--
经度
--
精度 (米)
--
速度 (km/h)
--
当前所在站点
📋 事件记录
暂无事件记录
🗺️ 站点行程进度
已过站点 下一站 未到站点
开始行程后显示站点进度
📝 系统运行日志
[系统] 日志系统已就绪...

📍 1. GPS定位参数配置

参数说明
enableHighAccuracytrue高精度模式,使用GPS而非网络定位
timeout3000ms (3秒)单次定位超时时间
maximumAge0ms不使用缓存,每次获取最新位置
目标频率~500ms (2次/秒)实际频率由浏览器自动调整
精度过滤阈值> 50米超过此精度的点将被丢弃

🛡️ 2. 防漂移算法:滑动平均滤波

原理:使用最近N个位置点的加权平均值来平滑GPS数据,消除随机噪声。

算法步骤:
1. 将新位置加入历史队列(最多保留5个点)
2. 计算队列中所有点的平均值
3. 使用平均值作为当前位置
// 滑动平均滤波实现
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米以内。

🎯 3. 进站检测规则

触发条件(必须同时满足):

  1. 距离条件:车辆与站点的直线距离 < 站点半径(80米)
  2. 方向条件:行驶方向与站点预设方向的偏差 < 方向容忍度(45°)
  3. 连续确认:连续2个定位点都满足上述条件(防误触)
  4. 状态检查:当前未处于任何站点范围内
距离公式(Haversine):
d = 2R × arcsin(√(sin²((lat₂-lat₁)/2) + cos(lat₁)×cos(lat₂)×sin²((lng₂-lng₁)/2)))
参数默认值说明
radius(半径)80米进站判定范围
tolerance(容忍度)45°方向偏差允许范围
consecutiveCount2次连续确认次数
accuracyFilter>50米精度过滤阈值

🚪 4. 出站检测规则

触发条件(必须同时满足):

  1. 状态检查:当前处于某个站点范围内
  2. 距离条件:车辆与该站点的直线距离 > 站点半径 × 1.2(96米)

设计说明:出站阈值高于进站阈值(80m → 96m),防止在边界反复触发进/出站事件。

⚙️ 5. 方向过滤机制

// 计算两点之间的方位角(度数)
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);

作用:防止反向经过站点时误报(例如返程时不会重复报站)。

📊 6. 性能优化策略

  • 低功耗模式:使用Wake Lock API防止屏幕休眠
  • 智能更新:站点进度每5次位置更新刷新一次
  • 内存管理:事件记录限制200条,日志限制100条
  • CPU优化:避免频繁DOM操作,批量更新UI
  • 离线支持:所有数据存储在localStorage