Пример #1
0
CFLOAT
M_DECL_FUNC (__catanh) (CFLOAT x)
{
  CFLOAT res;
  int rcls = fpclassify (__real__ x);
  int icls = fpclassify (__imag__ x);

  if (__glibc_unlikely (rcls <= FP_INFINITE || icls <= FP_INFINITE))
    {
      if (icls == FP_INFINITE)
	{
	  __real__ res = M_COPYSIGN (0, __real__ x);
	  __imag__ res = M_COPYSIGN (M_MLIT (M_PI_2), __imag__ x);
	}
      else if (rcls == FP_INFINITE || rcls == FP_ZERO)
	{
	  __real__ res = M_COPYSIGN (0, __real__ x);
	  if (icls >= FP_ZERO)
	    __imag__ res = M_COPYSIGN (M_MLIT (M_PI_2), __imag__ x);
	  else
	    __imag__ res = M_NAN;
	}
      else
	{
	  __real__ res = M_NAN;
	  __imag__ res = M_NAN;
	}
    }
  else if (__glibc_unlikely (rcls == FP_ZERO && icls == FP_ZERO))
    {
      res = x;
    }
  else
    {
      if (M_FABS (__real__ x) >= 16 / M_EPSILON
	  || M_FABS (__imag__ x) >= 16 / M_EPSILON)
	{
	  __imag__ res = M_COPYSIGN (M_MLIT (M_PI_2), __imag__ x);
	  if (M_FABS (__imag__ x) <= 1)
	    __real__ res = 1 / __real__ x;
	  else if (M_FABS (__real__ x) <= 1)
	    __real__ res = __real__ x / __imag__ x / __imag__ x;
	  else
	    {
	      FLOAT h = M_HYPOT (__real__ x / 2, __imag__ x / 2);
	      __real__ res = __real__ x / h / h / 4;
	    }
	}
      else
	{
	  if (M_FABS (__real__ x) == 1
	      && M_FABS (__imag__ x) < M_EPSILON * M_EPSILON)
	    __real__ res = (M_COPYSIGN (M_LIT (0.5), __real__ x)
			    * ((FLOAT) M_MLIT (M_LN2)
			       - M_LOG (M_FABS (__imag__ x))));
	  else
	    {
	      FLOAT i2 = 0;
	      if (M_FABS (__imag__ x) >= M_EPSILON * M_EPSILON)
		i2 = __imag__ x * __imag__ x;

	      FLOAT num = 1 + __real__ x;
	      num = i2 + num * num;

	      FLOAT den = 1 - __real__ x;
	      den = i2 + den * den;

	      FLOAT f = num / den;
	      if (f < M_LIT (0.5))
		__real__ res = M_LIT (0.25) * M_LOG (f);
	      else
		{
		  num = 4 * __real__ x;
		  __real__ res = M_LIT (0.25) * M_LOG1P (num / den);
		}
	    }

	  FLOAT absx, absy, den;

	  absx = M_FABS (__real__ x);
	  absy = M_FABS (__imag__ x);
	  if (absx < absy)
	    {
	      FLOAT t = absx;
	      absx = absy;
	      absy = t;
	    }

	  if (absy < M_EPSILON / 2)
	    {
	      den = (1 - absx) * (1 + absx);
	      if (den == 0)
		den = 0;
	    }
	  else if (absx >= 1)
	    den = (1 - absx) * (1 + absx) - absy * absy;
	  else if (absx >= M_LIT (0.75) || absy >= M_LIT (0.5))
	    den = -M_SUF (__x2y2m1) (absx, absy);
	  else
	    den = (1 - absx) * (1 + absx) - absy * absy;

	  __imag__ res = M_LIT (0.5) * M_ATAN2 (2 * __imag__ x, den);
	}

      math_check_force_underflow_complex (res);
    }

  return res;
}
Пример #2
0
/**
* full state strap down IMU emulation function.
* output IS A/V state as sensed at IMU given location.
*
* @param  {struct} IMU inputs
* @return {struct} IMU outputs
**/
void F_IMU(struct imu_inputs_def *pIn, struct imu_outputs_def *pOut) {
	// locals
	double _omega[3][3],			// rotational velocity matrix
	       _earth2body[3][3],		// earth -> body transformation matrix
	       _body2earth[3][3],		// body -> earth transformation matrix
	       _imu2body[3][3],			// IMU -> body transformation matrix
	       _body2imu[3][3],			// body -> IMU transformation matrix
	       _geodeticCG[3],			// {lat, long, alt} of the cg [rad, rad, ft]
	       _matTemp1[3][3],			// temporary matrix
	       _vectorTemp1[3],			// temporary vector
	       _VectorTemp2[3],			// temporary vector
	       _vectorTemp3[3],			// temporary vector
	       _lat, _lon;				// latitude and longitude [rad]

	// construct Euler "omega cross" matrix
	_omega[_X][_X] =  0.0;
	_omega[_X][_Y] = -pIn->cg_pqr[_Z];
	_omega[_X][_Z] =  pIn->cg_pqr[_Y];
	_omega[_Y][_X] =  pIn->cg_pqr[_Z];
	_omega[_Y][_Y] =  0.0;
	_omega[_Y][_Z] = -pIn->cg_pqr[_X];
	_omega[_Z][_X] = -pIn->cg_pqr[_Y];
	_omega[_Z][_Y] =  pIn->cg_pqr[_X];
	_omega[_Z][_Z] =  0.0;

	// create earth to body transformation matrix
	F_EULER_TO_DCM(_earth2body, pIn->cg_THETA[_PHI], pIn->cg_THETA[_THETA], pIn->cg_THETA[_PSI]);

	// create body to earth transformation matrix
	M_MAT_TRANSPOSE(_body2earth, _earth2body);

	// create body to IMU transformation matrix
	memcpy(_body2imu, pIn->body2imu, 9 * sizeof(double));

	// create IMU to body transformation matrix
	M_MAT_TRANSPOSE(_imu2body, _body2imu);

	// calculate C.G location in geodetic coordinate system [ft]
	_vectorTemp1[_X] = pIn->cg_pos[_X] * C_FOOT_TO_METER;
	_vectorTemp1[_Y] = pIn->cg_pos[_Y] * C_FOOT_TO_METER;
	_vectorTemp1[_Z] = pIn->cg_pos[_Z] * C_FOOT_TO_METER;
	F_ECEF_TO_GEODETIC(_vectorTemp1, _geodeticCG);
	_geodeticCG[_Z] = _geodeticCG[_Z] * C_METER_TO_FOOT;
	_lat = _geodeticCG[_X];
	_lon = _geodeticCG[_Y];

	// calculate acceleration vector at IMU location ( a_imu = _body2imu * (a_cg + (alpha X position) + (w X (w X position)) )
	// alpha X position
	_vectorTemp1[_X] = pIn->cg_alpha[_Y] * pIn->cg2imu[_Z] - pIn->cg_alpha[_Z] * pIn->cg2imu[_Y];
	_vectorTemp1[_Y] = pIn->cg_alpha[_Z] * pIn->cg2imu[_X] - pIn->cg_alpha[_X] * pIn->cg2imu[_Z];
	_vectorTemp1[_Z] = pIn->cg_alpha[_X] * pIn->cg2imu[_Y] - pIn->cg_alpha[_Y] * pIn->cg2imu[_X];

	// _omega X _omega
	_matTemp1[_X][_X] = _omega[_X][_X] * _omega[_X][_X] + _omega[_X][_Y] * _omega[_Y][_X] + _omega[_X][_Z] * _omega[_Z][_X];
	_matTemp1[_X][_Y] = _omega[_X][_X] * _omega[_X][_Y] + _omega[_X][_Y] * _omega[_Y][_Y] + _omega[_X][_Z] * _omega[_Z][_Y];
	_matTemp1[_X][_Z] = _omega[_X][_X] * _omega[_X][_Z] + _omega[_X][_Y] * _omega[_Y][_Z] + _omega[_X][_Z] * _omega[_Z][_Z];
	_matTemp1[_Y][_X] = _omega[_Y][_X] * _omega[_X][_X] + _omega[_Y][_Y] * _omega[_Y][_X] + _omega[_Y][_Z] * _omega[_Z][_X];
	_matTemp1[_Y][_Y] = _omega[_Y][_X] * _omega[_X][_Y] + _omega[_Y][_Y] * _omega[_Y][_Y] + _omega[_Y][_Z] * _omega[_Z][_Y];
	_matTemp1[_Y][_Z] = _omega[_Y][_X] * _omega[_X][_Z] + _omega[_Y][_Y] * _omega[_Y][_Z] + _omega[_Y][_Z] * _omega[_Z][_Z];
	_matTemp1[_Z][_X] = _omega[_Z][_X] * _omega[_X][_X] + _omega[_Z][_Y] * _omega[_Y][_X] + _omega[_Z][_Z] * _omega[_Z][_X];
	_matTemp1[_Z][_Y] = _omega[_Z][_X] * _omega[_X][_Y] + _omega[_Z][_Y] * _omega[_Y][_Y] + _omega[_Z][_Z] * _omega[_Z][_Y];
	_matTemp1[_Z][_Z] = _omega[_Z][_X] * _omega[_X][_Z] + _omega[_Z][_Y] * _omega[_Y][_Z] + _omega[_Z][_Z] * _omega[_Z][_Z];

	// (_omega X _omega) X position
	_VectorTemp2[_X] = _matTemp1[_X][_X] * pIn->cg2imu[_X] + _matTemp1[_X][_Y] * pIn->cg2imu[_Y] + _matTemp1[_X][_Z] * pIn->cg2imu[_Z];
	_VectorTemp2[_Y] = _matTemp1[_Y][_X] * pIn->cg2imu[_X] + _matTemp1[_Y][_Y] * pIn->cg2imu[_Y] + _matTemp1[_Y][_Z] * pIn->cg2imu[_Z];
	_VectorTemp2[_Z] = _matTemp1[_Z][_X] * pIn->cg2imu[_X] + _matTemp1[_Z][_Y] * pIn->cg2imu[_Y] + _matTemp1[_Z][_Z] * pIn->cg2imu[_Z];


	// (_omega X _omega) X position + (alpha X position)
	_vectorTemp3[_X] = _vectorTemp1[_X] + _VectorTemp2[_X];
	_vectorTemp3[_Y] = _vectorTemp1[_Y] + _VectorTemp2[_Y];
	_vectorTemp3[_Z] = _vectorTemp1[_Z] + _VectorTemp2[_Z];

	// a_cg + (_omega X _omega) X position + (alpha X position)
	_vectorTemp1[_X] = _vectorTemp3[_X] + pIn->cg_accel[_X];
	_vectorTemp1[_Y] = _vectorTemp3[_Y] + pIn->cg_accel[_Y];
	_vectorTemp1[_Z] = _vectorTemp3[_Z] + pIn->cg_accel[_Z];

	// a_imu = _body2imu * a_cg
	pOut->accel[_X] = _body2imu[_X][_X] * _vectorTemp1[_X] + _body2imu[_X][_Y] * _vectorTemp1[_Y] + _body2imu[_X][_Z] * _vectorTemp1[_Z];
	pOut->accel[_Y] = _body2imu[_Y][_X] * _vectorTemp1[_X] + _body2imu[_Y][_Y] * _vectorTemp1[_Y] + _body2imu[_Y][_Z] * _vectorTemp1[_Z];
	pOut->accel[_Z] = _body2imu[_Z][_X] * _vectorTemp1[_X] + _body2imu[_Z][_Y] * _vectorTemp1[_Y] + _body2imu[_Z][_Z] * _vectorTemp1[_Z];

	// calculate velocity vector at IMU location (v_imu = _body2imu * (v_cg + (w X pos)) )
	// w X position
	_vectorTemp1[_X] = _omega[_X][_X] * pIn->cg2imu[_X] + _omega[_X][_Y] * pIn->cg2imu[_Y] + _omega[_X][_Z] * pIn->cg2imu[_Z];
	_vectorTemp1[_Y] = _omega[_Y][_X] * pIn->cg2imu[_X] + _omega[_Y][_Y] * pIn->cg2imu[_Y] + _omega[_Y][_Z] * pIn->cg2imu[_Z];
	_vectorTemp1[_Z] = _omega[_Z][_X] * pIn->cg2imu[_X] + _omega[_Z][_Y] * pIn->cg2imu[_Y] + _omega[_Z][_Z] * pIn->cg2imu[_Z];

	// v_cg + (w X position)
	_VectorTemp2[_X] = _vectorTemp1[_X] + pIn->cg_uvw[_X];
	_VectorTemp2[_Y] = _vectorTemp1[_Y] + pIn->cg_uvw[_Y];
	_VectorTemp2[_Z] = _vectorTemp1[_Z] + pIn->cg_uvw[_Z];

	// v_imu = _body2imu * (v_cg + (w X position))
	pOut->uvw[_X] = _body2imu[_X][_X] * _VectorTemp2[_X] + _body2imu[_X][_Y] * _VectorTemp2[_Y] + _body2imu[_X][_Z] * _VectorTemp2[_Z];
	pOut->uvw[_Y] = _body2imu[_Y][_X] * _VectorTemp2[_X] + _body2imu[_Y][_Y] * _VectorTemp2[_Y] + _body2imu[_Y][_Z] * _VectorTemp2[_Z];
	pOut->uvw[_Z] = _body2imu[_Z][_X] * _VectorTemp2[_X] + _body2imu[_Z][_Y] * _VectorTemp2[_Y] + _body2imu[_Z][_Z] * _VectorTemp2[_Z];

	// rotate IMU position in body coordinate system to TP coordinates
	_vectorTemp1[_X] = _body2earth[_X][_X] * pIn->cg2imu[_X] + _body2earth[_X][_Y] * pIn->cg2imu[_Y] + _body2earth[_X][_Z] * pIn->cg2imu[_Z];
	_vectorTemp1[_Y] = _body2earth[_Y][_X] * pIn->cg2imu[_X] + _body2earth[_Y][_Y] * pIn->cg2imu[_Y] + _body2earth[_Y][_Z] * pIn->cg2imu[_Z];
	_vectorTemp1[_Z] = _body2earth[_Z][_X] * pIn->cg2imu[_X] + _body2earth[_Z][_Y] * pIn->cg2imu[_Y] + _body2earth[_Z][_Z] * pIn->cg2imu[_Z];

	// transform position to ECEF coordinate system
	F_GEODETIC_TO_ECEF(_VectorTemp2, _vectorTemp1, _lat, _lon);

	// calculate IMU position in ECEF coordinate system
	pOut->ECEFpos[_X] = _VectorTemp2[_X] + pIn->cg_pos[_X];
	pOut->ECEFpos[_Y] = _VectorTemp2[_Y] + pIn->cg_pos[_Y];
	pOut->ECEFpos[_Z] = _VectorTemp2[_Z] + pIn->cg_pos[_Z];

	// calculate IMU position in geodetic coordinate system [ft]
	_vectorTemp1[_X] = pOut->ECEFpos[_X] * C_FOOT_TO_METER;
	_vectorTemp1[_Y] = pOut->ECEFpos[_Y] * C_FOOT_TO_METER;
	_vectorTemp1[_Z] = pOut->ECEFpos[_Z] * C_FOOT_TO_METER;
	F_ECEF_TO_GEODETIC(_vectorTemp1, pOut->LLHpos);
	pOut->LLHpos[_ALT] = pOut->LLHpos[_ALT] * C_METER_TO_FOOT;

	// calculate IMU angular velocity vector
	pOut->pqr[_X] = _body2imu[_X][_X] * pIn->cg_pqr[_X] + _body2imu[_X][_Y] * pIn->cg_pqr[_Y] + _body2imu[_X][_Z] * pIn->cg_pqr[_Z];
	pOut->pqr[_Y] = _body2imu[_Y][_X] * pIn->cg_pqr[_X] + _body2imu[_Y][_Y] * pIn->cg_pqr[_Y] + _body2imu[_Y][_Z] * pIn->cg_pqr[_Z];
	pOut->pqr[_Z] = _body2imu[_Z][_X] * pIn->cg_pqr[_X] + _body2imu[_Z][_Y] * pIn->cg_pqr[_Y] + _body2imu[_Z][_Z] * pIn->cg_pqr[_Z];

	// calculate IMU attitude (DCM matrix)
	_matTemp1[_X][_X] = _body2imu[_X][_X] * _earth2body[_X][_X] + _body2imu[_X][_Y] * _earth2body[_Y][_X] + _body2imu[_X][_Z] * _earth2body[_Z][_X];
	_matTemp1[_X][_Y] = _body2imu[_X][_X] * _earth2body[_X][_Y] + _body2imu[_X][_Y] * _earth2body[_Y][_Y] + _body2imu[_X][_Z] * _earth2body[_Z][_Y];
	_matTemp1[_X][_Z] = _body2imu[_X][_X] * _earth2body[_X][_Z] + _body2imu[_X][_Y] * _earth2body[_Y][_Z] + _body2imu[_X][_Z] * _earth2body[_Z][_Z];
	_matTemp1[_Y][_X] = _body2imu[_Y][_X] * _earth2body[_X][_X] + _body2imu[_Y][_Y] * _earth2body[_Y][_X] + _body2imu[_Y][_Z] * _earth2body[_Z][_X];
	_matTemp1[_Y][_Y] = _body2imu[_Y][_X] * _earth2body[_X][_Y] + _body2imu[_Y][_Y] * _earth2body[_Y][_Y] + _body2imu[_Y][_Z] * _earth2body[_Z][_Y];
	_matTemp1[_Y][_Z] = _body2imu[_Y][_X] * _earth2body[_X][_Z] + _body2imu[_Y][_Y] * _earth2body[_Y][_Z] + _body2imu[_Y][_Z] * _earth2body[_Z][_Z];
	_matTemp1[_Z][_X] = _body2imu[_Z][_X] * _earth2body[_X][_X] + _body2imu[_Z][_Y] * _earth2body[_Y][_X] + _body2imu[_Z][_Z] * _earth2body[_Z][_X];
	_matTemp1[_Z][_Y] = _body2imu[_Z][_X] * _earth2body[_X][_Y] + _body2imu[_Z][_Y] * _earth2body[_Y][_Y] + _body2imu[_Z][_Z] * _earth2body[_Z][_Y];
	_matTemp1[_Z][_Z] = _body2imu[_Z][_X] * _earth2body[_X][_Z] + _body2imu[_Z][_Y] * _earth2body[_Y][_Z] + _body2imu[_Z][_Z] * _earth2body[_Z][_Z];

	pOut->THETA[_PHI]   =  M_ATAN2(_matTemp1[_Y][_Z], _matTemp1[_Z][_Z]);
	pOut->THETA[_THETA] = -asin(_matTemp1[_X][_Z]);
	pOut->THETA[_PSI]   =  M_ATAN2(_matTemp1[_X][_Y], _matTemp1[_X][_X]);
}
Пример #3
0
CFLOAT
M_DECL_FUNC (__clog) (CFLOAT x)
{
  CFLOAT result;
  int rcls = fpclassify (__real__ x);
  int icls = fpclassify (__imag__ x);

  if (__glibc_unlikely (rcls == FP_ZERO && icls == FP_ZERO))
    {
      /* Real and imaginary part are 0.0.  */
      __imag__ result = signbit (__real__ x) ? (FLOAT) M_MLIT (M_PI) : 0;
      __imag__ result = M_COPYSIGN (__imag__ result, __imag__ x);
      /* Yes, the following line raises an exception.  */
      __real__ result = -1 / M_FABS (__real__ x);
    }
  else if (__glibc_likely (rcls != FP_NAN && icls != FP_NAN))
    {
      /* Neither real nor imaginary part is NaN.  */
      FLOAT absx = M_FABS (__real__ x), absy = M_FABS (__imag__ x);
      int scale = 0;

      if (absx < absy)
	{
	  FLOAT t = absx;
	  absx = absy;
	  absy = t;
	}

      if (absx > M_MAX / 2)
	{
	  scale = -1;
	  absx = M_SCALBN (absx, scale);
	  absy = (absy >= M_MIN * 2 ? M_SCALBN (absy, scale) : 0);
	}
      else if (absx < M_MIN && absy < M_MIN)
	{
	  scale = M_MANT_DIG;
	  absx = M_SCALBN (absx, scale);
	  absy = M_SCALBN (absy, scale);
	}

      if (absx == 1 && scale == 0)
	{
	  __real__ result = M_LOG1P (absy * absy) / 2;
	  math_check_force_underflow_nonneg (__real__ result);
	}
      else if (absx > 1 && absx < 2 && absy < 1 && scale == 0)
	{
	  FLOAT d2m1 = (absx - 1) * (absx + 1);
	  if (absy >= M_EPSILON)
	    d2m1 += absy * absy;
	  __real__ result = M_LOG1P (d2m1) / 2;
	}
      else if (absx < 1
	       && absx >= M_LIT (0.5)
	       && absy < M_EPSILON / 2
	       && scale == 0)
	{
	  FLOAT d2m1 = (absx - 1) * (absx + 1);
	  __real__ result = M_LOG1P (d2m1) / 2;
	}
      else if (absx < 1
	       && absx >= M_LIT (0.5)
	       && scale == 0
	       && absx * absx + absy * absy >= M_LIT (0.5))
	{
	  FLOAT d2m1 = M_SUF (__x2y2m1) (absx, absy);
	  __real__ result = M_LOG1P (d2m1) / 2;
	}
      else
	{
	  FLOAT d = M_HYPOT (absx, absy);
	  __real__ result = M_LOG (d) - scale * (FLOAT) M_MLIT (M_LN2);
	}

      __imag__ result = M_ATAN2 (__imag__ x, __real__ x);
    }
  else
    {
      __imag__ result = M_NAN;
      if (rcls == FP_INFINITE || icls == FP_INFINITE)
	/* Real or imaginary part is infinite.  */
	__real__ result = M_HUGE_VAL;
      else
	__real__ result = M_NAN;
    }

  return result;
}