Skip to content

Integral Errors

The Mellinger controller uses integral terms to reject steady-state errors. Because every controller in this package is a pure function, integral state cannot be stored inside the function; it is an explicit return value that you pass back on the next call.

Initialisation

Pass ctrl_errors=None on the first call. The controller initialises the integral error to zero internally.

import numpy as np
from drone_controllers import parametrize
from drone_controllers.mellinger import state2attitude

ctrl = parametrize(state2attitude, "cf2x_L250")
pos  = np.zeros(3)
quat = np.array([0., 0., 0., 1.])
vel  = np.zeros(3)
cmd  = np.zeros(13)

# First call — no integral history.
rpyt, int_pos_err = ctrl(pos, quat, vel, cmd, ctrl_errors=None)

Carrying errors across timesteps

Wrap the returned error in a tuple and pass it as ctrl_errors on the next call:

import numpy as np
from drone_controllers import parametrize
from drone_controllers.mellinger import state2attitude

ctrl = parametrize(state2attitude, "cf2x_L250")
pos  = np.zeros(3)
quat = np.array([0., 0., 0., 1.])
vel  = np.zeros(3)
cmd  = np.zeros(13)
cmd[0] = 1.0  # 1 m setpoint error in x

ctrl_errors = None
for _ in range(10):
    rpyt, int_pos_err = ctrl(pos, quat, vel, cmd, ctrl_errors=ctrl_errors)
    ctrl_errors = (int_pos_err,)  # carry forward

# After 10 steps at 100 Hz, integral error ≈ 10 × 0.01 = 0.1 m

Both stages have integral errors

state2attitude tracks position error; attitude2force_torque tracks angular velocity error. Manage them independently:

import numpy as np
from drone_controllers import parametrize
from drone_controllers.mellinger import attitude2force_torque, state2attitude

state_ctrl = parametrize(state2attitude, "cf2x_L250")
att_ctrl   = parametrize(attitude2force_torque, "cf2x_L250")

pos     = np.zeros(3)
quat    = np.array([0., 0., 0., 1.])
vel     = np.zeros(3)
ang_vel = np.zeros(3)
cmd     = np.zeros(13)

state_errs = None
att_errs   = None

for _ in range(5):
    rpyt, int_pos_err = state_ctrl(pos, quat, vel, cmd, ctrl_errors=state_errs)
    state_errs = (int_pos_err,)

    force, torque, r_int_err = att_ctrl(quat, ang_vel, rpyt, ctrl_errors=att_errs)
    att_errs = (r_int_err,)