mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-05-31 18:47:21 +08:00
control_allocator: implement trim + slew rate limits configuration
This commit is contained in:
@@ -44,6 +44,7 @@ set(msg_files
|
|||||||
actuator_motors.msg
|
actuator_motors.msg
|
||||||
actuator_outputs.msg
|
actuator_outputs.msg
|
||||||
actuator_servos.msg
|
actuator_servos.msg
|
||||||
|
actuator_servos_trim.msg
|
||||||
actuator_test.msg
|
actuator_test.msg
|
||||||
adc_report.msg
|
adc_report.msg
|
||||||
airspeed.msg
|
airspeed.msg
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Servo trims, added as offset to servo outputs
|
||||||
|
uint64 timestamp # time since system start (microseconds)
|
||||||
|
|
||||||
|
uint8 NUM_CONTROLS = 8
|
||||||
|
float32[8] trim # range: [-1, 1]
|
||||||
@@ -81,6 +81,17 @@ void ActuatorTest::update(int num_outputs, float thrust_curve)
|
|||||||
FunctionMotors::updateValues(motors.reversible_flags >> motor_idx, thrust_curve, &value, 1);
|
FunctionMotors::updateValues(motors.reversible_flags >> motor_idx, thrust_curve, &value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle servos: add trim
|
||||||
|
if (actuator_test.function >= (int)OutputFunction::Servo1 && actuator_test.function <= (int)OutputFunction::ServoMax) {
|
||||||
|
actuator_servos_trim_s trim{};
|
||||||
|
_actuator_servos_trim_sub.copy(&trim);
|
||||||
|
int idx = actuator_test.function - (int)OutputFunction::Servo1;
|
||||||
|
|
||||||
|
if (idx < actuator_servos_trim_s::NUM_CONTROLS) {
|
||||||
|
value += trim.trim[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_current_outputs[i] = value;
|
_current_outputs[i] = value;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
#include <drivers/drv_pwm_output.h>
|
#include <drivers/drv_pwm_output.h>
|
||||||
#include <uORB/topics/actuator_test.h>
|
#include <uORB/topics/actuator_test.h>
|
||||||
#include <uORB/topics/actuator_motors.h>
|
#include <uORB/topics/actuator_motors.h>
|
||||||
|
#include <uORB/topics/actuator_servos_trim.h>
|
||||||
#include <uORB/Subscription.hpp>
|
#include <uORB/Subscription.hpp>
|
||||||
|
|
||||||
static_assert(actuator_test_s::FUNCTION_MOTOR1 == (int)OutputFunction::Motor1, "define mismatch");
|
static_assert(actuator_test_s::FUNCTION_MOTOR1 == (int)OutputFunction::Motor1, "define mismatch");
|
||||||
@@ -66,6 +67,7 @@ private:
|
|||||||
|
|
||||||
uORB::Subscription _actuator_test_sub{ORB_ID(actuator_test)};
|
uORB::Subscription _actuator_test_sub{ORB_ID(actuator_test)};
|
||||||
uORB::Subscription _actuator_motors_sub{ORB_ID(actuator_motors)};
|
uORB::Subscription _actuator_motors_sub{ORB_ID(actuator_motors)};
|
||||||
|
uORB::Subscription _actuator_servos_trim_sub{ORB_ID(actuator_servos_trim)};
|
||||||
bool _in_test_mode{false};
|
bool _in_test_mode{false};
|
||||||
hrt_abstime _next_timeout{0};
|
hrt_abstime _next_timeout{0};
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
*
|
*
|
||||||
* Minimum time allowed for the motor input signal to pass through
|
* Minimum time allowed for the motor input signal to pass through
|
||||||
* a range of 1000 PWM units. A value x means that the motor signal
|
* a range of 1000 PWM units. A value x means that the motor signal
|
||||||
* can only go from 1000 to 2000 PWM in maximum x seconds.
|
* can only go from 1000 to 2000 PWM in minimum x seconds.
|
||||||
*
|
*
|
||||||
* Zero means that slew rate limiting is disabled.
|
* Zero means that slew rate limiting is disabled.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ public:
|
|||||||
int num_actuators_matrix[MAX_NUM_MATRICES]; ///< current amount, and next actuator index to fill in to effectiveness_matrices
|
int num_actuators_matrix[MAX_NUM_MATRICES]; ///< current amount, and next actuator index to fill in to effectiveness_matrices
|
||||||
ActuatorVector trim[MAX_NUM_MATRICES];
|
ActuatorVector trim[MAX_NUM_MATRICES];
|
||||||
|
|
||||||
|
ActuatorVector linearization_point[MAX_NUM_MATRICES];
|
||||||
|
|
||||||
int selected_matrix;
|
int selected_matrix;
|
||||||
|
|
||||||
uint8_t matrix_selection_indexes[NUM_ACTUATORS * MAX_NUM_MATRICES];
|
uint8_t matrix_selection_indexes[NUM_ACTUATORS * MAX_NUM_MATRICES];
|
||||||
|
|||||||
+9
-1
@@ -50,6 +50,8 @@ ActuatorEffectivenessControlSurfaces::ActuatorEffectivenessControlSurfaces(Modul
|
|||||||
_param_handles[i].torque[1] = param_find(buffer);
|
_param_handles[i].torque[1] = param_find(buffer);
|
||||||
snprintf(buffer, sizeof(buffer), "CA_SV_CS%u_TRQ_Y", i);
|
snprintf(buffer, sizeof(buffer), "CA_SV_CS%u_TRQ_Y", i);
|
||||||
_param_handles[i].torque[2] = param_find(buffer);
|
_param_handles[i].torque[2] = param_find(buffer);
|
||||||
|
snprintf(buffer, sizeof(buffer), "CA_SV_CS%u_TRIM", i);
|
||||||
|
_param_handles[i].trim = param_find(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
_count_handle = param_find("CA_SV_CS_COUNT");
|
_count_handle = param_find("CA_SV_CS_COUNT");
|
||||||
@@ -78,6 +80,8 @@ void ActuatorEffectivenessControlSurfaces::updateParams()
|
|||||||
param_get(_param_handles[i].torque[n], &torque(n));
|
param_get(_param_handles[i].torque[n], &torque(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
param_get(_param_handles[i].trim, &_params[i].trim);
|
||||||
|
|
||||||
// TODO: enforce limits?
|
// TODO: enforce limits?
|
||||||
switch (_params[i].type) {
|
switch (_params[i].type) {
|
||||||
case Type::Elevator:
|
case Type::Elevator:
|
||||||
@@ -126,7 +130,11 @@ bool ActuatorEffectivenessControlSurfaces::getEffectivenessMatrix(Configuration
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < _count; i++) {
|
for (int i = 0; i < _count; i++) {
|
||||||
configuration.addActuator(ActuatorType::SERVOS, _params[i].torque, Vector3f{});
|
int actuator_idx = configuration.addActuator(ActuatorType::SERVOS, _params[i].torque, Vector3f{});
|
||||||
|
|
||||||
|
if (actuator_idx >= 0) {
|
||||||
|
configuration.trim[configuration.selected_matrix](actuator_idx) = _params[i].trim;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+2
@@ -63,6 +63,7 @@ public:
|
|||||||
Type type;
|
Type type;
|
||||||
|
|
||||||
matrix::Vector3f torque;
|
matrix::Vector3f torque;
|
||||||
|
float trim;
|
||||||
};
|
};
|
||||||
|
|
||||||
ActuatorEffectivenessControlSurfaces(ModuleParams *parent);
|
ActuatorEffectivenessControlSurfaces(ModuleParams *parent);
|
||||||
@@ -86,6 +87,7 @@ private:
|
|||||||
param_t type;
|
param_t type;
|
||||||
|
|
||||||
param_t torque[3];
|
param_t torque[3];
|
||||||
|
param_t trim;
|
||||||
};
|
};
|
||||||
ParamHandles _param_handles[MAX_COUNT];
|
ParamHandles _param_handles[MAX_COUNT];
|
||||||
param_t _count_handle;
|
param_t _count_handle;
|
||||||
|
|||||||
@@ -51,18 +51,15 @@ ControlAllocation::ControlAllocation()
|
|||||||
void
|
void
|
||||||
ControlAllocation::setEffectivenessMatrix(
|
ControlAllocation::setEffectivenessMatrix(
|
||||||
const matrix::Matrix<float, ControlAllocation::NUM_AXES, ControlAllocation::NUM_ACTUATORS> &effectiveness,
|
const matrix::Matrix<float, ControlAllocation::NUM_AXES, ControlAllocation::NUM_ACTUATORS> &effectiveness,
|
||||||
const matrix::Vector<float, ControlAllocation::NUM_ACTUATORS> &actuator_trim, int num_actuators)
|
const ActuatorVector &actuator_trim, const ActuatorVector &linearization_point, int num_actuators)
|
||||||
{
|
{
|
||||||
_effectiveness = effectiveness;
|
_effectiveness = effectiveness;
|
||||||
_actuator_trim = actuator_trim;
|
ActuatorVector linearization_point_clipped = linearization_point;
|
||||||
|
clipActuatorSetpoint(linearization_point_clipped);
|
||||||
|
_actuator_trim = actuator_trim + linearization_point_clipped;
|
||||||
clipActuatorSetpoint(_actuator_trim);
|
clipActuatorSetpoint(_actuator_trim);
|
||||||
_control_trim = _effectiveness * _actuator_trim;
|
|
||||||
_num_actuators = num_actuators;
|
_num_actuators = num_actuators;
|
||||||
|
_control_trim = _effectiveness * linearization_point_clipped;
|
||||||
// make sure unused actuators are initialized to trim
|
|
||||||
for (int i = num_actuators; i < NUM_ACTUATORS; ++i) {
|
|
||||||
_actuator_sp(i) = _actuator_trim(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -109,3 +106,20 @@ const
|
|||||||
|
|
||||||
return actuator_normalized;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public:
|
|||||||
* @param B Effectiveness matrix
|
* @param B Effectiveness matrix
|
||||||
*/
|
*/
|
||||||
virtual void setEffectivenessMatrix(const matrix::Matrix<float, NUM_AXES, NUM_ACTUATORS> &effectiveness,
|
virtual void setEffectivenessMatrix(const matrix::Matrix<float, NUM_AXES, NUM_ACTUATORS> &effectiveness,
|
||||||
const matrix::Vector<float, NUM_ACTUATORS> &actuator_trim, int num_actuators);
|
const ActuatorVector &actuator_trim, const ActuatorVector &linearization_point, int num_actuators);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the allocated actuator vector
|
* Get the allocated actuator vector
|
||||||
@@ -181,6 +181,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setActuatorSetpoint(const matrix::Vector<float, NUM_ACTUATORS> &actuator_sp);
|
void setActuatorSetpoint(const matrix::Vector<float, NUM_ACTUATORS> &actuator_sp);
|
||||||
|
|
||||||
|
void setSlewRateLimit(const matrix::Vector<float, NUM_ACTUATORS> &slew_rate_limit)
|
||||||
|
{ _actuator_slew_rate_limit = slew_rate_limit; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply slew rate to current actuator setpoint
|
||||||
|
*/
|
||||||
|
void applySlewRateLimit(float dt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clip the actuator setpoint between minimum and maximum values.
|
* Clip the actuator setpoint between minimum and maximum values.
|
||||||
*
|
*
|
||||||
@@ -211,13 +219,15 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
friend class ControlAllocator; // for _actuator_sp
|
friend class ControlAllocator; // for _actuator_sp
|
||||||
|
|
||||||
matrix::Matrix<float, NUM_AXES, NUM_ACTUATORS> _effectiveness; //< Effectiveness matrix
|
matrix::Matrix<float, NUM_AXES, NUM_ACTUATORS> _effectiveness; ///< Effectiveness matrix
|
||||||
matrix::Vector<float, NUM_AXES> _control_allocation_scale; //< Scaling applied during allocation
|
matrix::Vector<float, NUM_AXES> _control_allocation_scale; ///< Scaling applied during allocation
|
||||||
matrix::Vector<float, NUM_ACTUATORS> _actuator_trim; //< Neutral actuator values
|
matrix::Vector<float, NUM_ACTUATORS> _actuator_trim; ///< Neutral actuator values
|
||||||
matrix::Vector<float, NUM_ACTUATORS> _actuator_min; //< Minimum actuator values
|
matrix::Vector<float, NUM_ACTUATORS> _actuator_min; ///< Minimum actuator values
|
||||||
matrix::Vector<float, NUM_ACTUATORS> _actuator_max; //< Maximum actuator values
|
matrix::Vector<float, NUM_ACTUATORS> _actuator_max; ///< Maximum actuator values
|
||||||
matrix::Vector<float, NUM_ACTUATORS> _actuator_sp; //< Actuator setpoint
|
matrix::Vector<float, NUM_ACTUATORS> _actuator_slew_rate_limit; ///< Slew rate limit
|
||||||
matrix::Vector<float, NUM_AXES> _control_sp; //< Control setpoint
|
matrix::Vector<float, NUM_ACTUATORS> _prev_actuator_sp; ///< Previous actuator setpoint
|
||||||
matrix::Vector<float, NUM_AXES> _control_trim; //< Control at trim actuator values
|
matrix::Vector<float, NUM_ACTUATORS> _actuator_sp; ///< Actuator setpoint
|
||||||
|
matrix::Vector<float, NUM_AXES> _control_sp; ///< Control setpoint
|
||||||
|
matrix::Vector<float, NUM_AXES> _control_trim; ///< Control at trim actuator values
|
||||||
int _num_actuators{0};
|
int _num_actuators{0};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,9 +44,9 @@
|
|||||||
void
|
void
|
||||||
ControlAllocationPseudoInverse::setEffectivenessMatrix(
|
ControlAllocationPseudoInverse::setEffectivenessMatrix(
|
||||||
const matrix::Matrix<float, ControlAllocation::NUM_AXES, ControlAllocation::NUM_ACTUATORS> &effectiveness,
|
const matrix::Matrix<float, ControlAllocation::NUM_AXES, ControlAllocation::NUM_ACTUATORS> &effectiveness,
|
||||||
const matrix::Vector<float, ControlAllocation::NUM_ACTUATORS> &actuator_trim, int num_actuators)
|
const ActuatorVector &actuator_trim, const ActuatorVector &linearization_point, int num_actuators)
|
||||||
{
|
{
|
||||||
ControlAllocation::setEffectivenessMatrix(effectiveness, actuator_trim, num_actuators);
|
ControlAllocation::setEffectivenessMatrix(effectiveness, actuator_trim, linearization_point, num_actuators);
|
||||||
_mix_update_needed = true;
|
_mix_update_needed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +120,8 @@ ControlAllocationPseudoInverse::allocate()
|
|||||||
//Compute new gains if needed
|
//Compute new gains if needed
|
||||||
updatePseudoInverse();
|
updatePseudoInverse();
|
||||||
|
|
||||||
|
_prev_actuator_sp = _actuator_sp;
|
||||||
|
|
||||||
// Allocate
|
// Allocate
|
||||||
_actuator_sp = _actuator_trim + _mix * (_control_sp - _control_trim);
|
_actuator_sp = _actuator_trim + _mix * (_control_sp - _control_trim);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public:
|
|||||||
|
|
||||||
void allocate() override;
|
void allocate() override;
|
||||||
void setEffectivenessMatrix(const matrix::Matrix<float, NUM_AXES, NUM_ACTUATORS> &effectiveness,
|
void setEffectivenessMatrix(const matrix::Matrix<float, NUM_AXES, NUM_ACTUATORS> &effectiveness,
|
||||||
const matrix::Vector<float, NUM_ACTUATORS> &actuator_trim, int num_actuators) override;
|
const ActuatorVector &actuator_trim, const ActuatorVector &linearization_point, int num_actuators) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
matrix::Matrix<float, NUM_ACTUATORS, NUM_AXES> _mix;
|
matrix::Matrix<float, NUM_ACTUATORS, NUM_AXES> _mix;
|
||||||
|
|||||||
+2
-1
@@ -54,9 +54,10 @@ TEST(ControlAllocationTest, AllZeroCase)
|
|||||||
matrix::Matrix<float, 6, 16> effectiveness;
|
matrix::Matrix<float, 6, 16> effectiveness;
|
||||||
matrix::Vector<float, 16> actuator_sp;
|
matrix::Vector<float, 16> actuator_sp;
|
||||||
matrix::Vector<float, 16> actuator_trim;
|
matrix::Vector<float, 16> actuator_trim;
|
||||||
|
matrix::Vector<float, 16> linearization_point;
|
||||||
matrix::Vector<float, 16> actuator_sp_expected;
|
matrix::Vector<float, 16> actuator_sp_expected;
|
||||||
|
|
||||||
method.setEffectivenessMatrix(effectiveness, actuator_trim, 16);
|
method.setEffectivenessMatrix(effectiveness, actuator_trim, linearization_point, 16);
|
||||||
method.setControlSetpoint(control_sp);
|
method.setControlSetpoint(control_sp);
|
||||||
method.allocate();
|
method.allocate();
|
||||||
method.clipActuatorSetpoint();
|
method.clipActuatorSetpoint();
|
||||||
|
|||||||
+2
@@ -47,6 +47,8 @@ ControlAllocationSequentialDesaturation::allocate()
|
|||||||
//Compute new gains if needed
|
//Compute new gains if needed
|
||||||
updatePseudoInverse();
|
updatePseudoInverse();
|
||||||
|
|
||||||
|
_prev_actuator_sp = _actuator_sp;
|
||||||
|
|
||||||
switch (_param_mc_airmode.get()) {
|
switch (_param_mc_airmode.get()) {
|
||||||
case 1:
|
case 1:
|
||||||
mixAirmodeRP();
|
mixAirmodeRP();
|
||||||
|
|||||||
@@ -54,6 +54,18 @@ ControlAllocator::ControlAllocator() :
|
|||||||
WorkItem(MODULE_NAME, px4::wq_configurations::rate_ctrl),
|
WorkItem(MODULE_NAME, px4::wq_configurations::rate_ctrl),
|
||||||
_loop_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": cycle"))
|
_loop_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": cycle"))
|
||||||
{
|
{
|
||||||
|
for (int i = 0; i < MAX_NUM_MOTORS; ++i) {
|
||||||
|
char buffer[17];
|
||||||
|
snprintf(buffer, sizeof(buffer), "CA_R%u_SLEW", i);
|
||||||
|
_param_handles.slew_rate_motors[i] = param_find(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUM_SERVOS; ++i) {
|
||||||
|
char buffer[17];
|
||||||
|
snprintf(buffer, sizeof(buffer), "CA_SV%u_SLEW", i);
|
||||||
|
_param_handles.slew_rate_servos[i] = param_find(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
parameters_updated();
|
parameters_updated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +99,18 @@ ControlAllocator::init()
|
|||||||
void
|
void
|
||||||
ControlAllocator::parameters_updated()
|
ControlAllocator::parameters_updated()
|
||||||
{
|
{
|
||||||
|
_has_slew_rate = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUM_MOTORS; ++i) {
|
||||||
|
param_get(_param_handles.slew_rate_motors[i], &_params.slew_rate_motors[i]);
|
||||||
|
_has_slew_rate |= _params.slew_rate_motors[i] > FLT_EPSILON;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUM_SERVOS; ++i) {
|
||||||
|
param_get(_param_handles.slew_rate_servos[i], &_params.slew_rate_servos[i]);
|
||||||
|
_has_slew_rate |= _params.slew_rate_servos[i] > FLT_EPSILON;
|
||||||
|
}
|
||||||
|
|
||||||
// Allocation method & effectiveness source
|
// Allocation method & effectiveness source
|
||||||
// Do this first: in case a new method is loaded, it will be configured below
|
// Do this first: in case a new method is loaded, it will be configured below
|
||||||
bool updated = update_effectiveness_source();
|
bool updated = update_effectiveness_source();
|
||||||
@@ -343,6 +367,11 @@ ControlAllocator::Run()
|
|||||||
// Do allocation
|
// Do allocation
|
||||||
_control_allocation[i]->allocate();
|
_control_allocation[i]->allocate();
|
||||||
_actuator_effectiveness->updateSetpoint(c[i], i, _control_allocation[i]->_actuator_sp);
|
_actuator_effectiveness->updateSetpoint(c[i], i, _control_allocation[i]->_actuator_sp);
|
||||||
|
|
||||||
|
if (_has_slew_rate) {
|
||||||
|
_control_allocation[i]->applySlewRateLimit(dt);
|
||||||
|
}
|
||||||
|
|
||||||
_control_allocation[i]->clipActuatorSetpoint();
|
_control_allocation[i]->clipActuatorSetpoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,14 +407,19 @@ ControlAllocator::update_effectiveness_matrix_if_needed(bool force)
|
|||||||
// Get the minimum and maximum depending on type and configuration
|
// Get the minimum and maximum depending on type and configuration
|
||||||
ActuatorEffectiveness::ActuatorVector minimum[ActuatorEffectiveness::MAX_NUM_MATRICES];
|
ActuatorEffectiveness::ActuatorVector minimum[ActuatorEffectiveness::MAX_NUM_MATRICES];
|
||||||
ActuatorEffectiveness::ActuatorVector maximum[ActuatorEffectiveness::MAX_NUM_MATRICES];
|
ActuatorEffectiveness::ActuatorVector maximum[ActuatorEffectiveness::MAX_NUM_MATRICES];
|
||||||
|
ActuatorEffectiveness::ActuatorVector slew_rate[ActuatorEffectiveness::MAX_NUM_MATRICES];
|
||||||
int actuator_idx = 0;
|
int actuator_idx = 0;
|
||||||
int actuator_idx_matrix[ActuatorEffectiveness::MAX_NUM_MATRICES] {};
|
int actuator_idx_matrix[ActuatorEffectiveness::MAX_NUM_MATRICES] {};
|
||||||
|
|
||||||
|
actuator_servos_trim_s trims{};
|
||||||
|
static_assert(actuator_servos_trim_s::NUM_CONTROLS == actuator_servos_s::NUM_CONTROLS, "size mismatch");
|
||||||
|
|
||||||
for (int actuator_type = 0; actuator_type < (int)ActuatorType::COUNT; ++actuator_type) {
|
for (int actuator_type = 0; actuator_type < (int)ActuatorType::COUNT; ++actuator_type) {
|
||||||
_num_actuators[actuator_type] = config.num_actuators[actuator_type];
|
_num_actuators[actuator_type] = config.num_actuators[actuator_type];
|
||||||
|
|
||||||
for (int actuator_type_idx = 0; actuator_type_idx < config.num_actuators[actuator_type]; ++actuator_type_idx) {
|
for (int actuator_type_idx = 0; actuator_type_idx < config.num_actuators[actuator_type]; ++actuator_type_idx) {
|
||||||
if (actuator_idx >= NUM_ACTUATORS) {
|
if (actuator_idx >= NUM_ACTUATORS) {
|
||||||
|
_num_actuators[actuator_type] = 0;
|
||||||
PX4_ERR("Too many actuators");
|
PX4_ERR("Too many actuators");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -393,6 +427,12 @@ ControlAllocator::update_effectiveness_matrix_if_needed(bool force)
|
|||||||
int selected_matrix = _control_allocation_selection_indexes[actuator_idx];
|
int selected_matrix = _control_allocation_selection_indexes[actuator_idx];
|
||||||
|
|
||||||
if ((ActuatorType)actuator_type == ActuatorType::MOTORS) {
|
if ((ActuatorType)actuator_type == ActuatorType::MOTORS) {
|
||||||
|
if (actuator_type_idx >= MAX_NUM_MOTORS) {
|
||||||
|
PX4_ERR("Too many motors");
|
||||||
|
_num_actuators[actuator_type] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (_param_r_rev.get() & (1u << actuator_type_idx)) {
|
if (_param_r_rev.get() & (1u << actuator_type_idx)) {
|
||||||
minimum[selected_matrix](actuator_idx_matrix[selected_matrix]) = -1.f;
|
minimum[selected_matrix](actuator_idx_matrix[selected_matrix]) = -1.f;
|
||||||
|
|
||||||
@@ -400,11 +440,25 @@ ControlAllocator::update_effectiveness_matrix_if_needed(bool force)
|
|||||||
minimum[selected_matrix](actuator_idx_matrix[selected_matrix]) = 0.f;
|
minimum[selected_matrix](actuator_idx_matrix[selected_matrix]) = 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slew_rate[selected_matrix](actuator_idx_matrix[selected_matrix]) = _params.slew_rate_motors[actuator_type_idx];
|
||||||
|
|
||||||
|
} else if ((ActuatorType)actuator_type == ActuatorType::SERVOS) {
|
||||||
|
if (actuator_type_idx >= MAX_NUM_SERVOS) {
|
||||||
|
PX4_ERR("Too many servos");
|
||||||
|
_num_actuators[actuator_type] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
minimum[selected_matrix](actuator_idx_matrix[selected_matrix]) = -1.f;
|
||||||
|
slew_rate[selected_matrix](actuator_idx_matrix[selected_matrix]) = _params.slew_rate_servos[actuator_type_idx];
|
||||||
|
trims.trim[actuator_type_idx] = config.trim[selected_matrix](actuator_idx_matrix[selected_matrix]);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
minimum[selected_matrix](actuator_idx_matrix[selected_matrix]) = -1.f;
|
minimum[selected_matrix](actuator_idx_matrix[selected_matrix]) = -1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
maximum[selected_matrix](actuator_idx_matrix[selected_matrix]) = 1.f;
|
maximum[selected_matrix](actuator_idx_matrix[selected_matrix]) = 1.f;
|
||||||
|
|
||||||
++actuator_idx_matrix[selected_matrix];
|
++actuator_idx_matrix[selected_matrix];
|
||||||
++actuator_idx;
|
++actuator_idx;
|
||||||
}
|
}
|
||||||
@@ -413,11 +467,16 @@ ControlAllocator::update_effectiveness_matrix_if_needed(bool force)
|
|||||||
for (int i = 0; i < _num_control_allocation; ++i) {
|
for (int i = 0; i < _num_control_allocation; ++i) {
|
||||||
_control_allocation[i]->setActuatorMin(minimum[i]);
|
_control_allocation[i]->setActuatorMin(minimum[i]);
|
||||||
_control_allocation[i]->setActuatorMax(maximum[i]);
|
_control_allocation[i]->setActuatorMax(maximum[i]);
|
||||||
|
_control_allocation[i]->setSlewRateLimit(slew_rate[i]);
|
||||||
|
|
||||||
// Assign control effectiveness matrix
|
// Assign control effectiveness matrix
|
||||||
int total_num_actuators = config.num_actuators_matrix[i];
|
int total_num_actuators = config.num_actuators_matrix[i];
|
||||||
_control_allocation[i]->setEffectivenessMatrix(config.effectiveness_matrices[i], config.trim[i], total_num_actuators);
|
_control_allocation[i]->setEffectivenessMatrix(config.effectiveness_matrices[i], config.trim[i],
|
||||||
|
config.linearization_point[i], total_num_actuators);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trims.timestamp = hrt_absolute_time();
|
||||||
|
_actuator_servos_trim_pub.publish(trims);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
#include <uORB/SubscriptionCallback.hpp>
|
#include <uORB/SubscriptionCallback.hpp>
|
||||||
#include <uORB/topics/actuator_motors.h>
|
#include <uORB/topics/actuator_motors.h>
|
||||||
#include <uORB/topics/actuator_servos.h>
|
#include <uORB/topics/actuator_servos.h>
|
||||||
|
#include <uORB/topics/actuator_servos_trim.h>
|
||||||
#include <uORB/topics/control_allocator_status.h>
|
#include <uORB/topics/control_allocator_status.h>
|
||||||
#include <uORB/topics/parameter_update.h>
|
#include <uORB/topics/parameter_update.h>
|
||||||
#include <uORB/topics/vehicle_torque_setpoint.h>
|
#include <uORB/topics/vehicle_torque_setpoint.h>
|
||||||
@@ -76,6 +77,9 @@ public:
|
|||||||
static constexpr int NUM_ACTUATORS = ControlAllocation::NUM_ACTUATORS;
|
static constexpr int NUM_ACTUATORS = ControlAllocation::NUM_ACTUATORS;
|
||||||
static constexpr int NUM_AXES = ControlAllocation::NUM_AXES;
|
static constexpr int NUM_AXES = ControlAllocation::NUM_AXES;
|
||||||
|
|
||||||
|
static constexpr int MAX_NUM_MOTORS = actuator_motors_s::NUM_CONTROLS;
|
||||||
|
static constexpr int MAX_NUM_SERVOS = actuator_servos_s::NUM_CONTROLS;
|
||||||
|
|
||||||
using ActuatorVector = ActuatorEffectiveness::ActuatorVector;
|
using ActuatorVector = ActuatorEffectiveness::ActuatorVector;
|
||||||
|
|
||||||
ControlAllocator();
|
ControlAllocator();
|
||||||
@@ -100,6 +104,16 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
struct ParamHandles {
|
||||||
|
param_t slew_rate_motors[MAX_NUM_MOTORS];
|
||||||
|
param_t slew_rate_servos[MAX_NUM_SERVOS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Params {
|
||||||
|
float slew_rate_motors[MAX_NUM_MOTORS];
|
||||||
|
float slew_rate_servos[MAX_NUM_SERVOS];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initialize some vectors/matrices from parameters
|
* initialize some vectors/matrices from parameters
|
||||||
*/
|
*/
|
||||||
@@ -147,6 +161,7 @@ private:
|
|||||||
|
|
||||||
uORB::Publication<actuator_motors_s> _actuator_motors_pub{ORB_ID(actuator_motors)};
|
uORB::Publication<actuator_motors_s> _actuator_motors_pub{ORB_ID(actuator_motors)};
|
||||||
uORB::Publication<actuator_servos_s> _actuator_servos_pub{ORB_ID(actuator_servos)};
|
uORB::Publication<actuator_servos_s> _actuator_servos_pub{ORB_ID(actuator_servos)};
|
||||||
|
uORB::Publication<actuator_servos_trim_s> _actuator_servos_trim_pub{ORB_ID(actuator_servos_trim)};
|
||||||
|
|
||||||
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
|
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
|
||||||
|
|
||||||
@@ -161,6 +176,10 @@ private:
|
|||||||
hrt_abstime _timestamp_sample{0};
|
hrt_abstime _timestamp_sample{0};
|
||||||
hrt_abstime _last_status_pub{0};
|
hrt_abstime _last_status_pub{0};
|
||||||
|
|
||||||
|
ParamHandles _param_handles{};
|
||||||
|
Params _params{};
|
||||||
|
bool _has_slew_rate{false};
|
||||||
|
|
||||||
DEFINE_PARAMETERS(
|
DEFINE_PARAMETERS(
|
||||||
(ParamInt<px4::params::CA_AIRFRAME>) _param_ca_airframe,
|
(ParamInt<px4::params::CA_AIRFRAME>) _param_ca_airframe,
|
||||||
(ParamInt<px4::params::CA_METHOD>) _param_ca_method,
|
(ParamInt<px4::params::CA_METHOD>) _param_ca_method,
|
||||||
|
|||||||
@@ -53,6 +53,42 @@ parameters:
|
|||||||
6: Motor 7
|
6: Motor 7
|
||||||
7: Motor 8
|
7: Motor 8
|
||||||
default: 0
|
default: 0
|
||||||
|
CA_R${i}_SLEW:
|
||||||
|
description:
|
||||||
|
short: Motor ${i} slew rate limit
|
||||||
|
long: |
|
||||||
|
Minimum time allowed for the motor input signal to pass through
|
||||||
|
the full output range. A value x means that the motor signal
|
||||||
|
can only go from 0 to 1 in minimum x seconds (in case of
|
||||||
|
reversible motors, the range is -1 to 1).
|
||||||
|
|
||||||
|
Zero means that slew rate limiting is disabled.
|
||||||
|
type: float
|
||||||
|
decimal: 2
|
||||||
|
increment: 0.01
|
||||||
|
num_instances: *max_num_mc_motors
|
||||||
|
min: 0
|
||||||
|
max: 10
|
||||||
|
default: 0.0
|
||||||
|
|
||||||
|
# Servo params
|
||||||
|
CA_SV${i}_SLEW:
|
||||||
|
description:
|
||||||
|
short: Servo ${i} slew rate limit
|
||||||
|
long: |
|
||||||
|
Minimum time allowed for the servo input signal to pass through
|
||||||
|
the full output range. A value x means that the servo signal
|
||||||
|
can only go from -1 to 1 in minimum x seconds.
|
||||||
|
|
||||||
|
Zero means that slew rate limiting is disabled.
|
||||||
|
type: float
|
||||||
|
decimal: 2
|
||||||
|
increment: 0.05
|
||||||
|
num_instances: *max_num_servos
|
||||||
|
min: 0
|
||||||
|
max: 10
|
||||||
|
default: 0.0
|
||||||
|
|
||||||
|
|
||||||
# (MC) Rotors
|
# (MC) Rotors
|
||||||
CA_ROTOR_COUNT:
|
CA_ROTOR_COUNT:
|
||||||
@@ -246,6 +282,17 @@ parameters:
|
|||||||
num_instances: *max_num_servos
|
num_instances: *max_num_servos
|
||||||
instance_start: 0
|
instance_start: 0
|
||||||
default: 0.0
|
default: 0.0
|
||||||
|
CA_SV_CS${i}_TRIM:
|
||||||
|
description:
|
||||||
|
short: Control Surface ${i} trim
|
||||||
|
long: Can be used to add an offset to the servo control.
|
||||||
|
type: float
|
||||||
|
decimal: 2
|
||||||
|
min: -1.0
|
||||||
|
max: 1.0
|
||||||
|
num_instances: *max_num_servos
|
||||||
|
instance_start: 0
|
||||||
|
default: 0.0
|
||||||
|
|
||||||
# Tilts
|
# Tilts
|
||||||
CA_SV_TL_COUNT:
|
CA_SV_TL_COUNT:
|
||||||
@@ -341,12 +388,21 @@ mixer:
|
|||||||
show_as: 'bitset'
|
show_as: 'bitset'
|
||||||
index_offset: 0
|
index_offset: 0
|
||||||
advanced: true
|
advanced: true
|
||||||
|
- name: 'CA_R${i}_SLEW'
|
||||||
|
label: 'Slew Rate'
|
||||||
|
index_offset: 0
|
||||||
|
advanced: true
|
||||||
servo:
|
servo:
|
||||||
functions: 'Servo'
|
functions: 'Servo'
|
||||||
actuator_testing_values:
|
actuator_testing_values:
|
||||||
min: -1
|
min: -1
|
||||||
max: 1
|
max: 1
|
||||||
default: 0
|
default: 0
|
||||||
|
per_item_parameters:
|
||||||
|
- name: 'CA_SV${i}_SLEW'
|
||||||
|
label: 'Slew Rate'
|
||||||
|
index_offset: 0
|
||||||
|
advanced: true
|
||||||
DEFAULT:
|
DEFAULT:
|
||||||
actuator_testing_values:
|
actuator_testing_values:
|
||||||
min: -1
|
min: -1
|
||||||
@@ -427,6 +483,8 @@ mixer:
|
|||||||
- name: 'CA_SV_CS${i}_TRQ_Y'
|
- name: 'CA_SV_CS${i}_TRQ_Y'
|
||||||
label: 'Yaw Scale'
|
label: 'Yaw Scale'
|
||||||
identifier: 'servo-torque-yaw'
|
identifier: 'servo-torque-yaw'
|
||||||
|
- name: 'CA_SV_CS${i}_TRIM'
|
||||||
|
label: 'Trim'
|
||||||
|
|
||||||
2: # Tiltrotor VTOL
|
2: # Tiltrotor VTOL
|
||||||
actuators:
|
actuators:
|
||||||
@@ -458,6 +516,8 @@ mixer:
|
|||||||
- name: 'CA_SV_CS${i}_TRQ_Y'
|
- name: 'CA_SV_CS${i}_TRQ_Y'
|
||||||
label: 'Yaw Torque'
|
label: 'Yaw Torque'
|
||||||
identifier: 'servo-torque-yaw'
|
identifier: 'servo-torque-yaw'
|
||||||
|
- name: 'CA_SV_CS${i}_TRIM'
|
||||||
|
label: 'Trim'
|
||||||
- actuator_type: 'servo'
|
- actuator_type: 'servo'
|
||||||
group_label: 'Tilt Servos'
|
group_label: 'Tilt Servos'
|
||||||
count: 'CA_SV_TL_COUNT'
|
count: 'CA_SV_TL_COUNT'
|
||||||
@@ -519,5 +579,7 @@ mixer:
|
|||||||
- name: 'CA_SV_CS${i}_TRQ_Y'
|
- name: 'CA_SV_CS${i}_TRQ_Y'
|
||||||
label: 'Yaw Torque'
|
label: 'Yaw Torque'
|
||||||
identifier: 'servo-torque-yaw'
|
identifier: 'servo-torque-yaw'
|
||||||
|
- name: 'CA_SV_CS${i}_TRIM'
|
||||||
|
label: 'Trim'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user