(window.webpackJsonp=window.webpackJsonp||[]).push([[393],{1523:function(e,t,r){"use strict";r.r(t);var o=r(18),a=Object(o.a)({},(function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[o("h1",{attrs:{id:"mixing-and-actuators"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#mixing-and-actuators"}},[e._v("#")]),e._v(" Mixing and Actuators")]),e._v(" "),o("p",[e._v("The PX4 architecture ensures that the airframe layout does not require special case handling in the core controllers.")]),e._v(" "),o("p",[e._v("Mixing means to take force commands (e.g. "),o("code",[e._v("turn right")]),e._v(") and translate them to actuator commands which control motors or servos.\nFor a plane with one servo per aileron this means to command one of them high and the other low.\nThe same applies for multicopters: Pitching forward requires changing the speed of all motors.")]),e._v(" "),o("p",[e._v("Separating the mixer logic from the actual attitude controller greatly improves reusability.")]),e._v(" "),o("h2",{attrs:{id:"control-pipeline"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#control-pipeline"}},[e._v("#")]),e._v(" Control Pipeline")]),e._v(" "),o("p",[e._v("A particular controller sends a particular normalized force or torque demand (scaled from -1..+1) to the mixer, which then sets individual actuators accordingly.\nThe output driver (e.g. UART, UAVCAN or PWM) then scales it to the actuators native units, e.g. a PWM value of 1300.")]),e._v(" "),o("p",[o("img",{attrs:{src:r(599),alt:"Mixer Control Pipeline"}})]),e._v(" "),o("h2",{attrs:{id:"control-groups"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#control-groups"}},[e._v("#")]),e._v(" Control Groups")]),e._v(" "),o("p",[e._v("PX4 uses control groups (inputs) and output groups.\nConceptually they are very simple: A control group is e.g. "),o("code",[e._v("attitude")]),e._v(", for the core flight controls, or "),o("code",[e._v("gimbal")]),e._v(" for payload.\nAn output group is one physical bus, e.g. the first 8 PWM outputs for servos.\nEach of these groups has 8 normalized (-1..+1) command ports, which can be mapped and scaled through the mixer.\nA mixer defines how each of these 8 signals of the controls are connected to the 8 outputs.")]),e._v(" "),o("p",[e._v("For a simple plane control 0 (roll) is connected straight to output 0 (aileron).\nFor a multicopter things are a bit different: control 0 (roll) is connected to all four motors and combined with throttle.")]),e._v(" "),o("h3",{attrs:{id:"control-group-0-flight-control"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#control-group-0-flight-control"}},[e._v("#")]),e._v(" Control Group #0 (Flight Control)")]),e._v(" "),o("ul",[o("li",[e._v("0: roll (-1..1)")]),e._v(" "),o("li",[e._v("1: pitch (-1..1)")]),e._v(" "),o("li",[e._v("2: yaw (-1..1)")]),e._v(" "),o("li",[e._v("3: throttle (0..1 normal range, -1..1 for variable pitch / thrust reversers)")]),e._v(" "),o("li",[e._v("4: flaps (-1..1)")]),e._v(" "),o("li",[e._v("5: spoilers (-1..1)")]),e._v(" "),o("li",[e._v("6: airbrakes (-1..1)")]),e._v(" "),o("li",[e._v("7: landing gear (-1..1)")])]),e._v(" "),o("h3",{attrs:{id:"control-group-1-flight-control-vtol-alternate"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#control-group-1-flight-control-vtol-alternate"}},[e._v("#")]),e._v(" Control Group #1 (Flight Control VTOL/Alternate)")]),e._v(" "),o("ul",[o("li",[e._v("0: roll ALT (-1..1)")]),e._v(" "),o("li",[e._v("1: pitch ALT (-1..1)")]),e._v(" "),o("li",[e._v("2: yaw ALT (-1..1)")]),e._v(" "),o("li",[e._v("3: throttle ALT (0..1 normal range, -1..1 for variable pitch / thrust reversers)")]),e._v(" "),o("li",[e._v("4: reserved / aux0")]),e._v(" "),o("li",[e._v("5: reserved / aux1")]),e._v(" "),o("li",[e._v("6: reserved / aux2")]),e._v(" "),o("li",[e._v("7: reserved / aux3")])]),e._v(" "),o("h3",{attrs:{id:"control-group-2-gimbal"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#control-group-2-gimbal"}},[e._v("#")]),e._v(" Control Group #2 (Gimbal)")]),e._v(" "),o("ul",[o("li",[e._v("0: gimbal roll")]),e._v(" "),o("li",[e._v("1: gimbal pitch")]),e._v(" "),o("li",[e._v("2: gimbal yaw")]),e._v(" "),o("li",[e._v("3: gimbal shutter")]),e._v(" "),o("li",[e._v("4: camera zoom")]),e._v(" "),o("li",[e._v("5: reserved")]),e._v(" "),o("li",[e._v("6: reserved")]),e._v(" "),o("li",[e._v("7: reserved (parachute, -1..1)")])]),e._v(" "),o("h3",{attrs:{id:"control-group-3-manual-passthrough"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#control-group-3-manual-passthrough"}},[e._v("#")]),e._v(" Control Group #3 (Manual Passthrough)")]),e._v(" "),o("ul",[o("li",[e._v("0: RC roll")]),e._v(" "),o("li",[e._v("1: RC pitch")]),e._v(" "),o("li",[e._v("2: RC yaw")]),e._v(" "),o("li",[e._v("3: RC throttle")]),e._v(" "),o("li",[e._v("4: RC mode switch (Passthrough of RC channel mapped by "),o("RouterLink",{attrs:{to:"/en/advanced_config/parameter_reference.html#RC_MAP_FLAPS"}},[e._v("RC_MAP_FLAPS")]),e._v(")")],1),e._v(" "),o("li",[e._v("5: RC aux1 (Passthrough of RC channel mapped by "),o("RouterLink",{attrs:{to:"/en/advanced_config/parameter_reference.html#RC_MAP_AUX1"}},[e._v("RC_MAP_AUX1")]),e._v(")")],1),e._v(" "),o("li",[e._v("6: RC aux2 (Passthrough of RC channel mapped by "),o("RouterLink",{attrs:{to:"/en/advanced_config/parameter_reference.html#RC_MAP_AUX2"}},[e._v("RC_MAP_AUX2")]),e._v(")")],1),e._v(" "),o("li",[e._v("7: RC aux3 (Passthrough of RC channel mapped by "),o("RouterLink",{attrs:{to:"/en/advanced_config/parameter_reference.html#RC_MAP_AUX3"}},[e._v("RC_MAP_AUX3")]),e._v(")")],1)]),e._v(" "),o("div",{staticClass:"custom-block note"},[o("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),o("p",[e._v("This group is only used to define mapping of RC inputs to specific outputs during "),o("em",[e._v("normal operation")]),e._v(" (see "),o("a",{attrs:{href:"https://github.com/PX4/PX4-Autopilot/blob/master/ROMFS/px4fmu_common/mixers/quad_x.main.mix#L7",target:"_blank",rel:"noopener noreferrer"}},[e._v("quad_x.main.mix"),o("OutboundLink")],1),e._v(" for an example of AUX2 being scaled in a mixer).\nIn the event of manual IO failsafe override (if the PX4FMU stops communicating with the PX4IO board) only the mapping/mixing defined by control group 0 inputs for roll, pitch, yaw and throttle are used (other mappings are ignored).")])]),e._v(" "),o("p",[o("a",{attrs:{id:"control_group_6"}})]),e._v(" "),o("h3",{attrs:{id:"control-group-6-first-payload"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#control-group-6-first-payload"}},[e._v("#")]),e._v(" Control Group #6 (First Payload)")]),e._v(" "),o("ul",[o("li",[e._v("0: function 0")]),e._v(" "),o("li",[e._v("1: function 1")]),e._v(" "),o("li",[e._v("2: function 2")]),e._v(" "),o("li",[e._v("3: function 3")]),e._v(" "),o("li",[e._v("4: function 4")]),e._v(" "),o("li",[e._v("5: function 5")]),e._v(" "),o("li",[e._v("6: function 6")]),e._v(" "),o("li",[e._v("7: function 7")])]),e._v(" "),o("h2",{attrs:{id:"virtual-control-groups"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#virtual-control-groups"}},[e._v("#")]),e._v(" Virtual Control Groups")]),e._v(" "),o("div",{staticClass:"custom-block warning"},[o("p",{staticClass:"custom-block-title"},[e._v("WARNING")]),e._v(" "),o("p",[o("em",[e._v("Virtual Control Group")]),e._v('s are only relevant to developers creating VTOL code.\nThey should not be used in mixers, and are provided only for "completeness".')])]),e._v(" "),o("p",[e._v("These groups are NOT mixer inputs, but serve as meta-channels to feed fixed wing and multicopter controller outputs into the VTOL governor module.")]),e._v(" "),o("h3",{attrs:{id:"control-group-4-flight-control-mc-virtual"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#control-group-4-flight-control-mc-virtual"}},[e._v("#")]),e._v(" Control Group #4 (Flight Control MC VIRTUAL)")]),e._v(" "),o("ul",[o("li",[e._v("0: roll ALT (-1..1)")]),e._v(" "),o("li",[e._v("1: pitch ALT (-1..1)")]),e._v(" "),o("li",[e._v("2: yaw ALT (-1..1)")]),e._v(" "),o("li",[e._v("3: throttle ALT (0..1 normal range, -1..1 for variable pitch / thrust reversers)")]),e._v(" "),o("li",[e._v("4: reserved / aux0")]),e._v(" "),o("li",[e._v("5: reserved / aux1")]),e._v(" "),o("li",[e._v("6: reserved / aux2")]),e._v(" "),o("li",[e._v("7: reserved / aux3")])]),e._v(" "),o("h3",{attrs:{id:"control-group-5-flight-control-fw-virtual"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#control-group-5-flight-control-fw-virtual"}},[e._v("#")]),e._v(" Control Group #5 (Flight Control FW VIRTUAL)")]),e._v(" "),o("ul",[o("li",[e._v("0: roll ALT (-1..1)")]),e._v(" "),o("li",[e._v("1: pitch ALT (-1..1)")]),e._v(" "),o("li",[e._v("2: yaw ALT (-1..1)")]),e._v(" "),o("li",[e._v("3: throttle ALT (0..1 normal range, -1..1 for variable pitch / thrust reversers)")]),e._v(" "),o("li",[e._v("4: reserved / aux0")]),e._v(" "),o("li",[e._v("5: reserved / aux1")]),e._v(" "),o("li",[e._v("6: reserved / aux2")]),e._v(" "),o("li",[e._v("7: reserved / aux3")])]),e._v(" "),o("h2",{attrs:{id:"output-groups-mapping"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#output-groups-mapping"}},[e._v("#")]),e._v(" Output Groups/Mapping")]),e._v(" "),o("p",[e._v("An output group is one physical bus (e.g. FMU PWM outputs, IO PWM outputs, UAVCAN etc.) that has N (usually 8) normalized (-1..+1) command ports that can be mapped and scaled through the mixer.")]),e._v(" "),o("p",[e._v("The mixer file does not explicitly define the actual "),o("em",[e._v("output group")]),e._v(" (physical bus) where the outputs are applied.\nInstead, the purpose of the mixer (e.g. to control MAIN or AUX outputs) is inferred from the mixer "),o("a",{attrs:{href:"#mixer_file_names"}},[e._v("filename")]),e._v(", and mapped to the appropriate physical bus in the system "),o("RouterLink",{attrs:{to:"/en/concept/system_startup.html"}},[e._v("startup scripts")]),e._v(" (and in particular in "),o("a",{attrs:{href:"https://github.com/PX4/PX4-Autopilot/blob/master/ROMFS/px4fmu_common/init.d/rc.interface",target:"_blank",rel:"noopener noreferrer"}},[e._v("rc.interface"),o("OutboundLink")],1),e._v(").")],1),e._v(" "),o("div",{staticClass:"custom-block note"},[o("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),o("p",[e._v("This approach is needed because the physical bus used for MAIN outputs is not always the same; it depends on whether or not the flight controller has an IO Board (see "),o("RouterLink",{attrs:{to:"/en/hardware/reference_design.html#mainio-function-breakdown"}},[e._v("PX4 Reference Flight Controller Design > Main/IO Function Breakdown")]),e._v(') or uses UAVCAN for motor control.\nThe startup scripts load the mixer files into the appropriate device driver for the board, using the abstraction of a "device".\nThe main mixer is loaded into device '),o("code",[e._v("/dev/uavcan/esc")]),e._v(" (uavcan) if UAVCAN is enabled, and otherwise "),o("code",[e._v("/dev/pwm_output0")]),e._v(" (this device is mapped to the IO driver on controllers with an I/O board, and the FMU driver on boards that don't).\nThe aux mixer file is loaded into device "),o("code",[e._v("/dev/pwm_output1")]),e._v(", which maps to the FMU driver on Pixhawk controllers that have an I/O board.")],1)]),e._v(" "),o("p",[e._v("Since there are multiple control groups (like flight controls, payload, etc.) and multiple output groups (busses), one control group can send commands to multiple output groups.")]),e._v(" "),o("p",[o("img",{attrs:{src:r(600),alt:"Mixer Input/Output Mapping"}})]),e._v(" "),o("div",{staticClass:"custom-block note"},[o("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),o("p",[e._v("In practice, the startup scripts only load mixers into a single device (output group).\nThis is a configuration rather than technical limitation; you could load the main mixer into multiple drivers and have, for example, the same signal on both UAVCAN and the main pins.")])]),e._v(" "),o("h2",{attrs:{id:"px4-mixer-definitions"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#px4-mixer-definitions"}},[e._v("#")]),e._v(" PX4 Mixer Definitions")]),e._v(" "),o("p",[e._v("Mixers are defined in plain-text files using the "),o("a",{attrs:{href:"#mixer_syntax"}},[e._v("syntax")]),e._v(" below.")]),e._v(" "),o("p",[e._v("Files for pre-defined airframes can be found in "),o("a",{attrs:{href:"https://github.com/PX4/PX4-Autopilot/tree/master/ROMFS/px4fmu_common/mixers",target:"_blank",rel:"noopener noreferrer"}},[e._v("ROMFS/px4fmu_common/mixers"),o("OutboundLink")],1),e._v(".\nThese can be used as a basis for customisation, or for general testing purposes.")]),e._v(" "),o("p",[o("a",{attrs:{id:"mixer_file_names"}})]),e._v(" "),o("h3",{attrs:{id:"mixer-file-names"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#mixer-file-names"}},[e._v("#")]),e._v(" Mixer File Names")]),e._v(" "),o("p",[e._v("A mixer file must be named "),o("strong",[e._v("XXXX."),o("em",[e._v("main")]),e._v(".mix")]),e._v(" if it is responsible for the mixing of MAIN outputs or "),o("strong",[e._v("XXXX."),o("em",[e._v("aux")]),e._v(".mix")]),e._v(" if it mixes AUX outputs.")]),e._v(" "),o("p",[o("a",{attrs:{id:"loading_mixer"}})]),e._v(" "),o("h3",{attrs:{id:"mixer-loading"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#mixer-loading"}},[e._v("#")]),e._v(" Mixer Loading")]),e._v(" "),o("p",[e._v("The default set of mixer files (in PX4 firmware) are defined in "),o("a",{attrs:{href:"https://github.com/PX4/PX4-Autopilot/blob/master/ROMFS/px4fmu_common/init.d/airframes/",target:"_blank",rel:"noopener noreferrer"}},[e._v("px4fmu_common/init.d/airframes/"),o("OutboundLink")],1),e._v(".\nThese can be overridden by mixer files with the same name in the SD card directory "),o("strong",[e._v("/etc/mixers/")]),e._v(" (SD card mixer files are loaded by preference).")]),e._v(" "),o("p",[e._v("PX4 loads mixer files named "),o("strong",[e._v("XXXX."),o("em",[e._v("main")]),e._v(".mix")]),e._v(" onto the MAIN outputs and "),o("strong",[e._v("YYYY."),o("em",[e._v("aux")]),e._v(".mix")]),e._v(" onto the AUX outputs, where the prefixes depend on the airframe and airframe configuration.\nCommonly the MAIN and AUX outputs correspond to MAIN and AUX PWM outputs, but these may be loaded into a UAVCAN (or other) bus when that is enabled.")]),e._v(" "),o("p",[e._v("The MAIN mixer filename (prefix "),o("code",[e._v("XXXX")]),e._v(") is set in the airframe configuration using "),o("code",[e._v("set MIXER XXXX")]),e._v(" (e.g. "),o("a",{attrs:{href:"https://github.com/PX4/PX4-Autopilot/blob/master/ROMFS/px4fmu_common/init.d/airframes/10015_tbs_discovery",target:"_blank",rel:"noopener noreferrer"}},[e._v("airframes/10015_tbs_discovery"),o("OutboundLink")],1),e._v(" calls "),o("code",[e._v("set MIXER quad_w")]),e._v(" to load the main mixer file "),o("strong",[e._v("quad_w."),o("em",[e._v("main")]),e._v(".mix")]),e._v(").")]),e._v(" "),o("p",[e._v("The AUX mixer filename (prefix "),o("code",[e._v("YYYY")]),e._v(" above) depends on airframe settings and/or defaults:")]),e._v(" "),o("ul",[o("li",[o("code",[e._v("MIXER_AUX")]),e._v(" can be used to "),o("em",[e._v("explicitly")]),e._v(" set which AUX file is loaded (e.g. in the aiframe configuration, "),o("code",[e._v("set MIXER_AUX vtol_AAERT")]),e._v(" will load "),o("code",[e._v("vtol_AAERT.aux.mix")]),e._v(").")]),e._v(" "),o("li",[e._v("Multicopter and Fixed-Wing airframes load "),o("a",{attrs:{href:"https://github.com/PX4/PX4-Autopilot/blob/master/ROMFS/px4fmu_common/mixers/pass.aux.mix",target:"_blank",rel:"noopener noreferrer"}},[e._v("pass.aux.mix"),o("OutboundLink")],1),e._v(" by default (i.e if not set using "),o("code",[e._v("MIXER_AUX")]),e._v(")."),o("div",{staticClass:"custom-block tip"},[o("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),o("p",[o("code",[e._v("pass.aux.mix")]),e._v(" is the "),o("em",[e._v("RC passthrough mixer")]),e._v(", which passes the values of 4 user-defined RC channels (set using the "),o("RouterLink",{attrs:{to:"/en/advanced_config/parameter_reference.html#RC_MAP_AUX1"}},[e._v("RC_MAP_AUXx/RC_MAP_FLAPS")]),e._v(" parameters) to the first four outputs on the AUX output.")],1)])]),e._v(" "),o("li",[e._v("VTOL frames load the AUX file specified using "),o("code",[e._v("MIXER_AUX")]),e._v(" if set, or the value specified by "),o("code",[e._v("MIXER")]),e._v(" if not.")]),e._v(" "),o("li",[e._v("Frames with gimbal control enabled (and output mode set to AUX) will "),o("em",[e._v("override")]),e._v(" the airframe-specific MIXER_AUX setting and load "),o("code",[e._v("mount.aux.mix")]),e._v(" on the AUX outputs.")])]),e._v(" "),o("div",{staticClass:"custom-block note"},[o("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),o("p",[e._v("Mixer file loading is implemented in "),o("a",{attrs:{href:"https://github.com/PX4/PX4-Autopilot/blob/master/ROMFS/px4fmu_common/init.d/rc.interface",target:"_blank",rel:"noopener noreferrer"}},[e._v("ROMFS/px4fmu_common/init.d/rc.interface"),o("OutboundLink")],1),e._v(".")])]),e._v(" "),o("p",[o("a",{attrs:{id:"loading_custom_mixer"}})]),e._v(" "),o("h3",{attrs:{id:"loading-a-custom-mixer"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#loading-a-custom-mixer"}},[e._v("#")]),e._v(" Loading a Custom Mixer")]),e._v(" "),o("p",[e._v("PX4 loads appropriately named mixer files from the SD card directory "),o("strong",[e._v("/etc/mixers/")]),e._v(", by preference, and then the version in Firmware.")]),e._v(" "),o("p",[e._v('To load a custom mixer, you should give it the same name as a "normal" mixer file (that is going to be loaded by your airframe) and put it in the '),o("strong",[e._v("etc/mixers")]),e._v(" directory on your flight controller's SD card.")]),e._v(" "),o("p",[e._v("Most commonly you will override/replace the "),o("strong",[e._v("AUX")]),e._v(" mixer file for your current airframe (which may be the RC passthrough mixer - "),o("a",{attrs:{href:"https://github.com/PX4/PX4-Autopilot/blob/master/ROMFS/px4fmu_common/mixers/pass.aux.mix",target:"_blank",rel:"noopener noreferrer"}},[e._v("pass.aux.mix"),o("OutboundLink")],1),e._v(").\nSee above for more information on "),o("a",{attrs:{href:"#loading_mixer"}},[e._v("mixer loading")]),e._v(".")]),e._v(" "),o("div",{staticClass:"custom-block tip"},[o("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),o("p",[e._v("You can also "),o("em",[e._v("manually")]),e._v(" load a mixer at runtime using the "),o("RouterLink",{attrs:{to:"/en/modules/modules_command.html#mixer"}},[e._v("mixer load")]),e._v(" command  (thereby avoiding the need for a reboot).\nFor example, to load a mixer "),o("strong",[e._v("/etc/mixers/test_mixer.mix")]),e._v(" onto the MAIN PWM outputs, you could enter the following command in a "),o("RouterLink",{attrs:{to:"/en/debug/consoles.html"}},[e._v("console")]),e._v(":")],1),e._v(" "),o("div",{staticClass:"language- extra-class"},[o("pre",{pre:!0,attrs:{class:"language-text"}},[o("code",[e._v("mixer load /dev/pwm_output0 /fs/microsd/etc/mixers/test_mixer.mix\n")])])])]),e._v(" "),o("p",[o("a",{attrs:{id:"mixer_syntax"}})]),e._v(" "),o("h3",{attrs:{id:"syntax"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#syntax"}},[e._v("#")]),e._v(" Syntax")]),e._v(" "),o("p",[e._v("Mixer files are text files that define one or more mixer definitions: mappings between one or more inputs and one or more outputs.")]),e._v(" "),o("p",[e._v("There are four types of mixers definitions: "),o("a",{attrs:{href:"#multirotor_mixer"}},[e._v("multirotor mixer")]),e._v(", "),o("a",{attrs:{href:"#helicopter_mixer"}},[e._v("helicopter mixer")]),e._v(", "),o("a",{attrs:{href:"#summing_mixer"}},[e._v("summing mixer")]),e._v(", and "),o("a",{attrs:{href:"#null_mixer"}},[e._v("null mixer")]),e._v(".")]),e._v(" "),o("ul",[o("li",[o("a",{attrs:{href:"#multirotor_mixer"}},[e._v("Multirotor mixer")]),e._v(" - Defines outputs for 4, 6, or 8 rotor vehicles with + or X geometry.")]),e._v(" "),o("li",[o("a",{attrs:{href:"#helicopter_mixer"}},[e._v("Helicopter mixer")]),e._v(" - Defines outputs for helicopter swash-plate servos and main motor ESCs\n(the tail-rotor is a separate "),o("a",{attrs:{href:"#summing_mixer"}},[e._v("summing mixer")]),e._v(".)")]),e._v(" "),o("li",[o("a",{attrs:{href:"#summing_mixer"}},[e._v("Summing mixer")]),e._v(" - Combines zero or more control inputs into a single actuator output.\nInputs are scaled, and the mixing function sums the result before applying an output scaler.")]),e._v(" "),o("li",[o("a",{attrs:{href:"#null_mixer"}},[e._v("Null mixer")]),e._v(" - Generates a single actuator output that has zero output (when not in failsafe mode).")])]),e._v(" "),o("div",{staticClass:"custom-block tip"},[o("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),o("p",[e._v("Use "),o("em",[e._v("multirotor")]),e._v(" and "),o("em",[e._v("helicopter mixers")]),e._v(" for the respective types, the "),o("em",[e._v("summing mixer")]),e._v(" for servos and actuator controls, and the "),o("em",[e._v("null mixer")]),e._v(" for creating outputs that must be zero during normal use (e.g. a parachute has 0 normally, but might have a particular value during failsafe).\nA "),o("a",{attrs:{href:"#vtol_mixer"}},[e._v("VTOL Mixer")]),e._v(" combines the other mixer types.")])]),e._v(" "),o("p",[e._v("The number of outputs generated by each mixer depends on the mixer type and configuration.\nFor example, the multirotor mixer generates 4, 6, or 8 outputs depending on the geometry, while a summing mixer or null mixer generate just one output.")]),e._v(" "),o("p",[e._v('You can specify more than one mixer in each file.\nThe output order (allocation of mixers to actuators) is specific to the device reading the mixer definition; for a PWM device the output order matches the order of declaration.\nFor example, if you define a multi-rotor mixer for a quad geometry, followed by a null mixer, followed by two summing mixers then this would allocate the first 4 outputs to the quad, an "empty" output, and the next two outputs.')]),e._v(" "),o("p",[e._v("Each mixer definition begin with a line of the form:")]),e._v(" "),o("div",{staticClass:"language- extra-class"},[o("pre",{pre:!0,attrs:{class:"language-text"}},[o("code",[e._v("<tag>: <mixer arguments>\n")])])]),o("p",[e._v("The "),o("code",[e._v("tag")]),e._v(" selects the mixer type (see links for detail on each type):")]),e._v(" "),o("ul",[o("li",[o("code",[e._v("R")]),e._v(": "),o("a",{attrs:{href:"#multirotor_mixer"}},[e._v("Multirotor mixer")])]),e._v(" "),o("li",[o("code",[e._v("H")]),e._v(": "),o("a",{attrs:{href:"#helicopter_mixer"}},[e._v("Helicopter mixer")])]),e._v(" "),o("li",[o("code",[e._v("M")]),e._v(": "),o("a",{attrs:{href:"#summing_mixer"}},[e._v("Summing mixer")])]),e._v(" "),o("li",[o("code",[e._v("Z")]),e._v(": "),o("a",{attrs:{href:"#null_mixer"}},[e._v("Null mixer")])])]),e._v(" "),o("p",[e._v("Some mixers definitions consist of a number of tags (e.g. "),o("code",[e._v("O")]),e._v(" and "),o("code",[e._v("S")]),e._v(") that follow the mixer-type tag above.")]),e._v(" "),o("div",{staticClass:"custom-block note"},[o("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),o("p",[e._v("Any line that does not begin with a single capital letter followed by a colon may be ignored (so explanatory text can be freely mixed with the definitions).")])]),e._v(" "),o("p",[o("a",{attrs:{id:"summing_mixer"}})]),e._v(" "),o("h4",{attrs:{id:"summing-mixer"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#summing-mixer"}},[e._v("#")]),e._v(" Summing Mixer")]),e._v(" "),o("p",[e._v("Summing mixers are used for actuator and servo control.")]),e._v(" "),o("p",[e._v("A summing (simple) mixer combines zero or more control inputs into a single actuator output.\nInputs are scaled, and the mixing function sums the result before applying an output scaler.\nA minimal actuator traversal time limit can also be specified in the output scaler (inverse of a slew rate).")]),e._v(" "),o("p",[e._v("A simple mixer definition begins with:")]),e._v(" "),o("div",{staticClass:"language- extra-class"},[o("pre",{pre:!0,attrs:{class:"language-text"}},[o("code",[e._v("M: <control count>\nO: <-ve scale> <+ve scale> <offset> <lower limit> <upper limit> <traversal time>\n")])])]),o("p",[e._v("If "),o("code",[e._v("<control count>")]),e._v(" is zero, the sum is effectively zero and the mixer will output a fixed value that is "),o("code",[e._v("<offset>")]),e._v(" constrained by "),o("code",[e._v("<lower limit>")]),e._v(" and "),o("code",[e._v("<upper limit>")]),e._v(".")]),e._v(" "),o("p",[e._v("The second line defines the output scaler with scaler parameters as discussed above.\nWhile the calculations are performed as floating-point operations, the values stored in the definition file are scaled by a factor of 10000; i.e. an offset of -0.5 is encoded as -5000.\nThe "),o("code",[e._v("<traversal time>")]),e._v(" (optional) on the output scaler is intended for actuators that may be damaged if they move too fast — like the tilting actuators on a tiltrotor VTOL vehicle.\nIt can be used to limit the rate of change of an actuator (if this is not specified then no rate limit is applied).\nFor example, a "),o("code",[e._v("<traversal time>")]),e._v(" value of 20000 will limit the rate of change of the actuator such that it takes at least 2 seconds from the "),o("code",[e._v("<lower limit>")]),e._v(" to the "),o("code",[e._v("<upper limit>")]),e._v(" and vice versa.")]),e._v(" "),o("div",{staticClass:"custom-block note"},[o("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),o("ul",[o("li",[e._v("The "),o("code",[e._v("<traversal time>")]),e._v(" should only be used if the hardware requires it!")]),e._v(" "),o("li",[e._v("Do not apply any limit on actuators controlling the attitude of a vehicle (such as servos for the aerodynamic surfaces), as this could easily lead to controller instability.")])])]),e._v(" "),o("p",[e._v("The definition continues with "),o("code",[e._v("<control count>")]),e._v(" entries describing the control\ninputs and their scaling, in the form:")]),e._v(" "),o("div",{staticClass:"language- extra-class"},[o("pre",{pre:!0,attrs:{class:"language-text"}},[o("code",[e._v("S: <group> <index> <-ve scale> <+ve scale> <offset> <lower limit> <upper limit>\n")])])]),o("div",{staticClass:"custom-block note"},[o("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),o("p",[e._v("The "),o("code",[e._v("S:")]),e._v(" lines must be below the "),o("code",[e._v("O:")]),e._v(" line.")])]),e._v(" "),o("div",{staticClass:"custom-block note"},[o("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),o("p",[e._v("Any mixer output that has a throttle input (an "),o("code",[e._v("S:")]),e._v("-line with "),o("code",[e._v("<group>=0")]),e._v(" and "),o("code",[e._v("<index>=3")]),e._v(") won't work in disarmed or prearmed state. For example, a servo that has four inputs (roll, pitch, yaw and throttle) won't move in disarmed state even with roll/pitch/yaw signals.")])]),e._v(" "),o("p",[e._v("The "),o("code",[e._v("<group>")]),e._v(" value identifies the control group from which the scaler will read, and the "),o("code",[e._v("<index>")]),e._v(" value an offset within that group.\nThese values are specific to the device reading the mixer definition.")]),e._v(" "),o("p",[e._v("When used to mix vehicle controls, mixer group zero is the vehicle attitude control group, and index values zero through three are normally roll, pitch, yaw and thrust respectively.")]),e._v(" "),o("p",[e._v("The remaining fields on the line configure the control scaler with parameters as discussed above.\nWhilst the calculations are performed as floating-point operations, the values stored in the definition file are scaled by a factor of 10000; i.e. an offset of -0.5 is encoded as -5000.")]),e._v(" "),o("p",[e._v("An example of a typical mixer file is explained "),o("RouterLink",{attrs:{to:"/en/dev_airframes/adding_a_new_frame.html#mixer-file"}},[e._v("here")]),e._v(".")],1),e._v(" "),o("p",[o("a",{attrs:{id:"null_mixer"}})]),e._v(" "),o("h4",{attrs:{id:"null-mixer"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#null-mixer"}},[e._v("#")]),e._v(" Null Mixer")]),e._v(" "),o("p",[e._v("A null mixer consumes no controls and generates a single actuator output with a value that is always zero.")]),e._v(" "),o("p",[e._v("Typically a null mixer is used as a placeholder in a collection of mixers in order to achieve a specific pattern of actuator outputs.\nIt may also be used to control the value of an output used for a failsafe device (the output is 0 in normal use; during failsafe the mixer is ignored and a failsafe value is used instead).")]),e._v(" "),o("p",[e._v("The null mixer definition has the form:")]),e._v(" "),o("div",{staticClass:"language- extra-class"},[o("pre",{pre:!0,attrs:{class:"language-text"}},[o("code",[e._v("Z:\n")])])]),o("p",[o("a",{attrs:{id:"multirotor_mixer"}})]),e._v(" "),o("h4",{attrs:{id:"multirotor-mixer"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#multirotor-mixer"}},[e._v("#")]),e._v(" Multirotor Mixer")]),e._v(" "),o("p",[e._v("The multirotor mixer combines four control inputs (roll, pitch, yaw, thrust) into a set of actuator outputs intended to drive motor speed controllers.")]),e._v(" "),o("p",[e._v("The mixer definition is a single line of the form:")]),e._v(" "),o("div",{staticClass:"language- extra-class"},[o("pre",{pre:!0,attrs:{class:"language-text"}},[o("code",[e._v("R: <geometry> <roll scale> <pitch scale> <yaw scale> <idlespeed>\n")])])]),o("p",[e._v("The supported geometries include:")]),e._v(" "),o("ul",[o("li",[e._v("4x - quadrotor in X configuration")]),e._v(" "),o("li",[e._v("4+ - quadrotor in + configuration")]),e._v(" "),o("li",[e._v("6x - hexacopter in X configuration")]),e._v(" "),o("li",[e._v("6+ - hexacopter in + configuration")]),e._v(" "),o("li",[e._v("8x - octocopter in X configuration")]),e._v(" "),o("li",[e._v("8+ - octocopter in + configuration")])]),e._v(" "),o("p",[e._v("Each of the roll, pitch and yaw scale values determine scaling of the roll, pitch and yaw controls relative to the thrust control.\nWhilst the calculations are performed as floating-point operations, the values stored in the definition file are scaled by a factor of 10000; i.e. an factor of 0.5 is encoded as 5000.")]),e._v(" "),o("p",[e._v("Roll, pitch and yaw inputs are expected to range from -1.0 to 1.0, whilst the thrust input ranges from 0.0 to 1.0.\nOutput for each actuator is in the range -1.0 to 1.0.")]),e._v(" "),o("p",[e._v("Idlespeed can range from 0.0 to 1.0.\nIdlespeed is relative to the maximum speed of motors and it is the speed at which the motors are commanded to rotate when all control inputs are zero.")]),e._v(" "),o("p",[e._v("In the case where an actuator saturates, all actuator values are rescaled so that the saturating actuator is limited to 1.0.")]),e._v(" "),o("p",[o("a",{attrs:{id:"helicopter_mixer"}})]),e._v(" "),o("h4",{attrs:{id:"helicopter-mixer"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#helicopter-mixer"}},[e._v("#")]),e._v(" Helicopter Mixer")]),e._v(" "),o("p",[e._v("The helicopter mixer combines three control inputs (roll, pitch, thrust) into four outputs (swash-plate servos and main motor ESC setting).\nThe first output of the helicopter mixer is the throttle setting for the main motor.\nThe subsequent outputs are the swash-plate servos.\nThe tail-rotor can be controlled by adding a simple mixer.")]),e._v(" "),o("p",[e._v("The thrust control input is used for both the main motor setting as well as the collective pitch for the swash-plate.\nIt uses a throttle-curve and a pitch-curve, both consisting of five points.")]),e._v(" "),o("div",{staticClass:"custom-block note"},[o("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),o("p",[e._v('The throttle- and pitch- curves map the "thrust" stick input position to a throttle value and a pitch value (separately).\nThis allows the flight characteristics to be tuned for different types of flying.\nAn explanation of how curves might be tuned can be found in '),o("a",{attrs:{href:"https://www.rchelicopterfun.com/rc-helicopter-radios.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("this guide"),o("OutboundLink")],1),e._v(" (search on "),o("em",[e._v("Programmable Throttle Curves")]),e._v(" and "),o("em",[e._v("Programmable Pitch Curves")]),e._v(").")])]),e._v(" "),o("p",[e._v("The mixer definition begins with:")]),e._v(" "),o("div",{staticClass:"language- extra-class"},[o("pre",{pre:!0,attrs:{class:"language-text"}},[o("code",[e._v("H: <number of swash-plate servos, either 3 or 4>\nT: <throttle setting at thrust: 0%> <25%> <50%> <75%> <100%>\nP: <collective pitch at thrust: 0%> <25%> <50%> <75%> <100%>\n")])])]),o("p",[o("code",[e._v("T:")]),e._v(" defines the points for the throttle-curve.\n"),o("code",[e._v("P:")]),e._v("  defines the points for the pitch-curve.\nBoth curves contain five points in the range between 0 and 10000.\nFor simple linear behavior, the five values for a curve should be "),o("code",[e._v("0 2500 5000 7500 10000")]),e._v(".")]),e._v(" "),o("p",[e._v("This is followed by lines for each of the swash-plate servos (either 3 or 4) in the following form:")]),e._v(" "),o("div",{staticClass:"language- extra-class"},[o("pre",{pre:!0,attrs:{class:"language-text"}},[o("code",[e._v("S: <angle> <arm length> <scale> <offset> <lower limit> <upper limit>\n")])])]),o("p",[e._v("The "),o("code",[e._v("<angle>")]),e._v(" is in degrees, with 0 degrees being in the direction of the nose.\nViewed from above, a positive angle is clock-wise.\nThe "),o("code",[e._v("<arm length>")]),e._v(" is a normalized length with 10000 being equal to 1.\nIf all servo-arms are the same length, the values should al be 10000.\nA bigger arm length reduces the amount of servo deflection and a shorter arm will increase the servo deflection.")]),e._v(" "),o("p",[e._v("The servo output is scaled by "),o("code",[e._v("<scale> / 10000")]),e._v(".\nAfter the scaling, the "),o("code",[e._v("<offset>")]),e._v(" is applied, which should be between -10000 and +10000.\nThe "),o("code",[e._v("<lower limit>")]),e._v(" and "),o("code",[e._v("<upper limit>")]),e._v(" should be -10000 and +10000 for full servo range.")]),e._v(" "),o("p",[e._v("The tail rotor can be controller by adding a "),o("a",{attrs:{href:"#summing_mixer"}},[e._v("summing mixer")]),e._v(":")]),e._v(" "),o("div",{staticClass:"language- extra-class"},[o("pre",{pre:!0,attrs:{class:"language-text"}},[o("code",[e._v("M: 1\nS: 0 2  10000  10000      0 -10000  10000\n")])])]),o("p",[e._v("By doing so, the tail rotor setting is directly mapped to the yaw command.\nThis works for both servo-controlled tail-rotors, as well as for tail rotors with a dedicated motor.")]),e._v(" "),o("p",[e._v("The "),o("a",{attrs:{href:"https://github.com/PX4/PX4-Autopilot/blob/master/ROMFS/px4fmu_common/mixers/blade130.main.mix",target:"_blank",rel:"noopener noreferrer"}},[e._v("blade 130 helicopter mixer"),o("OutboundLink")],1),e._v(" can be viewed as an example.")]),e._v(" "),o("div",{staticClass:"language- extra-class"},[o("pre",{pre:!0,attrs:{class:"language-text"}},[o("code",[e._v("H: 3\nT:      0   3000   6000   8000  10000\nP:    500   1500   2500   3500   4500\n# Swash plate servos:\nS:      0  10000  10000      0  -8000   8000\nS:    140  13054  10000      0  -8000   8000\nS:    220  13054  10000      0  -8000   8000\n\n# Tail servo:\nM: 1\nS: 0 2  10000  10000      0 -10000  10000\n")])])]),o("ul",[o("li",[e._v("The throttle-curve starts with a slightly steeper slope to reach 6000 (0.6) at 50% thrust.")]),e._v(" "),o("li",[e._v("It continues with a less steep slope to reach 10000 (1.0) at 100% thrust.")]),e._v(" "),o("li",[e._v("The pitch-curve is linear, but does not use the entire range.")]),e._v(" "),o("li",[e._v("At 0% throttle, the collective pitch setting is already at 500 (0.05).")]),e._v(" "),o("li",[e._v("At maximum throttle, the collective pitch is only 4500 (0.45).")]),e._v(" "),o("li",[e._v("Using higher values for this type of helicopter would stall the blades.")]),e._v(" "),o("li",[e._v("The swash-plate servos for this helicopter are located at angles of 0, 140 and 220 degrees.")]),e._v(" "),o("li",[e._v("The servo arm-lenghts are not equal.")]),e._v(" "),o("li",[e._v("The second and third servo have a longer arm, by a ratio of 1.3054 compared to the first servo.")]),e._v(" "),o("li",[e._v("The servos are limited at -8000 and 8000 because they are mechanically constrained.")])]),e._v(" "),o("p",[o("a",{attrs:{id:"vtol_mixer"}})]),e._v(" "),o("h4",{attrs:{id:"vtol-mixer"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#vtol-mixer"}},[e._v("#")]),e._v(" VTOL Mixer")]),e._v(" "),o("p",[e._v("VTOL systems use a "),o("a",{attrs:{href:"#multirotor_mixer"}},[e._v("multirotor mixer")]),e._v(" for the multirotor outputs, and "),o("a",{attrs:{href:"#summing_mixer"}},[e._v("summing mixers")]),e._v(" for the fixed-wing actuators (and the tilting servos in case of a tiltrotor VTOL).")]),e._v(" "),o("p",[e._v("The mixer system for a VTOL vehicle can be either combined into a single mixer, where all the actuators are connected to either the IO or the FMU port, or split into separate mixer files for IO and for AUX.\nIf separated, we recommend that all the multicopter motors are on one port, and all the servos and the fixed-wing motor on the other.")]),e._v(" "),o("div",{staticClass:"custom-block note"},[o("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),o("p",[e._v("The FMU output can only be used for multirotor motors starting from PX4 v1.11.\nTo use the FMU output set "),o("RouterLink",{attrs:{to:"/en/advanced_config/parameter_reference.html#VT_MC_ON_FMU"}},[e._v("VT_MC_ON_FMU=1")]),e._v(" (otherwise they are not switched off when in fixed-wing flight mode).")],1)])])}),[],!1,null,null,null);t.default=a.exports},599:function(e,t,r){e.exports=r.p+"assets/img/mermaid_mixer_control_pipeline.eb378e93.png"},600:function(e,t){e.exports="data:image/png;base64,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"}}]);