Files
trail-mate/docs/engineering/linux-offline-navigation.md
T
Trail Mate Dev 6e613e382e Add CM0 Linux support and share device services across platforms
Compose the CM0 fullscreen application and standard Debian package, align the
Cardputer Zero shell, and share protocol, configuration, audio and storage
services with embedded targets through existing platform seams.

Add the paginated on-device TMAP creator using Center's published producer,
private workspace recovery and direct keyboard shortcuts. Preserve unfinished
management work behind its existing opt-in capability.

Include native, ARM and shared-core regression fixtures, integration records,
packaging helpers and dependency/license updates. Keep local build trees,
device credentials, produced packages and validation logs outside version control.

Validation before integration: ESP stack hygiene, Reticulum scope guard, staged
whitespace checks and GitNexus scope audit. Prior device/build evidence and
remaining hardware/package boundaries are recorded in the acceptance documents.
2026-10-29 10:29:29 +08:00

6.2 KiB

Native Linux offline navigation and place search

Linux now implements the shared platform::ui::navigation and platform::ui::map_search ports. The existing P4 Tracker navigation dialog, place picker, route preview and indexed archive reader use these ports. Board configuration does not enter the calculation or UI. A GNSS receiver is required only for choosing the current location or live guidance; manual origin and destination selection remains available on a CM0 without the GNSS expansion.

Calculation and file ownership

The native worker uses the existing navigation::ArchiveCalculation pipeline and pinned TMAP SDK. It retains the production foot-routing defaults: 50-metre endpoint snapping, 65,536 states/legs, a 2 MiB search-array budget, 200,000 expansions and an 8 MiB route archive limit. Native aligned heap allocation uses the SDK's InternalOnly policy; it does not pretend that Linux RAM is ESP PSRAM. No routing algorithm is reimplemented in the platform layer.

The map catalog uses the same logical directories as the ESP routing adapter: maps/tmap/{osm,terrain,satellite}, maps/tmap, maps/navigation and maps/tmap/navigation, all beneath the configured SD root. It visits a bounded number of entries per call, rejects symlink directories and linked files, and limits the catalog to 256 packages and 8,192 visited entries. Files remain bound to opened descriptors, their named inode and the media root identity.

A job owns an exclusive .pending-*.tmroute output and .spool-* file under routes/navigation. Files and calculation state have one worker owner. The worker publishes a small synchronized snapshot and never accesses LVGL. A cancelled job cannot publish a ready result. Closing a finished job removes only its still-matching temporary files; saved archives and replacement files survive. The runtime signals cancellation and joins its worker during destruction.

Saving synchronizes the complete archive and publishes it without replacing an existing destination. The generated name includes sanitized, UTF-8-safe endpoint names and a random suffix. The shared snapshot's 160-byte path capacity is checked before admitting a job; a long configured root is rejected rather than silently truncating a usable path. The list excludes temporary files, links and unrelated extensions. Deletion accepts a direct KML/TMROUTE filename and refuses nested/outside paths and hidden temporary files.

Malformed or non-routing packages do not hide a later usable candidate. No path, endpoint coverage, storage and memory failures retain distinct UI states. The integer SDK's Missing result during endpoint snapping is reported as outside routing coverage; Missing during package initialization remains missing routing data. The former distinction was established by the out-of-coverage regression.

Place search and regions

Search uses the existing TMAP Reader and substring-search cursor, including its name normalization and Unicode support. One owned worker processes the latest request. New queries invalidate earlier generations, so an old result cannot overwrite the current input. Cancellation clears the published result and invalidates outstanding region tokens.

The adapter deduplicates stable POI IDs and retains at most 24 results, ordered by distance, match quality, importance and ID. Zoom metadata and administrative path quality are carried to the shared place picker. Search scans the four display/POI map roots used by the ESP adapter. Corrupt packages set the incomplete flag while other valid maps can still provide results; an unreadable catalog reports an error rather than an empty successful search.

The approximate region lookup considers nearby POIs within 30 km, bounds each package's candidate scan, and intersects complete administrative hierarchy segments across the nearest retained candidates. It does not present a nearby POI's district as an exact boundary lookup. Published region data retains the request's media identity and becomes unavailable after that root is replaced.

Verification

The native navigation fixture is generated by the pinned SDK producer from the existing restricted-junction test. linux_navigation_runtime exercises the real background adapter, verifies its three-leg detour, reopens and fully validates the archive through the SDK, then checks save/list/delete, invalid requests, no-path/coverage/missing/corrupt data, cancellation/retry and replacement-file preservation.

make_linux_search_fixture.py extends the pinned SDK's two-POI schema fixture with name documents, strings and gram postings. The test writer is not shipped or used by the application. linux_map_search_runtime verifies actual SDK search results, ASCII case normalization, Chinese names, ranking, administrative paths, zoom metadata, query replacement, cancellation, approximate common regions, media replacement and mixed valid/corrupt packages.

Both fixtures and both native runtime tests passed; both ARM runtime fixtures also passed on CM0. The complete native suite passed 128/128 and Cardputer Zero passed 14/14. The standard armhf deb passed Lintian without diagnostics, was installed and passed dpkg -V, original-logo and 1232 x 568 P4 render checks. The compositor confirmed fullscreen/focus, and Alt+F4 exited with code 0 in 0.636 seconds.

The installed P4 UI searched and selected the two fixture POIs as manual origin and destination, calculated four points, saved a uniquely named archive, and opened Route Preview with the prohibited-turn detour polyline. The process exited and left the saved archive with no owned temporary files. Its isolated profile disables radio and stores all data beneath a separate test directory. The fixture has no OSM raster tiles, so a missing-tile background is expected. It also has no CJK font pack: Unicode search/file names are verified, Chinese glyph rendering is not. Native TMAP raster/annotation rendering is now connected and verified separately; see packaged map rendering. Large real-world map timing, physical GNSS guidance and interrupted-power recovery are not established by these fixtures. Artifact hashes and the latest installed-app checks are recorded in the CM0 integration ledger.