文章目录
团队博客: 汽车电子社区
1. 模块概述
Autoware定位模块位于src/universe/autoware_universe/localization/目录下,是自动驾驶系统的"位置感知器",负责精确确定车辆在全局坐标系中的位置和姿态。该模块采用多传感器融合架构,集成GNSS、IMU、轮速计、激光雷达等多种传感器,提供厘米级的高精度定位能力。
2. 模块架构设计
2.1 整体架构
2.2 传感器融合架构
3. EKF定位器 (EKF Localizer)
3.1 核心实现
class EKFLocalizer : public rclcpp::Node
{
private:
// EKF状态向量 [x, y, yaw, yaw_bias, vx, wz]
Eigen::VectorXd x_; // 状态向量
Eigen::MatrixXd P_; // 协方差矩阵
Eigen::MatrixXd Q_; // 过程噪声矩阵
// 观测矩阵
Eigen::MatrixXd H_gnss_; // GNSS观测矩阵
Eigen::MatrixXd H_odom_; // 里程计观测矩阵
Eigen::MatrixXd H_imu_; // IMU观测矩阵
// 观测噪声矩阵
Eigen::MatrixXd R_gnss_; // GNSS观测噪声
Eigen::MatrixXd R_odom_; // 里程计观测噪声
Eigen::MatrixXd R_imu_; // IMU观测噪声
// 延时补偿
std::deque<DelayCompensationData> delay_buffer_;
double max_delay_time_;
// 定时器
rclcpp::TimerBase::SharedPtr ekf_timer_;
double ekf_rate_;
// 订阅和发布
rclcpp::Subscription<Odometry>::SharedPtr sub_odom_;
rclcpp::Subscription<Imu>::SharedPtr sub_imu_;
rclcpp::Subscription<NavSatFix>::SharedPtr sub_gnss_pose_;
rclcpp::Subscription<PoseWithCovarianceStamped>::SharedPtr sub_ndt_pose_;
rclcpp::Publisher<PoseWithCovarianceStamped>::SharedPtr pub_pose_;
rclcpp::Publisher<TwistWithCovarianceStamped>::SharedPtr pub_twist_;
public:
EKFLocalizer() : Node("ekf_localizer")
{
// 1. 初始化EKF参数
initializeEKF();
// 2. 设置观测矩阵
setupObservationMatrices();
// 3. 设置噪声参数
setupNoiseParameters();
// 4. 设置订阅和发布
setupPubSub();
// 5. 启动EKF定时器
startEKFTimer();
}
private:
void onTimer()
{
// 1. 预测步骤
predict();
// 2. 延时补偿
compensateDelay();
// 3. 更新步骤
updateWithAvailableMeasurements();
// 4. 发布结果
publishResult();
}
void predict()
{
// 1. 构建状态转移矩阵
Eigen::MatrixXd F = createStateTransitionMatrix();
// 2. 预测状态
x_ = F * x_;
// 3. 预测协方差
P_ = F * P_ * F.transpose() + Q_;
// 4. 归一化角度
x_(2) = normalizeAngle(x_(2)); // yaw
}
Eigen::MatrixXd createStateTransitionMatrix()
{
Eigen::MatrixXd F = Eigen::MatrixXd::Identity(STATE_DIM, STATE_DIM);
double dt = ekf_rate_ > 0.0 ? 1.0 / ekf_rate_ : 0.1;
// x(k+1) = x(k) + vx(k) * cos(yaw(k)) * dt
F(0, 3) = std::cos(x_(2)) * dt; // ∂x/∂vx
// y(k+1) = y(k) + vx(k) * sin(yaw(k)) * dt
F(1, 3) = std::sin(x_(2)) * dt; // ∂y/∂vx
// yaw(k+1) = yaw(k) + (wz(k) + yaw_bias) * dt
F(2, 4) = dt; // ∂yaw/∂wz
F(2, 5) = dt; // ∂yaw/∂yaw_bias
// yaw_bias(k+1) = yaw_bias(k) (假设偏航偏置恒定)
// vx(k+1) = vx(k) (假设速度恒定)
F(3, 3) = 1.0; // ∂vx/∂vx
// wz(k+1) = wz(k) (假设角速度恒定)
F(4, 4) = 1.0; // ∂wz/∂wz
return F;
}
void updateWithAvailableMeasurements()
{
// 1. GNSS更新
if (hasGNSSMeasurement()) {
updateWithGNSS();
}
// 2. 里程计更新
if (hasOdometryMeasurement()) {
updateWithOdometry();
}
// 3. IMU更新
if (hasIMUMeasurement()) {
updateWithIMU();
}
// 4. NDT更新
if (hasNDTMeasurement()) {
updateWithNDT();
}
}
void updateWithGNSS()
{
if (gnss_buffer_.empty()) return;
auto gnss_measurement = getLatestGNSS();
// 1. 坐标转换
auto gnss_pose_in_map = transformGNSSToMap(gnss_measurement);
// 2. 构建观测向量
Eigen::VectorXd z = Eigen::VectorXd::Zero(3);
z << gnss_pose_in_map.pose.position.x,
gnss_pose_in_map.pose.position.y,
tf2::getYaw(gnss_pose_in_map.pose.orientation);
// 3. 预测观测
Eigen::VectorXd h = Eigen::VectorXd::Zero(3);
h << x_(0), x_(1), x_(2); // [x, y, yaw]
// 4. 计算卡尔曼增益
Eigen::MatrixXd K = P_ * H_gnss_.transpose() *
(H_gnss_ * P_ * H_gnss_.transpose() + R_gnss_).inverse();
// 5. 更新状态
x_ = x_ + K * (z - h);
// 6. 更新协方差
P_ = (Eigen::MatrixXd::Identity(STATE_DIM, STATE_DIM) - K * H_gnss_) * P_;
// 7. 归一化角度
x_(2) = normalizeAngle(x_(2));
}
void updateWithNDT()
{
if (ndt_buffer_.empty()) return;
auto ndt_measurement = getLatestNDT();
// 1. 构建观测向量 [x, y, yaw, vx, wz]
Eigen::VectorXd z = Eigen::VectorXd::Zero(5);
z << ndt_measurement.pose.pose.position.x,
ndt_measurement.pose.pose.position.y,
tf2::getYaw(ndt_measurement.pose.pose.orientation),
ndt_measurement.twist.twist.linear.x,
ndt_measurement.twist.twist.angular.z;
// 2. 预测观测
Eigen::VectorXd h = Eigen::VectorXd::Zero(5);
h << x_(0), x_(1), x_(2), x_(3), x_(4); // [x, y, yaw, vx, wz]
// 3. NDT观测矩阵 (观测所有状态)
Eigen::MatrixXd H_ndt = Eigen::MatrixXd::Zero(5, STATE_DIM);
H_ndt(0, 0) = 1.0; // x
H_ndt(1, 1) = 1.0; // y
H_ndt(2, 2) = 1.0; // yaw
H_ndt(3, 3) = 1.0; // vx
H_ndt(4, 4) = 1.0; // wz
// 4. 计算卡尔曼增益
Eigen::MatrixXd R_ndt = calculateNDTCovariance(ndt_measurement);
Eigen::MatrixXd K = P_ * H_ndt.transpose() *
(H_ndt * P_ * H_ndt.transpose() + R_ndt).inverse();
// 5. 更新状态
x_ = x_ + K * (z - h);
// 6. 更新协方差
P_ = (Eigen::MatrixXd::Identity(STATE_DIM, STATE_DIM) - K * H_ndt) * P_;
// 7. 归一化角度
x_(2) = normalizeAngle(x_(2));
}
void compensateDelay()
{
// 1. 检查延时缓冲区
if (delay_buffer_.empty()) return;
auto now = std::chrono::steady_clock::now();
double current_time = now.time_since_epoch().count() * 1e-9;
// 2. 移除过期的延时数据
while (!delay_buffer_.empty() &&
current_time - delay_buffer_.front().time > max_delay_time_) {
delay_buffer_.pop_front();
}
// 3. 延时补偿
for (auto & delay_data : delay_buffer_) {
double delay = current_time - delay_data.time;
if (delay > 0.0 && delay < max_delay_time_) {
applyDelayCompensation(delay_data, delay);
}
}
}
static constexpr int STATE_DIM = 6; // [x, y, yaw, yaw_bias, vx, wz]
};
3.2 延时补偿机制
class DelayCompensator
{
private:
// 延时数据结构
struct DelayData {
std::chrono::steady_clock::time_point timestamp;
Eigen::VectorXd measurement;
Eigen::MatrixXd observation_matrix;
Eigen::MatrixXd noise_matrix;
};
// 延时缓冲区
std::deque<DelayData> delay_buffer_;
double max_delay_time_;
// 状态历史
std::deque<StateHistory> state_history_;
public:
void addDelayedMeasurement(
const Eigen::VectorXd & measurement,
const Eigen::MatrixXd & H,
const Eigen::MatrixXd & R)
{
DelayData data;
data.timestamp = std::chrono::steady_clock::now();
data.measurement = measurement;
data.observation_matrix = H;
data.noise_matrix = R;
delay_buffer_.push_back(data);
}
void compensateDelay(
Eigen::VectorXd & x,
Eigen::MatrixXd & P,
const std::chrono::steady_clock::time_point & current_time)
{
// 1. 移除过期的延时数据
removeExpiredData(current_time);
// 2. 按时间顺序处理延时数据
for (auto & delay_data : delay_buffer_) {
double delay = std::chrono::duration<double>(
current_time - delay_data.timestamp).count();
if (delay > 0.0) {
// 3. 查找对应的历史状态
auto historical_state = findHistoricalState(delay_data.timestamp);
if (historical_state) {
// 4. 从历史时刻重新应用EKF更新
applyEKFUpdateAtTime(
historical_state->x, historical_state->P,
delay_data.measurement, delay_data.observation_matrix,
delay_data.noise_matrix);
}
}
}
// 5. 清空已处理的延时数据
delay_buffer_.clear();
}
private:
struct StateHistory {
std::chrono::steady_clock::time_point timestamp;
Eigen::VectorXd x;
Eigen::MatrixXd P;
};
void applyEKFUpdateAtTime(
const Eigen::VectorXd & x_hist,
const Eigen::MatrixXd & P_hist,
const Eigen::VectorXd & z,
const Eigen::MatrixXd & H,
const Eigen::MatrixXd & R)
{
// 1. 预测观测
Eigen::VectorXd h = H * x_hist;
// 2. 计算创新
Eigen::VectorXd y = z - h;
// 3. 计算创新协方差
Eigen::MatrixXd S = H * P_hist * H.transpose() + R;
// 4. 计算卡尔曼增益
Eigen::MatrixXd K = P_hist * H.transpose() * S.inverse();
// 5. 更新当前状态
x_ = x_hist + K * y;
P_ = (Eigen::MatrixXd::Identity(P_hist.rows(), P_hist.cols()) - K * H) * P_hist;
}
};
4. NDT扫描匹配器 (NDT Scan Matcher)
4.1 核心算法实现
class NDTScanMatcher : public rclcpp::Node
{
private:
// NDT算法实现
std::unique_ptr<NormalDistributionsTransform> ndt_;
// 点云预处理
std::unique_ptr<PointCloudProcessor> pointcloud_processor_;
// 地图管理
std::shared_ptr<PointCloudMap> pointcloud_map_;
// 坐标转换
std::shared_ptr<tf2_ros::Buffer> tf_buffer_;
std::shared_ptr<tf2_ros::TransformListener> tf_listener_;
// 配置参数
NDTConfig config_;
// 状态
Eigen::Matrix4f current_pose_;
Eigen::Matrix4f previous_pose_;
// 诊断
std::unique_ptr<NDTDiagnostics> diagnostics_;
public:
NDTScanMatcher() : Node("ndt_scan_matcher")
{
// 1. 初始化NDT算法
initializeNDT();
// 2. 加载点云地图
loadPointCloudMap();
// 3. 设置点云预处理
setupPointCloudPreprocessing();
// 4. 设置订阅和发布
setupPubSub();
// 5. 初始化诊断
initializeDiagnostics();
}
private:
void onPointCloud(
const PointCloud2::ConstSharedPtr input_cloud_msg)
{
// 1. 点云预处理
auto processed_cloud = preprocessPointCloud(input_cloud_msg);
// 2. 坐标转换
auto cloud_in_map = transformPointCloudToMap(processed_cloud);
// 3. NDT配准
auto registration_result = performNDTRegistration(cloud_in_map);
// 4. 结果验证和滤波
auto validated_result = validateAndFilterResult(registration_result);
// 5. 发布结果
publishNDTResult(validated_result);
// 6. 更新诊断
updateDiagnostics(validated_result);
}
NDTResult performNDTRegistration(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud)
{
NDTResult result;
// 1. 设置目标(地图)
ndt_->setInputTarget(pointcloud_map_->getMap());
// 2. 设置源(当前点云)
ndt_->setInputSource(cloud);
// 3. 设置初始猜测
Eigen::Matrix4f initial_guess = calculateInitialGuess();
ndt_->align(*cloud, initial_guess);
// 4. 检查收敛性
if (ndt_->hasConverged()) {
result.success = true;
result.final_transformation = ndt_->getFinalTransformation();
result.fitness_score = ndt_->getFitnessScore();
result.transformation_probability = ndt_->getTransformationProbability();
result.iterations = ndt_->getFinalNumIteration();
} else {
result.success = false;
result.error_message = "NDT did not converge";
}
return result;
}
Eigen::Matrix4f calculateInitialGuess()
{
// 1. 基于运动模型预测
Eigen::Matrix4f motion_prediction = predictPoseFromMotion();
// 2. 基于IMU积分预测
Eigen::Matrix4f imu_prediction = predictPoseFromIMU();
// 3. 融合预测
double motion_weight = config_.motion_prediction_weight;
double imu_weight = config_.imu_prediction_weight;
// 简单的加权平均(实际应用中可能需要更复杂的融合)
Eigen::Matrix4f initial_guess =
motion_weight * motion_prediction +
imu_weight * imu_prediction;
// 4. 归一化旋转矩阵
Eigen::Matrix3f rotation = initial_guess.block<3,3>(0,0);
Eigen::Quaternionf quat(rotation);
quat.normalize();
initial_guess.block<3,3>(0,0) = quat.toRotationMatrix();
return initial_guess;
}
NDTResult validateAndFilterResult(const NDTResult & raw_result)
{
NDTResult filtered_result = raw_result;
// 1. 检查收敛性
if (!raw_result.success) {
return createFallbackResult();
}
// 2. 检查适应度分数
if (raw_result.fitness_score > config_.max_fitness_score) {
RCLCPP_WARN(get_logger(),
"NDT fitness score too high: %f (threshold: %f)",
raw_result.fitness_score, config_.max_fitness_score);
return createFallbackResult();
}
// 3. 检查变换合理性
if (!isTransformationReasonable(raw_result.final_transformation)) {
RCLCPP_WARN(get_logger(),
"NDT transformation unreasonable");
return createFallbackResult();
}
// 4. 检查迭代次数
if (raw_result.iterations >= config_.max_iterations) {
RCLCPP_WARN(get_logger(),
"NDT reached max iterations: %d",
raw_result.iterations);
// 不拒绝结果,但标记为低置信度
filtered_result.confidence = NDTConfidence::LOW;
} else if (raw_result.iterations <= config_.min_iterations) {
filtered_result.confidence = NDTConfidence::HIGH;
} else {
filtered_result.confidence = NDTConfidence::MEDIUM;
}
// 5. 应用移动平均滤波
filtered_result.final_transformation =
applyMovingAverageFilter(raw_result.final_transformation);
return filtered_result;
}
bool isTransformationReasonable(const Eigen::Matrix4f & transform)
{
// 1. 检查平移量
Eigen::Vector3f translation = transform.block<3,1>(0,3);
double translation_magnitude = translation.norm();
if (translation_magnitude > config_.max_translation_per_frame) {
RCLCPP_WARN(get_logger(),
"Translation too large: %f (max: %f)",
translation_magnitude, config_.max_translation_per_frame);
return false;
}
// 2. 检查旋转量
Eigen::Matrix3f rotation = transform.block<3,3>(0,0);
Eigen::Quaternionf quat(rotation);
double rotation_angle = 2.0 * std::acos(std::clamp(quat.w(), -1.0, 1.0));
if (rotation_angle > config_.max_rotation_per_frame) {
RCLCPP_WARN(get_logger(),
"Rotation too large: %f (max: %f)",
rotation_angle, config_.max_rotation_per_frame);
return false;
}
return true;
}
Eigen::Matrix4f applyMovingAverageFilter(
const Eigen::Matrix4f & current_transform)
{
if (!config_.enable_moving_average_filter) {
return current_transform;
}
// 1. 提取平移和旋转
Eigen::Vector3f current_translation = current_transform.block<3,1>(0,3);
Eigen::Matrix3f current_rotation = current_transform.block<3,3>(0,0);
Eigen::Quaternionf current_quat(current_rotation);
// 2. 对平移应用移动平均
Eigen::Vector3f filtered_translation =
config_.moving_average_alpha * current_translation +
(1.0 - config_.moving_average_alpha) * previous_translation_;
// 3. 对旋转应用球面线性插值(SLERP)
Eigen::Quaternionf previous_quat(previous_rotation_);
Eigen::Quaternionf filtered_quat = previous_quat.slerp(
config_.moving_average_alpha, current_quat);
// 4. 构建滤波后的变换矩阵
Eigen::Matrix4f filtered_transform = Eigen::Matrix4f::Identity();
filtered_transform.block<3,1>(0,3) = filtered_translation;
filtered_transform.block<3,3>(0,0) = filtered_quat.toRotationMatrix();
// 5. 更新历史
previous_transform_ = filtered_transform;
return filtered_transform;
}
};
4.2 NDT算法核心实现
class NormalDistributionsTransform
{
private:
// 正态分布参数
struct NormalDistribution {
Eigen::Vector3f mean; // 均值
Eigen::Matrix3f covariance; // 协方差矩阵
Eigen::Matrix3f inv_covariance; // 协方差逆矩阵
double probability_density; // 概率密度
bool is_valid; // 是否有效
};
// 体素网格
struct VoxelGrid {
Eigen::Vector3f origin; // 网格原点
Eigen::Vector3f voxel_size; // 体素大小
Eigen::Vector3i grid_size; // 网格尺寸
std::vector<NormalDistribution> voxels; // 体素数据
};
// NDT参数
double resolution_;
double step_size_;
double outlier_ratio_;
int max_iterations_;
double transformation_epsilon_;
double euclidean_fitness_epsilon_;
// 网格数据
VoxelGrid target_voxel_grid_;
VoxelGrid source_voxel_grid_;
public:
void setInputTarget(const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud)
{
// 1. 构建目标体素网格
target_voxel_grid_ = buildVoxelGrid(cloud, resolution_);
// 2. 计算每个体素的统计参数
calculateVoxelStatistics(target_voxel_grid_);
// 3. 过滤无效体素
filterValidVoxels(target_voxel_grid_);
}
void align(
pcl::PointCloud<pcl::PointXYZ> & output,
const Eigen::Matrix4f & initial_guess)
{
// 1. 初始化变换
Eigen::Matrix4f current_transformation = initial_guess;
double previous_fitness_score = std::numeric_limits<double>::max();
// 2. 迭代优化
for (int iteration = 0; iteration < max_iterations_; ++iteration) {
// 3. 构建源体素网格
auto transformed_cloud = transformPointCloud(output, current_transformation);
source_voxel_grid_ = buildVoxelGrid(transformed_cloud, resolution_);
// 4. 计算得分和梯度
auto [score, gradient, hessian] = calculateScoreAndGradient(
current_transformation);
// 5. 检查收敛性
if (hasConverged(previous_fitness_score, score, current_transformation, iteration)) {
final_transformation_ = current_transformation;
fitness_score_ = score;
final_num_iteration_ = iteration + 1;
has_converged_ = true;
break;
}
// 6. 更新变换(Gauss-Newton方法)
current_transformation = updateTransformation(
current_transformation, gradient, hessian);
previous_fitness_score = score;
}
// 7. 应用最终变换
pcl::transformPointCloud(*input_source_, output, final_transformation_);
}
private:
std::tuple<double, Eigen::VectorXf, Eigen::MatrixXf> calculateScoreAndGradient(
const Eigen::Matrix4f & transformation)
{
double total_score = 0.0;
Eigen::VectorXf gradient = Eigen::VectorXf::Zero(6); // [tx, ty, tz, rx, ry, rz]
Eigen::MatrixXf hessian = Eigen::MatrixXf::Zero(6, 6);
int valid_point_count = 0;
// 1. 遍历源点云中的每个点
for (const auto & point : input_source_->points) {
// 2. 应用当前变换
Eigen::Vector4f transformed_point = transformation *
Eigen::Vector4f(point.x, point.y, point.z, 1.0f);
// 3. 找到对应的体素
auto voxel_info = findVoxel(transformed_point.head<3>(), target_voxel_grid_);
if (!voxel_info.is_valid) {
continue; // 跳过无效体素
}
// 4. 计算点到体素的距离和概率
Eigen::Vector3f d = transformed_point.head<3>() - voxel_info.mean;
double exponent = -0.5 * d.transpose() * voxel_info.inv_covariance * d;
double probability_density = std::exp(exponent) /
(std::pow(2.0 * M_PI, 1.5) * std::sqrt(voxel_info.covariance.determinant()));
// 5. 累加得分
double point_score = -exponent;
total_score += point_score;
// 6. 计算梯度
Eigen::VectorXf point_gradient = calculatePointGradient(
d, voxel_info.inv_covariance, transformed_point);
gradient += point_gradient;
// 7. 计算Hessian
Eigen::MatrixXf point_hessian = calculatePointHessian(
d, voxel_info.inv_covariance, transformed_point);
hessian += point_hessian;
++valid_point_count;
}
// 8. 归一化
if (valid_point_count > 0) {
total_score /= valid_point_count;
gradient /= valid_point_count;
hessian /= valid_point_count;
}
return std::make_tuple(total_score, gradient, hessian);
}
Eigen::VectorXf calculatePointGradient(
const Eigen::Vector3f & d,
const Eigen::Matrix3f & inv_covariance,
const Eigen::Vector4f & transformed_point)
{
Eigen::VectorXf gradient = Eigen::VectorXf::Zero(6);
// 1. 计算概率密度的梯度
Eigen::Vector3f grad_p = inv_covariance * d;
// 2. 计算变换参数的梯度
// ∂score/∂tx = grad_p_x
gradient(0) = grad_p(0);
// ∂score/∂ty = grad_p_y
gradient(1) = grad_p(1);
// ∂score/∂tz = grad_p_z
gradient(2) = grad_p(2);
// 3. 旋转部分的梯度(使用链式法则)
Eigen::Vector3f position = transformed_point.head<3>();
// ∂score/∂rx = grad_p · (∂d/∂rx)
gradient(3) = grad_p.dot(Eigen::Vector3f(
0.0, position(2), -position(1)));
// ∂score/∂ry = grad_p · (∂d/∂ry)
gradient(4) = grad_p.dot(Eigen::Vector3f(
-position(2), 0.0, position(0)));
// ∂score/∂rz = grad_p · (∂d/∂rz)
gradient(5) = grad_p.dot(Eigen::Vector3f(
position(1), -position(0), 0.0));
return gradient;
}
Eigen::MatrixXf calculatePointHessian(
const Eigen::Vector3f & d,
const Eigen::Matrix3f & inv_covariance,
const Eigen::Vector4f & transformed_point)
{
Eigen::MatrixXf hessian = Eigen::MatrixXf::Zero(6, 6);
Eigen::Vector3f position = transformed_point.head<3>();
// 1. 平移部分的Hessian(二阶导数)
hessian.block<3,3>(0,0) = inv_covariance;
// 2. 旋转部分的Hessian(近似计算)
// 这里使用简化的二阶导数计算
// ∂²score/∂rx²
hessian(3,3) = d(1) * inv_covariance(1,1) * d(1) +
d(2) * inv_covariance(2,2) * d(2);
// ∂²score/∂ry²
hessian(4,4) = d(0) * inv_covariance(0,0) * d(0) +
d(2) * inv_covariance(2,2) * d(2);
// ∂²score/∂rz²
hessian(5,5) = d(0) * inv_covariance(0,0) * d(0) +
d(1) * inv_covariance(1,1) * d(1);
// 3. 混合偏导数
hessian(3,4) = -d(0) * inv_covariance(0,1) * d(2);
hessian(4,3) = hessian(3,4);
hessian(3,5) = -d(0) * inv_covariance(0,2) * d(1);
hessian(5,3) = hessian(3,5);
hessian(4,5) = -d(1) * inv_covariance(1,2) * d(0);
hessian(5,4) = hessian(4,5);
return hessian;
}
Eigen::Matrix4f updateTransformation(
const Eigen::Matrix4f & current_transform,
const Eigen::VectorXf & gradient,
const Eigen::MatrixXf & hessian)
{
// 1. 求解线性系统 H * delta = -gradient
Eigen::VectorXf delta = hessian.ldlt().solve(-gradient);
// 2. 限制步长以避免过大的更新
delta = clampUpdateStep(delta);
// 3. 构建更新矩阵
Eigen::Matrix4f update_matrix = Eigen::Matrix4f::Identity();
// 平移更新
update_matrix(0,3) = delta(0); // tx
update_matrix(1,3) = delta(1); // ty
update_matrix(2,3) = delta(2); // tz
// 旋转更新(使用指数映射)
Eigen::Vector3f rotation_update(delta(3), delta(4), delta(5));
double rotation_angle = rotation_update.norm();
if (rotation_angle > 1e-6) {
Eigen::Vector3f rotation_axis = rotation_update / rotation_angle;
Eigen::Matrix3f rotation_update_matrix =
Eigen::AngleAxisf(rotation_angle, rotation_axis).toRotationMatrix();
update_matrix.block<3,3>(0,0) = rotation_update_matrix;
}
// 4. 应用更新
return update_matrix * current_transform;
}
};
5. 陀螺里程计 (Gyro Odometer)
5.1 IMU数据融合
class GyroOdometer : public rclcpp::Node
{
private:
// IMU处理
std::unique_ptr<IMUProcessor> imu_processor_;
// 轮速里程计
std::unique_ptr<WheelOdometryCalculator> wheel_odom_;
// 坐标变换
std::shared_ptr<tf2_ros::Buffer> tf_buffer_;
std::shared_ptr<tf2_ros::TransformListener> tf_listener_;
// 状态
struct OdometerState {
double x;
double y;
double yaw;
double vx;
double vy;
double wz;
std::chrono::steady_clock::time_point timestamp;
} current_state_;
// 校准参数
struct CalibrationParams {
double gyro_bias_x;
double gyro_bias_y;
double gyro_bias_z;
double wheel_radius_left;
double wheel_radius_right;
double wheel_base;
bool is_calibrated;
} calibration_params_;
public:
GyroOdometer() : Node("gyro_odometer")
{
// 1. 初始化处理器
imu_processor_ = std::make_unique<IMUProcessor>();
wheel_odom_ = std::make_unique<WheelOdometryCalculator>();
// 2. 设置订阅
setupSubscriptions();
// 3. 设置发布
setupPublishers();
// 4. 设置校准服务
setupCalibrationService();
// 5. 启动定时器
startTimer();
}
private:
void onIMU(const Imu::ConstSharedPtr imu_msg)
{
// 1. IMU数据预处理
auto processed_imu = imu_processor_->processIMU(*imu_msg);
// 2. 陀螺偏置补偿
if (calibration_params_.is_calibrated) {
processed_imu.angular_velocity.x -= calibration_params_.gyro_bias_x;
processed_imu.angular_velocity.y -= calibration_params_.gyro_bias_y;
processed_imu.angular_velocity.z -= calibration_params_.gyro_bias_z;
}
// 3. 积分角速度
integrateAngularVelocity(processed_imu);
}
void onWheelOdometry(const Odometry::ConstSharedPtr wheel_odom_msg)
{
// 1. 轮速数据处理
auto wheel_data = extractWheelData(*wheel_odom_msg);
// 2. 计算线速度
double linear_velocity = calculateLinearVelocity(wheel_data);
// 3. 更新速度状态
current_state_.vx = linear_velocity;
current_state_.vy = 0.0; // 假设无横向速度
// 4. 积分位置
integratePosition();
}
void integrateAngularVelocity(const sensor_msgs::msg::Imu & imu)
{
if (prev_imu_timestamp_.nanosec == 0) {
prev_imu_timestamp_ = imu.header.stamp;
return;
}
// 1. 计算时间间隔
double dt = (imu.header.stamp.sec - prev_imu_timestamp_.sec) +
(imu.header.stamp.nanosec - prev_imu_timestamp_.nanosec) * 1e-9;
if (dt <= 0.0 || dt > 1.0) { // 异常时间间隔
return;
}
// 2. 欧拉角积分
double delta_yaw = imu.angular_velocity.z * dt;
current_state_.yaw += delta_yaw;
// 3. 归一化角度
current_state_.yaw = normalizeAngle(current_state_.yaw);
// 4. 更新角速度
current_state_.wz = imu.angular_velocity.z;
// 5. 更新时间戳
current_state_.timestamp = imu.header.stamp;
prev_imu_timestamp_ = imu.header.stamp;
}
void integratePosition()
{
if (last_integration_time_.nanosec == 0) {
last_integration_time_ = current_state_.timestamp;
return;
}
// 1. 计算时间间隔
double dt = (current_state_.timestamp.sec - last_integration_time_.sec) +
(current_state_.timestamp.nanosec - last_integration_time_.nanosec) * 1e-9;
if (dt <= 0.0 || dt > 1.0) {
return;
}
// 2. 使用航向角积分位置(假设车辆模型)
current_state_.x += current_state_.vx * std::cos(current_state_.yaw) * dt;
current_state_.y += current_state_.vx * std::sin(current_state_.yaw) * dt;
// 3. 更新时间戳
last_integration_time_ = current_state_.timestamp;
}
double calculateLinearVelocity(const WheelData & wheel_data)
{
// 1. 计算左右轮线速度
double v_left = wheel_data.left_wheel_speed * calibration_params_.wheel_radius_left;
double v_right = wheel_data.right_wheel_speed * calibration_params_.wheel_radius_right;
// 2. 计算车辆中心线速度
double v_center = (v_left + v_right) / 2.0;
// 3. 低通滤波以减少噪声
static double filtered_velocity = 0.0;
double alpha = 0.1; // 滤波系数
filtered_velocity = alpha * v_center + (1.0 - alpha) * filtered_velocity;
return filtered_velocity;
}
};
6. 定位错误监控
6.1 定位质量评估
class LocalizationErrorMonitor : public rclcpp::Node
{
private:
// 错误检测器
std::vector<std::shared_ptr<ErrorDetector>> error_detectors_;
// 质量评估器
std::shared_ptr<QualityAssessment> quality_assessor_;
// 历史数据
std::deque<LocalizationData> localization_history_;
// 统计信息
struct LocalizationStatistics {
double position_error_mean;
double position_error_std;
double orientation_error_mean;
double orientation_error_std;
double ndt_fitness_score_mean;
double ndt_fitness_score_std;
size_t total_samples;
std::chrono::steady_clock::time_point last_update;
} statistics_;
public:
LocalizationErrorMonitor() : Node("localization_error_monitor")
{
// 1. 设置错误检测器
setupErrorDetectors();
// 2. 设置订阅
setupSubscriptions();
// 3. 设置发布
setupPublishers();
// 4. 启动监控定时器
startMonitoringTimer();
}
private:
void setupErrorDetectors()
{
// 1. 位置跳跃检测
error_detectors_.push_back(
std::make_shared<PositionJumpDetector>());
// 2. 角度跳跃检测
error_detectors_.push_back(
std::make_shared<OrientationJumpDetector>());
// 3. NDT收敛性检测
error_detectors_.push_back(
std::make_shared<NDTConvergenceDetector>());
// 4. GNSS质量检测
error_detectors_.push_back(
std::make_shared<GNSSQualityDetector>());
// 5. 传感器一致性检测
error_detectors_.push_back(
std::make_shared<SensorConsistencyDetector>());
}
void onLocalizationResult(
const PoseWithCovarianceStamped::ConstSharedPtr pose_msg)
{
// 1. 记录定位数据
LocalizationData loc_data;
loc_data.pose = *pose_msg;
loc_data.timestamp = pose_msg->header.stamp;
// 2. 执行错误检测
ErrorDetectionResult error_result = performErrorDetection(loc_data);
// 3. 更新质量评估
updateQualityAssessment(loc_data, error_result);
// 4. 更新统计信息
updateStatistics(loc_data);
// 5. 存储历史数据
storeLocalizationData(loc_data, error_result);
// 6. 发布诊断信息
publishDiagnostics(error_result);
}
ErrorDetectionResult performErrorDetection(
const LocalizationData & loc_data)
{
ErrorDetectionResult result;
result.is_valid = true;
// 1. 执行所有错误检测器
for (auto & detector : error_detectors_) {
auto detector_result = detector->detect(loc_data);
if (!detector_result.is_valid) {
result.is_valid = false;
result.error_messages.push_back(
detector->getName() + ": " + detector_result.error_message);
result.error_types.push_back(detector_result.error_type);
result.error_severity = std::max(
result.error_severity, detector_result.severity);
}
}
return result;
}
void updateQualityAssessment(
const LocalizationData & loc_data,
const ErrorDetectionResult & error_result)
{
// 1. 基础质量分数
double quality_score = 100.0;
// 2. 根据错误检测结果扣分
if (error_result.is_valid) {
// 计算位置不确定性
double position_uncertainty =
std::sqrt(loc_data.pose.pose.covariance[0] +
loc_data.pose.pose.covariance[7]);
// 计算角度不确定性
double orientation_uncertainty =
std::sqrt(loc_data.pose.pose.covariance[35]);
// 不确定性扣分
quality_score -= position_uncertainty * 10.0; // 10分/米
quality_score -= orientation_uncertainty * 100.0; // 100分/弧度
} else {
// 严重错误扣分
quality_score -= error_result.error_severity * 20.0;
}
// 3. 限制在0-100范围内
quality_score = std::clamp(quality_score, 0.0, 100.0);
// 4. 更新质量评估
quality_assessor_->updateQuality(loc_data.timestamp, quality_score);
}
};
6.2 位置跳跃检测器
class PositionJumpDetector : public ErrorDetector
{
private:
// 跳跃检测参数
double max_position_jump_threshold_; // 最大位置跳跃阈值
double max_orientation_jump_threshold_; // 最大角度跳跃阈值
double max_velocity_threshold_; // 最大速度阈值
// 历史数据
LocalizationData previous_data_;
public:
ErrorDetectorResult detect(const LocalizationData & current_data) override
{
ErrorDetectorResult result;
result.is_valid = true;
result.error_type = ErrorType::NONE;
result.severity = ErrorSeverity::LOW;
if (previous_data_.timestamp.sec == 0) {
// 第一次数据,直接保存
previous_data_ = current_data;
return result;
}
// 1. 计算时间间隔
double time_diff = calculateTimeDifference(
current_data.timestamp, previous_data_.timestamp);
if (time_diff <= 0.0 || time_diff > 1.0) {
return result; // 时间间隔异常,跳过检测
}
// 2. 计算位置跳跃
double position_jump = calculatePositionJump(
current_data.pose.pose.position,
previous_data_.pose.pose.position);
// 3. 计算角度跳跃
double orientation_jump = calculateOrientationJump(
current_data.pose.pose.orientation,
previous_data_.pose.pose.orientation);
// 4. 计算速度
double velocity = position_jump / time_diff;
// 5. 检查位置跳跃
if (position_jump > max_position_jump_threshold_) {
result.is_valid = false;
result.error_type = ErrorType::POSITION_JUMP;
result.severity = ErrorSeverity::HIGH;
result.error_message =
"Position jump detected: " + std::to_string(position_jump) +
"m (threshold: " + std::to_string(max_position_jump_threshold_) + "m)";
}
// 6. 检查角度跳跃
if (orientation_jump > max_orientation_jump_threshold_) {
result.is_valid = false;
result.error_type = ErrorType::ORIENTATION_JUMP;
result.severity = ErrorSeverity::HIGH;
result.error_message =
"Orientation jump detected: " + std::to_string(orientation_jump * 180.0 / M_PI) +
"° (threshold: " + std::to_string(max_orientation_jump_threshold_ * 180.0 / M_PI) + "°)";
}
// 7. 检查速度合理性
if (velocity > max_velocity_threshold_) {
result.is_valid = false;
result.error_type = ErrorType::UNREALISTIC_VELOCITY;
result.severity = ErrorSeverity::MEDIUM;
result.error_message =
"Unrealistic velocity: " + std::to_string(velocity) +
"m/s (threshold: " + std::to_string(max_velocity_threshold_) + "m/s)";
}
// 8. 更新历史数据
previous_data_ = current_data;
return result;
}
private:
double calculatePositionJump(
const geometry_msgs::msg::Point & current_pos,
const geometry_msgs::msg::Point & previous_pos)
{
double dx = current_pos.x - previous_pos.x;
double dy = current_pos.y - previous_pos.y;
double dz = current_pos.z - previous_pos.z;
return std::sqrt(dx * dx + dy * dy + dz * dz);
}
double calculateOrientationJump(
const geometry_msgs::msg::Quaternion & current_quat,
const geometry_msgs::msg::Quaternion & previous_quat)
{
tf2::Quaternion current_tf, previous_tf;
tf2::fromMsg(current_quat, current_tf);
tf2::fromMsg(previous_quat, previous_tf);
// 计算四元数差值
tf2::Quaternion diff_quat = current_tf * previous_tf.inverse();
// 转换为角度
double angle = 2.0 * std::acos(std::clamp(diff_quat.w(), -1.0, 1.0));
return std::abs(angle);
}
};
7. 定位仲裁器
7.1 多源定位融合
class PoseEstimatorArbiter : public rclcpp::Node
{
private:
// 定位源
enum class LocalizationSource {
EKF_LOCALIZER, // EKF定位器
NDT_SCAN_MATCHER, // NDT扫描匹配器
GNSS_LOCALIZER, // GNSS定位器
LANDMARK_LOCALIZER, // 地标定位器
DEAD_RECKONING // 航位推算
};
// 定位源数据
struct SourceData {
LocalizationSource source;
PoseWithCovarianceStamped::ConstSharedPtr pose;
double quality_score;
double confidence;
std::chrono::steady_clock::time_point timestamp;
bool is_valid;
};
// 活跃的定位源
std::map<LocalizationSource, SourceData> active_sources_;
// 融合策略
std::shared_ptr<FusionStrategy> fusion_strategy_;
// 当前最佳定位源
LocalizationSource current_best_source_ = LocalizationSource::EKF_LOCALIZER;
// 质量阈值
struct QualityThresholds {
double min_quality_score;
double source_switch_threshold;
double outlier_rejection_threshold;
} quality_thresholds_;
public:
void onEKFPose(const PoseWithCovarianceStamped::ConstSharedPtr pose_msg)
{
// 1. 评估EKF定位质量
double quality_score = evaluateEKFQuality(*pose_msg);
// 2. 更新源数据
updateSourceData(LocalizationSource::EKF_LOCALIZER, pose_msg, quality_score);
// 3. 执行仲裁决策
performArbitrationDecision();
}
void onNDTPose(const PoseWithCovarianceStamped::ConstSharedPtr pose_msg)
{
// 1. 评估NDT定位质量
double quality_score = evaluateNDTQuality(*pose_msg);
// 2. 更新源数据
updateSourceData(LocalizationSource::NDT_SCAN_MATCHER, pose_msg, quality_score);
// 3. 执行仲裁决策
performArbitrationDecision();
}
private:
void performArbitrationDecision()
{
// 1. 确定最佳定位源
auto best_source = determineBestSource();
// 2. 检查是否需要切换源
if (shouldSwitchSource(best_source)) {
switchLocalizationSource(best_source);
}
// 3. 融合定位结果
auto fused_pose = fuseLocalizationResults();
// 4. 发布融合结果
publishFusedPose(fused_pose);
}
LocalizationSource determineBestSource()
{
LocalizationSource best_source = current_best_source_;
double best_score = -1.0;
// 1. 遍历所有活跃源
for (const auto & [source, data] : active_sources_) {
if (!data.is_valid || data.quality_score < quality_thresholds_.min_quality_score) {
continue;
}
// 2. 考虑数据新鲜度
double age_penalty = calculateAgePenalty(data.timestamp);
double adjusted_score = data.quality_score - age_penalty;
// 3. 考虑场景适应性
double scene_factor = calculateSceneFactor(source);
adjusted_score *= scene_factor;
// 4. 更新最佳源
if (adjusted_score > best_score) {
best_score = adjusted_score;
best_source = source;
}
}
return best_source;
}
bool shouldSwitchSource(LocalizationSource new_source)
{
if (new_source == current_best_source_) {
return false; // 没有变化
}
auto & current_data = active_sources_[current_best_source_];
auto & new_data = active_sources_[new_source];
// 1. 检查新源是否有效
if (!new_data.is_valid) {
return false;
}
// 2. 检查质量差异
double quality_diff = new_data.quality_score - current_data.quality_score;
if (quality_diff < quality_thresholds_.source_switch_threshold) {
return false; // 质量提升不够显著
}
// 3. 检查切换稳定性
if (!isSwitchStable(new_source)) {
return false; // 切换可能导致不稳定
}
// 4. 检查场景适用性
if (!isSourceAppropriateForScene(new_source)) {
return false; // 新源不适合当前场景
}
return true;
}
PoseWithCovarianceStamped fuseLocalizationResults()
{
PoseWithCovarianceStamped fused_pose;
// 1. 获取有效源
std::vector<std::pair<LocalizationSource, double>> weighted_sources;
double total_weight = 0.0;
for (const auto & [source, data] : active_sources_) {
if (!data.is_valid) {
continue;
}
// 计算权重(基于质量和置信度)
double weight = data.quality_score * data.confidence;
// 考虑时间相关性
double time_factor = calculateTimeCorrelation(data.timestamp);
weight *= time_factor;
weighted_sources.push_back({source, weight});
total_weight += weight;
}
if (weighted_sources.empty() || total_weight <= 0.0) {
// 没有有效源,返回默认值
return createDefaultPose();
}
// 2. 加权平均融合
Eigen::Vector3d fused_position = Eigen::Vector3d::Zero();
Eigen::Quaterniond fused_orientation = Eigen::Quaterniond::Identity();
Eigen::Matrix6d fused_covariance = Eigen::Matrix6d::Zero();
for (const auto & [source, weight] : weighted_sources) {
const auto & data = active_sources_[source];
double normalized_weight = weight / total_weight;
// 位置融合
fused_position += normalized_weight * Eigen::Vector3d(
data.pose->pose.pose.position.x,
data.pose->pose.pose.position.y,
data.pose->pose.pose.position.z);
// 方向融合(使用SLERP)
tf2::Quaternion source_quat;
tf2::fromMsg(data.pose->pose.pose.orientation, source_quat);
Eigen::Quaterniond eigen_quat(source_quat.w(), source_quat.x(),
source_quat.y(), source_quat.z());
if (fused_orientation.w() == 1.0) { // 初始值
fused_orientation = eigen_quat;
} else {
fused_orientation = fused_orientation.slerp(normalized_weight, eigen_quat);
}
// 协方差融合
// 这里使用加权的协方差,实际中可能需要更复杂的融合
for (int i = 0; i < 36; ++i) {
fused_covariance(i/6, i%6) += normalized_weight *
data.pose->pose.covariance[i];
}
}
// 3. 构建融合结果
fused_pose.header.stamp = this->now();
fused_pose.header.frame_id = "map";
fused_pose.pose.pose.position.x = fused_position.x();
fused_pose.pose.pose.position.y = fused_position.y();
fused_pose.pose.pose.position.z = fused_position.z();
fused_pose.pose.pose.orientation = tf2::toMsg(
tf2::Quaternion(fused_orientation.x(), fused_orientation.y(),
fused_orientation.z(), fused_orientation.w()));
for (int i = 0; i < 36; ++i) {
fused_pose.pose.covariance[i] = fused_covariance(i/6, i%6);
}
return fused_pose;
}
double calculateSceneFactor(LocalizationSource source)
{
// 根据当前场景调整源权重
SceneType current_scene = detectCurrentScene();
switch (source) {
case LocalizationSource::NDT_SCAN_MATCHER:
// NDT在结构化环境中表现良好
return (current_scene == SceneType::URBAN ||
current_scene == SceneType::HIGHWAY) ? 1.2 : 0.8;
case LocalizationSource::GNSS_LOCALIZER:
// GNSS在开阔地带表现良好
return (current_scene == SceneType::OPEN_AREA ||
current_scene == SceneType::HIGHWAY) ? 1.2 : 0.6;
case LocalizationSource::EKF_LOCALIZER:
// EKF是通用源,较为稳定
return 1.0;
case LocalizationSource::LANDMARK_LOCALIZER:
// 地标定位在有地标的环境中表现良好
return (current_scene == SceneType::URBAN) ? 1.1 : 0.5;
case LocalizationSource::DEAD_RECKONING:
// 航位推算作为备用源
return 0.3;
}
return 1.0;
}
};
8. 总结
Autoware定位模块展现了现代自动驾驶定位系统的先进性和完整性:
8.1 技术特点
1. 多传感器融合: 有效融合GNSS、IMU、轮速计、激光雷达数据
2. 先进算法: EKF扩展卡尔曼滤波和NDT正态分布变换
3. 延时补偿: 精确的传感器延时补偿机制
4. 错误监控: 完善的定位质量评估和错误检测
5. 智能仲裁: 多源定位的智能选择和融合
8.2 核心优势
- 高精度定位: 厘米级的定位精度
- 鲁棒性: 在各种环境条件下都能提供可靠定位
- 实时性: 高频定位输出保证控制需求
- 可扩展性: 支持新的定位源集成
- 自诊断: 完善的错误检测和质量评估机制
8.3 应用价值
该定位模块为自动驾驶系统提供了精确、可靠的位置信息,是自动驾驶的基础支撑。其先进的多传感器融合技术和智能仲裁机制使其能够在复杂环境下提供高质量的定位服务,为安全驾驶奠定坚实基础。
定位系统的设计充分体现了现代导航技术的工程应用,结合了最先进的传感器融合算法和智能决策机制,代表了自动驾驶定位技术的领先水平。

984

被折叠的 条评论
为什么被折叠?



