2019-01-15 13:46:13 -04:00
|
|
|
#include "mode.h"
|
|
|
|
#include "Plane.h"
|
|
|
|
|
2021-09-10 03:28:21 -03:00
|
|
|
#if HAL_QUADPLANE_ENABLED
|
|
|
|
|
2019-01-15 13:46:13 -04:00
|
|
|
bool ModeQLoiter::_enter()
|
2021-08-14 15:56:40 -03:00
|
|
|
{
|
|
|
|
// initialise loiter
|
|
|
|
loiter_nav->clear_pilot_desired_acceleration();
|
|
|
|
loiter_nav->init_target();
|
|
|
|
|
|
|
|
// set vertical speed and acceleration limits
|
2024-01-18 22:40:25 -04:00
|
|
|
pos_control->set_max_speed_accel_z(-quadplane.get_pilot_velocity_z_max_dn(), quadplane.pilot_speed_z_max_up*100, quadplane.pilot_accel_z*100);
|
|
|
|
pos_control->set_correction_speed_accel_z(-quadplane.get_pilot_velocity_z_max_dn(), quadplane.pilot_speed_z_max_up*100, quadplane.pilot_accel_z*100);
|
2021-08-14 15:56:40 -03:00
|
|
|
|
|
|
|
quadplane.init_throttle_wait();
|
|
|
|
|
|
|
|
// prevent re-init of target position
|
|
|
|
quadplane.last_loiter_ms = AP_HAL::millis();
|
2024-03-07 01:05:41 -04:00
|
|
|
|
|
|
|
// clear precland timestamp
|
|
|
|
last_target_loc_set_ms = 0;
|
|
|
|
|
2021-09-04 16:21:04 -03:00
|
|
|
return true;
|
2021-08-14 15:56:40 -03:00
|
|
|
}
|
|
|
|
|
2019-01-15 13:46:13 -04:00
|
|
|
void ModeQLoiter::update()
|
|
|
|
{
|
|
|
|
plane.mode_qstabilize.update();
|
|
|
|
}
|
|
|
|
|
2021-08-14 15:56:40 -03:00
|
|
|
// run quadplane loiter controller
|
|
|
|
void ModeQLoiter::run()
|
|
|
|
{
|
2023-05-01 22:05:00 -03:00
|
|
|
const uint32_t now = AP_HAL::millis();
|
2024-03-07 01:05:41 -04:00
|
|
|
|
|
|
|
#if AC_PRECLAND_ENABLED
|
|
|
|
const uint32_t precland_timeout_ms = 250;
|
|
|
|
/*
|
|
|
|
see if precision landing or precision loiter is active with
|
|
|
|
an override of the target location.
|
|
|
|
|
|
|
|
*/
|
|
|
|
const uint32_t last_pos_set_ms = last_target_loc_set_ms;
|
|
|
|
const uint32_t last_vel_set_ms = quadplane.poscontrol.last_velocity_match_ms;
|
|
|
|
|
|
|
|
if (last_pos_set_ms != 0 && now - last_pos_set_ms < precland_timeout_ms) {
|
|
|
|
// we have an active landing target override
|
|
|
|
Vector2f rel_origin;
|
|
|
|
if (plane.next_WP_loc.get_vector_xy_from_origin_NE(rel_origin)) {
|
|
|
|
quadplane.pos_control->set_pos_target_xy_cm(rel_origin.x, rel_origin.y);
|
|
|
|
last_target_loc_set_ms = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// allow for velocity override as well
|
|
|
|
if (last_vel_set_ms != 0 && now - last_vel_set_ms < precland_timeout_ms) {
|
|
|
|
// we have an active landing velocity override
|
|
|
|
Vector2f target_accel;
|
|
|
|
Vector2f target_speed_xy_cms{quadplane.poscontrol.velocity_match.x*100, quadplane.poscontrol.velocity_match.y*100};
|
|
|
|
quadplane.pos_control->input_vel_accel_xy(target_speed_xy_cms, target_accel);
|
|
|
|
quadplane.poscontrol.last_velocity_match_ms = 0;
|
|
|
|
}
|
|
|
|
#endif // AC_PRECLAND_ENABLED
|
|
|
|
|
2023-05-01 22:05:00 -03:00
|
|
|
if (quadplane.tailsitter.in_vtol_transition(now)) {
|
|
|
|
// Tailsitters in FW pull up phase of VTOL transition run FW controllers
|
|
|
|
Mode::run();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-08-14 15:56:40 -03:00
|
|
|
if (quadplane.throttle_wait) {
|
|
|
|
quadplane.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
|
|
|
attitude_control->set_throttle_out(0, true, 0);
|
|
|
|
quadplane.relax_attitude_control();
|
|
|
|
pos_control->relax_z_controller(0);
|
|
|
|
loiter_nav->clear_pilot_desired_acceleration();
|
|
|
|
loiter_nav->init_target();
|
2023-05-01 22:05:00 -03:00
|
|
|
|
|
|
|
// Stabilize with fixed wing surfaces
|
|
|
|
plane.stabilize_roll();
|
|
|
|
plane.stabilize_pitch();
|
2021-08-14 15:56:40 -03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!quadplane.motors->armed()) {
|
2021-09-04 16:21:04 -03:00
|
|
|
plane.mode_qloiter._enter();
|
2021-08-14 15:56:40 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (quadplane.should_relax()) {
|
|
|
|
loiter_nav->soften_for_landing();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (now - quadplane.last_loiter_ms > 500) {
|
|
|
|
loiter_nav->clear_pilot_desired_acceleration();
|
|
|
|
loiter_nav->init_target();
|
|
|
|
}
|
|
|
|
quadplane.last_loiter_ms = now;
|
|
|
|
|
|
|
|
// motors use full range
|
|
|
|
quadplane.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
|
|
|
|
|
|
|
|
// set vertical speed and acceleration limits
|
2024-01-18 22:40:25 -04:00
|
|
|
pos_control->set_max_speed_accel_z(-quadplane.get_pilot_velocity_z_max_dn(), quadplane.pilot_speed_z_max_up*100, quadplane.pilot_accel_z*100);
|
2021-08-14 15:56:40 -03:00
|
|
|
|
|
|
|
// process pilot's roll and pitch input
|
|
|
|
float target_roll_cd, target_pitch_cd;
|
2021-09-06 06:44:18 -03:00
|
|
|
quadplane.get_pilot_desired_lean_angles(target_roll_cd, target_pitch_cd, loiter_nav->get_angle_max_cd(), attitude_control->get_althold_lean_angle_max_cd());
|
2021-08-14 15:56:40 -03:00
|
|
|
loiter_nav->set_pilot_desired_acceleration(target_roll_cd, target_pitch_cd);
|
|
|
|
|
|
|
|
// run loiter controller
|
|
|
|
if (!pos_control->is_active_xy()) {
|
|
|
|
pos_control->init_xy_controller();
|
|
|
|
}
|
|
|
|
loiter_nav->update();
|
|
|
|
|
|
|
|
// nav roll and pitch are controller by loiter controller
|
|
|
|
plane.nav_roll_cd = loiter_nav->get_roll();
|
|
|
|
plane.nav_pitch_cd = loiter_nav->get_pitch();
|
2023-08-13 04:08:28 -03:00
|
|
|
|
|
|
|
plane.quadplane.assign_tilt_to_fwd_thr();
|
2021-08-14 15:56:40 -03:00
|
|
|
|
2021-11-06 16:48:13 -03:00
|
|
|
if (quadplane.transition->set_VTOL_roll_pitch_limit(plane.nav_roll_cd, plane.nav_pitch_cd)) {
|
|
|
|
pos_control->set_externally_limited_xy();
|
2021-08-14 15:56:40 -03:00
|
|
|
}
|
2021-11-06 16:48:13 -03:00
|
|
|
|
2022-07-03 19:39:05 -03:00
|
|
|
// Pilot input, use yaw rate time constant
|
|
|
|
quadplane.set_pilot_yaw_rate_time_constant();
|
|
|
|
|
2021-08-14 15:56:40 -03:00
|
|
|
// call attitude controller with conservative smoothing gain of 4.0f
|
|
|
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(plane.nav_roll_cd,
|
|
|
|
plane.nav_pitch_cd,
|
|
|
|
quadplane.get_desired_yaw_rate_cds());
|
|
|
|
|
|
|
|
if (plane.control_mode == &plane.mode_qland) {
|
|
|
|
if (poscontrol.get_state() < QuadPlane::QPOS_LAND_FINAL && quadplane.check_land_final()) {
|
|
|
|
poscontrol.set_state(QuadPlane::QPOS_LAND_FINAL);
|
|
|
|
quadplane.setup_target_position();
|
2022-07-15 08:50:12 -03:00
|
|
|
#if AP_ICENGINE_ENABLED
|
2021-08-14 15:56:40 -03:00
|
|
|
// cut IC engine if enabled
|
|
|
|
if (quadplane.land_icengine_cut != 0) {
|
2021-07-19 20:54:33 -03:00
|
|
|
plane.g2.ice_control.engine_control(0, 0, 0, false);
|
2021-08-14 15:56:40 -03:00
|
|
|
}
|
2022-07-15 08:50:12 -03:00
|
|
|
#endif // AP_ICENGINE_ENABLED
|
2021-08-14 15:56:40 -03:00
|
|
|
}
|
|
|
|
float height_above_ground = plane.relative_ground_altitude(plane.g.rangefinder_landing);
|
|
|
|
float descent_rate_cms = quadplane.landing_descent_rate_cms(height_above_ground);
|
|
|
|
|
2022-08-05 12:08:59 -03:00
|
|
|
if (poscontrol.get_state() == QuadPlane::QPOS_LAND_FINAL && !quadplane.option_is_set(QuadPlane::OPTION::DISABLE_GROUND_EFFECT_COMP)) {
|
2023-02-12 09:33:27 -04:00
|
|
|
ahrs.set_touchdown_expected(true);
|
2021-08-14 15:56:40 -03:00
|
|
|
}
|
|
|
|
|
2022-12-17 14:27:48 -04:00
|
|
|
pos_control->land_at_climb_rate_cm(-descent_rate_cms, descent_rate_cms>0);
|
2021-08-14 15:56:40 -03:00
|
|
|
quadplane.check_land_complete();
|
|
|
|
} else if (plane.control_mode == &plane.mode_guided && quadplane.guided_takeoff) {
|
2022-12-17 14:27:48 -04:00
|
|
|
quadplane.set_climb_rate_cms(0);
|
2021-08-14 15:56:40 -03:00
|
|
|
} else {
|
|
|
|
// update altitude target and call position controller
|
2022-12-17 14:27:48 -04:00
|
|
|
quadplane.set_climb_rate_cms(quadplane.get_pilot_desired_climb_rate_cms());
|
2021-08-14 15:56:40 -03:00
|
|
|
}
|
|
|
|
quadplane.run_z_controller();
|
2023-05-01 22:05:00 -03:00
|
|
|
|
|
|
|
// Stabilize with fixed wing surfaces
|
|
|
|
plane.stabilize_roll();
|
|
|
|
plane.stabilize_pitch();
|
2021-08-14 15:56:40 -03:00
|
|
|
}
|
2019-01-15 13:46:13 -04:00
|
|
|
|
2021-09-10 03:28:21 -03:00
|
|
|
#endif
|