control_allocator: implement trim + slew rate limits configuration

This commit is contained in:
Beat Küng
2021-12-03 11:52:01 +01:00
committed by Daniel Agar
parent 301100ce0e
commit 4c80adfaf1
17 changed files with 224 additions and 24 deletions
+1
View File
@@ -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
+5
View File
@@ -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]
+11
View File
@@ -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 {
+2
View File
@@ -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};
+1 -1
View File
@@ -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];
@@ -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;
@@ -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;
@@ -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();
@@ -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,
+62
View File
@@ -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'