Skip to content

Commit ced3aa6

Browse files
authored
fix: interpolate invalid GPS timestamps (#696)
* skip invalid GPS timestamps * backfill GPS timestamps with sample times
1 parent 1213ebf commit ced3aa6

File tree

1 file changed

+37
-5
lines changed

1 file changed

+37
-5
lines changed

mapillary_tools/geotag/gpmf_parser.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
import dataclasses
2+
import datetime
23
import io
34
import itertools
45
import pathlib
56
import typing as T
6-
import datetime
7-
87

98
import construct as C
109

1110
from .. import imu
1211
from ..mp4.mp4_sample_parser import MovieBoxParser, Sample, TrackBoxParser
13-
1412
from ..telemetry import GPSFix, GPSPoint
1513

1614
"""
@@ -209,7 +207,11 @@ def gps5_from_stream(
209207

210208
gpsu = indexed.get(b"GPSU")
211209
if gpsu is not None:
212-
epoch_time = _gps5_timestamp_to_epoch_time(gpsu[0][0].decode("utf-8"))
210+
try:
211+
yymmdd = gpsu[0][0].decode("utf-8")
212+
epoch_time = _gps5_timestamp_to_epoch_time(yymmdd)
213+
except Exception:
214+
epoch_time = None
213215
else:
214216
epoch_time = None
215217

@@ -478,6 +480,28 @@ def _extract_dvnm_from_samples(
478480
return dvnm_by_dvid
479481

480482

483+
def _backfill_gps_timestamps(gps_points: T.Iterable[GPSPoint]) -> None:
484+
it = iter(gps_points)
485+
486+
# find the first point with epoch time
487+
last = None
488+
for point in it:
489+
if point.epoch_time is not None:
490+
last = point
491+
break
492+
493+
# if no point with epoch time found, return
494+
if last is None:
495+
return
496+
497+
# backfill points without epoch time
498+
for point in it:
499+
assert last.epoch_time is not None
500+
if point.epoch_time is None:
501+
point.epoch_time = last.epoch_time + (point.time - last.time)
502+
last = point
503+
504+
481505
def _extract_points_from_samples(
482506
fp: T.BinaryIO, samples: T.Iterable[Sample]
483507
) -> TelemetryData:
@@ -549,8 +573,16 @@ def _extract_points_from_samples(
549573
for idx, (z, x, y, *_) in enumerate(sample_magns)
550574
)
551575

576+
gps_points = list(points_by_dvid.values())[0] if points_by_dvid else []
577+
578+
# backfill forward from the first point with epoch time
579+
_backfill_gps_timestamps(gps_points)
580+
581+
# backfill backward from the first point with epoch time in reversed order
582+
_backfill_gps_timestamps(reversed(gps_points))
583+
552584
return TelemetryData(
553-
gps=list(points_by_dvid.values())[0] if points_by_dvid else [],
585+
gps=gps_points,
554586
accl=list(accls_by_dvid.values())[0] if accls_by_dvid else [],
555587
gyro=list(gyros_by_dvid.values())[0] if gyros_by_dvid else [],
556588
magn=list(magns_by_dvid.values())[0] if magns_by_dvid else [],

0 commit comments

Comments
 (0)