LQRControlledRotorCraft
Quadrotor under static LQR state feedback. The 13 measured signals from the RotorCraft (altitude, roll, pitch, yaw, forward, sideways positions; their time derivatives; and an altitude-integral state) drive a 4-output LQRGain whose outputs command the four thrusters.
The gain matrix K is normally computed offline (e.g. via lqr in Julia) and passed in at instantiation. For negative feedback u = -L*x, pass K = -L.
Usage
MultibodyComponents.LQRControlledRotorCraft(K=[[-3.590249696105279, -6.386205455329567, 0.0, -0.5, 0.7071067811863276, 0.0, -2.4104333743964053, -0.9347669692054266, 0.0, -0.5033317624877438, 2.453372410273359, 0.0, -1.1180339887498718], [-3.590249696105340, 0.0, 6.386205455330055, 0.5, 0.0, 0.7071067811864641, -2.4104333743964120, 0.0, 0.9347669692054512, 0.5033317624877437, 0.0, 2.453372410273697, -1.1180339887498978], [-3.590249696105403, 6.386205455329599, 0.0, -0.5, -0.7071067811863199, 0.0, -2.4104333743964093, 0.9347669692054266, 0.0, -0.5033317624877437, -2.453372410273364, 0.0, -1.1180339887499418], [-3.590249696105389, 0.0, -6.386205455330053, 0.5, 0.0, -0.7071067811865076, -2.4104333743964044, 0.0, -0.9347669692054503, 0.5033317624877437, 0.0, -2.453372410273718, -1.1180339887498985]])
Parameters:
| Name | Description | Units | Default value |
|---|---|---|---|
add_load | Attach a Cable + suspended Body load to the airframe | – | true |
end_joints | Include Universal joints at both ends of the cable | – | true |
number_of_links | Number of rigid segments in the cable | – | 3 |
K | Feedback gain matrix (4 × 13) applied as u = K*y (so for negative state-feedback u = -L*x the default already stores -L). The default was computed by dyad/examples/quad_lqr.jl for the no-load airframe with Q = diag([30,1,1,1,1,1,20,1,1,1,10,10,5]), R = I(4); override at instantiation to install a different gain. | – | [-3.5902496...9887498985] |
Behavior
Source
"""
Quadrotor under static LQR state feedback. The 13 measured signals from the
`RotorCraft` (altitude, roll, pitch, yaw, forward, sideways positions; their
time derivatives; and an altitude-integral state) drive a 4-output `LQRGain`
whose outputs command the four thrusters.
The gain matrix `K` is normally computed offline (e.g. via `lqr` in Julia)
and passed in at instantiation. For negative feedback `u = -L*x`, pass `K = -L`.
"""
component LQRControlledRotorCraft
world = MultibodyComponents.World(nominal_length = 0.1) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 20, "y1": 20, "x2": 120, "y2": 120, "rot": 0}
},
"tags": []
}
}
rotorcraft = RotorCraft(number_of_links = number_of_links, add_load = add_load, end_joints = end_joints) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 40, "y1": 130, "x2": 140, "y2": 230, "rot": 0}
},
"tags": []
}
}
ie_mux = Mux1() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 180, "y1": 230, "x2": 280, "y2": 330, "rot": 0}
},
"tags": []
}
}
state_mux = Concat3(n1 = 6, n2 = 6, n3 = 1) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 320, "y1": 130, "x2": 420, "y2": 230, "rot": 0}
},
"tags": []
}
}
feedback_gain = LQRGain(ny = 13, nu = 4, K = K) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 280, "y1": 380, "x2": 180, "y2": 480, "rot": 0}
},
"tags": []
}
}
"Attach a `Cable` + suspended `Body` load to the airframe"
structural parameter add_load::Boolean = true
"Include Universal joints at both ends of the cable"
structural parameter end_joints::Boolean = true
"Number of rigid segments in the cable"
structural parameter number_of_links::Integer = 3
"Feedback gain matrix (4 × 13) applied as `u = K*y` (so for negative state-feedback `u = -L*x` the default already stores `-L`). The default was computed by `dyad/examples/quad_lqr.jl` for the no-load airframe with Q = diag([30,1,1,1,1,1,20,1,1,1,10,10,5]), R = I(4); override at instantiation to install a different gain."
parameter K::Real[4, 13] = [[-3.590249696105279, -6.386205455329567, 0.0, -0.5, 0.7071067811863276, 0.0, -2.4104333743964053, -0.9347669692054266, 0.0, -0.5033317624877438, 2.453372410273359, 0.0, -1.1180339887498718], [-3.590249696105340, 0.0, 6.386205455330055, 0.5, 0.0, 0.7071067811864641, -2.4104333743964120, 0.0, 0.9347669692054512, 0.5033317624877437, 0.0, 2.453372410273697, -1.1180339887498978], [-3.590249696105403, 6.386205455329599, 0.0, -0.5, -0.7071067811863199, 0.0, -2.4104333743964093, 0.9347669692054266, 0.0, -0.5033317624877437, -2.453372410273364, 0.0, -1.1180339887499418], [-3.590249696105389, 0.0, -6.386205455330053, 0.5, 0.0, -0.7071067811865076, -2.4104333743964044, 0.0, -0.9347669692054503, 0.5033317624877437, 0.0, -2.453372410273718, -1.1180339887498985]]
relations
connect(rotorcraft.y_pos, state_mux.u1) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 300, "y": 151}, {"x": 300, "y": 152}], "E": 2}],
"renderStyle": "standard"
}
}
connect(rotorcraft.y_v, state_mux.u2) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(rotorcraft.y_Ie_alt, ie_mux.u1) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 160, "y": 209}, {"x": 160, "y": 280}], "E": 2}],
"renderStyle": "standard"
}
}
connect(ie_mux.y, state_mux.u3) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 300, "y": 280}, {"x": 300, "y": 208}], "E": 2}],
"renderStyle": "standard"
}
}
connect(state_mux.y, feedback_gain.u_in) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 450, "y": 180}, {"x": 450, "y": 430}], "E": 2}],
"renderStyle": "standard"
}
}
connect(feedback_gain.y_out, rotorcraft.u) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 10, "y": 430}, {"x": 10, "y": 180}], "E": 2}],
"renderStyle": "standard"
}
}
endFlattened Source
"""
Quadrotor under static LQR state feedback. The 13 measured signals from the
`RotorCraft` (altitude, roll, pitch, yaw, forward, sideways positions; their
time derivatives; and an altitude-integral state) drive a 4-output `LQRGain`
whose outputs command the four thrusters.
The gain matrix `K` is normally computed offline (e.g. via `lqr` in Julia)
and passed in at instantiation. For negative feedback `u = -L*x`, pass `K = -L`.
"""
component LQRControlledRotorCraft
world = MultibodyComponents.World(nominal_length = 0.1) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 20, "y1": 20, "x2": 120, "y2": 120, "rot": 0}
},
"tags": []
}
}
rotorcraft = RotorCraft(number_of_links = number_of_links, add_load = add_load, end_joints = end_joints) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 40, "y1": 130, "x2": 140, "y2": 230, "rot": 0}
},
"tags": []
}
}
ie_mux = Mux1() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 180, "y1": 230, "x2": 280, "y2": 330, "rot": 0}
},
"tags": []
}
}
state_mux = Concat3(n1 = 6, n2 = 6, n3 = 1) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 320, "y1": 130, "x2": 420, "y2": 230, "rot": 0}
},
"tags": []
}
}
feedback_gain = LQRGain(ny = 13, nu = 4, K = K) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 280, "y1": 380, "x2": 180, "y2": 480, "rot": 0}
},
"tags": []
}
}
"Attach a `Cable` + suspended `Body` load to the airframe"
structural parameter add_load::Boolean = true
"Include Universal joints at both ends of the cable"
structural parameter end_joints::Boolean = true
"Number of rigid segments in the cable"
structural parameter number_of_links::Integer = 3
"Feedback gain matrix (4 × 13) applied as `u = K*y` (so for negative state-feedback `u = -L*x` the default already stores `-L`). The default was computed by `dyad/examples/quad_lqr.jl` for the no-load airframe with Q = diag([30,1,1,1,1,1,20,1,1,1,10,10,5]), R = I(4); override at instantiation to install a different gain."
parameter K::Real[4, 13] = [[-3.590249696105279, -6.386205455329567, 0.0, -0.5, 0.7071067811863276, 0.0, -2.4104333743964053, -0.9347669692054266, 0.0, -0.5033317624877438, 2.453372410273359, 0.0, -1.1180339887498718], [-3.590249696105340, 0.0, 6.386205455330055, 0.5, 0.0, 0.7071067811864641, -2.4104333743964120, 0.0, 0.9347669692054512, 0.5033317624877437, 0.0, 2.453372410273697, -1.1180339887498978], [-3.590249696105403, 6.386205455329599, 0.0, -0.5, -0.7071067811863199, 0.0, -2.4104333743964093, 0.9347669692054266, 0.0, -0.5033317624877437, -2.453372410273364, 0.0, -1.1180339887499418], [-3.590249696105389, 0.0, -6.386205455330053, 0.5, 0.0, -0.7071067811865076, -2.4104333743964044, 0.0, -0.9347669692054503, 0.5033317624877437, 0.0, -2.453372410273718, -1.1180339887498985]]
relations
connect(rotorcraft.y_pos, state_mux.u1) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 300, "y": 151}, {"x": 300, "y": 152}], "E": 2}],
"renderStyle": "standard"
}
}
connect(rotorcraft.y_v, state_mux.u2) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(rotorcraft.y_Ie_alt, ie_mux.u1) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 160, "y": 209}, {"x": 160, "y": 280}], "E": 2}],
"renderStyle": "standard"
}
}
connect(ie_mux.y, state_mux.u3) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 300, "y": 280}, {"x": 300, "y": 208}], "E": 2}],
"renderStyle": "standard"
}
}
connect(state_mux.y, feedback_gain.u_in) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 450, "y": 180}, {"x": 450, "y": 430}], "E": 2}],
"renderStyle": "standard"
}
}
connect(feedback_gain.y_out, rotorcraft.u) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 10, "y": 430}, {"x": 10, "y": 180}], "E": 2}],
"renderStyle": "standard"
}
}
metadata {}
endTest Cases
No test cases defined.
Related
Examples
Experiments
Analyses