/**************************************************************************** * * Copyright (c) 2019 PX4 Development Team. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name PX4 nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /** * @file ControlAllocation.cpp * * Interface for Control Allocation Algorithms * * @author Julien Lecoeur */ #include "ControlAllocation.hpp" ControlAllocation::ControlAllocation() { _control_allocation_scale.setAll(1.f); _actuator_min.setAll(0.f); _actuator_max.setAll(1.f); } void ControlAllocation::setEffectivenessMatrix( const matrix::Matrix &effectiveness, const ActuatorVector &actuator_trim, const ActuatorVector &linearization_point, int num_actuators, bool update_normalization_scale) { _effectiveness = effectiveness; ActuatorVector linearization_point_clipped = linearization_point; clipActuatorSetpoint(linearization_point_clipped); _actuator_trim = actuator_trim + linearization_point_clipped; clipActuatorSetpoint(_actuator_trim); _num_actuators = num_actuators; _control_trim = _effectiveness * linearization_point_clipped; } void ControlAllocation::setActuatorSetpoint( const matrix::Vector &actuator_sp) { // Set actuator setpoint _actuator_sp = actuator_sp; // Clip clipActuatorSetpoint(_actuator_sp); } void ControlAllocation::clipActuatorSetpoint(matrix::Vector &actuator) const { for (int i = 0; i < _num_actuators; i++) { if (_actuator_max(i) < _actuator_min(i)) { actuator(i) = _actuator_trim(i); } else if (actuator(i) < _actuator_min(i)) { actuator(i) = _actuator_min(i); } else if (actuator(i) > _actuator_max(i)) { actuator(i) = _actuator_max(i); } } } matrix::Vector ControlAllocation::normalizeActuatorSetpoint(const matrix::Vector &actuator) const { matrix::Vector actuator_normalized; for (int i = 0; i < _num_actuators; i++) { if (_actuator_min(i) < _actuator_max(i)) { actuator_normalized(i) = (actuator(i) - _actuator_min(i)) / (_actuator_max(i) - _actuator_min(i)); } else { actuator_normalized(i) = (_actuator_trim(i) - _actuator_min(i)) / (_actuator_max(i) - _actuator_min(i)); } } return actuator_normalized; } void ControlAllocation::applySlewRateLimit(float dt) { for (int i = 0; i < _num_actuators; i++) { if (_actuator_slew_rate_limit(i) > FLT_EPSILON) { float delta_sp_max = dt * (_actuator_max(i) - _actuator_min(i)) / _actuator_slew_rate_limit(i); float delta_sp = _actuator_sp(i) - _prev_actuator_sp(i); if (delta_sp > delta_sp_max) { _actuator_sp(i) = _prev_actuator_sp(i) + delta_sp_max; } else if (delta_sp < -delta_sp_max) { _actuator_sp(i) = _prev_actuator_sp(i) - delta_sp_max; } } } }