void main(int argc, char**argv){ if(argc != 2){ fprintf(stderr,"Error: usage: ./calibrate <file_name>\n"); exit(EXIT_FAILURE); } // Init printf("init\n"); init_gui(); init_motors(); init_sensor(); printf("+---+---+\n"); printf("| 2 | 3 |\n"); printf("+---+---+\n"); printf("| 0 | 1 |\n"); printf("+---+---+\n"); printf(" ^ \n"); printf(" | \n"); printf("Init compass\n"); init_compass(); printf("Calibrate compass\n"); calibrate_location(argv[1]); destroy_sensors(); destroy_motors(); }
void initSensors(void){ // TODO: init the GPS here fd = init_I2C(); init_compass(fd); gpioInit(); gpsRet = init_GPS(); }
void main(int * argv){ signal(SIGINT, signal_handler); fd = init_I2C(); init_compass(fd); gpioInit(); // testTurn(); /**turn(45.0); sleep(1); turn(280.0); sleep(1); turn(310.0); turn(180.0); **/ waypointManager(); //testTurn(); }
void init(int use_http, char *address, int port){ // Setup periferal and library init_gui(); init_motors(); init_sensor(); init_compass(); calibrate_compass(0); // 0 = do not execute a new calibration of the compass // Load ball predefined positions get_positions(POINTS_FILE_NAME, &positions, &n_points); // Start bluetooth if(use_http) bluetooth_test_init(address, port); else bluetooth_init(); //bluetooth_register_and_start(fAction_t, fAck_t, fLead_t, fStart_t, fStop_t, fWait_t, fKick_t, fCancel_t); bluetooth_register_and_start(&follower_action_cb, NULL, &lead_cb, &start_cb, &stop_cb, NULL, NULL, &cancel_cb); // Reset global variables send_action_flag = 1; act = 0; end_game = 0; start_game = 0; wait = 0; cancel = 0; // Waiting for the game start set_light(LIT_LEFT, LIT_GREEN); set_light(LIT_RIGHT, LIT_GREEN); while(!start_game); //start game, robot rank and snake size initialized by start_cb // Initial position home.x = BORDER_X_MAX/2; home.y = (snake_size - robot_rank -1)*40 + 20; center.x = BORDER_X_MAX/4; center.y = BORDER_Y_MAX/2; robot = home; printf("[DEBUG] Starting position X: %d, Y: %d, T: %d\n", robot.x , robot.y, robot.t); update_sensor(SENSOR_GYRO); gyro_init_val = get_sensor_value(SENSOR_GYRO); set_light(LIT_LEFT, LIT_OFF); set_light(LIT_RIGHT, LIT_OFF); }
void Copter::init_ardupilot() { if (!hal.gpio->usb_connected()) { // USB is not connected, this means UART0 may be a Xbee, with // its darned bricking problem. We can't write to it for at // least one second after powering up. Simplest solution for // now is to delay for 1 second. Something more elegant may be // added later delay(1000); } // initialise serial port serial_manager.init_console(); // init vehicle capabilties init_capabilities(); cliSerial->printf("\n\nInit " FIRMWARE_STRING "\n\nFree RAM: %u\n", (unsigned)hal.util->available_memory()); // // Report firmware version code expect on console (check of actual EEPROM format version is done in load_parameters function) // report_version(); // load parameters from EEPROM load_parameters(); BoardConfig.init(); // initialise serial port serial_manager.init(); // init EPM cargo gripper #if EPM_ENABLED == ENABLED epm.init(); #endif // initialise notify system // disable external leds if epm is enabled because of pin conflict on the APM notify.init(true); // initialise battery monitor battery.init(); // Init RSSI rssi.init(); barometer.init(); // Register the mavlink service callback. This will run // anytime there are more than 5ms remaining in a call to // hal.scheduler->delay. hal.scheduler->register_delay_callback(mavlink_delay_cb_static, 5); // we start by assuming USB connected, as we initialed the serial // port with SERIAL0_BAUD. check_usb_mux() fixes this if need be. ap.usb_connected = true; check_usb_mux(); // init the GCS connected to the console gcs[0].setup_uart(serial_manager, AP_SerialManager::SerialProtocol_Console, 0); // init telemetry port gcs[1].setup_uart(serial_manager, AP_SerialManager::SerialProtocol_MAVLink, 0); // setup serial port for telem2 gcs[2].setup_uart(serial_manager, AP_SerialManager::SerialProtocol_MAVLink, 1); // setup serial port for fourth telemetry port (not used by default) gcs[3].setup_uart(serial_manager, AP_SerialManager::SerialProtocol_MAVLink, 2); #if FRSKY_TELEM_ENABLED == ENABLED // setup frsky frsky_telemetry.init(serial_manager); #endif // identify ourselves correctly with the ground station mavlink_system.sysid = g.sysid_this_mav; #if LOGGING_ENABLED == ENABLED log_init(); #endif GCS_MAVLINK::set_dataflash(&DataFlash); // update motor interlock state update_using_interlock(); #if FRAME_CONFIG == HELI_FRAME // trad heli specific initialisation heli_init(); #endif init_rc_in(); // sets up rc channels from radio init_rc_out(); // sets up motors and output to escs // initialise which outputs Servo and Relay events can use ServoRelayEvents.set_channel_mask(~motors.get_motor_mask()); relay.init(); /* * setup the 'main loop is dead' check. Note that this relies on * the RC library being initialised. */ hal.scheduler->register_timer_failsafe(failsafe_check_static, 1000); // Do GPS init gps.init(&DataFlash, serial_manager); if(g.compass_enabled) init_compass(); #if OPTFLOW == ENABLED // make optflow available to AHRS ahrs.set_optflow(&optflow); #endif // init Location class Location_Class::set_ahrs(&ahrs); #if AP_TERRAIN_AVAILABLE && AC_TERRAIN Location_Class::set_terrain(&terrain); wp_nav.set_terrain(&terrain); #endif pos_control.set_dt(MAIN_LOOP_SECONDS); // init the optical flow sensor init_optflow(); #if MOUNT == ENABLED // initialise camera mount camera_mount.init(&DataFlash, serial_manager); #endif #if PRECISION_LANDING == ENABLED // initialise precision landing init_precland(); #endif #ifdef USERHOOK_INIT USERHOOK_INIT #endif #if CLI_ENABLED == ENABLED if (g.cli_enabled) { const char *msg = "\nPress ENTER 3 times to start interactive setup\n"; cliSerial->println(msg); if (gcs[1].initialised && (gcs[1].get_uart() != NULL)) { gcs[1].get_uart()->println(msg); } if (num_gcs > 2 && gcs[2].initialised && (gcs[2].get_uart() != NULL)) { gcs[2].get_uart()->println(msg); } } #endif // CLI_ENABLED #if HIL_MODE != HIL_MODE_DISABLED while (barometer.get_last_update() == 0) { // the barometer begins updating when we get the first // HIL_STATE message gcs_send_text(MAV_SEVERITY_WARNING, "Waiting for first HIL_STATE message"); delay(1000); } // set INS to HIL mode ins.set_hil_mode(); #endif // read Baro pressure at ground //----------------------------- init_barometer(true); // initialise sonar #if CONFIG_SONAR == ENABLED init_sonar(); #endif // initialise AP_RPM library rpm_sensor.init(); // initialise mission library mission.init(); // initialise the flight mode and aux switch // --------------------------- reset_control_switch(); init_aux_switches(); startup_INS_ground(); // set landed flags set_land_complete(true); set_land_complete_maybe(true); // we don't want writes to the serial port to cause us to pause // mid-flight, so set the serial ports non-blocking once we are // ready to fly serial_manager.set_blocking_writes_all(false); // enable CPU failsafe failsafe_enable(); ins.set_raw_logging(should_log(MASK_LOG_IMU_RAW)); ins.set_dataflash(&DataFlash); cliSerial->print("\nReady to FLY "); // flag that initialisation has completed ap.initialised = true; }
// setup_compassmot - sets compass's motor interference parameters uint8_t Copter::mavlink_compassmot(mavlink_channel_t chan) { #if FRAME_CONFIG == HELI_FRAME // compassmot not implemented for tradheli return 1; #else int8_t comp_type; // throttle or current based compensation Vector3f compass_base[COMPASS_MAX_INSTANCES]; // compass vector when throttle is zero Vector3f motor_impact[COMPASS_MAX_INSTANCES]; // impact of motors on compass vector Vector3f motor_impact_scaled[COMPASS_MAX_INSTANCES]; // impact of motors on compass vector scaled with throttle Vector3f motor_compensation[COMPASS_MAX_INSTANCES]; // final compensation to be stored to eeprom float throttle_pct; // throttle as a percentage 0.0 ~ 1.0 float throttle_pct_max = 0.0f; // maximum throttle reached (as a percentage 0~1.0) float current_amps_max = 0.0f; // maximum current reached float interference_pct[COMPASS_MAX_INSTANCES]; // interference as a percentage of total mag field (for reporting purposes only) uint32_t last_run_time; uint32_t last_send_time; bool updated = false; // have we updated the compensation vector at least once uint8_t command_ack_start = command_ack_counter; // exit immediately if we are already in compassmot if (ap.compass_mot) { // ignore restart messages return 1; }else{ ap.compass_mot = true; } // initialise output for (uint8_t i=0; i<COMPASS_MAX_INSTANCES; i++) { interference_pct[i] = 0.0f; } // check compass is enabled if (!g.compass_enabled) { gcs[chan-MAVLINK_COMM_0].send_text(MAV_SEVERITY_CRITICAL, "Compass disabled"); ap.compass_mot = false; return 1; } // check compass health compass.read(); for (uint8_t i=0; i<compass.get_count(); i++) { if (!compass.healthy(i)) { gcs[chan-MAVLINK_COMM_0].send_text(MAV_SEVERITY_CRITICAL, "Check compass"); ap.compass_mot = false; return 1; } } // check if radio is calibrated pre_arm_rc_checks(); if (!ap.pre_arm_rc_check) { gcs[chan-MAVLINK_COMM_0].send_text(MAV_SEVERITY_CRITICAL, "RC not calibrated"); ap.compass_mot = false; return 1; } // check throttle is at zero read_radio(); if (channel_throttle->control_in != 0) { gcs[chan-MAVLINK_COMM_0].send_text(MAV_SEVERITY_CRITICAL, "Throttle not zero"); ap.compass_mot = false; return 1; } // check we are landed if (!ap.land_complete) { gcs[chan-MAVLINK_COMM_0].send_text(MAV_SEVERITY_CRITICAL, "Not landed"); ap.compass_mot = false; return 1; } // disable cpu failsafe failsafe_disable(); // initialise compass init_compass(); // default compensation type to use current if possible if (battery.has_current()) { comp_type = AP_COMPASS_MOT_COMP_CURRENT; }else{ comp_type = AP_COMPASS_MOT_COMP_THROTTLE; } // send back initial ACK mavlink_msg_command_ack_send(chan, MAV_CMD_PREFLIGHT_CALIBRATION,0); // flash leds AP_Notify::flags.esc_calibration = true; // warn user we are starting calibration gcs[chan-MAVLINK_COMM_0].send_text(MAV_SEVERITY_INFO, "Starting calibration"); // inform what type of compensation we are attempting if (comp_type == AP_COMPASS_MOT_COMP_CURRENT) { gcs[chan-MAVLINK_COMM_0].send_text(MAV_SEVERITY_INFO, "Current"); } else{ gcs[chan-MAVLINK_COMM_0].send_text(MAV_SEVERITY_INFO, "Throttle"); } // disable throttle and battery failsafe g.failsafe_throttle = FS_THR_DISABLED; g.failsafe_battery_enabled = FS_BATT_DISABLED; // disable motor compensation compass.motor_compensation_type(AP_COMPASS_MOT_COMP_DISABLED); for (uint8_t i=0; i<compass.get_count(); i++) { compass.set_motor_compensation(i, Vector3f(0,0,0)); } // get initial compass readings last_run_time = millis(); while ( millis() - last_run_time < 500 ) { compass.accumulate(); } compass.read(); // store initial x,y,z compass values // initialise interference percentage for (uint8_t i=0; i<compass.get_count(); i++) { compass_base[i] = compass.get_field(i); interference_pct[i] = 0.0f; } // enable motors and pass through throttle init_rc_out(); enable_motor_output(); motors.armed(true); // initialise run time last_run_time = millis(); last_send_time = millis(); // main run while there is no user input and the compass is healthy while (command_ack_start == command_ack_counter && compass.healthy(compass.get_primary()) && motors.armed()) { // 50hz loop if (millis() - last_run_time < 20) { // grab some compass values compass.accumulate(); hal.scheduler->delay(5); continue; } last_run_time = millis(); // read radio input read_radio(); // pass through throttle to motors motors.throttle_pass_through(channel_throttle->radio_in); // read some compass values compass.read(); // read current read_battery(); // calculate scaling for throttle throttle_pct = (float)channel_throttle->control_in / 1000.0f; throttle_pct = constrain_float(throttle_pct,0.0f,1.0f); // if throttle is near zero, update base x,y,z values if (throttle_pct <= 0.0f) { for (uint8_t i=0; i<compass.get_count(); i++) { compass_base[i] = compass_base[i] * 0.99f + compass.get_field(i) * 0.01f; } // causing printing to happen as soon as throttle is lifted } else { // calculate diff from compass base and scale with throttle for (uint8_t i=0; i<compass.get_count(); i++) { motor_impact[i] = compass.get_field(i) - compass_base[i]; } // throttle based compensation if (comp_type == AP_COMPASS_MOT_COMP_THROTTLE) { // for each compass for (uint8_t i=0; i<compass.get_count(); i++) { // scale by throttle motor_impact_scaled[i] = motor_impact[i] / throttle_pct; // adjust the motor compensation to negate the impact motor_compensation[i] = motor_compensation[i] * 0.99f - motor_impact_scaled[i] * 0.01f; } updated = true; } else { // for each compass for (uint8_t i=0; i<compass.get_count(); i++) { // current based compensation if more than 3amps being drawn motor_impact_scaled[i] = motor_impact[i] / battery.current_amps(); // adjust the motor compensation to negate the impact if drawing over 3amps if (battery.current_amps() >= 3.0f) { motor_compensation[i] = motor_compensation[i] * 0.99f - motor_impact_scaled[i] * 0.01f; updated = true; } } } // calculate interference percentage at full throttle as % of total mag field if (comp_type == AP_COMPASS_MOT_COMP_THROTTLE) { for (uint8_t i=0; i<compass.get_count(); i++) { // interference is impact@fullthrottle / mag field * 100 interference_pct[i] = motor_compensation[i].length() / (float)COMPASS_MAGFIELD_EXPECTED * 100.0f; } }else{ for (uint8_t i=0; i<compass.get_count(); i++) { // interference is impact/amp * (max current seen / max throttle seen) / mag field * 100 interference_pct[i] = motor_compensation[i].length() * (current_amps_max/throttle_pct_max) / (float)COMPASS_MAGFIELD_EXPECTED * 100.0f; } } // record maximum throttle and current throttle_pct_max = MAX(throttle_pct_max, throttle_pct); current_amps_max = MAX(current_amps_max, battery.current_amps()); } if (AP_HAL::millis() - last_send_time > 500) { last_send_time = AP_HAL::millis(); mavlink_msg_compassmot_status_send(chan, channel_throttle->control_in, battery.current_amps(), interference_pct[compass.get_primary()], motor_compensation[compass.get_primary()].x, motor_compensation[compass.get_primary()].y, motor_compensation[compass.get_primary()].z); } } // stop motors motors.output_min(); motors.armed(false); // set and save motor compensation if (updated) { compass.motor_compensation_type(comp_type); for (uint8_t i=0; i<compass.get_count(); i++) { compass.set_motor_compensation(i, motor_compensation[i]); } compass.save_motor_compensation(); // display success message gcs[chan-MAVLINK_COMM_0].send_text(MAV_SEVERITY_INFO, "Calibration successful"); } else { // compensation vector never updated, report failure gcs[chan-MAVLINK_COMM_0].send_text(MAV_SEVERITY_NOTICE, "Failed"); compass.motor_compensation_type(AP_COMPASS_MOT_COMP_DISABLED); } // display new motor offsets and save report_compass(); // turn off notify leds AP_Notify::flags.esc_calibration = false; // re-enable cpu failsafe failsafe_enable(); // re-enable failsafes g.failsafe_throttle.load(); g.failsafe_battery_enabled.load(); // flag we have completed ap.compass_mot = false; return 0; #endif // FRAME_CONFIG != HELI_FRAME }
// It all starts here: int main(void) { // start with default user settings in case there's nothing in eeprom default_user_settings(); // try to load settings from eeprom read_user_settings_from_eeprom(); // set our LED as a digital output lib_digitalio_initpin(LED1_OUTPUT,DIGITALOUTPUT); //initialize the libraries that require initialization lib_timers_init(); lib_i2c_init(); // pause a moment before initializing everything. To make sure everything is powered up lib_timers_delaymilliseconds(100); // initialize all other modules init_rx(); init_outputs(); serial_init(); init_gyro(); init_acc(); init_baro(); init_compass(); init_gps(); init_imu(); // set the default i2c speed to 400 KHz. If a device needs to slow it down, it can, but it should set it back. lib_i2c_setclockspeed(I2C_400_KHZ); // initialize state global.state.armed=0; global.state.calibratingCompass=0; global.state.calibratingAccAndGyro=0; global.state.navigationMode=NAVIGATION_MODE_OFF; global.failsafeTimer=lib_timers_starttimer(); // run loop for(;;) { // check to see what switches are activated check_checkbox_items(); // check for config program activity serial_check_for_action(); calculate_timesliver(); // run the imu to estimate the current attitude of the aircraft imu_calculate_estimated_attitude(); // arm and disarm via rx aux switches if (global.rxValues[THROTTLE_INDEX]<FPSTICKLOW) { // see if we want to change armed modes if (!global.state.armed) { if (global.activeCheckboxItems & CHECKBOX_MASK_ARM) { global.state.armed=1; #if (GPS_TYPE!=NO_GPS) navigation_set_home_to_current_location(); #endif global.home.heading=global.currentEstimatedEulerAttitude[YAW_INDEX]; global.home.location.altitude=global.baroRawAltitude; } } else if (!(global.activeCheckboxItems & CHECKBOX_MASK_ARM)) global.state.armed=0; } #if (GPS_TYPE!=NO_GPS) // turn on or off navigation when appropriate if (global.state.navigationMode==NAVIGATION_MODE_OFF) { if (global.activeCheckboxItems & CHECKBOX_MASK_RETURNTOHOME) { // return to home switch turned on navigation_set_destination(global.home.location.latitude,global.home.location.longitude); global.state.navigationMode=NAVIGATION_MODE_RETURN_TO_HOME; } else if (global.activeCheckboxItems & CHECKBOX_MASK_POSITIONHOLD) { // position hold turned on navigation_set_destination(global.gps.currentLatitude,global.gps.currentLongitude); global.state.navigationMode=NAVIGATION_MODE_POSITION_HOLD; } } else { // we are currently navigating // turn off navigation if desired if ((global.state.navigationMode==NAVIGATION_MODE_RETURN_TO_HOME && !(global.activeCheckboxItems & CHECKBOX_MASK_RETURNTOHOME)) || (global.state.navigationMode==NAVIGATION_MODE_POSITION_HOLD && !(global.activeCheckboxItems & CHECKBOX_MASK_POSITIONHOLD))) { global.state.navigationMode=NAVIGATION_MODE_OFF; // we will be turning control back over to the pilot. reset_pilot_control(); } } #endif // read the receiver read_rx(); // turn on the LED when we are stable and the gps has 5 satelites or more #if (GPS_TYPE==NO_GPS) lib_digitalio_setoutput(LED1_OUTPUT, (global.state.stable==0)==LED1_ON); #else lib_digitalio_setoutput(LED1_OUTPUT, (!(global.state.stable && global.gps.numSatelites>=5))==LED1_ON); #endif // get the angle error. Angle error is the difference between our current attitude and our desired attitude. // It can be set by navigation, or by the pilot, etc. fixedpointnum angleError[3]; // let the pilot control the aircraft. get_angle_error_from_pilot_input(angleError); #if (GPS_TYPE!=NO_GPS) // read the gps unsigned char gotNewGpsReading=read_gps(); // if we are navigating, use navigation to determine our desired attitude (tilt angles) if (global.state.navigationMode!=NAVIGATION_MODE_OFF) { // we are navigating navigation_set_angle_error(gotNewGpsReading,angleError); } #endif if (global.rxValues[THROTTLE_INDEX]<FPSTICKLOW) { // We are probably on the ground. Don't accumnulate error when we can't correct it reset_pilot_control(); // bleed off integrated error by averaging in a value of zero lib_fp_lowpassfilter(&global.integratedAngleError[ROLL_INDEX],0L,global.timesliver>>TIMESLIVEREXTRASHIFT,FIXEDPOINTONEOVERONEFOURTH,0); lib_fp_lowpassfilter(&global.integratedAngleError[PITCH_INDEX],0L,global.timesliver>>TIMESLIVEREXTRASHIFT,FIXEDPOINTONEOVERONEFOURTH,0); lib_fp_lowpassfilter(&global.integratedAngleError[YAW_INDEX],0L,global.timesliver>>TIMESLIVEREXTRASHIFT,FIXEDPOINTONEOVERONEFOURTH,0); } #ifndef NO_AUTOTUNE // let autotune adjust the angle error if the pilot has autotune turned on if (global.activeCheckboxItems & CHECKBOX_MASK_AUTOTUNE) { if (!(global.previousActiveCheckboxItems & CHECKBOX_MASK_AUTOTUNE)) { autotune(angleError,AUTOTUNE_STARTING); // tell autotune that we just started autotuning } else { autotune(angleError,AUTOTUNE_TUNING); // tell autotune that we are in the middle of autotuning } } else if (global.previousActiveCheckboxItems & CHECKBOX_MASK_AUTOTUNE) { autotune(angleError,AUTOTUNE_STOPPING); // tell autotune that we just stopped autotuning } #endif // This gets reset every loop cycle // keep a flag to indicate whether we shoud apply altitude hold. The pilot can turn it on or // uncrashability/autopilot mode can turn it on. global.state.altitudeHold=0; if (global.activeCheckboxItems & CHECKBOX_MASK_ALTHOLD) { global.state.altitudeHold=1; if (!(global.previousActiveCheckboxItems & CHECKBOX_MASK_ALTHOLD)) { // we just turned on alt hold. Remember our current alt. as our target global.altitudeHoldDesiredAltitude=global.altitude; global.integratedAltitudeError=0; } } fixedpointnum throttleOutput; #ifndef NO_AUTOPILOT // autopilot is available if (global.activeCheckboxItems & CHECKBOX_MASK_AUTOPILOT) { if (!(global.previousActiveCheckboxItems & CHECKBOX_MASK_AUTOPILOT)) { // let autopilot know to transition to the starting state autopilot(AUTOPILOT_STARTING); } else { // autopilot normal run state autopilot(AUTOPILOT_RUNNING); } } else if (global.previousActiveCheckboxItems & CHECKBOX_MASK_AUTOPILOT) { // tell autopilot that we just stopped autotuning autopilot(AUTOPILOT_STOPPING); } else { // get the pilot's throttle component // convert from fixedpoint -1 to 1 to fixedpoint 0 to 1 throttleOutput=(global.rxValues[THROTTLE_INDEX]>>1)+FIXEDPOINTCONSTANT(.5)+FPTHROTTLETOMOTOROFFSET; } #else // get the pilot's throttle component // convert from fixedpoint -1 to 1 to fixedpoint 0 to 1 throttleOutput=(global.rxValues[THROTTLE_INDEX]>>1)+FIXEDPOINTCONSTANT(.5)+FPTHROTTLETOMOTOROFFSET; #endif #ifndef NO_UNCRASHABLE uncrashable(gotNewGpsReading,angleError,&throttleOutput); #endif #if (BAROMETER_TYPE!=NO_BAROMETER) // check for altitude hold and adjust the throttle output accordingly if (global.state.altitudeHold) { global.integratedAltitudeError+=lib_fp_multiply(global.altitudeHoldDesiredAltitude-global.altitude,global.timesliver); lib_fp_constrain(&global.integratedAltitudeError,-INTEGRATED_ANGLE_ERROR_LIMIT,INTEGRATED_ANGLE_ERROR_LIMIT); // don't let the integrated error get too high // do pid for the altitude hold and add it to the throttle output throttleOutput+=lib_fp_multiply(global.altitudeHoldDesiredAltitude-global.altitude,settings.pid_pgain[ALTITUDE_INDEX])-lib_fp_multiply(global.altitudeVelocity,settings.pid_dgain[ALTITUDE_INDEX])+lib_fp_multiply(global.integratedAltitudeError,settings.pid_igain[ALTITUDE_INDEX]); } #endif #ifndef NO_AUTOTHROTTLE if ((global.activeCheckboxItems & CHECKBOX_MASK_AUTOTHROTTLE) || global.state.altitudeHold) { if (global.estimatedDownVector[Z_INDEX]>FIXEDPOINTCONSTANT(.3)) { // Divide the throttle by the throttleOutput by the z component of the down vector // This is probaly the slow way, but it's a way to do fixed point division fixedpointnum recriprocal=lib_fp_invsqrt(global.estimatedDownVector[Z_INDEX]); recriprocal=lib_fp_multiply(recriprocal,recriprocal); throttleOutput=lib_fp_multiply(throttleOutput-AUTOTHROTTLE_DEAD_AREA,recriprocal)+AUTOTHROTTLE_DEAD_AREA; } } #endif #ifndef NO_FAILSAFE // if we don't hear from the receiver for over a second, try to land safely if (lib_timers_gettimermicroseconds(global.failsafeTimer)>1000000L) { throttleOutput=FPFAILSAFEMOTOROUTPUT; // make sure we are level! angleError[ROLL_INDEX]=-global.currentEstimatedEulerAttitude[ROLL_INDEX]; angleError[PITCH_INDEX]=-global.currentEstimatedEulerAttitude[PITCH_INDEX]; } #endif // calculate output values. Output values will range from 0 to 1.0 // calculate pid outputs based on our angleErrors as inputs fixedpointnum pidOutput[3]; // Gain Scheduling essentialy modifies the gains depending on // throttle level. If GAIN_SCHEDULING_FACTOR is 1.0, it multiplies PID outputs by 1.5 when at full throttle, // 1.0 when at mid throttle, and .5 when at zero throttle. This helps // eliminate the wobbles when decending at low throttle. fixedpointnum gainSchedulingMultiplier=lib_fp_multiply(throttleOutput-FIXEDPOINTCONSTANT(.5),FIXEDPOINTCONSTANT(GAIN_SCHEDULING_FACTOR))+FIXEDPOINTONE; for (int x=0;x<3;++x) { global.integratedAngleError[x]+=lib_fp_multiply(angleError[x],global.timesliver); // don't let the integrated error get too high (windup) lib_fp_constrain(&global.integratedAngleError[x],-INTEGRATED_ANGLE_ERROR_LIMIT,INTEGRATED_ANGLE_ERROR_LIMIT); // do the attitude pid pidOutput[x]=lib_fp_multiply(angleError[x],settings.pid_pgain[x])-lib_fp_multiply(global.gyrorate[x],settings.pid_dgain[x])+(lib_fp_multiply(global.integratedAngleError[x],settings.pid_igain[x])>>4); // add gain scheduling. pidOutput[x]=lib_fp_multiply(gainSchedulingMultiplier,pidOutput[x]); } lib_fp_constrain(&throttleOutput,0,FIXEDPOINTONE); // Keep throttle output between 0 and 1 compute_mix(throttleOutput, pidOutput); // aircraft type dependent mixes #if (NUM_SERVOS>0) // do not update servos during unarmed calibration of sensors which are sensitive to vibration if (global.state.armed || (!global.state.calibratingAccAndGyro)) write_servo_outputs(); #endif write_motor_outputs(); }
void Sub::init_ardupilot() { if (!hal.gpio->usb_connected()) { // USB is not connected, this means UART0 may be a Xbee, with // its darned bricking problem. We can't write to it for at // least one second after powering up. Simplest solution for // now is to delay for 1 second. Something more elegant may be // added later hal.scheduler->delay(1000); } // initialise serial port serial_manager.init_console(); cliSerial->printf("\n\nInit " FIRMWARE_STRING "\n\nFree RAM: %u\n", (unsigned)hal.util->available_memory()); // // Report firmware version code expect on console (check of actual EEPROM format version is done in load_parameters function) // report_version(); // load parameters from EEPROM load_parameters(); BoardConfig.init(); // initialise serial port serial_manager.init(); // init cargo gripper #if GRIPPER_ENABLED == ENABLED g2.gripper.init(); #endif // initialise notify system notify.init(true); // initialise battery monitor battery.init(); barometer.init(); celsius.init(); // Register the mavlink service callback. This will run // anytime there are more than 5ms remaining in a call to // hal.scheduler->delay. hal.scheduler->register_delay_callback(mavlink_delay_cb_static, 5); // we start by assuming USB connected, as we initialed the serial // port with SERIAL0_BAUD. check_usb_mux() fixes this if need be. ap.usb_connected = true; check_usb_mux(); // setup telem slots with serial ports for (uint8_t i = 0; i < MAVLINK_COMM_NUM_BUFFERS; i++) { gcs_chan[i].setup_uart(serial_manager, AP_SerialManager::SerialProtocol_MAVLink, i); } // identify ourselves correctly with the ground station mavlink_system.sysid = g.sysid_this_mav; #if LOGGING_ENABLED == ENABLED log_init(); #endif gcs().set_dataflash(&DataFlash); init_rc_in(); // sets up rc channels from radio init_rc_out(); // sets up motors and output to escs init_joystick(); // joystick initialization // initialise which outputs Servo and Relay events can use ServoRelayEvents.set_channel_mask(~motors.get_motor_mask()); relay.init(); /* * setup the 'main loop is dead' check. Note that this relies on * the RC library being initialised. */ hal.scheduler->register_timer_failsafe(failsafe_check_static, 1000); // Do GPS init gps.init(&DataFlash, serial_manager); if (g.compass_enabled) { init_compass(); } #if OPTFLOW == ENABLED // make optflow available to AHRS ahrs.set_optflow(&optflow); #endif // init Location class Location_Class::set_ahrs(&ahrs); #if AP_TERRAIN_AVAILABLE && AC_TERRAIN Location_Class::set_terrain(&terrain); wp_nav.set_terrain(&terrain); #endif #if AVOIDANCE_ENABLED == ENABLED wp_nav.set_avoidance(&avoid); #endif pos_control.set_dt(MAIN_LOOP_SECONDS); // init the optical flow sensor init_optflow(); #if MOUNT == ENABLED // initialise camera mount camera_mount.init(&DataFlash, serial_manager); #endif #ifdef USERHOOK_INIT USERHOOK_INIT #endif #if CLI_ENABLED == ENABLED if (g.cli_enabled) { const char *msg = "\nPress ENTER 3 times to start interactive setup\n"; cliSerial->println(msg); if (gcs_chan[1].initialised && (gcs_chan[1].get_uart() != NULL)) { gcs_chan[1].get_uart()->println(msg); } if (num_gcs > 2 && gcs_chan[2].initialised && (gcs_chan[2].get_uart() != NULL)) { gcs_chan[2].get_uart()->println(msg); } } #endif // CLI_ENABLED #if HIL_MODE != HIL_MODE_DISABLED while (barometer.get_last_update() == 0) { // the barometer begins updating when we get the first // HIL_STATE message gcs_send_text(MAV_SEVERITY_WARNING, "Waiting for first HIL_STATE message"); hal.scheduler->delay(1000); } // set INS to HIL mode ins.set_hil_mode(); #endif // read Baro pressure at ground //----------------------------- init_barometer(false); barometer.update(); for (uint8_t i = 0; i < barometer.num_instances(); i++) { if (barometer.get_type(i) == AP_Baro::BARO_TYPE_WATER && barometer.healthy(i)) { barometer.set_primary_baro(i); ap.depth_sensor_present = true; break; } } if (!ap.depth_sensor_present) { // We only have onboard baro // No external underwater depth sensor detected barometer.set_primary_baro(0); EKF2.set_baro_alt_noise(10.0f); // Readings won't correspond with rest of INS EKF3.set_baro_alt_noise(10.0f); } else { EKF2.set_baro_alt_noise(0.1f); EKF3.set_baro_alt_noise(0.1f); } leak_detector.init(); // backwards compatibility if (attitude_control.get_accel_yaw_max() < 110000.0f) { attitude_control.save_accel_yaw_max(110000.0f); } last_pilot_heading = ahrs.yaw_sensor; // initialise rangefinder #if RANGEFINDER_ENABLED == ENABLED init_rangefinder(); #endif // initialise AP_RPM library #if RPM_ENABLED == ENABLED rpm_sensor.init(); #endif // initialise mission library mission.init(); startup_INS_ground(); // we don't want writes to the serial port to cause us to pause // mid-flight, so set the serial ports non-blocking once we are // ready to fly serial_manager.set_blocking_writes_all(false); // enable CPU failsafe failsafe_enable(); ins.set_raw_logging(should_log(MASK_LOG_IMU_RAW)); ins.set_dataflash(&DataFlash); // init vehicle capabilties init_capabilities(); cliSerial->print("\nReady to FLY "); // flag that initialisation has completed ap.initialised = true; }