前端里程计使用NDT配准得到的关键帧位姿都为姿态增量,这就可以解释以下代码的操作:
1. front_end.cpp中:
for (size_t i = 0; i < local_map_frames_.size(); ++i) {
pcl::transformPointCloud(*local_map_frames_.at(i).cloud_data.cloud_ptr,
*transformed_cloud_ptr,
local_map_frames_.at(i).pose);
2. loop_closing.cpp中
bool LoopClosing::JointMap(int key_frame_index, CloudData::CLOUD_PTR& map_cloud_ptr, Eigen::Matrix4f& map_pose) {
map_pose = all_key_gnss_.at(key_frame_index).pose;
current_loop_pose_.index0 = all_key_frames_.at(key_frame_index).index;
// 合成地图
Eigen::Matrix4f pose_to_gnss = map_pose * all_key_frames_.at(key_frame_index).pose.inverse();
for (int i = key_frame_index - extend_frame_num_; i < key_frame_index + extend_frame_num_; ++i) {
std::string file_path = key_frames_path_ + "/key_frame_" + std::to_string(all_key_frames_.at(i).index) + ".pcd";
CloudData::CLOUD_PTR cloud_ptr(new CloudData::CLOUD());
pcl::io::loadPCDFile(file_path, *cloud_ptr);
Eigen::Matrix4f cloud_pose = pose_to_gnss * all_key_frames_.at(i).pose;
pcl::transformPointCloud(*cloud_ptr, *cloud_ptr, cloud_pose);
*map_cloud_ptr += *cloud_ptr;
}
map_filter_ptr_->Filter(map_cloud_ptr, map_cloud_ptr);
return true;
}
// 计算相对位姿
current_loop_pose_.pose = map_pose.inverse() * result_pose;
前端里程计中,预测位姿的做法:
step_pose = last_pose.inverse() * current_frame_.pose;
predict_pose = current_frame_.pose * step_pose;
last_pose = current_frame_.pose;
代码中的做法为假设雷达做的是匀速运动,即预测位姿为上一时刻的
注:NDT和ICP配准需一个良好的初始位姿,若初始位姿较差,配准出来的结果会令人大失所望