Compare commits

...

9 Commits

Author SHA1 Message Date
Konrad adbe15ee9e FixedWingPositionControl: Use reference model for all auto modes except when in vtol transition 2024-06-26 08:34:49 +02:00
Konrad 2f200d13e0 FixedWingAttControl: Add a reference attitude mode. 2024-06-26 08:34:49 +02:00
Konrad c330aba875 Add attitude reference setpoint topic 2024-06-26 08:34:49 +02:00
KonradRudin 09f066a73a mission: skip a vtol takoff mission item if already in air (#23319)
* mission: skip a vtol takoff mission item if already in air and a fixed wing

* MissionBase: also skip FW takeoff when already in-air

Signed-off-by: Silvan Fuhrer <silvan@auterion.com>

* mission: use setNextMissionItem to skip vtol takeoff when already in air

* mission: Only skip the VTOL takeoff in air for mission and rtl mission

If flying RTL mission reverse it must still include the takeoff point.

---------

Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
Co-authored-by: Silvan Fuhrer <silvan@auterion.com>
2024-06-25 16:33:45 +02:00
Nate 6fd0e98a69 Correct units of CRSF GPS altitude
Bug fix to correct returning mm units of altitude to m.
2024-06-24 12:27:21 +02:00
David Sidrane e8e8a60ca8 NuttX with backport of stm32h7 No phy 2024-06-24 06:12:12 -04:00
Matthias Grob 8cc7c99b59 mavlink: report generator error (#23313)
Without this flag the command silently succeeds even though the logs contains
an error. It's much more developer friendly to fail early in case of an error.
The log path is then also shown in the console output.
2024-06-24 10:00:03 +02:00
Daniel Agar 30ce560e3a ekf2: mag control reset filtered test ratio on start (if aligning yaw) 2024-06-20 13:41:54 -04:00
Daniel Agar dcb1103299 ekf2: move estimator_status test ratios to filtered values 2024-06-20 13:41:54 -04:00
32 changed files with 681 additions and 114 deletions
+1 -1
View File
@@ -223,7 +223,7 @@ def create_pdf_report(ulog: ULog, multi_instance: int, output_plot_filename: str
data_plot.save()
data_plot.close()
# plot innovation_check_flags summary
# plot innovation flags summary
data_plot = CheckFlagsPlot(
status_flags_time, estimator_status_flags, [['reject_hor_vel', 'reject_hor_pos'], ['reject_ver_vel', 'reject_ver_pos',
'reject_hagl'],
@@ -154,7 +154,6 @@
*(.text._ZN3Ekf20updateIMUBiasInhibitERKN9estimator9imuSampleE)
*(.text._ZN9Commander13dataLinkCheckEv)
*(.text._ZN17FlightModeManager10switchTaskE15FlightTaskIndex)
*(.text._ZNK3Ekf26get_innovation_test_statusERtRfS1_S1_S1_S1_S1_S1_)
*(.text._ZN12PX4Gyroscope9set_scaleEf)
*(.text._ZN12FailsafeBase6updateERKyRKNS_5StateEbbRK16failsafe_flags_s)
*(.text._ZN18MavlinkStreamDebug4sendEv)
+7 -20
View File
@@ -69,27 +69,14 @@ uint32 filter_fault_flags # Bitmask to indicate EKF internal faults
float32 pos_horiz_accuracy # 1-Sigma estimated horizontal position accuracy relative to the estimators origin (m)
float32 pos_vert_accuracy # 1-Sigma estimated vertical position accuracy relative to the estimators origin (m)
uint16 innovation_check_flags # Bitmask to indicate pass/fail status of innovation consistency checks
# 0 - true if velocity observations have been rejected
# 1 - true if horizontal position observations have been rejected
# 2 - true if true if vertical position observations have been rejected
# 3 - true if the X magnetometer observation has been rejected
# 4 - true if the Y magnetometer observation has been rejected
# 5 - true if the Z magnetometer observation has been rejected
# 6 - true if the yaw observation has been rejected
# 7 - true if the airspeed observation has been rejected
# 8 - true if the synthetic sideslip observation has been rejected
# 9 - true if the height above ground observation has been rejected
# 10 - true if the X optical flow observation has been rejected
# 11 - true if the Y optical flow observation has been rejected
float32 mag_test_ratio # ratio of the largest magnetometer innovation component to the innovation test limit
float32 vel_test_ratio # ratio of the largest velocity innovation component to the innovation test limit
float32 pos_test_ratio # ratio of the largest horizontal position innovation component to the innovation test limit
float32 hgt_test_ratio # ratio of the vertical position innovation to the innovation test limit
float32 tas_test_ratio # ratio of the true airspeed innovation to the innovation test limit
float32 hagl_test_ratio # ratio of the height above ground innovation to the innovation test limit
float32 beta_test_ratio # ratio of the synthetic sideslip innovation to the innovation test limit
float32 mag_test_ratio # low-pass filtered ratio of the largest magnetometer innovation component to the innovation test limit
float32 vel_test_ratio # low-pass filtered ratio of the largest velocity innovation component to the innovation test limit
float32 pos_test_ratio # low-pass filtered ratio of the largest horizontal position innovation component to the innovation test limit
float32 hgt_test_ratio # low-pass filtered ratio of the vertical position innovation to the innovation test limit
float32 tas_test_ratio # low-pass filtered ratio of the true airspeed innovation to the innovation test limit
float32 hagl_test_ratio # low-pass filtered ratio of the height above ground innovation to the innovation test limit
float32 beta_test_ratio # low-pass filtered ratio of the synthetic sideslip innovation to the innovation test limit
uint16 solution_status_flags # Bitmask indicating which filter kinematic state outputs are valid for flight control use.
# 0 - True if the attitude estimate is good
+1 -1
View File
@@ -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
+2
View File
@@ -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]
+1 -1
View File
@@ -241,7 +241,7 @@ void CrsfRc::Run()
int32_t longitude = static_cast<int32_t>(round(sensor_gps.longitude_deg * 1e7));
uint16_t groundspeed = sensor_gps.vel_d_m_s / 3.6f * 10.f;
uint16_t gps_heading = math::degrees(sensor_gps.cog_rad) * 100.f;
uint16_t altitude = static_cast<int16_t>(sensor_gps.altitude_msl_m * 1e3) + 1000;
uint16_t altitude = static_cast<int16_t>(sensor_gps.altitude_msl_m) + 1000;
uint8_t num_satellites = sensor_gps.satellites_used;
this->SendTelemetryGps(latitude, longitude, groundspeed, gps_heading, altitude, num_satellites);
}
@@ -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);
}
/**
@@ -151,6 +151,8 @@ void AuxGlobalPosition::update(Ekf &ekf, const estimator::imuSample &imu_delayed
#if defined(MODULE_NAME)
aid_src.timestamp = hrt_absolute_time();
_estimator_aid_src_aux_global_position_pub.publish(aid_src);
_test_ratio_filtered = math::max(fabsf(aid_src.test_ratio_filtered[0]), fabsf(aid_src.test_ratio_filtered[1]));
#endif // MODULE_NAME
} else if ((_state != State::stopped) && isTimedOut(_time_last_buffer_push, imu_delayed.time_us, (uint64_t)5e6)) {
@@ -74,6 +74,8 @@ public:
updateParams();
}
float test_ratio_filtered() const { return _test_ratio_filtered; }
private:
bool isTimedOut(uint64_t last_sensor_timestamp, uint64_t time_delayed_us, uint64_t timeout_period) const
{
@@ -106,6 +108,8 @@ private:
State _state{State::stopped};
float _test_ratio_filtered{INFINITY};
#if defined(MODULE_NAME)
struct reset_counters_s {
uint8_t lat_lon{};
@@ -245,6 +245,7 @@ void Ekf::controlMagFusion()
if (reset_heading) {
_control_status.flags.yaw_align = true;
resetAidSourceStatusZeroInnovation(aid_src);
}
_control_status.flags.mag = true;
+11 -7
View File
@@ -383,13 +383,17 @@ public:
*counter = _state_reset_status.reset_count.quat;
}
// get EKF innovation consistency check status information comprising of:
// status - a bitmask integer containing the pass/fail status for each EKF measurement innovation consistency check
// Innovation Test Ratios - these are the ratio of the innovation to the acceptance threshold.
// A value > 1 indicates that the sensor measurement has exceeded the maximum acceptable level and has been rejected by the EKF
// Where a measurement type is a vector quantity, eg magnetometer, GPS position, etc, the maximum value is returned.
void get_innovation_test_status(uint16_t &status, float &mag, float &vel, float &pos, float &hgt, float &tas,
float &hagl, float &beta) const;
float getHeadingInnovationTestRatio() const;
float getVelocityInnovationTestRatio() const;
float getHorizontalPositionInnovationTestRatio() const;
float getVerticalPositionInnovationTestRatio() const;
float getAirspeedInnovationTestRatio() const;
float getSyntheticSideslipInnovationTestRatio() const;
float getHeightAboveGroundInnovationTestRatio() const;
// return a bitmask integer that describes which state estimates are valid
void get_ekf_soln_status(uint16_t *status) const;
+109 -44
View File
@@ -301,131 +301,196 @@ void Ekf::resetAccelBias()
resetAccelBiasCov();
}
void Ekf::get_innovation_test_status(uint16_t &status, float &mag, float &vel, float &pos, float &hgt, float &tas,
float &hagl, float &beta) const
float Ekf::getHeadingInnovationTestRatio() const
{
// return the integer bitmask containing the consistency check pass/fail status
status = _innov_check_fail_status.value;
// return the largest magnetometer innovation test ratio
mag = 0.f;
// return the largest heading innovation test ratio
float test_ratio = 0.f;
#if defined(CONFIG_EKF2_MAGNETOMETER)
if (_control_status.flags.mag_hdg ||_control_status.flags.mag_3D) {
mag = math::max(mag, sqrtf(Vector3f(_aid_src_mag.test_ratio).max()));
for (auto &test_ratio_filtered : _aid_src_mag.test_ratio_filtered) {
test_ratio = math::max(test_ratio, fabsf(test_ratio_filtered));
}
}
#endif // CONFIG_EKF2_MAGNETOMETER
#if defined(CONFIG_EKF2_GNSS_YAW)
if (_control_status.flags.gps_yaw) {
mag = math::max(mag, sqrtf(_aid_src_gnss_yaw.test_ratio));
test_ratio = math::max(test_ratio, fabsf(_aid_src_gnss_yaw.test_ratio_filtered));
}
#endif // CONFIG_EKF2_GNSS_YAW
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_yaw) {
mag = math::max(mag, sqrtf(_aid_src_ev_yaw.test_ratio));
test_ratio = math::max(test_ratio, fabsf(_aid_src_ev_yaw.test_ratio_filtered));
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
// return the largest velocity and position innovation test ratio
vel = NAN;
pos = NAN;
return sqrtf(test_ratio);
}
float Ekf::getVelocityInnovationTestRatio() const
{
// return the largest velocity innovation test ratio
float test_ratio = -1.f;
#if defined(CONFIG_EKF2_GNSS)
if (_control_status.flags.gps) {
float gps_vel = sqrtf(Vector3f(_aid_src_gnss_vel.test_ratio).max());
vel = math::max(gps_vel, FLT_MIN);
float gps_pos = sqrtf(Vector2f(_aid_src_gnss_pos.test_ratio).max());
pos = math::max(gps_pos, FLT_MIN);
for (int i = 0; i < 3; i++) {
test_ratio = math::max(test_ratio, fabsf(_aid_src_gnss_vel.test_ratio_filtered[i]));
}
}
#endif // CONFIG_EKF2_GNSS
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_vel) {
float ev_vel = sqrtf(Vector3f(_aid_src_ev_vel.test_ratio).max());
vel = math::max(vel, ev_vel, FLT_MIN);
}
if (_control_status.flags.ev_pos) {
float ev_pos = sqrtf(Vector2f(_aid_src_ev_pos.test_ratio).max());
pos = math::max(pos, ev_pos, FLT_MIN);
for (int i = 0; i < 3; i++) {
test_ratio = math::max(test_ratio, fabsf(_aid_src_ev_vel.test_ratio_filtered[i]));
}
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
if (isOnlyActiveSourceOfHorizontalAiding(_control_status.flags.opt_flow)) {
float of_vel = sqrtf(Vector2f(_aid_src_optical_flow.test_ratio).max());
vel = math::max(of_vel, FLT_MIN);
for (auto &test_ratio_filtered : _aid_src_optical_flow.test_ratio_filtered) {
test_ratio = math::max(test_ratio, fabsf(test_ratio_filtered));
}
}
#endif // CONFIG_EKF2_OPTICAL_FLOW
if (PX4_ISFINITE(test_ratio) && (test_ratio >= 0.f)) {
return sqrtf(test_ratio);
}
return NAN;
}
float Ekf::getHorizontalPositionInnovationTestRatio() const
{
// return the largest position innovation test ratio
float test_ratio = -1.f;
#if defined(CONFIG_EKF2_GNSS)
if (_control_status.flags.gps) {
for (auto &test_ratio_filtered : _aid_src_gnss_pos.test_ratio_filtered) {
test_ratio = math::max(test_ratio, fabsf(test_ratio_filtered));
}
}
#endif // CONFIG_EKF2_GNSS
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_pos) {
for (auto &test_ratio_filtered : _aid_src_ev_pos.test_ratio_filtered) {
test_ratio = math::max(test_ratio, fabsf(test_ratio_filtered));
}
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
#if defined(CONFIG_EKF2_AUX_GLOBAL_POSITION) && defined(MODULE_NAME)
if (_control_status.flags.aux_gpos) {
test_ratio = math::max(test_ratio, fabsf(_aux_global_position.test_ratio_filtered()));
}
#endif // CONFIG_EKF2_AUX_GLOBAL_POSITION
if (PX4_ISFINITE(test_ratio) && (test_ratio >= 0.f)) {
return sqrtf(test_ratio);
}
return NAN;
}
float Ekf::getVerticalPositionInnovationTestRatio() const
{
// return the combined vertical position innovation test ratio
float hgt_sum = 0.f;
int n_hgt_sources = 0;
#if defined(CONFIG_EKF2_BAROMETER)
if (_control_status.flags.baro_hgt) {
hgt_sum += sqrtf(_aid_src_baro_hgt.test_ratio);
hgt_sum += sqrtf(fabsf(_aid_src_baro_hgt.test_ratio_filtered));
n_hgt_sources++;
}
#endif // CONFIG_EKF2_BAROMETER
#if defined(CONFIG_EKF2_GNSS)
if (_control_status.flags.gps_hgt) {
hgt_sum += sqrtf(_aid_src_gnss_hgt.test_ratio);
hgt_sum += sqrtf(fabsf(_aid_src_gnss_hgt.test_ratio_filtered));
n_hgt_sources++;
}
#endif // CONFIG_EKF2_GNSS
#if defined(CONFIG_EKF2_RANGE_FINDER)
if (_control_status.flags.rng_hgt) {
hgt_sum += sqrtf(_aid_src_rng_hgt.test_ratio);
hgt_sum += sqrtf(fabsf(_aid_src_rng_hgt.test_ratio_filtered));
n_hgt_sources++;
}
#endif // CONFIG_EKF2_RANGE_FINDER
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_hgt) {
hgt_sum += sqrtf(_aid_src_ev_hgt.test_ratio);
hgt_sum += sqrtf(fabsf(_aid_src_ev_hgt.test_ratio_filtered));
n_hgt_sources++;
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
if (n_hgt_sources > 0) {
hgt = math::max(hgt_sum / static_cast<float>(n_hgt_sources), FLT_MIN);
} else {
hgt = NAN;
return math::max(hgt_sum / static_cast<float>(n_hgt_sources), FLT_MIN);
}
return NAN;
}
float Ekf::getAirspeedInnovationTestRatio() const
{
#if defined(CONFIG_EKF2_AIRSPEED)
// return the airspeed fusion innovation test ratio
tas = sqrtf(_aid_src_airspeed.test_ratio);
if (_control_status.flags.fuse_aspd) {
// return the airspeed fusion innovation test ratio
return sqrtf(fabsf(_aid_src_airspeed.test_ratio_filtered));
}
#endif // CONFIG_EKF2_AIRSPEED
hagl = NAN;
return NAN;
}
float Ekf::getSyntheticSideslipInnovationTestRatio() const
{
#if defined(CONFIG_EKF2_SIDESLIP)
if (_control_status.flags.fuse_beta) {
// return the synthetic sideslip innovation test ratio
return sqrtf(fabsf(_aid_src_sideslip.test_ratio_filtered));
}
#endif // CONFIG_EKF2_SIDESLIP
return NAN;
}
float Ekf::getHeightAboveGroundInnovationTestRatio() const
{
float test_ratio = -1.f;
#if defined(CONFIG_EKF2_TERRAIN)
# if defined(CONFIG_EKF2_RANGE_FINDER)
if (_hagl_sensor_status.flags.range_finder) {
// return the terrain height innovation test ratio
hagl = sqrtf(_aid_src_terrain_range_finder.test_ratio);
test_ratio = math::max(test_ratio, fabsf(_aid_src_terrain_range_finder.test_ratio_filtered));
}
#endif // CONFIG_EKF2_RANGE_FINDER
# if defined(CONFIG_EKF2_OPTICAL_FLOW)
if (_hagl_sensor_status.flags.flow) {
// return the terrain height innovation test ratio
hagl = sqrtf(math::max(_aid_src_terrain_optical_flow.test_ratio[0], _aid_src_terrain_optical_flow.test_ratio[1]));
for (auto &test_ratio_filtered : _aid_src_terrain_optical_flow.test_ratio_filtered) {
test_ratio = math::max(test_ratio, fabsf(test_ratio_filtered));
}
}
# endif // CONFIG_EKF2_OPTICAL_FLOW
#endif // CONFIG_EKF2_TERRAIN
#if defined(CONFIG_EKF2_SIDESLIP)
// return the synthetic sideslip innovation test ratio
beta = sqrtf(_aid_src_sideslip.test_ratio);
#endif // CONFIG_EKF2_SIDESLIP
if (PX4_ISFINITE(test_ratio) && (test_ratio >= 0.f)) {
return sqrtf(test_ratio);
}
return NAN;
}
void Ekf::get_ekf_soln_status(uint16_t *status) const
+7 -9
View File
@@ -1802,15 +1802,13 @@ void EKF2::PublishStatus(const hrt_abstime &timestamp)
status.control_mode_flags = _ekf.control_status().value;
status.filter_fault_flags = _ekf.fault_status().value;
uint16_t innov_check_flags_temp = 0;
_ekf.get_innovation_test_status(innov_check_flags_temp, status.mag_test_ratio,
status.vel_test_ratio, status.pos_test_ratio,
status.hgt_test_ratio, status.tas_test_ratio,
status.hagl_test_ratio, status.beta_test_ratio);
// Bit mismatch between ecl and Firmware, combine the 2 first bits to preserve msg definition
// TODO: legacy use only, those flags are also in estimator_status_flags
status.innovation_check_flags = (innov_check_flags_temp >> 1) | (innov_check_flags_temp & 0x1);
status.mag_test_ratio = _ekf.getHeadingInnovationTestRatio();
status.vel_test_ratio = _ekf.getVelocityInnovationTestRatio();
status.pos_test_ratio = _ekf.getHorizontalPositionInnovationTestRatio();
status.hgt_test_ratio = _ekf.getVerticalPositionInnovationTestRatio();
status.tas_test_ratio = _ekf.getAirspeedInnovationTestRatio();
status.hagl_test_ratio = _ekf.getHeightAboveGroundInnovationTestRatio();
status.beta_test_ratio = _ekf.getSyntheticSideslipInnovationTestRatio();
_ekf.get_ekf_lpos_accuracy(&status.pos_horiz_accuracy, &status.pos_vert_accuracy);
_ekf.get_ekf_soln_status(&status.solution_status_flags);
+1 -1
View File
@@ -36,8 +36,8 @@ px4_add_module(
MAIN fw_att_control
SRCS
FixedwingAttitudeControl.cpp
FixedwingAttitudeControl.hpp
att_ref_model.cpp
fw_pitch_controller.cpp
fw_roll_controller.cpp
fw_wheel_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);
@@ -371,10 +370,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);
@@ -404,6 +407,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 "fw_pitch_controller.h"
#include "fw_roll_controller.h"
#include "fw_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 */
@@ -165,9 +165,10 @@ private:
YawController _yaw_ctrl;
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(&param_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());
}
}
+178
View File
@@ -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)
@@ -2574,7 +2576,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
@@ -216,6 +216,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)};
@@ -358,6 +358,7 @@ void FixedwingRateControl::Run()
const Vector3f angular_acceleration_setpoint = _rate_control.update(rates, body_rates_setpoint, angular_accel, dt,
_landed);
const Vector3f reference_ff(_param_fw_ra_ff.get() * _rates_sp.accel_feedforward[0], _param_fw_pa_ff.get() * _rates_sp.accel_feedforward[1], 0.f);
const Vector3f gain_ff(_param_fw_rr_ff.get(), _param_fw_pr_ff.get(), _param_fw_yr_ff.get());
const Vector3f feedforward = gain_ff.emult(body_rates_setpoint) * _airspeed_scaling;
@@ -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,
@@ -211,6 +211,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
*
@@ -225,6 +237,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
*
+1
View File
@@ -124,6 +124,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);
+2 -4
View File
@@ -44,8 +44,7 @@ add_custom_command(
COMMAND
${PYTHON_EXECUTABLE} ${MAVLINK_GIT_DIR}/pymavlink/tools/mavgen.py
--lang C --wire-protocol 2.0
#--no-validate
#--strict-units
--exit-code
--output ${MAVLINK_LIBRARY_DIR}
${MAVLINK_GIT_DIR}/message_definitions/v1.0/${MAVLINK_DIALECT_UAVIONIX}.xml > ${CMAKE_CURRENT_BINARY_DIR}/mavgen_${MAVLINK_DIALECT_UAVIONIX}.log
DEPENDS
@@ -64,8 +63,7 @@ add_custom_command(
COMMAND
${PYTHON_EXECUTABLE} ${MAVLINK_GIT_DIR}/pymavlink/tools/mavgen.py
--lang C --wire-protocol 2.0
#--no-validate
#--strict-units
--exit-code
--output ${MAVLINK_LIBRARY_DIR}
${MAVLINK_GIT_DIR}/message_definitions/v1.0/${CONFIG_MAVLINK_DIALECT}.xml > ${CMAKE_CURRENT_BINARY_DIR}/mavgen_${CONFIG_MAVLINK_DIALECT}.log
DEPENDS
@@ -309,8 +309,7 @@ private:
if (_estimator_status_sub.update(&estimator_status)) {
if (estimator_status.gps_check_fail_flags > 0 ||
estimator_status.filter_fault_flags > 0 ||
estimator_status.innovation_check_flags > 0) {
estimator_status.filter_fault_flags > 0) {
msg->failure_flags |= HL_FAILURE_FLAG_ESTIMATOR;
}
+17
View File
@@ -216,6 +216,23 @@ void Mission::setActiveMissionItems()
position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet();
const position_setpoint_s current_setpoint_copy = pos_sp_triplet->current;
/* Skip VTOL/FW Takeoff item if in air, fixed-wing and didn't start the takeoff already*/
if ((_mission_item.nav_cmd == NAV_CMD_VTOL_TAKEOFF || _mission_item.nav_cmd == NAV_CMD_TAKEOFF) &&
(_work_item_type == WorkItemType::WORK_ITEM_TYPE_DEFAULT) &&
(_vehicle_status_sub.get().vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING) &&
!_land_detected_sub.get().landed) {
if (setNextMissionItem()) {
if (!loadCurrentMissionItem()) {
setEndOfMissionItems();
return;
}
} else {
setEndOfMissionItems();
return;
}
}
if (item_contains_position(_mission_item)) {
handleTakeoff(new_work_item_type, next_mission_items, num_found_items);
@@ -92,6 +92,23 @@ void RtlMissionFast::setActiveMissionItems()
WorkItemType new_work_item_type{WorkItemType::WORK_ITEM_TYPE_DEFAULT};
position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet();
/* Skip VTOL/FW Takeoff item if in air, fixed-wing and didn't start the takeoff already*/
if ((_mission_item.nav_cmd == NAV_CMD_VTOL_TAKEOFF || _mission_item.nav_cmd == NAV_CMD_TAKEOFF) &&
(_work_item_type == WorkItemType::WORK_ITEM_TYPE_DEFAULT) &&
(_vehicle_status_sub.get().vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING) &&
!_land_detected_sub.get().landed) {
if (setNextMissionItem()) {
if (!loadCurrentMissionItem()) {
setEndOfMissionItems();
return;
}
} else {
setEndOfMissionItems();
return;
}
}
// Transition to fixed wing if necessary.
if (_vehicle_status_sub.get().vehicle_type == vehicle_status_s::VEHICLE_TYPE_ROTARY_WING &&
_vehicle_status_sub.get().is_vtol &&
@@ -369,6 +369,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();
@@ -415,6 +427,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;
@@ -157,6 +157,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)};
@@ -173,6 +174,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)};
@@ -183,6 +185,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{};
@@ -209,6 +212,8 @@ private:
float _air_density{atmosphere::kAirDensitySeaLevelStandardAtmos}; // [kg/m^3]
bool _is_in_att_ref_mode{false};
#if !defined(ENABLE_LOCKSTEP_SCHEDULER)
hrt_abstime _last_run_timestamp {0};
#endif // !ENABLE_LOCKSTEP_SCHEDULER