Skip to main content

A precise PPK + MRK-based geotagging tool for DJI RTK drones

Project description

DJI Geotagger

A precise PPK + MRK-based geotagging tool for DJI RTK drones

This Python library enables centimetre-level camera geotagging by combining PPK .pos solutions, DJI .MRK gimbal offset corrections, and EXIF/XMP metadata from DJI RTK drone images. It is designed for photogrammetry and remote sensing workflows that require accurate EOPs.

Features

  • Batch process .obs raw GNSS logs into RINEX and perform PPK with RTKLIB
  • Download precise ephemeris data (SP3/CLK) automatically
  • Parse DJI .MRK and interpolate correction vectors to camera center (ECEF)
  • Match images by GPS time, apply PPK + MRK correction with covariance propagation
  • Export geotagged results in ECEF/ENU/UTM with estimated 3D precision
  • Support for DJI P1, M300, and other RTK-enabled drones

Installation

git clone https://github.com/RayPan-UC/dji-geotagger.git
cd dji-geotagger
pip install dji-geotagger

Dependencies

  • Python ≥ 3.9
  • pillow, defusedxml, pandas, numpy, pyproj, tqdm
  • RTKLIB (convbin.exe, rnx2rtkp.exe)

Workflow Overview

  1. Convert raw GNSS to RINEXUses RTKLIB convbin for both base and rover logs.
  2. Download precise IGS ephemerisAutomatically fetch .sp3 and .clk based on RINEX timestamps.
  3. Run PPKBatch PPK processing using rnx2rtkp with optional override base coordinates from PPP .sum file.
  4. Parse image EXIF/XMP metadataExtracts capture time, attitude, and gimbal orientation.
  5. Parse MRK filesConverts NED to ENU, then ENU → ECEF correction vectors.
  6. Interpolate camera centerMatches MRK by time, interpolates PPK positions, applies gimbal offset.
  7. Export results Generates a DataFrame (or CSV) of corrected positions and attitude per image.

Example Usage

from pathlib import Path
from pyproj import CRS
from dji_geotagger import *

# === User-defined project path ===
project_root = Path(r"/path/to/your/project/SynopticSite1")

# === Clean temporary directories ===
clean_temp_dirs()

# === Convert base and rover raw logs to RINEX ===
rover_dir = raw_to_rinex_batch(
    keywords=['20250513', 'PPKRAW', '.bin'],
    input_dir=project_root,
    type="rover"
)

base_obs, base_nav = raw_to_rinex_batch(
    keywords=['20250513', '0006', 'DRTK', '.dat'],
    input_dir=project_root,
    type="base",
)

# === Pause here to process base .sum file if available ===

ppp_sum_file = pause_for_PPP_sum_file()


# === Post-process PPK with base .sum file ===
process_ppk(
    base_obs=base_obs,
    base_nav=base_nav,
    rover_dir=rover_dir,
    override_base_from_sum_file=ppp_sum_file,
    output_dir=Path("temp/ppk_result"),
)

# === Compute corrected camera positions ===
final_df = load_and_compute_camera_positions(
    mrk_dir=project_root,
    img_dir=project_root,
    pos_dir=Path("temp/ppk_result"),
    base_sum_file=ppp_sum_file
)

# === Transform to target coordinate system (e.g., WGS84/UTM) ===
target_crs = 32612
final_df = transform_coordinates(
    final_df,
    target_crs=CRS.from_user_input(target_crs),
    out_x="Easting",
    out_y="Northing",
    out_z="Height_Ellp",
    cov_ecef2enu=True,
    drop_original=True
)

# === Save result as CSV ===
save_csv(final_df)

Output Format

The output CSV contains the following columns:

Column Name Description
file_name Image file name
gps_week GPS week number
gps_time Seconds into the GPS week
sd_x_ecef Standard deviation in ECEF X (metres)
sd_y_ecef Standard deviation in ECEF Y (metres)
sd_z_ecef Standard deviation in ECEF Z (metres)
cov_ecef_flat Flattened 3×3 ECEF covariance matrix (row-major, space-separated)
flight_roll Aircraft body roll (degrees)
flight_pitch Aircraft body pitch (degrees)
flight_yaw Aircraft body yaw (degrees)
gimbal_roll Gimbal-reported roll (degrees)
gimbal_pitch Gimbal-reported pitch (degrees)
gimbal_yaw Gimbal-reported yaw (degrees)
dji_geotagger_roll Corrected camera roll for photogrammetry (degrees), with gimbal lock handling
dji_geotagger_pitch Corrected camera pitch for photogrammetry (degrees), computed as gimbal_pitch + 90
dji_geotagger_yaw Camera yaw for photogrammetry (degrees), taken directly from flight_yaw
Easting Easting in WGS84 / UTM Zone 12N (metres)
Northing Northing in WGS84 / UTM Zone 12N (metres)
Height_Ellp Height in WGS84 ellipsoidal coordinates (metres)
sd_E Standard deviation in Easting (ENU, metres)
sd_N Standard deviation in Northing (ENU, metres)
sd_U Standard deviation in Up (ENU, metres)
cov_enu_flat Flattened 3×3 ENU covariance matrix (row-major, space-separated)

Note: The projected coordinates (Easting, Northing, Height) are output in WGS84 / UTM Zone 12N by default. Users can customize the coordinate reference system (CRS) and output column formats according to their project requirements.

License

This project is licensed under the BSD 2-Clause (see LICENSE for details).

Acknowledgments

  • Developed at the University of Calgary, Applied Geospatial Research Group (appliedgrg.ca)
  • Inspired by real-world field workflows involving DJI Matrice 350 RTK + Zenmuse P1, Hemisphere base stations, and CSRS-PPP post-processing

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dji_geotagger-1.0.11.tar.gz (24.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dji_geotagger-1.0.11-py3-none-any.whl (27.5 kB view details)

Uploaded Python 3

File details

Details for the file dji_geotagger-1.0.11.tar.gz.

File metadata

  • Download URL: dji_geotagger-1.0.11.tar.gz
  • Upload date:
  • Size: 24.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for dji_geotagger-1.0.11.tar.gz
Algorithm Hash digest
SHA256 d4c4da20a96e6a0b59521ca460af74c4b6e5c544431a740eaf0abd4c73bd53ff
MD5 98afa284c6e7ada3f37a8aa67e064d43
BLAKE2b-256 d7752cd76a3511fae650382419f8d2c7924d38d50b1e4af45456ef283ecda464

See more details on using hashes here.

File details

Details for the file dji_geotagger-1.0.11-py3-none-any.whl.

File metadata

  • Download URL: dji_geotagger-1.0.11-py3-none-any.whl
  • Upload date:
  • Size: 27.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for dji_geotagger-1.0.11-py3-none-any.whl
Algorithm Hash digest
SHA256 6b6ad70f674e533722f2f797b84c484829984d0077addd4563d67512eb861f1f
MD5 f04f3a706268f4512c64bdbbbe1d22a6
BLAKE2b-256 42be82a74f0031ddd616a2968142254cd6d89757ab016b37b0e37be92939145b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page