Cruise Controller FLC refactored using PID#36
Cruise Controller FLC refactored using PID#36T2Fat2Fly wants to merge 1 commit intoBoris-Barboris:masterfrom
Conversation
FLC logic changed: 1. FLC now uses PID instead of the previous thrust/drag balancing algorithm, which may cause trouble with crafts with a low TWR; 2. FLC now moderates both ascend and descent; 3. Speed Control is no longer required to be enabled for FLC to function, it will work with manual throttle as well; 4. FLC now defaults to off due to the major change in logic. To incorporate the change, Prograde Thrust Controller now allows forced throttle output from other module.
Boris-Barboris
left a comment
There was a problem hiding this comment.
Test it with at least one very big craft please. And, if possible, let's clamp the infinities.
| flc_controller.KP = 0.6; | ||
| flc_controller.KI = 0.03; | ||
| flc_controller.KD = 0.2; | ||
| flc_controller.IntegralClamp = double.PositiveInfinity; |
There was a problem hiding this comment.
Not a fan of infinities here. If the controller's output is logically bound to [-90; 90], we can dynamically choose some sane clamp value (derived from current KI value). If not, crafts that are very very fat and approach desired climb angle very slowly, may end up with an enormous accumulator value that will cause FLC to overshoot.
Set some limit. It needs not to be rigorous or universal, but it should be some sane number.
There was a problem hiding this comment.
TBH I have trouble understanding these clamps (sorry I'm (very!) new to the industrial controllers).
If I understand correctly, the IntergralClamp is used to filter out inputs that is off the setpoint too much. But this is not the case where actual airspeed can be anywhere, regardless of where the setpoint is. So I set it to infinity.
For the AccumulatorClamp, you are right about it should be clamped. Maybe setting it to 1.0 / KI just like you did it in the thrust PID controller? I still have no idea about how to tweak this value.
There was a problem hiding this comment.
I would try:
accumulator clamp = 90.0 / KI
AccumulDerivClamp = 2
There was a problem hiding this comment.
IntegralClamp as infinity should probably be fine
Sure! Let's test with the massive FAR stock craft "FAR SkyEye". It is a pain to fly by hand since its wings break off easily at 1.2G! FYI, I used flart's Speed Unit Annex plugin for better speed information. This is my setting for the test videos. All AA settings are default. And I changed the code setting AccumulatorClamp to Ascend testCommanding an acceleration and ascending flight level change simultaneously: test_ascend.webmDue to the long acceleration process, the airspeeds overshot by 30 m/s. Then the plane established steady climb. Due to the nature of FLC I made it excluded from the relaxing algorithm. At 9830m altitude the plane entered relaxing frame and FLC quits. The transition process is not very smooth but acceptable. Perhaps making FLC an seperate mode and allows altitude mode to be automatically activated when reaching target altitude (like IRL) would make it smoother. For the rest of the process it seems the default PID value works good (not fine, but, good) since they are tweaked with flying these jumbos in mind! Note that I used IAS as setpoint, which means the ground speed mps setpoint is constantly changing during the ascent, which should be to blamed for the slow convergence. Descend testAlmost the same to the ascend: test_descend.webmIt took 10 min for a jumbo jet (and even more IRL) to descend from 10000m to 1000m. You may see what I mean by fuel efficiency when using FLC. |
And that is why it overshot. 1.0/KI would mean that integral part of the controller would never contribute a value larger than 1 degree to the controller's output. When the craft is on perfect FLC ascent trajectory, it's speed matches the setpoint exactly, proportional component is zero and ascent angle is provided fully by integral component. For such perfect ascent, integral part must be able to produce [-90;90] values. Hence my 90.0/KI proposal for the accumulator limit. |
I did a quick test with these parameters and the overshoot becomes more severe after climbing is established. It now overshoots from above the setpoint due to over pitching. Also my default KI is set to I think these are the culprit for overshooting:
|
|
That would mean we're not strictly improving the controller then. I'm a bit busy now, so I'll reply slowly, but don't get discouraged. Actual control parts do take long to invent, we just need to think in the background. It may well be that the problem was somewhere else entirely. PIDs are rarely the best solution. |
Not at all! You are already replying very fast from my point of view! 😉 Please take it easy and put time on tasks that really need them. Meanwhile I can optimize my code (and learn!) on my side.
Can't agree more with this. RL aircrafts use PID for almost every task that is carefully tuned for that specific task (and even for specific configuration e.g. weight, engine model, flaps, etc..) but you are making an autopilot that suits most viable crafts in KSP. I've learned a lot from you and your code (thanks!) and hopefully we can sort this issue out with a solution that is up to the standard of other parts of the plugin. |



Cruise Controller FLC refactoring
The issue
The current pseudo-FLC (Flight Level Change) code estimates total aircraft thrust & drag, and tries to balance them using climb angle when within "flc_margin" speed:
AtmosphereAutopilot/AtmosphereAutopilot/Modules/CruiseController.cs
Lines 313 to 321 in 6d21fdb
However, for aircrafts with low TWR (~0.2), the estimation fails and the flc code refuses to work, since (it thinks) it is impossible to climb when drag > thrust.
This is an example when it fails. The aircraft was Squad stock craft "Gull" with thrust limited to 0.8. It was fine until it started wobbling around 5400m altitude and climbing steeply disregarding the set flc speed, which ultimately resulted in deep stall:
flc_fail.webm
Also, the current code doesn't work for descents. It always descends at max_climb_angle, which is not efficient for both fuel efficiency (energy loss due to drags) and maneuverability (aircrafts become unstable at high speed).
Solution
Refactoring FLC using a PID loop. Several logic is changed (matching the real world FLC behavior):
Result
Squad stock craft "Gull" is used for example.
Accelerate before climb / Decelerate before descend
If FLC is activated and airspeed setpoint is above current speed, it will level off to accelerate:

When airspeed reaches setpoint, it then starts to climb:

And vise versa for descend.
Pitch to maintain airspeed
Airspeed should be close to setpoint when stabilized.

The default PID parameters is tuned to my liking but could be much better. Right now it overshoots alot and takes a long time before reaching back to the setpoint.
Throttle to control pitch
If using manual throttle, it can be used to manipulate the ascend/descend process without changing autopilot modes and parameters. For example, throttle up a bit can make a descent shallower:


If Speed Control is activated, it will set to max thrust when climbing, and min thrust when descending. This behavior returns to normal when reaching relaxing altitude frame or disabling either FLC or Speed Control.