Exemple #1
0
void hoverPitchCntrl(void)
{
	union longww pitchAccum;

	if (flags._.pitch_feedback)
	{
		pitchAccum.WW = (__builtin_mulss(-rmat[7] , omegagyro[0])
		               - __builtin_mulss(rmat[6] , omegagyro[1])) << 1;
		pitchrate = pitchAccum._.W1;

		int16_t elevInput = (udb_flags._.radio_on == 1) ?
		    REVERSE_IF_NEEDED(ELEVATOR_CHANNEL_REVERSED, udb_pwIn[ELEVATOR_INPUT_CHANNEL] - udb_pwTrim[ELEVATOR_INPUT_CHANNEL]) : 0;
		int16_t manualPitchOffset = elevInput * (int16_t)(RMAX/600);

		int32_t pitchToWP;

		if (flags._.GPS_steering)
		{
			pitchToWP = (tofinish_line > HOVER_NAV_MAX_PITCH_RADIUS) ?
			    HOVERPTOWP : (HOVERPTOWP / HOVER_NAV_MAX_PITCH_RADIUS * tofinish_line);
		}
		else
		{
			pitchToWP = 0;
		}

		pitchAccum.WW = __builtin_mulsu(rmat[8] + HOVERPOFFSET - pitchToWP + manualPitchOffset , hoverpitchgain)
		              + __builtin_mulus(hoverpitchkd , pitchrate);
	}
	else
	{
		pitchAccum.WW = 0;
	}
	pitch_control = (int32_t)pitchAccum._.W1;
}
Exemple #2
0
void normalRollCntrl(void)
{
    union longww rollAccum = { 0 };
    union longww gyroRollFeedback;
    union longww gyroYawFeedback;
    fractional omegaAccum2;

    if (!canStabilizeInverted() || !desired_behavior._.inverted)
    {
        omegaAccum2 = omegaAccum[2];
    }
    else
    {
        omegaAccum2 = -omegaAccum[2];
    }

#ifdef TestGains
    state_flags._.pitch_feedback = 1;
#endif
    if (settings._.RollStabilizaionAilerons && state_flags._.pitch_feedback)
    {
        gyroRollFeedback.WW = - __builtin_mulus(rollkd, rotationRateError[1]);
        rollAccum.WW -= __builtin_mulsu(tiltError[1], rollkp);
        rollAccum.WW += __builtin_mulsu(desiredRotationRateRadians[1], rollkpfdfwd);
    }
    else
    {
        gyroRollFeedback.WW = 0;
    }
    if (settings._.YawStabilizationAileron && state_flags._.pitch_feedback)
    {
        gyroYawFeedback.WW = - __builtin_mulus(yawkdail, omegaAccum2);
    }
    else
    {
        gyroYawFeedback.WW = 0;
    }
    roll_control = (int32_t)rollAccum._.W1 + (int32_t)gyroRollFeedback._.W1 + (int32_t)gyroYawFeedback._.W1;
    // Servo reversing is handled in servoMix.c
}
static int16_t relativeWingLoading(int16_t wingLoad, uint16_t airSpeed)
{
	// wingLoad is(2**16)*((wing_load / mass*gravity) / 16)
	// stallSpeed is the stall speed in centimeters per second
	// airSpeed is the air speed in centimeters per second

	uint16_t stallSpeed = STALL_SPEED_CM_SEC;
	int16_t result = 0;
	uint32_t long_unsigned_accum;
	union longww long_signed_accum;
	uint16_t unsigned_accum;

	// if airspeed is less than or equal to stall speed, return zero
	if (airSpeed <= stallSpeed)
	{
		return 0;
	}

	long_unsigned_accum = (uint32_t)stallSpeed;
	long_unsigned_accum = long_unsigned_accum << 16; //(2**16)*V0, 32 bits unsigned
	unsigned_accum = __builtin_divud(long_unsigned_accum, airSpeed); //(2**16)*(V0/V), 16 bits unsigned
	long_unsigned_accum = __builtin_muluu(unsigned_accum, unsigned_accum); //(2**32)*(V0/V)**2, 32 bits unsigned
	unsigned_accum = long_unsigned_accum >> 16; //(2**16)*(V0/V)**2, 16 bits unsigned
	long_signed_accum.WW = __builtin_mulus(unsigned_accum, wingLoad); //(2**32)*(a/16g)*(V0/V)**2, 32 bits unsigned
	if (abs(long_signed_accum._.W1) < 4095)
	{
		long_signed_accum.WW = long_signed_accum.WW << 3; // multiply by 8
		result = long_signed_accum._.W1;
	}
	else
	{
		if (wingLoad > 0)
		{
			result = 32767;
		}
		else
		{
			result = -32767;
		}
	}	
	return result;
}
Exemple #4
0
void hoverYawCntrl(void)
{
	union longww yawAccum;
	union longww gyroYawFeedback;

	if (flags._.pitch_feedback)
	{
		gyroYawFeedback.WW = __builtin_mulus(hoveryawkd, omegaAccum[2]);
		
		int16_t yawInput = (udb_flags._.radio_on == 1) ? REVERSE_IF_NEEDED(RUDDER_CHANNEL_REVERSED, udb_pwIn[RUDDER_INPUT_CHANNEL] - udb_pwTrim[RUDDER_INPUT_CHANNEL]) : 0;
		int16_t manualYawOffset = yawInput * (int16_t)(RMAX/2000);
		
		yawAccum.WW = __builtin_mulsu(rmat[6] + HOVERYOFFSET + manualYawOffset, hoveryawkp);
	}
	else
	{
		gyroYawFeedback.WW = 0;
		yawAccum.WW = 0;
	}

	yaw_control = (int32_t)yawAccum._.W1 - (int32_t)gyroYawFeedback._.W1;
}
Exemple #5
0
void hoverRollCntrl(void)
{
    int16_t rollNavDeflection;
    union longww gyroRollFeedback;

    if (state_flags._.pitch_feedback)
    {
        if (settings._.AileronNavigation && state_flags._.GPS_steering)
        {
            rollNavDeflection = (tofinish_line > hover.HoverNavMaxPitchRadius/2) ? navigate_determine_deflection('h') : 0;
        }
        else
        {
            rollNavDeflection = 0;
        }
        gyroRollFeedback.WW = __builtin_mulus(hoverrollkd , omegaAccum[1]);
    }
    else
    {
        rollNavDeflection = 0;
        gyroRollFeedback.WW = 0;
    }
    roll_control = rollNavDeflection -(int32_t)gyroRollFeedback._.W1;
}
void dead_reckon(void)
{
	int16_t air_speed_x, air_speed_y, air_speed_z;
	union longww accum;
	union longww energy;

	if (dcm_flags._.dead_reckon_enable == 1)  // wait for startup of GPS
	{
		// integrate the accelerometers to update IMU velocity
		IMUintegralAccelerationx.WW += __builtin_mulss(((int16_t)(ACCEL2DELTAV)), accelEarth[0]);
		IMUintegralAccelerationy.WW += __builtin_mulss(((int16_t)(ACCEL2DELTAV)), accelEarth[1]);
		IMUintegralAccelerationz.WW += __builtin_mulss(((int16_t)(ACCEL2DELTAV)), accelEarth[2]);

		// integrate IMU velocity to update the IMU location	
		IMUlocationx.WW += (__builtin_mulss(((int16_t)(VELOCITY2LOCATION)), IMUintegralAccelerationx._.W1)>>4);
		IMUlocationy.WW += (__builtin_mulss(((int16_t)(VELOCITY2LOCATION)), IMUintegralAccelerationy._.W1)>>4);
		IMUlocationz.WW += (__builtin_mulss(((int16_t)(VELOCITY2LOCATION)), IMUintegralAccelerationz._.W1)>>4);

		if (dead_reckon_clock > 0)
		// apply drift adjustments only while valid GPS data is in force.
		// This is done with a countdown clock that gets reset each time new data comes in.
		{
			dead_reckon_clock --;

			IMUintegralAccelerationx.WW += __builtin_mulss(DR_FILTER_GAIN, velocityErrorEarth[0]);
			IMUintegralAccelerationy.WW += __builtin_mulss(DR_FILTER_GAIN, velocityErrorEarth[1]);
			IMUintegralAccelerationz.WW += __builtin_mulss(DR_FILTER_GAIN, velocityErrorEarth[2]);

			IMUlocationx.WW += __builtin_mulss(DR_FILTER_GAIN, locationErrorEarth[0]);
			IMUlocationy.WW += __builtin_mulss(DR_FILTER_GAIN, locationErrorEarth[1]);
			IMUlocationz.WW += __builtin_mulss(DR_FILTER_GAIN, locationErrorEarth[2]);

			IMUvelocityx.WW = IMUintegralAccelerationx.WW +
			                  __builtin_mulus(ONE_OVER_TAU, 100*locationErrorEarth[0]);
			IMUvelocityy.WW = IMUintegralAccelerationy.WW +
			                  __builtin_mulus(ONE_OVER_TAU, 100*locationErrorEarth[1]);
			IMUvelocityz.WW = IMUintegralAccelerationz.WW +
			                  __builtin_mulus(ONE_OVER_TAU, 100*locationErrorEarth[2]);

		}
		else  // GPS has gotten disconnected
		{
			yaw_drift_reset();
			dcm_flags._.gps_history_valid = 0; // restart GPS history variables
			IMUvelocityx.WW = IMUintegralAccelerationx.WW;
			IMUvelocityy.WW = IMUintegralAccelerationy.WW;
			IMUvelocityz.WW = IMUintegralAccelerationz.WW;
		}

		if (gps_nav_valid() && (dcm_flags._.reckon_req == 1))
		{
			// compute error indications and restart the dead reckoning clock to apply them
			dcm_flags._.reckon_req = 0;
			dead_reckon_clock = DR_PERIOD;

			locationErrorEarth[0] = GPSlocation.x - IMUlocationx._.W1;
			locationErrorEarth[1] = GPSlocation.y - IMUlocationy._.W1;
			locationErrorEarth[2] = GPSlocation.z - IMUlocationz._.W1;

			velocityErrorEarth[0] = GPSvelocity.x - IMUintegralAccelerationx._.W1;
			velocityErrorEarth[1] = GPSvelocity.y - IMUintegralAccelerationy._.W1;
			velocityErrorEarth[2] = GPSvelocity.z - IMUintegralAccelerationz._.W1;
		}
	}
void normalPitchCntrl(void)
{
	union longww pitchAccum;
	int16_t rtlkick;
//	int16_t aspd_adj;
//	fractional aspd_err, aspd_diff;

	fractional rmat6;
	fractional rmat7;
	fractional rmat8;

	if (!canStabilizeInverted() || current_orientation != F_INVERTED)
	{
		rmat6 = rmat[6];
		rmat7 = rmat[7];
		rmat8 = rmat[8];
	}
	else
	{
		rmat6 = -rmat[6];
		rmat7 = -rmat[7];
		rmat8 = -rmat[8];
		pitchAltitudeAdjust = -pitchAltitudeAdjust - INVNPITCH;
	}

	navElevMix = 0;
	if (flags._.pitch_feedback)
	{
		if (RUDDER_OUTPUT_CHANNEL != CHANNEL_UNUSED && RUDDER_INPUT_CHANNEL != CHANNEL_UNUSED) {
			pitchAccum.WW = __builtin_mulsu(rmat6 , rudderElevMixGain) << 1;
			pitchAccum.WW = __builtin_mulss(pitchAccum._.W1 ,
			    REVERSE_IF_NEEDED(RUDDER_CHANNEL_REVERSED, udb_pwTrim[RUDDER_INPUT_CHANNEL] - udb_pwOut[RUDDER_OUTPUT_CHANNEL])) << 3;
			navElevMix += pitchAccum._.W1;
		}

		pitchAccum.WW = __builtin_mulsu(rmat6 , rollElevMixGain) << 1;
		pitchAccum.WW = __builtin_mulss(pitchAccum._.W1 , rmat[6]) >> 3;
		navElevMix += pitchAccum._.W1;
	}

	pitchAccum.WW = (__builtin_mulss(rmat8 , omegagyro[0])
	               - __builtin_mulss(rmat6 , omegagyro[2])) << 1;
	pitchrate = pitchAccum._.W1;
	
	if (!udb_flags._.radio_on && flags._.GPS_steering)
	{
		rtlkick = RTLKICK;
	}
	else
	{
		rtlkick = 0;
	}

#if(GLIDE_AIRSPEED_CONTROL == 1)
	fractional aspd_pitch_adj = gliding_airspeed_pitch_adjust();
#endif

	if (PITCH_STABILIZATION && flags._.pitch_feedback)
	{
#if(GLIDE_AIRSPEED_CONTROL == 1)
		pitchAccum.WW = __builtin_mulsu(rmat7 - rtlkick + aspd_pitch_adj + pitchAltitudeAdjust, pitchgain) 
		              + __builtin_mulus(pitchkd , pitchrate);
#else
		pitchAccum.WW = __builtin_mulsu(rmat7 - rtlkick + pitchAltitudeAdjust, pitchgain) 
		              + __builtin_mulus(pitchkd , pitchrate);
#endif
	}
	else
	{
		pitchAccum.WW = 0;
	}

	pitch_control = (int32_t)pitchAccum._.W1 + navElevMix;
}
Exemple #8
0
void normalYawCntrl(void)
{
	int16_t yawNavDeflection;
	union longww rollStabilization;
	union longww gyroYawFeedback;
	int16_t ail_rud_mix;

#ifdef TestGains
	flags._.GPS_steering = 0; // turn off navigation
	flags._.pitch_feedback = 1; // turn on stabilization
#endif 
	if (RUDDER_NAVIGATION && flags._.GPS_steering)
	{
		yawNavDeflection = determine_navigation_deflection('y');
		
		if (canStabilizeInverted() && current_orientation == F_INVERTED)
		{
			yawNavDeflection = -yawNavDeflection;
		}
	}
	else
	{
		yawNavDeflection = 0;
	}

	if (YAW_STABILIZATION_RUDDER && flags._.pitch_feedback)
	{
		gyroYawFeedback.WW = __builtin_mulus(yawkdrud, omegaAccum[2]);
	}
	else
	{
		gyroYawFeedback.WW = 0;
	}

	rollStabilization.WW = 0; // default case is no roll rudder stabilization
	if (ROLL_STABILIZATION_RUDDER && flags._.pitch_feedback)
	{
		if (!desired_behavior._.inverted && !desired_behavior._.hover)  // normal
		{
			rollStabilization.WW = __builtin_mulsu(rmat[6], rollkprud);
		}
		else if (desired_behavior._.inverted) // inverted
		{
			rollStabilization.WW = - __builtin_mulsu(rmat[6], rollkprud);
		}
		rollStabilization.WW -= __builtin_mulus(rollkdrud, omegaAccum[1]);
	}

	if (flags._.pitch_feedback)
	{
		int16_t ail_offset = (udb_flags._.radio_on) ? (udb_pwIn[AILERON_INPUT_CHANNEL] - udb_pwTrim[AILERON_INPUT_CHANNEL]) : 0;
		ail_rud_mix = MANUAL_AILERON_RUDDER_MIX * REVERSE_IF_NEEDED(AILERON_CHANNEL_REVERSED, ail_offset);
		if (canStabilizeInverted() && current_orientation == F_INVERTED) ail_rud_mix = -ail_rud_mix;
	}
	else
	{
		ail_rud_mix = 0;
	}

	yaw_control = (int32_t)yawNavDeflection 
	            - (int32_t)gyroYawFeedback._.W1 
	            + (int32_t)rollStabilization._.W1 
	            + ail_rud_mix;
	// Servo reversing is handled in servoMix.c
}