Skip to content

Commit 52bd5f8

Browse files
generatedunixname2711760795700672meta-codesync[bot]
authored andcommitted
fbcode/mapillary/opensfm/opensfm/geotag_from_gpx.py
Reviewed By: hanle11 Differential Revision: D99824734 fbshipit-source-id: cd31d19224cfeb0c651d8e02124046013d35fb55
1 parent 6cbe48a commit 52bd5f8

File tree

1 file changed

+58
-25
lines changed

1 file changed

+58
-25
lines changed

opensfm/geotag_from_gpx.py

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
#!/usr/bin/python3
22

3-
# pyre-unsafe
3+
# pyre-strict
44

55
import datetime
66
import math
77
import os
88
import shutil
99
import sys
1010
import time
11-
from typing import List, Union
1211

1312
import numpy as np
1413
from opensfm import geo
@@ -54,12 +53,14 @@
5453
"""
5554

5655

57-
def utc_to_localtime(utc_time):
56+
def utc_to_localtime(utc_time: datetime.datetime) -> datetime.datetime:
5857
utc_offset_timedelta = datetime.datetime.utcnow() - datetime.datetime.now()
5958
return utc_time - utc_offset_timedelta
6059

6160

62-
def get_lat_lon_time(gpx_file: str, gpx_time: str = "utc"):
61+
def get_lat_lon_time(
62+
gpx_file: str, gpx_time: str = "utc"
63+
) -> list[tuple[datetime.datetime, float, float, float]]:
6364
"""
6465
Read location and time stamps from a track in a GPX file.
6566
@@ -118,7 +119,10 @@ def compute_bearing(
118119
return bearing
119120

120121

121-
def interpolate_lat_lon(points, t):
122+
def interpolate_lat_lon(
123+
points: list[tuple[datetime.datetime, float, float, float]],
124+
t: datetime.datetime,
125+
) -> tuple[float, float, float, float | None]:
122126
"""
123127
Return interpolated lat, lon and compass bearing for time t.
124128
@@ -158,7 +162,7 @@ def interpolate_lat_lon(points, t):
158162
return lat, lon, bearing, ele
159163

160164

161-
def to_deg(value, loc):
165+
def to_deg(value: float, loc: list[str]) -> tuple[int, int, float, str]:
162166
"""
163167
Convert decimal position to degrees.
164168
"""
@@ -176,7 +180,11 @@ def to_deg(value, loc):
176180
return (deg, mint, sec, loc_value)
177181

178182

179-
def gpx_lerp(alpha: int, a, b):
183+
def gpx_lerp(
184+
alpha: float,
185+
a: tuple[datetime.datetime, float, float, float],
186+
b: tuple[datetime.datetime, float, float, float],
187+
) -> tuple[datetime.datetime, float, float, float]:
180188
"""Interpolate gpx point as (1 - alpha) * a + alpha * b"""
181189
dt = alpha * (b[0] - a[0]).total_seconds()
182190
t = a[0] + datetime.timedelta(seconds=dt)
@@ -186,7 +194,12 @@ def gpx_lerp(alpha: int, a, b):
186194
return t, lat, lon, alt
187195

188196

189-
def segment_sphere_intersection(A, B, C, r):
197+
def segment_sphere_intersection(
198+
A: tuple[float, float, float],
199+
B: tuple[float, float, float],
200+
C: tuple[float, float, float],
201+
r: float,
202+
) -> float:
190203
"""Intersect the segment AB and the sphere (C,r).
191204
192205
Assumes A is inside the sphere and B is outside.
@@ -202,30 +215,50 @@ def segment_sphere_intersection(A, B, C, r):
202215
return (-b + np.sqrt(d)) / (2 * a)
203216

204217

205-
def space_next_point(a, b, last, dx):
218+
def space_next_point(
219+
a: tuple[datetime.datetime, float, float, float],
220+
b: tuple[datetime.datetime, float, float, float],
221+
last: tuple[datetime.datetime, float, float, float],
222+
dx: float,
223+
) -> tuple[datetime.datetime, float, float, float]:
206224
A = geo.ecef_from_lla(a[1], a[2], 0.0)
207225
B = geo.ecef_from_lla(b[1], b[2], 0.0)
208226
C = geo.ecef_from_lla(last[1], last[2], 0.0)
209227
alpha = segment_sphere_intersection(A, B, C, dx)
210228
return gpx_lerp(alpha, a, b)
211229

212230

213-
def time_next_point(a, b, last, dt):
231+
def time_next_point(
232+
a: tuple[datetime.datetime, float, float, float],
233+
b: tuple[datetime.datetime, float, float, float],
234+
last: tuple[datetime.datetime, float, float, float],
235+
dt: float,
236+
) -> tuple[datetime.datetime, float, float, float]:
214237
da = (a[0] - last[0]).total_seconds()
215238
db = (b[0] - last[0]).total_seconds()
216239
alpha = (dt - da) / (db - da)
217240
return gpx_lerp(alpha, a, b)
218241

219242

220-
def time_distance(a, b) -> int:
243+
def time_distance(
244+
a: tuple[datetime.datetime, float, float, float],
245+
b: tuple[datetime.datetime, float, float, float],
246+
) -> float:
221247
return (b[0] - a[0]).total_seconds()
222248

223249

224-
def space_distance(a, b) -> float:
250+
def space_distance(
251+
a: tuple[datetime.datetime, float, float, float],
252+
b: tuple[datetime.datetime, float, float, float],
253+
) -> float:
225254
return geo.gps_distance(a[1:3], b[1:3])
226255

227256

228-
def sample_gpx(points, dx: float, dt=None):
257+
def sample_gpx(
258+
points: list[tuple[datetime.datetime, float, float, float]],
259+
dx: float,
260+
dt: float | None = None,
261+
) -> list[tuple[datetime.datetime, float, float, float]]:
229262
if dt is not None:
230263
dx = float(dt)
231264
print("Sampling GPX file every {0} seconds".format(dx))
@@ -251,12 +284,12 @@ def sample_gpx(points, dx: float, dt=None):
251284

252285

253286
def add_gps_to_exif(
254-
filename: Union["os.PathLike[str]", str],
255-
lat,
256-
lon,
257-
bearing,
258-
elevation,
259-
updated_filename: Union[None, "os.PathLike[str]", str] = None,
287+
filename: os.PathLike[str] | str,
288+
lat: float,
289+
lon: float,
290+
bearing: float,
291+
elevation: float | None,
292+
updated_filename: os.PathLike[str] | str | None = None,
260293
remove_image_description: bool = True,
261294
) -> None:
262295
"""
@@ -308,12 +341,12 @@ def add_gps_to_exif(
308341

309342

310343
def add_exif_using_timestamp(
311-
filename,
312-
points,
344+
filename: os.PathLike[str] | str,
345+
points: list[tuple[datetime.datetime, float, float, float]],
313346
offset_time: int = 0,
314-
timestamp=None,
347+
timestamp: datetime.datetime | None = None,
315348
orientation: int = 1,
316-
image_description=None,
349+
image_description: str | None = None,
317350
) -> None:
318351
"""
319352
Find lat, lon and bearing of filename and write to EXIF.
@@ -403,10 +436,10 @@ def add_exif_using_timestamp(
403436

404437
if path.lower().endswith(".jpg"):
405438
# single file
406-
file_list: List[str] = [path]
439+
file_list: list[str] = [path]
407440
else:
408441
# folder(s)
409-
file_list: List[str] = []
442+
file_list: list[str] = []
410443
for root, _, files in os.walk(path):
411444
file_list += [
412445
os.path.join(root, filename)

0 commit comments

Comments
 (0)