2021-03-18 00:12:54 -03:00
# include "Blimp.h"
/*
* High level calls to set and update flight modes logic for individual
* flight modes is in control_acro . cpp , control_stabilize . cpp , etc
*/
2022-09-29 20:10:41 -03:00
# include <AP_Vehicle/AP_MultiCopter.h>
2021-03-18 00:12:54 -03:00
/*
constructor for Mode object
*/
Mode : : Mode ( void ) :
g ( blimp . g ) ,
g2 ( blimp . g2 ) ,
inertial_nav ( blimp . inertial_nav ) ,
ahrs ( blimp . ahrs ) ,
motors ( blimp . motors ) ,
2023-07-27 02:03:08 -03:00
loiter ( blimp . loiter ) ,
2021-03-18 00:12:54 -03:00
channel_right ( blimp . channel_right ) ,
channel_front ( blimp . channel_front ) ,
2023-07-27 02:05:11 -03:00
channel_up ( blimp . channel_up ) ,
2021-03-18 00:12:54 -03:00
channel_yaw ( blimp . channel_yaw ) ,
G_Dt ( blimp . G_Dt )
{ } ;
// return the static controller object corresponding to supplied mode
Mode * Blimp : : mode_from_mode_num ( const Mode : : Number mode )
{
Mode * ret = nullptr ;
switch ( mode ) {
case Mode : : Number : : LAND :
ret = & mode_land ;
break ;
2021-09-04 04:33:31 -03:00
case Mode : : Number : : MANUAL :
ret = & mode_manual ;
break ;
2021-06-18 01:40:01 -03:00
case Mode : : Number : : VELOCITY :
ret = & mode_velocity ;
break ;
case Mode : : Number : : LOITER :
ret = & mode_loiter ;
break ;
2023-07-27 02:03:08 -03:00
case Mode : : Number : : RTL :
ret = & mode_rtl ;
break ;
2021-03-18 00:12:54 -03:00
default :
break ;
}
return ret ;
}
// set_mode - change flight mode and perform any necessary initialisation
// optional force parameter used to force the flight mode change (used only first time mode is set)
// returns true if mode was successfully set
2021-06-17 04:03:49 -03:00
// Some modes can always be set successfully but the return state of other flight modes should be checked and the caller should deal with failures appropriately
2021-03-18 00:12:54 -03:00
bool Blimp : : set_mode ( Mode : : Number mode , ModeReason reason )
{
// return immediately if we are already in the desired mode
if ( mode = = control_mode ) {
control_mode_reason = reason ;
return true ;
}
Mode * new_flightmode = mode_from_mode_num ( ( Mode : : Number ) mode ) ;
if ( new_flightmode = = nullptr ) {
2021-08-24 23:04:50 -03:00
notify_no_such_mode ( ( uint8_t ) mode ) ;
2021-03-18 00:12:54 -03:00
return false ;
}
bool ignore_checks = ! motors - > armed ( ) ; // allow switching to any mode if disarmed. We rely on the arming check to perform
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 ( ) ) ;
2024-01-09 23:37:03 -04:00
LOGGER_WRITE_ERROR ( LogErrorSubsystem : : FLIGHT_MODE , LogErrorCode ( mode ) ) ;
2021-03-18 00:12:54 -03:00
return false ;
}
// check for valid altitude if old mode did not require it but new one does
// we only want to stop changing modes if it could make things worse
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 ( ) ) ;
2024-01-09 23:37:03 -04:00
LOGGER_WRITE_ERROR ( LogErrorSubsystem : : FLIGHT_MODE , LogErrorCode ( mode ) ) ;
2021-03-18 00:12:54 -03:00
return false ;
}
if ( ! new_flightmode - > init ( ignore_checks ) ) {
gcs ( ) . send_text ( MAV_SEVERITY_WARNING , " Flight mode change failed %s " , new_flightmode - > name ( ) ) ;
2024-01-09 23:37:03 -04:00
LOGGER_WRITE_ERROR ( LogErrorSubsystem : : FLIGHT_MODE , LogErrorCode ( mode ) ) ;
2021-03-18 00:12:54 -03:00
return false ;
}
// perform any cleanup required by previous flight mode
exit_mode ( flightmode , new_flightmode ) ;
// store previous flight mode (only used by tradeheli's autorotation)
prev_control_mode = control_mode ;
// update flight mode
flightmode = new_flightmode ;
control_mode = mode ;
control_mode_reason = reason ;
2024-01-09 23:37:03 -04:00
# if HAL_LOGGING_ENABLED
2021-03-18 00:12:54 -03:00
logger . Write_Mode ( ( uint8_t ) control_mode , reason ) ;
2024-01-09 23:37:03 -04:00
# endif
2021-03-18 00:12:54 -03:00
gcs ( ) . send_message ( MSG_HEARTBEAT ) ;
// update notify object
notify_flight_mode ( ) ;
// return success
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 ) {
// don't allow mode changes while in radio failsafe
return false ;
}
# endif
return blimp . set_mode ( static_cast < Mode : : Number > ( new_mode ) , reason ) ;
}
// update_flight_mode - calls the appropriate attitude controllers based on flight mode
// called at 100hz or more
void Blimp : : update_flight_mode ( )
{
flightmode - > run ( ) ;
}
// exit_mode - high level call to organise cleanup as a flight mode is exited
void Blimp : : exit_mode ( Mode * & old_flightmode ,
2023-08-21 08:19:19 -03:00
Mode * & new_flightmode ) { }
2021-03-18 00:12:54 -03:00
// notify_flight_mode - sets notify object based on current flight mode. Only used for OreoLED notify device
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 to make high level decisions about control modes
run_autopilot ( ) ;
}
2023-07-27 02:03:08 -03:00
// returns desired thrust/acceleration
void Mode : : get_pilot_input ( Vector3f & pilot , float & yaw )
2021-03-18 00:12:54 -03:00
{
// throttle failsafe check
2024-02-07 00:14:28 -04:00
if ( blimp . failsafe . radio | | ! rc ( ) . has_ever_seen_rc_input ( ) ) {
2023-07-27 02:03:08 -03:00
pilot . y = 0 ;
pilot . x = 0 ;
pilot . z = 0 ;
yaw = 0 ;
2021-03-18 00:12:54 -03:00
return ;
}
2023-07-27 02:03:08 -03:00
// fetch pilot inputs
pilot . y = channel_right - > get_control_in ( ) / float ( RC_SCALE ) ;
pilot . x = channel_front - > get_control_in ( ) / float ( RC_SCALE ) ;
//TODO: need to make this channel_up instead, and then have it .negative. before being sent to pilot.z -> this is "throttle" channel, so higher = up.
pilot . z = - channel_up - > get_control_in ( ) / float ( RC_SCALE ) ;
yaw = channel_yaw - > get_control_in ( ) / float ( RC_SCALE ) ;
2021-03-18 00:12:54 -03:00
}
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 ( ) ;
}