第六篇:Android / IoT 如何接入 RTK 模块?——串口、蓝牙、TCP 工程实践

第六篇:Android / IoT 如何接入 RTK 模块?——串口、蓝牙、TCP 工程实践 上一篇我们讲了《NMEA、RTCM、NTRIP 到底是什么——RTK 数据链路详解》很多人已经知道NMEA 负责输出定位结果 RTCM 负责传输差分数据 NTRIP 负责通过网络传输 RTCM但问题来了这些数据在真实项目里到底怎么接Android 怎么拿到 RTK 数据IoT 设备怎么和 RTK 模块通信串口、蓝牙、TCP 又分别是什么场景今天这一篇我们就从工程视角真正讲透Android / IoT 如何接入 RTK 模块一、先理解一个核心问题很多人以为接 RTK 调一个 SDK其实真实工程里很多时候并不是这样。尤其是机器人、割草机、AGV、巡检设备这些场景RTK 模块通常是一个独立硬件。它通过串口蓝牙USBTCP4G 网络把定位数据输出给上层系统。所以在 Android / IoT 工程里真正要做的是接收数据流然后解析数据流最后交给地图和机器人控制系统使用二、RTK 模块到底输出什么RTK 模块通常会输出NMEA 定位数据例如$GNGGA,092750.000,3123.456789,N,12034.567890,E,4,18,0.8,12.3,M,0.0,M,,*6A第一次看到这种数据很多人会懵。但它本质上就是一行文本这一行里面包含时间经纬度Fix 状态卫星数量海拔精度因子所以 Android / IoT 上层最常见的工作就是读取 NMEA 字符串 解析经纬度 判断 Fix 状态 更新机器人当前位置三、真实工程中的整体链路真实项目里通常是这样RTK 模块 ↓ 串口 / 蓝牙 / TCP ↓ Android / Linux / MCU ↓ 解析 NMEA ↓ 转换坐标 ↓ 更新地图位置 ↓ 机器人控制系统使用如果还涉及差分数据链路可能是NTRIP Server ↓ 获取 RTCM 差分流 ↓ 发送给 RTK 模块 ↓ RTK 模块完成解算 ↓ 输出 Fix 后的 NMEA所以你会发现RTK 接入并不是一个点。而是一条完整数据链路。四、第一种接入方式串口这是最常见的方式。在很多机器人设备里RTK 模块会通过 UART 串口连接主控板。例如/dev/ttyS1 /dev/ttyS3 /dev/ttyUSB0Android 或 Linux 上层程序不断从串口读取数据。五、串口接入的核心流程核心流程非常简单打开串口 ↓ 设置波特率 ↓ 读取字节流 ↓ 拼接成完整 NMEA 行 ↓ 解析数据 ↓ 更新定位状态例如波特率可能是9600 38400 115200具体要看 RTK 模块配置。六、串口接入最容易踩的坑1. 半包问题串口读出来的数据不一定是一整行。例如你想要的是$GNGGA,092750.000,3123.456789,N,12034.567890,E,4,18...但实际可能分几次读到$GNGGA,092750.000,3123下一次才读到.456789,N,12034.567890,E,4,18...所以不能每次 read 就立刻解析。必须先缓存。等遇到\n再认为是一条完整 NMEA。2. 粘包问题也可能一次读到多条$GNGGA,... $GNRMC,... $GNGSA,...所以你要按行拆分。而不是按 read 次数拆分。3. 编码问题NMEA 本质是 ASCII 文本。通常按ASCII / UTF-8处理即可。但不要直接乱转编码。否则容易出现解析异常。七、Android 串口读取的核心思想在 Android 里如果设备有串口权限通常会有一个串口库或者厂商提供的 SDK。核心代码思想大概是while (running) { val bytes serialPort.read() buffer.append(bytes.toString(Charsets.US_ASCII)) while (buffer contains \n) { val line buffer.readLine() parseNmea(line) } }重点不是代码多复杂。重点是串口是字节流不是消息流所以你必须自己处理半包 粘包 换行 缓存 异常重连八、第二种接入方式蓝牙有些 RTK 设备比如手持 RTK、外置 GNSS 接收机会通过蓝牙输出定位数据。Android 手机或平板可以通过蓝牙连接。蓝牙接入流程通常是搜索设备 ↓ 配对设备 ↓ 建立蓝牙 Socket ↓ 读取 InputStream ↓ 解析 NMEA你会发现它和串口非常像。因为本质上蓝牙也是数据流只不过底层通信方式不同。九、蓝牙接入的常见问题1. 连接不稳定蓝牙容易受到距离障碍物设备休眠系统省电策略影响。所以必须做断线重连2. Android 权限问题Android 新版本蓝牙权限变复杂了。例如可能涉及BLUETOOTH_CONNECT BLUETOOTH_SCAN ACCESS_FINE_LOCATION不同 Android 版本权限处理不同。这是实际开发中很常见的问题。3. 后台保活问题如果你的 App 退到后台蓝牙连接可能被系统回收。所以机器人类应用通常需要前台服务来维持连接。十、第三种接入方式TCP有些 RTK 模块或者中间设备会直接通过 TCP 输出数据。例如192.168.1.100:9000Android 作为客户端连接这个地址然后持续读取数据。TCP 接入流程通常是创建 Socket ↓ 连接 IP 和端口 ↓ 读取 InputStream ↓ 按行拆分 NMEA ↓ 解析定位结果它和串口、蓝牙一样最终都是读取数据流十一、TCP 接入的常见问题1. 网络断开机器人移动过程中WiFi 或 4G 可能不稳定。所以需要心跳 断线检测 自动重连2. 数据延迟定位数据是实时数据。如果 TCP 数据延迟太大地图上的机器人位置就会滞后。所以要关注时间戳 数据频率 延迟3. 旧数据不能乱用有时候网络恢复后可能会收到缓存数据。但机器人已经移动了。这时候如果直接使用旧定位地图会突然跳。所以工程里要判断数据时间是否过期十二、NMEA 解析应该关注哪些字段在机器人项目中最重要的通常不是所有字段。而是这几个1. 经纬度这是机器人位置的基础。例如latitude longitude2. Fix 状态这个非常关键。比如 GGA 里的定位质量字段。常见含义0无定位 1普通 GPS 2差分定位 4RTK Fix 5RTK Float实际项目里必须根据这个字段判断定位是否可信不能只要有经纬度就用。3. 卫星数量例如satellites 18卫星数量太少定位就不稳定。4. HDOP可以简单理解为定位精度因子数值越小通常越好。如果 HDOP 很大说明当前定位质量不理想。十三、为什么不能只看经纬度这是很多新人容易犯的错。他们只要拿到lat lng就直接显示在地图上。但真实机器人里这是不够的。你还必须判断是否 Fix卫星数量够不够HDOP 是否正常数据是否过期是否突然跳点是否和上一帧位置连续否则机器人地图位置会非常不稳定。十四、RTK 数据进入系统后怎么设计在 Android / IoT 里更建议把 RTK 当成一个独立数据源。例如RtkDataSource ↓ RtkRepository ↓ LocationUseCase ↓ MapViewModel ↓ Map UI / Robot Control不要在 UI 层直接解析 NMEA。因为 NMEA 是底层通信数据。UI 层只应该关心当前位置 定位状态 精度 是否可用十五、推荐的数据模型可以设计一个统一模型data class RtkLocation( val latitude: Double, val longitude: Double, val fixType: FixType, val satelliteCount: Int, val hdop: Double?, val timestamp: Long, val isValid: Boolean )FixType 可以是enum class FixType { NONE, GPS, DGPS, RTK_FLOAT, RTK_FIX }这样上层就不用关心 NMEA 细节。十六、定位数据如何分发在 Android 里 可以用StateFlow SharedFlow Callback LiveData我更建议StateFlow因为定位状态天然是一个当前最新状态例如val rtkLocationFlow: StateFlowRtkLocation?地图页面订阅它。机器人控制模块也可以订阅它。十七、工程里必须做的保护真实项目中一定不能裸用 RTK 数据。至少要做这些保护1. Fix 状态过滤例如只有RTK_FIX才认为是高可信。如果是RTK_FLOAT GPS NONE要降级处理。2. 跳点过滤如果上一秒位置在 A下一秒突然跳出去 20 米就不能立刻相信。要结合速度 时间间隔 最大移动距离判断是否异常。3. 数据超时判断如果超过几秒没有新数据说明定位已经不新鲜了。例如3 秒没有更新就应该认为 RTK 数据不可用。4. 异常重连串口、蓝牙、TCP 都可能断。所以必须有重连机制不能断了就死。十八、差分数据在 Android 里怎么处理这里要分两种情况。第一种RTK 模块自己处理 NTRIP有些高级 RTK 模块自己可以连接 NTRIP Server。它内部完成获取 RTCM 完成解算 输出 NMEAAndroid 只需要读取 NMEA。这种最简单。第二种Android 负责获取 RTCM有些方案里Android 需要连接 NTRIP Server拿到 RTCM 差分流再通过串口或蓝牙写回 RTK 模块。流程是Android 连接 NTRIP ↓ 获取 RTCM ↓ 写入 RTK 模块 ↓ RTK 模块完成 Fix ↓ 输出 NMEA这种就复杂一些。因为 Android 同时要处理NTRIP 网络输入 RTCM 写入模块 NMEA 读取模块本质上是双向数据流。十九、真实机器人定位系统架构真实工程里大概是RTK 模块 ↓ NMEA 数据 ↓ RtkDataSource ↓ RtkRepository ↓ 定位质量判断 ↓ 坐标转换 ↓ 地图系统 ↓ 电子围栏 ↓ 路径规划 ↓ 运动控制如果有 IMURTK IMU 编码器 ↓ 融合定位 ↓ 机器人当前位姿最终机器人需要的不是单纯经纬度。而是当前位姿包括x y heading speed status二十、面试怎么回答如果面试官问“Android / IoT 如何接入 RTK 模块”推荐回答标准答案面试版Android / IoT 接入 RTK 模块本质上是接入 RTK 的数据流。常见方式包括串口 UART蓝牙USBTCP SocketRTK 模块通常会输出 NMEA 数据上层系统需要读取数据流处理半包、粘包按行解析 NMEA。重点解析经纬度Fix 状态卫星数量HDOP时间戳如果需要差分数据Android 还可能需要通过 NTRIP 获取 RTCM再写入 RTK 模块。真实机器人系统中不会直接裸用经纬度而是会做Fix 状态过滤跳点过滤数据超时判断异常重连坐标转换与 IMU / 编码器融合最终提供给地图、电子围栏和运动控制系统使用。二十一、总结一句话总结接 RTK不是简单拿经纬度而是接入一条实时定位数据链路串口、蓝牙、TCP本质都是读取数据流 解析 NMEA 判断定位质量 输出稳定位置真正的工程重点不是能不能读到数据而是数据稳不稳 状态准不准 异常能不能处理 系统能不能长期运行这才是 Android / IoT 接入 RTK 的核心。下篇预告下一篇我们继续《RTK 地图 机器人完整定位系统架构解析》深入讲透RTK 数据如何进入地图系统经纬度如何转换为地图坐标机器人当前位置如何显示电子围栏如何参与判断路径规划如何使用定位数据RTK、IMU、地图、控制系统如何协同工作这些才是真正的机器人定位系统架构。《RTK / GNSS 工程实战系列》为什么机器人能厘米级定位——一篇讲透 GPS、北斗 与 RTKRTK 为什么比 GPS 准——差分定位原理详解机器人为什么会“漂”——RTK 漂移问题详解Point-In-Polygon 是什么——机器人电子围栏核心算法NMEA、RTCM、NTRIP 到底是什么——RTK 数据链路详解Android / IoT 如何接入 RTK 模块——串口、蓝牙、TCP 工程实践RTK 地图 机器人完整定位系统架构解析