void airspeed_analog_update(airspeed_analog_t* airspeed_analog)
{
	float raw_airspeed = 0.0f;

	///< measure differential pressure and remove offset
	airspeed_analog->differential_pressure = airspeed_analog_get_pressure(airspeed_analog) - airspeed_analog->pressure_offset;

	///< Avoid negative pressures
	airspeed_analog->differential_pressure = abs(airspeed_analog->differential_pressure);

	///< compute airspeed from differential pressure using Bernouilli
	raw_airspeed = maths_fast_sqrt(airspeed_analog->differential_pressure * airspeed_analog->gain);

	///< Filter airspeed estimation
	airspeed_analog->airspeed = 0.7f * airspeed_analog->airspeed + 0.3f * raw_airspeed; 
}
Exemplo n.º 2
0
void calculate_radar(dsp16_t i_buffer[], dsp16_t q_buffer[])
{
    int32_t i = 0;
    int32_t j = 0;
    int32_t counter = 0;
    int32_t reading_status = 3;
    int32_t* c = 0;
    int32_t read_value = 0;
    int32_t index = 0;

    dsp16_trans_realcomplexfft(vect_outputI, i_buffer, FFT_POWER);  //WARNING !! If you change the buffer size you need to change the base 2 power size
    dsp16_trans_realcomplexfft(vect_outputQ, q_buffer, FFT_POWER);  //WARNING !! If you change the buffer size you need to change the base 2 power size

    for (i = 0; i < RADAR_BUFFER_SIZE; i++)
    {
        fft_amp[i] = maths_fast_sqrt(SQR(vect_outputI[i].real) + SQR(vect_outputI[i].imag));
    }

    //Find maximum of FFT and corresponding frequency
    //time1 = time_keeper_get_us();
    amplitude = 0;
    index = 0;
    for (i = 1; i < RADAR_BUFFER_SIZE / 2 - 1; i++) //ignore the element 0 (low frequency noise)
    {
        if (fft_amp[i] > amplitude)
        {
            amplitude = fft_amp[i];
            index = i;          //find index of max
        }
    }

    //Let's find the second maximum peak
    amplitude2 = 0;
    index2 = 0;
    for (i = 1; i < RADAR_BUFFER_SIZE / 2 - 1; i++)
    {
        if (fft_amp[i] > amplitude2 && i != index)
        {
            amplitude2 = fft_amp[i];
            index2 = i;
        }
    }

    //Don't need to test the following with index2 because index corresponds to the absolute maximum anyway
    if (index > 1)
    {
        mean_amp = (2 * fft_amp[index] + fft_amp[index + 1] + fft_amp[index - 1]) / 4; //Average on the three peaks in Fourier domain
    }
    else
    {
        mean_amp = (fft_amp[index] + fft_amp[index + 1]) / 2; //Same average
    }

    if (mean_amp < THRESHOLD)
    {
        mean_amp = 0;
        index = 0;
        index2 = 0;
        amp_old = 0;
        speed = 0;
    }
    else
    {
        //lowpass exponential filtering applied (alpha =0.75f so we multiply by 100, do the operations then divide by 100)
        if (index > 1)
        {
            mean_amp = (alpha * ((fft_amp[index] + fft_amp[index + 1] + fft_amp[index - 1]) / 3) + (filter_conversion - alpha) * amp_old) / filter_conversion;
            amp_old = mean_amp; //update the value of the previous amplitude for next iteration
        }
        else
        {
            mean_amp = (alpha * ((fft_amp[index] + fft_amp[index + 1]) / 2) + (filter_conversion - alpha) * amp_old) / filter_conversion;
            amp_old = mean_amp;
        }
        //Factor 1000 for speed to avoid decimal value
        //The true speed is (speed) / 100 (m / s) or interpret it as cm / s

        frequency = f_v_factor * 10 * (index);
        speed = 1000 * (3 * powf(10, 8) * frequency / (2 * 2415 * pow(10, 9))); //compute speed (*0.01f because of Fsample and *10 because of freq)

        frequency = f_v_factor * 10 * (index2);
        speed2 = 1000 * (3 * powf(10, 8) * frequency / (2 * 2415 * pow(10, 9)));    //compute speed (*0.01f because of Fsample and *10 because of freq)

        //Let's find the speed that is closer to the previous one (to avoid high frequency changes for the speed)

        if (abs(speed - speed_old) <= abs(speed2 - speed_old))
        {
            speed_old = speed;          //update the old speed

        }
        else if (abs(speed - speed_old) > abs(speed2 - speed_old)) // in this case the speed is the one corresponding to the second peak
        {
            speed_old = speed2;     //update the old speed
            speed = speed2;
            index = index2;

            if (index > 1)
            {
                mean_amp = (alpha * ((fft_amp[index2] + fft_amp[index2 + 1] + fft_amp[index2 - 1]) / 3) + (filter_conversion - alpha) * amp_old) / filter_conversion;
                amp_old = mean_amp;
            }
            else
            {
                //mean_amp = (vect_inputQ[index2] + vect_inputQ[index2 + 1]) / 2;
                mean_amp = (alpha * ((fft_amp[index2] + fft_amp[index2 + 1]) / 2) + (filter_conversion - alpha) * amp_old) / filter_conversion;
                amp_old = mean_amp;
            }
        }
    }

    //Find the direction of motion by doing vector product between I and Q channel
    if (vect_outputI[index].real * vect_outputQ[index].imag - vect_outputI[index].imag * vect_outputQ[index].real < 0)
    {
        direction = -1;
    }
    else if (speed == 0)
    {
        direction = 0;
    }
    else
    {
        direction = 1;
    }

    for (i = 0; i < RADAR_BUFFER_SIZE; i++)
    {
        if (vect_outputI[index].real * vect_outputQ[index].imag - vect_outputI[index].imag * vect_outputQ[index].real < 0)
        {
            fft_amp[i] = -fft_amp[i];
        }
    }

    time2 = time_keeper_get_us();
    time_result = time2 - time1;
    time1 = time_keeper_get_us();

    main_target.velocity = direction * speed / 100.0f;
    //main_target.velocity = speed / 100.0f;
    main_target.amplitude = amplitude;

    amplitude = 0;
    amplitude2 = 0;
    index = 0;
    index2 = 0;
    input_min = 0;
    input_max = 0;
    rms = 0;
    mean_amp = 0;
    read_value = 0;
}
Exemplo n.º 3
0
void qfilter_update(qfilter_t *qf)
{
	static uint32_t convergence_update_count = 0;
	float  omc[3], omc_mag[3] , tmp[3], snorm, norm, s_acc_norm, acc_norm, s_mag_norm, mag_norm;
	quat_t qed, qtmp1, up, up_bf;
	quat_t mag_global, mag_corrected_local;
	quat_t front_vec_global = 
	{
		.s = 0.0f, 
		.v = {1.0f, 0.0f, 0.0f}
	};

	float kp 	 = qf->kp;
	float kp_mag = qf->kp_mag;
	float ki 	 = qf->ki;
	float ki_mag = qf->ki_mag;

	// Update time in us
	float now_us 	= time_keeper_get_micros();
	
	// Delta t in seconds
	float dt     = 1e-6 * (float)(now_us - qf->ahrs->last_update);
	
	// Write to ahrs structure
	qf->ahrs->dt 		  = dt;
	qf->ahrs->last_update = now_us;

	
	// up_bf = qe^-1 *(0,0,0,-1) * qe
	up.s = 0; up.v[X] = UPVECTOR_X; up.v[Y] = UPVECTOR_Y; up.v[Z] = UPVECTOR_Z;
	up_bf = quaternions_global_to_local(qf->ahrs->qe, up);
	
	// calculate norm of acceleration vector
	s_acc_norm = qf->imu->scaled_accelero.data[X] * qf->imu->scaled_accelero.data[X] + qf->imu->scaled_accelero.data[Y] * qf->imu->scaled_accelero.data[Y] + qf->imu->scaled_accelero.data[Z] * qf->imu->scaled_accelero.data[Z];
	if ( (s_acc_norm > 0.7f * 0.7f) && (s_acc_norm < 1.3f * 1.3f) ) 
	{
		// approximate square root by running 2 iterations of newton method
		acc_norm = maths_fast_sqrt(s_acc_norm);

		tmp[X] = qf->imu->scaled_accelero.data[X] / acc_norm;
		tmp[Y] = qf->imu->scaled_accelero.data[Y] / acc_norm;
		tmp[Z] = qf->imu->scaled_accelero.data[Z] / acc_norm;

		// omc = a x up_bf.v
		CROSS(tmp, up_bf.v, omc);
	}
	else
	{
		omc[X] = 0;
		omc[Y] = 0;
		omc[Z] = 0;
	}

	// Heading computation
	// transfer 
	qtmp1 = quaternions_create_from_vector(qf->imu->scaled_compass.data); 
	mag_global = quaternions_local_to_global(qf->ahrs->qe, qtmp1);
	
	// calculate norm of compass vector
	//s_mag_norm = SQR(mag_global.v[X]) + SQR(mag_global.v[Y]) + SQR(mag_global.v[Z]);
	s_mag_norm = SQR(mag_global.v[X]) + SQR(mag_global.v[Y]);

	if ( (s_mag_norm > 0.004f * 0.004f) && (s_mag_norm < 1.8f * 1.8f) ) 
	{
		mag_norm = maths_fast_sqrt(s_mag_norm);

		mag_global.v[X] /= mag_norm;
		mag_global.v[Y] /= mag_norm;
		mag_global.v[Z] = 0.0f;   // set z component in global frame to 0

		// transfer magneto vector back to body frame 
		qf->ahrs->north_vec = quaternions_global_to_local(qf->ahrs->qe, front_vec_global);		
		
		mag_corrected_local = quaternions_global_to_local(qf->ahrs->qe, mag_global);		
		
		// omc = a x up_bf.v
		CROSS(mag_corrected_local.v, qf->ahrs->north_vec.v,  omc_mag);
		
	}
	else
	{
		omc_mag[X] = 0;
		omc_mag[Y] = 0;
		omc_mag[Z] = 0;
	}


	// get error correction gains depending on mode
	switch (qf->ahrs->internal_state)
	{
		case AHRS_UNLEVELED:
			kp = qf->kp * 10.0f;
			kp_mag = qf->kp_mag * 10.0f;
			
			ki = 0.5f * qf->ki;
			ki_mag = 0.5f * qf->ki_mag;
			
			convergence_update_count += 1;
			if( convergence_update_count > 2000 )
			{
				convergence_update_count = 0;
				qf->ahrs->internal_state = AHRS_CONVERGING;
				print_util_dbg_print("End of AHRS attitude initialization.\r\n");
			}
			break;
			
		case AHRS_CONVERGING:
			kp = qf->kp;
			kp_mag = qf->kp_mag;
			
			ki = qf->ki * 3.0f;
			ki_mag = qf->ki_mag * 3.0f;
			
			convergence_update_count += 1;
			if( convergence_update_count > 2000 )
			{
				convergence_update_count = 0;
				qf->ahrs->internal_state = AHRS_READY;
				print_util_dbg_print("End of AHRS leveling.\r\n");
			}
			break;

		case AHRS_READY:
			kp = qf->kp;
			kp_mag = qf->kp_mag;
			ki = qf->ki;
			ki_mag = qf->ki_mag;
			break;
	}

	// apply error correction with appropriate gains for accelerometer and compass

	for (uint8_t i = 0; i < 3; i++)
	{
		qtmp1.v[i] = 0.5f * (qf->imu->scaled_gyro.data[i] + kp * omc[i] + kp_mag * omc_mag[i]);
	}
	qtmp1.s = 0;

	// apply step rotation with corrections
	qed = quaternions_multiply(qf->ahrs->qe,qtmp1);

	// TODO: correct this formulas! 
	qf->ahrs->qe.s = qf->ahrs->qe.s + qed.s * dt;
	qf->ahrs->qe.v[X] += qed.v[X] * dt;
	qf->ahrs->qe.v[Y] += qed.v[Y] * dt;
	qf->ahrs->qe.v[Z] += qed.v[Z] * dt;

	snorm = qf->ahrs->qe.s * qf->ahrs->qe.s + qf->ahrs->qe.v[X] * qf->ahrs->qe.v[X] + qf->ahrs->qe.v[Y] * qf->ahrs->qe.v[Y] + qf->ahrs->qe.v[Z] * qf->ahrs->qe.v[Z];
	if (snorm < 0.0001f)
	{
		norm = 0.01f;
	}
	else
	{
		// approximate square root by running 2 iterations of newton method
		norm = maths_fast_sqrt(snorm);
	}
	qf->ahrs->qe.s /= norm;
	qf->ahrs->qe.v[X] /= norm;
	qf->ahrs->qe.v[Y] /= norm;
	qf->ahrs->qe.v[Z] /= norm;

	// bias estimate update
	qf->imu->calib_gyro.bias[X] += - dt * ki * omc[X] / qf->imu->calib_gyro.scale_factor[X];
	qf->imu->calib_gyro.bias[Y] += - dt * ki * omc[Y] / qf->imu->calib_gyro.scale_factor[Y];
	qf->imu->calib_gyro.bias[Z] += - dt * ki * omc[Z] / qf->imu->calib_gyro.scale_factor[Z];
	
	qf->imu->calib_gyro.bias[X] += - dt * ki_mag * omc_mag[X] / qf->imu->calib_compass.scale_factor[X];
	qf->imu->calib_gyro.bias[Y] += - dt * ki_mag * omc_mag[Y] / qf->imu->calib_compass.scale_factor[Y];
	qf->imu->calib_gyro.bias[Z] += - dt * ki_mag * omc_mag[Z] / qf->imu->calib_compass.scale_factor[Z];
	
	// set up-vector (bodyframe) in attitude
	qf->ahrs->up_vec.v[X] = up_bf.v[X];
	qf->ahrs->up_vec.v[Y] = up_bf.v[Y];
	qf->ahrs->up_vec.v[Z] = up_bf.v[Z];

	// Update linear acceleration
	qf->ahrs->linear_acc[X] = 9.81f * (qf->imu->scaled_accelero.data[X] - qf->ahrs->up_vec.v[X]) ;							// TODO: review this line!
	qf->ahrs->linear_acc[Y] = 9.81f * (qf->imu->scaled_accelero.data[Y] - qf->ahrs->up_vec.v[Y]) ;							// TODO: review this line!
	qf->ahrs->linear_acc[Z] = 9.81f * (qf->imu->scaled_accelero.data[Z] - qf->ahrs->up_vec.v[Z]) ;							// TODO: review this line!

	//update angular_speed.
	qf->ahrs->angular_speed[X] = qf->imu->scaled_gyro.data[X];
	qf->ahrs->angular_speed[Y] = qf->imu->scaled_gyro.data[Y];
	qf->ahrs->angular_speed[Z] = qf->imu->scaled_gyro.data[Z];
}