11#!/usr/bin/python3
22
3- # pyre-unsafe
3+ # pyre-strict
44
55import datetime
66import math
77import os
88import shutil
99import sys
1010import time
11- from typing import List , Union
1211
1312import numpy as np
1413from opensfm import geo
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
253286def 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
310343def 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