forked from Archive/PX4-Autopilot
Compare commits
3 Commits
main
...
add_attitu
Author | SHA1 | Date |
---|---|---|
Konrad | 1b83d720b2 | |
Konrad | 8212cc49af | |
Konrad | 0c24cff5c2 |
|
@ -17,4 +17,4 @@ bool reset_integral # Reset roll/pitch/yaw integrals (navigation logic change)
|
|||
|
||||
bool fw_control_yaw_wheel # control heading with steering wheel (used for auto takeoff on runway)
|
||||
|
||||
# TOPICS vehicle_attitude_setpoint mc_virtual_attitude_setpoint fw_virtual_attitude_setpoint
|
||||
# TOPICS vehicle_attitude_setpoint mc_virtual_attitude_setpoint fw_virtual_attitude_setpoint vehicle_attitude_reference_setpoint fw_virtual_vehicle_attitude_reference_setpoint
|
||||
|
|
|
@ -5,6 +5,8 @@ float32 roll # [rad/s] roll rate setpoint
|
|||
float32 pitch # [rad/s] pitch rate setpoint
|
||||
float32 yaw # [rad/s] yaw rate setpoint
|
||||
|
||||
float32[3] accel_feedforward # [rad/s²] angular acceleration feedforward
|
||||
|
||||
# For clarification: For multicopters thrust_body[0] and thrust[1] are usually 0 and thrust[2] is the negative throttle demand.
|
||||
# For fixed wings thrust_x is the throttle demand and thrust_y, thrust_z will usually be zero.
|
||||
float32[3] thrust_body # Normalized thrust command in body NED frame [-1,1]
|
||||
|
|
|
@ -41,8 +41,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <px4_platform_common/defines.h>
|
||||
#include <matrix/SquareMatrix.hpp>
|
||||
|
||||
#include "lib/matrix/matrix/math.hpp"
|
||||
|
||||
namespace math
|
||||
{
|
||||
|
@ -150,9 +154,6 @@ public:
|
|||
// take a step forward from the last state (and input), update the filter states
|
||||
integrateStates(time_step, last_state_sample_, last_rate_sample_);
|
||||
|
||||
// instantaneous acceleration from current input / state
|
||||
filter_accel_ = calculateInstantaneousAcceleration(state_sample, rate_sample);
|
||||
|
||||
// store the current samples
|
||||
last_state_sample_ = state_sample;
|
||||
last_rate_sample_ = rate_sample;
|
||||
|
@ -174,7 +175,7 @@ public:
|
|||
last_rate_sample_ = rate;
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
// A conservative multiplier (>=2) on sample frequency to bound the maximum time step
|
||||
static constexpr float kSampleRateMultiplier = 4.0f;
|
||||
|
@ -247,7 +248,7 @@ private:
|
|||
* @param[in] state_sample [units]
|
||||
* @param[in] rate_sample [units/s]
|
||||
*/
|
||||
void integrateStatesForwardEuler(const float time_step, const T &state_sample, const T &rate_sample)
|
||||
virtual void integrateStatesForwardEuler(const float time_step, const T &state_sample, const T &rate_sample)
|
||||
{
|
||||
// general notation for what follows:
|
||||
// c: continuous
|
||||
|
@ -278,6 +279,9 @@ private:
|
|||
|
||||
// discrete state transition
|
||||
transitionStates(state_matrix, input_matrix, state_sample, rate_sample);
|
||||
|
||||
// instantaneous acceleration from current input / state
|
||||
filter_accel_ = calculateInstantaneousAcceleration(state_sample, rate_sample);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -324,6 +328,9 @@ private:
|
|||
|
||||
// discrete state transition
|
||||
transitionStates(state_matrix, input_matrix, state_sample, rate_sample);
|
||||
|
||||
// instantaneous acceleration from current input / state
|
||||
filter_accel_ = calculateInstantaneousAcceleration(state_sample, rate_sample);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -36,8 +36,8 @@ px4_add_module(
|
|||
MAIN fw_att_control
|
||||
SRCS
|
||||
FixedwingAttitudeControl.cpp
|
||||
FixedwingAttitudeControl.hpp
|
||||
|
||||
att_ref_model.cpp
|
||||
ecl_controller.cpp
|
||||
ecl_pitch_controller.cpp
|
||||
ecl_roll_controller.cpp
|
||||
|
|
|
@ -119,16 +119,6 @@ FixedwingAttitudeControl::vehicle_manual_poll(const float yaw_body)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
FixedwingAttitudeControl::vehicle_attitude_setpoint_poll()
|
||||
{
|
||||
if (_att_sp_sub.update(&_att_sp)) {
|
||||
_rates_sp.thrust_body[0] = _att_sp.thrust_body[0];
|
||||
_rates_sp.thrust_body[1] = _att_sp.thrust_body[1];
|
||||
_rates_sp.thrust_body[2] = _att_sp.thrust_body[2];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FixedwingAttitudeControl::vehicle_land_detected_poll()
|
||||
{
|
||||
|
@ -260,7 +250,16 @@ void FixedwingAttitudeControl::Run()
|
|||
|
||||
vehicle_manual_poll(euler_angles.psi());
|
||||
|
||||
vehicle_attitude_setpoint_poll();
|
||||
// attitude setpoint poll
|
||||
_reference_model.update();
|
||||
|
||||
_att_sp = _reference_model.getOutput();
|
||||
matrix::Vector2f vel_feedforward = _reference_model.getRateFeedforward();
|
||||
matrix::Vector2f acc_feedforward = _reference_model.getTorqueFeedforward();
|
||||
|
||||
_rates_sp.thrust_body[0] = _att_sp.thrust_body[0];
|
||||
_rates_sp.thrust_body[1] = _att_sp.thrust_body[1];
|
||||
_rates_sp.thrust_body[2] = _att_sp.thrust_body[2];
|
||||
|
||||
// vehicle status update must be before the vehicle_control_mode poll, otherwise rate sp are not published during whole transition
|
||||
_vehicle_status_sub.update(&_vehicle_status);
|
||||
|
@ -383,10 +382,14 @@ void FixedwingAttitudeControl::Run()
|
|||
}
|
||||
|
||||
/* Publish the rate setpoint for analysis once available */
|
||||
_rates_sp.roll = body_rates_setpoint(0);
|
||||
_rates_sp.pitch = body_rates_setpoint(1);
|
||||
_rates_sp.roll = body_rates_setpoint(0) + vel_feedforward(0);
|
||||
_rates_sp.pitch = body_rates_setpoint(1) + vel_feedforward(1);
|
||||
_rates_sp.yaw = body_rates_setpoint(2);
|
||||
|
||||
_rates_sp.accel_feedforward[0] = acc_feedforward(0);
|
||||
_rates_sp.accel_feedforward[1] = acc_feedforward(1);
|
||||
_rates_sp.accel_feedforward[2] = 0.f;
|
||||
|
||||
_rates_sp.timestamp = hrt_absolute_time();
|
||||
|
||||
_rate_sp_pub.publish(_rates_sp);
|
||||
|
@ -415,6 +418,7 @@ void FixedwingAttitudeControl::Run()
|
|||
} else {
|
||||
// full manual
|
||||
_wheel_ctrl.reset_integrator();
|
||||
_reference_model.reset();
|
||||
|
||||
_landing_gear_wheel.normalized_wheel_setpoint = PX4_ISFINITE(_manual_control_setpoint.yaw) ?
|
||||
_manual_control_setpoint.yaw : 0.f;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include "att_ref_model.h"
|
||||
#include "ecl_pitch_controller.h"
|
||||
#include "ecl_roll_controller.h"
|
||||
#include "ecl_wheel_controller.h"
|
||||
|
@ -98,7 +99,6 @@ private:
|
|||
|
||||
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
|
||||
|
||||
uORB::Subscription _att_sp_sub{ORB_ID(vehicle_attitude_setpoint)}; /**< vehicle attitude setpoint */
|
||||
uORB::Subscription _autotune_attitude_control_status_sub{ORB_ID(autotune_attitude_control_status)};
|
||||
uORB::Subscription _local_pos_sub{ORB_ID(vehicle_local_position)}; /**< local position subscription */
|
||||
uORB::Subscription _manual_control_setpoint_sub{ORB_ID(manual_control_setpoint)}; /**< notification of manual control updates */
|
||||
|
@ -164,9 +164,10 @@ private:
|
|||
ECL_YawController _yaw_ctrl;
|
||||
ECL_WheelController _wheel_ctrl;
|
||||
|
||||
FixedwingAttitudeReferenceModel _reference_model;
|
||||
|
||||
void parameters_update();
|
||||
void vehicle_manual_poll(const float yaw_body);
|
||||
void vehicle_attitude_setpoint_poll();
|
||||
void vehicle_land_detected_poll();
|
||||
float get_airspeed_constrained();
|
||||
};
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
#include "att_ref_model.h"
|
||||
|
||||
#include <px4_platform_common/log.h>
|
||||
|
||||
#include <lib/mathlib/mathlib.h>
|
||||
#include "lib/slew_rate/SlewRate.hpp"
|
||||
|
||||
float REFERENCE_MODEL_DAMPING{1.f};
|
||||
|
||||
FixedwingAttitudeReferenceModel::FixedwingAttitudeReferenceModel() :
|
||||
ModuleParams(nullptr)
|
||||
{
|
||||
parameters_update();
|
||||
}
|
||||
|
||||
void FixedwingAttitudeReferenceModel::update()
|
||||
{
|
||||
parameters_update();
|
||||
|
||||
/* We check if the attitude setpoint topic got updated externally, put in throughput mode,
|
||||
if attitude reference got updated, but into filter mode. If none, keep the current mode.
|
||||
If both put throughput mode for safety. */
|
||||
_att_sp_sub.update();
|
||||
|
||||
if (_att_sp_sub.get().timestamp > _last_att_setpoint_timestamp) {
|
||||
if (_mode == ModelMode::MODELMODE_FILTERING) {
|
||||
PX4_INFO("FixedWingAttitudeReferenceModel: Switch to throughput mode");
|
||||
}
|
||||
|
||||
_mode = ModelMode::MODELMODE_THROUGHPUT;
|
||||
|
||||
} else if (_att_ref_sp_sub.updated()) {
|
||||
_att_ref_sp_sub.update();
|
||||
|
||||
if (_mode == ModelMode::MODELMODE_THROUGHPUT) {
|
||||
PX4_INFO("FixedWingAttitudeReferenceModel: Switch to filtering mode");
|
||||
}
|
||||
|
||||
_mode = ModelMode::MODELMODE_FILTERING;
|
||||
|
||||
}
|
||||
|
||||
hrt_abstime now = hrt_absolute_time();
|
||||
|
||||
_attitiude_rate_feedforward_output = matrix::Vector2f{};
|
||||
_attitiude_torque_feedforward_output = matrix::Vector2f{};
|
||||
|
||||
if (_mode == ModelMode::MODELMODE_FILTERING) {
|
||||
|
||||
if (!_is_initialized) {
|
||||
|
||||
_is_initialized = true;
|
||||
_roll_ref_model.reset(_att_ref_sp_sub.get().roll_body);
|
||||
_pitch_ref_model.reset(_att_ref_sp_sub.get().pitch_body);
|
||||
|
||||
} else {
|
||||
if (_att_ref_sp_sub.get().timestamp > _last_update_timestamp) {
|
||||
_roll_ref_model.update(static_cast<float>(_att_ref_sp_sub.get().timestamp - _last_update_timestamp) / 1_s,
|
||||
_last_attitude_reference_setpoint.roll_body);
|
||||
_pitch_ref_model.update(static_cast<float>(_att_ref_sp_sub.get().timestamp - _last_update_timestamp) / 1_s,
|
||||
_last_attitude_reference_setpoint.pitch_body);
|
||||
_last_update_timestamp = _att_ref_sp_sub.get().timestamp;
|
||||
}
|
||||
|
||||
_roll_ref_model.update(static_cast<float>(math::max(now - _last_update_timestamp, static_cast<hrt_abstime>(0U))) / 1_s,
|
||||
_att_ref_sp_sub.get().roll_body);
|
||||
_pitch_ref_model.update(static_cast<float>(math::max(now - _last_update_timestamp, static_cast<hrt_abstime>(0U))) / 1_s,
|
||||
_att_ref_sp_sub.get().pitch_body);
|
||||
|
||||
}
|
||||
|
||||
_last_attitude_reference_setpoint = _att_ref_sp_sub.get();
|
||||
|
||||
_last_update_timestamp = now;
|
||||
|
||||
_attitude_setpoint_output = _att_ref_sp_sub.get();
|
||||
_attitude_setpoint_output.timestamp = now;
|
||||
|
||||
if (_param_ref_r_en.get()) {
|
||||
_attitude_setpoint_output.roll_body = _roll_ref_model.getState();
|
||||
_attitiude_rate_feedforward_output(0) = _roll_ref_model.getRate();
|
||||
_attitiude_torque_feedforward_output(0) = _roll_ref_model.getAccel();
|
||||
}
|
||||
|
||||
if (_param_ref_p_en.get()) {
|
||||
_attitude_setpoint_output.pitch_body = _pitch_ref_model.getState();
|
||||
_attitiude_rate_feedforward_output(1) = _pitch_ref_model.getRate();
|
||||
_attitiude_torque_feedforward_output(1) = _pitch_ref_model.getAccel();
|
||||
|
||||
}
|
||||
|
||||
// Other fields in the attitude setpoints are passed through
|
||||
|
||||
// Publish attitude setpoint for logging
|
||||
_att_sp_pub.publish(_attitude_setpoint_output);
|
||||
_last_att_setpoint_timestamp = _attitude_setpoint_output.timestamp;
|
||||
|
||||
} else {
|
||||
_attitude_setpoint_output = _att_sp_sub.get();
|
||||
_roll_ref_model.reset(_att_sp_sub.get().roll_body);
|
||||
_pitch_ref_model.reset(_att_sp_sub.get().pitch_body);
|
||||
_is_initialized = true;
|
||||
_last_update_timestamp = now;
|
||||
_last_att_setpoint_timestamp = _att_sp_sub.get().timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
void FixedwingAttitudeReferenceModel::reset()
|
||||
{
|
||||
_is_initialized = false;
|
||||
|
||||
if (_mode == ModelMode::MODELMODE_FILTERING) {
|
||||
_att_ref_sp_sub.update();
|
||||
_attitude_setpoint_output = _att_ref_sp_sub.get();
|
||||
|
||||
} else {
|
||||
_att_sp_sub.update();
|
||||
_attitude_setpoint_output = _att_sp_sub.get();
|
||||
}
|
||||
|
||||
_attitiude_rate_feedforward_output = matrix::Vector2f{};
|
||||
_attitiude_torque_feedforward_output = matrix::Vector2f{};
|
||||
}
|
||||
|
||||
void FixedwingAttitudeReferenceModel::parameters_update()
|
||||
{
|
||||
if (_parameter_update_sub.updated()) {
|
||||
parameter_update_s param_update;
|
||||
_parameter_update_sub.copy(¶m_update);
|
||||
|
||||
// If any parameter updated, call updateParams() to check if
|
||||
// this class attributes need updating (and do so).
|
||||
updateParams();
|
||||
|
||||
_roll_ref_model.setParameters(_param_ref_r_freq.get(), REFERENCE_MODEL_DAMPING, _param_ref_r_vel_limit.get(),
|
||||
_param_ref_r_acc_limit.get());
|
||||
_pitch_ref_model.setParameters(_param_ref_p_freq.get(), REFERENCE_MODEL_DAMPING, _param_ref_p_vel_limit.get(),
|
||||
_param_ref_p_acc_limit.get());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2023 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <matrix/math.hpp>
|
||||
#include <mathlib/mathlib.h>
|
||||
|
||||
#include <drivers/drv_hrt.h>
|
||||
|
||||
#include <px4_platform_common/module_params.h>
|
||||
|
||||
#include <lib/mathlib/math/filter/second_order_reference_model.hpp>
|
||||
#include <lib/slew_rate/SlewRateYaw.hpp>
|
||||
|
||||
#include <uORB/Publication.hpp>
|
||||
#include <uORB/Subscription.hpp>
|
||||
#include <uORB/SubscriptionInterval.hpp>
|
||||
#include <uORB/topics/parameter_update.h>
|
||||
#include <uORB/topics/vehicle_attitude_setpoint.h>
|
||||
|
||||
using namespace time_literals;
|
||||
|
||||
class AttitudeReferenceModel : public math::SecondOrderReferenceModel<float>
|
||||
{
|
||||
public:
|
||||
AttitudeReferenceModel()
|
||||
{
|
||||
setDiscretizationMethod(math::SecondOrderReferenceModel<float>::DiscretizationMethod::kForwardEuler);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the system parameters
|
||||
*
|
||||
* Calculates the damping coefficient, spring constant, and maximum allowed
|
||||
* time step based on the natural frequency.
|
||||
*
|
||||
* @param[in] natural_freq The desired undamped natural frequency of the system [rad/s]
|
||||
* @param[in] damping_ratio The desired damping ratio of the system
|
||||
* @param[in] vel_limit the limit for the velocity [rad/s]
|
||||
* @param[in] acc_limit the limit for the acceleration [rad/s^2]
|
||||
* @param[in] jerk_limit set maximum jerk [rad/s^3]. Optional, only used in kForwardEuler mode
|
||||
* @return Whether or not the param set was successful
|
||||
*/
|
||||
bool setParameters(const float natural_freq, const float damping_ratio, float vel_limit = INFINITY,
|
||||
float acc_limit = INFINITY)
|
||||
{
|
||||
if (acc_limit < FLT_EPSILON) {
|
||||
acc_limit_ = INFINITY;
|
||||
|
||||
} else {
|
||||
acc_limit_ = acc_limit;
|
||||
}
|
||||
|
||||
if (vel_limit < FLT_EPSILON) {
|
||||
vel_limit_ = INFINITY;
|
||||
|
||||
} else {
|
||||
vel_limit_ = vel_limit;
|
||||
}
|
||||
|
||||
return math::SecondOrderReferenceModel<float>::setParameters(natural_freq, damping_ratio);
|
||||
}
|
||||
|
||||
private:
|
||||
float vel_limit_; /** velocity limit [rad/s]*/
|
||||
float acc_limit_; /** acceleration limit [rad/s^2]*/
|
||||
|
||||
/**
|
||||
* Take one integration step using Euler-forward integration
|
||||
*
|
||||
* @param[in] time_step Integration time [s]
|
||||
* @param[in] state_sample [rad]
|
||||
* @param[in] rate_sample [rad/s]
|
||||
*/
|
||||
void integrateStatesForwardEuler(const float time_step, const float &state_sample, const float &rate_sample) override
|
||||
{
|
||||
filter_accel_ = calculateInstantaneousAcceleration(state_sample, rate_sample);
|
||||
|
||||
if (filter_accel_ > 0.f) {
|
||||
filter_accel_ = math::min(math::min(filter_accel_, (vel_limit_ - filter_rate_) / time_step), acc_limit_);
|
||||
|
||||
} else {
|
||||
filter_accel_ = math::max(math::max(filter_accel_, (-vel_limit_ - filter_rate_) / time_step), -acc_limit_);
|
||||
}
|
||||
|
||||
const float new_rate = filter_rate_ + filter_accel_ * time_step;
|
||||
const float new_state = filter_state_ + filter_rate_ * time_step;
|
||||
|
||||
filter_state_ = new_state;
|
||||
filter_rate_ = new_rate;
|
||||
}
|
||||
};
|
||||
|
||||
class FixedwingAttitudeReferenceModel : public ModuleParams
|
||||
{
|
||||
public:
|
||||
FixedwingAttitudeReferenceModel();
|
||||
~FixedwingAttitudeReferenceModel() = default;
|
||||
|
||||
void update();
|
||||
|
||||
void reset();
|
||||
|
||||
const vehicle_attitude_setpoint_s &getOutput() {return _attitude_setpoint_output;};
|
||||
|
||||
const matrix::Vector2f &getRateFeedforward() {return _attitiude_rate_feedforward_output;};
|
||||
const matrix::Vector2f &getTorqueFeedforward() {return _attitiude_torque_feedforward_output;};
|
||||
|
||||
private:
|
||||
|
||||
enum class ModelMode {
|
||||
MODELMODE_THROUGHPUT,
|
||||
MODELMODE_FILTERING
|
||||
} _mode{ModelMode::MODELMODE_THROUGHPUT}; /*< Mode in which the attitude reference model works on */
|
||||
|
||||
/**
|
||||
* Check for parameter changes and update them if needed.
|
||||
*/
|
||||
void parameters_update();
|
||||
|
||||
AttitudeReferenceModel _roll_ref_model; /*< Second order reference filter for the roll angle */
|
||||
AttitudeReferenceModel _pitch_ref_model; /*< Second order reference filter for the pitch angle */
|
||||
bool _is_initialized{false}; /*< Flag indicating if the reference model is already initialized */
|
||||
uint64_t _last_att_setpoint_timestamp{UINT64_C(0)}; /*< Timestamp of the last own published vehicle attitude setpoint topic */
|
||||
hrt_abstime _last_update_timestamp{0U}; /*< Timestamp of the last update*/
|
||||
vehicle_attitude_setpoint_s _last_attitude_reference_setpoint; /*< Last attitude reference setpoint input */
|
||||
vehicle_attitude_setpoint_s _attitude_setpoint_output; /*< Attitude setpoint to be set by output*/
|
||||
matrix::Vector2f _attitiude_rate_feedforward_output; /*< Attitude rate feedforward output */
|
||||
matrix::Vector2f _attitiude_torque_feedforward_output; /*< Attitude torque feedforward output */
|
||||
|
||||
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s}; /*< parameter update subscription */
|
||||
uORB::SubscriptionData<vehicle_attitude_setpoint_s> _att_ref_sp_sub{ORB_ID(vehicle_attitude_reference_setpoint)}; /*< vehicle attitude reference setpoint */
|
||||
uORB::SubscriptionData<vehicle_attitude_setpoint_s> _att_sp_sub{ORB_ID(vehicle_attitude_setpoint)}; /*< vehicle attitude setpoint */
|
||||
uORB::Publication<vehicle_attitude_setpoint_s> _att_sp_pub{ORB_ID(vehicle_attitude_setpoint)}; /*< vehicle attitude setpoint publication when reference model is active for logging */
|
||||
|
||||
DEFINE_PARAMETERS(
|
||||
(ParamFloat<px4::params::FW_REF_R_FREQ>) _param_ref_r_freq,
|
||||
(ParamFloat<px4::params::FW_REF_R_V_LIM>) _param_ref_r_vel_limit,
|
||||
(ParamFloat<px4::params::FW_REF_R_A_LIM>) _param_ref_r_acc_limit,
|
||||
(ParamBool<px4::params::FW_REF_R_EN>) _param_ref_r_en,
|
||||
(ParamFloat<px4::params::FW_REF_P_FREQ>) _param_ref_p_freq,
|
||||
(ParamFloat<px4::params::FW_REF_P_V_LIM>) _param_ref_p_vel_limit,
|
||||
(ParamFloat<px4::params::FW_REF_P_A_LIM>) _param_ref_p_acc_limit,
|
||||
(ParamBool<px4::params::FW_REF_P_EN>) _param_ref_p_en
|
||||
)
|
||||
};
|
|
@ -254,3 +254,87 @@ PARAM_DEFINE_FLOAT(FW_MAN_R_MAX, 45.0f);
|
|||
* @group FW Attitude Control
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_MAN_P_MAX, 30.0f);
|
||||
|
||||
/**
|
||||
* Natural frequency of the roll reference model
|
||||
*
|
||||
* Frequency of the critically damped second order roll reference model
|
||||
*
|
||||
* @min 0.0
|
||||
* @decimal 3
|
||||
* @group FW Attitude Control
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_REF_R_FREQ, 5.0f);
|
||||
|
||||
/**
|
||||
* Velocity limit of the roll reference model
|
||||
*
|
||||
* Limit of the critically damped second order roll reference model velocity. A negative value disables the limit.
|
||||
*
|
||||
* @min -1.0
|
||||
* @decimal 3
|
||||
* @group FW Attitude Control
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_REF_R_V_LIM, -1.0f);
|
||||
|
||||
/**
|
||||
* Acceleration limit of the roll reference model
|
||||
*
|
||||
* Limit of the critically damped second order roll reference model acceleration. A negative value disables the limit.
|
||||
*
|
||||
* @min -1.0
|
||||
* @decimal 3
|
||||
* @group FW Attitude Control
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_REF_R_A_LIM, -1.0f);
|
||||
|
||||
/**
|
||||
* Enable roll reference model
|
||||
*
|
||||
*
|
||||
* @boolean
|
||||
* @group FW Attitude Control
|
||||
*/
|
||||
PARAM_DEFINE_INT32(FW_REF_R_EN, 0);
|
||||
|
||||
/**
|
||||
* Natural frequency of the roll reference model
|
||||
*
|
||||
* Frequency of the critically damped second order pitch reference model
|
||||
*
|
||||
* @min 0.0
|
||||
* @decimal 3
|
||||
* @group FW Attitude Control
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_REF_P_FREQ, 5.0f);
|
||||
|
||||
/**
|
||||
* Velocity limit of the pitch reference model
|
||||
*
|
||||
* Limit of the critically damped second order pitch reference model velocity. A negative value disables the limit.
|
||||
*
|
||||
* @min -1.0
|
||||
* @decimal 3
|
||||
* @group FW Attitude Control
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_REF_P_V_LIM, -1.0f);
|
||||
|
||||
/**
|
||||
* Acceleration limit of the pitch reference model
|
||||
*
|
||||
* Limit of the critically damped second order pitch reference model acceleration. A negative value disables the limit.
|
||||
*
|
||||
* @min -1.0
|
||||
* @decimal 3
|
||||
* @group FW Attitude Control
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_REF_P_A_LIM, -1.0f);
|
||||
|
||||
/**
|
||||
* Enable pitch reference model
|
||||
*
|
||||
*
|
||||
* @boolean
|
||||
* @group FW Attitude Control
|
||||
*/
|
||||
PARAM_DEFINE_INT32(FW_REF_P_EN, 0);
|
||||
|
|
|
@ -52,6 +52,8 @@ FixedwingPositionControl::FixedwingPositionControl(bool vtol) :
|
|||
ModuleParams(nullptr),
|
||||
WorkItem(MODULE_NAME, px4::wq_configurations::nav_and_controllers),
|
||||
_attitude_sp_pub(vtol ? ORB_ID(fw_virtual_attitude_setpoint) : ORB_ID(vehicle_attitude_setpoint)),
|
||||
_attitude_ref_sp_pub(vtol ? ORB_ID(fw_virtual_vehicle_attitude_reference_setpoint) : ORB_ID(
|
||||
vehicle_attitude_reference_setpoint)),
|
||||
_loop_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")),
|
||||
_launchDetector(this),
|
||||
_runway_takeoff(this)
|
||||
|
@ -2435,7 +2437,14 @@ FixedwingPositionControl::Run()
|
|||
q.copyTo(_att_sp.q_d);
|
||||
|
||||
_att_sp.timestamp = hrt_absolute_time();
|
||||
_attitude_sp_pub.publish(_att_sp);
|
||||
|
||||
// Enable reference model use for auto modes except when transitioning.
|
||||
if (_control_mode_current == FW_POSCTRL_MODE_AUTO && !_vehicle_status.in_transition_mode) {
|
||||
_attitude_ref_sp_pub.publish(_att_sp);
|
||||
|
||||
} else {
|
||||
_attitude_sp_pub.publish(_att_sp);
|
||||
}
|
||||
|
||||
// only publish status in full FW mode
|
||||
if (_vehicle_status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING
|
||||
|
|
|
@ -204,6 +204,7 @@ private:
|
|||
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
|
||||
|
||||
uORB::Publication<vehicle_attitude_setpoint_s> _attitude_sp_pub;
|
||||
uORB::Publication<vehicle_attitude_setpoint_s> _attitude_ref_sp_pub;
|
||||
uORB::Publication<vehicle_local_position_setpoint_s> _local_pos_sp_pub{ORB_ID(vehicle_local_position_setpoint)};
|
||||
uORB::Publication<npfg_status_s> _npfg_status_pub{ORB_ID(npfg_status)};
|
||||
uORB::Publication<position_controller_status_s> _pos_ctrl_status_pub{ORB_ID(position_controller_status)};
|
||||
|
|
|
@ -360,8 +360,10 @@ void FixedwingRateControl::Run()
|
|||
const Vector3f angular_acceleration_setpoint = _rate_control.update(rates, body_rates_setpoint, angular_accel, dt,
|
||||
_landed);
|
||||
|
||||
const float roll_feedforward = _param_fw_rr_ff.get() * _airspeed_scaling * body_rates_setpoint(0);
|
||||
const float pitch_feedforward = _param_fw_pr_ff.get() * _airspeed_scaling * body_rates_setpoint(1);
|
||||
const float roll_feedforward = _param_fw_rr_ff.get() * _airspeed_scaling * body_rates_setpoint(
|
||||
0) + _param_fw_ra_ff.get() * _rates_sp.accel_feedforward[0];
|
||||
const float pitch_feedforward = _param_fw_pr_ff.get() * _airspeed_scaling * body_rates_setpoint(
|
||||
1) + _param_fw_pa_ff.get() * _rates_sp.accel_feedforward[1];
|
||||
const float yaw_feedforward = _param_fw_yr_ff.get() * _airspeed_scaling * body_rates_setpoint(2);
|
||||
|
||||
const float roll_u = angular_acceleration_setpoint(0) * _airspeed_scaling * _airspeed_scaling + roll_feedforward;
|
||||
|
|
|
@ -182,6 +182,7 @@ private:
|
|||
(ParamFloat<px4::params::FW_MAN_Y_SC>) _param_fw_man_y_sc,
|
||||
|
||||
(ParamFloat<px4::params::FW_PR_FF>) _param_fw_pr_ff,
|
||||
(ParamFloat<px4::params::FW_PA_FF>) _param_fw_pa_ff,
|
||||
(ParamFloat<px4::params::FW_PR_I>) _param_fw_pr_i,
|
||||
(ParamFloat<px4::params::FW_PR_IMAX>) _param_fw_pr_imax,
|
||||
(ParamFloat<px4::params::FW_PR_P>) _param_fw_pr_p,
|
||||
|
@ -189,6 +190,7 @@ private:
|
|||
|
||||
(ParamFloat<px4::params::FW_RLL_TO_YAW_FF>) _param_fw_rll_to_yaw_ff,
|
||||
(ParamFloat<px4::params::FW_RR_FF>) _param_fw_rr_ff,
|
||||
(ParamFloat<px4::params::FW_RA_FF>) _param_fw_ra_ff,
|
||||
(ParamFloat<px4::params::FW_RR_I>) _param_fw_rr_i,
|
||||
(ParamFloat<px4::params::FW_RR_IMAX>) _param_fw_rr_imax,
|
||||
(ParamFloat<px4::params::FW_RR_P>) _param_fw_rr_p,
|
||||
|
|
|
@ -209,6 +209,18 @@ PARAM_DEFINE_FLOAT(FW_YR_IMAX, 0.2f);
|
|||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_RR_FF, 0.5f);
|
||||
|
||||
/**
|
||||
* roll acceleration feedforward gain
|
||||
*
|
||||
* feedforward gain for acceleration to scale rad/s^2 to percentage output
|
||||
*
|
||||
* @min 0.0
|
||||
* @max 10.0
|
||||
* @decimal 2
|
||||
* @group FW Rate Control
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_RA_FF, 0.0f);
|
||||
|
||||
/**
|
||||
* Pitch rate feed forward
|
||||
*
|
||||
|
@ -223,6 +235,19 @@ PARAM_DEFINE_FLOAT(FW_RR_FF, 0.5f);
|
|||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_PR_FF, 0.5f);
|
||||
|
||||
/**
|
||||
* pitch acceleration feedforward gain
|
||||
*
|
||||
* feedforward gain for acceleration to scale rad/s^2 to unitless output
|
||||
*
|
||||
* @unit %/rad/s
|
||||
* @min 0.0
|
||||
* @max 10.0
|
||||
* @decimal 2
|
||||
* @group FW Rate Control
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_PA_FF, 0.0f);
|
||||
|
||||
/**
|
||||
* Yaw rate feed forward
|
||||
*
|
||||
|
|
|
@ -116,6 +116,7 @@ void LoggedTopics::add_default_topics()
|
|||
add_topic("vehicle_angular_velocity", 20);
|
||||
add_topic("vehicle_attitude", 50);
|
||||
add_topic("vehicle_attitude_setpoint", 50);
|
||||
add_topic("vehicle_attitude_reference_setpoint", 50);
|
||||
add_topic("vehicle_command");
|
||||
add_topic("vehicle_command_ack");
|
||||
add_topic("vehicle_constraints", 1000);
|
||||
|
|
|
@ -378,6 +378,18 @@ VtolAttitudeControl::Run()
|
|||
// check if mc and fw sp were updated
|
||||
const bool mc_att_sp_updated = _mc_virtual_att_sp_sub.update(&_mc_virtual_att_sp);
|
||||
const bool fw_att_sp_updated = _fw_virtual_att_sp_sub.update(&_fw_virtual_att_sp);
|
||||
const bool fw_att_ref_sp_updated = _fw_virtual_att_ref_sp_sub.update(&_fw_virtual_att_ref_sp);
|
||||
|
||||
if (fw_att_sp_updated) {
|
||||
_is_in_att_ref_mode = false;
|
||||
|
||||
} else if (fw_att_ref_sp_updated) {
|
||||
_is_in_att_ref_mode = true;
|
||||
}
|
||||
|
||||
if (_is_in_att_ref_mode) {
|
||||
_fw_virtual_att_sp = _fw_virtual_att_ref_sp;
|
||||
}
|
||||
|
||||
// update the vtol state machine which decides which mode we are in
|
||||
_vtol_type->update_vtol_state();
|
||||
|
@ -424,6 +436,10 @@ VtolAttitudeControl::Run()
|
|||
if (fw_att_sp_updated) {
|
||||
_vtol_type->update_fw_state();
|
||||
_vehicle_attitude_sp_pub.publish(_vehicle_attitude_sp);
|
||||
|
||||
} else if (fw_att_ref_sp_updated) {
|
||||
_vtol_type->update_fw_state();
|
||||
_vehicle_attitude_ref_sp_pub.publish(_vehicle_attitude_sp);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -159,6 +159,7 @@ private:
|
|||
uORB::Subscription _action_request_sub{ORB_ID(action_request)};
|
||||
uORB::Subscription _airspeed_validated_sub{ORB_ID(airspeed_validated)};
|
||||
uORB::Subscription _fw_virtual_att_sp_sub{ORB_ID(fw_virtual_attitude_setpoint)};
|
||||
uORB::Subscription _fw_virtual_att_ref_sp_sub{ORB_ID(fw_virtual_vehicle_attitude_reference_setpoint)};
|
||||
uORB::Subscription _home_position_sub{ORB_ID(home_position)};
|
||||
uORB::Subscription _land_detected_sub{ORB_ID(vehicle_land_detected)};
|
||||
uORB::Subscription _local_pos_sp_sub{ORB_ID(vehicle_local_position_setpoint)};
|
||||
|
@ -175,6 +176,7 @@ private:
|
|||
uORB::Publication<normalized_unsigned_setpoint_s> _flaps_setpoint_pub{ORB_ID(flaps_setpoint)};
|
||||
uORB::Publication<normalized_unsigned_setpoint_s> _spoilers_setpoint_pub{ORB_ID(spoilers_setpoint)};
|
||||
uORB::Publication<vehicle_attitude_setpoint_s> _vehicle_attitude_sp_pub{ORB_ID(vehicle_attitude_setpoint)};
|
||||
uORB::Publication<vehicle_attitude_setpoint_s> _vehicle_attitude_ref_sp_pub{ORB_ID(vehicle_attitude_reference_setpoint)};
|
||||
uORB::PublicationMulti<vehicle_thrust_setpoint_s> _vehicle_thrust_setpoint0_pub{ORB_ID(vehicle_thrust_setpoint)};
|
||||
uORB::PublicationMulti<vehicle_thrust_setpoint_s> _vehicle_thrust_setpoint1_pub{ORB_ID(vehicle_thrust_setpoint)};
|
||||
uORB::PublicationMulti<vehicle_torque_setpoint_s> _vehicle_torque_setpoint0_pub{ORB_ID(vehicle_torque_setpoint)};
|
||||
|
@ -185,6 +187,7 @@ private:
|
|||
|
||||
vehicle_attitude_setpoint_s _vehicle_attitude_sp{}; // vehicle attitude setpoint
|
||||
vehicle_attitude_setpoint_s _fw_virtual_att_sp{}; // virtual fw attitude setpoint
|
||||
vehicle_attitude_setpoint_s _fw_virtual_att_ref_sp{}; // virtual fw attitude setpoint
|
||||
vehicle_attitude_setpoint_s _mc_virtual_att_sp{}; // virtual mc attitude setpoint
|
||||
|
||||
vehicle_torque_setpoint_s _vehicle_torque_setpoint_virtual_mc{};
|
||||
|
@ -211,6 +214,8 @@ private:
|
|||
|
||||
float _air_density{atmosphere::kAirDensitySeaLevelStandardAtmos}; // [kg/m^3]
|
||||
|
||||
bool _is_in_att_ref_mode{false};
|
||||
|
||||
hrt_abstime _last_run_timestamp{0};
|
||||
|
||||
/* For multicopters it is usual to have a non-zero idle speed of the engines
|
||||
|
|
Loading…
Reference in New Issue