Skip to content

feat(radar): add radar minimap overlay to the Distance/Bearings frame#10224

Open
egorsiniaev wants to merge 37 commits into
meshtastic:developfrom
egorsiniaev:feat/radar-node-view
Open

feat(radar): add radar minimap overlay to the Distance/Bearings frame#10224
egorsiniaev wants to merge 37 commits into
meshtastic:developfrom
egorsiniaev:feat/radar-node-view

Conversation

@egorsiniaev
Copy link
Copy Markdown

@egorsiniaev egorsiniaev commented Apr 21, 2026

What this PR does

Adds a radar minimap view as an alternative rendering of the existing Distance/Bearings frame — no new screen slot in the rotation.

From the node-list long-press menu, a new "Tracking View" picker (clock-face style) lets the user switch between the regular Bearings list and the Radar overlay. While in radar mode, long-pressing opens a radar-specific menu (Tracking View, N-UP/HDG-UP toggle, Favorites Only toggle, Zoom In/Out). Both choices are persistent across reboots (bearings_view_radar and radar_favorites_only in DeviceUIConfig, proto fields 20 and 21).

Radar layout

  • Left panel: up to 5 closest nodes — per-row marker symbol, short name, distance
  • Right panel: circular minimap with 3 range rings and 2 px padding so the circle never touches the display edge
  • Header: shows the current outer-ring range as Radar 5km / Radar 1.5mi (units follow display.units)
  • Own position is a single pixel at the centre
  • Five unique markers (■ + × □ ◆) — sort-position-based, so the dot on the radar always matches the row in the list
  • Heading-up when IMU (BMX160/RAK12034) is present; falls back to north-up
  • Favorites-only filter for use at large gatherings — toggled from the radar long-press menu
  • No GPS fix state shows a clear message instead of an empty radar
  • No impact on e-ink devices — the entire bearings/distance frame this view lives in is already inside a #ifndef USE_EINK block in NodeListRenderer.cpp, so the radar code isn't compiled in for e-ink builds

Files changed

  • src/graphics/draw/RadarRenderer.cpp/.h — radar overlay renderer; owns its own header so the title can carry the current range
  • src/graphics/draw/NodeListRenderer.cpp — delegates to RadarRenderer::drawRadarOverlay when bearings_view_radar is set
  • src/graphics/draw/MenuHandler.cpp/.h — adds trackingViewPicker() and radarBearingsMenu(); wires "Tracking View" into the node-list menu
  • src/graphics/Screen.cpp — routes long-press on the bearings frame to radarBearingsMenu when radar is active
  • src/mesh/generated/meshtastic/device_ui.pb.h — adds bool bearings_view_radar (field 20) and bool radar_favorites_only (field 21), both backwards-compatible

🤝 Attestations

  • I have tested that my proposed changes behave as described.
  • I have tested that my proposed changes do not cause any obvious regressions on the following devices:
    • Heltec (Lora32) V3
    • lilygo lora32 v2.1
    • LilyGo T-Deck
    • LilyGo T-Beam
    • RAK WisBlock 4631
    • Seeed Studio T-1000E tracker card
    • Other (please specify below)

Note: Happy to get help testing on other hardware from the community.

image 20260603_083837

Video: https://photos.app.goo.gl/Tj3y2PKypFPwczE58

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 21, 2026

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions Bot added needs-review Needs human review enhancement New feature or request labels Apr 21, 2026
@egorsiniaev
Copy link
Copy Markdown
Author

CLA assistant check Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.You have signed the CLA already but the status is still pending? Let us recheck it.

I have 500 Internal Server Error after signing it.

@caveman99
Copy link
Copy Markdown
Member

We have 3 nodelist displays with different additonal things. This adds a 4th list with a graphical representation. Also overlaps with the functionality of the GPS Compass. Maybe we can have this panel as an option instead of the GPS Compass or even merge it with the compass.

@caveman99
Copy link
Copy Markdown
Member

I have 500 Internal Server Error after signing it.

The CLA server seems to have issues. Can you try again maybe tomorrow?

@egorsiniaev
Copy link
Copy Markdown
Author

egorsiniaev commented Apr 21, 2026

We have 3 nodelist displays with different additonal things. This adds a 4th list with a graphical representation. Also overlaps with the functionality of the GPS Compass. Maybe we can have this panel as an option instead of the GPS Compass or even merge it with the compass.

I thought about it, but because this is my first PR and contribution - to suggest such merge without long term community vision is a strange step. That's why I decided to have clear separate section that easy to review + easy to disable if people don't need it.

@caveman99
Copy link
Copy Markdown
Member

Problem is, we rather would like to make the interface more clear, not pile on it. I see the value in your contribution, i just think i t would really benefit the existing screens rather than open up a new one.

@fifieldt
Copy link
Copy Markdown
Member

This is cool :) I want to see how it looks on a larger screen, like the sensecap indicator - will try when I get time.

Also, appreciate your collaborative approach.

@egorsiniaev egorsiniaev changed the title feat(radar): add radar minimap screen showing nearby nodes by bearing and distance feat(radar): add radar minimap overlay to the compass/position screen Apr 21, 2026
@egorsiniaev
Copy link
Copy Markdown
Author

egorsiniaev commented Apr 21, 2026

Problem is, we rather would like to make the interface more clear, not pile on it. I see the value in your contribution, i just think i t would really benefit the existing screens rather than open up a new one.

I updated. Removed separate Radar view and add option to switch Compass mode Radar mode. Plus changed a bit orientation (nodes on the left, radar on the right) to match compass layout.

Please take a look. Should I need to update screenshots? They are still showing old layout.

@egorsiniaev
Copy link
Copy Markdown
Author

This is cool :) I want to see how it looks on a larger screen, like the sensecap indicator - will try when I get time.

Also, appreciate your collaborative approach.

Will appreciate for checking it. I have no such devices yet.

@egorsiniaev
Copy link
Copy Markdown
Author

Hey @caveman99 Thanks for your suggestion. I'v made changes and pushed them. Today made photos and record video for better representation. In short - I extended Compass, add long-press menu to switch to the radar view + changed a bit layout to match compass. Please take a look and let me know if anything else is missing.

@egorsiniaev
Copy link
Copy Markdown
Author

egorsiniaev commented May 4, 2026

Hey @caveman99 @fifieldt
Could you please tell me - how to move forward with this PR? There are no reviewers added automatically. It's waiting about 2 weeks. Maybe I missed something to do or somebody need to approve CI to start checking changes.
Thank you.

@Xaositek
Copy link
Copy Markdown
Contributor

Xaositek commented May 7, 2026

Reviewing the video - I do like the idea and concept. It's well executed and provides a display not so dissimilar to what is in InkHUD. Need to load it up on a couple devices to give it a run through.

Copy link
Copy Markdown
Contributor

@Xaositek Xaositek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested it out on my Cardputer and I can't see it actually working. I tried Zooming In and Out, verified I have a GPS lock, and nodes are pretty close by.

I feel like we need some refinements like "What is my current Zoom level?", "Do I have GPS lock"?

Also the toggle between Compass and Radar likely needs to be similar to what we have on the Clock screen where you click on "Clock Face" and then choose Digital or Analog.

@Xaositek
Copy link
Copy Markdown
Contributor

Xaositek commented May 7, 2026

IMG_3250.mov

Video of my attempt

@HarukiToreda
Copy link
Copy Markdown
Contributor

I had a similar idea while creating the distance and bearing screen, I ultimately opted to not implement due to the following:

  • Adds another screen frame into an already extensive list of frames users have to cycle through, this was prior to the action menus (I see you solved this nicely using action menu but I would suggest making it swap the distance and bearing screen instead of the position screen since the position screen is not related to tracking nodes)

  • Showing the closest random nodes does not add much value other than a wow factor, something the position and bearing screen already do with arrows and distance markers, (However if you can limit it to show favorite nodes only, now that adds a lot of value for people since that is a deliberate action useful for large events and gatherings "Favorite Radar View")

  • Markers to differentiate the nodes was very limited (I see from the video you're reusing the x for the first 3, would you be able to make them different?)

…stance

Adds a new RadarRenderer that draws a circular radar view with three range
rings. The user's node sits at the centre; other nodes with valid GPS
positions are plotted as 3×3 squares at their true bearing and
proportional distance. A "N" indicator marks north, the info panel to
the right shows the current scale, total node count, and the name and
distance of the closest node.

The screen is registered for non-E-Ink builds that have GPS (HAS_GPS)
and can be hidden via the existing hiddenFrames mechanism.
When BMX160 (RAK12034) is connected, Screen::setHeading() is updated
by BMX160Sensor::runOnce() after tilt-compensated compass fusion.
The radar now reads that heading via screen->hasHeading()/getHeading()
and rotates all node bearings and the "N" indicator accordingly, so
the direction the device faces is always at the top of the display
(heading-up mode).

Falls back to GPS-estimated track heading, then north-up when neither
is available. The info panel shows "HDG-UP" or "N-UP" so the current
mode is always visible.
- Centre the radar circle horizontally, filling the full content height
  (radius=27 on 128×64, scales up on larger displays)
- Replace the wide info panel with a compact ring legend to the right:
  three stacked distance labels (outer/middle/inner ring scale)
  plus a small "IMU" indicator when the BMX160 is active
- Remove per-screen closest-node text — node positions on the rings
  now carry the distance information visually
… long-press menu

1. Scale table — all values now multiples of 3 so ring labels (scale/3
   and scale*2/3) are always whole numbers (e.g. 30/60/90m, 100/200/300m).

2. Layout — radar shifted to the left edge; right panel shows three ring
   scale labels, closest node short name, distance, and a node-count +
   orientation badge (HDG / N^) in the bottom row.

3. Icon — replaced shared icon_compass with a new icon_radar (concentric
   rings with centre dot) so the radar has its own menu indicator.

4. Menu toggle — "Show/Hide Radar" added to the Show/Hide Frames menu
   via the existing toggleFrameVisibility / isFrameHidden pattern.

5. Long-press menu — pressing SELECT on the radar screen opens "Radar
   Options" with: Switch N-UP / HDG-UP (overrides IMU), Zoom In, Zoom Out.
   Zoom is clamped to ±2 steps from auto-scale; state is held in module-
   static variables in RadarRenderer.
Problem: on 128×64 OLED with FONT_SMALL≈13px, the 3 ring-label rows
left no space for node info — name/distance were clipped off screen.

Fix:
- Info panel reduced to 4 rows:
    Row 0  outer ring scale (scale reference)
    Row 1  closest node: name (left) + distance (right-aligned)
    Row 2  2nd closest node: name + distance
    Row 3  node count + HDG/N^ badge
- Entries sorted by distance ascending before drawing so rows 1/2
  always show the two nearest nodes.
- Closest node rendered as a + cross on the radar; all others keep
  the 3×3 filled-square marker. The cross lets the user match the
  top panel row to the correct dot without cluttering the radar with
  text labels.
Each node is assigned a persistent marker shape based on nodeNum % 5:
  0 ■  filled square
  1 +  axis-aligned cross
  2 ×  diagonal X
  3 □  hollow square
  4 ◆  diamond

The same symbol appears on the radar dot AND in the right-panel list,
so the user can visually match any dot on the map to its panel entry
without text labels cluttering the radar.

Info panel:
  Row 0  outer ring scale
  Row 1  [sym] closest node name (left)  distance (right)
  Row 2  [sym] 2nd closest      (left)  distance (right)
  Row 3  node count (left)      orientation badge (right)
Instead of a separate screen slot in the rotation, the radar now lives inside
the existing Position/Compass screen.

- Remove standalone Radar frame and icon from screen rotation
- Add 'Radar View' entry to the position long-press menu (positionBaseMenu)
- Long-press in radar mode opens radarPositionMenu with: Compass View,
  N-UP/HDG-UP toggle, Zoom In, Zoom Out
- UIRenderer::drawCompassAndLocationScreen delegates to
  RadarRenderer::drawRadarOverlay when uiconfig.radar_mode is true
- Radar layout: node list (left) + radar circle (right, 2 px padding)
- radar_mode persisted as bool field 20 in DeviceUIConfig (proto-compatible)
- Removes nodelist_radar from hiddenFrames, framesetInfo.positions, and
  all frame-toggle machinery
Re-do the previous fix without modifying SharedUIDisplay.  The shared
drawCommonFooter still does its full-width black wipe — that's the
correct behaviour for every other screen — but the radar overlay now
owns its own icon-drawing path:

- New static drawConnectionIconNoWipe() in RadarRenderer renders just
  the 5x5 BT/API glyph at x=0..4 with no surrounding fill.  Replicates
  the icon-rendering half of drawCommonFooter inline so radar can stay
  self-contained.
- drawRadarOverlay calls it at the end, after radar + list have been
  drawn.  The icon's footprint (x=0..4) doesn't spatially overlap the
  radar circle (x=80..126) or list text (x>=7), so leaving the rest of
  the bottom row untouched preserves the radar arc and the last list
  row's text.
- NodeListRenderer's radar branch drops its drawCommonFooter call —
  radar handles the icon itself now.

SharedUIDisplay.cpp/.h are untouched, so other view modes and menus
keep their original footer behaviour.
@egorsiniaev
Copy link
Copy Markdown
Author

Updated PR a bit. Fixed layout to better show radar and node list, especially when bluetooth connected. Plus fixed a bug with wrong order of nodes and showing not correct ones.

@HarukiToreda
Copy link
Copy Markdown
Contributor

Looks good, got a chance to test it today

20260517_143536_1.mp4

CI cppcheck flagged constVariablePointer on line 244:
  Variable 'ourNode' can be declared as pointer to const
We never mutate the node through the pointer (only read num and pass
to copyNodePosition), so the stricter declaration is correct.
CI's Trunk Check Runner flagged two files as unformatted:
  src/graphics/draw/MenuHandler.cpp
  src/graphics/draw/RadarRenderer.cpp

Ran clang-format (version 17.0.6, project config .trunk/configs/.clang-format).
Diff is style-only — include reordering (alphabetical within group) and
compacting a single static const array to one line under the 130-col
limit.  No semantic changes.
@egorsiniaev
Copy link
Copy Markdown
Author

@HarukiToreda Thanks for checking!
I think I need to order some device with TFT to test it properly. UI now is too far from ideal, it could show 8-10 nodes + radar could be more readable.

@HarukiToreda
Copy link
Copy Markdown
Contributor

HarukiToreda commented May 18, 2026

yes, if you can fit it, allowing more nodes to show to take advantage of the higher resolution and space would be great.

@egorsiniaev
Copy link
Copy Markdown
Author

@HarukiToreda could you tell me your device name and screen resolution?

I also think - let's use Meshtastic community you to test it properly. I wrote it for 128×64 OLED, but there are some TFT and eInk screens. Any idea how & where to populate it to test?
We need:

  • T-Display S3 / T-Lora Pager (170×320 TFT)
  • T-Echo or t114 with EInk (200×200 / 250×122 EInk)
  • T-Deck / T-Deck Pro (240×320 TFT )
  • M5Stack Cardputer (240×135 TFT)
  • Elecrow / T5-S3 / large EInk (20×480+)
  • Unit C6L (64×48 OLED)

@HarukiToreda
Copy link
Copy Markdown
Contributor

HarukiToreda commented May 25, 2026

I was using a Heltec T114 with a large 240x320 screen I personally added, a good one to try with a large enough screen like that is the Tdeck, i think what you have now is good to merge. Fine tuning for larger screens could be a new PR

@egorsiniaev
Copy link
Copy Markdown
Author

Hey @Xaositek. Could you please take a look on this PR?

@fifieldt fifieldt force-pushed the feat/radar-node-view branch from 79e6264 to 3e7ed0d Compare May 29, 2026 23:46
@fifieldt fifieldt added triaged Reviewed by the team, has enough information and ready to work on now. baseui Issues directly related to BaseUI and removed needs-review Needs human review labels May 29, 2026
#define meshtastic_DeviceUIConfig_screen_rgb_color_tag 17
#define meshtastic_DeviceUIConfig_is_clockface_analog_tag 18
#define meshtastic_DeviceUIConfig_gps_format_tag 19
#define meshtastic_DeviceUIConfig_bearings_view_radar_tag 20
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please make a PR in the meshtastic/protobufs repo to add these there?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. This is the PR - meshtastic/protobufs#935

@egorsiniaev egorsiniaev force-pushed the feat/radar-node-view branch from 3e7ed0d to 4d6109c Compare June 3, 2026 08:28
@egorsiniaev
Copy link
Copy Markdown
Author

While waiting for PR - I ordered T-Deck and did some tweaks for highres screens:

  • Now it could 5 \ 8 \ 10 nodes depends on screen size
  • Optimised paddings for different screens
  • Added ring labels to show distance. Works only on highres.
20260603_083837

FYI @HarukiToreda @HarukiToreda @fifieldt Let me know what do you think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

baseui Issues directly related to BaseUI enhancement New feature or request triaged Reviewed by the team, has enough information and ready to work on now.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants