Add airspeed TPA support
User description
add a cli command to let fixed wing use airspeed based tpa. It calculates the corresponding throttle value based on the airspeed. Ensure a seamless integration with the current throttle-based TPA. Turn it on with cli command and no more tunning is needed, fallback to old throttle based tpa if airspeed is not avaliable
tpa_breakpoint + (airspeed - fw_reference_airspeed)/fw_reference_airspeed * (tpa_breakpoint - ThrottleIdleValue(default:1150)) sim test ok
recommend to raise pitot_lpf_milli_hz on vitual pitot
PR Type
Enhancement
Description
This description is generated by an AI tool. It may have inaccuracies
-
Add airspeed-based TPA calculation for fixed-wing aircraft
-
New
airspeed_tpasetting to enable airspeed TPA mode -
Refactor TPA calculation to support both throttle and airspeed
-
Add airspeed validity check function for sensor health
Diagram Walkthrough
flowchart LR
A["Throttle Input"] --> B["TPA Calculation"]
C["Airspeed Sensor"] --> D["Airspeed Valid Check"]
D --> E["Airspeed TPA Mode"]
E --> B
B --> F["PID Coefficients Update"]
File Walkthrough
| Relevant files | |||||||
|---|---|---|---|---|---|---|---|
| Configuration changes |
| ||||||
| Enhancement |
| ||||||
| Documentation |
|
PR Reviewer Guide 🔍
Here are some key observations to aid the review process:
| ⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪ |
⚡ Recommended focus areas for reviewPossible Issue
throttle parameter but updatePIDCoefficients passes prevThrottle, which may represent airspeed-derived or filtered values in fixed-wing mode. Ensure that for multirotor mode the raw throttle is used so attenuation matches actual RC throttle, and verify integer vs float math does not cause unintended clamping. |
PR Code Suggestions ✨
Explore these optional code suggestions:
| Category | Suggestion | Impact |
| High-level |
✅
| High |
| Possible issue |
✅
| High |
Ensure a pitot sensor is detectedAdd a check in src/main/sensors/pitotmeter.c [308-316]
Suggestion importance[1-10]: 7__ Why: The suggestion correctly identifies a potential edge case where the system might incorrectly use airspeed TPA if no pitot sensor is configured, improving the robustness of the check. | Medium | |
| ||
throttle position vs tpa factor
This does look kinda over-complicated for historical reasons. But I'm not volunteering to refactor it, so I'm not really complaining.
We originally saw we need to reduce the PID when airspeed increases. Because the force/lift from the control surface is proportional to ( 0.5 * airspeed) ².
What we really wanted originally when TPA was introduced was the airspeed. But we often don't have the airspeed. So we used the throttle value to make a rough estimate of what the airspeed might be, in order to reduce the PID appropriately.
Now when we DO have the airspeed (the value we wanted in the first place), we're using the airspeed to simulate a throttle value, in order to estimate how much the throttle value might affect the airspeed and therefore the PID.
Kinda like: We want to know how much Mike weighs. The scale says he weighs 140 pounds. Therefore we can estimate he's about six feet tall. On average, people who are six feet tall weigh 155 pounds. Therefore Mike probably weighs 155 pounds (an estimate originally based on the fact that he weighs 140 pounds).
Given we already know the airspeed, there's no need to mess around with estimating a "virtual throttle", then estimating how much that will affect the velocity and therefore the force. The number we need is simply ( 0.5 * airspeed ) ² , from the lift equation.
We originally saw we need to reduce the PID when airspeed increases. Because the force/lift from the control surface is proportional to ( 0.5 * airspeed) ².
I think this only explain the first half of the theory and it is not proportial but inverse propotional, The following are my thoughts, in short the angular velocity of the plane is propotional to the control surface multiplied by airspeed. If the old TPA assumes throttle is propotional to airspeed. then it is on same page with the following. And airspeed gain reduction(TPA) will need some internal variable to calculate, then why dont we use the virtual throttle value as the internal variable to maintain the compability, reducing the workload of users to shift from throttle based to airspeed based.
Relationship Between Airspeed, Control Surface Deflection, and Angular Velocity in Model Aircraft
1. Fundamental Dynamic Equation
For a single rotational axis (roll, pitch, or yaw):
dot(ω) + A·V·ω = B·V²·δ
ω: angular velocity (rad/s)dot(ω): angular acceleration (rad/s²)V: airspeed (m/s)δ: control surface deflection angle (rad)A, B: lumped constants (geometry, aero derivatives, inertia, air density)
Interpretation:
Angular acceleration + rate damping = airspeed² × control surface deflection
2. Steady-State Condition
In our small plane, the plane enters Steady-State quily, that is why the plane is mainly driven by FF gain When angular acceleration is negligible:
0 + A·V·ω = B·V²·δ
Therefore:
ω = (B/A)·V·δ
3. Key Proportional Relationships
- At fixed
δ: angular velocity increases linearly with airspeed. - At fixed
ω: required control deflection decreases as1/V.
4. Quick Reference
-
Constant angular rate control law
δ ≈ K·(ω_cmd / V), whereK = A / B -
Two-speed comparison
For the same target angular rateω:
δ₂ / δ₁ = V₁ / V₂
Summary
| Condition | Relationship |
|---|---|
| General dynamics | dot(ω) + A·V·ω = B·V²·δ |
| Steady state | ω = (B/A)·V·δ |
| Constant rate control | δ ∝ 1/V |
| Two-speed comparison | δ₂ / δ₁ = V₁ / V₂ |
High-speed flight requires smaller control deflections to achieve the same rotation rate due to aerodynamic damping and increased control effectiveness.
I think this only explain the first half of the theory and it is not proportial but inverse propotional, ... High-speed flight requires smaller control deflections to achieve the same rotation rate due to aerodynamic damping and increased control effectiveness.
Agreed. The lift force from the control surface (the dynamic pressure) at a given AoA is proportional to (0.5 * V)² . (Assuming barometric pressure etc doesn't change)
Therefore the deflection needed to generate the force is ~ inversely proportional. (Given assumptions).
So no need to bring a simulated throttle into it.
THAT said, you actually wrote the dang code. And it works, presumably. I didn't write it and probably wouldn't, so whichever way you want to write it is fine by me. I'm somewhat regretting having said anything because you do great work and my comment wasn't pointing out a real problem that needed to be fixed. It just felt awkward to do a "virtual throttle".
Ps I had mentioned inversely proportional to (0.5 * V)², I see why you said inversely proportional to V itself. I see V is probably more correct for correcting for external disturbances, whereas V² would be for initiating maneuver, for starting a a turn. (If I understand correctly).
On an unrelated topic - I wanted to let you know I'm hoping to cut an INAV 9.0RC1 in the next couple of weeks. Hopefully with airspeed PID attenuation included. I sent a build with this plus some other PRs over to James Downing for testing.
I see V is probably more correct for correcting for external disturbances, whereas V² would be for initiating a maneuver, for starting a turn. (If I understand correctly).
I think V is more important for continuous control stick input , and V² is more important for everything else including disturbances and starting a turn.
I am changing my mind. considering only V, then the TPA formula can be much simplier δ = δref * Vref / V
but have some promlems.
- no uperlimit, hard code or config will introduce complexity
- the real situation might be some where between V² and V, and the formula could not mimic that
- there might be deflect in the control link
While the virtual throttle method has some extra parameters to toggle, or add a new parameter/modify δ = δref * Vref / V
curiousto know how others think
I love that I have someone to discuss this with who understands it better than I do. :)
the real situation might be some where between V² and V, and the formula could not mimic that
It occurs to me that V^1.3 or V^1.4 will always be in between. I think V^1.3 would probably be a good compromise between the two.
Of course, if you didn't want to do a decimal exponent, something like (0.5 * V) ^ 2 would also give a compromise value in between V and V² 😜 (Assuming the velocity is faster than a snail).
no uperlimit, hard code or config will introduce complexity
The baseline is not having any airspeed-based attenuation at all, so IMHO capping the attenuation at 4 * vref or so would be pretty good. It's not like it explodes at the cap. It just doesn't attenuate any further. I don't think the exact cap is critical. Of course one could smooth out the saturation by multiplying by (10 - Vfactor) / (Vfactor + 8) or whatever. (Where Vfactor = current airspeed / Vref).
there might be deflect in the control link
Yeah I expect the deflection will be approximately linear to the force (0.5V)^2 given the material is reasonably sized for the application.
In the end, I suspect that's about the difference between V^1.3 and V^1.35.
I got to do a preliminary test flight of this today. I am particularly interested in this because I've wanted it for a couple years. Currently I fly the three PID profiles based on custom programming logic that auto changes control profile based on airspeed. I have tuned these breakpoints as shown below (ignore the best-fit curves). These profiles are tuned fairly high to provide the best performance and stabilization without inducing oscillations. I've put many hours of flight on these settings without issues, and these PIDs are well established. Also I am using the Matek digital airspeed sensor.
To test this PR, I applied airspeed TPA to profile 2, and added a switch that would force that profile over the airspeed-based changes. Profile 2 was tuned for use between 45 and 55 mph with no TPA in effect. So I applied the reference airspeed at 55mph, and the TPA throttle reference (BP) at 1500, which is roughly the throttle that achieves 55mph.
I'll talk through my flight today. I set up the TPA % at 35 to start.
Above is the view as I started flight. I increased throttle to understand how the current setting operated, and I ran into roll oscillations around 66 mph airspeed. In flight, I adjusted the TPA number to try to push the oscillation point to a higher airspeed. I increased it up to its maximum, 100, and it didn't seem to have much affect on the airspeed in which I encountered oscillations. Oscillations always seemed to occur around 66-70 mph.
I expected increasing TPA to progressively attenuate PIDs and delay oscillation onset to higher speeds. However, changing it from 35% to 100% didn’t significantly affect the oscillation airspeed, suggesting the attenuation scaling or mapping may not be strong enough.
I also tried moving the BP or TPA throttle reference up and down, from 1380 to 1605 and it always seemed to oscillate around the same airspeed, 69 mph-ish. I was hesitant to change this a whole lot because I didn't really understand what effects it would have on flight performance.
I never ran into any oscillations or issues at lower airspeeds, only higher airspeeds. It was hard to tell, but it seemed like it may have a little more stability when in my profile 1, than when I locked in profile 2.
Because TPA is largely an invisible adjustment behind the scenes, its difficult to fully understand and visualize what's going on inside it while flying, and because airspeed is mapped on top of throttle, it makes it difficult to understand the attenuation curve when looking at the current graphs.
If you've got any advice for how I should adjust the "TPA levers", I can do another test flight tomorrow to test anything different. My takeaway is that 100% TPA doesn't seen to be enough. I'd love to get a better idea of what the formula is that I applied, and what that looks like on top of the stepped profile program that I use today.
BTW, I am James Downing FPV on discord.
I did some further digging on this, and I attempted to visualize the airspeed TPA math directly to my stepped curve. I think I uncovered something.
First, I realized I had something wrong in my earlier graph. In my second step profile, my Roll-P (which is what was likely causing my roll oscillation) is actually higher than I have depicted. I have it set at 46. So I marked that on the graph below with the green dot. That's at the reference airspeed, 55 mph.
I then graphed in red and orange the two curves I flew. Starting with 35% TPA factor, and then again at 100% TPA factor. I encountered an oscillation at roughly 65mph and 70 mph. Those two points are shown purple and annotated. A rough "local max" slope line can be inferred by these two points. It shows that the ideal curve needs to be steeper than what is provided.
I found what look to be two potential solutions, both graphed below.
The preferred solution I believe is to remove the reference to idle throttle (or more accurately pull that down to 0). This is shown in the blue line. Unless I did something wrong in my math, its not doing what we want it to. Its really the cause of the slope limitation. When I set that to 0, I get a curve that looks much more like what is intended, and its very close to the "local max" slope in that airspeed range.
An alternative approach could be to increase the TPA %. I increased it to 300% and was able to create the grey dashed line. I don't think this is as ideal, but it would be preferred to at least have greater control on the effective slope.
There's also a non-zero potential I got my math wrong and translated this incorrectly, but this matches my experience. Hope this helps shed some light on what I saw.
I need to apologize, the graph I originally produced didn’t sit right with me. The curves didn’t match the logic I expected and saw from the code and other reference material, they were far too linear looking. After re-checking the math carefully, I found some errors. The overall takeaway about why oscillation occurs was still correct, but my earlier recommendation was not.
Below is the corrected airspeed-TPA graph based on the exact formulas pulled from the code (double checked this time). The red and orange lines and purple points still represent the same things in my prior post, but they show the correct overall shape. 100% TPA attenuates more than I showed before, but not significantly more. This increased the slope of the "local max" roll-P term calculated based on the oscillation points I encountered. The low-speed is boosted much more than I calculated last time, and I show the 2x cap on the graph rather than leaving it unbounded.
My conclusion has changed. We simply need a higher dynamic TPA range in order to better match the curve of the dynamic pressure effects. Planes with looser tuning may not reveal these effects when testing. However on my tightly tuned Penguin, the mismatch is noticeable. If I had to make an educated guess at the best dynamic pressure curve based on the data I have available, I think it would be in the range of 200-250% TPA.
I recommend opening the bounds for the dynamic TPA factor. Instead of limiting it to 0-100%, it needs to be 0-300% at minimum, but it may make sense to open this up further to accommodate and anticipate future needs. I also recommend the removal of the lower bound of 1/2 attenuation factor. If I had a lower bound of 1/2 TPA factor, there's a chance I'd still run into an oscillation at or above 100 mph. Difficult to extrapolate this, but I'd recommend lowering the lower scaler bound to 1/4 TPA. I think the upper bound of 2X can remain.
Thanks for your time on this. I think with these small tweaks it will be ideal.
Recommendations:
- Increase allowable TPA dynamic factor from 0-100% to 0-300%, or even as much as 500%.
- Remove the lower attenuation limit of 1/2, replace with 1/4.
- Keep current upper bound of 2x.
In speaking with Jetrell, I realized some minor clarification would be helpful.
In my last post, I referred to the "TPA dynamic factor", for lack of the correct term. The correct term is tpa_rate. So to clarify my recommendation is to raise the upper limit of tpa_rate from 100 to at least 300, with 500 giving more headroom as needed to accommodate different unforeseen setups.
Second, I recommended moving the lower attenuation limit from 1/2 to 1/4. This is a hard coded sanity limit. I added an annotation on the graph with the dotted blue lines, showing where my "theoretically ideal" 225% tpa_rate line would be otherwise truncated at 1/2 with today's limit. This could potentially create oscillations at very high speeds, 100mph+ because it didn't allow enough attenuation.
The recommendation is to adjust the following line in pid.c from:
tpaFactor = constrainf(tpaFactor, 0.5f, 2.0f);
to:
tpaFactor = constrainf(tpaFactor, 0.25f, 2.0f);
I'm looking to get INAV 9RC1 cut very soon so that 9.0 can be released in time to flash Christmas gifts with it.
Based on the above discussion about using an exponent of around ^1.3 or ^1.5, and the testing by @trailx , do you expect to make further refinements on this soon?
My tests showed the current tpafactor constraint of 0.5 attenuation to be okay on planes with lower control surface throw limits, and at speeds up to around 150km/h.. But beyond that speed, or if the airplane has larger control surface throws. Then attenuating the gains by 50% was not enough.
I'd agree with James. It could do with the gains being attenuated by 75%. Which lowers them to only 25% of their tuned value, when at the TPA_breakpoint.
And due to this. I also think it might be good to have the tpafactor broken out as a user adjustable setting, within that new constraint.
Just to add a bit more. I think it would also aid attenuation/boost response time if Down Pitch was accounted for in the calculations. I noticed there was occasionally a little bit of lag in the virtual airspeed. Likely GPS velocity related.
But if it knew an attitude change was commanded. That could maybe bring on attenuation/boost faster.
When testing this. It should also be noted that fw_tpa_time_constant ideally should be set to zero, Otherwise it will add to this lag.
Another thing that would be helpful for tuning. Is if the TPA gain changes could be shown on the OSD Outputs. So the user can see the attenuated or boosted gains being adjusted real-time while in flight. This would certainly help while trying to get the base gain tune more accurate etc.
@sensei-hacker I have update the codes to use ^1.2 as default with 2x(low speed)~0.3x(high speed) limiter. and seems ok in SITL.
Update the pitot LPF Hz default value to 1hz, default 0.35hz is lagging
Looks like you changed the code to no longer map to throttle. If I followed the math right, the proposed ^1.2 default looks like its effectively really close to my proposal of 225%. Purple line is new power function. Is this power value adjustable in the air? I didn't look that far into the code, but that's typically how I tune.
Thanks! Looking forward to flying it. Hopefully tomorrow.
@shota3527 Thanks for the extra commits.. You've ticked a lot more boxes with its handling.
However, I don't mean to come across ungrateful for your work here. But integrating pitch angle based on + or - from gravity vector, would help in a GNSS failure or if a reduction in airspeed accuracy occurs in aerobatic maneuvers, which Turnrate can't detect either... Or the pitot tube gets partially blocked.
My reasoning is this. With this addition, users will now likely have the base PID tune at the TPA_breakpoint, set much tighter than before. Which would cause a much higher probability of control surface oscillations, if airspeed sensor inaccuracy occurs.
It's in the case of a dive condition that the current fixedwing TPA doesn't work correctly. Because throttle can be low and airspeed will still rise in a dive. So due to this fact. If the plane either goes into a nose downward dive, either aerobatically by a stick command, whether from right way up or inverted flight. Or a command that comes from the nav controller. Or even a loss of control leading to a nose down dive,. This detection of pitch angle with either an increase in acceleration or a timer, should certainly indicate that airspeed will be rising. Which should be a safe fallback for sensor failure, and also fix the limitations of the current fixedwing TPA implementation. What is your view on this ?
I got two flights in today on this PR. I'll try to keep my notes short. Wind was between 10-15 mph according to both feel and windspeed estimator in INAV. Once again I took off into my airspeed-driven 3-profile setup. I had a switch that would lock the middle profile, which is the one that had airspeed-pid-attenuation power at 1.20. Reference airspeed was set to 55 mph, where profile 2 maxed out previously.
First flight, overall everything performed as expected. Low speeds worked flawlessly, showing excellent control at low speeds even in the wind. I did run into some oscillations in the 75+ mph range, but I noted that my pitot was under-reporting airspeed. I have both GPS 3D speed and airspeed on the OSD, and airspeed was consistently low. I've had a consistent struggle with this and am working on tuning the scale properly. Assuming this was the issue, I landed and adjusted the scale.
Second flight, the airspeed was more inline with expectations at normal flight speed, while over-estimated at low speeds. I think the FC restart in windy conditions disturbed the zero offset. That said, the oscillations were gone. I did a few steep power off and power on dives without issue.
Overall, this flew extremely well, and I'm looking forward to getting my pitot sensor dialed in a little better, and further adjusting things as needed. I'd like to try flying with the virtual pitot too.
TLDR:
- Ensure airspeed sensors are calibrated well, otherwise if its under-reporting airspeed, it may not attenuate well enough at higher speeds, but this isn't an issue with this PR, just a general implementation note.
- Being able to adjust the airspeed PID attenuation power, reference airspeed, and pitot scale in-flight via the OSD adjustments tab would be useful improvements.
Thanks for all your work on this!
In case of climb/dive situation, how about based on current throttle based tpa, offset the throttle value by "pitch to throttle value"(i forget the variable name but it is in navigation settings). Then hopefully no additional parameters needed.
I am also thinking about raise the default tpa value from 0, if it is also 0 in the default presets. Then user just need to set the fw_reference_airplspeed. Then it is mostly ok.
pitch2thr is typically only tuned for climb performance up to the max angles because this is only used for automated flight modes. I've got pitch2thr set to 10 (not sure if that's the default or not, I don't remember). If we use pitch2thr as an unconstrained multiplier, and assume the ref throttle is set to 1500, I'd essentially max out the TPA effect at 50 degrees (50*10=500, gets you to 1000 or 2000). Or potentially get as much as a 900us effect with a vertical dive or climb. That seems excessive to me and would get truncated in many cases to max boost or min attenuation levels - for instance a power off 90deg dive would be equivalent to almost full power level? I mean, maybe, but it really depends on the plane and how well its tuned.
Notable is the physics as you dive steeper - the effect that gravity has isn't linear, especially as you get to very steep dive angles - its added effect is minimal for every additional degree of tilt. It may make sense to apply a sine function over top of the pitch2thr, roughly shown in the screen shot below (the 57.29 is just there to turn radians into degrees). This would naturally taper the pitch2thr effect at steeper angles while still compensating linearly as expected in the typical range.
It would end up something like: effective_pitch = sin(pitch_angle / 57.29) * 57.29 (I'm sure theres a better way to do the radian/deg math) which then gets to multiplied by pitch2thr.
It may make sense to apply a sine function over top of the pitch2thr, roughly shown in the screen shot below (the 57.29 is just there to turn radians into degrees). T
Agreed. The force of gravity accelerating the aircraft (replacing motor thrust) is proportional to the sine of the angle. Linear is close enough up to about 30-40 degrees, which is fine for adjusting the actual throttle with nav_fw_pitch2thr - you aren't going to reduce it below zero. :)
I've flown the current implementation on my Penguin a few additional times since my last update, and it flies great. No more need for my stepped PID attenuation program. Today's flight had very little wind, and I was able to confirm the calibration on my airspeed pitot. With that correct, I didn't run into any oscillatory issues, but those oscillations could also have been adjusted by applying a higher attenuation power. Again, it would be nice to be able to adjust this in flight, but I don't feel its imperative for inclusion on 9.0 RC.
I am curious if the 1.20 power on Airspeed TPA will be a constant for all planes, but I do believe its a solid starting point, and luckily - its adjustable.
TPA meaning Throttle PID Attenuation does seem like a bit of a misnomer now. I'm going to propose we keep "TPA" though, since its now embedded in the lexicon of INAV/BF, but I propose we change its interpretation to mean "Tuned PID Attenuation". So Airspeed TPA meaning "Airspeed-Tuned PID Attenuation" still makes sense. Certainly more sense than "Airspeed Throttle PID Attenuation". Standard Throttle TPA can then be referred to as Throttle-Tuned PID Attenuation. I think it would be best to differentiate it as "Throttle TPA" in any documentation updates.
My friends and I have also been testing this feature over the last week. From what we can tell it works good. The only issue we've found is surrounding attenuation delay when sharp turns or loops are made. And I also found attenuation was slower and sketchy if the plane was diving or climbing at a high angle greater than 70°. This virtual airspeed delay effecting gain reduction could be seen in one of the guys data logs. It wasn't much. Only about 450ms. However it was enough to cause a slight ringing or oscillation on roll and pitch traces when the gains are tuned tightly at reference_airspeed.
@trailx Again, it would be nice to be able to adjust this in flight
@shota3527 I agree with this. Tuning is noticeably more time consuming. It would be awesome if airspeed_tpa_pow was broken out in the OSD and Adjustments for inflight tuning,, as TPA_rate is. And possibly have fw_reference_airspeed broken out as TPA_breakpoint is also.
AFAKI, this isn't to replace TPA. But to be a better option if you can use it.
So my recommendation would be to leave TPA as TPA. Which isn't a misnomer if it remains as it was. This should be called something like SPA for Speed PID Attenuation, or APA for Airspeed PID Attenuation.
Also, adding adjustments and the appropriate OSD elements should be pretty simple. It would also be nice to see the setup to this in Configurator above or below the TPA settings.
MrD-RC: or
APAfor Airspeed PID Attenuation.
I was wondering why this new feature was still being called TPA if T means throttle... but yes I think APA makes better sense, or since Air Speed can be abbreviated as AS, ASPA would be another option.
updated cli variable name to apa enhanced the old tpa method with pitch angle awareness
@shota3527 Thanks for your work on this. I went over your commits and did my best to translate its function into tuning info for the release notes. Let me know if it covers everything you intended it to. Or I left anything out ?
https://github.com/iNavFlight/inav/wiki/PID-Attenuation-and-scaling
Edit: Have a look at the part I wrote as a caution. What is you view on this with the use of high power airplanes ? Or have I missed something in TPA/Pitch angle operation.
Lots of info in there @Jetrell. I don't know what the right mechanism would be for providing feedback on different parts. There are a few small items I see. Overall I appreciate the detail, though it may be bordering on too much information for the average user and may result in overload.
Since you asked specifically about the caution about planes with high thrust to weight, where did the referenced 1.3:1 power/weight ratio come from? The resolution implies that the TPA_rate would need to be adjusted, but I'd think the pitch2throttle would be the item you'd ideally adjust, right? I think if P2T is adjusted to maintain a constant speed during climb and dive, then it should be relatively well tuned. Until there's more time on it, I think the warning may be clearer if it states: while the system adjusts the PIDs proportionally through vertical pitch and dive angles, it may not be well tuned beyond climb and dive angles seen in typical autopilot flight profiles (+/- 30 deg).
Also, here are some reference images that should help visualize how the system adjusts the attenuation/gain curve depending on a few factors. I found the reference images provided previously to be really helpful to help me understand what was going on behind the scenes.