Skip to content

RayPan-UC/dji-geotagger

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DJI Geotagger Downloads

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
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 RINEX Uses RTKLIB convbin for both base and rover logs.
  2. Download precise IGS ephemeris Automatically fetch .sp3 and .clk based on RINEX timestamps.
  3. Run PPK Batch PPK processing using rnx2rtkp with optional override base coordinates from PPP .sum file.
  4. Parse image EXIF/XMP metadata Extracts capture time, attitude, and gimbal orientation.
  5. Parse MRK files Converts NED to ENU, then ENU to ECEF correction vectors.
  6. Interpolate camera centre Matches 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

About

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

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages