Skip to content
LIBRARY
ControlledRotorCraft.md

ControlledRotorCraft

Quadrotor with three PID feedback loops (altitude, roll, pitch) and a 4-element thrust-mixing matrix. Wraps a RotorCraft and drives its thrusters from the controller outputs.

Usage

MultibodyComponents.ControlledRotorCraft(kalt=2.7, Tialt=3, Tdalt=0.5, kroll=0.2, Tiroll=100, Tdroll=1, kpitch=0.2, Tipitch=100, Tdpitch=1)

Parameters:

NameDescriptionUnitsDefault value
end_jointstrue
number_of_links3
kaltAltitude PID proportional gain2.7
TialtAltitude PID integral times3
TdaltAltitude PID derivative times0.5
krollRoll PID proportional gain0.2
TirollRoll PID integral times100
TdrollRoll PID derivative times1
kpitchPitch PID proportional gain0.2
TipitchPitch PID integral times100
TdpitchPitch PID derivative times1

Behavior

Source

dyad
"""
Quadrotor with three PID feedback loops (altitude, roll, pitch) and a
4-element thrust-mixing matrix. Wraps a `RotorCraft` and drives its
thrusters from the controller outputs.
"""
component ControlledRotorCraft
  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 = true, end_joints = end_joints) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 715, "y1": 161, "x2": 815, "y2": 261, "rot": 0}
      },
      "tags": []
    }
  }
  Calt = BlockComponents.Continuous.LimPID(k = kalt, Ti = Tialt, Td = Tdalt) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 315, "y1": 30, "x2": 415, "y2": 130, "rot": 0}
      },
      "tags": []
    }
  }
  Croll = BlockComponents.Continuous.LimPID(k = kroll, Ti = Tiroll, Td = Tdroll) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 315, "y1": 160, "x2": 415, "y2": 260, "rot": 0}
      },
      "tags": []
    }
  }
  Cpitch = BlockComponents.Continuous.LimPID(k = kpitch, Ti = Tipitch, Td = Tdpitch) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 315, "y1": 290, "x2": 415, "y2": 390, "rot": 0}
      },
      "tags": []
    }
  }
  mixer = ControlMixer() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 585, "y1": 161, "x2": 685, "y2": 261, "rot": 0}
      },
      "tags": []
    }
  }
  pid_mux = Mux3() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 455, "y1": 161, "x2": 555, "y2": 261, "rot": 0}
      },
      "tags": []
    }
  }
  pos_demux = Demux6() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 165, "y1": 93, "x2": 265, "y2": 193, "rot": 0}
      },
      "tags": []
    }
  }
  "Altitude PID proportional gain"
  parameter kalt::Real = 2.7
  "Altitude PID integral time"
  parameter Tialt::Time = 3
  "Altitude PID derivative time"
  parameter Tdalt::Time = 0.5
  "Roll PID proportional gain"
  parameter kroll::Real = 0.2
  "Roll PID integral time"
  parameter Tiroll::Time = 100
  "Roll PID derivative time"
  parameter Tdroll::Time = 1
  "Pitch PID proportional gain"
  parameter kpitch::Real = 0.2
  "Pitch PID integral time"
  parameter Tipitch::Time = 100
  "Pitch PID derivative time"
  parameter Tdpitch::Time = 1
  structural parameter end_joints::Boolean = true
  structural parameter number_of_links::Integer = 3
relations
  Calt.u_s = 0
  Calt.u_ff = 0
  Croll.u_s = 0
  Croll.u_ff = 0
  Cpitch.u_s = 0
  Cpitch.u_ff = 0
  connect(Calt.y, pid_mux.u1) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 435, "y": 81}, {"x": 435, "y": 184}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(Croll.y, pid_mux.u2) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(Cpitch.y, pid_mux.u3) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 435, "y": 341}, {"x": 435, "y": 238}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(pid_mux.y, mixer.u_in) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(mixer.u_out, rotorcraft.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(rotorcraft.y_pos, pos_demux.u_in) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [
            {"x": 835, "y": 182},
            {"x": 835, "y": 440},
            {"x": 145, "y": 440},
            {"x": 145, "y": 143}
          ],
          "E": 2
        }
      ],
      "renderStyle": "standard"
    }
  }
  connect(pos_demux.y1, Calt.u_m) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(pos_demux.y2, Croll.u_m) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 295, "y": 119}, {"x": 295, "y": 233}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(pos_demux.y3, Cpitch.u_m) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 285, "y": 135}, {"x": 285, "y": 363}], "E": 2}],
      "renderStyle": "standard"
    }
  }
end
Flattened Source
dyad
"""
Quadrotor with three PID feedback loops (altitude, roll, pitch) and a
4-element thrust-mixing matrix. Wraps a `RotorCraft` and drives its
thrusters from the controller outputs.
"""
component ControlledRotorCraft
  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 = true, end_joints = end_joints) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 715, "y1": 161, "x2": 815, "y2": 261, "rot": 0}
      },
      "tags": []
    }
  }
  Calt = BlockComponents.Continuous.LimPID(k = kalt, Ti = Tialt, Td = Tdalt) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 315, "y1": 30, "x2": 415, "y2": 130, "rot": 0}
      },
      "tags": []
    }
  }
  Croll = BlockComponents.Continuous.LimPID(k = kroll, Ti = Tiroll, Td = Tdroll) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 315, "y1": 160, "x2": 415, "y2": 260, "rot": 0}
      },
      "tags": []
    }
  }
  Cpitch = BlockComponents.Continuous.LimPID(k = kpitch, Ti = Tipitch, Td = Tdpitch) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 315, "y1": 290, "x2": 415, "y2": 390, "rot": 0}
      },
      "tags": []
    }
  }
  mixer = ControlMixer() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 585, "y1": 161, "x2": 685, "y2": 261, "rot": 0}
      },
      "tags": []
    }
  }
  pid_mux = Mux3() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 455, "y1": 161, "x2": 555, "y2": 261, "rot": 0}
      },
      "tags": []
    }
  }
  pos_demux = Demux6() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 165, "y1": 93, "x2": 265, "y2": 193, "rot": 0}
      },
      "tags": []
    }
  }
  "Altitude PID proportional gain"
  parameter kalt::Real = 2.7
  "Altitude PID integral time"
  parameter Tialt::Time = 3
  "Altitude PID derivative time"
  parameter Tdalt::Time = 0.5
  "Roll PID proportional gain"
  parameter kroll::Real = 0.2
  "Roll PID integral time"
  parameter Tiroll::Time = 100
  "Roll PID derivative time"
  parameter Tdroll::Time = 1
  "Pitch PID proportional gain"
  parameter kpitch::Real = 0.2
  "Pitch PID integral time"
  parameter Tipitch::Time = 100
  "Pitch PID derivative time"
  parameter Tdpitch::Time = 1
  structural parameter end_joints::Boolean = true
  structural parameter number_of_links::Integer = 3
relations
  Calt.u_s = 0
  Calt.u_ff = 0
  Croll.u_s = 0
  Croll.u_ff = 0
  Cpitch.u_s = 0
  Cpitch.u_ff = 0
  connect(Calt.y, pid_mux.u1) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 435, "y": 81}, {"x": 435, "y": 184}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(Croll.y, pid_mux.u2) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(Cpitch.y, pid_mux.u3) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 435, "y": 341}, {"x": 435, "y": 238}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(pid_mux.y, mixer.u_in) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(mixer.u_out, rotorcraft.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(rotorcraft.y_pos, pos_demux.u_in) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [
            {"x": 835, "y": 182},
            {"x": 835, "y": 440},
            {"x": 145, "y": 440},
            {"x": 145, "y": 143}
          ],
          "E": 2
        }
      ],
      "renderStyle": "standard"
    }
  }
  connect(pos_demux.y1, Calt.u_m) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(pos_demux.y2, Croll.u_m) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 295, "y": 119}, {"x": 295, "y": 233}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(pos_demux.y3, Cpitch.u_m) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 285, "y": 135}, {"x": 285, "y": 363}], "E": 2}],
      "renderStyle": "standard"
    }
  }
metadata {}
end


Test Cases

No test cases defined.

  • Examples

  • Experiments

  • Analyses