Fixed-wing Position controller: add modes for auto altitude and auto descend

- bit of clean up
- add GPS failsafe mode auto_altitude, that will keep current altitude with a fixed-bank angle
for some time, then switches to auto_descend that will descend with constant sink rate
of 0.5m/s
- params controlling GPS failsafe are not FW params: NAV_GPSF_R --> FW_GPSF_R and
NAV_GPSF_LT --> FW_GPSF_LT

Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
This commit is contained in:
Silvan Fuhrer
2021-10-25 11:48:05 +02:00
committed by Roman Bapst
parent c73a1b4c68
commit b77487d69c
4 changed files with 197 additions and 43 deletions
@@ -236,7 +236,6 @@ FixedwingPositionControl::vehicle_command_poll()
abort_landing(true);
}
}
}
}
@@ -493,7 +492,7 @@ FixedwingPositionControl::status_publish()
pos_ctrl_status.timestamp = hrt_absolute_time();
pos_ctrl_status.type = _type;
pos_ctrl_status.type = _position_sp_type;
_pos_ctrl_status_pub.publish(pos_ctrl_status);
}
@@ -671,7 +670,7 @@ FixedwingPositionControl::do_takeoff_help(float *hold_altitude, float *pitch_lim
}
void
FixedwingPositionControl::set_control_mode_current(bool pos_sp_curr_valid)
FixedwingPositionControl::set_control_mode_current(const hrt_abstime &now, bool pos_sp_curr_valid)
{
/* only run position controller in fixed-wing mode and during transitions for VTOL */
if (_vehicle_status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_ROTARY_WING && !_vehicle_status.in_transition_mode) {
@@ -679,11 +678,41 @@ FixedwingPositionControl::set_control_mode_current(bool pos_sp_curr_valid)
return; // do not publish the setpoint
}
if ((_control_mode.flag_control_auto_enabled || _control_mode.flag_control_offboard_enabled) && pos_sp_curr_valid) {
if (((_control_mode.flag_control_auto_enabled && _control_mode.flag_control_position_enabled) ||
_control_mode.flag_control_offboard_enabled) && pos_sp_curr_valid) {
_control_mode_current = FW_POSCTRL_MODE_AUTO;
} else if (_control_mode.flag_control_velocity_enabled && _control_mode.flag_control_altitude_enabled) {
if (_control_mode_current != FW_POSCTRL_MODE_POSITION) {
} else if (_control_mode.flag_control_auto_enabled && _control_mode.flag_control_climb_rate_enabled) {
// reset timer the first time we switch into this mode
if (_control_mode_current != FW_POSCTRL_MODE_AUTO_ALTITUDE && _control_mode_current != FW_POSCTRL_MODE_AUTO_CLIMBRATE) {
_time_in_fixed_bank_loiter = now;
}
if (hrt_elapsed_time(&_time_in_fixed_bank_loiter) < (_param_nav_gpsf_lt.get() * 1_s)
&& !_vehicle_status.in_transition_mode) {
if (_control_mode_current != FW_POSCTRL_MODE_AUTO_ALTITUDE) {
// Need to init because last loop iteration was in a different mode
_hold_alt = _current_altitude;
mavlink_log_critical(&_mavlink_log_pub, "Start loiter with fixed bank angle.\t");
events::send(events::ID("fixedwing_position_control_fb_loiter"), events::Log::Critical,
"Start loiter with fixed bank angle");
}
_control_mode_current = FW_POSCTRL_MODE_AUTO_ALTITUDE;
} else {
if (_control_mode_current != FW_POSCTRL_MODE_AUTO_CLIMBRATE && !_vehicle_status.in_transition_mode) {
mavlink_log_critical(&_mavlink_log_pub, "Start descending.\t");
events::send(events::ID("fixedwing_position_control_descend"), events::Log::Critical, "Start descending");
}
_control_mode_current = FW_POSCTRL_MODE_AUTO_CLIMBRATE;
}
} else if (_control_mode.flag_control_manual_enabled && _control_mode.flag_control_position_enabled) {
if (_control_mode_current != FW_POSCTRL_MODE_MANUAL_POSITION) {
/* Need to init because last loop iteration was in a different mode */
_hold_alt = _current_altitude;
_hdg_hold_yaw = _yaw; // yaw is not controlled, so set setpoint to current yaw
@@ -696,15 +725,16 @@ FixedwingPositionControl::set_control_mode_current(bool pos_sp_curr_valid)
_att_sp.yaw_body = _yaw; // yaw is not controlled, so set setpoint to current yaw
}
_control_mode_current = FW_POSCTRL_MODE_POSITION;
_control_mode_current = FW_POSCTRL_MODE_MANUAL_POSITION;
} else if (_control_mode.flag_control_altitude_enabled) {
if (_control_mode_current != FW_POSCTRL_MODE_POSITION && _control_mode_current != FW_POSCTRL_MODE_ALTITUDE) {
} else if (_control_mode.flag_control_manual_enabled && _control_mode.flag_control_altitude_enabled) {
if (_control_mode_current != FW_POSCTRL_MODE_MANUAL_POSITION
&& _control_mode_current != FW_POSCTRL_MODE_MANUAL_ALTITUDE) {
/* Need to init because last loop iteration was in a different mode */
_hold_alt = _current_altitude;
}
_control_mode_current = FW_POSCTRL_MODE_ALTITUDE;
_control_mode_current = FW_POSCTRL_MODE_MANUAL_ALTITUDE;
} else {
_control_mode_current = FW_POSCTRL_MODE_OTHER;
@@ -724,9 +754,6 @@ FixedwingPositionControl::control_auto(const hrt_abstime &now, const Vector2d &c
_att_sp.fw_control_yaw = false; // by default we don't want yaw to be contoller directly with rudder
_att_sp.apply_flaps = vehicle_attitude_setpoint_s::FLAPS_OFF; // by default we don't use flaps
/* no throttle limit as default */
float throttle_max = 1.0f;
/* save time when airplane is in air */
if (!_was_in_air && !_landed) {
_was_in_air = true;
@@ -767,11 +794,9 @@ FixedwingPositionControl::control_auto(const hrt_abstime &now, const Vector2d &c
publishOrbitStatus(pos_sp_curr);
}
const uint8_t position_sp_type = handle_setpoint_type(pos_sp_curr.type, pos_sp_curr);
_position_sp_type = handle_setpoint_type(pos_sp_curr.type, pos_sp_curr);
_type = position_sp_type; // for publication
switch (position_sp_type) {
switch (_position_sp_type) {
case position_setpoint_s::SETPOINT_TYPE_IDLE:
_att_sp.thrust_body[0] = 0.0f;
_att_sp.roll_body = 0.0f;
@@ -796,12 +821,12 @@ FixedwingPositionControl::control_auto(const hrt_abstime &now, const Vector2d &c
}
/* reset landing state */
if (position_sp_type != position_setpoint_s::SETPOINT_TYPE_LAND) {
if (_position_sp_type != position_setpoint_s::SETPOINT_TYPE_LAND) {
reset_landing_state();
}
/* reset takeoff/launch state */
if (position_sp_type != position_setpoint_s::SETPOINT_TYPE_TAKEOFF) {
if (_position_sp_type != position_setpoint_s::SETPOINT_TYPE_TAKEOFF) {
reset_takeoff_state();
}
@@ -823,7 +848,7 @@ FixedwingPositionControl::control_auto(const hrt_abstime &now, const Vector2d &c
} else if (pos_sp_curr.type == position_setpoint_s::SETPOINT_TYPE_TAKEOFF &&
_runway_takeoff.runwayTakeoffEnabled()) {
_att_sp.thrust_body[0] = _runway_takeoff.getThrottle(now, min(get_tecs_thrust(), throttle_max));
_att_sp.thrust_body[0] = _runway_takeoff.getThrottle(now, get_tecs_thrust());
} else if (pos_sp_curr.type == position_setpoint_s::SETPOINT_TYPE_IDLE) {
@@ -833,10 +858,10 @@ FixedwingPositionControl::control_auto(const hrt_abstime &now, const Vector2d &c
/* Copy thrust and pitch values from tecs */
if (_landed) {
// when we are landed state we want the motor to spin at idle speed
_att_sp.thrust_body[0] = min(_param_fw_thr_idle.get(), throttle_max);
_att_sp.thrust_body[0] = min(_param_fw_thr_idle.get(), 1.f);
} else {
_att_sp.thrust_body[0] = min(get_tecs_thrust(), throttle_max);
_att_sp.thrust_body[0] = get_tecs_thrust();
}
}
@@ -854,8 +879,68 @@ FixedwingPositionControl::control_auto(const hrt_abstime &now, const Vector2d &c
if (use_tecs_pitch) {
_att_sp.pitch_body = get_tecs_pitch();
}
}
_last_manual = !_control_mode.flag_control_position_enabled;
void
FixedwingPositionControl::control_auto_fixed_bank_alt_hold(const hrt_abstime &now)
{
// only control altitude and airspeed ("fixed-bank loiter")
tecs_update_pitch_throttle(now, _hold_alt,
_param_fw_airspd_trim.get(),
radians(_param_fw_p_lim_min.get()),
radians(_param_fw_p_lim_max.get()),
_param_fw_thr_min.get(),
_param_fw_thr_max.get(),
_param_fw_thr_cruise.get(),
false,
_param_fw_p_lim_min.get());
_att_sp.roll_body = math::radians(_param_nav_gpsf_r.get()); // open loop loiter bank angle
_att_sp.yaw_body = 0.f;
if (_landed) {
_att_sp.thrust_body[0] = _param_fw_thr_min.get();
} else {
_att_sp.thrust_body[0] = min(get_tecs_thrust(), _param_fw_thr_max.get());
}
_att_sp.pitch_body = get_tecs_pitch();
}
void
FixedwingPositionControl::control_auto_descend(const hrt_abstime &now)
{
// only control height rate
// Hard-code descend rate to 0.5m/s. This is a compromise to give the system to recover,
// but not letting it drift too far away.
const float descend_rate = -0.5f;
tecs_update_pitch_throttle(now, _hold_alt,
_param_fw_airspd_trim.get(),
radians(_param_fw_p_lim_min.get()),
radians(_param_fw_p_lim_max.get()),
_param_fw_thr_min.get(),
_param_fw_thr_max.get(),
_param_fw_thr_cruise.get(),
false,
_param_fw_p_lim_min.get(),
tecs_status_s::TECS_MODE_NORMAL,
descend_rate);
_att_sp.roll_body = math::radians(_param_nav_gpsf_r.get()); // open loop loiter bank angle
_att_sp.yaw_body = 0.f;
if (_landed) {
_att_sp.thrust_body[0] = _param_fw_thr_min.get();
} else {
_att_sp.thrust_body[0] = min(get_tecs_thrust(), _param_fw_thr_max.get());
}
_att_sp.pitch_body = get_tecs_pitch();
}
uint8_t
@@ -927,6 +1012,11 @@ FixedwingPositionControl::handle_setpoint_type(const uint8_t setpoint_type, cons
}
}
// set to type loiter during VTOL transitions in Land mode (to not start FW landing logic)
if (pos_sp_curr.type == position_setpoint_s::SETPOINT_TYPE_LAND && _vehicle_status.in_transition_mode) {
position_sp_type = position_setpoint_s::SETPOINT_TYPE_LOITER;
}
return position_sp_type;
}
@@ -1641,7 +1731,7 @@ FixedwingPositionControl::control_auto_landing(const hrt_abstime &now, const Vec
}
void
FixedwingPositionControl::control_altitude(const hrt_abstime &now, const Vector2d &curr_pos,
FixedwingPositionControl::control_manual_altitude(const hrt_abstime &now, const Vector2d &curr_pos,
const Vector2f &ground_speed)
{
/* ALTITUDE CONTROL: pitch stick moves altitude setpoint, throttle stick sets airspeed */
@@ -1693,12 +1783,10 @@ FixedwingPositionControl::control_altitude(const hrt_abstime &now, const Vector2
}
_att_sp.pitch_body = get_tecs_pitch();
_last_manual = !_control_mode.flag_control_position_enabled;
}
void
FixedwingPositionControl::control_position(const hrt_abstime &now, const Vector2d &curr_pos,
FixedwingPositionControl::control_manual_position(const hrt_abstime &now, const Vector2d &curr_pos,
const Vector2f &ground_speed)
{
const float dt = math::constrain((now - _control_position_last_called) * 1e-6f, 0.01f, 0.05f);
@@ -1813,8 +1901,6 @@ FixedwingPositionControl::control_position(const hrt_abstime &now, const Vector2
}
_att_sp.pitch_body = get_tecs_pitch();
_last_manual = !_control_mode.flag_control_position_enabled;
}
float
@@ -1832,7 +1918,7 @@ float
FixedwingPositionControl::get_tecs_thrust()
{
if (_is_tecs_running) {
return _tecs.get_throttle_setpoint();
return min(_tecs.get_throttle_setpoint(), 1.f);
}
// return 0 to prevent stale tecs state when it's not running
@@ -1959,7 +2045,7 @@ FixedwingPositionControl::Run()
Vector2d curr_pos(_current_latitude, _current_longitude);
Vector2f ground_speed(_local_pos.vx, _local_pos.vy);
set_control_mode_current(_pos_sp_triplet.current.valid);
set_control_mode_current(_local_pos.timestamp, _pos_sp_triplet.current.valid);
switch (_control_mode_current) {
case FW_POSCTRL_MODE_AUTO: {
@@ -1968,13 +2054,23 @@ FixedwingPositionControl::Run()
break;
}
case FW_POSCTRL_MODE_POSITION: {
control_position(_local_pos.timestamp, curr_pos, ground_speed);
case FW_POSCTRL_MODE_AUTO_ALTITUDE: {
control_auto_fixed_bank_alt_hold(_local_pos.timestamp);
break;
}
case FW_POSCTRL_MODE_ALTITUDE: {
control_altitude(_local_pos.timestamp, curr_pos, ground_speed);
case FW_POSCTRL_MODE_AUTO_CLIMBRATE: {
control_auto_descend(_local_pos.timestamp);
break;
}
case FW_POSCTRL_MODE_MANUAL_POSITION: {
control_manual_position(_local_pos.timestamp, curr_pos, ground_speed);
break;
}
case FW_POSCTRL_MODE_MANUAL_ALTITUDE: {
control_manual_altitude(_local_pos.timestamp, curr_pos, ground_speed);
break;
}
@@ -2008,7 +2104,8 @@ FixedwingPositionControl::Run()
if (_control_mode.flag_control_position_enabled ||
_control_mode.flag_control_velocity_enabled ||
_control_mode.flag_control_acceleration_enabled ||
_control_mode.flag_control_altitude_enabled) {
_control_mode.flag_control_altitude_enabled ||
_control_mode.flag_control_climb_rate_enabled) {
const Quatf q(Eulerf(_att_sp.roll_body, _att_sp.pitch_body, _att_sp.yaw_body));
q.copyTo(_att_sp.q_d);
@@ -2025,6 +2122,7 @@ FixedwingPositionControl::Run()
}
_l1_control.reset_has_guidance_updated();
_last_manual = !_control_mode.flag_control_position_enabled;
}
perf_end(_loop_perf);
@@ -2168,7 +2266,8 @@ FixedwingPositionControl::tecs_update_pitch_throttle(const hrt_abstime &now, flo
bool in_air_alt_control = (!_landed &&
(_control_mode.flag_control_auto_enabled ||
_control_mode.flag_control_velocity_enabled ||
_control_mode.flag_control_altitude_enabled));
_control_mode.flag_control_altitude_enabled ||
_control_mode.flag_control_climb_rate_enabled));
/* update TECS vehicle state estimates */
_tecs.update_vehicle_state_estimates(_airspeed, _body_acceleration(0), (_local_pos.timestamp > 0), in_air_alt_control,