예제 #1
0
/*----------------------------------------------------------------------------
 * norm_corr - Find the normalized correlation between the target vector and
 *             the filtered past excitation.
 *----------------------------------------------------------------------------
 */
static void norm_corr(
 FLOAT exc[],           /* input : excitation buffer */
 FLOAT xn[],            /* input : target vector */
 FLOAT h[],             /* input : imp response of synth and weighting flt */
 int l_subfr,           /* input : Length of frame to compute pitch */
 int t_min,             /* input : minimum value of searched range */
 int t_max,             /* input : maximum value of search range */
 FLOAT corr_norm[]      /* output: normalized correlation (correlation between
                                   target and filtered excitation divided by
                                   the square root of energy of filtered
                                    excitation) */
)
{
 int    i, j, k;
 FLOAT excf[L_SUBFR];     /* filtered past excitation */
 FLOAT  alp, s, norm;

 k = -t_min;

 /* compute the filtered excitation for the first delay t_min */

 convolve(&exc[k], h, excf, l_subfr);

 /* loop for every possible period */

 for (i = t_min; i <= t_max; i++)
 {
   /* Compute 1/sqrt(energie of excf[]) */

   alp = (F)0.01;
   for (j = 0; j < l_subfr; j++)
     alp += excf[j]*excf[j];

   norm = inv_sqrt(alp);


   /* Compute correlation between xn[] and excf[] */

   s = (F)0.0;
   for (j = 0; j < l_subfr; j++)  s += xn[j]*excf[j];


   /* Normalize correlation = correlation * (1/sqrt(energie)) */

   corr_norm[i] = s*norm;

   /* modify the filtered excitation excf[] for the next iteration */

   if (i != t_max)
   {
     k--;
     for (j = l_subfr-1; j > 0; j--)
        excf[j] = excf[j-1] + exc[k]*h[j];
     excf[0] = exc[k];
   }
 }

 return;

}
예제 #2
0
파일: ahrs.c 프로젝트: Aerobota/PenguPilot
static void ahrs_normalize_3(real_t *v0, real_t *v1, real_t *v2)
{
   real_t recip_norm = inv_sqrt(*v0 * *v0 + *v1 * *v1 + *v2 * *v2);
   *v0 *= recip_norm;
   *v1 *= recip_norm;
   *v2 *= recip_norm;
}
예제 #3
0
// Quaternion Normalization operator. Expects its 4-element arrays in wxyz order 
void quat_norm(float a[4]) {
  float n = a[1]*a[1] + a[2]*a[2] + a[3]*a[3] + a[0]*a[0];

  if (n == 1.0f) 
    return ;

  n = inv_sqrt(n);

  a[1]*=n;
  a[2]*=n;
  a[3]*=n;
  a[0]*=n;

  return;
}
예제 #4
0
/*----------------------------------------------------------------------------
 * lag_max - Find the lag that has maximum correlation
 *----------------------------------------------------------------------------
 */
static int lag_max(     /* output: lag found */
  FLOAT signal[],       /* input : Signal to compute the open loop pitch
                                   signal[-142:-1] should be known.       */
  int l_frame,          /* input : Length of frame to compute pitch       */
  int lagmax,           /* input : maximum lag                            */
  int lagmin,           /* input : minimum lag                            */
  FLOAT *cor_max        /* input : normalized correlation of selected lag */
)
{
    int    i, j;
    FLOAT  *p, *p1;
    FLOAT  max, t0;
    int    p_max;

    max = FLT_MIN_G729;

    for (i = lagmax; i >= lagmin; i--) {
        p  = signal;
        p1 = &signal[-i];
        t0 = (F)0.0;

        for (j=0; j<l_frame; j++) {
            t0 += *p++ * *p1++;
        }

        if (t0 >= max) {
            max    = t0;
            p_max = i;
        }
    }

    /* compute energy */

    t0 = (F)0.01;                  /* to avoid division by zero */
    p = &signal[-p_max];
    for(i=0; i<l_frame; i++, p++) {
        t0 += *p * *p;
    }
    t0 = inv_sqrt(t0);          /* 1/sqrt(energy)    */

    *cor_max = max * t0;        /* max/sqrt(energy)  */

    return(p_max);
}
예제 #5
0
파일: target.c 프로젝트: shortlab/IM3D
/*=============================================================================
  Function Name : cal_relative_target_atom_position
  Description   : This calculates the direction in which the target nucleus is found.
                  v is the projectile velocity vector, the IP vector is returned
                  in p components.

  Inputs  :
            float vx,float vy, float vz
            unsigned int azim_angle
  Outputs : float *px, float *py, float *pz

  Notes :
      This routine works similar to the rotation (DIRCOS) routine. It simply
      assumes a fixed scattering angle of 90 degrees and reverses the resulting
      vector. Adding the result multiplied with impact_par to the current
      projectile position leads to the target nucleus position.

      Function call:
        fromcorteo - float my_inv_sqrt (float val);
                     float sqrtdf (double val).
=============================================================================*/
void cal_relative_target_atom_position (double vx, double vy, double vz, double *px,
                             double *py, double *pz, unsigned int iazim_angle) {
    float k, kinv;
    float k2 = 1.0f - vz * vz;

    /* random azimutal rotation angle components */
    float cosomega = cos_azim_angle[iazim_angle];
    float sinomega = sin_azim_angle[iazim_angle];
    /* In the rotation routine, we would have to increase the azim-counter here, but
       since we want to have the same angle for target position and deflection, we must
       not change the index in this function! */
    if (k2 < 0.000001) {  /* extremely rare case */
        *pz = 0;
        *py = cosomega;
        *px = sinomega;
        return;
    }

    /* usual case */
#ifndef SAFE_SQR_ROTATION
    kinv = inv_sqrt (k2);  /* 1/sqrt() (approximate) */
    k = k2 * kinv;         /* so we get k and 1/k by a table lookup and a multiplication */
#else
    /* these two lines can be replaced by the following two lines but... */
    k  = sqrtdf (k2);   /* ... using a sqrt() here makes the program 25% slower! */
    kinv = 1.0f / k;
#endif

    *px = -kinv * (vx * vz * cosomega + vy * sinomega);
    *py = -kinv * (vy * vz * cosomega - vx * sinomega);
    *pz =  k * cosomega;

#ifdef SAFE_ROTATION  /* makes slower, but safer */
    if (*px > 1)  *px =  1;
    if (*px < -1) *px = -1;
    if (*py > 1)  *py =  1;
    if (*py < -1) *py = -1;
    if (*pz > 1)  *pz =  1;
    if (*pz < -1) *pz = -1;
#endif

    return;
}
예제 #6
0
void spatial_ahrs_update_imu(SpatialInfo *spatial_info, 
    float gx, float gy, float gz, 
    float ax, float ay, float az) {

  // Just a shorthand meant to make this a bit easier to work with, and transact
  // commits (eventually)
  float q0 = spatial_info->orientation_q[0];
  float q1 = spatial_info->orientation_q[1];
  float q2 = spatial_info->orientation_q[2];
  float q3 = spatial_info->orientation_q[3];

  float sample_rate_in_hz = 1000.0f / spatial_info->data_rate;

	float recipNorm;
	float s0, s1, s2, s3;
	float qDot1, qDot2, qDot3, qDot4;
	float _2q0, _2q1, _2q2, _2q3, _4q0, _4q1, _4q2 ,_8q1, _8q2, q0q0, q1q1, q2q2, q3q3;

	// Rate of change of quaternion from gyroscope
	qDot1 = 0.5f * (-q1 * gx - q2 * gy - q3 * gz);
	qDot2 = 0.5f * (q0 * gx + q2 * gz - q3 * gy);
	qDot3 = 0.5f * (q0 * gy - q1 * gz + q3 * gx);
	qDot4 = 0.5f * (q0 * gz + q1 * gy - q2 * gx);

	// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
	if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {

		// Normalise accelerometer measurement
		recipNorm = inv_sqrt(ax * ax + ay * ay + az * az);
		ax *= recipNorm;
		ay *= recipNorm;
		az *= recipNorm;   

		// Auxiliary variables to avoid repeated arithmetic
		_2q0 = 2.0f * q0;
		_2q1 = 2.0f * q1;
		_2q2 = 2.0f * q2;
		_2q3 = 2.0f * q3;
		_4q0 = 4.0f * q0;
		_4q1 = 4.0f * q1;
		_4q2 = 4.0f * q2;
		_8q1 = 8.0f * q1;
		_8q2 = 8.0f * q2;
		q0q0 = q0 * q0;
		q1q1 = q1 * q1;
		q2q2 = q2 * q2;
		q3q3 = q3 * q3;

		// Gradient decent algorithm corrective step
		s0 = _4q0 * q2q2 + _2q2 * ax + _4q0 * q1q1 - _2q1 * ay;
		s1 = _4q1 * q3q3 - _2q3 * ax + 4.0f * q0q0 * q1 - _2q0 * ay - _4q1 + _8q1 * q1q1 + _8q1 * q2q2 + _4q1 * az;
		s2 = 4.0f * q0q0 * q2 + _2q0 * ax + _4q2 * q3q3 - _2q3 * ay - _4q2 + _8q2 * q1q1 + _8q2 * q2q2 + _4q2 * az;
		s3 = 4.0f * q1q1 * q3 - _2q1 * ax + 4.0f * q2q2 * q3 - _2q2 * ay;
		recipNorm = inv_sqrt(s0 * s0 + s1 * s1 + s2 * s2 + s3 * s3); // normalise step magnitude
		s0 *= recipNorm;
		s1 *= recipNorm;
		s2 *= recipNorm;
		s3 *= recipNorm;

		// Apply feedback step
		qDot1 -= SPATIAL_AHRS_BETA * s0;
		qDot2 -= SPATIAL_AHRS_BETA * s1;
		qDot3 -= SPATIAL_AHRS_BETA * s2;
		qDot4 -= SPATIAL_AHRS_BETA * s3;
	}

	// Integrate rate of change of quaternion to yield quaternion
	q0 += qDot1 * (1.0f / sample_rate_in_hz);
	q1 += qDot2 * (1.0f / sample_rate_in_hz);
	q2 += qDot3 * (1.0f / sample_rate_in_hz);
	q3 += qDot4 * (1.0f / sample_rate_in_hz);

	// Normalise quaternion
	recipNorm = inv_sqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
	q0 *= recipNorm;
	q1 *= recipNorm;
	q2 *= recipNorm;
	q3 *= recipNorm;

	spatial_info->orientation_q[0] = q0;
	spatial_info->orientation_q[1] = q1;
	spatial_info->orientation_q[2] = q2;
	spatial_info->orientation_q[3] = q3;
}
예제 #7
0
void spatial_ahrs_update(SpatialInfo *spatial_info, 
  float gx, float gy, float gz, 
  float ax, float ay, float az, 
  float mx, float my, float mz) {

  // Just a shorthand meant to make this a bit easier to work with, and transact
  // commits (eventually)
  float q0 = spatial_info->orientation_q[0];
  float q1 = spatial_info->orientation_q[1];
  float q2 = spatial_info->orientation_q[2];
  float q3 = spatial_info->orientation_q[3];

  float sample_rate_in_hz = 1000.0f / spatial_info->data_rate;

	float recipNorm;
	float s0, s1, s2, s3;
	float qDot1, qDot2, qDot3, qDot4;
	float hx, hy;
	float _2q0mx, _2q0my, _2q0mz, _2q1mx, _2bx, _2bz, _4bx, _4bz, _2q0, _2q1, _2q2, _2q3, _2q0q2, _2q2q3, q0q0, q0q1, q0q2, q0q3, q1q1, q1q2, q1q3, q2q2, q2q3, q3q3;

	// Rate of change of quaternion from gyroscope
	qDot1 = 0.5f * (-q1 * gx - q2 * gy - q3 * gz);
	qDot2 = 0.5f * (q0 * gx + q2 * gz - q3 * gy);
	qDot3 = 0.5f * (q0 * gy - q1 * gz + q3 * gx);
	qDot4 = 0.5f * (q0 * gz + q1 * gy - q2 * gx);

	// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
	if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {

		// Normalise accelerometer measurement
		recipNorm = inv_sqrt(ax * ax + ay * ay + az * az);
		ax *= recipNorm;
		ay *= recipNorm;
		az *= recipNorm;   

		// Normalise magnetometer measurement
		recipNorm = inv_sqrt(mx * mx + my * my + mz * mz);
		mx *= recipNorm;
		my *= recipNorm;
		mz *= recipNorm;

		// Auxiliary variables to avoid repeated arithmetic
		_2q0mx = 2.0f * q0 * mx;
		_2q0my = 2.0f * q0 * my;
		_2q0mz = 2.0f * q0 * mz;
		_2q1mx = 2.0f * q1 * mx;
		_2q0 = 2.0f * q0;
		_2q1 = 2.0f * q1;
		_2q2 = 2.0f * q2;
		_2q3 = 2.0f * q3;
		_2q0q2 = 2.0f * q0 * q2;
		_2q2q3 = 2.0f * q2 * q3;
		q0q0 = q0 * q0;
		q0q1 = q0 * q1;
		q0q2 = q0 * q2;
		q0q3 = q0 * q3;
		q1q1 = q1 * q1;
		q1q2 = q1 * q2;
		q1q3 = q1 * q3;
		q2q2 = q2 * q2;
		q2q3 = q2 * q3;
		q3q3 = q3 * q3;

		// Reference direction of Earth's magnetic field
		hx = mx * q0q0 - _2q0my * q3 + _2q0mz * q2 + mx * q1q1 + _2q1 * my * q2 + _2q1 * mz * q3 - mx * q2q2 - mx * q3q3;
		hy = _2q0mx * q3 + my * q0q0 - _2q0mz * q1 + _2q1mx * q2 - my * q1q1 + my * q2q2 + _2q2 * mz * q3 - my * q3q3;
		_2bx = sqrt(hx * hx + hy * hy);
		_2bz = -_2q0mx * q2 + _2q0my * q1 + mz * q0q0 + _2q1mx * q3 - mz * q1q1 + _2q2 * my * q3 - mz * q2q2 + mz * q3q3;
		_4bx = 2.0f * _2bx;
		_4bz = 2.0f * _2bz;

		// Gradient decent algorithm corrective step
		s0 = -_2q2 * (2.0f * q1q3 - _2q0q2 - ax) + _2q1 * (2.0f * q0q1 + _2q2q3 - ay) - _2bz * q2 * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (-_2bx * q3 + _2bz * q1) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + _2bx * q2 * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz);
		s1 = _2q3 * (2.0f * q1q3 - _2q0q2 - ax) + _2q0 * (2.0f * q0q1 + _2q2q3 - ay) - 4.0f * q1 * (1 - 2.0f * q1q1 - 2.0f * q2q2 - az) + _2bz * q3 * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (_2bx * q2 + _2bz * q0) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + (_2bx * q3 - _4bz * q1) * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz);
		s2 = -_2q0 * (2.0f * q1q3 - _2q0q2 - ax) + _2q3 * (2.0f * q0q1 + _2q2q3 - ay) - 4.0f * q2 * (1 - 2.0f * q1q1 - 2.0f * q2q2 - az) + (-_4bx * q2 - _2bz * q0) * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (_2bx * q1 + _2bz * q3) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + (_2bx * q0 - _4bz * q2) * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz);
		s3 = _2q1 * (2.0f * q1q3 - _2q0q2 - ax) + _2q2 * (2.0f * q0q1 + _2q2q3 - ay) + (-_4bx * q3 + _2bz * q1) * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (-_2bx * q0 + _2bz * q2) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + _2bx * q1 * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz);
		recipNorm = inv_sqrt(s0 * s0 + s1 * s1 + s2 * s2 + s3 * s3); // normalise step magnitude
		s0 *= recipNorm;
		s1 *= recipNorm;
		s2 *= recipNorm;
		s3 *= recipNorm;

		// Apply feedback step
		qDot1 -= SPATIAL_AHRS_BETA * s0;
		qDot2 -= SPATIAL_AHRS_BETA * s1;
		qDot3 -= SPATIAL_AHRS_BETA * s2;
		qDot4 -= SPATIAL_AHRS_BETA * s3;
	}

	// Integrate rate of change of quaternion to yield quaternion
	q0 += qDot1 * (1.0f / sample_rate_in_hz);
	q1 += qDot2 * (1.0f / sample_rate_in_hz);
	q2 += qDot3 * (1.0f / sample_rate_in_hz);
	q3 += qDot4 * (1.0f / sample_rate_in_hz);

	// Normalise quaternion
	recipNorm = inv_sqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
	q0 *= recipNorm;
	q1 *= recipNorm;
	q2 *= recipNorm;
	q3 *= recipNorm;

	spatial_info->orientation_q[0] = q0;
	spatial_info->orientation_q[1] = q1;
	spatial_info->orientation_q[2] = q2;
	spatial_info->orientation_q[3] = q3;
}