1.程序运行
cd ~/OB_GINS
./bin/ob_gins ./dataset/ob_gins.yaml
2.参数文件详解
imufile: "dataset/ADIS16465.txt"
gnssfile: "dataset/GNSS_RTK.pos"
outputpath: "dataset/"
windows: 30
starttime: 357473
endtime: 359090
num_iterations: 20
is_outlier_culling: false
initvel: [ 0, 0, 0 ]
initatt: [ 0, 0, 276 ]
initgb: [ 0, 0, 0 ]
initab: [ 0, 0, 0 ]
imudatalen: 8
imudatarate: 200
isearth: true
antlever: [ -0.073, 0.302, 0.087 ]
odolever: [ -0.64, -0.628, 2.122 ]
bodyangle: [ 0, -0.30, -1.09 ]
odometer:
isuseodo: true
std: [ 0.05, 0.05, 0.05 ]
srw: 100
imumodel:
arw: 0.1
vrw: 0.1
gbstd: 25.0
abstd: 200.0
corrtime: 1.0
isuseoutage: true
outagetime: 357900
outagelen: 60
outageperiod: 150
gnssthreshold: 0.2
3.主程序
3.1 看主程序之前首先看编译文件(cmakelist),其他的先不用看主要看可执行文件的生成以及包含的相关代码文件。
file(GLOB_RECURSE SOURCE
src/ob_gins.cc
src/fileio/fileloader.cc
src/fileio/filesaver.cc
src/preintegration/preintegration_base.cc
src/preintegration/preintegration_normal.cc
src/preintegration/preintegration_earth.cc
src/preintegration/preintegration_odo.cc
src/preintegration/preintegration_earth_odo.cc)
include_directories(${PROJECT_SOURCE_DIR})
add_executable(${PROJECT_NAME} ${SOURCE})
注:如果想查看具体的变量名字可以使用下述语句:
message("变量名" ${PROJECT_NAME} )
3.2主程序ob_gins.cc
OB_GINS代码结构清晰,注释详细,因此本节主要对代码整体结构进行阐述,随后在此基础讲解具体程序实现思路。
主程序包含上述四个函数,具体含义如注释所示。代码的阅读直接从主函数开始,顺序阅读即可。
main()
{
1.数据参数预处理
主要功能:读取参数文件,在OB_GINS中读取了,滑动窗口次数、处理数据时间段、优化迭代次数、初始速度、位置、IMU相关参数等。
2.程序初始化
主要作用:通过上一步读取的数据进行系统初始化。这个初始化详细讲一下
(1)设置站心坐标系(北东地)原点,更新当地重力参数。
(2)设置预积分选项:是否添加里程计,是否考虑地球自转
(3)初始状态(当前状态)设置:北东地位置、姿态、速度、加速度计陀螺仪偏置、安装角。
3.循环处理数据
(1)imu预积分
(2)利用GNSS数据进行优化
4.结果输出
}
3.3IMU预积分
preintegrationlist.back()->addNewImu(imu_cur);
void PreintegrationBase::addNewImu(const IMU &imu) {
imu_buffer_.push_back(imu);
integrationProcess(imu_buffer_.size() - 1);
}
integrationProcess()函数有很多个,具体选用与预积分选项设置相关,分为一下四种:
//imu预积分
if (options == PREINTEGRATION_NORMAL) {
preintegration = std::make_shared<PreintegrationNormal>(parameters, imu0, state);
}
// imu和里程计预积分
else if (options == PREINTEGRATION_ODO) {
preintegration = std::make_shared<PreintegrationOdo>(parameters, imu0, state);
}
// 考虑地球自转的imu预积分
else if (options == PREINTEGRATION_EARTH) {
preintegration = std::make_shared<PreintegrationEarth>(parameters, imu0, state);
}
// 考虑地球自转的IMU和里程计的预积分
else if (options == PREINTEGRATION_EARTH_ODO) {
preintegration = std::make_shared<PreintegrationEarthOdo>(parameters, imu0, state);
}
不考虑地球自转的预积分
// imu预积分
void PreintegrationNormal::integrationProcess(unsigned long index) {
IMU imu_pre = compensationBias(imu_buffer_[index - 1]);//获取零偏补偿后的速度,姿态增量
IMU imu_cur = compensationBias(imu_buffer_[index]);
// 预积分
integration(imu_pre, imu_cur);
// 更新系统状态雅克比和协方差矩阵
updateJacobianAndCovariance(imu_pre, imu_cur);
}
void PreintegrationBase::integration(const IMU &imu_pre, const IMU &imu_cur) {
double dt = imu_cur.dt;
delta_time_ += dt;
end_time_ = imu_cur.time;
current_state_.time = imu_cur.time;
Vector3d dvfb = imu_cur.dvel + 0.5 * imu_cur.dtheta.cross(imu_cur.dvel) +
1.0 / 12.0 * (imu_pre.dtheta.cross(imu_cur.dvel) + imu_pre.dvel.cross(imu_cur.dtheta));
Vector3d dvel = current_state_.q.toRotationMatrix() * dvfb + gravity_ * dt;
current_state_.p += dt * current_state_.v + 0.5 * dt * dvel;
current_state_.v += dvel;
Vector3d dtheta = imu_cur.dtheta + 1.0 / 12.0 * imu_pre.dtheta.cross(imu_cur.dtheta);
current_state_.q *= Rotation::rotvec2quaternion(dtheta);
current_state_.q.normalize();
dvel = delta_state_.q.toRotationMatrix() * dvfb;
delta_state_.p += dt * delta_state_.v + 0.5 * dt * dvel;
delta_state_.v += dvel;
delta_state_.q *= Rotation::rotvec2quaternion(dtheta);
delta_state_.q.normalize();
}
机械编排,OB_GINS对于旋转误差和划桨误差处理方法是:“单子样+前一周期的方法”:
速度增量:
注:速度增量计算中,有害加速度可以分为两项1.载体运动和地球自转引起的哥氏加速度、载体运动造成的对地向心加速度和重力加速度。不考虑地球自转的预计积分中只考虑了重力加速度,(补充考虑地球自转的预积分中考虑了在此基础上考虑了哥氏加速度)
姿态增量:
注意这个并未考虑地球自转的影响,因此代码姿态更新时并未加入C^nn。
考虑地球自转的IMU预积分:
void PreintegrationEarth::integrationProcess(unsigned long index) {
IMU imu_pre = compensationBias(imu_buffer_[index - 1]);
IMU imu_cur = compensationBias(imu_buffer_[index]);
double dt = imu_cur.dt;
delta_time_ += dt;
end_time_ = imu_cur.time;
current_state_.time = imu_cur.time;
Vector3d dvfb = imu_cur.dvel + 0.5 * imu_cur.dtheta.cross(imu_cur.dvel) +
1.0 / 12.0 * (imu_pre.dtheta.cross(imu_cur.dvel) + imu_pre.dvel.cross(imu_cur.dtheta));
Vector3d dv_cor_g = (gravity_ - 2.0 * iewn_.cross(current_state_.v)) * dt;
Vector3d dnn = -iewn_ * dt;
Quaterniond qnn = Rotation::rotvec2quaternion(dnn);
Vector3d dvel = 0.5 * (Matrix3d::Identity() + qnn.toRotationMatrix()) * current_state_.q.toRotationMatrix() * dvfb + dv_cor_g;
current_state_.p += dt * current_state_.v + 0.5 * dt * dvel;
current_state_.v += dvel;
pn_.emplace_back(std::make_pair(dt, current_state_.p));
Vector3d dtheta = imu_cur.dtheta + 1.0 / 12.0 * imu_pre.dtheta.cross(imu_cur.dtheta);
current_state_.q = qnn * current_state_.q * Rotation::rotvec2quaternion(dtheta);
current_state_.q.normalize();
dnn = -(delta_time_ - 0.5 * dt) * iewn_;
dvel = (q0_.inverse() * Rotation::rotvec2quaternion(dnn) * q0_ * delta_state_.q).toRotationMatrix()
* dvfb;
delta_state_.p += dt * delta_state_.v + 0.5 * dt * dvel;
delta_state_.v += dvel;
delta_state_.q *= Rotation::rotvec2quaternion(dtheta);
delta_state_.q.normalize();
updateJacobianAndCovariance(imu_pre, imu_cur);
}
机械编排:
预积分:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)