mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-05 07:28:29 -04:00
AP_Soaring: Calculate expected thermalling sink live and avoid divide by zero by limiting airspeed to that corresponding to CL max (generously assumed 1.5 for glider).
This commit is contained in:
parent
5963164a22
commit
fab74f8927
@ -213,12 +213,11 @@ SoaringController::LoiterStatus SoaringController::check_cruise_criteria()
|
|||||||
gcs().send_text(MAV_SEVERITY_ALERT, "Reached lower alt = %dm", (int16_t)alt);
|
gcs().send_text(MAV_SEVERITY_ALERT, "Reached lower alt = %dm", (int16_t)alt);
|
||||||
}
|
}
|
||||||
} else if ((AP_HAL::micros64() - _thermal_start_time_us) > ((unsigned)min_thermal_s * 1e6)) {
|
} else if ((AP_HAL::micros64() - _thermal_start_time_us) > ((unsigned)min_thermal_s * 1e6)) {
|
||||||
const float thermalability = (_ekf.X[0]*expf(-powf(_aparm.loiter_radius / _ekf.X[1], 2))) - EXPECTED_THERMALLING_SINK;
|
|
||||||
const float mcCreadyAlt = McCready(alt);
|
const float mcCreadyAlt = McCready(alt);
|
||||||
if (thermalability < mcCreadyAlt) {
|
if (_thermalability < mcCreadyAlt) {
|
||||||
result = THERMAL_WEAK;
|
result = THERMAL_WEAK;
|
||||||
if (result != _cruise_criteria_msg_last) {
|
if (result != _cruise_criteria_msg_last) {
|
||||||
gcs().send_text(MAV_SEVERITY_INFO, "Thermal weak: W %f.3 R %f.3 th %f.1 alt %dm Mc %dm", (double)_ekf.X[0], (double)_ekf.X[1], (double)thermalability, (int32_t)alt, (int32_t)mcCreadyAlt);
|
gcs().send_text(MAV_SEVERITY_INFO, "Thermal weak: W %f.3 R %f.3 th %f.1 alt %dm Mc %dm", (double)_ekf.X[0], (double)_ekf.X[1], (double)_thermalability, (int32_t)alt, (int32_t)mcCreadyAlt);
|
||||||
}
|
}
|
||||||
} else if (alt < (-_thermal_start_pos.z) || _vario.smoothed_climb_rate < 0.0) {
|
} else if (alt < (-_thermal_start_pos.z) || _vario.smoothed_climb_rate < 0.0) {
|
||||||
result = ALT_LOST;
|
result = ALT_LOST;
|
||||||
@ -303,8 +302,16 @@ void SoaringController::update_thermalling()
|
|||||||
|
|
||||||
Vector3f wind_drift = _ahrs.wind_estimate()*deltaT;
|
Vector3f wind_drift = _ahrs.wind_estimate()*deltaT;
|
||||||
|
|
||||||
|
// update the filter
|
||||||
|
_ekf.update(_vario.reading, current_position.x, current_position.y, wind_drift.x, wind_drift.y);
|
||||||
|
|
||||||
|
|
||||||
|
_thermalability = (_ekf.X[0]*expf(-powf(_aparm.loiter_radius / _ekf.X[1], 2))) - _vario.get_exp_thermalling_sink();
|
||||||
|
|
||||||
|
_prev_update_time = AP_HAL::micros64();
|
||||||
|
|
||||||
// write log - save the data.
|
// write log - save the data.
|
||||||
AP::logger().Write("SOAR", "TimeUS,nettorate,x0,x1,x2,x3,north,east,alt,dx_w,dy_w", "Qffffffffff",
|
AP::logger().Write("SOAR", "TimeUS,nettorate,x0,x1,x2,x3,north,east,alt,dx_w,dy_w,th", "Qfffffffffff",
|
||||||
AP_HAL::micros64(),
|
AP_HAL::micros64(),
|
||||||
(double)_vario.reading,
|
(double)_vario.reading,
|
||||||
(double)_ekf.X[0],
|
(double)_ekf.X[0],
|
||||||
@ -315,12 +322,8 @@ void SoaringController::update_thermalling()
|
|||||||
current_position.y,
|
current_position.y,
|
||||||
(double)_vario.alt,
|
(double)_vario.alt,
|
||||||
(double)wind_drift.x,
|
(double)wind_drift.x,
|
||||||
(double)wind_drift.y);
|
(double)wind_drift.y,
|
||||||
|
(double)_thermalability);
|
||||||
// update the filter
|
|
||||||
_ekf.update(_vario.reading, current_position.x, current_position.y, wind_drift.x, wind_drift.y);
|
|
||||||
|
|
||||||
_prev_update_time = AP_HAL::micros64();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoaringController::update_cruising()
|
void SoaringController::update_cruising()
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include "Variometer.h"
|
#include "Variometer.h"
|
||||||
#include <AP_SpdHgtControl/AP_SpdHgtControl.h>
|
#include <AP_SpdHgtControl/AP_SpdHgtControl.h>
|
||||||
|
|
||||||
#define EXPECTED_THERMALLING_SINK 0.7
|
|
||||||
#define INITIAL_THERMAL_STRENGTH 2.0
|
#define INITIAL_THERMAL_STRENGTH 2.0
|
||||||
#define INITIAL_THERMAL_RADIUS 30.0 //150.0
|
#define INITIAL_THERMAL_RADIUS 30.0 //150.0
|
||||||
#define INITIAL_STRENGTH_COVARIANCE 0.0049
|
#define INITIAL_STRENGTH_COVARIANCE 0.0049
|
||||||
@ -50,6 +49,9 @@ class SoaringController {
|
|||||||
|
|
||||||
float McCready(float alt);
|
float McCready(float alt);
|
||||||
|
|
||||||
|
float _thermalability;
|
||||||
|
float _expected_sink;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AP_Int8 soar_active;
|
AP_Int8 soar_active;
|
||||||
AP_Int8 soar_active_ch;
|
AP_Int8 soar_active_ch;
|
||||||
|
@ -42,10 +42,15 @@ void Variometer::update(const float polar_K, const float polar_B, const float po
|
|||||||
|
|
||||||
float roll = _ahrs.roll;
|
float roll = _ahrs.roll;
|
||||||
|
|
||||||
// Compute still-air sinkrate
|
// Constrained airspeed.
|
||||||
float sinkrate = correct_netto_rate(0.0f, roll, _aspd_filt, polar_K, polar_Cd0, polar_B);
|
const float minV = sqrt(polar_K/1.5);
|
||||||
|
float aspd_filt_constrained = _aspd_filt>minV ? _aspd_filt : minV;
|
||||||
|
|
||||||
reading = raw_climb_rate + dsp*_aspd_filt/GRAVITY_MSS + sinkrate;
|
|
||||||
|
// Compute still-air sinkrate
|
||||||
|
float sinkrate = correct_netto_rate(0.0f, roll, aspd_filt_constrained, polar_K, polar_Cd0, polar_B);
|
||||||
|
|
||||||
|
reading = raw_climb_rate + dsp*aspd_filt_constrained/GRAVITY_MSS + sinkrate;
|
||||||
|
|
||||||
|
|
||||||
filtered_reading = TE_FILT * reading + (1 - TE_FILT) * filtered_reading; // Apply low pass timeconst filter for noise
|
filtered_reading = TE_FILT * reading + (1 - TE_FILT) * filtered_reading; // Apply low pass timeconst filter for noise
|
||||||
@ -56,13 +61,16 @@ void Variometer::update(const float polar_K, const float polar_B, const float po
|
|||||||
AP::logger().Write("VAR", "TimeUS,aspd_raw,aspd_filt,alt,roll,raw,filt,cl,fc", "Qffffffff",
|
AP::logger().Write("VAR", "TimeUS,aspd_raw,aspd_filt,alt,roll,raw,filt,cl,fc", "Qffffffff",
|
||||||
AP_HAL::micros64(),
|
AP_HAL::micros64(),
|
||||||
(double)0.0,
|
(double)0.0,
|
||||||
(double)_aspd_filt,
|
(double)aspd_filt_constrained,
|
||||||
(double)alt,
|
(double)alt,
|
||||||
(double)roll,
|
(double)roll,
|
||||||
(double)reading,
|
(double)reading,
|
||||||
(double)filtered_reading,
|
(double)filtered_reading,
|
||||||
(double)raw_climb_rate,
|
(double)raw_climb_rate,
|
||||||
(double)smoothed_climb_rate);
|
(double)smoothed_climb_rate);
|
||||||
|
|
||||||
|
float expected_roll = asinf(constrain_float(powf(aspd_filt_constrained,2)/(GRAVITY_MSS*_aparm.loiter_radius),-1.0, 1.0));
|
||||||
|
_expected_thermalling_sink = correct_netto_rate(0.0, expected_roll, aspd_filt_constrained, polar_K, polar_Cd0, polar_B);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -80,6 +88,7 @@ float Variometer::correct_netto_rate(float climb_rate,
|
|||||||
float netto_rate;
|
float netto_rate;
|
||||||
float cosphi;
|
float cosphi;
|
||||||
CL0 = polar_K / (aspd * aspd);
|
CL0 = polar_K / (aspd * aspd);
|
||||||
|
|
||||||
C1 = polar_CD0 / CL0; // constant describing expected angle to overcome zero-lift drag
|
C1 = polar_CD0 / CL0; // constant describing expected angle to overcome zero-lift drag
|
||||||
C2 = polar_B * CL0; // constant describing expected angle to overcome lift induced drag at zero bank
|
C2 = polar_B * CL0; // constant describing expected angle to overcome lift induced drag at zero bank
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ class Variometer {
|
|||||||
float _last_aspd;
|
float _last_aspd;
|
||||||
float _last_roll;
|
float _last_roll;
|
||||||
float _last_total_E;
|
float _last_total_E;
|
||||||
|
float _expected_thermalling_sink;
|
||||||
|
|
||||||
// declares a 5point average filter using floats
|
// declares a 5point average filter using floats
|
||||||
AverageFilterFloat_Size5 _vdot_filter;
|
AverageFilterFloat_Size5 _vdot_filter;
|
||||||
@ -50,5 +51,9 @@ public:
|
|||||||
float correct_netto_rate(float climb_rate, float phi, float aspd, const float polar_K, const float polar_CD0, const float polar_B);
|
float correct_netto_rate(float climb_rate, float phi, float aspd, const float polar_K, const float polar_CD0, const float polar_B);
|
||||||
|
|
||||||
void reset_filter(float value) { _climb_filter.reset(value);}
|
void reset_filter(float value) { _climb_filter.reset(value);}
|
||||||
|
|
||||||
|
float get_airspeed(void) {return _aspd_filt;};
|
||||||
|
|
||||||
|
float get_exp_thermalling_sink(void) {return _expected_thermalling_sink;};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user