CLatLongPoint CGnomonicProjection::InverseProjectPoint(const CXYPoint& p, const CWorld3DModel& worldModel)
/****************************************************/
{
	//Inverse Gnomonic Projection (from J. Snyder - Map Projections: A Working Manual)
	double const a            = worldModel.SemiMajorAxis();
	double const lambda0      = toRad(OriginMeridian());
	double const phi1         = toRad(OriginParallel());
	double const x            = p.X();
	double const y            = p.Y();

	double rho = Calculate_rho(p);
	double c = Calculate_c(p, worldModel);
	double phi = asin(cos(c)*sin(phi1)+(y*sin(c)*cos(phi1)/rho));
	
	double lambda = 0.0;
	if ((phi1<90.0)&&(phi1>-90.0))
	{
		lambda = lambda0 + atan(x*sin(c)/(rho*cos(phi1)*cos(c)-y*sin(phi1)*sin(c)));

	}
	else if (phi1==90)
	{
		lambda = lambda0 + atan(x/(-y));
	}
	else if (phi1==-90)
	{
		lambda = lambda0 + atan(x/y);
	}

	return CLatLongPoint(toDeg(phi), toDeg(lambda));
}
示例#2
0
/*
 * GGA Global Positioning System Fix Data. Time, Position and fix related data for a GPS receiver
 *
 *                                              11
 * 1         2       3 4        5 6 7  8   9  10 |  12 13  14
 * |         |       | |        | | |  |   |   | |   | |   |
 * hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx
 * 1) Time (UTC)
 * 2) Latitude
 * 3) N or S (North or South)
 * 4) Longitude
 * 5) E or W (East or West)
 * 6) GPS Quality Indicator,
 *    0 - fix not available,
 *    1 - GPS fix,
 *    2 - Differential GPS fix
 * 7)  Number of satellites in view, 00 - 12
 * 8)  Horizontal Dilution of precision
 * 9)  Antenna Altitude above/below mean-sea-level (geoid)
 * 10) Units of antenna altitude, meters
 * 11) Geoidal separation, the difference between the WGS-84 earth
 *     ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level below ellipsoid
 * 12) Units of geoidal separation, meters
 * 13) Age of differential GPS data, time in seconds since last SC104
 *     type 1 or 9 update, null field when DGPS is not used
 * 14) Differential reference station ID, 0000-1023
 */
static void parseGGA(un8 index, char *value)
{
	if (*value == 0)
		return;

	switch (index)
	{
	case GPS_GGA_QUALITY_INDICATOR:
		/* 1+: fix; 0: no fix */
		veVariantUn8(&local.fix, value[0] != '0');
		return;

	case GPS_GGA_LATITUDE:
		errno = 0;
		veVariantFloat(&local.latitude, toDeg((float)atof(value)));
		if (errno)
			veVariantInvalidate(&local.latitude);
		return;

	case GPS_GGA_LAT_NORTH_SOUTH:
		/* North is positive, south is negative */
		if (value[0] == 'S')
			local.latitude.value.Float *= -1;
		return;

	case GPS_GGA_LONGITUDE:
		errno = 0;
		veVariantFloat(&local.longitude, toDeg((float)atof(value)));
		if (errno)
			veVariantInvalidate(&local.longitude);
		return;

	case GPS_GGA_LONG_EAST_WEST:
		/* East is positive, west is negative */
		if (value[0] == 'W')
			local.longitude.value.Float *= -1;
		return;

	case GPS_GGA_ALTITUDE:
		errno = 0;
		veVariantFloat(&local.altitude, (float)atof(value));
		if (errno)
			veVariantInvalidate(&local.altitude);
		return;

	case GPS_GGA_NR_OF_SATELITES:
		errno = 0;
		veVariantUn8(&local.nrOfSats, (un8)atol(value));
		if (errno)
			veVariantInvalidate(&local.nrOfSats);
		return;
	}
}
示例#3
0
bool DistVincenty(double lat1, double lon1, double lat2, double lon2, double *dist, double *fwdAz, double *revAz){

    InverseResult result;
    LLPoint pt1, pt2;
    pt1.latitude=toRad(lat1);
    pt1.longitude=toRad(lon1);
    pt2.latitude=toRad(lat2);
    pt2.longitude=toRad(lon2);

    bool test=DistVincenty( pt1,  pt2, & result);
    *dist = mtoNM(result.distance);
    *fwdAz = toDeg(result.azimuth);
    *revAz = toDeg(result.azimuth);
    return test;
}
示例#4
0
/**
 * Calculates destination point given start point lat/long, bearing & distance,
 * using Vincenty inverse formula for ellipsoids
 *
 * ->   double lat1, lon1: first point in decimal degrees
 * ->   double brng: initial bearing in decimal degrees
 * ->   double dist: distance along bearing in nautical miles
 * <-   double lat2, lat2 final point in decimal degrees
 * <-   double final bearing in decimal degrees
 */
void DestVincenty(double lat1, double lon1, double brng, double distNM, double* lat2, double* lon2, double* revAz) {

   LLPoint pt;
   pt.latitude=toRad(lat1);
   pt.longitude=toRad(lon1);
   double distm=NmToMeters(distNM);
   double brngrad=toRad(brng);
   double revAzrad;
   LLPoint Result_dest=DestVincenty(pt,  brngrad,  distm, &revAzrad );


    *lat2=toDeg(Result_dest.latitude);
    *lon2=toDeg(Result_dest.longitude);
    *revAz =toDeg(revAzrad);  // final bearing, if required
}
示例#5
0
float TS_Util::bind(std::string op, float a)
{
	if (op == "sin") return (float) sin(a);
	if (op == "cos") return (float) cos(a);
	if (op == "tan") return (float) tan(a);
	if (op == "csc") return safeDiv2(1.0f, (float) sin(a));
	if (op == "sec") return safeDiv2(1.0f, (float) cos(a));
	if (op == "cot") return safeDiv2(1.0f, (float) tan(a));
	if (op == "asin") return (float) asin(a);
	if (op == "acos") return (float) acos(a);
	if (op == "atan") return (float) atan(a);
	if (op == "rad") return (float) toRad(a);
	if (op == "deg") return (float) toDeg(a);
	if (op == "ln") return (float) log(a);
	if (op == "log") return (float) log10(a);
	if (op == "exp") return (float) exp(a);
	if (op == "abs") return (float) fabs(a);
	if (op == "sgn") return sgn(a);
	if (op == "neg") return -a;
	if (op == "not") return !a;
	if (op == "bnot") return (float) ~((int) a);
	if (op == "int") return (float) ((int) a);
	if (op == "floor") return (float) ((int) a);
	if (op == "ciel") return (float) ((int) a + 1);
	if (op == "round") return (float) ((int) (a + 0.5f));
	if (op == "rnd") return !a ? rnd() : rndEx(0, a);
	if (op == "sqrt") return (float) sqrt(a);
	if (op == "fact") return (float) fact((int) a);
	throw Exception("unary operator not found");
}
示例#6
0
void renderPlayer(Display *gDisplay, Assets *gAssets, ControlState *gControlState) {
	int cx, cy;
	double rotate;

	cy = gAssets->rPlayer.y + P_IMAGE_H / 2;
	cx = gAssets->rPlayer.x + P_IMAGE_W / 2;
	rotate = toDeg(atan2(gControlState->mouseY - cy, gControlState->mouseX - cx));

	SDL_RenderCopyEx(gDisplay->renderer, gAssets->tPlayer, NULL, &gAssets->rPlayer, rotate, NULL, SDL_FLIP_NONE);
}
示例#7
0
bool destRhumb(double lat1, double lon1, double brng, double dist, double* lat2, double* lon2) {
  lat1=toRad(lat1);
  lon1=toRad(lon1);
  double d=NMtorad(dist);
  double tc=toRad(brng);
  double lat= lat1+d*cos(tc);
    if (std::abs(lat) > M_PI/2) return false;//"d too large. You can't go this far along this rhumb line!"
    double q;
    if (std::abs(lat-lat1) < sqrt(Tol())){
     q=cos(lat1);
  } else {
     double dphi=log(tan(lat/2+M_PI/4)/tan(lat1/2+M_PI/4));
     q= (lat-lat1)/dphi;
  }
    double dlon=-d*sin(tc)/q;
    *lon2=toDeg(mod(lon1+dlon+M_PI,2*M_PI)-M_PI);
    *lat2=toDeg(lat);
  return true;
}
示例#8
0
int calculateBearing(float lon1, float lat1, float lon2, float lat2) {
	// bearing calc, feeded in radian, output degrees
	float a;
	a = atan2(sin(lon2 - lon1)*cos(lat2), cos(lat1)*sin(lat2) - sin(lat1)*cos(lat2)*cos(lon2 - lon1));
	a = toDeg(a);

	if (a < 0) a = 360 + a;
	a = 360-a;
	return (int)round(a);
}
示例#9
0
文件: main.c 项目: tom91136/TouhouC
void tracing(Bullet *bullet, World *world) {

	//bullet->velocity *= (1.0 - 0.002);

	double deltaX = (double) world->player.x - bullet->x;
	double deltaY = (double) bullet->y - world->player.y;
	double thetaCorrection = toDeg(atan2(deltaY, deltaX));

	bullet->theta = thetaCorrection;

}
示例#10
0
void global_aimming_angle(float *yaw,float *pitch)
{
	float diffx=0;
	float diffy=0;
	float diffz=0;
	float diffxy=0;

	diffx 	= target.x - gps.x;
	diffy 	= target.y - gps.y;
	diffz 	= target.z - gps.z;
	/*vector in global frame*/
	vector_x = diffx;
	vector_y = diffy;
	vector_z = diffz;

	//printf("%f,%f,%f\r\n",vector_x,vector_y,vector_z);

	diffxy 	= sqrt(pow2(diffx)+pow2(diffy));
	*yaw 	= toDeg(atan2f(diffx,diffy));
	*pitch 	= toDeg(atan2f(diffz,diffxy));  
}
示例#11
0
void body_aimming_angle()
{
	global_aimming_angle(&(global_yaw),&(global_pitch));
	
	
	/*transform global vetor form global to body*/
	
	vector_x_fc = vector_y;
	vector_y_fc = -vector_x;
	vector_z_fc = vector_z;

	//printf("%f,%f,%f\r\n",vector_x_fc,vector_y_fc,vector_z_fc);

	/*turn body by yaw,pitch,roll*/
	vector_body_x = Mq11*vector_x_fc + Mq12*vector_y_fc + Mq13*vector_z_fc;
	vector_body_y = Mq21*vector_x_fc + Mq22*vector_y_fc + Mq23*vector_z_fc;
	vector_body_z = Mq31*vector_x_fc + Mq32*vector_y_fc + Mq33*vector_z_fc;

	//printf("%f,%f,%f\r\n",vector_body_x,vector_body_y,vector_body_z);

	//printf("global_yaw,%f,global_pitch,%f\r\n",global_yaw,global_pitch);

	body_yaw   = (atan2f(vector_body_y,vector_body_x));
	body_pitch = toDeg(atan2f(-vector_body_z,(arm_cos_f32(body_yaw) * vector_body_x + arm_sin_f32(body_yaw) * vector_body_y)));
	body_yaw   = toDeg(body_yaw);

	if(body_pitch > 90.0)
	{
		body_yaw  = body_yaw + 180.0;
		body_pitch= 180.0 - body_pitch;
	}
/*	else if(body_pitch < 0.0)
	{
		body_yaw  = body_yaw + 180.0;
		body_pitch= -body_pitch;
	}
*/
	//printf("body_yaw,%f,body_pitch,%f\r\n",body_yaw,body_pitch);

}
示例#12
0
/**
 * Calculates rhumb line distance between two points specified by latitude/longitude
 * http://williams.best.vwh.net/avform.htm#Rhumb
 * ->   double lat1, lon1: first point in decimal degrees
 * ->   double lat2, lon2: second point in decimal degrees
 * <-   double dist: distance along bearing in nautical miles
 * <-   double bearing in decimal degrees
 * As stated in the introduction, North latitudes and West longitudes are treated as positive,
 * and South latitudes and East longitudes negative. It's easier to go with the flow, but if
 * you prefer another convention you can change the signs in the formulae.
*/
void distRhumb(double lat1,double lon1, double lat2, double lon2, double *distance, double *brng){
  lat1=toRad(lat1);
  lat2=toRad(lat2);
  lon1=toRad(lon1);
  lon2=toRad(lon2);

  double dlon_W=mod(lon2-lon1,(2*M_PI));
  double dlon_E=mod(lon1-lon2,(2*M_PI));
  double dphi=log(tan(lat2/2+M_PI/4)/tan(lat1/2+M_PI/4));
  double q=0;
  if (std::abs(lat2-lat1) < sqrt(Tol())){
     q=cos(lat1);
  } else {
     q= (lat2-lat1)/dphi;
  }
  if (dlon_W < dlon_E){// Westerly rhumb line is the shortest
      *brng=toDeg(mod(atan2(-dlon_W,dphi),(2*M_PI)));
      *distance= radtoNM(sqrt(sqr(q)*(sqr(dlon_W)) + sqr(lat2-lat1)));
  } else{
      *brng=toDeg(mod(atan2(dlon_E,dphi),(2*M_PI)));
      *distance= radtoNM(sqrt(sqr(q)*(sqr(dlon_E)) + sqr(lat2-lat1)));
      }
}
示例#13
0
int calculateElevation(float lon1, float lat1, float lon2, float lat2, int alt) {
	// feeded in radian, output in degrees
	float a, el, c, d, dLat, dLon;
	//calculating distance between uav & home	
	dLat = (lat2 - lat1);
	dLon = (lon2 - lon1);
	a = sin(dLat / 2) * sin(dLat / 2) + sin(dLon / 2) * sin(dLon / 2) * cos(lat1) * cos(lat2);
	c = 2 * asin(sqrt(a));
	d = (R * c);
	uavDistanceToHome = d;
	el = atan((float)alt / (10 * d));// in radian
	el = toDeg(el); // in degree
	return (int)round(el);
}
示例#14
0
/*====================================================================================================*/
void SysTick_Handler( void )
{
  u16 MOTOR[4] = {0};
  s16 Pitch = 0, Roll = 0, Yaw = 0;

  static u16 SysTick_Cnt = 0;
  static s16 *FIFO_X, *FIFO_Y, *FIFO_Z;
  static s16 FIFO_ACC[3][16] = {0}, FIFO_GYR[3][16] = {0}/*, FIFO_MAG[3][16] = {0}*/;
  static u32 Correction_Time = 0;

  /* Time Count */
  if(SysTick_Cnt == SampleRateFreg) {
    SysTick_Cnt = 0;
    Time_Sec++;
    if(Time_Sec == 60) {	// 0~59
      Time_Sec = 0;
      Time_Min++;
      if(Time_Sec == 60)
        Time_Min = 0;
    }
  }
  SysTick_Cnt++;

  /* 500Hz, Read Accelerometer, Gyroscope, Magnetometer */
  Sensor_Read(SampleRateFreg);

  /* Offset */
  Acc.X -= Acc.OffsetX;
  Acc.Y -= Acc.OffsetY;
  Acc.Z -= Acc.OffsetZ;
  Gyr.X -= Gyr.OffsetX;
  Gyr.Y -= Gyr.OffsetY;
  Gyr.Z -= Gyr.OffsetZ;

  #define MAFIFO_SIZE 250
  switch(SEN_STATE) {

    /************************** CorrectSelect ***********************************/
    case SEN_CORR:
//      SEN_STATE = (KEY == KEY_ON) ? SEN_GYR : SEN_NUMQ;
      SEN_STATE = SEN_GYR;
      break;

    /************************** CorrectGyr **************************************/
    case SEN_GYR:
      switch((u16)(Correction_Time/SampleRateFreg)) {
        case 0:   // 分配記憶體給 MaveAve 使用
          FIFO_X = (s16*)malloc(MAFIFO_SIZE*sizeof(s16));
          FIFO_Y = (s16*)malloc(MAFIFO_SIZE*sizeof(s16));
          FIFO_Z = (s16*)malloc(MAFIFO_SIZE*sizeof(s16));
          memset(FIFO_X, 0, MAFIFO_SIZE*sizeof(s16));
          memset(FIFO_Y, 0, MAFIFO_SIZE*sizeof(s16));
          memset(FIFO_Z, 0, MAFIFO_SIZE*sizeof(s16));
          Correction_Time = SampleRateFreg;
          break;
        case 1:   // 等待 FIFO 填滿靜態資料
          /* 移動平均 Simple Moving Average */
          Gyr.X = (s16)MoveAve_SMA(Gyr.X, FIFO_X, MAFIFO_SIZE);
          Gyr.Y = (s16)MoveAve_SMA(Gyr.Y, FIFO_Y, MAFIFO_SIZE);
          Gyr.Z = (s16)MoveAve_SMA(Gyr.Z, FIFO_Z, MAFIFO_SIZE);
          Correction_Time++;
          break;
        case 2:   // 釋放記憶體 & 計算陀螺儀偏移量
          free(FIFO_X);
          free(FIFO_Y);
          free(FIFO_Z);
          Gyr.OffsetX += (Gyr.X - GYR_X_OFFSET);  // 角速度為 0dps
          Gyr.OffsetY += (Gyr.Y - GYR_Y_OFFSET);  // 角速度為 0dps
          Gyr.OffsetZ += (Gyr.Z - GYR_Z_OFFSET);  // 角速度為 0dps
          Correction_Time = 0;
          SEN_STATE = SEN_ACC;
          break;
      }
      break;

    /************************** CorrectAcc **************************************/
    case SEN_ACC:
      switch((u16)(Correction_Time/SampleRateFreg)) {
        case 0:   // 分配記憶體給 MaveAve 使用
          FIFO_X = (s16*)malloc(MAFIFO_SIZE*sizeof(s16));
          FIFO_Y = (s16*)malloc(MAFIFO_SIZE*sizeof(s16));
          FIFO_Z = (s16*)malloc(MAFIFO_SIZE*sizeof(s16));
          memset(FIFO_X, 0, MAFIFO_SIZE*sizeof(s16));
          memset(FIFO_Y, 0, MAFIFO_SIZE*sizeof(s16));
          memset(FIFO_Z, 0, MAFIFO_SIZE*sizeof(s16));
          Correction_Time = SampleRateFreg;
          break;
        case 1:   // 等待 FIFO 填滿靜態資料
          /* 移動平均 Simple Moving Average */
          Acc.X = (s16)MoveAve_SMA(Acc.X, FIFO_X, MAFIFO_SIZE);
          Acc.Y = (s16)MoveAve_SMA(Acc.Y, FIFO_Y, MAFIFO_SIZE);
          Acc.Z = (s16)MoveAve_SMA(Acc.Z, FIFO_Z, MAFIFO_SIZE);
          Correction_Time++;
          break;
        case 2:   // 釋放記憶體 & 計算加速度計偏移量
          free(FIFO_X);
          free(FIFO_Y);
          free(FIFO_Z);
          Acc.OffsetX += (Acc.X - ACC_X_OFFSET);  // 重力加速度為 0g
          Acc.OffsetY += (Acc.Y - ACC_Y_OFFSET);  // 重力加速度為 0g
          Acc.OffsetZ += (Acc.Z - ACC_Z_OFFSET);  // 重力加速度為 1g
          Correction_Time = 0;

//          SEN_STATE = SEN_MAG;
          SEN_STATE = SEN_NUMQ;
          break;
      }
      break;

    /************************** CorrectMag **************************************/
    case SEN_MAG:
      SEN_STATE = SEN_NUMQ;
      break;

    /************************** Quaternion **************************************/
    case SEN_NUMQ:
      switch((u16)(Correction_Time/SampleRateFreg)) {
        case 0:   // 等待 FIFO 填滿靜態資料
          /* 加權移動平均法 Weighted Moving Average */
          Acc.X = (s16)MoveAve_WMA(Acc.X, FIFO_ACC[0], 16);
          Acc.Y = (s16)MoveAve_WMA(Acc.Y, FIFO_ACC[1], 16);
          Acc.Z = (s16)MoveAve_WMA(Acc.Z, FIFO_ACC[2], 16);
          Gyr.X = (s16)MoveAve_WMA(Gyr.X, FIFO_GYR[0], 16);
          Gyr.Y = (s16)MoveAve_WMA(Gyr.Y, FIFO_GYR[1], 16);
          Gyr.Z = (s16)MoveAve_WMA(Gyr.Z, FIFO_GYR[2], 16);

          Correction_Time++;
          break;
        case 1:

          /* 加權移動平均法 Weighted Moving Average */
          Acc.X = (s16)MoveAve_WMA(Acc.X, FIFO_ACC[0], 16);
          Acc.Y = (s16)MoveAve_WMA(Acc.Y, FIFO_ACC[1], 16);
          Acc.Z = (s16)MoveAve_WMA(Acc.Z, FIFO_ACC[2], 16);
          Gyr.X = (s16)MoveAve_WMA(Gyr.X, FIFO_GYR[0], 16);
          Gyr.Y = (s16)MoveAve_WMA(Gyr.Y, FIFO_GYR[1], 16);
          Gyr.Z = (s16)MoveAve_WMA(Gyr.Z, FIFO_GYR[2], 16);

          /* To Physical */
          Acc.TrueX  = Acc.X*MPU9250A_4g;       // g/LSB
          Acc.TrueY  = Acc.Y*MPU9250A_4g;       // g/LSB
          Acc.TrueZ  = Acc.Z*MPU9250A_4g;       // g/LSB
          Gyr.TrueX  = Gyr.X*MPU9250G_2000dps;  // dps/LSB
          Gyr.TrueY  = Gyr.Y*MPU9250G_2000dps;  // dps/LSB
          Gyr.TrueZ  = Gyr.Z*MPU9250G_2000dps;  // dps/LSB

          AngE.Pitch = toDeg(atan2f(Acc.TrueY, Acc.TrueZ));
          AngE.Roll  = toDeg(-asinf(Acc.TrueX));
//          AngE.Yaw   = toDeg(atan2f(Ellipse[3], Ellipse[4]))+180.0f;

          Quaternion_ToNumQ(&NumQ, &AngE);

          Correction_Time = 0;
          SEN_STATE = SEN_ALG;
          break;
      }
      break;

    /************************** Algorithm ***************************************/
    case SEN_ALG:

      /* 加權移動平均法 Weighted Moving Average */
      Acc.X = (s16)MoveAve_WMA(Acc.X, FIFO_ACC[0], 8);
      Acc.Y = (s16)MoveAve_WMA(Acc.Y, FIFO_ACC[1], 8);
      Acc.Z = (s16)MoveAve_WMA(Acc.Z, FIFO_ACC[2], 8);
      Gyr.X = (s16)MoveAve_WMA(Gyr.X, FIFO_GYR[0], 8);
      Gyr.Y = (s16)MoveAve_WMA(Gyr.Y, FIFO_GYR[1], 8);
      Gyr.Z = (s16)MoveAve_WMA(Gyr.Z, FIFO_GYR[2], 8);

      /* To Physical */
      Acc.TrueX = Acc.X*MPU9250A_4g;       // g/LSB
      Acc.TrueY = Acc.Y*MPU9250A_4g;       // g/LSB
      Acc.TrueZ = Acc.Z*MPU9250A_4g;       // g/LSB
      Gyr.TrueX = Gyr.X*MPU9250G_2000dps;  // dps/LSB
      Gyr.TrueY = Gyr.Y*MPU9250G_2000dps;  // dps/LSB
      Gyr.TrueZ = Gyr.Z*MPU9250G_2000dps;  // dps/LSB

      /* Get Attitude */
      AHRS_Update();

      if((KEY_LL == 1) && (KEY_RR == 1))  {	PID_Roll.Kp += 0.001f;	PID_Pitch.Kp += 0.001f;  }
      if((KEY_LL == 1) && (KEY_RP == 1))  {	PID_Roll.Kp -= 0.001f;	PID_Pitch.Kp -= 0.001f;  }
//      if((KEY_LL == 1) && (KEY_RR == 1))  {	PID_Roll.Ki += 0.0001f;	PID_Pitch.Ki += 0.0001f; }
//      if((KEY_LL == 1) && (KEY_RR == 1))  {	PID_Roll.Ki -= 0.0001f;	PID_Pitch.Ki -= 0.0001f; }
      if((KEY_LR == 1) && (KEY_RR == 1))  {	PID_Roll.Kd += 0.0001f;	PID_Pitch.Kd += 0.0001f; }
      if((KEY_LR == 1) && (KEY_RP == 1))  {	PID_Roll.Kd -= 0.0001f;	PID_Pitch.Kd -= 0.0001f; }
//      if((KEY_RR == 1) && (KEY_RR == 1))  {	PID_Yaw.Kd += 0.0001f; }
//      if((KEY_RR == 1) && (KEY_RR == 1))  {	PID_Yaw.Kd -= 0.0001f; }

      /* Get ZeroErr */
      PID_Pitch.ZeroErr = (fp32)((s16)EXP_PITCH/4.5f);
      PID_Roll.ZeroErr  = (fp32)((s16)EXP_ROLL/4.5f);
      PID_Yaw.ZeroErr   = (fp32)((s16)EXP_YAW)+180.0f;

      /* PID */
      Roll  = (s16)PID_AHRS_Cal(&PID_Roll,  AngE.Roll,  Gyr.TrueX);
      Pitch = (s16)PID_AHRS_Cal(&PID_Pitch, AngE.Pitch, Gyr.TrueY);
      Yaw   = (s16)(PID_Yaw.Kd*Gyr.TrueZ);

//      Roll  = 0;
//      Pitch = 0;
      Yaw   = 0;

      /* Motor Ctrl */
      MOTOR[0] = BasicThr + Pitch + Roll + Yaw;
      MOTOR[1] = BasicThr - Pitch + Roll - Yaw;
      MOTOR[2] = BasicThr - Pitch - Roll + Yaw;
      MOTOR[3] = BasicThr + Pitch - Roll - Yaw;

      /* Check Connection */
      #define NoSignal 1  // 1 sec
      if(KEY_RL == 1) {
        // Close Thr
        PID_Pitch.SumErr = 0.0f;
        PID_Roll.SumErr  = 0.0f;
        PID_Yaw.SumErr   = 0.0f;
        Ctrl_MotorTHR(MOTOR_THR_MIN, MOTOR_THR_MIN, MOTOR_THR_MIN, MOTOR_THR_MIN);
      }
      else if(((Time_Sec-RF_RecvData.Time.Sec)>NoSignal) || ((Time_Sec-RF_RecvData.Time.Sec)<-NoSignal))
        Ctrl_MotorTHR(MOTOR_THR_MIN, MOTOR_THR_MIN, MOTOR_THR_MIN, MOTOR_THR_MIN);
      else {
        // Thr Ctrl
        Ctrl_MotorTHR(MOTOR[0], MOTOR[1], MOTOR[2], MOTOR[3]);
      }
      break;

    /************************** Error *******************************************/
    default:
      while(1);
  }
}
void correct_sensor() 
{	/* IMU calibration */

#define MovegAveFIFO_Size 250

	switch (SensorMode) {

	/************************** Mode_CorrectGyr **************************************/
	case Mode_GyrCorrect:
		/* Simple Moving Average */
		Gyr.X = (s16)MoveAve_SMA(Gyr.X, GYR_FIFO[0], MovegAveFIFO_Size);
		Gyr.Y = (s16)MoveAve_SMA(Gyr.Y, GYR_FIFO[1], MovegAveFIFO_Size);
		Gyr.Z = (s16)MoveAve_SMA(Gyr.Z, GYR_FIFO[2], MovegAveFIFO_Size);
		//將上述讀取出來的陀螺儀數值作平均

		Correction_Time++;  // 等待 FIFO 填滿空值 or 填滿靜態資料

		if (Correction_Time == SampleRateFreg) {
			Gyr.OffsetX += (Gyr.X - GYR_X_OFFSET);  // 角速度為 0dps
			Gyr.OffsetY += (Gyr.Y - GYR_Y_OFFSET);  // 角速度為 0dps
			Gyr.OffsetZ += (Gyr.Z - GYR_Z_OFFSET);  // 角速度為 0dps

			Correction_Time = 0;
			SensorMode = Mode_AccCorrect;
		}

		break;

	/************************** Mode_CorrectAcc **************************************/
	case Mode_AccCorrect:
		/* Simple Moving Average */
		Acc.X = (s16)MoveAve_SMA(Acc.X, ACC_FIFO[0], MovegAveFIFO_Size);
		Acc.Y = (s16)MoveAve_SMA(Acc.Y, ACC_FIFO[1], MovegAveFIFO_Size);
		Acc.Z = (s16)MoveAve_SMA(Acc.Z, ACC_FIFO[2], MovegAveFIFO_Size);
		//將上述讀取出來的加速規數值作平均

		Correction_Time++;  // 等待 FIFO 填滿空值 or 填滿靜態資料

		if (Correction_Time == SampleRateFreg) {
			Acc.OffsetX += (Acc.X - ACC_X_OFFSET);  // 重力加速度為 0g
			Acc.OffsetY += (Acc.Y - ACC_Y_OFFSET);  // 重力加速度為 0g
			Acc.OffsetZ += (Acc.Z - ACC_Z_OFFSET);  // 重力加速度為 1g

			Correction_Time = 0;
			SensorMode = Mode_Quaternion; // Mode_MagCorrect;
		}

		break;

	/************************** Algorithm Mode **************************************/
	case Mode_Quaternion:
		/* To Physical */
		/* 將數值轉換為現實世界中單位 */
		Acc.TrueX = Acc.X * MPU9150A_4g;      // g/LSB
		Acc.TrueY = Acc.Y * MPU9150A_4g;      // g/LSB
		Acc.TrueZ = Acc.Z * MPU9150A_4g;      // g/LSB
		Gyr.TrueX = Gyr.X * MPU9150G_2000dps; // dps/LSB
		Gyr.TrueY = Gyr.Y * MPU9150G_2000dps; // dps/LSB
		Gyr.TrueZ = Gyr.Z * MPU9150G_2000dps; // dps/LSB

#if USE_MPU9150_and_MS5611
		Mag.TrueX = Mag.X * MPU9150M_1200uT;  // uT/LSB
		Mag.TrueY = Mag.Y * MPU9150M_1200uT;  // uT/LSB
		Mag.TrueZ = Mag.Z * MPU9150M_1200uT;  // uT/LSB
		Temp.TrueT = Temp.T * MPU9150T_85degC; // degC/LSB
#endif
		AngE.Pitch = toDeg(atan2f(Acc.TrueY, Acc.TrueZ));
		AngE.Roll  = toDeg(-asinf(Acc.TrueX));
		AngE.Yaw   = toDeg(atan2f(Mag.TrueX, Mag.TrueY)) + 180.0f;
		Quaternion_ToNumQ(&NumQ, &AngE);

		SensorMode = Mode_Algorithm;
		break;
	default:
		serial.printf("correct_sensor() [WARNING] unhandled case %d", SensorMode);
		break;
	}

}
示例#16
0
文件: Math.hpp 项目: questor/git-ws
	/// @brief Calculates radians needed to turn towards a point.
	/// @param mX1 First point X.
	/// @param mY1 First point Y.
	/// @param mX2 Second point X.
	/// @param mY2 Second point Y.
	/// @return Returns the needed radians.
	template<typename T1, typename T2, typename T3, typename T4> inline constexpr Common<T1, T2, T3, T4> getDegTowards(const T1& mX1, const T2& mY1, const T3& mX2, const T4& mY2) noexcept
	{
		return toDeg(getRadTowards(mX1, mY1, mX2, mY2));
	}
示例#17
0
文件: Math.hpp 项目: questor/git-ws
	/// @brief Gets a rotated angle in radians.
	/// @details Example use: a character slowly aiming towards the mouse position.
	/// @param mStart Angle to start from.
	/// @param mEnd Target angle.
	/// @param mSpeed Rotation speed.
	/// @return Returns the rotated angle in radians.
	template<typename T1, typename T2, typename T3> inline constexpr auto getRotatedRad(const T1& mStart, const T2& mEnd, const T3& mSpeed) noexcept
	{
		return getRotatedDeg(toDeg(mStart), toDeg(mEnd), mSpeed);
	}
void correct_sensor()
{
	float Ellipse[5] = {0};
#define MovegAveFIFO_Size 250

	switch (SensorMode) {

	/************************** Mode_CorrectGyr **************************************/
	case Mode_GyrCorrect:
		/* Simple Moving Average */
		Gyr.X = (s16)MoveAve_SMA(Gyr.X, GYR_FIFO[0], MovegAveFIFO_Size);
		Gyr.Y = (s16)MoveAve_SMA(Gyr.Y, GYR_FIFO[1], MovegAveFIFO_Size);
		Gyr.Z = (s16)MoveAve_SMA(Gyr.Z, GYR_FIFO[2], MovegAveFIFO_Size);

		Correction_Time++;  // 等待 FIFO 填滿空值 or 填滿靜態資料

		if (Correction_Time == SampleRateFreg) {
			Gyr.OffsetX += (Gyr.X - GYR_X_OFFSET);  // 角速度為 0dps
			Gyr.OffsetY += (Gyr.Y - GYR_Y_OFFSET);  // 角速度為 0dps
			Gyr.OffsetZ += (Gyr.Z - GYR_Z_OFFSET);  // 角速度為 0dps

			Correction_Time = 0;
			SensorMode = Mode_AccCorrect;
		}

		break;

	/************************** Mode_CorrectAcc **************************************/
	case Mode_AccCorrect:
		/* Simple Moving Average */
		Acc.X = (s16)MoveAve_SMA(Acc.X, ACC_FIFO[0], MovegAveFIFO_Size);
		Acc.Y = (s16)MoveAve_SMA(Acc.Y, ACC_FIFO[1], MovegAveFIFO_Size);
		Acc.Z = (s16)MoveAve_SMA(Acc.Z, ACC_FIFO[2], MovegAveFIFO_Size);

		Correction_Time++;  // 等待 FIFO 填滿空值 or 填滿靜態資料

		if (Correction_Time == SampleRateFreg) {
			Acc.OffsetX += (Acc.X - ACC_X_OFFSET);  // 重力加速度為 0g
			Acc.OffsetY += (Acc.Y - ACC_Y_OFFSET);  // 重力加速度為 0g
			Acc.OffsetZ += (Acc.Z - ACC_Z_OFFSET);  // 重力加速度為 1g

			Correction_Time = 0;
			SensorMode = Mode_Quaternion; // Mode_MagCorrect;
		}

		break;

		/************************** Mode_CorrectMag **************************************/
#define MagCorrect_Ave    100
#define MagCorrect_Delay  600   // DelayTime : SampleRate * 600

	case Mode_MagCorrect:
		Correction_Time++;

		switch ((u16)(Correction_Time / MagCorrect_Delay)) {
		case 0:

			MagDataX[0] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[0] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 1:

			MagDataX[1] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[1] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 2:

			MagDataX[2] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[2] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 3:

			MagDataX[3] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[3] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 4:

			MagDataX[4] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[4] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 5:

			MagDataX[5] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[5] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 6:

			MagDataX[6] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[6] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		case 7:

			MagDataX[7] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
			MagDataY[7] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
			break;

		default:

			EllipseFitting(Ellipse, MagDataX, MagDataY, 8);
			Mag.EllipseSita = Ellipse[0];
			Mag.EllipseX0   = Ellipse[1];
			Mag.EllipseY0   = Ellipse[2];
			Mag.EllipseA    = Ellipse[3];
			Mag.EllipseB    = Ellipse[4];

			Correction_Time = 0;
			SensorMode = Mode_Quaternion;
			break;
		}

		break;

	/************************** Algorithm Mode **************************************/
	case Mode_Quaternion:
		/* To Physical */
		Acc.TrueX = Acc.X * MPU9150A_4g;      // g/LSB
		Acc.TrueY = Acc.Y * MPU9150A_4g;      // g/LSB
		Acc.TrueZ = Acc.Z * MPU9150A_4g;      // g/LSB
		Gyr.TrueX = Gyr.X * MPU9150G_2000dps; // dps/LSB
		Gyr.TrueY = Gyr.Y * MPU9150G_2000dps; // dps/LSB
		Gyr.TrueZ = Gyr.Z * MPU9150G_2000dps; // dps/LSB
		Mag.TrueX = Mag.X * MPU9150M_1200uT;  // uT/LSB
		Mag.TrueY = Mag.Y * MPU9150M_1200uT;  // uT/LSB
		Mag.TrueZ = Mag.Z * MPU9150M_1200uT;  // uT/LSB
		Temp.TrueT = Temp.T * MPU9150T_85degC; // degC/LSB

		Ellipse[3] = (Mag.X * arm_cos_f32(Mag.EllipseSita) + Mag.Y * arm_sin_f32(Mag.EllipseSita)) / Mag.EllipseB;
		Ellipse[4] = (-Mag.X * arm_sin_f32(Mag.EllipseSita) + Mag.Y * arm_cos_f32(Mag.EllipseSita)) / Mag.EllipseA;

		AngE.Pitch = toDeg(atan2f(Acc.TrueY, Acc.TrueZ));
		AngE.Roll  = toDeg(-asinf(Acc.TrueX));
		AngE.Yaw   = toDeg(atan2f(Ellipse[3], Ellipse[4])) + 180.0f;

		Quaternion_ToNumQ(&NumQ, &AngE);

		SensorMode = Mode_Algorithm;
		break;
	}

}
示例#19
0
/*=====================================================================================================*/
void SysTick_Handler( void )
{
    s16 IMU_Buf[10] = {0};

    static s16 *FIFO_X, *FIFO_Y, *FIFO_Z;
    static s16 FIFO_ACC[3][16] = {0}, FIFO_GYR[3][16] = {0}, FIFO_MAG[3][16] = {0};
    static u32 Correction_Time = 0;

    /* 500Hz, Read Accelerometer, Gyroscope, Magnetometer */
    MPU9150_Read(IMU_Buf);

    /* 100Hz, Read Barometer */
    if((SysTick_Cnt%(SampleRateFreg/100)) == 0)
        MS5611_Read(&Baro, MS5611_D1_OSR_4096);

    /* Offset */
    Acc.X  = IMU_Buf[0] - Acc.OffsetX;
    Acc.Y  = IMU_Buf[1] - Acc.OffsetY;
    Acc.Z  = IMU_Buf[2] - Acc.OffsetZ;
    Gyr.X  = IMU_Buf[3] - Gyr.OffsetX;
    Gyr.Y  = IMU_Buf[4] - Gyr.OffsetY;
    Gyr.Z  = IMU_Buf[5] - Gyr.OffsetZ;
    Mag.X  = IMU_Buf[6] * Mag.AdjustX;
    Mag.Y  = IMU_Buf[7] * Mag.AdjustY;
    Mag.Z  = IMU_Buf[8] * Mag.AdjustZ;
    Temp.T = IMU_Buf[9];

#define MAFIFO_SIZE 250
    switch(SEN_STATE) {

    /************************** CorrectSelect ***********************************/
    case SEN_CORR:
        SEN_STATE = (KEY == KEY_ON) ? SEN_GYR : SEN_NUMQ;
        break;

    /************************** CorrectGyr **************************************/
    case SEN_GYR:
        LED_R = !LED_R;
        switch((u16)(Correction_Time/SampleRateFreg)) {
        case 0:   // 分配記憶體給 MaveAve 使用
            FIFO_X = (s16*)malloc(MAFIFO_SIZE*sizeof(s16));
            FIFO_Y = (s16*)malloc(MAFIFO_SIZE*sizeof(s16));
            FIFO_Z = (s16*)malloc(MAFIFO_SIZE*sizeof(s16));
            memset(FIFO_X, 0, MAFIFO_SIZE*sizeof(s16));
            memset(FIFO_Y, 0, MAFIFO_SIZE*sizeof(s16));
            memset(FIFO_Z, 0, MAFIFO_SIZE*sizeof(s16));
            Correction_Time = SampleRateFreg;
            break;
        case 1:   // 等待 FIFO 填滿靜態資料
            /* 移動平均 Simple Moving Average */
            Gyr.X = (s16)MoveAve_SMA(Gyr.X, FIFO_X, MAFIFO_SIZE);
            Gyr.Y = (s16)MoveAve_SMA(Gyr.Y, FIFO_Y, MAFIFO_SIZE);
            Gyr.Z = (s16)MoveAve_SMA(Gyr.Z, FIFO_Z, MAFIFO_SIZE);
            Correction_Time++;
            break;
        case 2:   // 釋放記憶體 & 計算陀螺儀偏移量
            free(FIFO_X);
            free(FIFO_Y);
            free(FIFO_Z);
            Gyr.OffsetX += (Gyr.X - GYR_X_OFFSET);  // 角速度為 0dps
            Gyr.OffsetY += (Gyr.Y - GYR_Y_OFFSET);  // 角速度為 0dps
            Gyr.OffsetZ += (Gyr.Z - GYR_Z_OFFSET);  // 角速度為 0dps
            Correction_Time = 0;
            SEN_STATE = SEN_ACC;
            break;
        }
        break;

    /************************** CorrectAcc **************************************/
    case SEN_ACC:
        LED_R = !LED_R;
        switch((u16)(Correction_Time/SampleRateFreg)) {
        case 0:   // 分配記憶體給 MaveAve 使用
            FIFO_X = (s16*)malloc(MAFIFO_SIZE*sizeof(s16));
            FIFO_Y = (s16*)malloc(MAFIFO_SIZE*sizeof(s16));
            FIFO_Z = (s16*)malloc(MAFIFO_SIZE*sizeof(s16));
            memset(FIFO_X, 0, MAFIFO_SIZE*sizeof(s16));
            memset(FIFO_Y, 0, MAFIFO_SIZE*sizeof(s16));
            memset(FIFO_Z, 0, MAFIFO_SIZE*sizeof(s16));
            Correction_Time = SampleRateFreg;
            break;
        case 1:   // 等待 FIFO 填滿靜態資料
            /* 移動平均 Simple Moving Average */
            Acc.X = (s16)MoveAve_SMA(Acc.X, FIFO_X, MAFIFO_SIZE);
            Acc.Y = (s16)MoveAve_SMA(Acc.Y, FIFO_Y, MAFIFO_SIZE);
            Acc.Z = (s16)MoveAve_SMA(Acc.Z, FIFO_Z, MAFIFO_SIZE);
            Correction_Time++;
            break;
        case 2:   // 釋放記憶體 & 計算加速度計偏移量
            free(FIFO_X);
            free(FIFO_Y);
            free(FIFO_Z);
            Acc.OffsetX += (Acc.X - ACC_X_OFFSET);  // 重力加速度為 0g
            Acc.OffsetY += (Acc.Y - ACC_Y_OFFSET);  // 重力加速度為 0g
            Acc.OffsetZ += (Acc.Z - ACC_Z_OFFSET);  // 重力加速度為 1g
            Correction_Time = 0;
            SEN_STATE = SEN_MAG;
            break;
        }
        break;

    /************************** CorrectMag **************************************/
    case SEN_MAG:
        LED_R = !LED_R;
        SEN_STATE = SEN_NUMQ;
        break;

    /************************** Quaternion **************************************/
    case SEN_NUMQ:
        switch((u16)(Correction_Time/SampleRateFreg)) {
        case 0:   // 等待 FIFO 填滿靜態資料
            /* 加權移動平均法 Weighted Moving Average */
            Acc.X = (s16)MoveAve_WMA(Acc.X, FIFO_ACC[0], 8);
            Acc.Y = (s16)MoveAve_WMA(Acc.Y, FIFO_ACC[1], 8);
            Acc.Z = (s16)MoveAve_WMA(Acc.Z, FIFO_ACC[2], 8);
            Gyr.X = (s16)MoveAve_WMA(Gyr.X, FIFO_GYR[0], 8);
            Gyr.Y = (s16)MoveAve_WMA(Gyr.Y, FIFO_GYR[1], 8);
            Gyr.Z = (s16)MoveAve_WMA(Gyr.Z, FIFO_GYR[2], 8);
            Mag.X = (s16)MoveAve_WMA(Mag.X, FIFO_MAG[0], 16);
            Mag.Y = (s16)MoveAve_WMA(Mag.Y, FIFO_MAG[1], 16);
            Mag.Z = (s16)MoveAve_WMA(Mag.Z, FIFO_MAG[2], 16);
            Correction_Time++;
            break;
        case 1:

            /* 加權移動平均法 Weighted Moving Average */
            Acc.X = (s16)MoveAve_WMA(Acc.X, FIFO_ACC[0], 8);
            Acc.Y = (s16)MoveAve_WMA(Acc.Y, FIFO_ACC[1], 8);
            Acc.Z = (s16)MoveAve_WMA(Acc.Z, FIFO_ACC[2], 8);
            Gyr.X = (s16)MoveAve_WMA(Gyr.X, FIFO_GYR[0], 8);
            Gyr.Y = (s16)MoveAve_WMA(Gyr.Y, FIFO_GYR[1], 8);
            Gyr.Z = (s16)MoveAve_WMA(Gyr.Z, FIFO_GYR[2], 8);
            Mag.X = (s16)MoveAve_WMA(Mag.X, FIFO_MAG[0], 16);
            Mag.Y = (s16)MoveAve_WMA(Mag.Y, FIFO_MAG[1], 16);
            Mag.Z = (s16)MoveAve_WMA(Mag.Z, FIFO_MAG[2], 16);

            /* To Physical */
            Acc.TrueX = Acc.X*MPU9150A_4g;        // g/LSB
            Acc.TrueY = Acc.Y*MPU9150A_4g;        // g/LSB
            Acc.TrueZ = Acc.Z*MPU9150A_4g;        // g/LSB
            Gyr.TrueX = Gyr.X*MPU9150G_2000dps;   // dps/LSB
            Gyr.TrueY = Gyr.Y*MPU9150G_2000dps;   // dps/LSB
            Gyr.TrueZ = Gyr.Z*MPU9150G_2000dps;   // dps/LSB
            Mag.TrueX = Mag.X*MPU9150M_1200uT;    // uT/LSB
            Mag.TrueY = Mag.Y*MPU9150M_1200uT;    // uT/LSB
            Mag.TrueZ = Mag.Z*MPU9150M_1200uT;    // uT/LSB

//          Ellipse[3] = ( Mag.X*arm_cos_f32(Mag.EllipseSita)+Mag.Y*arm_sin_f32(Mag.EllipseSita))/Mag.EllipseB;
//          Ellipse[4] = (-Mag.X*arm_sin_f32(Mag.EllipseSita)+Mag.Y*arm_cos_f32(Mag.EllipseSita))/Mag.EllipseA;

            AngE.Pitch = toDeg(atan2f(Acc.TrueY, Acc.TrueZ));
            AngE.Roll  = toDeg(-asinf(Acc.TrueX));
//          AngE.Yaw   = toDeg(atan2f(Ellipse[3], Ellipse[4]))+180.0f;

            Quaternion_ToNumQ(&NumQ, &AngE);

            Correction_Time = 0;
            SEN_STATE = SEN_ALG;
            break;
        }
        break;

    /************************** Algorithm ***************************************/
    case SEN_ALG:

        /* 加權移動平均法 Weighted Moving Average */
        Acc.X = (s16)MoveAve_WMA(Acc.X, FIFO_ACC[0], 8);
        Acc.Y = (s16)MoveAve_WMA(Acc.Y, FIFO_ACC[1], 8);
        Acc.Z = (s16)MoveAve_WMA(Acc.Z, FIFO_ACC[2], 8);
        Gyr.X = (s16)MoveAve_WMA(Gyr.X, FIFO_GYR[0], 8);
        Gyr.Y = (s16)MoveAve_WMA(Gyr.Y, FIFO_GYR[1], 8);
        Gyr.Z = (s16)MoveAve_WMA(Gyr.Z, FIFO_GYR[2], 8);
        Mag.X = (s16)MoveAve_WMA(Mag.X, FIFO_MAG[0], 16);
        Mag.Y = (s16)MoveAve_WMA(Mag.Y, FIFO_MAG[1], 16);
        Mag.Z = (s16)MoveAve_WMA(Mag.Z, FIFO_MAG[2], 16);

        /* To Physical */
        Acc.TrueX  = Acc.X*MPU9150A_4g;       // g/LSB
        Acc.TrueY  = Acc.Y*MPU9150A_4g;       // g/LSB
        Acc.TrueZ  = Acc.Z*MPU9150A_4g;       // g/LSB
        Gyr.TrueX  = Gyr.X*MPU9150G_2000dps;  // dps/LSB
        Gyr.TrueY  = Gyr.Y*MPU9150G_2000dps;  // dps/LSB
        Gyr.TrueZ  = Gyr.Z*MPU9150G_2000dps;  // dps/LSB
        Mag.TrueX  = Mag.X*MPU9150M_1200uT;   // uT/LSB
        Mag.TrueY  = Mag.Y*MPU9150M_1200uT;   // uT/LSB
        Mag.TrueZ  = Mag.Z*MPU9150M_1200uT;   // uT/LSB
        Temp.TrueT = Temp.T*MPU9150T_85degC;  // degC/LSB

        /* Get Attitude Angle */
        AHRS_Update();

        break;

    /************************** Error *******************************************/
    default:
        LED_R = 1;
        LED_G = 1;
        LED_B = 1;
        while(1) {
            LED_R = !LED_R;
            Delay_100ms(10);
        }
    }
}
Vector<dim> radToDeg(Vector<dim> rad) {
    for (unsigned int i = 0; i < dim; ++i)
        rad[i] *= toDeg();
    return rad;
}
/*=====================================================================================================*/
void AHRS_Update(void)
{
	float tempX = 0, tempY = 0;
	float Normalize;
	float gx, gy, gz;
// float hx, hy, hz;
// float wx, wy, wz;
// float bx, bz;
	float ErrX, ErrY, ErrZ;
	float AccX, AccY, AccZ;
	float GyrX, GyrY, GyrZ;
// float MegX, MegY, MegZ;
	float /*Mq11, Mq12, */Mq13,/* Mq21, Mq22, */Mq23,/* Mq31, Mq32, */Mq33;

	static float AngZ_Temp = 0.0f;
	static float exInt = 0.0f, eyInt = 0.0f, ezInt = 0.0f;

//   Mq11 = NumQ.q0*NumQ.q0 + NumQ.q1*NumQ.q1 - NumQ.q2*NumQ.q2 - NumQ.q3*NumQ.q3;
//   Mq12 = 2.0f*(NumQ.q1*NumQ.q2 + NumQ.q0*NumQ.q3);
	Mq13 = 2.0f * (NumQ.q1 * NumQ.q3 - NumQ.q0 * NumQ.q2);
//   Mq21 = 2.0f*(NumQ.q1*NumQ.q2 - NumQ.q0*NumQ.q3);
//   Mq22 = NumQ.q0*NumQ.q0 - NumQ.q1*NumQ.q1 + NumQ.q2*NumQ.q2 - NumQ.q3*NumQ.q3;
	Mq23 = 2.0f * (NumQ.q0 * NumQ.q1 + NumQ.q2 * NumQ.q3);
//   Mq31 = 2.0f*(NumQ.q0*NumQ.q2 + NumQ.q1*NumQ.q3);
//   Mq32 = 2.0f*(NumQ.q2*NumQ.q3 - NumQ.q0*NumQ.q1);
	Mq33 = NumQ.q0 * NumQ.q0 - NumQ.q1 * NumQ.q1 - NumQ.q2 * NumQ.q2 + NumQ.q3 * NumQ.q3;

	Normalize = invSqrtf(squa(Acc.TrueX) + squa(Acc.TrueY) + squa(Acc.TrueZ));
	AccX = Acc.TrueX * Normalize;
	AccY = Acc.TrueY * Normalize;
	AccZ = Acc.TrueZ * Normalize;

// Normalize = invSqrtf(squa(Meg.TrueX) + squa(Meg.TrueY) + squa(Meg.TrueZ));
// MegX = Meg.TrueX*Normalize;
// MegY = Meg.TrueY*Normalize;
// MegZ = Meg.TrueZ*Normalize;

	gx = Mq13;
	gy = Mq23;
	gz = Mq33;

// hx = MegX*Mq11 + MegY*Mq21 + MegZ*Mq31;
// hy = MegX*Mq12 + MegY*Mq22 + MegZ*Mq32;
// hz = MegX*Mq13 + MegY*Mq23 + MegZ*Mq33;

// bx = sqrtf(squa(hx) + squa(hy));
// bz = hz;

// wx = bx*Mq11 + bz*Mq13;
// wy = bx*Mq21 + bz*Mq23;
// wz = bx*Mq31 + bz*Mq33;

	ErrX = (AccY * gz - AccZ * gy)/* + (MegY*wz - MegZ*wy)*/;
	ErrY = (AccZ * gx - AccX * gz)/* + (MegZ*wx - MegX*wz)*/;
	ErrZ = (AccX * gy - AccY * gx)/* + (MegX*wy - MegY*wx)*/;

	exInt = exInt + ErrX * Ki;
	eyInt = eyInt + ErrY * Ki;
	ezInt = ezInt + ErrZ * Ki;

	GyrX = toRad(Gyr.TrueX);
	GyrY = toRad(Gyr.TrueY);
	GyrZ = toRad(Gyr.TrueZ);

	GyrX = GyrX + Kp * ErrX + exInt;
	GyrY = GyrY + Kp * ErrY + eyInt;
	GyrZ = GyrZ + Kp * ErrZ + ezInt;

	Quaternion_RungeKutta(&NumQ, GyrX, GyrY, GyrZ, SampleRateHelf);
	Quaternion_Normalize(&NumQ);
	Quaternion_ToAngE(&NumQ, &AngE);

	tempX    = (Mag.X * arm_cos_f32(Mag.EllipseSita) + Mag.Y * arm_sin_f32(Mag.EllipseSita)) / Mag.EllipseB;
	tempY    = (-Mag.X * arm_sin_f32(Mag.EllipseSita) + Mag.Y * arm_cos_f32(Mag.EllipseSita)) / Mag.EllipseA;
	AngE.Yaw = atan2f(tempX, tempY);

	AngE.Pitch = toDeg(AngE.Pitch);
	AngE.Roll  = toDeg(AngE.Roll);
	AngE.Yaw   = toDeg(AngE.Yaw) + 180.0f;

	/* 互補濾波 Complementary Filter */
#define CF_A 0.9f
#define CF_B 0.1f
	AngZ_Temp = AngZ_Temp + GyrZ * SampleRate;
	AngZ_Temp = CF_A * AngZ_Temp + CF_B * AngE.Yaw;

	if (AngZ_Temp > 360.0f)
		AngE.Yaw = AngZ_Temp - 360.0f;
	else if (AngZ_Temp < 0.0f)
		AngE.Yaw = AngZ_Temp + 360.0f;
	else
		AngE.Yaw = AngZ_Temp;
}
示例#22
0
/*=====================================================================================================*/
void SysTick_Handler( void )
{
  u8 IMU_Buf[20] = {0};

  u16 Final_M1 = 0;
  u16 Final_M2 = 0;
  u16 Final_M3 = 0;
  u16 Final_M4 = 0;

  s16 Thr = 0, Pitch = 0, Roll = 0, Yaw = 0;

  float Ellipse[5] = {0};

  static u8  BaroCnt = 0;

  static s16 ACC_FIFO[3][256] = {0};
  static s16 GYR_FIFO[3][256] = {0};
  static s16 MAG_FIFO[3][256] = {0};

  static s16 MagDataX[8] = {0};
  static s16 MagDataY[8] = {0};

  static u16 Correction_Time = 0;

  /* Time Count */
  SysTick_Cnt++;
  if(SysTick_Cnt == SampleRateFreg) {
    SysTick_Cnt = 0;
    Time_Sec++;
    if(Time_Sec == 60) {	// 0~59
      Time_Sec = 0;
      Time_Min++;
      if(Time_Sec == 60)
      Time_Min = 0;
    }
  }

  /* 400Hz, Read Sensor ( Accelerometer, Gyroscope, Magnetometer ) */
  MPU9150_Read(IMU_Buf);

  /* 100Hz, Read Barometer */
  BaroCnt++;
  if(BaroCnt == 4) {
    MS5611_Read(&Baro, MS5611_D1_OSR_4096);
    BaroCnt = 0;
  }

  Acc.X  = (s16)((IMU_Buf[0]  << 8) | IMU_Buf[1]);
  Acc.Y  = (s16)((IMU_Buf[2]  << 8) | IMU_Buf[3]);
  Acc.Z  = (s16)((IMU_Buf[4]  << 8) | IMU_Buf[5]);
  Temp.T = (s16)((IMU_Buf[6]  << 8) | IMU_Buf[7]);
  Gyr.X  = (s16)((IMU_Buf[8]  << 8) | IMU_Buf[9]);
  Gyr.Y  = (s16)((IMU_Buf[10] << 8) | IMU_Buf[11]);
  Gyr.Z  = (s16)((IMU_Buf[12] << 8) | IMU_Buf[13]);
  Mag.X  = (s16)((IMU_Buf[15] << 8) | IMU_Buf[14]);
  Mag.Y  = (s16)((IMU_Buf[17] << 8) | IMU_Buf[16]);
  Mag.Z  = (s16)((IMU_Buf[19] << 8) | IMU_Buf[18]);

  /* Offset */
  Acc.X -= Acc.OffsetX;
  Acc.Y -= Acc.OffsetY;
  Acc.Z -= Acc.OffsetZ;
  Gyr.X -= Gyr.OffsetX;
  Gyr.Y -= Gyr.OffsetY;
  Gyr.Z -= Gyr.OffsetZ;
  Mag.X *= Mag.AdjustX;
  Mag.Y *= Mag.AdjustY;
  Mag.Z *= Mag.AdjustZ;

  #define MovegAveFIFO_Size 250
  switch(SensorMode) {

  /************************** Mode_CorrectGyr **************************************/
    case Mode_GyrCorrect:
      LED_R = !LED_R;
      /* Simple Moving Average */
      Gyr.X = (s16)MoveAve_SMA(Gyr.X, GYR_FIFO[0], MovegAveFIFO_Size);
      Gyr.Y = (s16)MoveAve_SMA(Gyr.Y, GYR_FIFO[1], MovegAveFIFO_Size);
      Gyr.Z = (s16)MoveAve_SMA(Gyr.Z, GYR_FIFO[2], MovegAveFIFO_Size);

      Correction_Time++;  // 等待 FIFO 填滿空值 or 填滿靜態資料
      if(Correction_Time == 400) {
        Gyr.OffsetX += (Gyr.X - GYR_X_OFFSET);  // 角速度為 0dps
        Gyr.OffsetY += (Gyr.Y - GYR_Y_OFFSET);  // 角速度為 0dps
        Gyr.OffsetZ += (Gyr.Z - GYR_Z_OFFSET);  // 角速度為 0dps

        Correction_Time = 0;
        SensorMode = Mode_MagCorrect; // Mode_AccCorrect;
      }
      break;
 
  /************************** Mode_CorrectAcc **************************************/
    case Mode_AccCorrect:
      LED_R = ~LED_R;
      /* Simple Moving Average */
      Acc.X = (s16)MoveAve_SMA(Acc.X, ACC_FIFO[0], MovegAveFIFO_Size);
      Acc.Y = (s16)MoveAve_SMA(Acc.Y, ACC_FIFO[1], MovegAveFIFO_Size);
      Acc.Z = (s16)MoveAve_SMA(Acc.Z, ACC_FIFO[2], MovegAveFIFO_Size);

      Correction_Time++;  // 等待 FIFO 填滿空值 or 填滿靜態資料
      if(Correction_Time == 400) {
        Acc.OffsetX += (Acc.X - ACC_X_OFFSET);  // 重力加速度為 0g
        Acc.OffsetY += (Acc.Y - ACC_Y_OFFSET);  // 重力加速度為 0g
        Acc.OffsetZ += (Acc.Z - ACC_Z_OFFSET);  // 重力加速度為 1g

        Correction_Time = 0;
        SensorMode = Mode_Quaternion; // Mode_MagCorrect;
      }
      break;

  /************************** Mode_CorrectMag **************************************/
    #define MagCorrect_Ave    100
    #define MagCorrect_Delay  600   // 2.5ms * 600 = 1.5s
    case Mode_MagCorrect:
      LED_R = !LED_R;
      Correction_Time++;
      switch((u16)(Correction_Time/MagCorrect_Delay)) {
        case 0:
          LED_B = 0;
          MagDataX[0] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[0] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 1:
          LED_B = 1;
          MagDataX[1] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[1] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 2:
          LED_B = 0;
          MagDataX[2] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[2] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 3:
          LED_B = 1;
          MagDataX[3] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[3] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 4:
          LED_B = 0;
          MagDataX[4] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[4] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 5:
          LED_B = 1;
          MagDataX[5] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[5] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 6:
          LED_B = 0;
          MagDataX[6] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[6] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        case 7:
          LED_B = 1;
          MagDataX[7] = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], MagCorrect_Ave);
          MagDataY[7] = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], MagCorrect_Ave);
          break;
        default:
          LED_B = 1;
          EllipseFitting(Ellipse, MagDataX, MagDataY, 8);
          Mag.EllipseSita = Ellipse[0];
          Mag.EllipseX0   = Ellipse[1];
          Mag.EllipseY0   = Ellipse[2];
          Mag.EllipseA    = Ellipse[3];
          Mag.EllipseB    = Ellipse[4];

          Correction_Time = 0;
          SensorMode = Mode_Quaternion;
          break;
      }
      break;

  /************************** Algorithm Mode **************************************/
    case Mode_Quaternion:
      LED_R = !LED_R;

      /* To Physical */
      Acc.TrueX = Acc.X*MPU9150A_4g;        // g/LSB
      Acc.TrueY = Acc.Y*MPU9150A_4g;        // g/LSB
      Acc.TrueZ = Acc.Z*MPU9150A_4g;        // g/LSB
      Gyr.TrueX = Gyr.X*MPU9150G_2000dps;   // dps/LSB
      Gyr.TrueY = Gyr.Y*MPU9150G_2000dps;   // dps/LSB
      Gyr.TrueZ = Gyr.Z*MPU9150G_2000dps;   // dps/LSB
      Mag.TrueX = Mag.X*MPU9150M_1200uT;    // uT/LSB
      Mag.TrueY = Mag.Y*MPU9150M_1200uT;    // uT/LSB
      Mag.TrueZ = Mag.Z*MPU9150M_1200uT;    // uT/LSB
      Temp.TrueT = Temp.T*MPU9150T_85degC;  // degC/LSB

      Ellipse[3] = ( Mag.X*arm_cos_f32(Mag.EllipseSita)+Mag.Y*arm_sin_f32(Mag.EllipseSita))/Mag.EllipseB;
      Ellipse[4] = (-Mag.X*arm_sin_f32(Mag.EllipseSita)+Mag.Y*arm_cos_f32(Mag.EllipseSita))/Mag.EllipseA;

      AngE.Pitch = toDeg(atan2f(Acc.TrueY, Acc.TrueZ));
      AngE.Roll  = toDeg(-asinf(Acc.TrueX));
      AngE.Yaw   = toDeg(atan2f(Ellipse[3], Ellipse[4]))+180.0f;

      Quaternion_ToNumQ(&NumQ, &AngE);

      SensorMode = Mode_Algorithm;
      break;

  /************************** Algorithm Mode ****************************************/
    case Mode_Algorithm:

      /* 加權移動平均法 Weighted Moving Average */
      Acc.X = (s16)MoveAve_WMA(Acc.X, ACC_FIFO[0], 8);
      Acc.Y = (s16)MoveAve_WMA(Acc.Y, ACC_FIFO[1], 8);
      Acc.Z = (s16)MoveAve_WMA(Acc.Z, ACC_FIFO[2], 8);
      Gyr.X = (s16)MoveAve_WMA(Gyr.X, GYR_FIFO[0], 8);
      Gyr.Y = (s16)MoveAve_WMA(Gyr.Y, GYR_FIFO[1], 8);
      Gyr.Z = (s16)MoveAve_WMA(Gyr.Z, GYR_FIFO[2], 8);
      Mag.X = (s16)MoveAve_WMA(Mag.X, MAG_FIFO[0], 64);
      Mag.Y = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO[1], 64);
      Mag.Z = (s16)MoveAve_WMA(Mag.Z, MAG_FIFO[2], 64);

      /* To Physical */
      Acc.TrueX = Acc.X*MPU9150A_4g;        // g/LSB
      Acc.TrueY = Acc.Y*MPU9150A_4g;        // g/LSB
      Acc.TrueZ = Acc.Z*MPU9150A_4g;        // g/LSB
      Gyr.TrueX = Gyr.X*MPU9150G_2000dps;   // dps/LSB
      Gyr.TrueY = Gyr.Y*MPU9150G_2000dps;   // dps/LSB
      Gyr.TrueZ = Gyr.Z*MPU9150G_2000dps;   // dps/LSB
      Mag.TrueX = Mag.X*MPU9150M_1200uT;    // uT/LSB
      Mag.TrueY = Mag.Y*MPU9150M_1200uT;    // uT/LSB
      Mag.TrueZ = Mag.Z*MPU9150M_1200uT;    // uT/LSB
      Temp.TrueT = Temp.T*MPU9150T_85degC;  // degC/LSB

      /* Get Attitude Angle */
      AHRS_Update();

//      if(KEYL_U == 0)	{	PID_Roll.Kp += 0.001f;	PID_Pitch.Kp += 0.001f;  }
//      if(KEYL_L == 0)	{	PID_Roll.Kp -= 0.001f;	PID_Pitch.Kp -= 0.001f;  }
//      if(KEYL_R == 0)	{	PID_Roll.Ki += 0.0001f;	PID_Pitch.Ki += 0.0001f; }
//      if(KEYL_D == 0)	{	PID_Roll.Ki -= 0.0001f;	PID_Pitch.Ki -= 0.0001f; }
//      if(KEYR_R == 0)	{	PID_Roll.Kd += 0.0001f;	PID_Pitch.Kd += 0.0001f; }
//      if(KEYR_D == 0)	{	PID_Roll.Kd -= 0.0001f;	PID_Pitch.Kd -= 0.0001f; }
//      if(KEYR_L == 0)	{	PID_Roll.SumErr = 0.0f;	PID_Pitch.SumErr = 0.0f; }
//      if(KEYL_U == 0)	{	PID_Yaw.Kp += 0.001f;    }
//      if(KEYL_L == 0)	{	PID_Yaw.Kp -= 0.001f;    }
//      if(KEYL_R == 0)	{	PID_Yaw.Ki += 0.001f;	 }
//      if(KEYL_D == 0)	{	PID_Yaw.Ki -= 0.001f;	 }
//      if(KEYR_R == 0)	{	PID_Yaw.Kd += 0.0001f;	 }
//      if(KEYR_D == 0)	{	PID_Yaw.Kd -= 0.0001f;	 }
//      if(KEYR_L == 0)	{	PID_Roll.SumErr = 0.0f;	 }

      /* Get ZeroErr */
      PID_Pitch.ZeroErr = (float)((s16)Exp_Pitch/4.5f);
      PID_Roll.ZeroErr  = (float)((s16)Exp_Roll/4.5f);
      PID_Yaw.ZeroErr   = (float)((s16)Exp_Yaw)+180.0f;

      /* PID */
      Roll  = (s16)PID_AHRS_Cal(&PID_Roll,   AngE.Roll,  Gyr.TrueX);
      Pitch = (s16)PID_AHRS_Cal(&PID_Pitch,  AngE.Pitch, Gyr.TrueY);
//      Yaw   = (s16)PID_AHRS_CalYaw(&PID_Yaw, AngE.Yaw,   Gyr.TrueZ);
      Yaw   = (s16)(PID_Yaw.Kd*Gyr.TrueZ);
      Thr   = (s16)Exp_Thr;

      /* Motor Ctrl */
      Final_M1 = PWM_M1 + Thr + Pitch + Roll + Yaw;
      Final_M2 = PWM_M2 + Thr - Pitch + Roll - Yaw;
      Final_M3 = PWM_M3 + Thr - Pitch - Roll + Yaw;
      Final_M4 = PWM_M4 + Thr + Pitch - Roll - Yaw;

      /* Check Connection */
      #define NoSignal 1  // 1 sec
      if(KEYR_L == 0)
        Motor_Control(PWM_MOTOR_MIN, PWM_MOTOR_MIN, PWM_MOTOR_MIN, PWM_MOTOR_MIN);
      else if(((Time_Sec-RecvTime_Sec)>NoSignal) || ((Time_Sec-RecvTime_Sec)<-NoSignal))
        Motor_Control(PWM_MOTOR_MIN, PWM_MOTOR_MIN, PWM_MOTOR_MIN, PWM_MOTOR_MIN);
      else
        Motor_Control(Final_M1, Final_M2, Final_M3, Final_M4);

      /* DeBug */
      Tmp_PID_KP = PID_Yaw.Kp*1000;
      Tmp_PID_KI = PID_Yaw.Ki*1000;
      Tmp_PID_KD = PID_Yaw.Kd*1000;
      Tmp_PID_Pitch = Yaw;

      break;
  }
}
示例#23
0
Arc::Direction Arc::angleRadToDirEight( float angle )
{
    return angleDegToDirEight(toDeg(angle));
}
示例#24
0
Arc::Direction Arc::angleRadToDirFour( float angle )
{
    return angleDegToDirFour(toDeg(angle));
}
示例#25
0
void display(void)	
{
	// Buffer clearen
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// View Matrix erstellen
	glLoadIdentity();
	float x = distance * sin(theta) * cos(phi);
	float y = distance * cos(theta);
	float z = distance * sin(theta) * sin(phi);
	gluLookAt(x, y, z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

	// Teekanne rendern.
	glutSolidTeapot(1);

	// Den Matrix-Stack sichern.
	glPushMatrix();
	
		// Zeichnen der Kugelkreisbahn.	
			drawCircle(10.0f, 50);
		// Zeichnen der Kugel.
			// Wenden Sie eine Translation und eine Rotation an, bevor sie die Kugel zeichnen. Sie können die Variable 'angle' für die Rotation verwenden.
			// Bedenken Sie dabei die richtige Reihenfolge der beiden Transformationen.
			glRotated(angle, 0, 1.0f, 0);
			glTranslatef(10.0f, 0, 0);
			glutSolidSphere(1.0f, 32, 32);
		// Zeichnen der Würfelkreisbahn.
			// Hinweis: Der Ursprung des Koordinatensystems befindet sich nun im Zentrum des Würfels.
			// Drehen Sie das Koordinatensystem um 90° entlang der Achse, die für die Verschiebung des Würfels genutzt wurde.
			// Danach steht die Würfelkreisbahn senkrecht zur Tangentialrichtung der Kugelkreisbahn.
			glRotated(90.0f, 1.0f, 0, 0);
			drawCircle(5.0f, 50);
		// Zeichnen des Würfels.
			// Wenden Sie die entsprechende Translation und Rotation an, bevor sie den Würfel zeichnen.
			glRotated(angle, 0, 1.0f, 0);
			glTranslatef(5.0f, 0, 0);
			glutSolidCube(1.0f);
		// Zeichnen einer Linie von Würfel zu Kegel.
			glDisable(GL_LIGHTING);
			glTranslatef(3.0f, 0, 0);
			glBegin(GL_LINE_STRIP);
			glVertex3f(0, 0, 0);
			glVertex3f(-3.0f, 0, 0);
			glEnd();
			glEnable(GL_LIGHTING);
		// Drehung anwenden, sodass Koordinatensystem in Richtung Ursprung orientiert ist. (Hinweis: Implementieren Sie dies zuletzt.)
			GLfloat height = 8*cos(toRad(angle-90));
			GLfloat d = 8*sin(toRad(angle-90));
			GLfloat e = 10 - d;
			GLfloat l = pow(pow(height,2) + pow(e,2), 0.5f);
			GLfloat alpha = toDeg(acos(e/l)) - 90;
			if(static_cast<int>(angle)%360 > 180) alpha = -alpha;
			glRotated(alpha, 0, 1.0f, 0);
			if(static_cast<int>(angle)%360 > 180)
			{
				glRotated(180 - angle, 0, 1.0f, 0);
				std::cout << alpha + 180 - (int)angle%360 << std::endl;
			}
			else 
			{
				glRotated(-angle, 0, 1.0f, 0);
				std::cout << alpha - (int)angle%360 << std::endl;
			}
		// Zeichnen der Linie von Kegel zu Urpsrung.	
			glDisable(GL_LIGHTING);
			glBegin(GL_LINE_STRIP);
			glVertex3f(0, 0, 0);
			glVertex3f(0, 0, l);
			glEnd();
			glEnable(GL_LIGHTING);
		// Zeichnen des Kegels.
			glutSolidCone(0.5f, 1.0f, 32, 4);
	// Den Matrix-Stack wiederherstellen.

	glPopMatrix();
	
	glutSwapBuffers();	

	angle += 5.0f / 60.0f;
}
示例#26
0
/*
 * RMC Recommended Minimum Navigation Information
 *
 * 1         2 3       4 5        6 7   8   9    10  11
 * |         | |       | |        | |   |   |    |   |
 * hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxx,x.x,a
 *
 * 1) Time (UTC)
 * 2) Status, V = Navigation receiver warning
 * 3) Latitude
 * 4) N or S
 * 5) Longitude
 * 6) E or W
 * 7) Speed over ground, knots
 * 8) Track made good, degrees true
 * 9) Date, ddmmyy
 * 10) Magnetic Variation, degrees
 * 11) E or W
 */
static void parseRMC(un8 index, char *value)
{
	if (*value == 0)
		return;

	switch (index)
	{
	case GPS_RMC_STATUS:
		/* A: fix; V: no fix */
		veVariantUn8(&local.fix, value[0] == 'A');
		return;

	case GPS_RMC_LATITUDE:
		errno = 0;
		veVariantFloat(&local.latitude, toDeg((float)atof(value)));
		if (errno)
			veVariantInvalidate(&local.latitude);
		return;

	case GPS_RMC_LAT_NORTH_SOUTH:
		/* North is positive, south is negative */
		if (value[0] == 'S')
			local.latitude.value.Float *= -1;
		return;

	case GPS_RMC_LONGITUDE:
		errno = 0;
		veVariantFloat(&local.longitude, toDeg((float)atof(value)));
		if (errno)
			veVariantInvalidate(&local.longitude);
		return;

	case GPS_RMC_LONG_EAST_WEST:
		/* East is positive, west is negative */
		if (value[0] == 'W')
			local.longitude.value.Float *= -1;
		return;

	case GPS_RMC_VARIATION:
		errno = 0;
		veVariantFloat(&local.variation, toDeg((float)atof(value)));
		if (errno)
			veVariantInvalidate(&local.variation);
		return;

	case GPS_RMC_VAR_EAST_WEST:
		/* East is positive, west is negative */
		if (value[0] == 'W')
			local.variation.value.Float *= -1;
		return;

	case GPS_RMC_UTC_TIME:
		memset(&local.time, 0, sizeof(struct tm));
		local.time.tm_hour = a2b(*value++) * 10;
		local.time.tm_hour += a2b(*value++);
		local.time.tm_min = a2b(*value++) * 10;
		local.time.tm_min += a2b(*value++);
		local.time.tm_sec = a2b(*value++ ) * 10;
		local.time.tm_sec += a2b(*value++);
		return;

	case GPS_RMC_UTC_DATE:
		local.time.tm_mday = a2b(*value++) * 10;
		local.time.tm_mday += a2b(*value++);
		local.time.tm_mon = a2b(*value++) * 10;
		local.time.tm_mon += a2b(*value++) - 1;		/* 0-11 */
		local.time.tm_year = a2b(*value++) * 10;
		local.time.tm_year += a2b(*value++) + 100;	/* Since 1900 */
		veVariantUn32(&local.timestamp, (un32)mktime(&local.time));
		return;

	case GPS_RMC_SPEED:
		errno = 0;
		veVariantFloat(&local.speed, (float)atof(value));
		if (errno) {
			veVariantInvalidate(&local.speed);
			return;
		}
		/* Knots to m/s */
		local.speed.value.Float *= (1852.0 / 3600.0);
		return;

	case GPS_RMC_TRUE_COURSE:

		/* Prevent bouncing when not moving */
		if (!veVariantIsValid(&local.speed) || local.speed.value.Float == 0) {
			veVariantInvalidate(&local.course);
			return;
		}

		errno = 0;
		veVariantFloat(&local.course, (float)atof(value));
		if (errno)
			veVariantInvalidate(&local.course);
		return;
	}
}
示例#27
0
Angle::Angle(const sf::Vector2f &vec) :
    Angle(toDeg((float) atan2(vec.y, vec.x))) { }
示例#28
0
void mavlink_handleMessage(mavlink_message_t* msg) {
	mavlink_message_t msg2;
	char sysmsg_str[1024];
	switch (msg->msgid) {
		case MAVLINK_MSG_ID_HEARTBEAT: {
			mavlink_heartbeat_t packet;
			mavlink_msg_heartbeat_decode(msg, &packet);
			droneType = packet.type;
			autoPilot = packet.autopilot;

			if (packet.base_mode == MAV_MODE_MANUAL_ARMED) {
				ModelData.mode = MODEL_MODE_MANUAL;
			} else if (packet.base_mode == 128 + 64 + 16) {
				ModelData.mode = MODEL_MODE_RTL;
			} else if (packet.base_mode == 128 + 16) {
				ModelData.mode = MODEL_MODE_POSHOLD;
			} else if (packet.base_mode == 128 + 4) {
				ModelData.mode = MODEL_MODE_MISSION;
			}
			if (packet.system_status == MAV_STATE_ACTIVE) {
				ModelData.armed = MODEL_ARMED;
			} else {
				ModelData.armed = MODEL_DISARMED;
			}
//			SDL_Log("Heartbeat: %i, %i, %i\n", ModelData.armed, ModelData.mode, ModelData.status);
			ModelData.heartbeat = 100;
//			sprintf(sysmsg_str, "Heartbeat: %i", (int)time(0));
			if ((*msg).sysid != 0xff) {
				ModelData.sysid = (*msg).sysid;
				ModelData.compid = (*msg).compid;
				if (mavlink_maxparam == 0) {
					mavlink_start_feeds();
				}
			}
			redraw_flag = 1;
			break;
		}
		case MAVLINK_MSG_ID_RC_CHANNELS_SCALED: {
			mavlink_rc_channels_scaled_t packet;
			mavlink_msg_rc_channels_scaled_decode(msg, &packet);
//			SDL_Log("Radio: %i,%i,%i\n", packet.chan1_scaled, packet.chan2_scaled, packet.chan3_scaled);

/*			if ((int)packet.chan6_scaled > 1000) {
				mode = MODE_MISSION;
			} else if ((int)packet.chan6_scaled < -1000) {
				mode = MODE_MANUEL;
			} else {
				mode = MODE_POSHOLD;
			}
			if ((int)packet.chan7_scaled > 1000) {
				mode = MODE_RTL;
			} else if ((int)packet.chan7_scaled < -1000) {
				mode = MODE_SETHOME;
			}
*/
			ModelData.radio[0] = (int)packet.chan1_scaled / 100.0;
			ModelData.radio[1] = (int)packet.chan2_scaled / 100.0;
			ModelData.radio[2] = (int)packet.chan3_scaled / 100.0;
			ModelData.radio[3] = (int)packet.chan4_scaled / 100.0;
			ModelData.radio[4] = (int)packet.chan5_scaled / 100.0;
			ModelData.radio[5] = (int)packet.chan6_scaled / 100.0;
			ModelData.radio[6] = (int)packet.chan7_scaled / 100.0;
			ModelData.radio[7] = (int)packet.chan8_scaled / 100.0;

			redraw_flag = 1;
			break;
		}
		case MAVLINK_MSG_ID_SCALED_PRESSURE: {
			mavlink_scaled_pressure_t packet;
			mavlink_msg_scaled_pressure_decode(msg, &packet);
//			SDL_Log("BAR;%i;%0.2f;%0.2f;%0.2f\n", time(0), packet.press_abs, packet.press_diff, packet.temperature / 100.0);
//			redraw_flag = 1;
			break;
		}
		case MAVLINK_MSG_ID_ATTITUDE: {
			mavlink_attitude_t packet;
			mavlink_msg_attitude_decode(msg, &packet);
			ModelData.roll = toDeg(packet.roll);
			ModelData.pitch = toDeg(packet.pitch);
			if (toDeg(packet.yaw) < 0.0) {
				ModelData.yaw = 360.0 + toDeg(packet.yaw);
			} else {
				ModelData.yaw = toDeg(packet.yaw);
			}
			mavlink_update_yaw = 1;
//			SDL_Log("ATT;%i;%0.2f;%0.2f;%0.2f\n", time(0), toDeg(packet.roll), toDeg(packet.pitch), toDeg(packet.yaw));

			redraw_flag = 1;
			break;
		}
		case MAVLINK_MSG_ID_SCALED_IMU: {
//			SDL_Log("SCALED_IMU\n");
			break;
		}
		case MAVLINK_MSG_ID_GPS_RAW_INT: {
			mavlink_gps_raw_int_t packet;
			mavlink_msg_gps_raw_int_decode(msg, &packet);
			if (packet.lat != 0.0) {
				GPS_found = 1;
				ModelData.p_lat = (float)packet.lat / 10000000.0;
				ModelData.p_long = (float)packet.lon / 10000000.0;
				ModelData.p_alt = (float)packet.alt / 1000.0;
				ModelData.speed = (float)packet.vel / 100.0;
				ModelData.numSat = packet.satellites_visible;
				ModelData.gpsfix = packet.fix_type;
				redraw_flag = 1;
			}
			break;
		}
		case MAVLINK_MSG_ID_RC_CHANNELS_RAW: {
//			SDL_Log("RC_CHANNELS_RAW\n");
			break;
		}
		case MAVLINK_MSG_ID_SERVO_OUTPUT_RAW: {
//			SDL_Log("SERVO_OUTPUT_RAW\n");
			break;
		}
		case MAVLINK_MSG_ID_SYS_STATUS: {
			mavlink_sys_status_t packet;
			mavlink_msg_sys_status_decode(msg, &packet);
//			SDL_Log("%0.1f %%, %0.3f V)\n", packet.load / 10.0, packet.voltage_battery / 1000.0);
			ModelData.voltage = packet.voltage_battery / 1000.0;
			ModelData.load = packet.load / 10.0;
			redraw_flag = 1;
			break;
		}
		case MAVLINK_MSG_ID_STATUSTEXT: {
			mavlink_statustext_t packet;
			mavlink_msg_statustext_decode(msg, &packet);
			SDL_Log("mavlink: ## %s ##\n", packet.text);
			sys_message((char *)packet.text);
			redraw_flag = 1;
			break;
		}
		case MAVLINK_MSG_ID_PARAM_VALUE: {
			mavlink_param_value_t packet;
			mavlink_msg_param_value_decode(msg, &packet);
			char var[101];
			uint16_t n1 = 0;
			uint16_t n2 = 0;
			for (n1 = 0; n1 < strlen(packet.param_id); n1++) {
				if (packet.param_id[n1] != 9 && packet.param_id[n1] != ' ' && packet.param_id[n1] != '\t') {
					var[n2++] = packet.param_id[n1];
				}
			}
			var[n2++] = 0;

//	MAV_VAR_FLOAT=0, /* 32 bit float | */
//	MAV_VAR_UINT8=1, /* 8 bit unsigned integer | */
//	MAV_VAR_INT8=2, /* 8 bit signed integer | */
//	MAV_VAR_UINT16=3, /* 16 bit unsigned integer | */
//	MAV_VAR_INT16=4, /* 16 bit signed integer | */
//	MAV_VAR_UINT32=5, /* 32 bit unsigned integer | */
//	MAV_VAR_INT32=6, /* 32 bit signed integer | */

			sprintf(sysmsg_str, "PARAM_VALUE (%i/%i): #%s# = %f (Type: %i)", packet.param_index + 1, packet.param_count, var, packet.param_value, packet.param_type);
			SDL_Log("mavlink: %s\n", sysmsg_str);
			sys_message(sysmsg_str);
			mavlink_maxparam = packet.param_count;
			mavlink_timeout = 0;

			mavlink_set_value(var, packet.param_value, packet.param_type, packet.param_index);

			if (packet.param_index + 1 == packet.param_count || packet.param_index % 10 == 0) {
				mavlink_param_xml_meta_load();
			}

			redraw_flag = 1;
			break;
		}
		case MAVLINK_MSG_ID_MISSION_COUNT: {
			mavlink_mission_count_t packet;
			mavlink_msg_mission_count_decode(msg, &packet);
			sprintf(sysmsg_str, "MISSION_COUNT: %i\n", packet.count);
			sys_message(sysmsg_str);
			mission_max = packet.count;
			if (mission_max > 0) {
				mavlink_msg_mission_request_pack(127, 0, &msg2, ModelData.sysid, ModelData.compid, 0);
				mavlink_send_message(&msg2);
			}
			redraw_flag = 1;
			break;
		}
		case MAVLINK_MSG_ID_MISSION_ACK: {
			SDL_Log("mavlink: Mission-Transfer ACK\n");
			break;
		}
		case MAVLINK_MSG_ID_MISSION_REQUEST: {
			mavlink_mission_request_t packet;
			mavlink_msg_mission_request_decode(msg, &packet);
			uint16_t id = packet.seq;
			uint16_t id2 = packet.seq;
			uint16_t type = 0;

			if (ModelData.teletype == TELETYPE_MEGAPIRATE_NG || ModelData.teletype == TELETYPE_ARDUPILOT) {
				if (id2 > 0) {
					id2 = id2 - 1;
				} else {
					SDL_Log("mavlink: WORKAROUND: first WP == HOME ?\n");
				}
			}

			sprintf(sysmsg_str, "sending Waypoint (%i): %s\n", id, WayPoints[1 + id2].name);
			sys_message(sysmsg_str);
			if (strcmp(WayPoints[1 + id2].command, "WAYPOINT") == 0) {
				SDL_Log("mavlink: Type: MAV_CMD_NAV_WAYPOINT\n");
				type = MAV_CMD_NAV_WAYPOINT;
			} else if (strcmp(WayPoints[1 + id2].command, "RTL") == 0) {
				SDL_Log("mavlink: Type: MAV_CMD_NAV_RETURN_TO_LAUNCH\n");
				type = MAV_CMD_NAV_RETURN_TO_LAUNCH;
			} else if (strcmp(WayPoints[1 + id2].command, "LAND") == 0) {
				SDL_Log("mavlink: Type: MAV_CMD_NAV_LAND\n");
				type = MAV_CMD_NAV_LAND;
			} else if (strcmp(WayPoints[1 + id2].command, "TAKEOFF") == 0) {
				SDL_Log("mavlink: Type: MAV_CMD_NAV_TAKEOFF\n");
				type = MAV_CMD_NAV_TAKEOFF;
			} else {
				SDL_Log("mavlink: Type: UNKNOWN\n");
				type = MAV_CMD_NAV_WAYPOINT;
			}

			sprintf(sysmsg_str, "SENDING MISSION_ITEM: %i: %f, %f, %f\n", id, WayPoints[1 + id2].p_lat, WayPoints[1 + id2].p_long, WayPoints[1 + id2].p_alt);
			SDL_Log("mavlink: %s\n", sysmsg_str);


			mavlink_msg_mission_item_pack(127, 0, &msg2, ModelData.sysid, ModelData.compid, id, 0, type, 0.0, 0.0, WayPoints[1 + id2].radius, WayPoints[1 + id2].wait, WayPoints[1 + id2].orbit, WayPoints[1 + id2].yaw, WayPoints[1 + id2].p_lat, WayPoints[1 + id2].p_long, WayPoints[1 + id2].p_alt);
			mavlink_send_message(&msg2);
/*
mavlink_msg_mission_item_pack(system_id, component_id, &msg , packet1.target_system , packet1.target_component , packet1.seq , packet1.frame , packet1.command , packet1.current , packet1.autocontinue , packet1.param1 , packet1.param2 , packet1.param3 , packet1.param4 , packet1.x , packet1.y , packet1.z );
float param1; ///< PARAM1 / For NAV command MISSIONs: Radius in which the MISSION is accepted as reached, in meters
float param2; ///< PARAM2 / For NAV command MISSIONs: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds
float param3; ///< PARAM3 / For LOITER command MISSIONs: Orbit to circle around the MISSION, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise.
float param4; ///< PARAM4 / For NAV and LOITER command MISSIONs: Yaw orientation in degrees, [0..360] 0 = NORTH
float x; ///< PARAM5 / local: x position, global: latitude
float y; ///< PARAM6 / y position: global: longitude
float z; ///< PARAM7 / z position: global: altitude
uint16_t seq; ///< Sequence
uint16_t command; ///< The scheduled action for the MISSION. see MAV_CMD in common.xml MAVLink specs
uint8_t target_system; ///< System ID
uint8_t target_component; ///< Component ID
uint8_t frame; ///< The coordinate system of the MISSION. see MAV_FRAME in mavlink_types.h
uint8_t current; ///< false:0, true:1
uint8_t autocontinue; ///< autocontinue to next wp
*/

			redraw_flag = 1;
			break;
		}
		case MAVLINK_MSG_ID_MISSION_ITEM: {
			mavlink_mission_item_t packet;
			mavlink_msg_mission_item_decode(msg, &packet);

			sprintf(sysmsg_str, "RECEIVED MISSION_ITEM: %i/%i: %f, %f, %f (%i)\n", packet.seq, mission_max, packet.x, packet.y, packet.z, packet.frame);
			SDL_Log("mavlink: %s\n", sysmsg_str);
			sys_message(sysmsg_str);

			if (packet.seq < mission_max - 1) {
				mavlink_msg_mission_request_pack(127, 0, &msg2, ModelData.sysid, ModelData.compid, packet.seq + 1);
				mavlink_send_message(&msg2);
			} else {
				mavlink_msg_mission_ack_pack(127, 0, &msg2, ModelData.sysid, ModelData.compid, 15);
				mavlink_send_message(&msg2);
			}

			if (ModelData.teletype == TELETYPE_MEGAPIRATE_NG || ModelData.teletype == TELETYPE_ARDUPILOT) {
				if (packet.seq > 0) {
					packet.seq = packet.seq - 1;
				} else {
					SDL_Log("mavlink: WORKAROUND: ignore first WP\n");
					break;
				}
			}

			SDL_Log("mavlink: getting WP(%i): %f, %f\n", packet.seq, packet.x, packet.y);

			switch (packet.command) {
				case MAV_CMD_NAV_WAYPOINT: {
					strcpy(WayPoints[1 + packet.seq].command, "WAYPOINT");
					break;
				}
				case MAV_CMD_NAV_LOITER_UNLIM: {
					strcpy(WayPoints[1 + packet.seq].command, "LOITER_UNLIM");
					break;
				}
				case MAV_CMD_NAV_LOITER_TURNS: {
					strcpy(WayPoints[1 + packet.seq].command, "LOITER_TURNS");
					break;
				}
				case MAV_CMD_NAV_LOITER_TIME: {
					strcpy(WayPoints[1 + packet.seq].command, "LOITER_TIME");
					break;
				}
				case MAV_CMD_NAV_RETURN_TO_LAUNCH: {
					strcpy(WayPoints[1 + packet.seq].command, "RTL");
					break;
				}
				case MAV_CMD_NAV_LAND: {
					strcpy(WayPoints[1 + packet.seq].command, "LAND");
					break;
				}
				case MAV_CMD_NAV_TAKEOFF: {
					strcpy(WayPoints[1 + packet.seq].command, "TAKEOFF");
					break;
				}
				default: {
					sprintf(WayPoints[1 + packet.seq].command, "CMD:%i", packet.command);
					break;
				}
			}

			if (packet.x == 0.0) {
				packet.x = 0.00001;
			}
			if (packet.y == 0.0) {
				packet.y = 0.00001;
			}
			if (packet.z == 0.0) {
				packet.z = 0.00001;
			}
			WayPoints[1 + packet.seq].p_lat = packet.x;
			WayPoints[1 + packet.seq].p_long = packet.y;
			WayPoints[1 + packet.seq].p_alt = packet.z;
			WayPoints[1 + packet.seq].yaw = packet.param4;
			sprintf(WayPoints[1 + packet.seq].name, "WP%i", packet.seq + 1);

			WayPoints[1 + packet.seq + 1].p_lat = 0.0;
			WayPoints[1 + packet.seq + 1].p_long = 0.0;
			WayPoints[1 + packet.seq + 1].p_alt = 0.0;
			WayPoints[1 + packet.seq + 1].yaw = 0.0;
			WayPoints[1 + packet.seq + 1].name[0] = 0;
			WayPoints[1 + packet.seq + 1].command[0] = 0;



/*
 float param1; ///< PARAM1 / For NAV command MISSIONs: Radius in which the MISSION is accepted as reached, in meters
 float param2; ///< PARAM2 / For NAV command MISSIONs: Time that the MAV should stay inside the PARAM1 radius before advancing, in milliseconds
 float param3; ///< PARAM3 / For LOITER command MISSIONs: Orbit to circle around the MISSION, in meters. If positive the orbit direction should be clockwise, if negative the orbit direction should be counter-clockwise.
 float param4; ///< PARAM4 / For NAV and LOITER command MISSIONs: Yaw orientation in degrees, [0..360] 0 = NORTH
 float x; ///< PARAM5 / local: x position, global: latitude
 float y; ///< PARAM6 / y position: global: longitude
 float z; ///< PARAM7 / z position: global: altitude
 uint16_t seq; ///< Sequence
 uint16_t command; ///< The scheduled action for the MISSION. see MAV_CMD in common.xml MAVLink specs
 uint8_t target_system; ///< System ID
 uint8_t target_component; ///< Component ID
 uint8_t frame; ///< The coordinate system of the MISSION. see MAV_FRAME in mavlink_types.h
 uint8_t current; ///< false:0, true:1
 uint8_t autocontinue; ///< autocontinue to next wp

GCS_MAVLink/message_definitions_v1.0/common.xml:               <entry value="0" name="MAV_FRAME_GLOBAL">
GCS_MAVLink/message_definitions_v1.0/common.xml:               <entry value="1" name="MAV_FRAME_LOCAL_NED">
GCS_MAVLink/message_definitions_v1.0/common.xml:               <entry value="2" name="MAV_FRAME_MISSION">
GCS_MAVLink/message_definitions_v1.0/common.xml:               <entry value="3" name="MAV_FRAME_GLOBAL_RELATIVE_ALT">
GCS_MAVLink/message_definitions_v1.0/common.xml:               <entry value="4" name="MAV_FRAME_LOCAL_ENU">
*/

			redraw_flag = 1;
			break;
		}
		case MAVLINK_MSG_ID_MISSION_CURRENT: {
			mavlink_mission_current_t packet;
			mavlink_msg_mission_current_decode(msg, &packet);
//			SDL_Log("mavlink: ## Active_WP %f ##\n", packet.seq);
			uav_active_waypoint = (uint8_t)packet.seq;
			break;
		}
		case MAVLINK_MSG_ID_RAW_IMU: {
			mavlink_raw_imu_t packet;
			mavlink_msg_raw_imu_decode(msg, &packet);
/*
			SDL_Log("## IMU_RAW_ACC_X %i ##\n", packet.xacc);
			SDL_Log("## IMU_RAW_ACC_Y %i ##\n", packet.yacc);
			SDL_Log("## IMU_RAW_ACC_Z %i ##\n", packet.zacc);
			SDL_Log("## IMU_RAW_GYRO_X %i ##\n", packet.xgyro);
			SDL_Log("## IMU_RAW_GYRO_Y %i ##\n", packet.ygyro);
			SDL_Log("## IMU_RAW_GYRO_Z %i ##\n", packet.zgyro);
			SDL_Log("## IMU_RAW_MAG_X %i ##\n", packet.xmag);
			SDL_Log("## IMU_RAW_MAG_Y %i ##\n", packet.ymag);
			SDL_Log("## IMU_RAW_MAG_Z %i ##\n", packet.zmag);
*/
			ModelData.acc_x = (float)packet.xacc / 1000.0;
			ModelData.acc_y = (float)packet.yacc / 1000.0;
			ModelData.acc_z = (float)packet.zacc / 1000.0;
			ModelData.gyro_x = (float)packet.zgyro;
			ModelData.gyro_y = (float)packet.zgyro;
			ModelData.gyro_z = (float)packet.zgyro;
			redraw_flag = 1;
			break;
		}
		case MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT: {
			mavlink_nav_controller_output_t packet;
			mavlink_msg_nav_controller_output_decode(msg, &packet);
/*
nav_roll
nav_pitch
alt_error
aspd_error
xtrack_error
nav_bearing
target_bearing
wp_dist
*/

			break;
		}
		case MAVLINK_MSG_ID_VFR_HUD: {
			mavlink_vfr_hud_t packet;
			mavlink_msg_vfr_hud_decode(msg, &packet);

//			SDL_Log("## pa %f ##\n", packet.airspeed);
//			SDL_Log("## pg %f ##\n", packet.groundspeed);
//			SDL_Log("## palt %f ##\n", packet.alt);

			if (GPS_found == 0) {
				ModelData.p_alt = packet.alt;
			}

//			SDL_Log("## pc %f ##\n", packet.climb);
//			SDL_Log("## ph %i ##\n", packet.heading);
//			SDL_Log("## pt %i ##\n", packet.throttle);

			break;
		}


		case MAVLINK_MSG_ID_RADIO: {
			mavlink_radio_t packet;
			mavlink_msg_radio_decode(msg, &packet);

			SDL_Log("mavlink: ## rxerrors %i ##\n", packet.rxerrors);
			SDL_Log("mavlink: ## fixed %i ##\n", packet.fixed);
			SDL_Log("mavlink: ## rssi %i ##\n", packet.rssi);
			SDL_Log("mavlink: ## remrssi %i ##\n", packet.remrssi);
			SDL_Log("mavlink: ## txbuf %i ##\n", packet.txbuf);
			SDL_Log("mavlink: ## noise %i ##\n", packet.noise);
			SDL_Log("mavlink: ## remnoise %i ##\n", packet.remnoise);

			break;
		}



		default: {
//			SDL_Log("	## MSG_ID == %i ##\n", msg->msgid);
			break;
		}
	}
}
示例#29
0
static void parseGNS(un8 index, char *value)
{
	un8 i, fix;

	if (*value == 0)
		return;

	switch (index)
	{
	case GPS_GNS_MODE:
		/* One character per system, N: no fix */
		fix = 0;
		for (i = 0; value[i] != 0; i++) {
			fix |= (value[i] != 'N');
		}
		veVariantUn8(&local.fix, fix);
		return;

	case GPS_GNS_LATITUDE:
		errno = 0;
		veVariantFloat(&local.latitude, toDeg((float)atof(value)));
		if (errno)
			veVariantInvalidate(&local.latitude);
		return;

	case GPS_GNS_LAT_NORTH_SOUTH:
		/* North is positive, south is negative */
		if (value[0] == 'S')
			local.latitude.value.Float *= -1;
		return;

	case GPS_GNS_LONGITUDE:
		errno = 0;
		veVariantFloat(&local.longitude, toDeg((float)atof(value)));
		if (errno)
			veVariantInvalidate(&local.longitude);
		return;

	case GPS_GNS_LONG_EAST_WEST:
		/* East is positive, west is negative */
		if (value[0] == 'W')
			local.longitude.value.Float *= -1;
		return;

	case GPS_GNS_UTC_TIME:
		memset(&local.time, 0, sizeof(struct tm));
		local.time.tm_hour = a2b(*value++) * 10;
		local.time.tm_hour += a2b(*value++);
		local.time.tm_min = a2b(*value++) * 10;
		local.time.tm_min += a2b(*value++);
		local.time.tm_sec = a2b(*value++ ) * 10;
		local.time.tm_sec += a2b(*value++);
		return;

	case GPS_GNS_ALTITUDE:
		errno = 0;
		veVariantFloat(&local.altitude, (float)atof(value));
		if (errno)
			veVariantInvalidate(&local.altitude);
		return;

	case GPS_GNS_NR_OF_SATELITES:
		errno = 0;
		veVariantUn8(&local.nrOfSats, (un8)atol(value));
		if (errno)
			veVariantInvalidate(&local.nrOfSats);
		return;
	}
}