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
.obsraw GNSS logs into RINEX and perform PPK with RTKLIB - Download precise ephemeris data (SP3/CLK) automatically
- Parse DJI
.MRKand 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
- Convert raw GNSS to RINEXUses RTKLIB
convbinfor both base and rover logs. - Download precise IGS ephemerisAutomatically fetch
.sp3and.clkbased on RINEX timestamps. - Run PPKBatch PPK processing using
rnx2rtkpwith optional override base coordinates from PPP.sumfile. - Parse image EXIF/XMP metadataExtracts capture time, attitude, and gimbal orientation.
- Parse MRK filesConverts NED to ENU, then ENU → ECEF correction vectors.
- Interpolate camera centerMatches MRK by time, interpolates PPK positions, applies gimbal offset.
- 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4c4da20a96e6a0b59521ca460af74c4b6e5c544431a740eaf0abd4c73bd53ff
|
|
| MD5 |
98afa284c6e7ada3f37a8aa67e064d43
|
|
| BLAKE2b-256 |
d7752cd76a3511fae650382419f8d2c7924d38d50b1e4af45456ef283ecda464
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6b6ad70f674e533722f2f797b84c484829984d0077addd4563d67512eb861f1f
|
|
| MD5 |
f04f3a706268f4512c64bdbbbe1d22a6
|
|
| BLAKE2b-256 |
42be82a74f0031ddd616a2968142254cd6d89757ab016b37b0e37be92939145b
|