Skip to content
Snippets Groups Projects
Commit c416fc3f authored by Andreas Antener's avatar Andreas Antener Committed by Daniel Agar
Browse files

Tiltrotor:

- added open-loop transition time for airspeed-less flying
- added ramping down the back motors during forwards transition
parent 35740b0b
No related branches found
No related tags found
No related merge requests found
......@@ -35,6 +35,7 @@
* @file tiltrotor.cpp
*
* @author Roman Bapst <bapstroman@gmail.com>
* @author Andreas Antener <andreas@uaventure.com>
*
*/
......@@ -68,6 +69,7 @@ Tiltrotor::Tiltrotor(VtolAttitudeControl *attc) :
_params_handles_tiltrotor.elevons_mc_lock = param_find("VT_ELEV_MC_LOCK");
_params_handles_tiltrotor.front_trans_dur_p2 = param_find("VT_TRANS_P2_DUR");
_params_handles_tiltrotor.fw_motors_off = param_find("VT_FW_MOT_OFFID");
_params_handles_tiltrotor.airspeed_mode = param_find("FW_ARSP_MODE");
}
Tiltrotor::~Tiltrotor()
......@@ -128,6 +130,10 @@ Tiltrotor::parameters_update()
if (_params_tiltrotor.airspeed_trans < _params_tiltrotor.airspeed_blend_start + 1.0f) {
_params_tiltrotor.airspeed_trans = _params_tiltrotor.airspeed_blend_start + 1.0f;
}
/* airspeed mode */
param_get(_params_handles_tiltrotor.airspeed_mode, &l);
_params_tiltrotor.airspeed_mode = math::constrain(l, 0, 2);
}
int Tiltrotor::get_motor_off_channels(int channels)
......@@ -201,16 +207,27 @@ void Tiltrotor::update_vtol_state()
case FW_MODE:
break;
case TRANSITION_FRONT_P1:
case TRANSITION_FRONT_P1: {
// allow switch if we are not armed for the sake of bench testing
bool transition_to_p2 = can_transition_on_ground();
// check if we have reached airspeed to switch to fw mode
// also allow switch if we are not armed for the sake of bench testing
if (_airspeed->indicated_airspeed_m_s >= _params_tiltrotor.airspeed_trans || can_transition_on_ground()) {
_vtol_schedule.flight_mode = TRANSITION_FRONT_P2;
_vtol_schedule.transition_start = hrt_absolute_time();
}
// check if we have reached airspeed to switch to fw mode
transition_to_p2 |= _params_tiltrotor.airspeed_mode != control_state_s::AIRSPD_MODE_DISABLED &&
_airspeed->indicated_airspeed_m_s >= _params_tiltrotor.airspeed_trans &&
(float)hrt_elapsed_time(&_vtol_schedule.transition_start) > (_params->front_trans_time_min * 1e6f);
break;
// check if airspeed is invalid and transition by time
transition_to_p2 |= _params_tiltrotor.airspeed_mode == control_state_s::AIRSPD_MODE_DISABLED &&
_tilt_control > _params_tiltrotor.tilt_transition &&
(float)hrt_elapsed_time(&_vtol_schedule.transition_start) > (_params->front_trans_time_openloop * 1e6f);
if (transition_to_p2) {
_vtol_schedule.flight_mode = TRANSITION_FRONT_P2;
_vtol_schedule.transition_start = hrt_absolute_time();
}
break;
}
case TRANSITION_FRONT_P2:
......@@ -290,6 +307,8 @@ void Tiltrotor::update_fw_state()
void Tiltrotor::update_transition_state()
{
VtolType::update_transition_state();
if (!_flag_was_in_trans_mode) {
// save desired heading for transition and last thrust value
_flag_was_in_trans_mode = true;
......@@ -308,19 +327,25 @@ void Tiltrotor::update_transition_state()
&_vtol_schedule.transition_start) / (_params_tiltrotor.front_trans_dur * 1000000.0f);
}
// do blending of mc and fw controls
if (_airspeed->indicated_airspeed_m_s >= _params_tiltrotor.airspeed_blend_start) {
_mc_roll_weight = 0.0f;
bool use_airspeed = _params_tiltrotor.airspeed_mode != control_state_s::AIRSPD_MODE_DISABLED;
} else {
// at low speeds give full weight to mc
_mc_roll_weight = 1.0f;
// at low speeds give full weight to MC
_mc_roll_weight = 1.0f;
_mc_yaw_weight = 1.0f;
// reduce MC controls once the plane has picked up speed
if (use_airspeed && _airspeed->indicated_airspeed_m_s > ARSP_YAW_CTRL_DISABLE) {
_mc_yaw_weight = 0.0f;
}
// disable mc yaw control once the plane has picked up speed
_mc_yaw_weight = 1.0f;
if (use_airspeed && _airspeed->indicated_airspeed_m_s >= _params_tiltrotor.airspeed_blend_start) {
_mc_roll_weight = 0.0f;
}
if (_airspeed->indicated_airspeed_m_s > ARSP_YAW_CTRL_DISABLE) {
// without airspeed wait until half of open-loop time has passed
if (!use_airspeed
&& (float)hrt_elapsed_time(&_vtol_schedule.transition_start) > (_params->front_trans_time_openloop * 1e6f) / 2) {
_mc_roll_weight = 0.0f;
_mc_yaw_weight = 0.0f;
}
......@@ -331,7 +356,16 @@ void Tiltrotor::update_transition_state()
_tilt_control = _params_tiltrotor.tilt_transition +
fabsf(_params_tiltrotor.tilt_fw - _params_tiltrotor.tilt_transition) * (float)hrt_elapsed_time(
&_vtol_schedule.transition_start) / (_params_tiltrotor.front_trans_dur_p2 * 1000000.0f);
_mc_roll_weight = 0.0f;
_mc_yaw_weight = 0.0f;
// ramp down rear motors (setting MAX_PWM down scales the given output into the new range)
int rear_value = (1.0f - (float)hrt_elapsed_time(&_vtol_schedule.transition_start) /
(_params_tiltrotor.front_trans_dur_p2 *
1000000.0f)) * (float)(PWM_DEFAULT_MAX - PWM_DEFAULT_MIN) + (float)PWM_DEFAULT_MIN;
set_rear_motor_state(VALUE, rear_value);
_thrust_transition = _mc_virtual_att_sp->thrust;
......@@ -395,12 +429,12 @@ void Tiltrotor::fill_actuator_outputs()
}
_actuators_out_1->timestamp = _actuators_fw_in->timestamp;
_actuators_out_1->control[actuator_controls_s::INDEX_ROLL] = -_actuators_fw_in->control[actuator_controls_s::INDEX_ROLL]
* (1 - _mc_roll_weight);
_actuators_out_1->control[actuator_controls_s::INDEX_ROLL] =
-_actuators_fw_in->control[actuator_controls_s::INDEX_ROLL];
_actuators_out_1->control[actuator_controls_s::INDEX_PITCH] =
(_actuators_fw_in->control[actuator_controls_s::INDEX_PITCH] + _params->fw_pitch_trim) * (1 - _mc_pitch_weight);
_actuators_out_1->control[actuator_controls_s::INDEX_YAW] = _actuators_fw_in->control[actuator_controls_s::INDEX_YAW]
* (1 - _mc_yaw_weight); // yaw
(_actuators_fw_in->control[actuator_controls_s::INDEX_PITCH] + _params->fw_pitch_trim);
_actuators_out_1->control[actuator_controls_s::INDEX_YAW] =
_actuators_fw_in->control[actuator_controls_s::INDEX_YAW]; // yaw
_actuators_out_1->control[4] = _tilt_control;
}
......@@ -409,7 +443,7 @@ void Tiltrotor::fill_actuator_outputs()
* Set state of rear motors.
*/
void Tiltrotor::set_rear_motor_state(rear_motor_state state)
void Tiltrotor::set_rear_motor_state(rear_motor_state state, int value)
{
int pwm_value = PWM_DEFAULT_MAX;
......@@ -429,6 +463,11 @@ void Tiltrotor::set_rear_motor_state(rear_motor_state state)
pwm_value = _params->idle_pwm_mc;
_rear_motors = IDLE;
break;
case VALUE:
pwm_value = value;
_rear_motors = VALUE;
break;
}
int ret;
......@@ -457,7 +496,9 @@ void Tiltrotor::set_rear_motor_state(rear_motor_state state)
ret = px4_ioctl(fd, PWM_SERVO_SET_MAX_PWM, (long unsigned int)&pwm_max_values);
if (ret != OK) {PX4_WARN("failed setting max values");}
if (ret != OK) {
PX4_WARN("failed setting max values");
}
px4_close(fd);
}
......
......@@ -72,6 +72,7 @@ private:
int elevons_mc_lock; /**< lock elevons in multicopter mode */
float front_trans_dur_p2;
int fw_motors_off; /**< bitmask of all motors that should be off in fixed wing mode */
int airspeed_mode;
} _params_tiltrotor;
struct {
......@@ -85,6 +86,7 @@ private:
param_t elevons_mc_lock;
param_t front_trans_dur_p2;
param_t fw_motors_off;
param_t airspeed_mode;
} _params_handles_tiltrotor;
enum vtol_mode {
......@@ -103,7 +105,8 @@ private:
enum rear_motor_state {
ENABLED = 0,
DISABLED,
IDLE
IDLE,
VALUE
} _rear_motors;
struct {
......@@ -128,7 +131,7 @@ private:
/**
* Adjust the state of the rear motors. In fw mode they shouldn't spin.
*/
void set_rear_motor_state(rear_motor_state state);
void set_rear_motor_state(rear_motor_state state, int value = 0);
/**
* Update parameters.
......
......@@ -132,6 +132,8 @@ VtolAttitudeControl::VtolAttitudeControl() :
_params_handles.vtol_type = param_find("VT_TYPE");
_params_handles.elevons_mc_lock = param_find("VT_ELEV_MC_LOCK");
_params_handles.fw_min_alt = param_find("VT_FW_MIN_ALT");
_params_handles.front_trans_time_openloop = param_find("VT_F_TR_OL_TM");
_params_handles.front_trans_time_min = param_find("VT_TRANS_MIN_TM");
/* fetch initial parameter values */
parameters_update();
......@@ -560,6 +562,16 @@ VtolAttitudeControl::parameters_update()
param_get(_params_handles.fw_min_alt, &v);
_params.fw_min_alt = v;
param_get(_params_handles.front_trans_time_openloop, &_params.front_trans_time_openloop);
param_get(_params_handles.front_trans_time_min, &_params.front_trans_time_min);
/*
* Minimum transition time can be maximum 90 percent of the open loop transition time,
* anything else makes no sense and can potentially lead to numerical problems.
*/
_params.front_trans_time_min = math::min(_params.front_trans_time_openloop * 0.9f,
_params.front_trans_time_min);
// update the parameters of the instances of base VtolType
if (_vtol_type != nullptr) {
......
......@@ -210,6 +210,8 @@ private:
param_t vtol_type;
param_t elevons_mc_lock;
param_t fw_min_alt;
param_t front_trans_time_openloop;
param_t front_trans_time_min;
} _params_handles;
/* for multicopters it is usual to have a non-zero idle speed of the engines
......
......@@ -60,6 +60,8 @@ struct Params {
int vtol_type;
int elevons_mc_lock; // lock elevons in multicopter mode
float fw_min_alt; // minimum relative altitude for FW mode (QuadChute)
float front_trans_time_openloop;
float front_trans_time_min;
};
// Has to match 1:1 msg/vtol_vehicle_status.msg
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment