LCOV - code coverage report
Current view: top level - home/pbarker/rc/ardupilot/Rover - Rover.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 121 191 63.4 %
Date: 2026-09-09 11:02:08 Functions: 14 23 60.9 %

          Line data    Source code
       1             : /*
       2             :    This program is free software: you can redistribute it and/or modify
       3             :    it under the terms of the GNU General Public License as published by
       4             :    the Free Software Foundation, either version 3 of the License, or
       5             :    (at your option) any later version.
       6             : 
       7             :    This program is distributed in the hope that it will be useful,
       8             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10             :    GNU General Public License for more details.
      11             : 
      12             :    You should have received a copy of the GNU General Public License
      13             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      14             : */
      15             : 
      16             : /*
      17             :    This is the ArduRover firmware. It was originally derived from
      18             :    ArduPlane by Jean-Louis Naudin (JLN), and then rewritten after the
      19             :    AP_HAL merge by Andrew Tridgell
      20             : 
      21             :    Maintainer: Randy Mackay, Grant Morphett
      22             : 
      23             :    Authors:    Doug Weibel, Jose Julio, Jordi Munoz, Jason Short, Andrew Tridgell, Randy Mackay, Pat Hickey, John Arne Birkeland, Olivier Adler, Jean-Louis Naudin, Grant Morphett
      24             : 
      25             :    Thanks to:  Chris Anderson, Michael Oborne, Paul Mather, Bill Premerlani, James Cohen, JB from rotorFX, Automatik, Fefenin, Peter Meister, Remzibi, Yury Smirnov, Sandro Benigno, Max Levine, Roberto Navoni, Lorenz Meier
      26             : 
      27             :    APMrover alpha version tester: Franco Borasio, Daniel Chapelat...
      28             : 
      29             :    Please contribute your ideas! See https://ardupilot.club/dev for details
      30             : */
      31             : 
      32             : #include "Rover.h"
      33             : 
      34             : #define FORCE_VERSION_H_INCLUDE
      35             : #include "version.h"
      36             : #undef FORCE_VERSION_H_INCLUDE
      37             : 
      38             : const AP_HAL::HAL& hal = AP_HAL::get_HAL();
      39             : 
      40             : #define SCHED_TASK(func, rate_hz, _max_time_micros, _priority) SCHED_TASK_CLASS(Rover, &rover, func, rate_hz, _max_time_micros, _priority)
      41             : 
      42             : /*
      43             :   scheduler table - all regular tasks should be listed here.
      44             : 
      45             :   All entries in this table must be ordered by priority.
      46             : 
      47             :   This table is interleaved with the table in AP_Vehicle to determine
      48             :   the order in which tasks are run.  Convenience methods SCHED_TASK
      49             :   and SCHED_TASK_CLASS are provided to build entries in this structure:
      50             : 
      51             : SCHED_TASK arguments:
      52             :  - name of static function to call
      53             :  - rate (in Hertz) at which the function should be called
      54             :  - expected time (in MicroSeconds) that the function should take to run
      55             :  - priority (0 through 255, lower number meaning higher priority)
      56             : 
      57             : SCHED_TASK_CLASS arguments:
      58             :  - class name of method to be called
      59             :  - instance on which to call the method
      60             :  - method to call on that instance
      61             :  - rate (in Hertz) at which the method should be called
      62             :  - expected time (in MicroSeconds) that the method should take to run
      63             :  - priority (0 through 255, lower number meaning higher priority)
      64             : 
      65             :   scheduler table - all regular tasks are listed here, along with how
      66             :   often they should be called (in Hz) and the maximum time
      67             :   they are expected to take (in microseconds)
      68             :  */
      69             : const AP_Scheduler::Task Rover::scheduler_tasks[] = {
      70             :     //         Function name,          Hz,     us,
      71             :     SCHED_TASK(read_radio,             50,    200,   3),
      72             :     SCHED_TASK(ahrs_update,           400,    400,   6),
      73             : #if AP_RANGEFINDER_ENABLED
      74             :     SCHED_TASK(read_rangefinders,      50,    200,   9),
      75             : #endif
      76             : #if AP_OPTICALFLOW_ENABLED
      77             :     SCHED_TASK_CLASS(AP_OpticalFlow,      &rover.optflow,          update,         200, 160,  11),
      78             : #endif
      79             :     SCHED_TASK(update_current_mode,   400,    200,  12),
      80             :     SCHED_TASK(set_servos,            400,    200,  15),
      81             :     SCHED_TASK_CLASS(AP_GPS,              &rover.gps,              update,         50,  300,  18),
      82             :     SCHED_TASK_CLASS(AP_Baro,             &rover.barometer,        update,         10,  200,  21),
      83             : #if HAL_PROXIMITY_ENABLED
      84             :     SCHED_TASK_CLASS(AP_Proximity,        &rover.g2.proximity,     update,         200,  200,  27),
      85             : #endif
      86             :     SCHED_TASK_CLASS(AP_WindVane,         &rover.g2.windvane,      update,         20,  100,  30),
      87             :     SCHED_TASK(update_wheel_encoder,   50,    200,  36),
      88             :     SCHED_TASK(update_compass,         10,    200,  39),
      89             : #if HAL_LOGGING_ENABLED
      90             :     SCHED_TASK(update_logging1,        10,    200,  45),
      91             :     SCHED_TASK(update_logging2,        10,    200,  48),
      92             : #endif
      93             :     SCHED_TASK_CLASS(GCS,                 (GCS*)&rover._gcs,       update_receive,                    400,    500,  51),
      94             :     SCHED_TASK_CLASS(GCS,                 (GCS*)&rover._gcs,       update_send,                       400,   1000,  54),
      95             :     SCHED_TASK_CLASS(RC_Channels,         (RC_Channels*)&rover.g2.rc_channels, read_mode_switch,        7,    200,  57),
      96             :     SCHED_TASK_CLASS(RC_Channels,         (RC_Channels*)&rover.g2.rc_channels, read_aux_all,           10,    200,  60),
      97             :     SCHED_TASK_CLASS(AP_BattMonitor,      &rover.battery,          read,           10,  300,  63),
      98             : #if AP_SERVORELAYEVENTS_ENABLED
      99             :     SCHED_TASK_CLASS(AP_ServoRelayEvents, &rover.ServoRelayEvents, update_events,  50,  200,  66),
     100             : #endif
     101             : #if AC_PRECLAND_ENABLED
     102             :     SCHED_TASK(update_precland,      400,     50,  70),
     103             : #endif
     104             : #if HAL_MOUNT_ENABLED
     105             :     SCHED_TASK_CLASS(AP_Mount,            &rover.camera_mount,     update,         50,  200,  75),
     106             : #endif
     107             : #if AP_CAMERA_ENABLED
     108             :     SCHED_TASK_CLASS(AP_Camera,           &rover.camera,           update,         50,  200,  78),
     109             : #endif
     110             :     SCHED_TASK(gcs_failsafe_check,     10,    200,  81),
     111             : #if AP_FENCE_ENABLED
     112             :     SCHED_TASK(fence_check,            10,    200,  84),
     113             : #endif
     114             :     SCHED_TASK(ekf_check,              10,    100,  87),
     115             :     SCHED_TASK_CLASS(ModeSmartRTL,        &rover.mode_smartrtl,    save_position,   3,  200,  90),
     116             :     SCHED_TASK(one_second_loop,         1,   1500,  96),
     117             : #if HAL_SPRAYER_ENABLED
     118             :     SCHED_TASK_CLASS(AC_Sprayer,          &rover.g2.sprayer,       update,          3,  90,  99),
     119             : #endif
     120             : #if HAL_LOGGING_ENABLED
     121             :     SCHED_TASK_CLASS(AP_Logger,           &rover.logger,           periodic_tasks, 50,  300, 108),
     122             : #endif
     123             :     SCHED_TASK_CLASS(AP_InertialSensor,   &rover.ins,              periodic,      400,  200, 111),
     124             : #if HAL_LOGGING_ENABLED
     125             :     SCHED_TASK_CLASS(AP_Scheduler,        &rover.scheduler,        update_logging, 0.1, 200, 114),
     126             : #endif
     127             : #if HAL_BUTTON_ENABLED
     128             :     SCHED_TASK_CLASS(AP_Button,           &rover.button,           update,          5,  200, 117),
     129             : #endif
     130             :     SCHED_TASK(crash_check,            10,    200, 123),
     131             :     SCHED_TASK(cruise_learn_update,    50,    200, 126),
     132             : #if AP_ROVER_ADVANCED_FAILSAFE_ENABLED
     133             :     SCHED_TASK(afs_fs_check,           10,    200, 129),
     134             : #endif
     135             : };
     136             : 
     137             : 
     138         285 : void Rover::get_scheduler_tasks(const AP_Scheduler::Task *&tasks,
     139             :                                 uint8_t &task_count,
     140             :                                 uint32_t &log_bit)
     141             : {
     142         285 :     tasks = &scheduler_tasks[0];
     143         285 :     task_count = ARRAY_SIZE(scheduler_tasks);
     144         285 :     log_bit = MASK_LOG_PM;
     145         285 : }
     146             : 
     147             : constexpr int8_t Rover::_failsafe_priorities[7];
     148             : 
     149         285 : Rover::Rover(void) :
     150             :     AP_Vehicle(),
     151         285 :     param_loader(var_info),
     152         285 :     control_mode(&mode_initializing)
     153             : {
     154         285 : }
     155             : 
     156             : #if AP_SCRIPTING_ENABLED || AP_EXTERNAL_CONTROL_ENABLED
     157             : // set target location (for use by external control and scripting)
     158           0 : bool Rover::set_target_location(const Location& target_loc)
     159             : {
     160             :     // exit if vehicle is not in Guided mode or Auto-Guided mode
     161           0 :     if (!control_mode->in_guided_mode()) {
     162           0 :         return false;
     163             :     }
     164             : 
     165           0 :     return mode_guided.set_desired_location(target_loc);
     166             : }
     167             : #endif //AP_SCRIPTING_ENABLED || AP_EXTERNAL_CONTROL_ENABLED
     168             : 
     169             : #if AP_SCRIPTING_ENABLED
     170             : // set target velocity (for use by scripting)
     171           0 : bool Rover::set_target_velocity_NED(const Vector3f& vel_ned_ms, bool align_yaw_to_target)
     172             : {
     173             :     // exit if vehicle is not in Guided mode or Auto-Guided mode
     174           0 :     if (!control_mode->in_guided_mode()) {
     175           0 :         return false;
     176             :     }
     177             : 
     178             :     // convert vector length into speed
     179           0 :     const float target_speed_ms = safe_sqrt(sq(vel_ned_ms.x) + sq(vel_ned_ms.y));
     180             : 
     181             :     // convert vector direction to target yaw
     182           0 :     const float target_yaw_cd = degrees(atan2f(vel_ned_ms.y, vel_ned_ms.x)) * 100.0f;
     183             : 
     184             :     // send target heading and speed
     185           0 :     mode_guided.set_desired_heading_and_speed(target_yaw_cd, target_speed_ms);
     186             : 
     187           0 :     return true;
     188             : }
     189             : 
     190             : // set steering and throttle (-1 to +1) (for use by scripting)
     191          20 : bool Rover::set_steering_and_throttle(float steering, float throttle)
     192             : {
     193             :     // exit if vehicle is not in Guided mode or Auto-Guided mode
     194          20 :     if (!control_mode->in_guided_mode()) {
     195           0 :         return false;
     196             :     }
     197             : 
     198             :     // set steering and throttle
     199          20 :     mode_guided.set_steering_and_throttle(steering, throttle);
     200          20 :     return true;
     201             : }
     202             : 
     203             : // get steering and throttle (-1 to +1) (for use by scripting)
     204           0 : bool Rover::get_steering_and_throttle(float& steering, float& throttle)
     205             : {
     206           0 :     steering = g2.motors.get_steering() / 4500.0;
     207           0 :     throttle = g2.motors.get_throttle() * 0.01;
     208           0 :     return true;
     209             : }
     210             : 
     211             : // set desired turn rate (degrees/sec) and speed (m/s). Used for scripting
     212           0 : bool Rover::set_desired_turn_rate_and_speed(float turn_rate_degs, float speed_ms)
     213             : {
     214             :     // exit if vehicle is not in Guided mode or Auto-Guided mode
     215           0 :     if (!control_mode->in_guided_mode()) {
     216           0 :         return false;
     217             :     }
     218             : 
     219             :     // set turn rate and speed. Turn rate is expected in centidegrees/s and speed in meters/s
     220           0 :     mode_guided.set_desired_turn_rate_and_speed(turn_rate_degs * 100.0f, speed_ms);
     221           0 :     return true;
     222             : }
     223             : 
     224             : // set desired nav speed (m/s). Used for scripting.
     225           0 : bool Rover::set_desired_speed(float speed_ms)
     226             : {
     227           0 :     return control_mode->set_desired_speed(speed_ms);
     228             : }
     229             : 
     230             : // get control output (for use in scripting)
     231             : // returns true on success and control_value is set to a value in the range -1 to +1
     232           0 : bool Rover::get_control_output(AP_Vehicle::ControlOutput control_output, float &control_value)
     233             : {
     234           0 :     switch (control_output) {
     235           0 :     case AP_Vehicle::ControlOutput::Roll:
     236           0 :         control_value = constrain_float(g2.motors.get_roll(), -1.0f, 1.0f);
     237           0 :         return true;
     238           0 :     case AP_Vehicle::ControlOutput::Pitch:
     239           0 :         control_value = constrain_float(g2.motors.get_pitch(), -1.0f, 1.0f);
     240           0 :         return true;
     241           0 :     case AP_Vehicle::ControlOutput::Walking_Height:
     242           0 :         control_value = constrain_float(g2.motors.get_walking_height(), -1.0f, 1.0f);
     243           0 :         return true;
     244           0 :     case AP_Vehicle::ControlOutput::Throttle:
     245           0 :         control_value = constrain_float(g2.motors.get_throttle() * 0.01f, -1.0f, 1.0f);
     246           0 :         return true;
     247           0 :     case AP_Vehicle::ControlOutput::Yaw:
     248           0 :         control_value = constrain_float(g2.motors.get_steering() / 4500.0f, -1.0f, 1.0f);
     249           0 :         return true;
     250           0 :     case AP_Vehicle::ControlOutput::Lateral:
     251           0 :         control_value = constrain_float(g2.motors.get_lateral() * 0.01f, -1.0f, 1.0f);
     252           0 :         return true;
     253           0 :     case AP_Vehicle::ControlOutput::MainSail:
     254           0 :         control_value = constrain_float(g2.motors.get_mainsail() * 0.01f, -1.0f, 1.0f);
     255           0 :         return true;
     256           0 :     case AP_Vehicle::ControlOutput::WingSail:
     257           0 :         control_value = constrain_float(g2.motors.get_wingsail() * 0.01f, -1.0f, 1.0f);
     258           0 :         return true;
     259           0 :     default:
     260           0 :         return false;
     261             :     }
     262             :     return false;
     263             : }
     264             : 
     265             : // returns true if mode supports NAV_SCRIPT_TIME mission commands
     266           0 : bool Rover::nav_scripting_enable(uint8_t mode)
     267             : {
     268           0 :     return mode == (uint8_t)mode_auto.mode_number();
     269             : }
     270             : 
     271             : // lua scripts use this to retrieve the contents of the active command
     272           0 : bool Rover::nav_script_time(uint16_t &id, uint8_t &cmd, float &arg1, float &arg2, int16_t &arg3, int16_t &arg4)
     273             : {
     274           0 :     if (control_mode != &mode_auto) {
     275           0 :         return false;
     276             :     }
     277             : 
     278           0 :     return mode_auto.nav_script_time(id, cmd, arg1, arg2, arg3, arg4);
     279             : }
     280             : 
     281             : // lua scripts use this to indicate when they have complete the command
     282           0 : void Rover::nav_script_time_done(uint16_t id)
     283             : {
     284           0 :     if (control_mode != &mode_auto) {
     285           0 :         return;
     286             :     }
     287             : 
     288           0 :     return mode_auto.nav_script_time_done(id);
     289             : }
     290             : #endif // AP_SCRIPTING_ENABLED
     291             : 
     292             : // update AHRS system
     293      629048 : void Rover::ahrs_update()
     294             : {
     295      629048 :     arming.update_soft_armed();
     296             : 
     297             :     // AHRS may use movement to calculate heading
     298      629048 :     update_ahrs_flyforward();
     299             : 
     300      629048 :     ahrs.update();
     301             : 
     302             :     // update position
     303      629048 :     have_position = ahrs.get_location(current_loc);
     304             : 
     305             :     // set home from EKF if necessary and possible
     306      629048 :     if (!ahrs.home_is_set()) {
     307       68168 :         if (!set_home_to_current_location(false)) {
     308             :             // ignore this failure
     309             :         }
     310             :     }
     311             : 
     312             :     // if using the EKF get a speed update now (from accelerometers)
     313      629048 :     Vector3f velocity;
     314      629048 :     if (ahrs.get_velocity_NED(velocity)) {
     315      589379 :         ground_speed = velocity.xy().length();
     316       39669 :     } else if (gps.status() >= AP_GPS_FixType::FIX_3D) {
     317           0 :         ground_speed = ahrs.groundspeed();
     318             :     }
     319             :     
     320             : #if AP_FOLLOW_ENABLED
     321      629048 :     g2.follow.update_estimates();
     322             : #endif
     323             : 
     324             : #if HAL_LOGGING_ENABLED
     325      629048 :     if (should_log(MASK_LOG_ATTITUDE_FAST)) {
     326      600310 :         Log_Write_Attitude();
     327      600310 :         Log_Write_Sail();
     328             :     }
     329             : 
     330      629048 :     if (should_log(MASK_LOG_IMU)) {
     331      599570 :         AP::ins().Write_IMU();
     332             :     }
     333             : 
     334      629048 :     if (should_log(MASK_LOG_VIDEO_STABILISATION)) {
     335           0 :         ahrs.write_video_stabilisation();
     336             :     }
     337             : #endif
     338      629048 : }
     339             : 
     340             : /*
     341             :   check for GCS failsafe - 10Hz
     342             :  */
     343      125720 : void Rover::gcs_failsafe_check(void)
     344             : {
     345      125720 :     if (g.fs_gcs_enabled == FS_GCS_DISABLED) {
     346             :         // gcs failsafe disabled
     347      123710 :         return;
     348             :     }
     349             : 
     350        2010 :     const uint32_t gcs_last_seen_ms = gcs().sysid_mygcs_last_seen_time_ms();
     351        2010 :     if (gcs_last_seen_ms == 0) {
     352             :         // we've never seen the GCS, so we never failsafe for not seeing it
     353           0 :         return;
     354             :     }
     355             : 
     356             :     // calc time since last gcs update
     357             :     // note: this only looks at the heartbeat from the device ids approved by gcs().sysid_is_gcs()
     358        2010 :     const uint32_t last_gcs_update_ms = millis() - gcs_last_seen_ms;
     359        2010 :     const uint32_t gcs_timeout_ms = uint32_t(constrain_float(g2.fs_gcs_timeout * 1000.0f, 0.0f, UINT32_MAX));
     360             : 
     361        2010 :     const bool do_failsafe = last_gcs_update_ms >= gcs_timeout_ms ? true : false;
     362             : 
     363        2010 :     failsafe_trigger(FAILSAFE_EVENT_GCS, "GCS", do_failsafe);
     364             : }
     365             : 
     366             : #if HAL_LOGGING_ENABLED
     367             : /*
     368             :   log some key data - 10Hz
     369             :  */
     370      125720 : void Rover::update_logging1(void)
     371             : {
     372      125720 :     if (should_log(MASK_LOG_ATTITUDE_MED) && !should_log(MASK_LOG_ATTITUDE_FAST)) {
     373           0 :         Log_Write_Attitude();
     374           0 :         Log_Write_Sail();
     375             :     }
     376             : 
     377      125720 :     if (should_log(MASK_LOG_THR)) {
     378      119840 :         Log_Write_Throttle();
     379             : #if AP_BEACON_ENABLED
     380      119840 :         beacon.log();
     381             : #endif  // AP_BEACON_ENABLED
     382             :     }
     383             : 
     384      125720 :     if (should_log(MASK_LOG_NTUN)) {
     385      119840 :         Log_Write_Nav_Tuning();
     386      119840 :         if (g2.pos_control.is_active()) {
     387       35761 :             g2.pos_control.write_log();
     388       35761 :             logger.Write_PID(LOG_PIDN_MSG, g2.pos_control.get_vel_pid().get_pid_info_x());
     389       35761 :             logger.Write_PID(LOG_PIDE_MSG, g2.pos_control.get_vel_pid().get_pid_info_y());
     390             :         }
     391             :     }
     392             : 
     393             : #if HAL_PROXIMITY_ENABLED
     394      125720 :     if (should_log(MASK_LOG_RANGEFINDER)) {
     395      119840 :         g2.proximity.log();
     396             :     }
     397             : #endif
     398      125720 : }
     399             : 
     400             : /*
     401             :   log some key data - 10Hz
     402             :  */
     403      125720 : void Rover::update_logging2(void)
     404             : {
     405      125720 :     if (should_log(MASK_LOG_STEERING)) {
     406      119840 :         Log_Write_Steering();
     407             :     }
     408             : 
     409      125720 :     if (should_log(MASK_LOG_RC)) {
     410      119840 :         Log_Write_RC();
     411      119840 :         g2.wheel_encoder.Log_Write();
     412             :     }
     413             : 
     414      125720 :     if (should_log(MASK_LOG_IMU)) {
     415      119840 :         AP::ins().Write_Vibration();
     416             : #if HAL_GYROFFT_ENABLED
     417      119840 :         gyro_fft.write_log_messages();
     418             : #endif
     419             :     }
     420             : #if HAL_MOUNT_ENABLED
     421      125720 :     if (should_log(MASK_LOG_CAMERA)) {
     422      119840 :         camera_mount.write_log();
     423             :     }
     424             : #endif
     425      125720 : }
     426             : #endif  // HAL_LOGGING_ENABLED
     427             : 
     428             : #if AP_ROVER_AUTO_ARM_ONCE_ENABLED
     429       12526 : void Rover::handle_auto_arm_once()
     430             : {
     431       12526 :     if (arming.is_armed()) {
     432             :         // never re-arm automatically if the user ever armed the vehicle
     433        5012 :         auto_arm_once.done = true;
     434        5012 :         return;
     435             :     }
     436        7514 :     if (auto_arm_once.done) {
     437        7221 :         return;
     438             :     }
     439         293 :     switch (arming.arming_required()) {
     440         282 :     case AP_Arming::Required::NO:
     441             :     case AP_Arming::Required::YES_MIN_PWM:
     442             :     case AP_Arming::Required::YES_ZERO_PWM:
     443             :         // in case the user changes the require parameter at runtime,
     444             :         // don't auto-arm:
     445         282 :         auto_arm_once.done = true;
     446         282 :         return;
     447          11 :     case AP_Arming::Required::YES_AUTO_ARM_MIN_PWM:
     448             :     case AP_Arming::Required::YES_AUTO_ARM_ZERO_PWM:
     449          11 :         break;
     450             :     }
     451             : 
     452             :     // don't try to arm if prearms are not passing:
     453          11 :     if (!arming.get_last_prearm_checks_result()) {
     454          10 :         return;
     455             :     }
     456             : 
     457           1 :     const uint32_t now_ms = AP_HAL::millis();
     458             :     // only attempt to auto arm once per 5 seconds:
     459           1 :     if (now_ms - auto_arm_once.last_arm_attempt_ms < 5000) {
     460           0 :         return;
     461             :     }
     462           1 :     auto_arm_once.last_arm_attempt_ms = now_ms;
     463             : 
     464           1 :     if (!arming.arm(AP_Arming::Method::AUTO_ARM_ONCE)) {
     465           0 :         return;
     466             :     }
     467             : 
     468           1 :     auto_arm_once.done = true;
     469             : }
     470             : #endif  // AP_ROVER_AUTO_ARM_ONCE_ENABLED
     471             : 
     472             : /*
     473             :   once a second events
     474             :  */
     475       12526 : void Rover::one_second_loop(void)
     476             : {
     477       12526 :     set_control_channels();
     478             : 
     479             :     // cope with changes to aux functions
     480       12526 :     AP::srv().enable_aux_servos();
     481             : 
     482             :     // update notify flags
     483       12526 :     AP_Notify::flags.pre_arm_check = arming.pre_arm_checks(false);
     484       12526 :     AP_Notify::flags.pre_arm_gps_check = true;
     485       12526 :     AP_Notify::flags.armed = arming.is_armed();
     486       12526 :     AP_Notify::flags.flying = arming.is_armed_and_safety_off();
     487             : 
     488             : #if AP_ROVER_AUTO_ARM_ONCE_ENABLED
     489       12526 :     handle_auto_arm_once();
     490             : #endif  // AP_ROVER_AUTO_ARM_ONCE_ENABLED
     491             : 
     492             :     // attempt to update home position and baro calibration if not armed:
     493       12526 :     if (!arming.is_armed_and_safety_off()) {
     494        7527 :         update_home();
     495             :     }
     496             : 
     497             :     // need to set "likely flying" when armed to allow for compass
     498             :     // learning to run
     499       12526 :     set_likely_flying(arming.is_armed_and_safety_off());
     500             : 
     501             :     // send latest param values to wp_nav
     502       12526 :     g2.wp_nav.set_turn_params(g2.turn_radius, g2.motors.have_skid_steering());
     503       12526 :     g2.pos_control.set_turn_params(g2.turn_radius, g2.motors.have_skid_steering());
     504       12526 :     g2.wheel_rate_control.set_notch_sample_rate(AP::scheduler().get_filtered_loop_rate_hz());
     505             : 
     506             : #if AP_STATS_ENABLED
     507             :     // Update stats "flying" time
     508       12526 :     AP::stats()->set_flying(g2.motors.active());
     509             : #endif
     510       12526 : }
     511             : 
     512      629048 : void Rover::update_current_mode(void)
     513             : {
     514             :     // check for emergency stop
     515      629048 :     if (SRV_Channels::get_emergency_stop()) {
     516             :         // relax controllers, motor stopping done at output level
     517         417 :         g2.attitude_control.relax_I();
     518             :     }
     519             : 
     520      629048 :     control_mode->update();
     521      629048 : }
     522             : 
     523             : // vehicle specific waypoint info helpers
     524       12526 : bool Rover::get_wp_distance_m(float &distance) const
     525             : {
     526             :     // see GCS_MAVLINK_Rover::send_nav_controller_output()
     527       12526 :     if (!rover.control_mode->is_autopilot_mode()) {
     528        7395 :         return false;
     529             :     }
     530        5131 :     distance = control_mode->get_distance_to_destination();
     531        5131 :     return true;
     532             : }
     533             : 
     534             : // vehicle specific waypoint info helpers
     535        5131 : bool Rover::get_wp_bearing_deg(float &bearing) const
     536             : {
     537             :     // see GCS_MAVLINK_Rover::send_nav_controller_output()
     538        5131 :     if (!rover.control_mode->is_autopilot_mode()) {
     539           0 :         return false;
     540             :     }
     541        5131 :     bearing = control_mode->wp_bearing();
     542        5131 :     return true;
     543             : }
     544             : 
     545             : // vehicle specific waypoint info helpers
     546        5131 : bool Rover::get_wp_crosstrack_error_m(float &xtrack_error) const
     547             : {
     548             :     // see GCS_MAVLINK_Rover::send_nav_controller_output()
     549        5131 :     if (!rover.control_mode->is_autopilot_mode()) {
     550           0 :         return false;
     551             :     }
     552        5131 :     xtrack_error = control_mode->crosstrack_error_m();
     553        5131 :     return true;
     554             : }
     555             : 
     556             : 
     557             : Rover rover;
     558             : AP_Vehicle& vehicle = rover;
     559             : 
     560         285 : AP_HAL_MAIN_CALLBACKS(&rover);

Generated by: LCOV version 1.14