コード例 #1
0
/**
 * @brief Handler to interprete Command inputs in regards to arming/disarming
 * @input: ManualControlCommand, AccessoryDesired
 * @output: FlightStatus.Arming
 */
void armHandler(bool newinit)
{
    static ArmState_t armState;

    if (newinit) {
        AccessoryDesiredInitialize();
        setArmedIfChanged(FLIGHTSTATUS_ARMED_DISARMED);
        armState = ARM_STATE_DISARMED;
    }

    portTickType sysTime = xTaskGetTickCount();

    FlightModeSettingsData settings;
    FlightModeSettingsGet(&settings);
    ManualControlCommandData cmd;
    ManualControlCommandGet(&cmd);
    AccessoryDesiredData acc;

    bool lowThrottle = cmd.Throttle < 0;

    bool armSwitch   = false;

    switch (settings.Arming) {
    case FLIGHTMODESETTINGS_ARMING_ACCESSORY0:
        AccessoryDesiredInstGet(0, &acc);
        armSwitch = true;
        break;
    case FLIGHTMODESETTINGS_ARMING_ACCESSORY1:
        AccessoryDesiredInstGet(1, &acc);
        armSwitch = true;
        break;
    case FLIGHTMODESETTINGS_ARMING_ACCESSORY2:
        AccessoryDesiredInstGet(2, &acc);
        armSwitch = true;
        break;
    default:
        break;
    }

    // immediate disarm on switch
    if (armSwitch && acc.AccessoryVal <= -ARMED_THRESHOLD) {
        lowThrottle = true;
    }

    if (forcedDisArm()) {
        // PathPlanner forces explicit disarming due to error condition (crash, impact, fire, ...)
        setArmedIfChanged(FLIGHTSTATUS_ARMED_DISARMED);
        return;
    }

    if (settings.Arming == FLIGHTMODESETTINGS_ARMING_ALWAYSDISARMED) {
        // In this configuration we always disarm
        setArmedIfChanged(FLIGHTSTATUS_ARMED_DISARMED);
        return;
    }


    // The throttle is not low, in case we where arming or disarming, abort
    if (!lowThrottle) {
        switch (armState) {
        case ARM_STATE_DISARMING_MANUAL:
        case ARM_STATE_DISARMING_TIMEOUT:
            armState = ARM_STATE_ARMED;
            break;
        case ARM_STATE_ARMING_MANUAL:
            armState = ARM_STATE_DISARMED;
            break;
        default:
            // Nothing needs to be done in the other states
            break;
        }
        return;
    }

    // The rest of these cases throttle is low
    if (settings.Arming == FLIGHTMODESETTINGS_ARMING_ALWAYSARMED) {
        // In this configuration, we go into armed state as soon as the throttle is low, never disarm
        setArmedIfChanged(FLIGHTSTATUS_ARMED_ARMED);
        return;
    }

    // When the configuration is not "Always armed" and no "Always disarmed",
    // the state will not be changed when the throttle is not low
    static portTickType armedDisarmStart;
    float armingInputLevel = 0;

    // Calc channel see assumptions7
    switch (settings.Arming) {
    case FLIGHTMODESETTINGS_ARMING_ROLLLEFT:
        armingInputLevel = 1.0f * cmd.Roll;
        break;
    case FLIGHTMODESETTINGS_ARMING_ROLLRIGHT:
        armingInputLevel = -1.0f * cmd.Roll;
        break;
    case FLIGHTMODESETTINGS_ARMING_PITCHFORWARD:
        armingInputLevel = 1.0f * cmd.Pitch;
        break;
    case FLIGHTMODESETTINGS_ARMING_PITCHAFT:
        armingInputLevel = -1.0f * cmd.Pitch;
        break;
    case FLIGHTMODESETTINGS_ARMING_YAWLEFT:
        armingInputLevel = 1.0f * cmd.Yaw;
        break;
    case FLIGHTMODESETTINGS_ARMING_YAWRIGHT:
        armingInputLevel = -1.0f * cmd.Yaw;
        break;
    case FLIGHTMODESETTINGS_ARMING_ACCESSORY0:
    case FLIGHTMODESETTINGS_ARMING_ACCESSORY1:
    case FLIGHTMODESETTINGS_ARMING_ACCESSORY2:
        armingInputLevel = -1.0f * acc.AccessoryVal;
        break;
    }

    bool manualArm    = false;
    bool manualDisarm = false;

    if (armingInputLevel <= -ARMED_THRESHOLD) {
        manualArm = true;
    } else if (armingInputLevel >= +ARMED_THRESHOLD) {
        manualDisarm = true;
    }

    switch (armState) {
    case ARM_STATE_DISARMED:
        setArmedIfChanged(FLIGHTSTATUS_ARMED_DISARMED);

        // only allow arming if it's OK too
        if (manualArm && okToArm()) {
            armedDisarmStart = sysTime;
            armState = ARM_STATE_ARMING_MANUAL;
        }
        break;

    case ARM_STATE_ARMING_MANUAL:
        setArmedIfChanged(FLIGHTSTATUS_ARMED_ARMING);

        if (manualArm && (timeDifferenceMs(armedDisarmStart, sysTime) > settings.ArmingSequenceTime)) {
            armState = ARM_STATE_ARMED;
        } else if (!manualArm) {
            armState = ARM_STATE_DISARMED;
        }
        break;

    case ARM_STATE_ARMED:
        // When we get here, the throttle is low,
        // we go immediately to disarming due to timeout, also when the disarming mechanism is not enabled
        armedDisarmStart = sysTime;
        armState = ARM_STATE_DISARMING_TIMEOUT;
        setArmedIfChanged(FLIGHTSTATUS_ARMED_ARMED);
        break;

    case ARM_STATE_DISARMING_TIMEOUT:
    {
        // we should never reach the disarming timeout if the pathfollower is engaged - reset timeout
        FlightStatusControlChainData cc;
        FlightStatusControlChainGet(&cc);
        if (cc.PathFollower == FLIGHTSTATUS_CONTROLCHAIN_TRUE) {
            armedDisarmStart = sysTime;
        }
    }

        // We get here when armed while throttle low, even when the arming timeout is not enabled
        if ((settings.ArmedTimeout != 0) && (timeDifferenceMs(armedDisarmStart, sysTime) > settings.ArmedTimeout)) {
            armState = ARM_STATE_DISARMED;
        }

        // Switch to disarming due to manual control when needed
        if (manualDisarm) {
            armedDisarmStart = sysTime;
            armState = ARM_STATE_DISARMING_MANUAL;
        }
        break;

    case ARM_STATE_DISARMING_MANUAL:
        // arming switch disarms immediately,
        if (manualDisarm && (timeDifferenceMs(armedDisarmStart, sysTime) > settings.DisarmingSequenceTime)) {
            armState = ARM_STATE_DISARMED;
        } else if (!manualDisarm) {
            armState = ARM_STATE_ARMED;
        }
        break;
    } // End Switch
}
コード例 #2
0
ファイル: innerloop.c プロジェクト: GennadyKharlam/OpenPilot
/**
 * WARNING! This callback executes with critical flight control priority every
 * time a gyroscope update happens do NOT put any time consuming calculations
 * in this loop unless they really have to execute with every gyro update
 */
static void stabilizationInnerloopTask()
{
    // watchdog and error handling
    {
#ifdef PIOS_INCLUDE_WDG
        PIOS_WDG_UpdateFlag(PIOS_WDG_STABILIZATION);
#endif
        bool warn  = false;
        bool error = false;
        bool crit  = false;
        // check if outer loop keeps executing
        if (stabSettings.monitor.rateupdates > -64) {
            stabSettings.monitor.rateupdates--;
        }
        if (stabSettings.monitor.rateupdates < -(2 * OUTERLOOP_SKIPCOUNT)) {
            // warning if rate loop skipped more than 2 execution
            warn = true;
        }
        if (stabSettings.monitor.rateupdates < -(4 * OUTERLOOP_SKIPCOUNT)) {
            // critical if rate loop skipped more than 4 executions
            crit = true;
        }
        // check if gyro keeps updating
        if (stabSettings.monitor.gyroupdates < 1) {
            // error if gyro didn't update at all!
            error = true;
        }
        if (stabSettings.monitor.gyroupdates > 1) {
            // warning if we missed a gyro update
            warn = true;
        }
        if (stabSettings.monitor.gyroupdates > 3) {
            // critical if we missed 3 gyro updates
            crit = true;
        }
        stabSettings.monitor.gyroupdates = 0;

        if (crit) {
            AlarmsSet(SYSTEMALARMS_ALARM_STABILIZATION, SYSTEMALARMS_ALARM_CRITICAL);
        } else if (error) {
            AlarmsSet(SYSTEMALARMS_ALARM_STABILIZATION, SYSTEMALARMS_ALARM_ERROR);
        } else if (warn) {
            AlarmsSet(SYSTEMALARMS_ALARM_STABILIZATION, SYSTEMALARMS_ALARM_WARNING);
        } else {
            AlarmsClear(SYSTEMALARMS_ALARM_STABILIZATION);
        }
    }


    RateDesiredData rateDesired;
    ActuatorDesiredData actuator;
    StabilizationStatusInnerLoopData enabled;
    FlightStatusControlChainData cchain;

    RateDesiredGet(&rateDesired);
    ActuatorDesiredGet(&actuator);
    StabilizationStatusInnerLoopGet(&enabled);
    FlightStatusControlChainGet(&cchain);
    float *rate = &rateDesired.Roll;
    float *actuatorDesiredAxis = &actuator.Roll;
    int t;
    float dT;
    dT = PIOS_DELTATIME_GetAverageSeconds(&timeval);

    for (t = 0; t < AXES; t++) {
        bool reinit = (cast_struct_to_array(enabled, enabled.Roll)[t] != previous_mode[t]);
        previous_mode[t] = cast_struct_to_array(enabled, enabled.Roll)[t];

        if (t < STABILIZATIONSTATUS_INNERLOOP_THRUST) {
            if (reinit) {
                stabSettings.innerPids[t].iAccumulator = 0;
            }
            switch (cast_struct_to_array(enabled, enabled.Roll)[t]) {
            case STABILIZATIONSTATUS_INNERLOOP_VIRTUALFLYBAR:
                stabilization_virtual_flybar(gyro_filtered[t], rate[t], &actuatorDesiredAxis[t], dT, reinit, t, &stabSettings.settings);
                break;
            case STABILIZATIONSTATUS_INNERLOOP_RELAYTUNING:
                rate[t] = boundf(rate[t],
                                 -cast_struct_to_array(stabSettings.stabBank.MaximumRate, stabSettings.stabBank.MaximumRate.Roll)[t],
                                 cast_struct_to_array(stabSettings.stabBank.MaximumRate, stabSettings.stabBank.MaximumRate.Roll)[t]
                                 );
                stabilization_relay_rate(rate[t] - gyro_filtered[t], &actuatorDesiredAxis[t], t, reinit);
                break;
            case STABILIZATIONSTATUS_INNERLOOP_AXISLOCK:
                if (fabsf(rate[t]) > stabSettings.settings.MaxAxisLockRate) {
                    // While getting strong commands act like rate mode
                    axis_lock_accum[t] = 0;
                } else {
                    // For weaker commands or no command simply attitude lock (almost) on no gyro change
                    axis_lock_accum[t] += (rate[t] - gyro_filtered[t]) * dT;
                    axis_lock_accum[t]  = boundf(axis_lock_accum[t], -stabSettings.settings.MaxAxisLock, stabSettings.settings.MaxAxisLock);
                    rate[t] = axis_lock_accum[t] * stabSettings.settings.AxisLockKp;
                }
            // IMPORTANT: deliberately no "break;" here, execution continues with regular RATE control loop to avoid code duplication!
            // keep order as it is, RATE must follow!
            case STABILIZATIONSTATUS_INNERLOOP_RATE:
                // limit rate to maximum configured limits (once here instead of 5 times in outer loop)
                rate[t] = boundf(rate[t],
                                 -cast_struct_to_array(stabSettings.stabBank.MaximumRate, stabSettings.stabBank.MaximumRate.Roll)[t],
                                 cast_struct_to_array(stabSettings.stabBank.MaximumRate, stabSettings.stabBank.MaximumRate.Roll)[t]
                                 );
                actuatorDesiredAxis[t] = pid_apply_setpoint(&stabSettings.innerPids[t], speedScaleFactor, rate[t], gyro_filtered[t], dT);
                break;
            case STABILIZATIONSTATUS_INNERLOOP_DIRECT:
            default:
                actuatorDesiredAxis[t] = rate[t];
                break;
            }
        } else {
            switch (cast_struct_to_array(enabled, enabled.Roll)[t]) {
            case STABILIZATIONSTATUS_INNERLOOP_CRUISECONTROL:
                actuatorDesiredAxis[t] = cruisecontrol_apply_factor(rate[t]);
                break;
            case STABILIZATIONSTATUS_INNERLOOP_DIRECT:
            default:
                actuatorDesiredAxis[t] = rate[t];
                break;
            }
        }

        actuatorDesiredAxis[t] = boundf(actuatorDesiredAxis[t], -1.0f, 1.0f);
    }

    actuator.UpdateTime = dT * 1000;

    if (cchain.Stabilization == FLIGHTSTATUS_CONTROLCHAIN_TRUE) {
        ActuatorDesiredSet(&actuator);
    } else {
        // Force all axes to reinitialize when engaged
        for (t = 0; t < AXES; t++) {
            previous_mode[t] = 255;
        }
    }
    {
        uint8_t armed;
        FlightStatusArmedGet(&armed);
        float throttleDesired;
        ManualControlCommandThrottleGet(&throttleDesired);
        if (armed != FLIGHTSTATUS_ARMED_ARMED ||
            ((stabSettings.settings.LowThrottleZeroIntegral == STABILIZATIONSETTINGS_LOWTHROTTLEZEROINTEGRAL_TRUE) && throttleDesired < 0)) {
            // Force all axes to reinitialize when engaged
            for (t = 0; t < AXES; t++) {
                previous_mode[t] = 255;
            }
        }
    }
    PIOS_CALLBACKSCHEDULER_Schedule(callbackHandle, FAILSAFE_TIMEOUT_MS, CALLBACK_UPDATEMODE_LATER);
}