精准定位

功能说明

RTK Precise Position 功能用于将 DJI PSDK 订阅到的 RTK 定位、速度、航向和解状态转换为 MAVLink 标准定位消息输出。

本功能只负责“PSDK RTK 数据 -> MAVLink 定位消息”的转换,不负责启动网络 RTK 服务。网络 RTK 服务的账号、NTRIP 配置和启停请参考 network_rtk.md

相关文件

文件 说明
src/dji_function/dji_sub_callback.cpp RTK 订阅、坐标转换、MAVLink 定位消息发送
src/dji_mavlink/mavlink_tool.h MAVLink 工具函数、坐标/角度转换函数

PSDK 订阅 Topic

PSDK Topic 频率 用途
DJI_FC_SUBSCRIPTION_TOPIC_RTK_POSITION 5 Hz RTK 经纬度和高程
DJI_FC_SUBSCRIPTION_TOPIC_RTK_VELOCITY 5 Hz RTK 速度
DJI_FC_SUBSCRIPTION_TOPIC_RTK_YAW 5 Hz RTK 双天线航向
DJI_FC_SUBSCRIPTION_TOPIC_RTK_POSITION_INFO 5 Hz RTK 定位解状态
DJI_FC_SUBSCRIPTION_TOPIC_RTK_YAW_INFO 5 Hz RTK 航向解状态
DJI_FC_SUBSCRIPTION_TOPIC_RTK_CONNECT_STATUS 5 Hz RTK 连接状态

输出 MAVLink 消息

MAVLink 消息 说明
GPS_RAW_INT 主 GPS/RTK 定位输出
GPS2_RAW 第二路 GPS/RTK 定位输出,内容与 RTK 主定位一致
GPS_INPUT 给飞控/上位机使用的 GPS 输入格式
GLOBAL_POSITION_INT 全局位置、相对高度、速度和航向
GPS_RTK 主 RTK 状态
GPS2_RTK 第二路 RTK 状态

坐标系和单位

坐标系转换必须保持以下规则,避免 MAVLink 侧坐标混乱。

数据 DJI/PSDK 来源 MAVLink 输出 转换说明
纬度 RTK_POSITION.latitude,单位 degree lat,单位 degE7 degree * 1e7
经度 RTK_POSITION.longitude,单位 degree lon,单位 degE7 degree * 1e7
高程 RTK_POSITION.hfsl,单位 m alt,单位 mm m * 1000
北向速度 RTK_VELOCITY.x vn / vx 保持 North 方向
东向速度 RTK_VELOCITY.y ve / vy 保持 East 方向
垂向速度 RTK_VELOCITY.z vd / vz MAVLink NED 使用 Down,输出时取负
RTK 航向 RTK_YAW yaw / hdg,单位 cdeg DJI RTK yaw 为 ANT1->ANT2,输出前减 90 deg

航向转换

DJI RTK 双天线 yaw 与 MAVLink 车辆航向存在 90 度偏移,代码中统一使用:

mavlink_yaw_deg = dji_rtk_yaw_deg - 90
mavlink_yaw_cdeg = normalize_0_360(mavlink_yaw_deg) * 100

当结果为 0 deg 时,GPS_RAW_INT.yaw 按 MAVLink 约定输出 36000;当航向不可用时输出 UINT16_MAX

定位解状态映射

DJI RTK 解状态 MAVLink fix_type
窄巷固定解、宽巷固定解、L1 整周模糊度固定解 GPS_FIX_TYPE_RTK_FIXED
浮点解、L1 浮点解、无电离层组合浮点解 GPS_FIX_TYPE_RTK_FLOAT
单点解、伪距差分解、SBAS 解 GPS_FIX_TYPE_3D_FIX
其他/未知 GPS_FIX_TYPE_NO_FIX

数据输出策略

RTK 定位有效时,系统优先输出 RTK 定位数据,并临时抑制普通 GPS 位置回调中的低精度 GPS_RAW_INT / GLOBAL_POSITION_INT 输出。

RTK 定位无效或超过 1 秒未更新时,普通 GPS 输出恢复,避免上位机长时间没有定位消息。

使用流程

  1. 启动程序后,订阅模块自动订阅 RTK 相关 Topic。
  2. 上位机监听标准 MAVLink 定位消息。
  3. 当 RTK 进入 Float 或 Fixed 解时,GPS_RAW_INT.fix_type 变为 GPS_FIX_TYPE_RTK_FLOATGPS_FIX_TYPE_RTK_FIXED
  4. 如需网络 RTK 数据源,先通过 network_rtk.md 中的 Network RTK 功能配置并启动 NTRIP 服务。

Python 例程

以下例程使用 pymavlink 监听 RTK 精准定位相关 MAVLink 消息,并打印经纬度、高度、速度、航向和 RTK 解状态。

import time
from pymavlink import mavutil


def get_current_millis():
    return int(time.time() * 1000)


def fix_type_name(fix_type):
    names = {
        0: "NO_GPS",
        1: "NO_FIX",
        2: "2D_FIX",
        3: "3D_FIX",
        4: "DGPS",
        5: "RTK_FLOAT",
        6: "RTK_FIXED",
    }
    return names.get(fix_type, f"UNKNOWN({fix_type})")


def yaw_cdeg_to_deg(yaw):
    if yaw == 65535:
        return None
    if yaw == 36000:
        return 0.0
    return yaw / 100.0


# 连接无人机(UDP 端口 14550)
master = mavutil.mavlink_connection("udpin:0.0.0.0:14550")
print("等待无人机心跳...")
master.wait_heartbeat()
print(f"无人机已连接: system={master.target_system}, component={master.target_component}")
print("开始监听 RTK 精准定位消息")

message_types = [
    "GPS_RAW_INT",
    "GPS2_RAW",
    "GPS_INPUT",
    "GLOBAL_POSITION_INT",
    "GPS_RTK",
    "GPS2_RTK",
]

while True:
    msg = master.recv_match(type=message_types, blocking=True, timeout=5.0)
    now_ms = get_current_millis()

    if msg is None:
        print(f"[{now_ms}] 超时:未收到 RTK/MAVLink 定位消息")
        continue

    msg_type = msg.get_type()

    if msg_type in ("GPS_RAW_INT", "GPS2_RAW"):
        lat_deg = msg.lat / 1e7
        lon_deg = msg.lon / 1e7
        alt_m = msg.alt / 1000.0
        yaw_deg = yaw_cdeg_to_deg(getattr(msg, "yaw", 65535))
        print(
            f"[{now_ms}] {msg_type}: "
            f"fix={fix_type_name(msg.fix_type)}, "
            f"lat={lat_deg:.7f}, lon={lon_deg:.7f}, alt={alt_m:.3f}m, "
            f"vel={msg.vel / 100.0:.2f}m/s, cog={msg.cog / 100.0:.2f}deg, "
            f"yaw={yaw_deg}"
        )

    elif msg_type == "GPS_INPUT":
        print(
            f"[{now_ms}] GPS_INPUT: "
            f"fix={fix_type_name(msg.fix_type)}, "
            f"lat={msg.lat / 1e7:.7f}, lon={msg.lon / 1e7:.7f}, alt={msg.alt:.3f}m, "
            f"vn={msg.vn:.2f}, ve={msg.ve:.2f}, vd={msg.vd:.2f}"
        )

    elif msg_type == "GLOBAL_POSITION_INT":
        print(
            f"[{now_ms}] GLOBAL_POSITION_INT: "
            f"lat={msg.lat / 1e7:.7f}, lon={msg.lon / 1e7:.7f}, "
            f"alt={msg.alt / 1000.0:.3f}m, relative_alt={msg.relative_alt / 1000.0:.3f}m, "
            f"vx={msg.vx / 100.0:.2f}, vy={msg.vy / 100.0:.2f}, vz={msg.vz / 100.0:.2f}, "
            f"hdg={msg.hdg / 100.0:.2f}deg"
        )

    elif msg_type in ("GPS_RTK", "GPS2_RTK"):
        print(
            f"[{now_ms}] {msg_type}: "
            f"health={msg.rtk_health}, rate={msg.rtk_rate}Hz, nsats={msg.nsats}, "
            f"receiver_id={msg.rtk_receiver_id}"
        )

注意事项

  • MAVLink GLOBAL_POSITION_INT 的速度字段为 NED 坐标系,垂向速度必须使用 Down 为正。
  • RTK 服务状态等于 DJI_TRANSFER 只代表 RTCM/网络数据传输建立,不等于 RTK 已经收敛。是否可用必须看 RTK 定位解状态。
  • GPS_RTK / GPS2_RTK 中没有 DJI 可直接提供的基线详细值时,对应字段使用未知值或 0 填充。
  • 如果地面站只看 GPS_RAW_INT,需要确认其支持 GPS_FIX_TYPE_RTK_FLOATGPS_FIX_TYPE_RTK_FIXED
作者:bai  创建时间:2026-06-23 14:18
最后编辑:bai  更新时间:2026-07-08 09:44