...
Historically, AM has run on the “safety” chip of ZP-HW, however, since 2021, ZP has been shifted to a one-chip model, and so AM has been ported to run alongside PM, TM, and SF. It has been adapted to fly fixed wing aircraft, quadcopters, and in its most recent form, hybrid vtol aircraft.
Since 2022, Attitude Manager has been brought under the Umbrella of System Manager (SM), which alleviates attitude management of non-attitude management tasks (such as getting instructions, etc etc).
Old Architecture & Design
Attitude manager exists with 8 states, each of which handles a distinct state of control. AM also ensures that any fatal failures lead to a disarming and flight termination of the drone, as well as ensuring that there is no output when the drone is in a disarmed state.
...
The state machine is as follows:
...
New Architecture
Attitude Manager now runs as a threaded event loop, generating a new result at a constant time (Since PID’s run using approximated integrals and derivatives, it is important to keep timing as constant as we can). There are three main elements or “sections” of the event loops:
Getting Instructions (from State Manager)
Running Controls Algorithms
Output Mixing
Out of the three events, the most complicated is running controls. It is the only event with “memory” of the system state, since getting instrucitons and output mixing quite literally do what they’re told to do in one step. Attitude Manager expects a common type of data from system manager, as follows:
1. Getting Instructions
AM Expects a consistent input struct that looks like the following:
Code Block | ||
---|---|---|
| ||
typedef struct inputs_to_AM_t {
// unit distance in x, y, z
float x;
float y;
float z;
// cardinal heading to be pointed at the end
float heading;
// magnitude to adjust the heading
float magnitude;
// target velocity for this portion of flight (if applicable)
float speed;
} |
You will note that this looks fairly different from the code we expect pre-2022 AM to receive, since we are now receiving GPS-style movement commands, and the decoding of the instructions is being handled by System Manager and Path Manager to generate a gps point for attitude manager to target it’s flight to.
The unit vector described by x, y, z is relative to the aircraft, which means that if no update to the instructions is given, the aircraft will continue to try and fly the given distance and end in the given heading endlessly. If for example, x, y were sqrt(2), sqrt(2), and z was 0; with a heading of 90…the aircraft would continue to fly in a cicrle (until a new command were received).
Note that the instructions do not differentiate between fixed wing or quadcopter modes. This preprocessing is handled by System Manager and the decision on which airframe to fly is made entirely by Controls & Output Mixing logic. The user, unless in an override state, has no control over how the aircraft will fly, they will only expect the aircraft to move to where they tell it to.
2. Controls
Controls lives as a separate library under AM, with only a generic ControlsInterface being exposed to Attitude Manager. A large portion of this is still under development, but generically:
AM → Controls Interface (generic base class)
ControlsInterface → Specific Controls Interfaces (extends from ControlsInterface, has actual values and configurations)
Specific Controls Interfaces → Specific Controls Algorithms (The controls algorithms are available as libs for the Controls Interfaces
StateMix
This means that for any AM, we only expose the controls interface for things like a fixed wing or quadcopter. The input to one of these controls interfaces is also generic, where only the % effect of each control surface or motor is given to the algorithm in each direction and/or axis. For example, this would be a (likely) input to a multirotor & fixed wing interface
Code Block |
---|
StateMixQuad {
//r p y x y z
(+1, -1, +1, 0, 0, 1),
(-1, -1, -1, 0, 0, 1),
(+1, +1, -1, 0, 0, 1),
(-1, +1, +1, 0, 0, 1)
}
StateMixFixW {
(+0, +0, +0, +1, +0, +0), // push motor
(-1, +0, +0, +0, +0, +0), // left ail
(+1, +0, +0, +0, +0, +0), // right ail
(+0, +1, +0, +0, +0, +0), // elevator
(+0, +0, +1, +0, +0, +0), // rudder
} |
Note that it’s possible to have any value given to the state mix between -1 and 1, this value simply describes the intensity and direction of response any particular control surface or motor will give in that axis/direction.
In a very simple sense, we are computing the moment arms & forces each actuator can give us, and using PID Controllers to target the “Force” or “rate of acceleration” we want in any particular axis, which then gets translated to our state mix. For example, if we wanted to roll right in a fixed wing, our request would be for a particular force on the roll channel, and so any element with roll (left/right ail), would be activated.
Controls Interfaces
These are still under development, we aren’t super sure how we want to store the configuration of the drone, but the controls interfaces will be aware of how that particular model of flight control works, as well as have configurable PID’s that are loaded on runtime (not compile time), so you could theoretically plug in a different SD Card with different configurations loaded and fly different planes. I would check the code to see what is the most up to date in this area.
3. Output Mixing
The last stage of AM is output mixing, where the return values (which are channel : percentage pairs) from Controls are mixed. This is handled by a tiny bit of logic and only applies to VTOL aircraft, and briefly during a transition from one stage of flight to the next. Depending on airspeed, AM might initiate the following procedure to transition from quad to fixed wing (the reverse is true from fixed wing to quad).
Enable Quad Level Hold (disabling GPS mode, the quad can now be blown by the wind).
Add push prop.
Mix in control surfaces, mix out quad level hold.
Disable Quad Mode.
This does mean that two controls algorithms may have to run simultaneously, but only for brief moments in time.