mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-05 15:38:29 -04:00
94 lines
3.1 KiB
C++
94 lines
3.1 KiB
C++
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
|
|
|
|
|
|
|
#include <AP_Common.h>
|
|
#include <AP_Math.h>
|
|
#include <AP_HAL.h>
|
|
#include <AP_Notify.h>
|
|
#include "AP_GPS_Glitch.h"
|
|
|
|
extern const AP_HAL::HAL& hal;
|
|
|
|
// constuctor
|
|
GPS_Glitch::GPS_Glitch(GPS*& gps) :
|
|
_gps(gps)
|
|
{
|
|
_flags.enabled = true;
|
|
}
|
|
|
|
// check_position - returns true if gps position is acceptable, false if not
|
|
void GPS_Glitch::check_position()
|
|
{
|
|
uint32_t now = hal.scheduler->millis(); // current system time
|
|
float sane_dt; // time since last sane gps reading
|
|
float accel_based_distance; // movement based on max acceleration
|
|
Location curr_pos; // our current position estimate
|
|
Location gps_pos; // gps reported position
|
|
float distance_cm; // distance from gps to current position estimate in cm
|
|
bool all_ok; // true if the new gps position passes sanity checks
|
|
|
|
// exit immediately if we don't have gps lock
|
|
if (_gps == NULL || _gps->status() != GPS::GPS_OK_FIX_3D) {
|
|
_flags.glitching = true;
|
|
_flags.recovered = false;
|
|
return;
|
|
}
|
|
|
|
// if not initialised or disabled update last good position and exit
|
|
if (!_flags.initialised || !_flags.enabled) {
|
|
_last_good_update = now;
|
|
_last_good_lat = _gps->latitude;
|
|
_last_good_lon = _gps->longitude;
|
|
_last_good_vel.x = _gps->velocity_north();
|
|
_last_good_vel.y = _gps->velocity_east();
|
|
_flags.initialised = true;
|
|
_flags.glitching = false;
|
|
_flags.recovered = false;
|
|
return;
|
|
}
|
|
|
|
// calculate time since last sane gps reading in ms
|
|
sane_dt = (now - _last_good_update) / 1000.0f;
|
|
|
|
// project forward our position from last known velocity
|
|
curr_pos.lat = _last_good_lat;
|
|
curr_pos.lng = _last_good_lon;
|
|
location_offset(curr_pos, _last_good_vel.x * sane_dt, _last_good_vel.y * sane_dt);
|
|
|
|
// calculate distance from recent gps position to current estimate
|
|
gps_pos.lat = _gps->latitude;
|
|
gps_pos.lng = _gps->longitude;
|
|
distance_cm = get_distance_cm(curr_pos, gps_pos);
|
|
|
|
// all ok if within a given hardcoded radius
|
|
if (distance_cm <= GPS_GLITCH_MIN_RADIUS_CM) {
|
|
all_ok = true;
|
|
}else{
|
|
// or if within the maximum distance we could have moved based on our acceleration
|
|
accel_based_distance = 0.5f * GPS_GLITCH_MAX_ACCEL_CMSS * sane_dt * sane_dt;
|
|
all_ok = (distance_cm <= accel_based_distance);
|
|
}
|
|
|
|
// store updates to gps position
|
|
if (all_ok) {
|
|
// position is acceptable
|
|
_last_good_update = now;
|
|
_last_good_lat = _gps->latitude;
|
|
_last_good_lon = _gps->longitude;
|
|
_last_good_vel.x = _gps->velocity_north();
|
|
_last_good_vel.y = _gps->velocity_east();
|
|
// if we were glitching, we have now recovered
|
|
_flags.recovered = _flags.glitching;
|
|
}else{
|
|
_flags.recovered = false;
|
|
}
|
|
|
|
// To-Do: we need to stop consumer from seeing 'recovered' flag multiple times because GPS updates
|
|
// are much slower than inertial updates
|
|
|
|
// update glitching flag
|
|
_flags.glitching = !all_ok;
|
|
}
|
|
|