Source code for udaan.control.quadrotor.propeller_allocation
"""Direct propeller force allocation controller."""
import numpy as np
from ...control import Controller
from ...core.defaults import DEFAULT_ARM_LENGTH, DEFAULT_FORCE_CONSTANT, DEFAULT_TORQUE_CONSTANT
from .geometric_attitude import GeometricAttitudeController
from .position_pd import PositionPDController
[docs]
class DirectPropellerForceController(Controller):
[docs]
def __init__(self, **kwargs):
super().__init__()
self.compute_alloc_matrix()
self._pos_controller = PositionPDController(**kwargs)
self._att_controller = GeometricAttitudeController(**kwargs)
[docs]
def compute_alloc_matrix(self):
r"""Compute propeller force allocation matrix.
Propeller layout::
(1)CW CCW(0) [-1] y^
\_^_/ |
|_| |
/ \ |
(2)CCW CW(3) z.------> x
"""
self._force_constant = DEFAULT_FORCE_CONSTANT
self._torque_constant = DEFAULT_TORQUE_CONSTANT
self._force2torque_const = self._torque_constant / self._force_constant
l = DEFAULT_ARM_LENGTH
ang = [np.pi / 4.0, 3 * np.pi / 4.0, 5 * np.pi / 4.0, 7 * np.pi / 4.0]
d = [-1.0, 1.0, -1.0, 1.0]
self._allocation_matrix = np.zeros((4, 4))
for i in range(4):
self._allocation_matrix[0, i] = 1.0
self._allocation_matrix[1, i] = l * np.sin(ang[i])
self._allocation_matrix[2, i] = -l * np.cos(ang[i])
self._allocation_matrix[3, i] = self._force2torque_const * d[i]
self._allocation_inv = np.linalg.pinv(self._allocation_matrix)
[docs]
def compute(self, *args):
"""Compute propeller forces given current state.
Returns:
ndarray: four propeller forces in N
"""
t = args[0]
thrust_force = self._pos_controller.compute(t, (args[1][0], args[1][1]))
f, M = self._att_controller.compute(t, (args[1][2], args[1][3]), thrust_force)
return self._allocation_inv @ np.append(f, M)