#include "Blimp.h"
Mode::Mode(void) :
g(blimp.g),
g2(blimp.g2),
inertial_nav(blimp.inertial_nav),
ahrs(blimp.ahrs),
motors(blimp.motors),
loiter(blimp.loiter),
channel_right(blimp.channel_right),
channel_front(blimp.channel_front),
channel_up(blimp.channel_up),
channel_yaw(blimp.channel_yaw),
G_Dt(blimp.G_Dt)
{ };
Mode *Blimp::mode_from_mode_num(const Mode::Number mode)
{
Mode *ret = nullptr;
switch (mode) {
case Mode::Number::LAND:
ret = &mode_land;
break;
case Mode::Number::MANUAL:
ret = &mode_manual;
break;
case Mode::Number::VELOCITY:
ret = &mode_velocity;
break;
case Mode::Number::LOITER:
ret = &mode_loiter;
break;
case Mode::Number::RTL:
ret = &mode_rtl;
break;
default:
break;
}
return ret;
}
bool Blimp::set_mode(Mode::Number mode, ModeReason reason)
{
if (mode == control_mode) {
control_mode_reason = reason;
return true;
}
Mode *new_flightmode = mode_from_mode_num((Mode::Number)mode);
if (new_flightmode == nullptr) {
notify_no_such_mode((uint8_t)mode);
return false;
}
bool ignore_checks = !motors->armed();
if (!ignore_checks &&
new_flightmode->requires_GPS() &&
!blimp.position_ok()) {
gcs().send_text(MAV_SEVERITY_WARNING, "Mode change failed: %s requires position", new_flightmode->name());
LOGGER_WRITE_ERROR(LogErrorSubsystem::FLIGHT_MODE, LogErrorCode(mode));
return false;
}
if (!ignore_checks &&
!blimp.ekf_alt_ok() &&
flightmode->has_manual_throttle() &&
!new_flightmode->has_manual_throttle()) {
gcs().send_text(MAV_SEVERITY_WARNING, "Mode change failed: %s need alt estimate", new_flightmode->name());
LOGGER_WRITE_ERROR(LogErrorSubsystem::FLIGHT_MODE, LogErrorCode(mode));
return false;
}
if (!new_flightmode->init(ignore_checks)) {
gcs().send_text(MAV_SEVERITY_WARNING,"Flight mode change failed %s", new_flightmode->name());
LOGGER_WRITE_ERROR(LogErrorSubsystem::FLIGHT_MODE, LogErrorCode(mode));
return false;
}
exit_mode(flightmode, new_flightmode);
flightmode = new_flightmode;
control_mode = mode;
control_mode_reason = reason;
#if HAL_LOGGING_ENABLED
logger.Write_Mode((uint8_t)control_mode, reason);
#endif
gcs().send_message(MSG_HEARTBEAT);
notify_flight_mode();
return true;
}
bool Blimp::set_mode(const uint8_t new_mode, const ModeReason reason)
{
static_assert(sizeof(Mode::Number) == sizeof(new_mode), "The new mode can't be mapped to the vehicles mode number");
#ifdef DISALLOW_GCS_MODE_CHANGE_DURING_RC_FAILSAFE
if (reason == ModeReason::GCS_COMMAND && blimp.failsafe.radio) {
return false;
}
#endif
return blimp.set_mode(static_cast<Mode::Number>(new_mode), reason);
}
void Blimp::update_flight_mode()
{
flightmode->run();
}
void Blimp::exit_mode(Mode *&old_flightmode,
Mode *&new_flightmode) {}
void Blimp::notify_flight_mode()
{
AP_Notify::flags.autopilot_mode = flightmode->is_autopilot();
AP_Notify::flags.flight_mode = (uint8_t)control_mode;
notify.set_flight_mode_str(flightmode->name4());
}
void Mode::update_navigation()
{
run_autopilot();
}
void Mode::get_pilot_input(Vector3f &pilot, float &yaw)
{
if (blimp.failsafe.radio || !rc().has_ever_seen_rc_input()) {
pilot.y = 0;
pilot.x = 0;
pilot.z = 0;
yaw = 0;
return;
}
pilot.y = channel_right->get_control_in() / float(RC_SCALE);
pilot.x = channel_front->get_control_in() / float(RC_SCALE);
pilot.z = -channel_up->get_control_in() / float(RC_SCALE);
yaw = channel_yaw->get_control_in() / float(RC_SCALE);
}
bool Mode::is_disarmed_or_landed() const
{
if (!motors->armed() || !blimp.ap.auto_armed || blimp.ap.land_complete) {
return true;
}
return false;
}
bool Mode::set_mode(Mode::Number mode, ModeReason reason)
{
return blimp.set_mode(mode, reason);
}
GCS_Blimp &Mode::gcs()
{
return blimp.gcs();
}