Defining Custom Mixers in C++
Executive Summary
For standard frames (X, H), ArduPilot automatically calculates the motor mixer based on the frame angle (e.g., 45 degrees). However, for asymmetric frames, V-Tails, or custom actuator layouts, you must define the mixer manually. This is done using the add_motor or add_motor_raw primitives in the C++ source code.
Theory & Concepts
1. Torque vs. Thrust
Every motor produces two forces:
- Thrust: Pushes the drone UP (Vertical force).
- Torque: Tries to rotate the drone body in the opposite direction of the propeller (Newton's 3rd Law).
- Yaw Logic: To Yaw Right, the drone slows down the CW-spinning motors and speeds up the CCW-spinning motors. The net thrust stays the same, but the net torque changes, rotating the drone.
2. Coupling and Cross-talk
A "Bad" custom mixer causes Coupling.
- Scenario: You command a Roll. Because your motor factors are slightly wrong, the drone rolls and pitches forward.
- Fix: High-fidelity custom mixers (like the Deadcat) must calculate factors based on the exact X/Y distance from the CoG, ensuring the Pitch and Roll vectors are mathematically orthogonal.
The Primitive: add_motor_raw
This is the lowest-level way to define a motor. You explicitly tell the mixer how much each motor contributes to Roll, Pitch, and Yaw.
Function Signature
void add_motor_raw(int8_t motor_num, float roll_fac, float pitch_fac, float yaw_fac, uint8_t testing_order);
Understanding the Factors (-1.0 to 1.0)
- Roll Factor:
-1.0: Motor is on the Right. Spinning it up rolls the vehicle Left.+1.0: Motor is on the Left. Spinning it up rolls the vehicle Right.- Note: Yes, it seems inverted. A positive roll command (Right) requires the Left motors to spin up.
- Pitch Factor:
-1.0: Motor is in Front. Spinning it up pitches the nose Up.+1.0: Motor is in Back. Spinning it up pitches the nose Down.
- Yaw Factor:
-1.0: Motor torque spins the vehicle CW. To Yaw Right (CW), we spin this motor.+1.0: Motor torque spins the vehicle CCW.
The Helper: add_motor (Angle-Based)
If your frame is symmetrical but just has weird angles (e.g., a Deadcat), you can let ArduPilot calculate the Sin/Cos for you.
Function Signature
void add_motor(int8_t motor_num, float angle_degrees, float yaw_factor, uint8_t testing_order);
- Angle: 0 = Front. 90 = Right. 180 = Back. -90 = Left.
Case Study: The V-Tail
A V-Tail quadcopter is complex because the rear motors contribute to both Pitch and Yaw, but not much Roll.
- Code Path: See
MOTOR_FRAME_TYPE_VTAIL. - Logic:
- Front Motors: High Roll Factor, Zero Yaw Factor.
- Rear Motors: Low Roll Factor, High Pitch Factor, High Yaw Factor.
Source Code Reference
- Function Definitions:
AP_MotorsMatrix.cpp