mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-26 14:58:12 +00:00
refactor(nav): single GPS-position accessor + reset COG window after a gap
UITask::currentLocation() becomes the one place that reads the LocationProvider fix. TrailScreen::ownPos, CompassScreen::gpsValid and NearbyScreen::refresh now delegate to it instead of each duplicating the getLocationProvider/isValid dance (and the ENV_INCLUDE_GPS guard). pushCogFix now restarts the course-over-ground ring when the gap since the previous fix exceeds 15 s: after losing GPS for a while, a window spanning the stale old fixes would compute a bogus "teleport" heading. The last-good heading is kept for display continuity. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -13,14 +13,7 @@
|
||||
class CompassScreen : public UIScreen {
|
||||
UITask* _task;
|
||||
|
||||
static bool gpsValid() {
|
||||
#if ENV_INCLUDE_GPS == 1
|
||||
LocationProvider* loc = sensors.getLocationProvider();
|
||||
return loc && loc->isValid();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
bool gpsValid() const { int32_t lat, lon; return _task->currentLocation(lat, lon); }
|
||||
|
||||
// Midpoint circle (DisplayDriver has no circle primitive).
|
||||
static void drawCircle(DisplayDriver& d, int cx, int cy, int r) {
|
||||
|
||||
@@ -111,17 +111,8 @@ class NearbyScreen : public UIScreen {
|
||||
|
||||
void refresh() {
|
||||
_count = 0;
|
||||
_own_gps = false;
|
||||
_own_lat = _own_lon = 0;
|
||||
|
||||
#if ENV_INCLUDE_GPS == 1
|
||||
LocationProvider* loc = sensors.getLocationProvider();
|
||||
if (loc && loc->isValid()) {
|
||||
_own_lat = loc->getLatitude();
|
||||
_own_lon = loc->getLongitude();
|
||||
_own_gps = true;
|
||||
}
|
||||
#endif
|
||||
_own_gps = _task->currentLocation(_own_lat, _own_lon);
|
||||
|
||||
int nc = the_mesh.getNumContacts();
|
||||
for (int i = 0; i < nc && _count < MAX_NEARBY; i++) {
|
||||
|
||||
@@ -357,17 +357,7 @@ private:
|
||||
bool selIsStart() const { return hasStart() && _wp_sel == 0; }
|
||||
int wpIndex() const { return _wp_sel - (hasStart() ? 1 : 0); } // index into WaypointStore
|
||||
|
||||
static bool ownPos(int32_t& lat, int32_t& lon) {
|
||||
#if ENV_INCLUDE_GPS == 1
|
||||
LocationProvider* loc = sensors.getLocationProvider();
|
||||
if (loc && loc->isValid()) {
|
||||
lat = (int32_t)loc->getLatitude();
|
||||
lon = (int32_t)loc->getLongitude();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
bool ownPos(int32_t& lat, int32_t& lon) const { return _task->currentLocation(lat, lon); }
|
||||
|
||||
void handleMarkHere() {
|
||||
int32_t lat, lon;
|
||||
|
||||
@@ -1942,11 +1942,17 @@ void UITask::loop() {
|
||||
// Insert a GPS fix into the course-over-ground ring, rejecting gross outliers
|
||||
// (a jump implying an impossible speed) so one bad fix can't swing the heading.
|
||||
void UITask::pushCogFix(int32_t lat, int32_t lon) {
|
||||
static const uint32_t COG_MAX_GAP_MS = 15000; // GPS gap longer than this → window is stale
|
||||
uint32_t now = millis();
|
||||
if (_cog_count > 0) {
|
||||
const CogFix& prev = _cog[(_cog_head + _cog_count - 1) % COG_RING];
|
||||
uint32_t dt = now - prev.ms;
|
||||
if (dt > 0) {
|
||||
if (dt > COG_MAX_GAP_MS) {
|
||||
// GPS was lost for a while: the old fixes are far in the past, so a
|
||||
// window spanning them would imply a bogus "teleport" heading. Restart
|
||||
// the ring from this fix (the last-good _cog_deg is kept for display).
|
||||
_cog_head = 0; _cog_count = 0;
|
||||
} else if (dt > 0) {
|
||||
float dist_m = geo::haversineKm(prev.lat, prev.lon, lat, lon) * 1000.0f;
|
||||
float speed = dist_m / (dt / 1000.0f); // m/s
|
||||
if (speed > 50.0f) return; // > 180 km/h between fixes → reject
|
||||
@@ -1978,6 +1984,16 @@ bool UITask::currentCourse(int& deg_out) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UITask::currentLocation(int32_t& lat, int32_t& lon) const {
|
||||
LocationProvider* loc = _sensors ? _sensors->getLocationProvider() : nullptr;
|
||||
if (loc && loc->isValid()) {
|
||||
lat = (int32_t)loc->getLatitude();
|
||||
lon = (int32_t)loc->getLongitude();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UITask::saveWaypoints() {
|
||||
DataStore* ds = the_mesh.getDataStore();
|
||||
if (!ds) return;
|
||||
|
||||
@@ -152,6 +152,10 @@ public:
|
||||
// Current course over ground in degrees (0..359), or false if not enough
|
||||
// recent movement to derive a stable heading. Independent of trail logging.
|
||||
bool currentCourse(int& deg_out) const;
|
||||
// Current GPS position (1e6-scaled degrees), false when there's no usable
|
||||
// fix. Single source of truth for "where am I", shared by the nav / compass
|
||||
// / map screens so the LocationProvider lookup isn't duplicated per screen.
|
||||
bool currentLocation(int32_t& lat, int32_t& lon) const;
|
||||
void playMelody(const char* melody);
|
||||
void stopMelody();
|
||||
bool isMelodyPlaying();
|
||||
|
||||
Reference in New Issue
Block a user