基于C++的GPS/INS组合导航系统实现
一、系统架构设计
1.1 模块划分
// 主程序流程
int main() {
DataAcquisition daq; // 数据采集模块
KalmanFilter kf; // 卡尔曼滤波器
AttitudeSolver attitude; // 姿态解算模块
NavigationSolver nav; // 导航解算模块
while(1) {
// 数据采集(100Hz)
SensorData raw = daq.get_data();
// 姿态解算(四元数法)
Quaternion q = attitude.update(raw.gyro, raw.accel);
// 卡尔曼滤波(紧耦合架构)
kf.predict(q, raw.gyro_bias);
kf.update(raw.gps_pseudorange, raw.gps_doppler);
// 导航解算
NavData result = nav.calculate(kf.state);
// 数据输出
output_navigation_data(result);
}
}
1.2 数据流图
GPS接收机 → 伪距/伪距率 → 卡尔曼滤波器
INS模块 → 四元数姿态 → 卡尔曼滤波器
卡尔曼滤波器 → 导航状态 → 输出接口
二、核心算法实现
2.1 四元数姿态解算
// 四元数更新(四阶龙格-库塔法)
Quaternion AttitudeSolver::update(Vector3d gyro, Vector3d accel) {
double dt = 0.01; // 100Hz采样周期
// 1. 预积分陀螺数据
Quaternion q_dot = 0.5 * q * Quaternion(0, gyro.x, gyro.y, gyro.z);
// 2. 重力对准补偿
Vector3d gravity = q.to_rotation_matrix() * Vector3d(0,0,9.81);
Vector3d accel_error = accel - gravity.normalized()*9.81;
// 3. 误差补偿
q_dot += 0.01 * Quaternion(0, -0.01*accel_error.x,
-0.01*accel_error.y,
-0.01*accel_error.z);
// 4. 四元数归一化
q = q + q_dot * dt;
q.normalize();
return q;
}
2.2 卡尔曼滤波实现
// 状态向量定义(位置/速度/姿态/陀螺偏差)
struct StateVector {
double x[15]; // [pn, pe, h, vn, ve, vh, q0, q1, q2, q3,
// bx_bias, by_bias, bz_bias, wx_bias]
};
// 预测过程
void KalmanFilter::predict(const Quaternion &q, const Vector3d &gyro_bias) {
// 状态转移矩阵
MatrixXd F = MatrixXd::Identity(15,15);
F.block<3,3>(0,3) = -q.to_rotation_matrix() *
(0.5 * dt * (Vector3d(0,0,9.81) + accel_bias));
// 过程噪声协方差
MatrixXd Q = MatrixXd::Zero(15,15);
Q.block<3,3>(3,3) = imu_noise.acc_cov * dt*dt;
Q.block<3,3>(6,6) = imu_noise.gyro_cov * dt*dt*dt*dt/3.0;
}
// 更新过程(紧耦合架构)
void KalmanFilter::update(double pseudorange, double doppler) {
// 观测矩阵构建
MatrixXd H(2,15);
H <<
// 伪距观测矩阵
1, 0, 0,
-sin(lat)*cos(lon), -sin(lat)*sin(lon), cos(lat),
// 多普勒观测矩阵
0, 0, 0,
cos(lat)*cos(lon)*dt, cos(lat)*sin(lon)*dt, -sin(lat)*dt,
...; // 其他状态关联项
// 卡尔曼增益计算
MatrixXd K = P * H.transpose() * (H*P*H.transpose() + R).inverse();
// 状态更新
x = x + K * (z - H*x);
P = (MatrixXd::Identity(15,15) - K*H) * P;
}
三、数据结构
3.1 传感器数据结构
struct SensorData {
// INS原始数据
Vector3d accel; // 加速度计 (m/s²)
Vector3d gyro; // 陀螺仪 (rad/s)
Vector3d mag; // 磁力计 (μT)
// GPS原始数据
double pseudorange; // 伪距 (m)
double doppler; // 多普勒频移 (Hz)
double cn0; // 载噪比 (dBHz)
// 时间戳
uint64_t timestamp;
};
3.2 导航输出结构
struct NavData {
// 位置 (WGS84坐标系)
double latitude; // 纬度 (rad)
double longitude; // 经度 (rad)
double altitude; // 高度 (m)
// 速度 (NED坐标系)
double vn; // 北向速度 (m/s)
double ve; // 东向速度 (m/s)
double vh; // 天向速度 (m/s)
// 姿态
Quaternion q; // 四元数姿态
Vector3d euler; // 欧拉角 (roll, pitch, yaw)
};
四、优化
4.1 多传感器同步
// 时间戳对齐(GPS 1PPS同步)
void time_sync(SensorData &data) {
static uint64_t last_pps = 0;
if(data.gps_pps) {
last_pps = data.timestamp;
}
data.synced_time = data.timestamp - last_pps + 1e6; // 1PPS对齐
}
4.2 动态噪声调整
// 自适应卡尔曼滤波
void adaptive_kalman() {
static double noise_counter = 0;
if(cn0 > 45) { // 高信噪比时降低噪声
imu_noise.gyro_cov *= 0.9;
imu_noise.acc_cov *= 0.9;
} else if(cn0 < 30) { // 低信噪比时提高噪声
imu_noise.gyro_cov *= 1.1;
imu_noise.acc_cov *= 1.1;
}
}
五、测试方案
5.1 静态测试
// 基准测试(静止状态下)
void static_test() {
double position_error = 0;
for(int i=0; i<1000; i++) {
NavData data = nav.calculate();
position_error += hypot(data.latitude - ref_lat,
data.longitude - ref_lon);
}
cout << "平均位置误差: " << position_error/1000 << " m" << endl;
}
5.2 动态测试
// 车载动态测试
void dynamic_test() {
while(vehicle_moving) {
NavData data = nav.calculate();
// 计算动态误差
double dt = 0.01;
double dv = hypot(data.vn - prev_vn, data.ve - prev_ve) / dt;
double dtheta = (data.yaw - prev_yaw) / dt;
cout << "动态速度误差: " << dv << " m/s" << endl;
cout << "动态角速度误差: " << dtheta << " rad/s" << endl;
}
}
六、扩展功能实现
6.1 多传感器融合
// 多传感器数据融合(GPS+IMU+视觉)
void multi_sensor_fusion() {
// 视觉里程计数据
VisualOdometry vo_data = get_vo_data();
// 扩展卡尔曼滤波
MatrixXd H_vo = build_visual_hessian();
MatrixXd K_vo = P_vo * H_vo.transpose() *
(H_vo*P_vo*H_vo.transpose() + R_vo).inverse();
// 状态更新
x = x + K_vo * (z_vo - H_vo*x);
}
6.2 故障检测
// 传感器故障检测
void fault_detection() {
// 检查加速度计偏差
if(fabs(accel_bias.x) > 0.1 ||
fabs(accel_bias.y) > 0.1 ||
fabs(accel_bias.z) > 0.2) {
trigger_fault(FaultType::ACCEL_BIAS);
}
// 检查陀螺漂移
if(fabs(gyro_bias.x) > 0.01 ||
fabs(gyro_bias.y) > 0.01 ||
fabs(gyro_bias.z) > 0.02) {
trigger_fault(FaultType::GYRO_DRIFT);
}
}
七、开发环境配置
# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(GPS_INS_Navigation)
set(CMAKE_CXX_STANDARD 17)
# 依赖库
find_package(Eigen3 REQUIRED)
find_package(PCL 1.12 REQUIRED)
find_package(Boost 1.75 COMPONENTS filesystem REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIRS})
add_executable(gps_ins_main main.cpp)
target_link_libraries(gps_ins_main
${PCL_LIBRARIES}
${Boost_LIBRARIES}
imu_utils
kalman_filter
)
参考代码 实现gps/ins组合导航的C++程序 www.youwenfan.com/contentzhf/69525.html
八、典型性能指标
| 指标 | 实现值 | 测试条件 |
|---|---|---|
| 位置精度 | <0.5 m (RMS) | 城市峡谷环境 |
| 速度精度 | <0.1 m/s | 高速运动(30 m/s) |
| 姿态精度 | <0.1° (roll/pitch) | 静态测试 |
| 系统延迟 | <50 ms | 数据采集到输出 |
| 功耗 | <2.5 W | 树莓派4B平台 |