mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-25 10:08:28 -04:00
AP_NavEKF: Allow EKF to pull data from range finder object
This commit is contained in:
parent
7f1749dc1c
commit
1c8e3f9444
@ -382,9 +382,10 @@ const AP_Param::GroupInfo NavEKF::var_info[] PROGMEM = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
NavEKF::NavEKF(const AP_AHRS *ahrs, AP_Baro &baro) :
|
NavEKF::NavEKF(const AP_AHRS *ahrs, AP_Baro &baro, const RangeFinder &rng) :
|
||||||
_ahrs(ahrs),
|
_ahrs(ahrs),
|
||||||
_baro(baro),
|
_baro(baro),
|
||||||
|
_rng(rng),
|
||||||
state(*reinterpret_cast<struct state_elements *>(&states)),
|
state(*reinterpret_cast<struct state_elements *>(&states)),
|
||||||
gpsNEVelVarAccScale(0.05f), // Scale factor applied to horizontal velocity measurement variance due to manoeuvre acceleration - used when GPS doesn't report speed error
|
gpsNEVelVarAccScale(0.05f), // Scale factor applied to horizontal velocity measurement variance due to manoeuvre acceleration - used when GPS doesn't report speed error
|
||||||
gpsDVelVarAccScale(0.07f), // Scale factor applied to vertical velocity measurement variance due to manoeuvre acceleration - used when GPS doesn't report speed error
|
gpsDVelVarAccScale(0.07f), // Scale factor applied to vertical velocity measurement variance due to manoeuvre acceleration - used when GPS doesn't report speed error
|
||||||
@ -737,6 +738,9 @@ void NavEKF::UpdateFilter()
|
|||||||
covPredStep = false;
|
covPredStep = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read range finder data which is used by both position and optical flow fusion
|
||||||
|
readRangeFinder();
|
||||||
|
|
||||||
// Update states using GPS, altimeter, compass, airspeed and synthetic sideslip observations
|
// Update states using GPS, altimeter, compass, airspeed and synthetic sideslip observations
|
||||||
SelectVelPosFusion();
|
SelectVelPosFusion();
|
||||||
SelectMagFusion();
|
SelectMagFusion();
|
||||||
@ -4205,7 +4209,7 @@ void NavEKF::readAirSpdData()
|
|||||||
|
|
||||||
// write the raw optical flow measurements
|
// write the raw optical flow measurements
|
||||||
// this needs to be called externally.
|
// this needs to be called externally.
|
||||||
void NavEKF::writeOptFlowMeas(uint8_t &rawFlowQuality, Vector2f &rawFlowRates, Vector2f &rawGyroRates, uint32_t &msecFlowMeas, uint8_t &rangeHealth, float &rawSonarRange)
|
void NavEKF::writeOptFlowMeas(uint8_t &rawFlowQuality, Vector2f &rawFlowRates, Vector2f &rawGyroRates, uint32_t &msecFlowMeas)
|
||||||
{
|
{
|
||||||
// The raw measurements need to be optical flow rates in radians/second averaged across the time since the last update
|
// The raw measurements need to be optical flow rates in radians/second averaged across the time since the last update
|
||||||
// The PX4Flow sensor outputs flow rates with the following axis and sign conventions:
|
// The PX4Flow sensor outputs flow rates with the following axis and sign conventions:
|
||||||
@ -4244,21 +4248,6 @@ void NavEKF::writeOptFlowMeas(uint8_t &rawFlowQuality, Vector2f &rawFlowRates, V
|
|||||||
} else {
|
} else {
|
||||||
newDataFlow = false;
|
newDataFlow = false;
|
||||||
}
|
}
|
||||||
// Use range finder if 3 or more consecutive good samples. This reduces likelihood of using bad data.
|
|
||||||
if (rangeHealth >= 3) {
|
|
||||||
statesAtRngTime = statesAtFlowTime;
|
|
||||||
rngMea = rawSonarRange;
|
|
||||||
newDataRng = true;
|
|
||||||
rngValidMeaTime_ms = imuSampleTime_ms;
|
|
||||||
} else if (!vehicleArmed) {
|
|
||||||
statesAtRngTime = statesAtFlowTime;
|
|
||||||
rngMea = RNG_MEAS_ON_GND;
|
|
||||||
newDataRng = true;
|
|
||||||
rngValidMeaTime_ms = imuSampleTime_ms;
|
|
||||||
} else {
|
|
||||||
// set flag that will trigger fusion of height data
|
|
||||||
newDataRng = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate the NED earth spin vector in rad/sec
|
// calculate the NED earth spin vector in rad/sec
|
||||||
@ -4937,4 +4926,65 @@ bool NavEKF::calcGpsGoodToAlign(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read the range finder and take new measurements if available
|
||||||
|
// Read at 20Hz and apply a median filter
|
||||||
|
void NavEKF::readRangeFinder(void)
|
||||||
|
{
|
||||||
|
static float storedRngMeas[3];
|
||||||
|
static uint32_t storedRngMeasTime_ms[3];
|
||||||
|
static uint32_t lastRngMeasTime_ms = 0;
|
||||||
|
static uint8_t rngMeasIndex = 0;
|
||||||
|
uint8_t midIndex;
|
||||||
|
uint8_t maxIndex;
|
||||||
|
uint8_t minIndex;
|
||||||
|
// get theoretical correct range when the vehicle is on the ground
|
||||||
|
rngOnGnd = _rng.ground_clearance_cm() * 0.01f;
|
||||||
|
if (_rng.status() == RangeFinder::RangeFinder_Good && (imuSampleTime_ms - lastRngMeasTime_ms) > 50) {
|
||||||
|
// store samples and sample time into a ring buffer
|
||||||
|
rngMeasIndex ++;
|
||||||
|
if (rngMeasIndex > 2) {
|
||||||
|
rngMeasIndex = 0;
|
||||||
|
}
|
||||||
|
storedRngMeasTime_ms[rngMeasIndex] = imuSampleTime_ms;
|
||||||
|
storedRngMeas[rngMeasIndex] = _rng.distance_cm() * 0.01f;
|
||||||
|
// check for three fresh samples and take median
|
||||||
|
bool sampleFresh[3];
|
||||||
|
for (uint8_t index = 0; index <= 2; index++) {
|
||||||
|
sampleFresh[index] = (imuSampleTime_ms - storedRngMeasTime_ms[index]) < 500;
|
||||||
|
}
|
||||||
|
if (sampleFresh[0] && sampleFresh[1] && sampleFresh[2]) {
|
||||||
|
if (storedRngMeas[0] > storedRngMeas[1]) {
|
||||||
|
minIndex = 1;
|
||||||
|
maxIndex = 0;
|
||||||
|
} else {
|
||||||
|
maxIndex = 0;
|
||||||
|
minIndex = 1;
|
||||||
|
}
|
||||||
|
if (storedRngMeas[2] > storedRngMeas[maxIndex]) {
|
||||||
|
midIndex = maxIndex;
|
||||||
|
} else if (storedRngMeas[2] < storedRngMeas[minIndex]) {
|
||||||
|
midIndex = minIndex;
|
||||||
|
} else {
|
||||||
|
midIndex = 2;
|
||||||
|
}
|
||||||
|
rngMea = max(storedRngMeas[midIndex],rngOnGnd);
|
||||||
|
newDataRng = true;
|
||||||
|
rngValidMeaTime_ms = imuSampleTime_ms;
|
||||||
|
// recall vehicle states at mid sample time for range finder
|
||||||
|
RecallStates(statesAtRngTime, storedRngMeasTime_ms[midIndex] - 25);
|
||||||
|
} else if (!vehicleArmed) {
|
||||||
|
// if not armed and no return, we assume on ground range
|
||||||
|
rngMea = rngOnGnd;
|
||||||
|
newDataRng = true;
|
||||||
|
rngValidMeaTime_ms = imuSampleTime_ms;
|
||||||
|
// assume synthetic measurement is at current time (no delay)
|
||||||
|
statesAtRngTime = state;
|
||||||
|
} else {
|
||||||
|
newDataRng = false;
|
||||||
|
}
|
||||||
|
lastRngMeasTime_ms = imuSampleTime_ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect takeoff for optical flow navigation
|
||||||
#endif // HAL_CPU_CLASS
|
#endif // HAL_CPU_CLASS
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <AP_Param.h>
|
#include <AP_Param.h>
|
||||||
#include <AP_Nav_Common.h>
|
#include <AP_Nav_Common.h>
|
||||||
#include <GCS_MAVLink.h>
|
#include <GCS_MAVLink.h>
|
||||||
|
#include <RangeFinder.h>
|
||||||
|
|
||||||
// #define MATH_CHECK_INDEXES 1
|
// #define MATH_CHECK_INDEXES 1
|
||||||
|
|
||||||
@ -88,7 +89,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
NavEKF(const AP_AHRS *ahrs, AP_Baro &baro);
|
NavEKF(const AP_AHRS *ahrs, AP_Baro &baro, const RangeFinder &rng);
|
||||||
|
|
||||||
// This function is used to initialise the filter whilst moving, using the AHRS DCM solution
|
// This function is used to initialise the filter whilst moving, using the AHRS DCM solution
|
||||||
// It should NOT be used to re-initialise after a timeout as DCM will also be corrupted
|
// It should NOT be used to re-initialise after a timeout as DCM will also be corrupted
|
||||||
@ -193,9 +194,8 @@ public:
|
|||||||
// rawFlowRates are the optical flow rates in rad/sec about the X and Y sensor axes.
|
// rawFlowRates are the optical flow rates in rad/sec about the X and Y sensor axes.
|
||||||
// rawGyroRates are the sensor rotation rates in rad/sec measured by the sensors internal gyro
|
// rawGyroRates are the sensor rotation rates in rad/sec measured by the sensors internal gyro
|
||||||
// The sign convention is that a RH physical rotation of the sensor about an axis produces both a positive flow and gyro rate
|
// The sign convention is that a RH physical rotation of the sensor about an axis produces both a positive flow and gyro rate
|
||||||
// rawSonarRange is the range in metres measured by the range finder
|
|
||||||
// msecFlowMeas is the scheduler time in msec when the optical flow data was received from the sensor.
|
// msecFlowMeas is the scheduler time in msec when the optical flow data was received from the sensor.
|
||||||
void writeOptFlowMeas(uint8_t &rawFlowQuality, Vector2f &rawFlowRates, Vector2f &rawGyroRates, uint32_t &msecFlowMeas, uint8_t &rangeHealth, float &rawSonarRange);
|
void writeOptFlowMeas(uint8_t &rawFlowQuality, Vector2f &rawFlowRates, Vector2f &rawGyroRates, uint32_t &msecFlowMeas);
|
||||||
|
|
||||||
// return data for debugging optical flow fusion
|
// return data for debugging optical flow fusion
|
||||||
void getFlowDebug(float &varFlow, float &gndOffset, float &flowInnovX, float &flowInnovY, float &auxInnov, float &HAGL, float &rngInnov, float &range, float &gndOffsetErr) const;
|
void getFlowDebug(float &varFlow, float &gndOffset, float &flowInnovX, float &flowInnovY, float &auxInnov, float &HAGL, float &rngInnov, float &range, float &gndOffsetErr) const;
|
||||||
@ -245,6 +245,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
const AP_AHRS *_ahrs;
|
const AP_AHRS *_ahrs;
|
||||||
AP_Baro &_baro;
|
AP_Baro &_baro;
|
||||||
|
const RangeFinder &_rng;
|
||||||
|
|
||||||
// the states are available in two forms, either as a Vector34, or
|
// the states are available in two forms, either as a Vector34, or
|
||||||
// broken down as individual elements. Both are equivalent (same
|
// broken down as individual elements. Both are equivalent (same
|
||||||
@ -424,6 +425,10 @@ private:
|
|||||||
// Assess GPS data quality and return true if good enough to align the EKF
|
// Assess GPS data quality and return true if good enough to align the EKF
|
||||||
bool calcGpsGoodToAlign(void);
|
bool calcGpsGoodToAlign(void);
|
||||||
|
|
||||||
|
// Read the range finder and take new measurements if available
|
||||||
|
// Apply a median filter to range finder data
|
||||||
|
void readRangeFinder();
|
||||||
|
|
||||||
// EKF Mavlink Tuneable Parameters
|
// EKF Mavlink Tuneable Parameters
|
||||||
AP_Float _gpsHorizVelNoise; // GPS horizontal velocity measurement noise : m/s
|
AP_Float _gpsHorizVelNoise; // GPS horizontal velocity measurement noise : m/s
|
||||||
AP_Float _gpsVertVelNoise; // GPS vertical velocity measurement noise : m/s
|
AP_Float _gpsVertVelNoise; // GPS vertical velocity measurement noise : m/s
|
||||||
|
Loading…
Reference in New Issue
Block a user