搜索
bottom↓
回复: 4

MWC的姿态解算求解

[复制链接]

出0入0汤圆

发表于 2015-8-14 14:25:16 | 显示全部楼层 |阅读模式
最近在学习一个德国的BruGi的开源两轴云台的代码,他在姿态解算上参考了MWC的旋转矩阵计算方法。以下是部分代码:

void initIMU() {

  // resolutionDevider=131, scale = 0.000133
  // 102us
  gyroScale =  1.0 / resolutionDevider / 180.0 * 3.14159265359 * DT_FLOAT;
  
  // initialize complementary filter timw constant
  setACCtc(config.accTimeConstant);

  accMag = ACC_1G*ACC_1G; // magnitude = 1G initially

  // initialize coordinate system in EstG
  EstG.V.X = 0;
  EstG.V.Y = 0;
  EstG.V.Z = ACC_1G;

}

// Rotate Estimated vector(s) with small angle approximation, according to the gyro data
// needs angle in radian units !
inline void rotateV(struct fp_vector *v,float* delta) {
  fp_vector v_tmp = *v;
  v->Z -= delta[ROLL]  * v_tmp.X + delta[PITCH] * v_tmp.Y;
  v->X += delta[ROLL]  * v_tmp.Z - delta[YAW]   * v_tmp.Y;
  v->Y += delta[PITCH] * v_tmp.Z + delta[YAW]   * v_tmp.X;
}

void readGyros() {
  int16_t axisRot[3];
  char idx;
  // 414 us

  // read gyros
  mpu.getRotation(&axisRot[0], &axisRot[1], &axisRot[2]);
  axisRot[0] -= config.gyrOffsetX;
  axisRot[1] -= config.gyrOffsetY;
  axisRot[2] -= config.gyrOffsetZ;
  
  idx = sensorDef.Gyro[0].idx;
  gyroADC[ROLL] = axisRot[idx];
  gyroADC[ROLL] *= sensorDef.Gyro[0].dir;

  idx = sensorDef.Gyro[1].idx;
  gyroADC[PITCH] = axisRot[idx];
  gyroADC[PITCH] *= sensorDef.Gyro[1].dir;

  idx = sensorDef.Gyro[2].idx;
  gyroADC[YAW] = axisRot[idx];  
  gyroADC[YAW] *= sensorDef.Gyro[2].dir;
  
}

// get acceleration for 3-axis
void readACCs()
{
  int16_t rawVal[3];
  int16_t devVal[3];
  
  mpu.getAcceleration(
    &rawVal[0],
    &rawVal[1],
    &rawVal[2]
    );
   
  devVal[sensorDef.Acc[ROLL].idx]  = rawVal[0] - config.accOffsetX;
  devVal[sensorDef.Acc[PITCH].idx] = rawVal[1] - config.accOffsetY;
  devVal[sensorDef.Acc[YAW].idx]   = rawVal[2] - config.accOffsetZ;
  
  for (int8_t axis = 0; axis < 3; axis++) {
    accADC[axis] = devVal[axis]*sensorDef.Acc[axis].dir;
  }
}


void updateGyroAttitude(){
  uint8_t axis;
  
  float deltaGyroAngle[3];

  // 43 us
  for (axis = 0; axis < 3; axis++) {
    deltaGyroAngle[axis] = gyroADC[axis]  * gyroScale;
  }
  
  // 111 us
  rotateV(&EstG.V,deltaGyroAngle);

}

void updateACC(){
  uint8_t axis;
  float accMagSum = 0;

  for (axis = 0; axis < 3; axis++) {
    accLPF[axis] = accADC[axis];
    accMagSum += accLPF[axis]*accLPF[axis];
  }

  // 24 us
  accMagSum = accMagSum*100.0/(ACC_1G*ACC_1G);
  utilLP_float(&accMag, accMagSum, (1.0f/ACC_LPF_FACTOR));
}


void updateACCAttitude(){
  uint8_t axis;
  
  // 80 us
  // Apply complimentary filter (Gyro drift correction)
  // If accel magnitude >1.4G or <0.6G and ACC vector outside of the limit range => we neutralize the effect of accelerometers in the angle estimation.
  // To do that, we just skip filter, as EstV already rotated by Gyro
  if (( 36 < accMag && accMag < 196 ) || disableAccGtest) {
    for (axis = 0; axis < 3; axis++) {
      //utilLP_float(&EstG.A[axis], accLPF[axis], AccComplFilterConst);
      EstG.A[axis] = EstG.A[axis] * (1.0 - AccComplFilterConst) + accLPF[axis] * AccComplFilterConst; // note: this is different from MultiWii (wrong brackets postion in MultiWii ??.
    }
  }
}


void getAttiduteAngles() {

  // attitude of the estimated vector  
  // 200us
  angle[ROLL]  = angleOffsetRoll +  Rajan_FastArcTan2_deg1000(EstG.V.X , sqrt(EstG.V.Z*EstG.V.Z+EstG.V.Y*EstG.V.Y));
  // 142 us
  angle[PITCH] = angleOffsetPitch + Rajan_FastArcTan2_deg1000(EstG.V.Y , EstG.V.Z);

}

计算的原理可以理解,用陀螺仪积分和旋转矩阵求重力加速度分量,然后和加速度计测的加速度做互补滤波。但问题来了,按照代码中对EstG.V的赋值为(0,0,1g),如果用这个旋转矩阵算的话,不管IMU怎么翻转,算出来的Z轴的值都会是1g的值。因为 v->Z -= delta[ROLL]  * v_tmp.X + delta[PITCH] * v_tmp.Y;而X和Y都是初始为0。
所以现在就很迷茫,是我对代码的理解有误,还是代码中对EstG.V的值赋错了,如果是值错了,那EstG.V应该是什么呢。

同时附上MWC的部分代码,里面也用上了EstG,但MWC里反而没有对EstG赋值,所以弄的我更糊涂了。

typedef struct fp_vector {               
  float X,Y,Z;               
} t_fp_vector_def;

typedef union {               
  float A[3];               
  t_fp_vector_def V;               
} t_fp_vector;

// Rotate Estimated vector(s) with small angle approximation, according to the gyro data
void rotateV(struct fp_vector *v,float* delta) {
  fp_vector v_tmp = *v;
  v->Z -= delta[ROLL]  * v_tmp.X + delta[PITCH] * v_tmp.Y;
  v->X += delta[ROLL]  * v_tmp.Z - delta[YAW]   * v_tmp.Y;
  v->Y += delta[PITCH] * v_tmp.Z + delta[YAW]   * v_tmp.X;
}

static t_fp_vector EstG;

void getEstimatedAttitude(){
  uint8_t axis;
  int32_t accMag = 0;
  float scale, deltaGyroAngle[3];
  uint8_t validAcc;
  static uint16_t previousT;
  uint16_t currentT = micros();

  scale = (currentT - previousT) * GYRO_SCALE;
  previousT = currentT;

  // Initialization
  for (axis = 0; axis < 3; axis++) {
    deltaGyroAngle[axis] = imu.gyroADC[axis]  * scale;

    accLPF32[axis]    -= accLPF32[axis]>>ACC_LPF_FACTOR;
    accLPF32[axis]    += imu.accADC[axis];
    imu.accSmooth[axis]    = accLPF32[axis]>>ACC_LPF_FACTOR;

    accMag += (int32_t)imu.accSmooth[axis]*imu.accSmooth[axis] ;
  }

  rotateV(&EstG.V,deltaGyroAngle);

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2015-8-15 13:15:33 | 显示全部楼层
求源码  最近在看 apm的飞控源码  有点像

出0入0汤圆

 楼主| 发表于 2015-8-17 08:43:30 | 显示全部楼层
大风吹不倒 发表于 2015-8-15 13:15
求源码  最近在看 apm的飞控源码  有点像

你qq多少,我加你,发给你

出0入0汤圆

发表于 2015-8-17 10:53:29 | 显示全部楼层
forwinry 发表于 2015-8-17 08:43
你qq多少,我加你,发给你

2663498351

出0入0汤圆

发表于 2016-4-4 20:46:24 | 显示全部楼层
304193423 楼主 这个qq想加你请教问题
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 19:12

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表