I’m working on a multi-input/output (MIMO) learning-lab of sorts: Linear Quadratic (LQ) methods of attitude control instead of the decoupled roll-pitch-yaw PIDs and associated thrust controller. In a MIMO scheme thrust and the attitude axes are coupled in the solution (thrust somewhat less so but that’s my initial topic below).
I also see on here folks who are occasionally interested in model-predictive-control (MPC) for academic work. My LQ interests are a structural basis for any interest in MPC so with this topic I’m inviting any-and-all to discuss these topics and work together on how to structure an approach within the codebase.
At the point of creating this topic I have on my bench…
- An accumulating write-up at…
This has base theory and various diversions on the electro-mechanical theory side. I also have a nubmer of matlab resources to paper-study work.
-
A roughed-in AC_Attitude_Control_Multi_LQ class on my bench with #define logic needed to instantiate it instead of the AC_Attitude_Control_Multi class for typical quad.
-
Sim environment
Matlab SITL sim and MATLAB json listener for some streaming output plotting as I implement LQR schemes (and eventually LQ with roll-pitch-yaw reference inputs instead of regulation to zero)
- Questions/challenges…
A) MIMO scheme relies on kinetic model (units matter for now) instead of kinematic design within the codebase. not to say the MIMO scheme can’t evolve similarly BUT the “Academic” starting point of dealing with a physics model produces controller command outputs as thrust and torques, which then map to propeller speeds through to the ESC…mapping all this to the “motors” output logic needs some work from me still.
B) related to this, “Thrust” is presently decoupled as the z-controller’s output into attitude control, albeit with some, “boost” logic to account for roll-and-pitch but as-is base-level thrust for hover PLUS acceleration in Z is an input to attitude control.
LQ attitude controller output of roll-pitch-yaw as torques from a system of 4 propeller speeds is solveable as
Aw=T
where…
T is a 4-element vector [Thrust, Troll, Tpitch, Tyaw] (command outputs)
A maps prop speeds to torques through thrust and drag coefficients and quad lever arm.
w is solved for given controller output vector T. w is a 4-element vector of prop speed squared for props 1 to 4.
I’m starting this topic at a conceptual stepping-off point and would love some advice…
- I can let the existing Z-controller operate independent of attitude control and accept the unitless “thrust” output as input to my attitude control.
-I then need to figure out how to scale it into the first element of my T vector above, while the remaining 3 elements of that vector are from my LQ controller output.
OR…
2) I pull Z-error into my AttitudeController and generalize my thrust reference as a combination of minimum for hover (overcome g in z) and any additive acceleration in Z, X, and Y.
-This gets a bit logically “circular” because X-Y accelerations are achieved through non-zero roll and pitch reference inputs.
I’m thinking of starting with method 1 above as I implement LQR (goal is to regulate roll, pitch, yaw to zero)
Past that when roll and pitch reference inputs are desired it implies the high-level command involves X-Y-Z accelerations which are not decoupled and then I might pull thrust into my attitude controller.
Think of the reference input as the body Z-axis relative to Down. Magnitude representing desired total thrust and directions implying desired lateral accelerations with the up component representing local NED vertical acceleration command.
hover=g, ascend >g, descend <g so there is always a non-zero vertical acceleration that, with a mass estimate is the vertical thrust.
A combination of body X,Y, and Z accelerations is represented by this vector and I think then I might be tripping over myself if I let the independent Z-axis logic run as an input to my attitude controller.
I’m rambling though…still wrestling with how to fuse thrust and attitude control in a baby-step fashion that doesn’t discard too much existing value in the codebase.
Any advice would be nice…I might be over-thinking at this point