Repository navigation
Skip NMEA sentences cut short, rather than misdate a fix by them - #901
Merged
caglarpir merged 5 commits intoOct 24, 2026
Merged
Conversation
A file named on the command line that is neither an image nor a video
that mapillary_tools can process was left out of the description with
only a warning, "Skipping ..., which is not a supported image or video",
and process exited 0. Named on its own, such a file gave an empty
description and a successful run, so a user who named the original of an
Insta360 camera (.insv), which has to be stitched first, saw nothing
uploaded and no error.
Fail such a file with an error entry of its own, of the new type
MapillaryUnsupportedFileError: "Not a supported image or video". For an
Insta360 original, the message goes on to say to stitch it with Insta360
Studio first, and then to geotag the stitched video by the original with
--video_geotag_source '{"source": "exiftool_runtime", "pattern":
"../%g.insv"}', as the README does. Like any error, it makes process
exit 6, or 0 with --skip_process_errors, and upload skips it. The entry
names no file type, as the file is of none; the process summary counts
it as an "other file". A new error type rather than an existing one, as
none says what is wrong: the geotagging errors would let another source
try the file, and the file is not a video.
Unchanged: the files in a named folder that cannot be processed are
still left alone without a word, a named zip file is still uploaded as
it is by process_and_upload, and the process report still lists the
unsupported files, named or found, as unsupported_format.
Checked process on named images, videos, zip files, text files and an
Insta360 original, alone, together, named twice, beside a named folder,
with --filetypes image, and on folders holding such files, and
video_process and sample_video: only the runs that named an unsupported
file change, each by the one error entry. process_and_upload of named
zip files with a named text file uploads the zip files and fails the
text file.
Interval sampling cuts a frame every N seconds of the whole video, whatever GPS track will geotag the frames, so the frames past either end of the track were written and then failed geotagging, which failed the command: the last frame of a BlackVue video, cut after the last GPS point, with "Unable to extract GPS Longitude or GPS Latitude from the image", or the last frame of a GoPro MAX 2 timelapse sampled every 0.25 s against its GPX, 0.386 s past the end of the GPX, with MapillaryOutsideGPXTrackError. At a 1 s interval, 17 of 49 sample videos had such frames: one or two at an end of most, and up to 64 at the start of those whose GPS starts late. Leave such frames out, as distance sampling leaves out the frames outside the track it samples along, and warn once per video, e.g. "2 of the 61 samples of X fall outside its GPS track (A to B) and were left out". The track is the one that will geotag the frames: the video's own track, which sampling now writes into the frames, or a GPX or NMEA track of --geotag_source, which the geotagging stage locates the frames along by their capture times, with its offset, its start time and its gaps of more than an hour, as it does. If the track covers none of the frames, they are all written as before, so that a video that misses its track fails rather than goes without a word. The frames before the start of the track are kept where leaving them out would move the others: the legacy gopro, blackvue and camm sources and exiftool_xml geotag a frame by the time since the first frame of its video, which they place at the start of the video, and so does a GPX with --interpolation_use_gpx_start_time, which also starts at the first frame of all the videos sampled, so that with several videos none is left out. The sample_video command cannot tell which sources will geotag its frames, so it keeps them too. Nothing is left out of a GPX track that another source, which geotags frames by the GPS of their video or by another track file, may geotag instead. On those 49 videos, sampled every second with the default sources, the 17 lose only the frames that failed, and 16 of them now exit 0 (the other fails as before for an unrelated reason); every other description entry is the same. The BlackVue gives 60 frames and the GoPro MAX 2 timelapse 4, both exit 0. With the legacy sources, the frames before a late GPS start are kept and geotagged as before, and with a GPX of --geotag_source only the frames that it rejected are left out. Distance sampling does not change.
process uploads the track it places a GPX on a video by with the video, and the frames are placed along it. Since mapillary#874, a time in a gap of more than MAPILLARY_TOOLS_MAX_GPX_GAP_SECONDS (an hour) between two fixes is outside the track, but the track clipped to the video was still interpolated across such a gap. A video that starts in a gap got a point at video time 0 interpolated between the last fix before the gap and the first one after it. On a GoPro MAX video with a GPX whose fixes resume 99 seconds into the video, 2 hours after the previous one 5 km away, that point was 151 m from where the full track puts the start of the video, and the first 99 seconds of frames were placed between the two. At driving speed it is kilometres off. When video time 0, or the end of the video, falls in such a gap, leave out the fixes on its far side, and interpolate no point across it: the track starts (or ends) at the first fix past the gap, as one that starts after the video does, and process still warns that it covers only part of the video. A gap inside the video fails it with MapillaryOutsideGPXTrackError, which names the gap and suggests sampling the video with video_process and --video_geotag_source gpx (or nmea), which leaves out the frames in the gap. So does a gap that the video falls in but for an instant at one end, such as the gap after a lone first fix that the track is started with the video at. A track assumed to start with a video without a GPS clock keeps its end, which may be that of a timelapse, unless the end of the video at 1x falls in a gap. The limit is in GPS seconds, so it spans less video in a timelapse. Sampling is unchanged. Checked process with GPX and NMEA tracks made to have gaps: - The GoPro MAX video above: its track starts at 99.085 s, with the warning; with --interpolation_offset_time 2, at 97.085 s. With the track ending 159 s into the video and resuming 2 hours later, it ends at 159.085 s. With both, it runs from 99.085 to 159.085 s. - A gap of 70 s inside the video, with the limit at 60 s, fails it, by a GPS clock or with --interpolation_use_gpx_start_time, without a GPS clock, from an NMEA file, and in a timelapse, whose limit of 30 s is in GPS time. With native as the next source, native geotags it. video_process samples the same videos and tracks as before. - Without a GPS clock, a track that resumes 2 hours after the end of the video at 1x ends with the video, and one with a lone first fix 2 hours before the rest fails. With the limit raised above the gap, the tracks are interpolated across it as before. process with the GPX, NMEA and ExifTool tracks of sample videos and images from a dozen cameras (58 runs, among them GPX tracks of several trips with gaps of days, offsets and --interpolation_use_gpx_start_time), plain process, and video_process with GPX tracks write the same descriptions as before.
The legacy gopro_videos, blackvue_videos and camm sources geotag images from the videos they are given: the frames that sample_video took from them. An image that is not a frame of any of the videos got no entry at all: `process FRAMES --geotag_source blackvue_videos --geotag_source_path VIDEOS` left a foreign image in a folder of frames out of the description and exited 0. Since each video geotags only its own frames, nothing reported it; before, every video tried every image, and such an image was reported as outside the track. The legacy sources now fail such an image with "Not a frame of any video in VIDEOS". That is a geotagging error, which a later source can still replace: with `--geotag_source blackvue_videos --geotag_source exif` the image is geotagged from its EXIF, as before. And at the end of the source chain, a file that sources were let through but none of them described, nor said why, is failed with "The geotag sources ... gave no result for this image" (or video), so that every file given gets exactly one entry. Files that --filetypes leaves out are still left out: images by their names, and videos once a source finds them of other types, or the native reader cannot recognize one of the types asked for. On a folder of the frames of two BlackVue videos, with a foreign image among the frames and one beside them, the legacy sources fail the two images, and with exif after them geotag them as before. The frames, and process of a mixed folder with the default sources, exif, --filetypes image or gopro and --video_geotag_source native, of the frames with the default sources, of the frames of a GoPro and a CAMM video with their legacy sources, of an image sequence, and video_process with the default sources, the legacy source and exif, do not change.
A sentence cut short, such as the last one of a log when the recording stopped, could give a fix a wrong date. pynmea2 reads a sentence without its checksum, and the fields it can: an RMC sentence cut inside its date, "...,0.0,0.0,2212", reads as dated 2012-02-02. Since NMEA fixes are dated by the RMC sentences around them, the last fix of a log ending so took that date, and process placed a 10-minute video along a track that lasted 3976 days, with exit 0. A time cut short reads too: "00052" as 00:00:02. Treat such sentences as malformed, and skip them with the warning that malformed sentences get: - a sentence without a checksum, where the other sentences of the file have theirs: receivers end each sentence with one, so one without was cut short; - a time that is not hhmmss with an optional fraction of a second, and an RMC date that is not ddmmyy. A log whose sentences carry no checksum at all, as some converters write it, is read as before. Empty times and dates, as before a fix, are not malformed. On a 650-fix log that crosses midnight, written with each GGA sentence before its RMC sentence, cut inside the date of its last RMC sentence: the track is again 650 points over 649 s, with one warning naming the cut sentence. With 186 sentences cut short at random points, the 186 are skipped under one warning and no fix is misdated, where the track lasted 4006 days. Three other logs, one of them as a camera wrote it, give the same descriptions as before, for images and videos.
caglarpir
added a commit
that referenced
this pull request
Oct 24, 2026
#901 took every sentence without a checksum for cut short as soon as any other sentence of the file had one. Checksums are optional in NMEA 0183, and logs that mix sentences with and without them read in full before: a log with a checksum on one line only, or on its GGA sentences only, now failed whole as "not a valid NMEA file", and of two logs concatenated, one with checksums and one without, the half without was skipped. A sentence without its checksum is now cut short only when its own fields show it: when it has fewer fields than a complete sentence (11 for RMC, as NMEA 2.0 to 2.2 write it, 12 with the mode of NMEA 2.3 and 13 with the navigational status of NMEA 4.1; 14 for GGA), when the date of an RMC sentence is not 6 digits, or when its time does not parse. A sentence with its checksum ends where the checksum shows, however few fields it has, and one whose checksum does not match is still malformed. The checksums of other sentences no longer count. When no fix of a file can be read, the error now says why, with the first malformed sentence, its line and the reason: "track.nmea is not a valid NMEA file: 2 of its 2 RMC and GGA sentences are malformed, the first on line 1 (checksum does not match: 00 != 47): $GPRMC,...". It said only "not a valid NMEA file". (#901's message said that pynmea2 reads a time cut to "00052" as 00:00:02; it reads it as 00:05:02.) Checked on a 650-fix log, with the video it belongs to: with a checksum on one line only, with checksums on its GGA sentences only, and as two halves with and without checksums, it gives the track of the original, 650 points over 649 s, with no warning, where it failed twice and gave 325 points. Written GGA first across midnight and ending with an RMC sentence cut inside its date, it still gives the 650 points, and one warning. A log whose sentences are all cut short, which gave a stationary video, fails with the reason. The NMEA logs of a Sony action camera and of an image sequence read the same points as before, and process of the images and the video, video_process by distance and by interval with the NMEA log, and plain process and video_process of other cameras write the same descriptions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #900; review the last commit.
A sentence cut short, such as the last one of a log when the recording
stopped, could give a fix a wrong date. pynmea2 reads a sentence without
its checksum, and the fields it can: an RMC sentence cut inside its date,
"...,0.0,0.0,2212", reads as dated 2012-02-02. Since NMEA fixes are dated
by the RMC sentences around them, the last fix of a log ending so took
that date, and process placed a 10-minute video along a track that
lasted 3976 days, with exit 0. A time cut short reads too: "00052" as
00:00:02.
Treat such sentences as malformed, and skip them with the warning that
malformed sentences get:
have theirs: receivers end each sentence with one, so one without was
cut short;
an RMC date that is not ddmmyy.
A log whose sentences carry no checksum at all, as some converters write
it, is read as before. Empty times and dates, as before a fix, are not
malformed.
On a 650-fix log that crosses midnight, written with each GGA sentence
before its RMC sentence, cut inside the date of its last RMC sentence:
the track is again 650 points over 649 s, with one warning naming the
cut sentence. With 186 sentences cut short at random points, the 186 are
skipped under one warning and no fix is misdated, where the track lasted
4006 days. Three other logs, one of them as a camera wrote it, give
the same descriptions as before, for images and videos.
Unit and integration tests, doctests,
mypy --python-version 3.9,ruff check,ruff format --checkandusort diffare clean.