LCOV - code coverage report
Current view: top level - home/pbarker/rc/ardupilot/ArduCopter - mode_systemid.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 5 231 2.2 %
Date: 2026-09-09 11:02:08 Functions: 2 7 28.6 %

          Line data    Source code
       1             : #include "Copter.h"
       2             : #include <AP_Math/control.h>
       3             : 
       4             : #if MODE_SYSTEMID_ENABLED
       5             : 
       6             : /*
       7             :  * Init and run calls for systemId, flight mode
       8             :  */
       9             : 
      10             : const AP_Param::GroupInfo ModeSystemId::var_info[] = {
      11             : 
      12             :     // @Param: _AXIS
      13             :     // @DisplayName: System identification axis
      14             :     // @Description: Controls which axis are being excited.  Set to non-zero to see more parameters
      15             :     // @User: Standard
      16             :     // @Values: 0:None, 1:Input Roll Angle, 2:Input Pitch Angle, 3:Input Yaw Angle, 4:Recovery Roll Angle, 5:Recovery Pitch Angle, 6:Recovery Yaw Angle, 7:Rate Roll, 8:Rate Pitch, 9:Rate Yaw, 10:Mixer Roll, 11:Mixer Pitch, 12:Mixer Yaw, 13:Mixer Thrust, 14:Measured Lateral Position, 15:Measured Longitudinal Position, 16:Measured Lateral Velocity, 17:Measured Longitudinal Velocity, 18:Input Lateral Velocity, 19:Input Longitudinal Velocity
      17             :     AP_GROUPINFO_FLAGS("_AXIS", 1, ModeSystemId, axis, 0, AP_PARAM_FLAG_ENABLE),
      18             : 
      19             :     // @Param: _MAGNITUDE
      20             :     // @DisplayName: System identification Chirp Magnitude
      21             :     // @Description: Magnitude of sweep in deg, deg/s and 0-1 for mixer outputs.
      22             :     // @User: Standard
      23             :     AP_GROUPINFO("_MAGNITUDE", 2, ModeSystemId, waveform_magnitude, 15),
      24             : 
      25             :     // @Param: _F_START_HZ
      26             :     // @DisplayName: System identification Start Frequency
      27             :     // @Description: Frequency at the start of the sweep
      28             :     // @Range: 0.01 100
      29             :     // @Units: Hz
      30             :     // @User: Standard
      31             :     AP_GROUPINFO("_F_START_HZ", 3, ModeSystemId, frequency_start, 0.5f),
      32             : 
      33             :     // @Param: _F_STOP_HZ
      34             :     // @DisplayName: System identification Stop Frequency
      35             :     // @Description: Frequency at the end of the sweep
      36             :     // @Range: 0.01 100
      37             :     // @Units: Hz
      38             :     // @User: Standard
      39             :     AP_GROUPINFO("_F_STOP_HZ", 4, ModeSystemId, frequency_stop, 40),
      40             : 
      41             :     // @Param: _T_FADE_IN
      42             :     // @DisplayName: System identification Fade in time
      43             :     // @Description: Time to reach maximum amplitude of sweep
      44             :     // @Range: 0 20
      45             :     // @Units: s
      46             :     // @User: Standard
      47             :     AP_GROUPINFO("_T_FADE_IN", 5, ModeSystemId, time_fade_in, 15),
      48             : 
      49             :     // @Param: _T_REC
      50             :     // @DisplayName: System identification Total Sweep length
      51             :     // @Description: Time taken to complete the sweep
      52             :     // @Range: 0 255
      53             :     // @Units: s
      54             :     // @User: Standard
      55             :     AP_GROUPINFO("_T_REC", 6, ModeSystemId, time_record, 70),
      56             : 
      57             :     // @Param: _T_FADE_OUT
      58             :     // @DisplayName: System identification Fade out time
      59             :     // @Description: Time to reach zero amplitude at the end of the sweep
      60             :     // @Range: 0 5
      61             :     // @Units: s
      62             :     // @User: Standard
      63             :     AP_GROUPINFO("_T_FADE_OUT", 7, ModeSystemId, time_fade_out, 2),
      64             : 
      65             :     AP_GROUPEND
      66             : };
      67             : 
      68        1001 : ModeSystemId::ModeSystemId(void) : Mode()
      69             : {
      70        1001 :     AP_Param::setup_object_defaults(this, var_info);
      71        1001 : }
      72             : 
      73             : #define SYSTEM_ID_DELAY     1.0f      // time in seconds waited after system id mode change for frequency sweep injection
      74             : 
      75             : // Return true if this mode is enabled, used by MAVLink available modes
      76       75223 : bool ModeSystemId::enabled() const
      77             : {
      78       75223 :     return axis != 0;
      79             : }
      80             : 
      81             : // systemId_init - initialise systemId controller
      82           0 : bool ModeSystemId::init(bool ignore_checks)
      83             : {
      84             :     // check if enabled
      85           0 :     if (!enabled()) {
      86           0 :         gcs().send_text(MAV_SEVERITY_WARNING, "No axis selected, SID_AXIS = 0");
      87           0 :         return false;
      88             :     }
      89             : 
      90             :     // ensure we are flying
      91           0 :     if (!copter.motors->armed() || !copter.ap.auto_armed || copter.ap.land_complete) {
      92           0 :         gcs().send_text(MAV_SEVERITY_WARNING, "Aircraft must be flying");
      93           0 :         return false;
      94             :     }
      95             : 
      96           0 :     if (!is_poscontrol_axis_type()) {
      97             : 
      98             :         // System ID is being done on the attitude control loops
      99             : 
     100             :         // Can only switch into System ID Axes 1-13 with a flight mode that has manual throttle
     101           0 :         if (!copter.flightmode->has_manual_throttle()) {
     102           0 :             gcs().send_text(MAV_SEVERITY_WARNING, "Axis requires manual throttle");
     103           0 :             return false;
     104             :         }
     105             : 
     106             : #if FRAME_CONFIG == HELI_FRAME
     107           0 :         copter.input_manager.set_use_stab_col(true);
     108             : #endif
     109             : 
     110             :     } else {
     111             : 
     112             :         // System ID is being done on the position control loops
     113             : 
     114             :         // Can only switch into System ID Axes 14-19 from Loiter flight mode
     115           0 :         if (copter.flightmode->mode_number() != Mode::Number::LOITER) {
     116           0 :             gcs().send_text(MAV_SEVERITY_WARNING, "Axis requires switch from Loiter");
     117           0 :             return false;
     118             :         }
     119             : 
     120             :         // set horizontal speed and acceleration limits
     121           0 :         pos_control->NE_set_max_speed_accel_m(wp_nav->get_default_speed_NE_ms(), wp_nav->get_wp_acceleration_mss());
     122           0 :         pos_control->NE_set_correction_speed_accel_m(wp_nav->get_default_speed_NE_ms(), wp_nav->get_wp_acceleration_mss());
     123             : 
     124             :         // initialise the horizontal position controller
     125           0 :         if (!pos_control->NE_is_active()) {
     126           0 :             pos_control->NE_init_controller();
     127             :         }
     128             : 
     129             :         // set vertical speed and acceleration limits
     130           0 :         pos_control->D_set_max_speed_accel_m(wp_nav->get_default_speed_down_ms(), wp_nav->get_default_speed_up_ms(), wp_nav->get_accel_D_mss());
     131           0 :         pos_control->D_set_correction_speed_accel_m(wp_nav->get_default_speed_down_ms(), wp_nav->get_default_speed_up_ms(), wp_nav->get_accel_D_mss());
     132             : 
     133             :         // initialise the vertical position controller
     134           0 :         if (!pos_control->D_is_active()) {
     135           0 :             pos_control->D_init_controller();
     136             :         }
     137           0 :         target_pos_ne_m = pos_control->get_pos_estimate_NED_m().xy();
     138             :     }
     139             : 
     140           0 :     att_bf_feedforward = attitude_control->get_bf_feedforward();
     141           0 :     waveform_time = 0.0f;
     142           0 :     time_const_freq = 2.0f / frequency_start; // Two full cycles at the starting frequency
     143           0 :     systemid_state = SystemIDModeState::SYSTEMID_STATE_TESTING;
     144           0 :     log_subsample = 0;
     145             : 
     146           0 :     chirp_input.init(time_record, frequency_start, frequency_stop, time_fade_in, time_fade_out, time_const_freq);
     147             : 
     148           0 :     gcs().send_text(MAV_SEVERITY_INFO, "SystemID Starting: axis=%d", (unsigned)axis);
     149             : 
     150             : #if HAL_LOGGING_ENABLED
     151           0 :     copter.Log_Write_SysID_Setup(axis, waveform_magnitude, frequency_start, frequency_stop, time_fade_in, time_const_freq, time_record, time_fade_out);
     152             : #endif
     153             : 
     154           0 :     return true;
     155             : }
     156             : 
     157             : // systemId_exit - clean up systemId controller before exiting
     158           0 : void ModeSystemId::exit()
     159             : {
     160             :     // reset the feedforward enabled parameter to the initialized state
     161           0 :     attitude_control->bf_feedforward(att_bf_feedforward);
     162           0 : }
     163             : 
     164             : // systemId_run - runs the systemId controller
     165             : // should be called at 100hz or more
     166           0 : void ModeSystemId::run()
     167             : {
     168           0 :     float target_roll_rad = 0.0f;
     169           0 :     float target_pitch_rad = 0.0f;
     170           0 :     float target_yaw_rate_rads = 0.0f;
     171           0 :     float pilot_throttle_scaled = 0.0f;
     172           0 :     float target_climb_rate_ms = 0.0f;
     173           0 :     Vector2f input_vel_ne_ms;
     174             : 
     175           0 :     if (!is_poscontrol_axis_type()) {
     176             : 
     177             :         // convert pilot input to lean angles
     178           0 :         get_pilot_desired_lean_angles_rad(target_roll_rad, target_pitch_rad, attitude_control->lean_angle_max_rad(), attitude_control->lean_angle_max_rad());
     179             : 
     180             :         // get pilot's desired yaw rate
     181           0 :         target_yaw_rate_rads = get_pilot_desired_yaw_rate_rads();
     182             : 
     183           0 :         if (!motors->armed()) {
     184             :             // Motors should be Stopped
     185           0 :             motors->set_desired_spool_state(AP_Motors::DesiredSpoolState::SHUT_DOWN);
     186             :         // Tradheli doesn't set spool state to ground idle when throttle stick is zero.  Ground idle only set when
     187             :         // motor interlock is disabled.
     188           0 :         } else if (copter.ap.throttle_zero && !copter.is_tradheli()) {
     189             :             // Attempting to Land
     190           0 :             motors->set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
     191             :         } else {
     192           0 :             motors->set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
     193             :         }
     194             : 
     195           0 :         switch (motors->get_spool_state()) {
     196           0 :         case AP_Motors::SpoolState::SHUT_DOWN:
     197             :             // Motors Stopped
     198           0 :             attitude_control->reset_yaw_target_and_rate();
     199           0 :             attitude_control->reset_rate_controller_I_terms();
     200           0 :             break;
     201             : 
     202           0 :         case AP_Motors::SpoolState::GROUND_IDLE:
     203             :             // Landed
     204             :             // Tradheli initializes targets when going from disarmed to armed state.
     205             :             // init_targets_on_arming is always set true for multicopter.
     206           0 :             if (motors->init_targets_on_arming()) {
     207           0 :                 attitude_control->reset_yaw_target_and_rate();
     208           0 :                 attitude_control->reset_rate_controller_I_terms_smoothly();
     209             :             }
     210           0 :             break;
     211             : 
     212           0 :         case AP_Motors::SpoolState::THROTTLE_UNLIMITED:
     213             :             // clear landing flag above zero throttle
     214           0 :             if (!motors->limit.throttle_lower) {
     215           0 :                 set_land_complete(false);
     216             :             }
     217           0 :             break;
     218             : 
     219           0 :         case AP_Motors::SpoolState::SPOOLING_UP:
     220             :         case AP_Motors::SpoolState::SPOOLING_DOWN:
     221             :             // do nothing
     222           0 :             break;
     223             :         }
     224             : 
     225             :         // get pilot's desired throttle
     226             : #if FRAME_CONFIG == HELI_FRAME
     227           0 :         pilot_throttle_scaled = copter.input_manager.get_pilot_desired_collective(channel_throttle->get_control_in());
     228             : #else
     229           0 :         pilot_throttle_scaled = get_pilot_desired_throttle();
     230             : #endif
     231             : 
     232             :     }
     233             : 
     234           0 :     if ((systemid_state == SystemIDModeState::SYSTEMID_STATE_TESTING) &&
     235           0 :         (!is_positive(frequency_start) || !is_positive(frequency_stop) || is_negative(time_fade_in) || !is_positive(time_record) || is_negative(time_fade_out) || (time_record <= time_const_freq))) {
     236           0 :         systemid_state = SystemIDModeState::SYSTEMID_STATE_STOPPED;
     237           0 :         gcs().send_text(MAV_SEVERITY_INFO, "SystemID Parameter Error");
     238             :     }
     239             : 
     240           0 :     waveform_time += G_Dt;
     241           0 :     waveform_sample = chirp_input.update(waveform_time - SYSTEM_ID_DELAY, waveform_magnitude);
     242           0 :     waveform_freq_rads = chirp_input.get_frequency_rads();
     243           0 :     Vector2f disturb_state;
     244           0 :     switch (systemid_state) {
     245           0 :         case SystemIDModeState::SYSTEMID_STATE_STOPPED:
     246           0 :             attitude_control->bf_feedforward(att_bf_feedforward);
     247           0 :             break;
     248           0 :         case SystemIDModeState::SYSTEMID_STATE_TESTING:
     249             : 
     250           0 :             if (copter.ap.land_complete) {
     251           0 :                 systemid_state = SystemIDModeState::SYSTEMID_STATE_STOPPED;
     252           0 :                 gcs().send_text(MAV_SEVERITY_INFO, "SystemID Stopped: Landed");
     253           0 :                 break;
     254             :             }
     255           0 :             if (attitude_control->lean_angle_rad() > attitude_control->lean_angle_max_rad()) {
     256           0 :                 systemid_state = SystemIDModeState::SYSTEMID_STATE_STOPPED;
     257           0 :                 gcs().send_text(MAV_SEVERITY_INFO, "SystemID Stopped: lean=%f max=%f", (double)degrees(attitude_control->lean_angle_rad()), (double)degrees(attitude_control->lean_angle_max_rad()));
     258           0 :                 break;
     259             :             }
     260           0 :             if (waveform_time > SYSTEM_ID_DELAY + time_fade_in + time_const_freq + time_record + time_fade_out) {
     261           0 :                 systemid_state = SystemIDModeState::SYSTEMID_STATE_STOPPED;
     262           0 :                 gcs().send_text(MAV_SEVERITY_INFO, "SystemID Finished");
     263           0 :                 break;
     264             :             }
     265             : 
     266           0 :             switch ((AxisType)axis.get()) {
     267           0 :                 case AxisType::NONE:
     268           0 :                     systemid_state = SystemIDModeState::SYSTEMID_STATE_STOPPED;
     269           0 :                     gcs().send_text(MAV_SEVERITY_INFO, "SystemID Stopped: axis = 0");
     270           0 :                     break;
     271           0 :                 case AxisType::INPUT_ROLL:
     272           0 :                     target_roll_rad += radians(waveform_sample);
     273           0 :                     break;
     274           0 :                 case AxisType::INPUT_PITCH:
     275           0 :                     target_pitch_rad += radians(waveform_sample);
     276           0 :                     break;
     277           0 :                 case AxisType::INPUT_YAW:
     278           0 :                     target_yaw_rate_rads += radians(waveform_sample);
     279           0 :                     break;
     280           0 :                 case AxisType::RECOVER_ROLL:
     281           0 :                     target_roll_rad += radians(waveform_sample);
     282           0 :                     attitude_control->bf_feedforward(false);
     283           0 :                     break;
     284           0 :                 case AxisType::RECOVER_PITCH:
     285           0 :                     target_pitch_rad += radians(waveform_sample);
     286           0 :                     attitude_control->bf_feedforward(false);
     287           0 :                     break;
     288           0 :                 case AxisType::RECOVER_YAW:
     289           0 :                     target_yaw_rate_rads += radians(waveform_sample);
     290           0 :                     attitude_control->bf_feedforward(false);
     291           0 :                     break;
     292           0 :                 case AxisType::RATE_ROLL:
     293           0 :                     attitude_control->rate_bf_roll_sysid_rads(radians(waveform_sample));
     294           0 :                     break;
     295           0 :                 case AxisType::RATE_PITCH:
     296           0 :                     attitude_control->rate_bf_pitch_sysid_rads(radians(waveform_sample));
     297           0 :                     break;
     298           0 :                 case AxisType::RATE_YAW:
     299           0 :                     attitude_control->rate_bf_yaw_sysid_rads(radians(waveform_sample));
     300           0 :                     break;
     301           0 :                 case AxisType::MIX_ROLL:
     302           0 :                     attitude_control->actuator_roll_sysid(waveform_sample);
     303           0 :                     break;
     304           0 :                 case AxisType::MIX_PITCH:
     305           0 :                     attitude_control->actuator_pitch_sysid(waveform_sample);
     306           0 :                     break;
     307           0 :                 case AxisType::MIX_YAW:
     308           0 :                     attitude_control->actuator_yaw_sysid(waveform_sample);
     309           0 :                     break;
     310           0 :                 case AxisType::MIX_THROTTLE:
     311           0 :                     pilot_throttle_scaled += waveform_sample;
     312           0 :                     break;
     313           0 :                 case AxisType::DISTURB_POS_LAT:
     314           0 :                     disturb_state.x = 0.0f;
     315           0 :                     disturb_state.y = waveform_sample;
     316           0 :                     disturb_state.rotate(attitude_control->get_att_target_euler_rad().z);
     317           0 :                     pos_control->set_disturb_pos_NE_m(disturb_state);
     318           0 :                     break;
     319           0 :                 case AxisType::DISTURB_POS_LONG:
     320           0 :                     disturb_state.x = waveform_sample;
     321           0 :                     disturb_state.y = 0.0f;
     322           0 :                     disturb_state.rotate(attitude_control->get_att_target_euler_rad().z);
     323           0 :                     pos_control->set_disturb_pos_NE_m(disturb_state);
     324           0 :                     break;
     325           0 :                 case AxisType::DISTURB_VEL_LAT:
     326           0 :                     disturb_state.x = 0.0f;
     327           0 :                     disturb_state.y = waveform_sample;
     328           0 :                     disturb_state.rotate(attitude_control->get_att_target_euler_rad().z);
     329           0 :                     pos_control->set_disturb_vel_NE_ms(disturb_state);
     330           0 :                     break;
     331           0 :                 case AxisType::DISTURB_VEL_LONG:
     332           0 :                     disturb_state.x = waveform_sample;
     333           0 :                     disturb_state.y = 0.0f;
     334           0 :                     disturb_state.rotate(attitude_control->get_att_target_euler_rad().z);
     335           0 :                     pos_control->set_disturb_vel_NE_ms(disturb_state);
     336           0 :                     break;
     337           0 :                 case AxisType::INPUT_VEL_LAT:
     338           0 :                     input_vel_ne_ms.x = 0.0f;
     339           0 :                     input_vel_ne_ms.y = waveform_sample;
     340           0 :                     input_vel_ne_ms.rotate(attitude_control->get_att_target_euler_rad().z);
     341           0 :                     break;
     342           0 :                 case AxisType::INPUT_VEL_LONG:
     343           0 :                     input_vel_ne_ms.x = waveform_sample;
     344           0 :                     input_vel_ne_ms.y = 0.0f;
     345           0 :                     input_vel_ne_ms.rotate(attitude_control->get_att_target_euler_rad().z);
     346           0 :                     break;
     347             :             }
     348           0 :             break;
     349             :     }
     350             : 
     351           0 :     if (!is_poscontrol_axis_type()) {
     352             : 
     353             :         // call attitude controller
     354           0 :         attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw_rad(target_roll_rad, target_pitch_rad, target_yaw_rate_rads);
     355             : 
     356             :         // output pilot's throttle
     357           0 :         attitude_control->set_throttle_out(pilot_throttle_scaled, !copter.is_tradheli(), g.throttle_filt);
     358             :         
     359             :     } else {
     360             : 
     361             :         // relax loiter target if we might be landed
     362           0 :         if (copter.ap.land_complete_maybe) {
     363           0 :             pos_control->NE_soften_for_landing();
     364             :         }
     365             : 
     366           0 :         Vector2f accel_ne_mss;
     367           0 :         target_pos_ne_m += input_vel_ne_ms.topostype() * G_Dt;
     368           0 :         if (is_positive(G_Dt)) {
     369           0 :             accel_ne_mss = (input_vel_ne_ms - input_vel_last_ne_ms) / G_Dt;
     370           0 :             input_vel_last_ne_ms = input_vel_ne_ms;
     371             :         }
     372           0 :         pos_control->set_pos_vel_accel_NE_m(target_pos_ne_m, input_vel_ne_ms, accel_ne_mss);
     373             : 
     374             :         // run pos controller
     375           0 :         pos_control->NE_update_controller();
     376             : 
     377             :         // call attitude controller
     378           0 :         attitude_control->input_thrust_vector_rate_heading_rads(pos_control->get_thrust_vector(), target_yaw_rate_rads, false);
     379             : 
     380             :         // Send the commanded climb rate to the position controller
     381           0 :         pos_control->D_set_pos_target_from_climb_rate_ms(target_climb_rate_ms);
     382             : 
     383             :         // run the vertical position controller and set output throttle
     384           0 :         pos_control->D_update_controller();
     385             :     }
     386             : 
     387           0 :     if (log_subsample <= 0) {
     388           0 :         log_data();
     389           0 :         if (copter.should_log(MASK_LOG_ATTITUDE_FAST) && copter.should_log(MASK_LOG_ATTITUDE_MED)) {
     390           0 :             log_subsample = 1;
     391           0 :         } else if (copter.should_log(MASK_LOG_ATTITUDE_FAST)) {
     392           0 :             log_subsample = 2;
     393           0 :         } else if (copter.should_log(MASK_LOG_ATTITUDE_MED)) {
     394           0 :             log_subsample = 4;
     395             :         } else {
     396           0 :             log_subsample = 8;
     397             :         }
     398             :     }
     399           0 :     log_subsample -= 1;
     400           0 : }
     401             : 
     402             : // log system id and attitude
     403           0 : void ModeSystemId::log_data() const
     404             : {
     405           0 :     Vector3f delta_angle;
     406             :     float delta_angle_dt;
     407           0 :     copter.ins.get_delta_angle(delta_angle, delta_angle_dt);
     408             : 
     409           0 :     Vector3f delta_velocity;
     410             :     float delta_velocity_dt;
     411           0 :     copter.ins.get_delta_velocity(delta_velocity, delta_velocity_dt);
     412             : 
     413           0 :     if (is_positive(delta_angle_dt) && is_positive(delta_velocity_dt)) {
     414           0 :         copter.Log_Write_SysID_Data(waveform_time, waveform_sample, waveform_freq_rads / (2 * M_PI), degrees(delta_angle.x / delta_angle_dt), degrees(delta_angle.y / delta_angle_dt), degrees(delta_angle.z / delta_angle_dt), delta_velocity.x / delta_velocity_dt, delta_velocity.y / delta_velocity_dt, delta_velocity.z / delta_velocity_dt);
     415             :     }
     416             : 
     417             :     // Full rate logging of attitude, rate and pid loops
     418           0 :     copter.Log_Write_Attitude();
     419           0 :     copter.Log_Write_Rate();
     420           0 :     copter.Log_Write_PIDS();
     421             : 
     422           0 :     if (is_poscontrol_axis_type()) {
     423           0 :         pos_control->write_log();
     424           0 :         copter.logger.Write_PID(LOG_PIDN_MSG, pos_control->NE_get_vel_pid().get_pid_info_x());
     425           0 :         copter.logger.Write_PID(LOG_PIDE_MSG, pos_control->NE_get_vel_pid().get_pid_info_y());
     426             : 
     427             :     }
     428           0 : }
     429             : 
     430           0 : bool ModeSystemId::is_poscontrol_axis_type() const
     431             : {
     432           0 :     bool ret = false;
     433             : 
     434           0 :     switch ((AxisType)axis.get()) {
     435           0 :         case AxisType::DISTURB_POS_LAT:
     436             :         case AxisType::DISTURB_POS_LONG:
     437             :         case AxisType::DISTURB_VEL_LAT:
     438             :         case AxisType::DISTURB_VEL_LONG:
     439             :         case AxisType::INPUT_VEL_LAT:
     440             :         case AxisType::INPUT_VEL_LONG:
     441           0 :             ret = true;
     442           0 :             break;
     443           0 :         default:
     444           0 :             break;
     445             :         }
     446             : 
     447           0 :     return ret;
     448             : }
     449             : 
     450             : #endif

Generated by: LCOV version 1.14