- Messages
- 243
- Country
Alright everyone, back again with another PID thread, only this time I am a lot farther along than I was last time.
I have created a *somewhat* working PID based on endless re-reads of my NASA documentation on the Boeing 747 classic Sperry SPZ-1 autopilot, some reading of Heretic's excellent speed PID, and lots of trial and error. I have a heading select PID controller working perfectly using the same methods as I have so far employed for the pitch autopilot, so I am well convinced I am on the right track, but I am a little stuck on the classic problem of oscillations. The roll controller works with no oscillation whatsoever, so I am also convinced that I am just messing something stupid up somewhere when it comes to pitch control but I cannot figure out what it is.
I will break down step by step what I have done because it is a complex monster of XML code.
First, the reference documents and information:
In the excerpt above, I have understood that the target elevator deflection is the sum of 3.5 degrees for every degree of pitch error (attitude signal), plus a damping signal of 2.2 or 3.5 (depending on flaps) degrees per degree/second of pitch rate. The damping signal, logically, should counteract the attitude signal. In XML, I have the following:
The code calculates pitch rate in degrees per second and filters it to remove high frequency noise (NASA says the 747 autopilot does this as well), and I have verified that part of the code works well, providing a decently smooth and only extremely slightly delayed pitch rate figure. Of note is that I reverse the signs on the pitch because it was confusing me too much to see negative numbers corresponding to positive pitch.
Then, it checks for flight simulator being paused or in slew mode, determines the pitch damping coefficient, and then calculates the target pitch to be achieved by subtracting the pitch change target (which is calculated in another section that I will show soon), from the current pitch. Finally, the pitch error is multiplied by 3.5 (attitude signal), and the pitch rate multiplied by 2.2 or 3.5 (rate signal) and then subtracted from the attitude signal to produce an elevator deflection target. I filter this as well to remove a little more of the high frequency noise caused by pitch rate.
Next, the current elevator deflection is compared to the target deflection to produce an error, which is then multiplied by 0.015 to achieve a specific amount to add or subtract from the A:ELEVATOR POSITION variable every cycle. 0.042484 and -0.031401 correspond to a maximum rate of 13 degrees per second of elevator deflection, just as the real 747 autopilot does. The 0.015 figure is arbitrary but results in precise elevator control at small deflections.
Much testing has revealed that this code deflects the elevator to exactly the deflection angles calculated by the target elevator figure, which is exciting(!) and also tells me that this part of the code probably functions more or less like the real autopilot would, perhaps only minus the arbitrary 0.015 figure for elevator deflection rate.
This next part is where I suspect the problems are occurring. The first of the pitch modes I attempted to write is one I thought would be the simplest: vertical speed mode. The Sperry SPZ-1 will seek whatever vertical speed is selected on the vertical speed wheel via the following method (pardon the terrible scan, this is the best version of the paper I have yet been able to find):
The actual vertical speed command is a function of the rate of change of vertical speed, limited to 4 ft/sec^2. The gain listed is 0.09 deg/ft/sec, and there is an integral with a gain of 0.2. Also of note is the word CAS over to the right; this means that the entire vertical speed function is finally scaled by a computed airspeed (CAS) correction figure to prevent over-controlling at high airspeed. The superscript of 2 on CAS most likely does not refer to squaring the figure, I think it is just refering to footnote 2 on the page as every other mention of CAS also has this 2 superscript with a closed parenthesis next to it [for exmaple, CAS 2) ]. Here is the CAS correction chart, showing the correction multiplier dropping from 1.0 at and below 150 knots to 0.32 at and above 275:
Alright, let's see what I came up with in XML to describe this function:
First, the rate of change of the vertical speed is calculated in the same manner as pitch rate.
The CAS gain is calculated, then the VS error is calculated in feet per second.
The next statement says that if the error is not 0, multiply this error by 0.12 (another arbitrary figure) up to a maximum of +-4 feet per second^2 to achieve the commanded rate of VS change (AP VS Rate C)
Next, calculate the error by subtracting the commanded rate from the current rate.
The next step is my attempt to calculate the correct integral. Integrals still elude me conceptually but my best attempt to understand what they do is as follows:
The rate error is multiplied by -0.2 (integral term from the chart above), and then input into the AP VS Error Ki variable which is added to itself once per second (divided by 18 for XML cycles) to achieve a summed error. I filter this value to account for high frequency noise once again.
Finally, the VS rate of change error is multiplied by -0.09 (again from the chart above), the integral error is added, the whole figure multiplied by the CAS gain, and the pitch change target up to a max of +-8 degrees is written for the elevator target code above.
Now, the results? Inconclusive (and inconsistent), at best. There is also some auto stabilizer trim code running to assist the elevator but it works without flaw so I am leaving out of this discussion for brevity. It trims when it supposed to the exact amount its supposed to so it doesn't seem important to include.
Sometimes the controller works well and will very closely maintain the vertical speed desired, sometimes it does so but with a steady state error of about 200-500 fpm, sometimes it oscillates dramatically +- 5 degrees nose up or down trying to reach the setpoint. My test scenario keeps speed and thrust settings consistent, however when the controller works well it does not seem to be much affected by thrust changes or by selecting a new vertical speed, even with turbulence and gusts, it will just do what its supposed to without flaw. But when it doesn't work, it really doesn't work.
The inconsistency is perhaps the most frustrating part of this process. Except for trying to figure out the integral term, I have not changed anything else in the code because I have verified their values are what they are a (probably) supposed to be.
I know this is a huge post and a monster of a topic to tackle but any help at all is appreciated. I am quite open to the fact that I have grossly misinterpreted something somewhere as well as I am not particularly skilled when it comes to control theory.
Thanks!
Chris
I have created a *somewhat* working PID based on endless re-reads of my NASA documentation on the Boeing 747 classic Sperry SPZ-1 autopilot, some reading of Heretic's excellent speed PID, and lots of trial and error. I have a heading select PID controller working perfectly using the same methods as I have so far employed for the pitch autopilot, so I am well convinced I am on the right track, but I am a little stuck on the classic problem of oscillations. The roll controller works with no oscillation whatsoever, so I am also convinced that I am just messing something stupid up somewhere when it comes to pitch control but I cannot figure out what it is.
I will break down step by step what I have done because it is a complex monster of XML code.
First, the reference documents and information:
- The pitch autopilot uses inputs of a 'change of pitch target' and pitch rate referred to as theta-c (𝜃c) and theta-dot (
- Each autopilot mode uses a different gain setting based on its particular error or error rate to set the pitch change target.
- Finally, the autopilot uses fixed deflection and rate gains to set the target elevator deflection. More specifically, the quote directly from the source states the following:
In the excerpt above, I have understood that the target elevator deflection is the sum of 3.5 degrees for every degree of pitch error (attitude signal), plus a damping signal of 2.2 or 3.5 (depending on flaps) degrees per degree/second of pitch rate. The damping signal, logically, should counteract the attitude signal. In XML, I have the following:
XML:
(E:Absolute time, seconds) (G:Var6) - sp4
(E:Absolute time,seconds) (>G:Var6)
l4 (>G:Var5)
<!-- Pitch Rate -->
(A:PLANE PITCH DEGREES, radians) rddg /-/ (>L:Pitch, number)
(L:Pitch, number) s8 (L:Pitch1, number) - l4 / (>L:Pitch Rate, number)
l8 (>L:Pitch1, number)
0.1 (L:Pitch Rate, number) * 1 0.1 - (L:Pitch Rate Filter, number) * + (>L:Pitch Rate Filter, number)
<!-- Elevator Control -->
(G:Var5) 0 != (A:IS SLEW ACTIVE, bool) 0 == and
if{
(A:FLAPS HANDLE INDEX, number) 0 ==
if{ 2.2 (>L:Pitch Damping, number) }
els{ 3.5 (>L:Pitch Damping, number) }
(L:Pitch, number) (L:AP Pitch Change Target, number) + (>L:AP Target Pitch, number)
(L:Pitch, number) (L:AP Target Pitch, number) - /-/ (>L:AP Pitch Error, number)
(L:AP Pitch Error, number) 3.5 * (L:Pitch Rate Filter, number) (L:Pitch Damping, number) * - (>L:Target Elevator, number)
0.1 (L:Target Elevator, number) * 1 0.1 - (L:Target Elevator Filter, number) * + (>L:Target Elevator Filter, number)
(A:ELEVATOR DEFLECTION, degrees) (L:Target Elevator Filter, number) - (>L:Elevator Error, number)
(L:Elevator Error, number) 0.015 * 0.042484 min -0.031401 max (>L:Elev Control, number)
(L:Elevator Error, number) abs 0 >
if{
(A:ELEVATOR POSITION, position) (L:Elev Control, number) - -16383 * (>K:ELEVATOR_SET)
}
The code calculates pitch rate in degrees per second and filters it to remove high frequency noise (NASA says the 747 autopilot does this as well), and I have verified that part of the code works well, providing a decently smooth and only extremely slightly delayed pitch rate figure. Of note is that I reverse the signs on the pitch because it was confusing me too much to see negative numbers corresponding to positive pitch.
Then, it checks for flight simulator being paused or in slew mode, determines the pitch damping coefficient, and then calculates the target pitch to be achieved by subtracting the pitch change target (which is calculated in another section that I will show soon), from the current pitch. Finally, the pitch error is multiplied by 3.5 (attitude signal), and the pitch rate multiplied by 2.2 or 3.5 (rate signal) and then subtracted from the attitude signal to produce an elevator deflection target. I filter this as well to remove a little more of the high frequency noise caused by pitch rate.
Next, the current elevator deflection is compared to the target deflection to produce an error, which is then multiplied by 0.015 to achieve a specific amount to add or subtract from the A:ELEVATOR POSITION variable every cycle. 0.042484 and -0.031401 correspond to a maximum rate of 13 degrees per second of elevator deflection, just as the real 747 autopilot does. The 0.015 figure is arbitrary but results in precise elevator control at small deflections.
Much testing has revealed that this code deflects the elevator to exactly the deflection angles calculated by the target elevator figure, which is exciting(!) and also tells me that this part of the code probably functions more or less like the real autopilot would, perhaps only minus the arbitrary 0.015 figure for elevator deflection rate.
This next part is where I suspect the problems are occurring. The first of the pitch modes I attempted to write is one I thought would be the simplest: vertical speed mode. The Sperry SPZ-1 will seek whatever vertical speed is selected on the vertical speed wheel via the following method (pardon the terrible scan, this is the best version of the paper I have yet been able to find):
The actual vertical speed command is a function of the rate of change of vertical speed, limited to 4 ft/sec^2. The gain listed is 0.09 deg/ft/sec, and there is an integral with a gain of 0.2. Also of note is the word CAS over to the right; this means that the entire vertical speed function is finally scaled by a computed airspeed (CAS) correction figure to prevent over-controlling at high airspeed. The superscript of 2 on CAS most likely does not refer to squaring the figure, I think it is just refering to footnote 2 on the page as every other mention of CAS also has this 2 superscript with a closed parenthesis next to it [for exmaple, CAS 2) ]. Here is the CAS correction chart, showing the correction multiplier dropping from 1.0 at and below 150 knots to 0.32 at and above 275:
Alright, let's see what I came up with in XML to describe this function:
XML:
<!-- V/S Rate -->
(A:VERTICAL SPEED, feet per second) s10 (L:VS1, number) - l4 / (>L:VS Rate, number)
l10 (>L:VS1, number)
<!-- CAS Gain -->
(A:AIRSPEED INDICATED, knots) -0.00544 * 1.816 + 1 min 0.32 max (>L:AP Pitch CAS Gain, number)
<!-- Vertical Speed Hold -->
(L:AP Vertical Mode Knob, number) 2 ==
if{
(A:VERTICAL SPEED, feet per second) (L:VS Wheel Setting, number) 60 / - /-/ (>L:AP VS Error, number)
(L:AP VS Error, number) abs 0 >
if{ (L:AP VS Error, number) 0.12 * 4 min -4 max (>L:AP VS Rate C, number) }
els{ 0 (>L:AP VS Rate C, number) }
(L:VS Rate, number) (L:AP VS Rate C, number) - (>L:AP VS Rate Error, number)
(L:AP VS Rate Error, number) -0.2 * (L:AP VS Error Ki, number) 18 / + (>L:AP VS Error Ki, number)
0.1 (L:AP VS Error Ki, number) * 1 0.1 - (L:AP VS Error Ki Filter, number) * + (>L:AP VS Error Ki Filter, number)
(L:AP VS Rate Error, number) -0.09 * (L:AP VS Error Ki Filter, number) + (L:AP Pitch CAS Gain, number) * -8 max 8 min (>L:AP Pitch Change Target, number)
}
els{
0 (>L:AP VS Error Ki, number)
0 (>L:AP VS Rate Error, number)
0 (>L:AP VS Rate C, number)
0 (>L:AP VS Error, number)
}
First, the rate of change of the vertical speed is calculated in the same manner as pitch rate.
The CAS gain is calculated, then the VS error is calculated in feet per second.
The next statement says that if the error is not 0, multiply this error by 0.12 (another arbitrary figure) up to a maximum of +-4 feet per second^2 to achieve the commanded rate of VS change (AP VS Rate C)
Next, calculate the error by subtracting the commanded rate from the current rate.
The next step is my attempt to calculate the correct integral. Integrals still elude me conceptually but my best attempt to understand what they do is as follows:
The rate error is multiplied by -0.2 (integral term from the chart above), and then input into the AP VS Error Ki variable which is added to itself once per second (divided by 18 for XML cycles) to achieve a summed error. I filter this value to account for high frequency noise once again.
Finally, the VS rate of change error is multiplied by -0.09 (again from the chart above), the integral error is added, the whole figure multiplied by the CAS gain, and the pitch change target up to a max of +-8 degrees is written for the elevator target code above.
Now, the results? Inconclusive (and inconsistent), at best. There is also some auto stabilizer trim code running to assist the elevator but it works without flaw so I am leaving out of this discussion for brevity. It trims when it supposed to the exact amount its supposed to so it doesn't seem important to include.
Sometimes the controller works well and will very closely maintain the vertical speed desired, sometimes it does so but with a steady state error of about 200-500 fpm, sometimes it oscillates dramatically +- 5 degrees nose up or down trying to reach the setpoint. My test scenario keeps speed and thrust settings consistent, however when the controller works well it does not seem to be much affected by thrust changes or by selecting a new vertical speed, even with turbulence and gusts, it will just do what its supposed to without flaw. But when it doesn't work, it really doesn't work.
The inconsistency is perhaps the most frustrating part of this process. Except for trying to figure out the integral term, I have not changed anything else in the code because I have verified their values are what they are a (probably) supposed to be.
I know this is a huge post and a monster of a topic to tackle but any help at all is appreciated. I am quite open to the fact that I have grossly misinterpreted something somewhere as well as I am not particularly skilled when it comes to control theory.
Thanks!
Chris
Last edited: