development · trips ·
A trip is a line on the map, not a set of instructions
Plan a route on the phone with a handful of stops, share it, pick ExplorInk, and the trip is on the reader's card and drawn across the map. From then on the reader does what it always does: it shows where you are and what is around you, with your line running through it. No turn instructions, no recalculating, no voice, and no warning that you have left it.
This ships today on every supported device, in the published builds. The phone side is ExplorInk GPS 0.3.6, verified end to end on 2026-10-27: a six-stop route from a Samsung S24 Ultra, 346 points and 2.8 kB, on the card and ridden from the picker.
Why there are no turn instructions, and never will be
A reader that tells you to turn left is answering am I going the right way. That is the question this product does not answer, by design: it answers where you are and what is around you, the way a paper map does. An off-route warning was on our own roadmap for weeks and was dropped on 2026-10-27 for exactly that reason, by the person who had put it there.
What is left is the honest half, and it is the half a paper map already proves people can use: the planned line, drawn across the ground you are standing on. You compare the two yourself, which is a thing humans are good at and a thing that needs no battery, no voice and no attention on a screen.
Sharing a route from Google Maps to the reader
On the phone: plan the route in Google Maps, hit Share, pick ExplorInk GPS. The app shows every stop it read, with coordinates, and asks before it sends anything. Then the trip goes over Bluetooth to the reader's card, and it is in the picker the next time you open Trips.
If the reader is not switched on, the trip waits in a queue on the phone and goes across the next time the two are connected. A trip is small: a six-stop route came out at 346 points and 2.8 kB, and even a 3,000-point route is 24 kB, so the transfer is seconds rather than minutes.
The line is ours, not Google's, and the stop list is the only check
Google Maps does not share the route. A share hands over a short link, and resolving it gives the stops, as coordinates or as place names, and no geometry at all. There is no polyline in it at any point.
So the app recovers the stops and routes them itself, along real roads, with a routing engine of its own. The line the reader draws is that engine's line. It will differ from the one you saw on the Google screen, sometimes by a street and sometimes by a valley, and the app says so on the screen rather than hiding it.
That is also why the stop list matters. It is shown before anything is sent, and it is the only check that exists: a stop read wrong bends the whole trip, and nothing after that point can notice, because the file that comes out is valid and its checksums match. A human reading five lines of coordinates is the error check, and it is deliberate.
What a trip file is: one .tir per trip on the card
Trips live in /explorink/trips/, flat, one file per trip, written by the
phone or by a laptop tool. The format is ours and it is small on purpose, because the
reader is a microcontroller reading an SD card:
| Part | What is in it |
|---|---|
| Header, 40 bytes | Magic, version, point count, bounding box, build time, and two CRC32 checksums, one for the header and one for the points |
| Name | Up to 64 bytes of UTF-8, inside the file. Renaming the file cannot rename the trip |
| Points | Two 32-bit integers each, absolute Web Mercator metres, rounded to whole metres |
Whole metres are enough because one Mercator metre is a fifth of a pixel at the finest zoom the reader draws. Absolute coordinates rather than tile-local ones because a trip is not clipped to the tile grid: it is one file, read once when the map opens, not a thing streamed per tile. Both ends round-trip the same bytes under test, the Python writer on the laptop and the C++ reader on the device.
The picker on the reader: load a trip, or skip to the map
Trips is its own row on the home screen. It lists what is on the card with the point count of each, plus a Continue to map row for going out with no plan, which is the normal case and therefore the first row rather than a corner exit.
Holding Select on a row offers to delete that trip, and deleting the last one leaves to an empty screen that says nothing has been sent from the phone yet. That arrived on 2026-10-27 with the share feature, because until then a card collected every trip ever sent to it and nothing on the device could remove one.
A file the reader cannot read says so in the list, on its own row, rather than disappearing or taking the screen down with it.
The first frame is the whole trip, turned the way it runs
Picking a trip draws an overview: the zoom step and the orientation that show the most of it. The fit measures the points, not the bounding box, because a trip running north-east fills a thin diagonal strip inside a very large box, and the panel is taller than it is wide, so which way the map is turned changes what fits. Confirmed on the panel on 2026-08-06: a 71-point trip running north-east came out at the third zoom step of the ladder, rotated to match, whole trip on screen, with the compass turned with it.
Among orientations that land on the same zoom step the fit picks the one nearest the direction of travel, and a closed loop falls back to north up, which is the one orientation anybody can read. No marker is drawn on this frame: a dot in the middle of your own trip would claim you are standing there. And a position arriving while the overview is up is recorded but does not redraw it, because the phone sends one every five seconds and the overview would be snatched away before it could be read.
A trip longer than the coarsest zoom step can show gets the middle of it, and the frame says so out loud, because a frame showing part of a long trip looks exactly like one showing all of a short one.
Walking or riding it: there is no trip mode
After the overview, the reader is in the same follow loop it uses with no trip at all. The code that handles an incoming position never looks at the trip: it is one more layer drawn on top. That is the whole design, and it is why nothing on the device can nag you about leaving the line. It does not know you have.
One thing does change, and it is about the picture rather than the route. Normally the map is rebuilt when your heading drifts far enough, which on a mountain pass means a new frame every few bends, each one turned a different way. With a trip loaded, the trip holds the frame: the heading check is switched off and any rebuild that does happen hands back the same orientation.
Measured on an X4 on 2026-08-07, three runs of the same 136 positions along a 3.4 km serpentine leg at 25 m spacing, same firmware:
| Run | Full redraws | Of those, caused by heading | Distinct orientations |
|---|---|---|---|
| Trip loaded, at the zoom the fit chose | 0 | 0 | 1 |
| Trip loaded, forced to the finest zoom | 6 | 0 | 1 |
| No trip, the control | 11 | 3 | 9 |
The trip turned through most of the compass in every run, so the rider really was turning. The middle row is the one worth reading twice: forced to a zoom the leg does not fit, the marker runs out of the frame six times and gets six new frames, and every one of them is the same way up. The rule is not "never redraw". It is never redraw because the rider turned, and never hand back a differently oriented map. Memory use across a whole run: unchanged, to the byte.
What is not there yet
No GPX or KML import. A GPX file carries real geometry, so importing one would put the exact line you planned on the card with no routing engine in the middle and no difference to explain. It is specified and nobody has written it. Today a file like that goes through a laptop tool instead of the phone.
The routing engine is somebody else's. The app routes against a public BRouter instance. Our own is owed, and until it exists a shared trip needs the phone to have a connection at the moment of sharing.
Google's link shape is undocumented and can change. We read stops out of a URL that Google never promised to keep stable. When it changes, sharing breaks until we follow it, and a GPX path would not have that problem, which is one more reason it is next.