feat(radar): add radar minimap overlay to the Distance/Bearings frame#10224
feat(radar): add radar minimap overlay to the Distance/Bearings frame#10224egorsiniaev wants to merge 51 commits into
Conversation
I have 500 Internal Server Error after signing it. |
|
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. |
The CLA server seems to have issues. Can you try again maybe tomorrow? |
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. |
|
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. |
|
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. |
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. |
Will appreciate for checking it. I have no such devices yet. |
|
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. |
|
Hey @caveman99 @fifieldt |
|
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. |
Xaositek
left a comment
There was a problem hiding this comment.
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.
IMG_3250.movVideo of my attempt |
|
I had a similar idea while creating the distance and bearing screen, I ultimately opted to not implement due to the following:
|
…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
…ng labels, list top pad, adaptive radar padding
3e7ed0d to
4d6109c
Compare
|
While waiting for PR - I ordered T-Deck and did some tweaks for highres screens:
FYI @HarukiToreda @HarukiToreda @fifieldt Let me know what do you think. |
|
@HarukiToreda @fifieldt Could you take a look on this PRs, guys? |
…_SECS The radar overlay iterated every node in the DB with a stored position and plotted it, regardless of age. Since NodeDB never time-expires nodes, this drew "ghosts" at last-known positions of nodes that went offline long ago. Gate the plot loop on sinceLastSeen() < NUM_ONLINE_SECS (2 hrs), the same threshold getNumOnlineMeshNodes() uses, so the radar shows only nodes the rest of the UI also considers online. Lift NUM_ONLINE_SECS from NodeDB.cpp into NodeDB.h so RadarRenderer can share the single definition.
When no nodes have been heard within NUM_ONLINE_SECS, the radar drew empty rings with a blank list and no explanation. Render a centered 'No active nodes' message in the list-panel column so the empty state is intentional and clear, leaving the radar rings intact.
Firmware Size Report22 targets | vs
Show 17 more target(s)
Updated for 065053d |
Fixes Trunk Check (clang-format) failure - file was authored with 2-space/attached-brace style; reformat to repo Linux-brace 4-space style.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis PR adds a radar overlay renderer and menu-driven tracking view controls for the node list screen, and moves the online-node timeout constant into ChangesRadar Overlay Feature
Node Online Timeout Constant Relocation
Estimated code review effort: 4 (Complex) | ~60 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/graphics/draw/RadarRenderer.cpp (1)
194-229: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffIcon-drawing logic duplicated from
SharedUIDisplay::drawCommonFooter.The comment already acknowledges this replicates half of
drawCommonFooter's behavior. Since both copies must stay in sync (icon glyph format, scale handling, XBM bit layout), consider extracting a shareddrawConnectionIcon(display, x, y, scale)helper inSharedUIDisplaythat both call, so future icon-format changes don't need to be applied twice.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/graphics/draw/RadarRenderer.cpp` around lines 194 - 229, The connection icon drawing logic in drawConnectionIconNoWipe is duplicated from SharedUIDisplay::drawCommonFooter, so extract the shared icon-rendering behavior into a reusable helper such as drawConnectionIcon(display, x, y, scale) and have both drawCommonFooter and drawConnectionIconNoWipe call it. Keep the helper responsible for the icon glyph, resolution scaling, and XBM bit layout so changes stay synchronized in one place.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/graphics/draw/RadarRenderer.cpp`:
- Around line 285-293: The early return in RadarRenderer::drawRadar skips the
connection icon, causing it to disappear in the “No GPS fix” state. Update this
branch to preserve the same UI behavior as the other exits by calling
drawConnectionIconNoWipe(display) before returning, matching the rest of the
function’s icon-preservation flow.
- Around line 298-311: The heading fallback in RadarRenderer::draw is using
screen->estimatedHeading() directly as if it were radians, but it returns
degrees and can also yield the -1.0f sentinel when unavailable. Update the
headingRad selection so the GPS fallback branch converts estimatedHeading(myLat,
myLon) with DEG_TO_RAD, and preserve the north-up fallback when no real heading
is available; keep the change localized to the heading/headingUp logic in
RadarRenderer.cpp.
---
Nitpick comments:
In `@src/graphics/draw/RadarRenderer.cpp`:
- Around line 194-229: The connection icon drawing logic in
drawConnectionIconNoWipe is duplicated from SharedUIDisplay::drawCommonFooter,
so extract the shared icon-rendering behavior into a reusable helper such as
drawConnectionIcon(display, x, y, scale) and have both drawCommonFooter and
drawConnectionIconNoWipe call it. Keep the helper responsible for the icon
glyph, resolution scaling, and XBM bit layout so changes stay synchronized in
one place.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 3c08e9e0-dff6-475a-a602-b2c64eabe4d1
⛔ Files ignored due to path filters (1)
src/mesh/generated/meshtastic/device_ui.pb.his excluded by!**/generated/**
📒 Files selected for processing (9)
src/graphics/Screen.cppsrc/graphics/draw/MenuHandler.cppsrc/graphics/draw/MenuHandler.hsrc/graphics/draw/NodeListRenderer.cppsrc/graphics/draw/RadarRenderer.cppsrc/graphics/draw/RadarRenderer.hsrc/graphics/draw/UIRenderer.cppsrc/mesh/NodeDB.cppsrc/mesh/NodeDB.h
💤 Files with no reviewable changes (1)
- src/mesh/NodeDB.cpp
- Preserve connection icon in 'No GPS fix' early return (was skipped, causing the icon to disappear until a fix was acquired). - Convert GPS estimatedHeading() fallback from degrees to radians and honor its -1.0f sentinel, falling back to north-up until a real heading exists (matches CompassRenderer).
|
Sorry for the ping again, @Xaositek could you trigger CI again? I got some feedback from CodeRabbit and fixed them. |

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_radarandradar_favorites_onlyinDeviceUIConfig, proto fields 20 and 21).Radar layout
Radar 5km/Radar 1.5mi(units followdisplay.units)#ifndef USE_EINKblock inNodeListRenderer.cpp, so the radar code isn't compiled in for e-ink buildsFiles changed
src/graphics/draw/RadarRenderer.cpp/.h— radar overlay renderer; owns its own header so the title can carry the current rangesrc/graphics/draw/NodeListRenderer.cpp— delegates toRadarRenderer::drawRadarOverlaywhenbearings_view_radaris setsrc/graphics/draw/MenuHandler.cpp/.h— addstrackingViewPicker()andradarBearingsMenu(); wires "Tracking View" into the node-list menusrc/graphics/Screen.cpp— routes long-press on the bearings frame toradarBearingsMenuwhen radar is activesrc/mesh/generated/meshtastic/device_ui.pb.h— addsbool bearings_view_radar(field 20) andbool radar_favorites_only(field 21), both backwards-compatible🤝 Attestations
Note: Happy to get help testing on other hardware from the community.
Video: https://photos.app.goo.gl/Tj3y2PKypFPwczE58
Summary by CodeRabbit