How To Use
Important implentation notes
- The telemetered effort is not scalled by K, it's the raw effort coming out of the compensator
- The telemetered time intervals are hella descetized cause I fucked up the precision
Layperson "how it works"
The central idea to spaghetti is an linear compensator that computes a control effort, given the history of measured altitudes. You don't need to know how it works in order to command it. This control effort is in kg/s. It this then scaled by a gain, called k. Since ballasting and venting are discrete on/off, and the commanded effort is continuous, this needs to be converted into a series of discrete actions, separated by a time interval. This is much like PWM, but instead of changing duty cycle directly, you are changing the time interval between events such that the action time is fixed to it's minimum acceptable value, and produce the least discretization (in the future this may want to be changed to conserve power and minimize the number of valve actions).
Constants
freq: The frequency that the controller is called out, which will be a constant 20Hz
k: Scallar gain of the controller. High gains mean more actions, tighter control. Low gain means less actions, looser control
b_dldt: Magnitude of change in lift vs time for ballast actions IN kg/s. This can be directly measured on vb, and us usually around 0.001kg/s
v_dldt: Magnitude of Change in lift vs time for vent actions IN kg/s. This is always an estimate as can not be measured directly. It's a magnitude, and therefor always positive, even though venting decreases net lift
rate_min: minimum threshold for commanding a dl/dt
rate_max: maximum threshold for commanding a dl/dt
b_tmin: the minimum time that a discrete ballast event can be called for. This sets the time that ballast event will be for.
v_tmin: the minimum time that a vent ballast event can be called for. This sets the time that ballast event will be for.
h_cmd: the command altitude for the controller to aim for
Flight Controller Guide
In the dev version of spaghetti, you can't really set bounds on your altitude as you can with the legacy controller. Instead, you set a target, and a gain, and the controller attempts to hit the target, using an effort proportional to the gain. What gain will give you the altitude range you want? Who knows.
You also have other things to tune. You want a positive effort to have an equal but opposite effect on the system as a negative effort. Thing is, you don't exactly know you dl/dt for vent actions. So, you have to guess. If it looks like venting isn't having much effect, and the controller is spending much more time above the commanded altitude than below, decrease the set dl/dt for the venting, as your estimate of it is too high.
Also, you don't want to act when your effort is really low and you are close to the target. There needs to be a minimum threshold before you start acting. This is rate_min. The higher you make rate_min, the more the controller acts like a bang-bang controller, where it waits till it's pretty late and then acts a bunch. about 1 order of magnitude below your max rate is probably a decent place to start for your rate min.
How it works
Feedback control
Spaghetti uses feedback to determine what actions it should take. This is pretty intuitive, as obviously it needs to feedback the current altitude in order to make calculation of the next desired action. Here is the control loop structure:
[ Diagram coming soon]
Compensator
The heart of the spaghetti controller is the linear compensator that calculates the control effort. The first thing you may wonder is: what do you mean by linear? and what do you mean by compensatory? First of, the compensator is a single input single output system. It calculates an output given a sequence of inputs. It's also what is called Linear Time Invariant (LTI). This means that for any input u1 that produces output y1, the input 2*u1 will produce an output 2*y1. In addition, and two different inputs u1 and u2, with corresponding outputs y1 and y2, the input u1 + u2 will have output y1 + y2. In math terms, this means that it's closed under addition and multiplication, and hence linear. The time invariant part means that if you shift an input in time, the output will be exactly the same, just also shifted in time.
Why is this so important? Because it allows us to analyze the system in the frequency domain. to be continued.
Implementation in code
If we switch gears into digital signal processing land, we realize that we can implement a linear system in discrete time using what's called a difference equation. This is just a simple equation of a linear combination of past inputs and outputs. The are magical things, and you can pick coefficients tons of different stuff.
The difference equation used for spaghetti is called a https://en.wikipedia.org/wiki/Digital_biquad_filter. This forms a 2nd order difference equation, as it uses the last two inputs and outputs. With a biquad, we can place two poles and two zeros anywhere we want in the s-plane.
If you think controls are cool and wanna learn more
Relevant classes:
- EE102A Signal Processing and Linear Systems I (highly highly recommend, great intro class)
- EE102B Signal Processing and Linear Systems II
- ENGR105 Feedback Control