mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-06-02 11:59:17 +08:00
Compensate VTOL transition time for air density (#19293)
* vtol: compensate front transition minimum time and front transiton openloop time for air density Signed-off-by: RomanBapst <bapstroman@gmail.com>
This commit is contained in:
@@ -179,7 +179,7 @@ void Standard::update_vtol_state()
|
|||||||
|
|
||||||
const bool airspeed_triggers_transition = PX4_ISFINITE(_airspeed_validated->calibrated_airspeed_m_s)
|
const bool airspeed_triggers_transition = PX4_ISFINITE(_airspeed_validated->calibrated_airspeed_m_s)
|
||||||
&& !_params->airspeed_disabled;
|
&& !_params->airspeed_disabled;
|
||||||
const bool minimum_trans_time_elapsed = time_since_trans_start > _params->front_trans_time_min;
|
const bool minimum_trans_time_elapsed = time_since_trans_start > getMinimumFrontTransitionTime();
|
||||||
|
|
||||||
bool transition_to_fw = false;
|
bool transition_to_fw = false;
|
||||||
|
|
||||||
@@ -261,14 +261,14 @@ void Standard::update_transition_state()
|
|||||||
PX4_ISFINITE(_airspeed_validated->calibrated_airspeed_m_s) &&
|
PX4_ISFINITE(_airspeed_validated->calibrated_airspeed_m_s) &&
|
||||||
_airspeed_validated->calibrated_airspeed_m_s > 0.0f &&
|
_airspeed_validated->calibrated_airspeed_m_s > 0.0f &&
|
||||||
_airspeed_validated->calibrated_airspeed_m_s >= _params->airspeed_blend &&
|
_airspeed_validated->calibrated_airspeed_m_s >= _params->airspeed_blend &&
|
||||||
time_since_trans_start > _params->front_trans_time_min) {
|
time_since_trans_start > getMinimumFrontTransitionTime()) {
|
||||||
|
|
||||||
mc_weight = 1.0f - fabsf(_airspeed_validated->calibrated_airspeed_m_s - _params->airspeed_blend) /
|
mc_weight = 1.0f - fabsf(_airspeed_validated->calibrated_airspeed_m_s - _params->airspeed_blend) /
|
||||||
_airspeed_trans_blend_margin;
|
_airspeed_trans_blend_margin;
|
||||||
// time based blending when no airspeed sensor is set
|
// time based blending when no airspeed sensor is set
|
||||||
|
|
||||||
} else if (_params->airspeed_disabled || !PX4_ISFINITE(_airspeed_validated->calibrated_airspeed_m_s)) {
|
} else if (_params->airspeed_disabled || !PX4_ISFINITE(_airspeed_validated->calibrated_airspeed_m_s)) {
|
||||||
mc_weight = 1.0f - time_since_trans_start / _params->front_trans_time_min;
|
mc_weight = 1.0f - time_since_trans_start / getMinimumFrontTransitionTime();
|
||||||
mc_weight = math::constrain(2.0f * mc_weight, 0.0f, 1.0f);
|
mc_weight = math::constrain(2.0f * mc_weight, 0.0f, 1.0f);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,13 +180,13 @@ void Tiltrotor::update_vtol_state()
|
|||||||
|
|
||||||
bool transition_to_p2 = false;
|
bool transition_to_p2 = false;
|
||||||
|
|
||||||
if (time_since_trans_start > _params->front_trans_time_min) {
|
if (time_since_trans_start > getMinimumFrontTransitionTime()) {
|
||||||
if (airspeed_triggers_transition) {
|
if (airspeed_triggers_transition) {
|
||||||
transition_to_p2 = _airspeed_validated->calibrated_airspeed_m_s >= _params->transition_airspeed;
|
transition_to_p2 = _airspeed_validated->calibrated_airspeed_m_s >= _params->transition_airspeed;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
transition_to_p2 = _tilt_control >= _params_tiltrotor.tilt_transition &&
|
transition_to_p2 = _tilt_control >= _params_tiltrotor.tilt_transition &&
|
||||||
time_since_trans_start > _params->front_trans_time_openloop;;
|
time_since_trans_start > getOpenLoopFrontTransitionTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,9 +359,9 @@ void Tiltrotor::update_transition_state()
|
|||||||
|
|
||||||
// without airspeed do timed weight changes
|
// without airspeed do timed weight changes
|
||||||
if ((_params->airspeed_disabled || !PX4_ISFINITE(_airspeed_validated->calibrated_airspeed_m_s)) &&
|
if ((_params->airspeed_disabled || !PX4_ISFINITE(_airspeed_validated->calibrated_airspeed_m_s)) &&
|
||||||
time_since_trans_start > _params->front_trans_time_min) {
|
time_since_trans_start > getMinimumFrontTransitionTime()) {
|
||||||
_mc_roll_weight = 1.0f - (time_since_trans_start - _params->front_trans_time_min) /
|
_mc_roll_weight = 1.0f - (time_since_trans_start - getMinimumFrontTransitionTime()) /
|
||||||
(_params->front_trans_time_openloop - _params->front_trans_time_min);
|
(getOpenLoopFrontTransitionTime() - getMinimumFrontTransitionTime());
|
||||||
_mc_yaw_weight = _mc_roll_weight;
|
_mc_yaw_weight = _mc_roll_weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -460,6 +460,12 @@ VtolAttitudeControl::Run()
|
|||||||
action_request_poll();
|
action_request_poll();
|
||||||
vehicle_cmd_poll();
|
vehicle_cmd_poll();
|
||||||
|
|
||||||
|
vehicle_air_data_s air_data;
|
||||||
|
|
||||||
|
if (_vehicle_air_data_sub.update(&air_data)) {
|
||||||
|
_air_density = air_data.rho;
|
||||||
|
}
|
||||||
|
|
||||||
// check if mc and fw sp were updated
|
// check if mc and fw sp were updated
|
||||||
bool mc_att_sp_updated = _mc_virtual_att_sp_sub.update(&_mc_virtual_att_sp);
|
bool mc_att_sp_updated = _mc_virtual_att_sp_sub.update(&_mc_virtual_att_sp);
|
||||||
bool fw_att_sp_updated = _fw_virtual_att_sp_sub.update(&_fw_virtual_att_sp);
|
bool fw_att_sp_updated = _fw_virtual_att_sp_sub.update(&_fw_virtual_att_sp);
|
||||||
|
|||||||
@@ -68,6 +68,7 @@
|
|||||||
#include <uORB/topics/action_request.h>
|
#include <uORB/topics/action_request.h>
|
||||||
#include <uORB/topics/actuator_controls.h>
|
#include <uORB/topics/actuator_controls.h>
|
||||||
#include <uORB/topics/airspeed_validated.h>
|
#include <uORB/topics/airspeed_validated.h>
|
||||||
|
#include <uORB/topics/vehicle_air_data.h>
|
||||||
#include <uORB/topics/parameter_update.h>
|
#include <uORB/topics/parameter_update.h>
|
||||||
#include <uORB/topics/position_setpoint_triplet.h>
|
#include <uORB/topics/position_setpoint_triplet.h>
|
||||||
#include <uORB/topics/tecs_status.h>
|
#include <uORB/topics/tecs_status.h>
|
||||||
@@ -125,6 +126,8 @@ public:
|
|||||||
bool get_immediate_transition() {return _immediate_transition;}
|
bool get_immediate_transition() {return _immediate_transition;}
|
||||||
void reset_immediate_transition() {_immediate_transition = false;}
|
void reset_immediate_transition() {_immediate_transition = false;}
|
||||||
|
|
||||||
|
float getAirDensity() const { return _air_density; }
|
||||||
|
|
||||||
struct actuator_controls_s *get_actuators_fw_in() {return &_actuators_fw_in;}
|
struct actuator_controls_s *get_actuators_fw_in() {return &_actuators_fw_in;}
|
||||||
struct actuator_controls_s *get_actuators_mc_in() {return &_actuators_mc_in;}
|
struct actuator_controls_s *get_actuators_mc_in() {return &_actuators_mc_in;}
|
||||||
struct actuator_controls_s *get_actuators_out0() {return &_actuators_out_0;}
|
struct actuator_controls_s *get_actuators_out0() {return &_actuators_out_0;}
|
||||||
@@ -159,6 +162,7 @@ private:
|
|||||||
|
|
||||||
uORB::Subscription _action_request_sub{ORB_ID(action_request)};
|
uORB::Subscription _action_request_sub{ORB_ID(action_request)};
|
||||||
uORB::Subscription _airspeed_validated_sub{ORB_ID(airspeed_validated)}; // airspeed subscription
|
uORB::Subscription _airspeed_validated_sub{ORB_ID(airspeed_validated)}; // airspeed subscription
|
||||||
|
uORB::Subscription _vehicle_air_data_sub{ORB_ID(vehicle_air_data)};
|
||||||
uORB::Subscription _fw_virtual_att_sp_sub{ORB_ID(fw_virtual_attitude_setpoint)};
|
uORB::Subscription _fw_virtual_att_sp_sub{ORB_ID(fw_virtual_attitude_setpoint)};
|
||||||
uORB::Subscription _land_detected_sub{ORB_ID(vehicle_land_detected)};
|
uORB::Subscription _land_detected_sub{ORB_ID(vehicle_land_detected)};
|
||||||
uORB::Subscription _local_pos_sp_sub{ORB_ID(vehicle_local_position_setpoint)}; // setpoint subscription
|
uORB::Subscription _local_pos_sp_sub{ORB_ID(vehicle_local_position_setpoint)}; // setpoint subscription
|
||||||
@@ -206,6 +210,8 @@ private:
|
|||||||
vehicle_local_position_setpoint_s _local_pos_sp{};
|
vehicle_local_position_setpoint_s _local_pos_sp{};
|
||||||
vtol_vehicle_status_s _vtol_vehicle_status{};
|
vtol_vehicle_status_s _vtol_vehicle_status{};
|
||||||
|
|
||||||
|
float _air_density{CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C}; // [kg/m^3]
|
||||||
|
|
||||||
Params _params{}; // struct holding the parameters
|
Params _params{}; // struct holding the parameters
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -648,3 +648,32 @@ float VtolType::pusher_assist()
|
|||||||
return forward_thrust;
|
return forward_thrust;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float VtolType::getFrontTransitionTimeFactor() const
|
||||||
|
{
|
||||||
|
// assumptions: transition_time = transition_true_airspeed / average_acceleration (thrust)
|
||||||
|
// transition_true_airspeed ~ sqrt(rho0 / rh0)
|
||||||
|
// average_acceleration ~ rho / rho0
|
||||||
|
// transition_time ~ sqrt(rho0/rh0) * rho0 / rho
|
||||||
|
|
||||||
|
// low value: hot day at 4000m AMSL with some margin
|
||||||
|
// high value: cold day at 0m AMSL with some margin
|
||||||
|
const float rho = math::constrain(_attc->getAirDensity(), 0.7f, 1.5f);
|
||||||
|
|
||||||
|
if (PX4_ISFINITE(rho)) {
|
||||||
|
float rho0_over_rho = CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C / rho;
|
||||||
|
return sqrtf(rho0_over_rho) * rho0_over_rho;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float VtolType::getMinimumFrontTransitionTime() const
|
||||||
|
{
|
||||||
|
return getFrontTransitionTimeFactor() * _params->front_trans_time_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
float VtolType::getOpenLoopFrontTransitionTime() const
|
||||||
|
{
|
||||||
|
return getFrontTransitionTimeFactor() * _params->front_trans_time_openloop;
|
||||||
|
}
|
||||||
|
|||||||
@@ -195,6 +195,16 @@ public:
|
|||||||
|
|
||||||
bool was_in_trans_mode() {return _flag_was_in_trans_mode;}
|
bool was_in_trans_mode() {return _flag_was_in_trans_mode;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Minimum front transition time scaled for air density (if available) [s]
|
||||||
|
*/
|
||||||
|
float getMinimumFrontTransitionTime() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Minimum open-loop front transition time scaled for air density (if available) [s]
|
||||||
|
*/
|
||||||
|
float getOpenLoopFrontTransitionTime() const;
|
||||||
|
|
||||||
virtual void parameters_update() = 0;
|
virtual void parameters_update() = 0;
|
||||||
|
|
||||||
VtolAttitudeControl *_attc;
|
VtolAttitudeControl *_attc;
|
||||||
@@ -329,6 +339,11 @@ private:
|
|||||||
|
|
||||||
void stopBlendingThrottleAfterFrontTransition() { _throttle_blend_start_ts = 0; }
|
void stopBlendingThrottleAfterFrontTransition() { _throttle_blend_start_ts = 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Transition time scale factor for density.
|
||||||
|
*/
|
||||||
|
float getFrontTransitionTimeFactor() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user