Skip to content

Draw History's routes from every drive, and show where nothing was recorded - #106

Merged
blike merged 5 commits into
mainfrom
history-map-routes
Nov 9, 2026
Merged

blike merged 5 commits into
mainfrom
history-map-routes

Conversation

@blike

@blike blike commented Nov 9, 2026 •

Copy link
Copy Markdown
Owner

Also brings in #99 (All time) and #105 (time axis), so History's changes land in one merge and one Docker Hub publish.

Summary

History's map over long periods, for both Rivian and TeslaMate:

  • Routes averaged per drive in SQL, as TeslaMate's Grafana maps do. Up to a week, every
    point; up to a month, one per 5 seconds; past that, one per 15 seconds. This replaces sampling
    TeslaMate's positions by id, which was uneven and dropped some drives entirely.
  • Up to 200,000 points per response, up from 60,000, so a few years of a heavily driven car
    fits without being thinned evenly.
  • Dashed lines where nothing was recorded. When one drive ends more than 300m from where the
    next one starts, the map draws a faint dashed line between them, rather than leaving a gap or
    joining them up like a road.
  • No stack overflow when framing the map over many points.

Three years of a TeslaMate Model Y (12.7M positions):

Before After
Route more than 50m off the road 8.7% 0.2%
95th percentile distance off 65m 23m
Drives with no route 9 0
Query time 0.7s 3.8s

A minute a point, as TeslaMate's Visited map uses, left 24–30% of the route more than 50m off,
so it isn't used.

Testing

  • Unit tests added/updated: bucket sizes, averaging over a long window against every point
    over a short one, TeslaMate's bucketed query, and gaps between drives.
  • Integration tests passed: server suite against Postgres.
  • Manually tested: All time over a three-year TeslaMate history.

Deployment

  • No special deployment requirements

Additional Notes

  • 12 months now averages too, and its query is slower (1.5–2.3s on the Model Y, from 0.8s).
    It still polls every minute.

MrSerious0 and others added 4 commits November 8, 2026 18:17
History's longest period is 12 months, so a longer record cannot be seen
at all. This adds an "All time" period whose window runs from the first
drive to now, and nothing else: the window comes from the coverage the
page already loads, and a fixed-length-less period is drawn six hours a
point and a month a bar past two years.

Two things had to move for it. The queries that key on the period alone
wait for the window, or an empty answer would be cached under the key the
view then uses; and neither prefetch loads all time, whose window is the
whole history. If the coverage read fails with nothing loaded, the page
says so above the cards with a retry.
All time is the whole history, so polling it every minute re-read every
drive, session, span and location point each time. Its queries now load
when the period is picked and stay fresh for five minutes, so switching
away and straight back doesn't load it again.

The map's frame and the timeline's value range spread every point into
Math.min and Math.max, and a long history has more points than a call
takes arguments: the page threw "Maximum call stack size exceeded". Both
now use a loop.
Past a couple of months the axis stepped by 61 days at most, so a span
of more than a year drew about 18 ticks of month and day, and the same
dates came round again with no year to tell them apart. It now ticks on
the first of a month and, over several years, by year. A January, or a
tick a year or more from the last, reads as its year, and once the ticks
cover a year, other months carry theirs ("Jul ’24").

Labels were also placed without checking they fit, and overlapped at
phone width even on the 7-day default. The axis now measures its label
strip and the labels in the page's own font, and keeps only as many
ticks as clear each other by 8px.

Fixes #101
…corded

TeslaMate logs a position every second or so while driving, so a long
window was sampled to about 200,000 positions by id before its drives
were simplified. The ids are shared between cars and the sample is
uneven: over three years of one car, routes strayed more than 50 m from
the road for 8.7% of the way, and nine drives came back with no points.

Positions are now averaged per drive in SQL, as TeslaMate's own Grafana
maps do: every point up to a week, five seconds a point up to a month,
fifteen past that. Over the same three years that's 300,000 rows read
in about 4 s, 0.2% of the way more than 50 m off, and no drive missing.
A minute a point, as TeslaMate's Visited map uses, cut corners by
hundreds of metres. Rivian's location points are averaged the same way;
a bucket keeps its first bearing, since bearings don't average across
north.

The response now holds up to 200,000 points rather than 60,000, so
three years of a heavily driven car fits without being thinned evenly.
The map frames them with a loop rather than spreading them into
Math.min, which overflowed the stack.

Where the car moved with nothing logged, such as no signal or offline,
one drive ends far from where the next one starts. Those stretches are
now drawn as a faint dashed line between the two rather than left out,
and not joined up as a road the way TeslaMate's Trip map does.
@blike blike mentioned this pull request Nov 9, 2026
3 of 4 tasks
Merges the all-time period (#99) and the time axis fix (#105) into the
map routes branch, so History's changes ship in one merge to main.
@blike
blike merged commit e097f29 into main Nov 9, 2026
1 check passed
@blike
blike deleted the history-map-routes branch November 10, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants