One of the features of extreme high altitude flight is the high true airspeeds that are needed to generate the dynamic pressure required for airborne flight. To minimise these extreme speeds for my high altitude glider project, I wanted to increase the flyable operation envelope closer to the airframe's stall speed, helping the reign-in the stratospheric true airspeeds!
As I was playing about tuning the roll and pitch control PID loops using my airframe model in an X-plane HIL simulation, I discovered that a relatively large amount of derivative could yield some dramatic improvements to roll control when on the edge of the stall condition. The D term could be wound up at least an order of magnitude higher than could be tolerated at higher speeds.
To make use of this feature, I forensic'd my way through the codebase and the APM libraries to add a non-linearity to the PID speed scalar as it is applied to the derivative term. I did this by tweaking the PID.css file in the PID Arduino library folder (not the AP_PID, as it took me a while to discover..!) The mods are:
PID::get_pid(int32_t error, uint16_t dt, float scalar)
{
float output = 0;
float delta_time = (float)dt / 1000.0;
float deriv_scalar = (scalar - 0.5);// Compute proportional component
output += error * _kp;// Compute derivative component if time has elapsed
if ((fabs(_kd) > 0) && (dt > 0)) {
float derivative = (error - _last_error) / delta_time;// discrete low pass filter, cuts out the
// high frequency noise that can drive the controller crazy
float RC = 1/(2*M_PI*_fCut);
derivative = _last_derivative +
(delta_time / (RC + delta_time)) * (derivative - _last_derivative);// update state
_last_error = error;
_last_derivative = derivative;// add in derivative component
deriv_scalar *= deriv_scalar;
deriv_scalar = max(0,deriv_scalar);
output += _kd * derivative * deriv_scalar;
}// scale the P and D components
output *= scalar;
(Oh, and I corrected the spelling of scalar too!)
I have also expanded the clipping of the speed scalar delivered to the PID controller from the normal 0.5-2.0 in the standard APM codebase, to 0.01-5.0 I also chose to tune the controller with the reference speed to be the stall speed of the aircraft (7m/s) instead of the default cruise speed (25m/s).
The funny (scalar-0.5) term I have used to increase the decay of the term away from the stall speed without getting into complicated and CPU intensive maths. This allows a higher derivative gain to be used without unduly influencing normal flight.
So, having got this compiled and working in APM and X-plane, here are the results:
When I glide towards the stall speed in stabilise mode, holding as best I can, a level flight path, but with the roll control derivative term zeroed, which is more or less how I have tuned the controller till now, the airframe slows to approximately 16-17kts before a divergent roll instability develops. This instability can develop at slightly higher speeds too, but the main characteristic is once it develops, it is properly divergent. There is no saving it, except for a rapid pitch down and acceleration.
With the non-linear D term applied, I can now achieve relatively reliable roll control very close to the stall speed. The divergent instability is still there, but it is at a higher frequency and a much lower speed, clearing the way for operation much closer to the stall break than was possible before.
This work was done in X-plane 9, using an airframe model of my own forward-swept flying wing concept. The APM code was modified from Arduplane 2.28, using Michael Oborne's AP Mission Planner 1.1.42
Comments
You're right Gary. Simulation is only a starting point, but sadly, getting it into the real world all takes time..
I plan on having pitot-static IAS measurement on my aircraft, although even that will be subject to some filtering delay. I like the idea of having an accelerometer integrator to estimate the real free-body velocity and being trimmed by more accurate, but slower data in the same way the Direction Cosine Orientation Matrix is 'corrected' (or should I say, errected?)
Could prove a hairy mammoth project in itself to get that working well though...
You got it!
I've been doing a bit of fiddling Ryan and I think I've got the gist of your rule-of-thumb
My version of the equation would be:
TAS = (Altitude / 1000*0.02 + 1) * IAS, which works reasonably well up to thirty-odd thousand feet - useful for pilots but less so for astronauts! ;)
Well it is for sure a linear approximation. The actual equation is the square root of the density ratios recalling from the top of my head so it for sure isn't linear but it is just the rule of thumb used for pilots. We like to keep it simple. It's like the required decent rate equation for a 3 degree glideslope.... 5 x groundspeed = rate of decent in fps. Just a ballpark figure. If you want to get a more accurate model you would have to calc your density on the ground and then density at altitude either using an atmospheric model or back it out using temp and pressure. Let me know if you need me to bounce you some equations. I got them laying around, but work is kinda crushing me at the moment.
Ryan, it depends on what you need TAS for, but even so I think there's something wrong with your estimate model. Here's my results of your calculation, but maybe I've got something wrong...?
Gary, I think it should be possible to do stall estimation entirely within software, meaning no pesky hardware complications are necessary. Of course you have to model the entire airframe and know it's C_L and C_D characteristics, but these can be estimated by logging the appropriate data on a flying aircraft. Anyway, my objective isn't to have stall warning, but to have the flight conttroller allow flight as close to the stall as possible, but limiting it at some stall margin (1.2*Vs or similar). Obviously, some allowance has to be made for vertical air currents disturbing the system more quickly than it can measure and react to.
An easy estimation is:
TAS = 1.02*((altitude - sealevel_altitude)/1000)+IAS;
@Monroe - I barely understand it myself, but it seems to work! :)
@Ryan - The de-weighting on IAS still is there. I have just added additional de-weighting for the derivative term and made it, in effect, a 1/v³ law to eliminate the effect as quickly as possible as you accelerate away from the stall. In normal cruise flight, I can't get much satisfaction out of the derivative term, so I usually leave it at zero. The IAS/TAS is another issue entirely. I think this D - de-weighting needs to be a function of IAS/EAS (as is the stall condition), whereas the general gain de-weighting needs to be a function of TAS. I'm not sure if I can do this in the simulation, whether APM-MP drags across enough info from X-plane to allow me to do the IAS-TAS calculation. I need to look at this!
@Simon. Soon! Very soon! ;)
@Chris Card: Possibly, but I think the descent rate would be still huge. I can't think of a reason why you'd want to do this, apart from being quite cool, but maybe you can imagine something useful to use such capability for.
@fix8oscill8: The AP_PID doesn't appear to be used. At least I spent a bunch of time modifying it and wondering why there was no effect. It wasn't until I read through the code carefully that I discovered that there was a PID library function as well as an AP_PID. I don't know why the duplication, but it's confusing...
Very nice!
Why did you tweak the .css file instead of the AP_PID code?