PID gains from MATLAB way higher than ArduPilot limits — what am I missing?

Hi everyone,

I’m designing the pitch-rate (Q) controller for a fixed-wing aircraft and I’m running into a big discrepancy between the PID gains I get in MATLAB and what ArduPilot allows.

I derived the transfer function of pitch rate Q over elevator deflection delta, measured respectively in [rad/s] and [rad].

I then multiplied it by the transfer function of the servomotor I am using. Using this combined plant, I designed a PID controller in MATLAB. The controller works fine in simulation, but the gains are way higher than what Ardupilot allows, for example the P gain is supposed to be around 7, while Ardupilot only allows it to be at most 0.35

Naturally, a few questions arise.

Am I modeling the system incorrectly for ArduPilot’s control structure?

Is there a mismatch in units, normalization, or loop structure that I’m missing?

How should I properly map a MATLAB-designed controller to ArduPilot parameters?

Thanks in Advance for the help

I hope I’m wrong, but I would be surprised if anyone can help you without sharing more details.

My recommendation: Write out as clear of a “problem statement” as you possibly can. Generally things like:

  • What result(s) you expect. (And why you have those expectations.)
  • Things you think could possibly be the problem.
  • What equations you start from (with units).
  • What tools you use.
  • Details of how you get the surprising result(s).

Make it detailed enough that someone else could exactly reproduce your results.

In my personal experience, when I do a careful job to explain the issue, ~80% of the time I end up spotting my own mistake(s). In the other 20%, folks appreciate the effort I’ve put into trying to help myself, and they help me figure it out.

2 Likes

As an aside, this is a big one. I once read about a professor who would make students speak to a teddy bear about the problem they are facing before approaching him. A lot of the problems got solved by talking to the bear and only any remaining issues went to the professor :grinning_face:

1 Like
2 Likes

Hey! thanks for the feedback. You are right, I should give more context.

I am modeling my aircraft’s short-period pitch dynamics following the book “Flight Stability
and Automatic Control”, by Dr. Robert C. Nelson.

The transfer function equation for short-period found at page 284 of the book, when I substitute my aircraft’s parameters, yields

Q (s) / Delta (s) = (441.3s + 4637) / (s^2 + 19.66s + 345.5)

With q pitch angle rate measured in [rad/s] and delta elevator angle, measured in [rad]. Q and Delta are the respective Laplace transforms of q and delta,

I model my servo dynamics with a simple first order system TF, of the form

Delta (s) /U_(normalized) (s) = 1.047/(0.03s + 1)

When multiplied by my pitch rate dynamics, it gives me the following plant transfer function

P(s) = (462s + 4855) / (0.13 s^3 + 3.556 s^2 + 64.57 s + 345.5)

After importing this plant in a MATLAB transfer function and running the command
CPD = pidtune(plantTF,"PD"), I get the following gains:Kp = 3.96, Kd = 0.0348 .
These results are not compatible with Ardupilot’s max P gain for pitch rate, which is at max 0.35

I am unsure why this is. So then my questions are:

Am I modeling the system incorrectly for ArduPilot’s control structure?
Is there a mismatch in units, normalization, or loop structure that I’m missing?
How should I properly map a MATLAB-designed controller to ArduPilot parameters?

You can’t just apply any chosen control structure and expect it to match. You need to read the AP source to analyze its architecture.

2 Likes

I agree with Yuri. And

Am I modeling the system incorrectly for ArduPilot’s control structure?
Is there a mismatch in units, normalization, or loop structure that I’m missing?
How should I properly map a MATLAB-designed controller to ArduPilot parameters?

It sounds like you already figured this out yourself, too!

Thank you guys! I’ll try taking a closer look at it.
The source can look very intimidating at first glance, do you have any recommendations on where to start?

Yes, source-diving is very hard. Help me understand your coding familiarity and experience?

I find LLM (AI) assistants are wonderful in “I want to learn how to <do X = “understand source code of Ardupilot”>. What’s the big picture, and what are the first steps to get started?” Do you have access to a good LLM assistant?

I used the AI Overview from Google (free! but often not as good as paid alternatives) on your behalf and it said this first “Foundational Principle”:

  • Have a Goal: It’s easiest to read code when you have a specific purpose, such as fixing a bug, adding a feature, or understanding a specific algorithm. This gives you a narrow focus and helps you ignore irrelevant code.

That’s perfect for you! You’ve already got a background in controls & dynamic systems + topic-specific experience on this problem!

I can read and write code to a reasonable extent, mainly used java and python for a handful of projects.
My goal is to understand the pitch control architecture in the source of ardupilot so I can use my control systems experience so I can derive my own PID gains, I just don’t know where to start and what to look for, since the source is huge and pretty convoluted in my eyes.

I would also like to learn something from this so will be glad if anyone can confirm whether this is correct:

I think the various filters (LPF, notch, PID filters and possibly input and output smooting filters?) ardupilot uses changes the system function. I also know that there are two PID loops - the angle and the rate controllers so all these would imply a difference from a simple PID approach?

Agreed, digging from “the whole source” to “the part I care about” can be unnecessarily hard when you’re starting.

I think this is the pitch controller class which is being used: ardupilot/libraries/APM_Control/AP_PitchController.h at master · ArduPilot/ardupilot · GitHub

(Small caveat, I’m making lots of assumptions about your use-case.)

Can you dig in there and see if it helps answer your questions? OFC you’ll need C++ knowledge even to get going from there.

You’re correct, the roll controller and the pitch controller are not “identical”. I linked the pitch controller above. Anyone interested would find the roll controller in the same subdirectory here: ardupilot/libraries/APM_Control/AP_RollController.h at master · ArduPilot/ardupilot · GitHub

When you compare them side by side, you’ll see they have many similarities, but are not the same.

I think the various filters (LPF, notch, PID filters and possibly input and output smooting filters?) ardupilot uses changes the system function.

I’m not sure what you mean specifically… but by my best understanding the statement is “obviously true”. I think you mean both of these to support the conclusion:

The intent here is (IIUC) exactly what @Yuri_Rage was getting at above, and an important point for all:

You can’t expect that when you model an aircraft (using whatever modeling assumptions are justified for you) and use that to design a controller, that the designed controller will be a direct plug in to the controller that the AP source used.

If you want “your” designed controller to work on AP, you’ll need to either rewrite a custom copy AP to work the way you want (very hard) or study AP’s implementation and derive the transformation from your “P value” to the “P value” which AP uses.

(You were on the right track knowing that the units need to match… but that’s only the first of many ways it needs to match.)

That in @AtomicBanana’s model the filters aren’t accounted for…

Oh didnt know the roll and pitch controllers differ but I was talking about the Angle and Rate PIDs. Maybe that is only present on copters?

That in @AtomicBanana’s model the filters aren’t accounted for…

Thank you. Yes, I agree! In general, any kind of pre (or post) filtering would be yet another of the “many ways” that you need to adjust your own derived controller’s values to ‘match’ the system’s.

In specific cases, it may be that you can safely neglect the presence of some of these filters and your designed controller will ‘work well’. But that’s a hard judgement call to make until understanding the details of the specific filter.

but I was talking about the Angle and Rate PIDs. Maybe that is only present on copters?

Thanks for clarifying. Indeed, I totally misread your post, and caused the confusion myself by going on a tangent about roll vs pitch control. :slight_smile: Sorry about that.

FWIW, I interpreted AtomicBanana’s ask to be exclusively about the pitch-rate controller on Plane. (I didn’t check if a pitch-angle controller exists, if it’s a PID, etc.)

1 Like

Anyway the pitch and roll controllers being different is interesting. Have to try to learn the code sometime. But what might be the reason? Is it because on planes the pitch and roll axes aren’t symmetric, or in other words perhaps, controlled differently? I don’t think the roll and ltich controllers would be different on Copter, right?

But what might be the reason? Is it because on planes the pitch and roll axes aren’t symmetric, or in other words perhaps, controlled differently? I don’t think the roll and ltich controllers would be different on Copter, right?

Yes, I agree (although have not checked the code to confirm).

Thanks for the starting point, I’ll definitely look into it thoroughly as soon as I get home

In the meantime, I am wondering whether the model for flight dynamics listed in the book “Flight Stability and Automatic Control”, by Dr. Robert C. Nelson, is to be ditched completely, in favour of what ardupilot expects? If so, how does ardupilot model short-period pitch rate dynamics ?

I don’t know that you should disregard Nelson, but you can’t just plug in an arbitrary (if popular) algorithm and expect an apples to apples result.

See here for a high level block diagram overview. From exactly where this derives, I can’t say. I’m not super involved in Plane’s code development.

2 Likes