Line data Source code
1 : #include "Copter.h" 2 : #include <AP_ESC_Telem/AP_ESC_Telem.h> 3 : 4 : /***************************************************************************** 5 : * The init_ardupilot function processes everything we need for an in - air restart 6 : * We will determine later if we are actually on the ground and process a 7 : * ground start in that case. 8 : * 9 : *****************************************************************************/ 10 : 11 94293383 : static void failsafe_check_static() 12 : { 13 94293383 : copter.failsafe_check(); 14 94293383 : } 15 : 16 1001 : void Copter::init_ardupilot() 17 : { 18 : // init winch 19 : #if AP_WINCH_ENABLED 20 1001 : g2.winch.init(); 21 : #endif 22 : 23 : // initialise notify system 24 1001 : notify.init(); 25 1001 : notify_flight_mode(); 26 : 27 : // initialise battery monitor 28 1001 : battery.init(); 29 : 30 : #if AP_RSSI_ENABLED 31 : // Init RSSI 32 1001 : rssi.init(); 33 : #endif 34 : 35 1001 : barometer.init(); 36 : 37 : // setup telem slots with serial ports 38 1001 : gcs().setup_uarts(); 39 : 40 : #if OSD_ENABLED 41 1001 : osd.init(); 42 : #endif 43 : 44 : // update motor interlock state 45 1001 : update_using_interlock(); 46 : 47 : #if FRAME_CONFIG == HELI_FRAME 48 : // trad heli specific initialisation 49 83 : heli_init(); 50 : #endif 51 : #if FRAME_CONFIG == HELI_FRAME 52 83 : input_manager.set_loop_rate(scheduler.get_loop_rate_hz()); 53 : #endif 54 : 55 1001 : init_rc_in(); // sets up rc channels from radio 56 : 57 : #if AP_RANGEFINDER_ENABLED 58 : // initialise surface to be tracked in SurfaceTracking 59 : // must be before rc init to not override initial switch position 60 1001 : surface_tracking.init((SurfaceTracking::Surface)copter.g2.surftrak_mode.get()); 61 : #endif 62 : 63 : // allocate the motors class 64 1001 : allocate_motors(); 65 : 66 : // initialise rc channels including setting mode 67 1001 : rc().init(); 68 : 69 : // sets up motors and output to escs 70 1001 : init_rc_out(); 71 : 72 : // check if we should enter esc calibration mode 73 1001 : esc_calibration_startup_check(); 74 : 75 : // motors initialised so parameters can be sent 76 1001 : ap.initialised_params = true; 77 : 78 : #if AP_RELAY_ENABLED 79 1001 : relay.init(); 80 : #endif 81 : 82 : /* 83 : * setup the 'main loop is dead' check. Note that this relies on 84 : * the RC library being initialised. 85 : */ 86 1001 : hal.scheduler->register_timer_failsafe(failsafe_check_static, 1000); 87 : 88 : // Do GPS init 89 1001 : gps.set_log_gps_bit(MASK_LOG_GPS); 90 1001 : gps.init(); 91 : 92 1001 : AP::compass().set_log_bit(MASK_LOG_COMPASS); 93 1001 : AP::compass().init(); 94 : 95 : #if AP_AIRSPEED_ENABLED 96 1001 : airspeed.set_log_bit(MASK_LOG_IMU); 97 : #endif 98 : 99 : #if AP_OAPATHPLANNER_ENABLED 100 1001 : g2.oa.init(); 101 : #endif 102 : 103 1001 : attitude_control->parameter_sanity_check(); 104 : 105 : #if AP_OPTICALFLOW_ENABLED 106 : // initialise optical flow sensor 107 1001 : optflow.init(MASK_LOG_OPTFLOW); 108 : #endif // AP_OPTICALFLOW_ENABLED 109 : 110 : #if HAL_MOUNT_ENABLED 111 : // initialise camera mount 112 1001 : camera_mount.init(); 113 : #endif 114 : 115 : #if AP_CAMERA_ENABLED 116 : // initialise camera 117 1001 : camera.init(); 118 : #endif 119 : 120 : #if AC_PRECLAND_ENABLED 121 : // initialise precision landing 122 1001 : init_precland(); 123 : #endif 124 : 125 : #if AP_LANDINGGEAR_ENABLED 126 : // initialise landing gear position 127 1001 : landinggear.init(); 128 : #endif 129 : 130 : #ifdef USERHOOK_INIT 131 : USERHOOK_INIT 132 : #endif 133 : 134 : // read Baro pressure at ground 135 : //----------------------------- 136 1001 : barometer.set_log_baro_bit(MASK_LOG_IMU); 137 1001 : barometer.calibrate(); 138 : 139 : #if AP_RANGEFINDER_ENABLED 140 : // initialise rangefinder 141 998 : init_rangefinder(); 142 : #endif 143 : 144 : #if HAL_PROXIMITY_ENABLED 145 : // init proximity sensor 146 998 : g2.proximity.init(); 147 : #endif 148 : 149 : #if MODE_AUTO_ENABLED 150 : // initialise mission library 151 998 : mode_auto.mission.init(); 152 : #if HAL_LOGGING_ENABLED 153 998 : mode_auto.mission.set_log_start_mission_item_bit(MASK_LOG_CMD); 154 : #endif 155 : #endif 156 : 157 : #if MODE_SMARTRTL_ENABLED 158 : // initialize SmartRTL 159 998 : g2.smart_rtl.init(); 160 : #endif 161 : 162 : #if HAL_LOGGING_ENABLED 163 : // initialise AP_Logger library 164 998 : logger.setVehicle_Startup_Writer(FUNCTOR_BIND(&copter, &Copter::Log_Write_Vehicle_Startup_Messages, void)); 165 : #endif 166 : 167 998 : startup_INS_ground(); 168 : 169 : #if AC_CUSTOMCONTROL_MULTI_ENABLED 170 916 : custom_control.init(); 171 : #endif 172 : 173 : // set landed flags 174 998 : set_land_complete(true); 175 998 : set_land_complete_maybe(true); 176 : 177 : // enable CPU failsafe 178 998 : failsafe_enable(); 179 : 180 998 : ins.set_log_raw_bit(MASK_LOG_IMU_RAW); 181 : 182 998 : motors->output_min(); // output lowest possible value to motors 183 : 184 : // attempt to set the initial_mode, else set to STABILIZE 185 998 : if (!set_mode((enum Mode::Number)g.initial_mode.get(), ModeReason::INITIALISED)) { 186 : // set mode to STABILIZE will trigger mode change notification to pilot 187 0 : set_mode(Mode::Number::STABILIZE, ModeReason::UNAVAILABLE); 188 : } 189 : 190 998 : pos_variance_filt.set_cutoff_frequency(g2.fs_ekf_filt_hz); 191 998 : vel_variance_filt.set_cutoff_frequency(g2.fs_ekf_filt_hz); 192 : 193 : // flag that initialisation has completed 194 998 : ap.initialised = true; 195 998 : } 196 : 197 : 198 : //****************************************************************************** 199 : //This function does all the calibrations, etc. that we need during a ground start 200 : //****************************************************************************** 201 998 : void Copter::startup_INS_ground() 202 : { 203 : // initialise ahrs (may push imu calibration into the mpu6000 if using that device). 204 998 : ahrs.init(); 205 998 : ahrs.set_vehicle_class(AP_AHRS::VehicleClass::COPTER); 206 : 207 : // Warm up and calibrate gyro offsets 208 998 : ins.init(scheduler.get_loop_rate_hz()); 209 : 210 : // reset ahrs including gyro bias 211 998 : ahrs.reset(); 212 998 : } 213 : 214 : // position_ok - returns true if the horizontal absolute position is ok and home position is set 215 4788119 : bool Copter::position_ok() const 216 : { 217 : // return false if ekf failsafe has triggered 218 4788119 : if (failsafe.ekf) { 219 23127 : return false; 220 : } 221 : 222 : // check ekf position estimate 223 4764992 : return (ekf_has_absolute_position() || ekf_has_relative_position()); 224 : } 225 : 226 : // ekf_has_absolute_position - returns true if the EKF can provide an absolute WGS-84 position estimate 227 5419672 : bool Copter::ekf_has_absolute_position() const 228 : { 229 5419672 : if (!ahrs.have_inertial_nav()) { 230 : // do not allow navigation with dcm position 231 99086 : return false; 232 : } 233 : 234 : // if disarmed we accept a predicted horizontal position 235 5320586 : if (!motors->armed()) { 236 1487735 : if (ahrs.has_status(AP_AHRS::Status::HORIZ_POS_ABS)) { 237 598213 : return true; 238 : } 239 889522 : if (ahrs.has_status(AP_AHRS::Status::PRED_HORIZ_POS_ABS)) { 240 9 : return true; 241 : } 242 889513 : return false; 243 : } 244 : 245 : // once armed we require a good absolute position and EKF must not be in const_pos_mode 246 3832851 : if (ahrs.has_status(AP_AHRS::Status::CONST_POS_MODE)) { 247 4375 : return false; 248 : } 249 3828476 : return ahrs.has_status(AP_AHRS::Status::HORIZ_POS_ABS); 250 : } 251 : 252 : // ekf_has_relative_position - returns true if the EKF can provide a position estimate relative to it's starting position 253 2464711 : bool Copter::ekf_has_relative_position() const 254 : { 255 : // return immediately if EKF not used 256 2464711 : if (!ahrs.have_inertial_nav()) { 257 192569 : return false; 258 : } 259 : 260 : // return immediately if neither optflow nor visual odometry is enabled and dead reckoning is inactive 261 2272142 : bool enabled = false; 262 : #if AP_OPTICALFLOW_ENABLED 263 2272142 : if (optflow.enabled()) { 264 41472 : enabled = true; 265 : } 266 : #endif 267 : #if HAL_VISUALODOM_ENABLED 268 2272142 : if (visual_odom.enabled()) { 269 14640 : enabled = true; 270 : } 271 : #endif 272 2272142 : if (dead_reckoning.active && !dead_reckoning.timeout) { 273 1907 : enabled = true; 274 : } 275 2272142 : if (!enabled) { 276 2214123 : return false; 277 : } 278 : 279 : // if disarmed we accept a predicted horizontal relative position 280 58019 : if (!motors->armed()) { 281 34456 : return ahrs.has_status(AP_AHRS::Status::PRED_HORIZ_POS_REL); 282 : } 283 : 284 23563 : if (ahrs.has_status(AP_AHRS::Status::CONST_POS_MODE)) { 285 0 : return false; 286 : } 287 23563 : if (!ahrs.has_status(AP_AHRS::Status::HORIZ_POS_REL)) { 288 0 : return false; 289 : } 290 23563 : return true; 291 : } 292 : 293 : // returns true if the ekf has a good altitude estimate (required for modes which do AltHold) 294 10381 : bool Copter::ekf_alt_ok() const 295 : { 296 10381 : if (!ahrs.have_inertial_nav()) { 297 : // do not allow alt control with only dcm 298 111 : return false; 299 : } 300 : 301 : // require both vertical velocity and position 302 10270 : if (!ahrs.has_status(AP_AHRS::Status::VERT_POS)) { 303 128 : return false; 304 : } 305 10142 : if (!ahrs.has_status(AP_AHRS::Status::VERT_VEL)) { 306 0 : return false; 307 : } 308 10142 : return true; 309 : } 310 : 311 : // update_auto_armed - update status of auto_armed flag 312 3800955 : void Copter::update_auto_armed() 313 : { 314 : // disarm checks 315 3800955 : if(ap.auto_armed){ 316 : // if motors are disarmed, auto_armed should also be false 317 2437101 : if(!motors->armed()) { 318 28069 : set_auto_armed(false); 319 28069 : return; 320 : } 321 : // if in stabilize or acro flight mode and throttle is zero, auto-armed should become false 322 2409032 : if (flightmode->has_manual_throttle() && ap.throttle_zero && rc().has_valid_input()) { 323 16 : set_auto_armed(false); 324 : } 325 : 326 : }else{ 327 : // arm checks 328 : 329 : // for tradheli if motors are armed and throttle is above zero and the motor is started, auto_armed should be true 330 1363854 : if(motors->armed() && ap.using_interlock) { 331 37571 : if(!ap.throttle_zero && motors->get_spool_state() == AP_Motors::SpoolState::THROTTLE_UNLIMITED) { 332 35 : set_auto_armed(true); 333 : } 334 : // if motors are armed and throttle is above zero auto_armed should be true 335 : // if motors are armed and we are in throw mode, then auto_armed should be true 336 1326283 : } else if (motors->armed() && !ap.using_interlock) { 337 21577 : if(!ap.throttle_zero || flightmode->mode_number() == Mode::Number::THROW) { 338 242 : set_auto_armed(true); 339 : } 340 : } 341 : } 342 : } 343 : 344 : #if HAL_LOGGING_ENABLED 345 : /* 346 : should we log a message type now? 347 : */ 348 142538773 : bool Copter::should_log(uint32_t mask) 349 : { 350 142538773 : return logger.should_log(mask); 351 : } 352 : #endif 353 : 354 : /* 355 : allocate the motors class 356 : */ 357 1001 : void Copter::allocate_motors(void) 358 : { 359 1001 : switch ((AP_Motors::motor_frame_class)g2.frame_class.get()) { 360 : #if FRAME_CONFIG != HELI_FRAME 361 914 : case AP_Motors::MOTOR_FRAME_QUAD: 362 : case AP_Motors::MOTOR_FRAME_HEXA: 363 : case AP_Motors::MOTOR_FRAME_Y6: 364 : case AP_Motors::MOTOR_FRAME_OCTA: 365 : case AP_Motors::MOTOR_FRAME_OCTAQUAD: 366 : case AP_Motors::MOTOR_FRAME_DODECAHEXA: 367 : case AP_Motors::MOTOR_FRAME_DECA: 368 : case AP_Motors::MOTOR_FRAME_SCRIPTING_MATRIX: 369 : default: 370 914 : motors = NEW_NOTHROW AP_MotorsMatrix(copter.scheduler.get_loop_rate_hz()); 371 914 : motors_var_info = AP_MotorsMatrix::var_info; 372 914 : break; 373 : #if AP_MOTORS_TRI_ENABLED 374 1 : case AP_Motors::MOTOR_FRAME_TRI: 375 1 : motors = NEW_NOTHROW AP_MotorsTri(copter.scheduler.get_loop_rate_hz()); 376 1 : motors_var_info = AP_MotorsTri::var_info; 377 1 : AP_Param::set_frame_type_flags(AP_PARAM_FRAME_TRICOPTER); 378 1 : break; 379 : #endif // AP_MOTORS_TRI_ENABLED 380 1 : case AP_Motors::MOTOR_FRAME_SINGLE: 381 1 : motors = NEW_NOTHROW AP_MotorsSingle(copter.scheduler.get_loop_rate_hz()); 382 1 : motors_var_info = AP_MotorsSingle::var_info; 383 1 : break; 384 1 : case AP_Motors::MOTOR_FRAME_COAX: 385 1 : motors = NEW_NOTHROW AP_MotorsCoax(copter.scheduler.get_loop_rate_hz()); 386 1 : motors_var_info = AP_MotorsCoax::var_info; 387 1 : break; 388 0 : case AP_Motors::MOTOR_FRAME_TAILSITTER: 389 0 : motors = NEW_NOTHROW AP_MotorsTailsitter(copter.scheduler.get_loop_rate_hz()); 390 0 : motors_var_info = AP_MotorsTailsitter::var_info; 391 0 : break; 392 1 : case AP_Motors::MOTOR_FRAME_6DOF_SCRIPTING: 393 : #if AP_SCRIPTING_ENABLED 394 1 : motors = NEW_NOTHROW AP_MotorsMatrix_6DoF_Scripting(copter.scheduler.get_loop_rate_hz()); 395 1 : motors_var_info = AP_MotorsMatrix_6DoF_Scripting::var_info; 396 : #endif // AP_SCRIPTING_ENABLED 397 1 : break; 398 0 : case AP_Motors::MOTOR_FRAME_DYNAMIC_SCRIPTING_MATRIX: 399 : #if AP_SCRIPTING_ENABLED 400 0 : motors = NEW_NOTHROW AP_MotorsMatrix_Scripting_Dynamic(copter.scheduler.get_loop_rate_hz()); 401 0 : motors_var_info = AP_MotorsMatrix_Scripting_Dynamic::var_info; 402 : #endif // AP_SCRIPTING_ENABLED 403 0 : break; 404 : #else // FRAME_CONFIG == HELI_FRAME 405 0 : case AP_Motors::MOTOR_FRAME_HELI_DUAL: 406 0 : motors = NEW_NOTHROW AP_MotorsHeli_Dual(copter.scheduler.get_loop_rate_hz()); 407 0 : motors_var_info = AP_MotorsHeli_Dual::var_info; 408 0 : AP_Param::set_frame_type_flags(AP_PARAM_FRAME_HELI); 409 0 : break; 410 : 411 3 : case AP_Motors::MOTOR_FRAME_HELI_QUAD: 412 3 : motors = NEW_NOTHROW AP_MotorsHeli_Quad(copter.scheduler.get_loop_rate_hz()); 413 3 : motors_var_info = AP_MotorsHeli_Quad::var_info; 414 3 : AP_Param::set_frame_type_flags(AP_PARAM_FRAME_HELI); 415 3 : break; 416 : 417 80 : case AP_Motors::MOTOR_FRAME_HELI: 418 : default: 419 80 : motors = NEW_NOTHROW AP_MotorsHeli_Single(copter.scheduler.get_loop_rate_hz()); 420 80 : motors_var_info = AP_MotorsHeli_Single::var_info; 421 80 : AP_Param::set_frame_type_flags(AP_PARAM_FRAME_HELI); 422 80 : break; 423 : #endif 424 : } 425 1001 : if (motors == nullptr) { 426 0 : AP_BoardConfig::allocation_error("FRAME_CLASS=%u", (unsigned)g2.frame_class.get()); 427 : } 428 1001 : AP_Param::load_object_from_eeprom(motors, motors_var_info); 429 : 430 1001 : ahrs_view = ahrs.create_view(ROTATION_NONE); 431 1001 : if (ahrs_view == nullptr) { 432 0 : AP_BoardConfig::allocation_error("AP_AHRS_View"); 433 : } 434 : 435 : #if FRAME_CONFIG != HELI_FRAME 436 918 : if ((AP_Motors::motor_frame_class)g2.frame_class.get() == AP_Motors::MOTOR_FRAME_6DOF_SCRIPTING) { 437 : #if AP_SCRIPTING_ENABLED 438 1 : attitude_control = NEW_NOTHROW AC_AttitudeControl_Multi_6DoF(*ahrs_view, *motors); 439 1 : attitude_control_var_info = AC_AttitudeControl_Multi_6DoF::var_info; 440 : #endif // AP_SCRIPTING_ENABLED 441 : } else { 442 917 : attitude_control = NEW_NOTHROW AC_AttitudeControl_Multi(*ahrs_view, *motors); 443 917 : attitude_control_var_info = AC_AttitudeControl_Multi::var_info; 444 : } 445 : #else 446 83 : attitude_control = NEW_NOTHROW AC_AttitudeControl_Heli(*ahrs_view, *motors); 447 83 : attitude_control_var_info = AC_AttitudeControl_Heli::var_info; 448 : #endif 449 1001 : if (attitude_control == nullptr) { 450 0 : AP_BoardConfig::allocation_error("AttitudeControl"); 451 : } 452 1001 : AP_Param::load_object_from_eeprom(attitude_control, attitude_control_var_info); 453 : 454 1001 : pos_control = NEW_NOTHROW AC_PosControl(*ahrs_view, *motors, *attitude_control); 455 1001 : if (pos_control == nullptr) { 456 0 : AP_BoardConfig::allocation_error("PosControl"); 457 : } 458 1001 : AP_Param::load_object_from_eeprom(pos_control, pos_control->var_info); 459 : 460 : #if AP_GROUNDEFFECT_ENABLED 461 1001 : g2.ground_effect.set_pos_control(*pos_control); 462 : #endif 463 : 464 : #if AP_OAPATHPLANNER_ENABLED 465 1001 : wp_nav = NEW_NOTHROW AC_WPNav_OA(*ahrs_view, *pos_control, *attitude_control); 466 : #else 467 : wp_nav = NEW_NOTHROW AC_WPNav(*ahrs_view, *pos_control, *attitude_control); 468 : #endif 469 1001 : if (wp_nav == nullptr) { 470 0 : AP_BoardConfig::allocation_error("WPNav"); 471 : } 472 1001 : AP_Param::load_object_from_eeprom(wp_nav, wp_nav->var_info); 473 : 474 1001 : loiter_nav = NEW_NOTHROW AC_Loiter(*ahrs_view, *pos_control, *attitude_control); 475 1001 : if (loiter_nav == nullptr) { 476 0 : AP_BoardConfig::allocation_error("LoiterNav"); 477 : } 478 1001 : AP_Param::load_object_from_eeprom(loiter_nav, loiter_nav->var_info); 479 : 480 : #if MODE_CIRCLE_ENABLED 481 1001 : circle_nav = NEW_NOTHROW AC_Circle(*ahrs_view, *pos_control); 482 1001 : if (circle_nav == nullptr) { 483 0 : AP_BoardConfig::allocation_error("CircleNav"); 484 : } 485 1001 : AP_Param::load_object_from_eeprom(circle_nav, circle_nav->var_info); 486 : #endif 487 : 488 : // reload lines from the defaults file that may now be accessible 489 1001 : AP_Param::reload_defaults_file(true); 490 : 491 : // now setup some frame-class specific defaults 492 1001 : switch ((AP_Motors::motor_frame_class)g2.frame_class.get()) { 493 1 : case AP_Motors::MOTOR_FRAME_Y6: 494 1 : attitude_control->get_rate_roll_pid().kP().set_default(0.1); 495 1 : attitude_control->get_rate_roll_pid().kD().set_default(0.006); 496 1 : attitude_control->get_rate_pitch_pid().kP().set_default(0.1); 497 1 : attitude_control->get_rate_pitch_pid().kD().set_default(0.006); 498 1 : attitude_control->get_rate_yaw_pid().kP().set_default(0.15); 499 1 : attitude_control->get_rate_yaw_pid().kI().set_default(0.015); 500 1 : break; 501 1 : case AP_Motors::MOTOR_FRAME_TRI: 502 1 : attitude_control->get_rate_yaw_pid().filt_D_hz().set_default(100); 503 1 : break; 504 999 : default: 505 999 : break; 506 : } 507 : 508 : // brushed 16kHz defaults to 16kHz pulses 509 1001 : if (motors->is_brushed_pwm_type()) { 510 0 : g.rc_speed.set_default(16000); 511 : } 512 : 513 : // upgrade parameters. This must be done after allocating the objects 514 : #if FRAME_CONFIG == HELI_FRAME 515 83 : motors->heli_motors_param_conversions(); 516 : #endif 517 : 518 : // upgrade attitude controller parameters 519 1001 : copter.attitude_control->convert_parameters(); 520 : 521 : // upgrade position controller parameters 522 1001 : copter.pos_control->convert_parameters(); 523 : 524 : // convert wp_nav parameters 525 1001 : copter.wp_nav->convert_parameters(); 526 : 527 : // upgrade loiter navigation parameters 528 1001 : loiter_nav->convert_parameters(); 529 : 530 : #if MODE_CIRCLE_ENABLED 531 1001 : circle_nav->convert_parameters(); 532 : #endif 533 : 534 : // param count could have changed 535 1001 : AP_Param::invalidate_count(); 536 1001 : } 537 : 538 1613835 : bool Copter::is_tradheli() const 539 : { 540 : #if FRAME_CONFIG == HELI_FRAME 541 37866 : return true; 542 : #else 543 1575969 : return false; 544 : #endif 545 : }