深蓝学院-多传感器融合定位第五章作业

本文探讨了一种新颖的加速度计校准方法,无需手动推导雅可比矩阵,通过自动求导和解析式求导技术来计算残差对内参的敏感度。内容涉及雅克比矩阵推导、利用Ceres库的标定过程,以及MultiPosAccResidual类在解析求导中的应用。

**

1.不需要转台标定方法推导加速度计对应残差对加速度内参的雅克比

2.使用自动求导完成标定

3.使用解析式求导完成标定

**
1.雅克比推导
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.使用自动求导完成标定
修改三处TODO

CalibratedTriad_<_T2> calib_triad( 
  //
  // TODO: implement lower triad model here
  //
  // mis_yz, mis_zy, mis_zx:
  _T2(0), _T2(0), _T2(0),
  // mis_xz, mis_xy, mis_yx:
  params[0], params[1], params[2],
  //    s_x,    s_y,    s_z:
  params[3], params[4], params[5], 
  //    b_x,    b_y,    b_z: 
  params[6], params[7], params[8] 
);


// TODO: implement lower triad model here
//
acc_calib_params[0] = init_acc_calib_.misXZ();
acc_calib_params[1] = init_acc_calib_.misXY();
acc_calib_params[2] = init_acc_calib_.misYX();


acc_calib_ = CalibratedTriad_<_T>( 
//
// TODO: implement lower triad model here
// 
0,0,0,
min_cost_calib_params[0],
min_cost_calib_params[1],
min_cost_calib_params[2],
min_cost_calib_params[3],
min_cost_calib_params[4],
min_cost_calib_params[5],
min_cost_calib_params[6],
min_cost_calib_params[7],
min_cost_calib_params[8] 
);

标定结果
在这里插入图片描述
在这里插入图片描述

3.解析求导
写一个新的MultiPosAccResidual 类

template<typename _T1>
class MultiPosAccResidual  : public ceres::SizedCostFunction<1,9>
{
  public:
    MultiPosAccResidual(const _T1 &g_mag, const Eigen::Matrix< _T1, 3 , 1> &sample 
    ) : g_mag_(g_mag), sample_(sample){}
   
   virtual ~MultiPosAccResidual() {}
   virtual bool Evaluate(double const* const* parameters,double* residuals,double** jacobians) const 
	{
    Eigen::Matrix<double, 3, 1> raw_samp( 
      double(sample_(0)), 
      double(sample_(1)), 
      double(sample_(2)) 
    );
    /* Apply undistortion transform to accel measurements
         mis_mat_ <<  _T(1)   , -mis_yz  ,  mis_zy  ,
                       mis_xz ,  _T(1)   , -mis_zx  ,  
                      -mis_xy ,  mis_yx  ,  _T(1)   ; */
    CalibratedTriad_<double> calib_triad( 
      //
      // TODO: implement lower triad model here
      //
      // mis_yz, mis_zy, mis_zx:
      double(0), double(0), double(0),
      // mis_xz, mis_xy, mis_yx:
      parameters[0][0], parameters[0][1], parameters[0][2],
      //    s_x,    s_y,    s_z:
      parameters[0][3], parameters[0][4], parameters[0][5], 
      //    b_x,    b_y,    b_z: 
      parameters[0][6], parameters[0][7], parameters[0][8] 
    );
    
    // apply undistortion transform:
    Eigen::Matrix< double, 3 , 1> calib_samp = calib_triad.unbiasNormalize( raw_samp );
    
    residuals[0] = g_mag_*g_mag_ - calib_samp.squaredNorm();
    // residuals[0] = g_mag_- calib_samp.norm();

		if(jacobians != NULL)
		{
			if(jacobians[0] != NULL)
			{ 
        double S1 = parameters[0][0];
        double S2 = parameters[0][1];
        double S3 = parameters[0][2];

        double K1 = parameters[0][3];
        double K2 = parameters[0][4];
        double K3 = parameters[0][5];

        double b1 = parameters[0][6];
        double b2 = parameters[0][7];
        double b3 = parameters[0][8];

        double A1 = sample_(0);
        double A2 = sample_(1);
        double A3 = sample_(2);
        
        // 向量对向量的解析版:
        Eigen::MatrixXd a(3, 1);
        
         a << K1*(A1-b1), -S1*K1*(A1-b1)+K2*(A2-b2), -S2*K1*(A1-b1)-S3*K2*(A2-b2)+K3*(A3-b3);
        Eigen::MatrixXd da_dTheta(3, 9);
        da_dTheta << 0, 0, 0, A1-b1, 0, 0, -K1, 0, 0, 
                    -K1*(A1-b1), 0, 0, -S1*(A1-b1), A2-b2, 0, S1*K1, -K2, 0,
                    0, -K1*(A1-b1), -K2*(A2-b2), -S2*(A1-b1), -S3*(A2-b2), A3-b3, S2*K1, S3*K2, -K3;

        Eigen::Map<Eigen::Matrix<double, 1, 9, Eigen::RowMajor> > Jacob(jacobians[0]);
        Jacob.setZero();

        Jacob = - 2 * calib_samp.transpose() * da_dTheta;
                  
			}
		}

		return true;
	}

static ceres::CostFunction* Create ( const _T1 &g_mag, const Eigen::Matrix< _T1, 3 , 1> &sample )
  {
    return ( new MultiPosAccResidual<_T1>( g_mag, sample ) );
  }
protected:
	const _T1 g_mag_;
  const Eigen::Matrix< _T1, 3 , 1> sample_;
};

修改第二处

 inline _T misYZ() const { return -mis_mat_(0,1); };
  inline _T misZY() const { return -mis_mat_(0,2); }; //加-
  inline _T misZX() const { return -mis_mat_(1,2); };
  inline _T misXZ() const { return -mis_mat_(1,0); };//加-
  inline _T misXY() const { return -mis_mat_(2,0); };
  inline _T misYX() const { return -mis_mat_(2,1); };//加-

  inline _T scaleX() const { return scale_mat_(0,0); };
  inline _T scaleY() const { return scale_mat_(1,1); };
  inline _T scaleZ() const { return scale_mat_(2,2); };
      
  inline _T biasX() const { return bias_vec_(0); };
  inline _T biasY() const { return bias_vec_(1); };
  inline _T biasZ() const { return bias_vec_(2); };

修改第三处

  mis_mat_ <<  _T(1)   , -mis_yz  ,  -mis_zy  ,
                -mis_xz ,  _T(1)   , -mis_zx  ,  
               -mis_xy , -mis_yx  ,  _T(1)   ;          

标定结果
在这里插入图片描述
在这里插入图片描述

### 深蓝学院多传感器融合第五章资料 #### 5.1 惯性器件误差分析概述 惯性测量单元(IMU)作为自动驾驶车辆中的重要组成部分,在提供高精度位置估计方面起着至关重要的作用。然而,由于制造工艺、环境因素以及长期运行的影响,IMU不可避免地存在各种类型的误差[^1]。 这些误差可以分为两大类:静态误差和动态误差。静态误差主要包括偏置、比例因子失配等;而动态误差则涉及随机游走、角速度噪声密度等问题。了解并掌握这些误差特性对于提高基于IMU的姿态解算精度至关重要。 #### 5.2 常见惯性器件误差源解析 具体来说,常见的惯性器件误差来源有以下几个方面: - **加速度计零位漂移**:即使在静止状态下,输出也并非绝对为零; - **陀螺仪常值偏差**:当设备处于稳定状态时,理论上应保持恒定的角度变化率,但实际上会有微小波动; - **温度敏感度影响**:随着工作环境中温度的变化,内部参数会发生相应改变,进而引起读数不准; - **振动干扰效应**:外部机械震动会通过结构传递给传感元件,造成额外的扰动信号叠加到原始数据之上。 为了有效应对上述挑战,研究者们提出了多种校准算法和技术手段来降低或消除各类误差带来的负面影响。 ```python import numpy as np def calibrate_imu(sensor_data, temperature_coefficients): """ 对IMU数据进行温度补偿校正 参数: sensor_data (np.array): IMU原始采集的数据集 temperature_coefficients (dict): 各种温度系数字典 返回: calibrated_data (np.array): 经过处理后的更精确的结果数组 """ # 实现具体的校准逻辑... pass ``` #### 5.3 应用实例——基于Kalman滤波器的状态估计优化 针对实际应用场景中存在的复杂情况,采用扩展卡尔曼滤波(EKF)方法能够较好地解决非线性系统的最优估计问题。通过对预测模型与观测方程的设计,EKF可以在一定程度上抑制由IMU引起的累积误差增长趋势,从而获得更加可靠的导航解决方案。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值