Ejemplo n.º 1
0
 Matrix & Matrix::operator /= (const Matrix &p)
 {
     Matrix tmp(p);
     tmp.inverse();
     *this = MulMatrix(*this, tmp);
     return *this;
 }
Ejemplo n.º 2
0
/****************************************************************
 *函 数 名: DoEKF()
 *参    数:
 *               pModel model: 需要进行EKF滤波的模型
 *         pModelParam mParam: 状态量、观测量及估计值保存地址
 *         pEKFParam ekfParam: KF滤波所需要的参数
 *
 *功    能:对model所示的模型进行EKF滤波
 *          考虑了Pkk-1和Pk为对称矩阵,当求解这两项时的算法和
 *          普通矩阵的乘法不一样。
 *
 *返 回 值:
 *          成功: OK
 *          输入输出指针为空:ERR_MEM_NONE
 *
 *作    者:申文斌
 *完成日期:2011-3-22
 ****************************************************************/
int DoEKF(pModel model, pModelParam mParam, pEKFParam ekfParam)
{
    const double T = 0.033;      // 采样周期
    int i, j, k;                // 循环变量

    // 以下为滤波过程中要用的临时变量
    // 这里统一用一维数组表示矩阵,为了复用地址,这里按最大需求开辟
    // 由于在没有操作系统的ARM7上不可以动态开辟空间,所以这里只能用
    // 这种比较笨的方法了。
    double fx[MAX_STATE];    // 保存状态方程计算值
    double Xhatkk_1[MAX_STATE];
    double Hk[MAX_OBS * MAX_STATE];            // 保存观测矩阵Hk
    double Phikk_1[MAX_STATE * MAX_STATE];
    double tmp[MAX_STATE * MAX_STATE];
    double Pkk_1[MAX_STATE * MAX_STATE];
    double Kk[MAX_STATE * MAX_OBS];
    double PxHk[MAX_STATE * MAX_OBS];
    double TranHk[MAX_STATE * MAX_OBS];
    double KkTmp[MAX_OBS * MAX_OBS];
    double h[MAX_OBS];
    double KkxHk[MAX_STATE * MAX_STATE];

    //double TranPhikk_1[MAX_STATE * MAX_STATE];
      
#ifdef __DEBUG__
    if ( (model == NULL) || (mParam == NULL) || (ekfParam == NULL) )
    {
        return ERR_MEM_NONE;        // 输入输出指针为空
    }
#endif

    if (*ekfParam->isFirst == 1)        // 第一次执行滤波
    {
        
        *ekfParam->isFirst = 0;
        // 将传入的状态直接当作估计值
        for (i=0; i<mParam->lenState; i++)
        {
            ekfParam->preEst[i] = mParam->state[i];
            mParam->est[i] = mParam->state[i];
        }
        return OK;
    }//if

// EKF滤波过程
   
    
    // 进一步滤波Xhatkk_1 = Xhatk_1 + T * fxu(Xhatk_1) 式(3-60)
    model->fxu(ekfParam->preEst, mParam->othParam, fx);
    for (i=0; i<mParam->lenState; i++)
    {
        fx[i] *= T;
    }
    AddMatrix(ekfParam->preEst, fx, Xhatkk_1,  mParam->lenState, 1);

    if ( model->fxu == QGFxu)      // 如果状态方程为四元数的则需要归一Q
    {
        Norm(Xhatkk_1);       // 归一Q
    }

    // 求得观测矩阵对状态的求导,Hk被用的大小为mParam->lenObs * mParam->lenState
    model->hxDot(Xhatkk_1, Hk); 

    // 状态转移矩阵,离散化导致矩状态转移阵前面需要乘以T
    // Phikk_1被用的大小为mParam->lenState * mParam->lenState
    model->fxDot(ekfParam->preEst, mParam->othParam, Phikk_1);
    for (i=0; i<mParam->lenState; i++)
    {
        for (j=0; j<mParam->lenState; j++)
        {
            Phikk_1[i * mParam->lenState + j] *= T;
        }
    }

    // 预测误差方差矩阵Pkk_1
    // 计算Pkk_1,这里考虑Pkk_1为对称矩阵
    // 中间变量tmp用到的大小为mParam->lenState * mParam->lenState
    MulMatrix(Phikk_1, ekfParam->Pk, tmp,
              mParam->lenState, mParam->lenState, mParam->lenState);
    // 这里两矩阵相乘为对称矩阵,所以可以简化
    // 初始化Pkk_1,被用到的大小为mParam->lenState * mParam->lenState
    for (i=0; i<mParam->lenState; i++)
    {
        for (j=0; j<=i; j++)
        {
            Pkk_1[i * mParam->lenState + j] = 0.0;    // 将输出矩阵下三角初始化为0
        }
    }
    for (i=0; i<mParam->lenState; i++)        // 矩阵相乘
    {
        for (j=0; j<=i; j++)
        {
            for (k=0; k<mParam->lenState; k++)
            {
                // 这里乘以Phikk_1的转置
                Pkk_1[i * mParam->lenState + j] += 
                    tmp[i * mParam->lenState + k] *  Phikk_1[j * mParam->lenState + k];
            }
            Pkk_1[j * mParam->lenState + i] = Pkk_1[i * mParam->lenState + j];        // 对称的元素
        }
    }

    for (i=0; i<mParam->lenState; i++)
    {
        // 加上Q阵,这里只要加上对角线上的元素即可
        Pkk_1[i * mParam->lenState + i] += ekfParam->Q[i];
    }

    // 求取滤波增益矩阵 式(3-62)
    TranMatrix(Hk, TranHk, mParam->lenObs, mParam->lenState);
    // PxHk被用到的大小为 mParam->lenState * mParam->lenObs
    MulMatrix(Pkk_1, TranHk, PxHk, mParam->lenState, mParam->lenState, mParam->lenObs);
    // KkTmp被用到的大小为mParam->lenObs * mParam->lenObs
    MulMatrix(Hk, PxHk, KkTmp, mParam->lenObs, mParam->lenState, mParam->lenObs);

    // Hk*Pkk_1*Hk' + R,考虑到R为对角矩阵,所以不用按一般相乘计算
    // 只需要加对角线元素即可
    for (i=0; i<mParam->lenObs; i++)
    {
        KkTmp[i * mParam->lenObs + i] += ekfParam->R[i];
    }

    // Hk*Pkk_1*Hk' + R 对称矩阵
    if ( InvSymMtrx(KkTmp, KkTmp, mParam->lenObs) != OK )
    {
        // 如果Hk*Pkk_1*Hk' + R奇异无法求逆
        // 则将传入的状态直接当作估计值
        for (i=0; i<mParam->lenState; i++)
        {
            ekfParam->preEst[i] = mParam->state[i];
            mParam->est[i] = mParam->state[i];
        }
        return OK;
    }

    // Kk被用到的大小为mParam->lenState * mParam->lenObs
    MulMatrix(PxHk, KkTmp, Kk, mParam->lenState, mParam->lenObs, mParam->lenObs);

    // 状态估计
    model->hx(Xhatkk_1, h);
    SubMatrix( mParam->obs, h, h, mParam->lenObs, 1);        // h = obs - hx(Xhatkk_1)
     //----------------------- syc 2011.11.14------------------------------//
   if ( model->fxu == QGFxu)     // 如果状态方程为四元数的则需要调整角度
    {
      for(int i=0;i<3;i++)
      {
        if(h[i]>PI)
          h[i]-=2.0*PI;
        else
          if(h[i]<-PI)
            h[i]+=2.0*PI; 
      }
    }
    //------------------------------------------------------------------//
    MulMatrix(Kk, h, ekfParam->preEst, mParam->lenState, mParam->lenObs, 1);
    // ekfParam->preEst是本次求得的滤波值
    AddMatrix(ekfParam->preEst, Xhatkk_1, ekfParam->preEst, mParam->lenState, 1);

    if ( model->fxu == QGFxu)     // 如果状态方程为四元数的则需要归一Q
    {
        Norm(ekfParam->preEst);   // 归一Q
    }

    // 滤波方差矩阵
    // Kk被用到的大小为mParam->lenState * mParam->lenState
    MulMatrix(Kk, Hk, KkxHk, mParam->lenState, mParam->lenObs, mParam->lenState);
    for (i=0; i<mParam->lenState; i++)
    {
        for (j=0; j<mParam->lenState; j++)
        {
            KkxHk[i * mParam->lenState + j] = (i == j) - KkxHk[i * mParam->lenState + j];
        }
    }
   // MulMatrix(KkxHk, Pkk_1, ekfParam->Pk, mParam->lenState, mParam->lenState, mParam->lenState);
    for (i=0; i<mParam->lenState; i++)
    {
        for (j=0; j<=i; j++)
        {
            ekfParam->Pk[i*mParam->lenState + j] = 0.0;    // Pk下三角矩阵为零
        }
    }

    for (i=0; i<mParam->lenState; i++)        // 矩阵相乘
    {
        for (j=0; j<=i; j++)
        {
            for (k=0; k<mParam->lenState; k++)
            {
                ekfParam->Pk[i*mParam->lenState + j] +=
                    KkxHk[i * mParam->lenState + k] *  Pkk_1[k * mParam->lenState + j];
            }
            // 对称的元素
            ekfParam->Pk[j*mParam->lenState + i] = ekfParam->Pk[i*mParam->lenState + j];
        }
    }

    // 将结果复制到目的地址
    for (i=0; i<mParam->lenState; i++)
    {
        mParam->est[i] = ekfParam->preEst[i];
    }

    return OK;
}
Ejemplo n.º 3
0
 Matrix & Matrix::operator *= (const Matrix &p)
 {
     *this = MulMatrix(*this, p);
     return *this;
 }