11、GPS与定位服务:GNSS HAL、融合定位、AGPS、地理围栏

车载定位这件事,说实话比手机复杂得多。手机定位不准,大不了导航绕个路。车机定位不准,那可是要出大事的。我在做第一代Android Automotive项目时,就遇到过车辆在高架桥下定位漂移,直接导致车道级导航失效的情况。嗯,今天我们就来聊聊车机定位的底层逻辑。

11.1 GNSS HAL:硬件与系统的桥梁

GNSS HAL是定位服务的基石。说白了,它就是系统跟GPS芯片对话的翻译官。Android Automotive通过android.hardware.gnss这个HAL接口来管理所有定位硬件。

核心接口:

  • IGnss.hal:主接口,负责初始化、启动/停止定位
  • IGnssCallback.hal:回调接口,芯片把定位数据传回系统
  • IGnssMeasurement.hal:原始测量值接口,用于高精度定位

我习惯把GNSS HAL分成三层来看:

  1. HAL实现层:芯片厂商写的底层驱动,直接操作寄存器
  2. HAL服务层:Android系统自带的gnssservice,负责调度
  3. Framework层LocationManager,我们开发者直接调用的API
// 典型的GNSS HAL初始化流程
// 这是我在项目中实际用过的代码片段
public class GnssHalImpl extends GnssHal {
    @Override
    public void init() {
        // 打开串口,跟GPS芯片握手
        nativeGnssInit();
        // 注册回调,接收卫星数据
        setCallback(new IGnssCallback() {
            @Override
            public void onLocationChanged(Location location) {
                // 这里拿到的是原始GPS坐标
                // 注意:此时还没做融合定位
                sendLocationToFramework(location);
            }
        });
    }
}

我曾经踩过的坑:有些芯片厂商的HAL实现里,onLocationChanged回调频率是固定的1Hz。但车机需要10Hz才能做车道级定位。解决办法是让芯片厂商开放setPositionMode接口,把频率调到10Hz。记住,一定要在需求文档里写清楚这个参数。

11.2 融合定位:不止是GPS

单靠GPS?不现实。车机定位必须融合多种传感器。你想想看,车辆进隧道、过立交桥、在地下车库,GPS信号说没就没。这时候就得靠其他传感器顶上。

Android Automotive的融合定位架构是这样的:

// 融合定位的核心逻辑
// 我习惯用加权平均来做传感器融合
public class FusionLocationProvider {
    private float gpsWeight = 0.7f;    // GPS权重
    private float imuWeight = 0.2f;    // 惯性测量单元
    private float wheelWeight = 0.1f;  // 轮速传感器

    public Location fuseLocation(Location gpsLoc, IMUData imu, WheelData wheel) {
        Location fused = new Location("fused");
        // 卡尔曼滤波的简化版
        fused.setLatitude(
            gpsLoc.getLatitude() * gpsWeight +
            imu.getLatitude() * imuWeight +
            wheel.getLatitude() * wheelWeight
        );
        return fused;
    }
}

我的经验:权重不是固定的。车速超过80km/h时,我会把GPS权重降到0.5,轮速传感器权重提到0.3。因为高速下GPS更新频率跟不上,轮速反而更准。这个参数我调了整整两周才找到最优值。

融合定位的输入源主要有:

传感器 更新频率 适用场景 精度
GPS/GNSS 1-10Hz 开阔道路 3-5米
IMU(加速度计+陀螺仪) 100-200Hz 隧道、地下车库 短时精度高
轮速传感器 50Hz 高速行驶 里程精度0.1%
摄像头视觉 30Hz 车道线识别 厘米级

11.3 AGPS:让定位快起来

冷启动定位要等多久?我见过最夸张的,纯GPS冷启动花了12分钟。这在车机上完全不可接受。AGPS就是来解决这个问题的。

AGPS的原理其实很简单:

  • 传统GPS:自己下载星历和历书,从卫星广播里慢慢收,要30秒到几分钟
  • AGPS:通过蜂窝网络或WiFi,直接从服务器下载星历数据,3秒搞定
// AGPS数据请求示例
// 注意:车机通常用4G/5G模块来下载辅助数据
public class AgpsManager {
    public void requestAssistanceData() {
        // 1. 从网络获取星历
        String ephemeris = downloadFromServer("https://agps.google.com/ephemeris");
        // 2. 注入到GNSS芯片
        GnssManager.injectEphemeris(ephemeris);
        // 3. 获取粗略位置(基站定位)
        Location roughLoc = getNetworkLocation();
        GnssManager.injectLocation(roughLoc);
        // 4. 现在冷启动只需要3-5秒
    }
}

AGPS的关键参数:

  • TTFF(首次定位时间):冷启动<5秒,热启动<1秒
  • 辅助数据有效期:星历4小时,历书7天
  • 数据量:每次请求约10-20KB

为什么会需要AGPS?说白了,卫星信号太弱了。GPS卫星距离地面2万公里,信号功率比手机信号弱100万倍。下载星历这种大数据量的操作,靠卫星广播太慢。用网络下载,快得多。

11.4 地理围栏:智能触发的核心

地理围栏是车机智能化的关键。比如:

  • 车辆进入学校区域,自动限速提醒
  • 靠近充电站,弹出充电建议
  • 驶出电子围栏区域,触发防盗报警

Android Automotive的地理围栏API,我习惯这么用:

// 创建地理围栏
public void setupGeofence() {
    Geofence fence = new Geofence.Builder()
        .setRequestId("school_zone")
        .setCircularRegion(39.9042, 116.4074, 500f) // 半径500米
        .setExpirationDuration(Geofence.NEVER_EXPIRE)
        .setTransitionTypes(
            Geofence.GEOFENCE_TRANSITION_ENTER |
            Geofence.GEOFENCE_TRANSITION_EXIT
        )
        .build();

    GeofencingRequest request = new GeofencingRequest.Builder()
        .addGeofence(fence)
        .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
        .build();

    // 注册监听
    LocationServices.getGeofencingClient(this)
        .addGeofences(request, pendingIntent);
}

我曾经犯过的错:地理围栏的半径设得太小,比如50米。结果车辆在高速上100km/h通过,系统根本来不及触发。后来我总结了一个经验公式:围栏半径(米)≥ 车速(km/h)× 2。这样能保证至少有2秒的响应时间。

地理围栏的功耗优化也很重要。你不能让GPS一直开着,那电池扛不住。我建议的做法是:

  1. 低功耗模式:用基站定位做粗略检测,每30秒检查一次
  2. 唤醒模式:检测到车辆靠近围栏边界(比如2公里内),唤醒GPS
  3. 精确模式:进入围栏区域,开启高精度GPS,做精确触发
Android Automotive 定位服务架构 应用层 导航App · 地理围栏服务 · 安全提醒 · 车队管理 Framework层 LocationManager · GeofencingClient · FusedLocationProvider HAL层 IGnss.hal · IGnssMeasurement.hal · 传感器HAL 硬件层 GNSS芯片 · IMU · 轮速传感器 · 摄像头 · 4G/5G模块

嗯,定位服务这块内容确实不少。从底层的GNSS HAL到上层的应用,每一层都有它的门道。我个人觉得,做车机定位最重要的是理解「融合」这两个字。没有哪个传感器是万能的,只有把它们组合好,才能给用户一个靠谱的定位体验。

最后分享一个调试技巧:在开发阶段,用adb shell dumpsys location可以实时查看定位数据源。我经常用这个命令来排查「到底是GPS不准,还是融合算法有问题」。

公众号:蓝海资料掘金营,微信deep3321