4#include <gtsam_points/factors/integrated_vgicp_factor.hpp>
6#include <gtsam/geometry/Pose3.h>
7#include <gtsam/linear/HessianFactor.h>
8#include <gtsam_points/config.hpp>
9#include <gtsam_points/types/gaussian_voxelmap_cpu.hpp>
10#include <gtsam_points/util/parallelism.hpp>
11#include <gtsam_points/util/compact.hpp>
12#include <gtsam_points/factors/impl/scan_matching_reduction.hpp>
14#ifdef GTSAM_POINTS_USE_TBB
15#include <tbb/parallel_for.h>
18namespace gtsam_points {
20template <
typename SourceFrame>
22 gtsam::Key target_key,
23 gtsam::Key source_key,
24 const GaussianVoxelMap::ConstPtr& target_voxels,
25 const std::shared_ptr<const SourceFrame>& source)
28 mahalanobis_cache_mode(FusedCovCacheMode::FULL),
32 if (!frame::has_points(*source)) {
33 std::cerr <<
"error: source points have not been allocated!!" << std::endl;
37 if (!frame::has_covs(*source)) {
38 std::cerr <<
"error: source don't have covs!!" << std::endl;
42 if (!this->target_voxels) {
43 std::cerr <<
"error: target voxelmap has not been created!!" << std::endl;
48template <
typename SourceFrame>
50 const gtsam::Pose3& fixed_target_pose,
51 gtsam::Key source_key,
52 const GaussianVoxelMap::ConstPtr& target_voxels,
53 const std::shared_ptr<const SourceFrame>& source)
56 mahalanobis_cache_mode(FusedCovCacheMode::FULL),
60 if (!frame::has_points(*source)) {
61 std::cerr <<
"error: source points have not been allocated!!" << std::endl;
65 if (!frame::has_covs(*source)) {
66 std::cerr <<
"error: source don't have covs!!" << std::endl;
70 if (!this->target_voxels) {
71 std::cerr <<
"error: target voxelmap has not been created!!" << std::endl;
76template <
typename SourceFrame>
79template <
typename SourceFrame>
81 std::cout << s <<
"IntegratedVGICPFactor";
83 std::cout <<
"(" << keyFormatter(this->keys()[0]) <<
", " << keyFormatter(this->keys()[1]) <<
")" << std::endl;
85 std::cout <<
"(fixed, " << keyFormatter(this->keys()[0]) <<
")" << std::endl;
88 std::cout <<
"target_resolusion=" << target_voxels->voxel_resolution() <<
", |source|=" << frame::size(*source) <<
"pts" << std::endl;
89 std::cout <<
"num_threads=" << num_threads << std::endl;
92template <
typename SourceFrame>
94 return sizeof(*this) +
sizeof(
const GaussianVoxel*) * correspondences.capacity() +
sizeof(Eigen::Matrix4d) * mahalanobis_full.capacity() +
95 sizeof(Eigen::Matrix<float, 6, 1>) * mahalanobis_compact.capacity();
98template <
typename SourceFrame>
100 linearization_point = delta;
101 correspondences.resize(frame::size(*source));
103 switch (mahalanobis_cache_mode) {
104 case FusedCovCacheMode::FULL:
105 mahalanobis_full.resize(frame::size(*source));
107 case FusedCovCacheMode::COMPACT:
108 mahalanobis_compact.resize(frame::size(*source));
110 case FusedCovCacheMode::NONE:
114 const auto perpoint_task = [&](
int i) {
115 Eigen::Vector4d pt = delta * frame::point(*source, i);
116 Eigen::Vector3i coord = target_voxels->voxel_coord(pt);
117 const auto voxel_id = target_voxels->lookup_voxel_index(coord);
120 correspondences[i] =
nullptr;
122 switch (mahalanobis_cache_mode) {
123 case FusedCovCacheMode::FULL:
124 mahalanobis_full[i].setZero();
126 case FusedCovCacheMode::COMPACT:
127 mahalanobis_compact[i].setZero();
129 case FusedCovCacheMode::NONE:
133 const auto voxel = &target_voxels->lookup_voxel(voxel_id);
134 correspondences[i] = voxel;
136 switch (mahalanobis_cache_mode) {
137 case FusedCovCacheMode::FULL: {
138 const Eigen::Matrix4d RCR = (voxel->cov + delta.matrix() * frame::cov(*source, i) * delta.matrix().transpose());
139 mahalanobis_full[i].setZero();
140 mahalanobis_full[i].template topLeftCorner<3, 3>() = RCR.topLeftCorner<3, 3>().inverse();
143 case FusedCovCacheMode::COMPACT: {
144 const Eigen::Matrix4d RCR = (voxel->cov + delta.matrix() * frame::cov(*source, i) * delta.matrix().transpose());
145 const Eigen::Matrix3d maha = RCR.topLeftCorner<3, 3>().inverse();
146 mahalanobis_compact[i] = compact_cov(maha);
149 case FusedCovCacheMode::NONE:
155 if (is_omp_default() || num_threads == 1) {
156#pragma omp parallel for num_threads(num_threads) schedule(guided, 8)
157 for (
int i = 0; i < frame::size(*source); i++) {
161#ifdef GTSAM_POINTS_USE_TBB
162 tbb::parallel_for(tbb::blocked_range<int>(0, frame::size(*source), 8), [&](
const tbb::blocked_range<int>& range) {
163 for (
int i = range.begin(); i < range.end(); i++) {
168 std::cerr <<
"error: TBB is not available" << std::endl;
174template <
typename SourceFrame>
175double IntegratedVGICPFactor_<SourceFrame>::evaluate(
176 const Eigen::Isometry3d& delta,
177 Eigen::Matrix<double, 6, 6>* H_target,
178 Eigen::Matrix<double, 6, 6>* H_source,
179 Eigen::Matrix<double, 6, 6>* H_target_source,
180 Eigen::Matrix<double, 6, 1>* b_target,
181 Eigen::Matrix<double, 6, 1>* b_source)
const {
183 if (correspondences.size() != frame::size(*source)) {
184 update_correspondences(delta);
187 double sum_errors = 0.0;
189 const auto perpoint_task = [&](
191 Eigen::Matrix<double, 6, 6>* H_target,
192 Eigen::Matrix<double, 6, 6>* H_source,
193 Eigen::Matrix<double, 6, 6>* H_target_source,
194 Eigen::Matrix<double, 6, 1>* b_target,
195 Eigen::Matrix<double, 6, 1>* b_source) {
196 const auto& target_voxel = correspondences[i];
197 if (target_voxel ==
nullptr) {
201 const auto& mean_A = frame::point(*source, i);
202 const auto& cov_A = frame::cov(*source, i);
204 const auto& mean_B = target_voxel->mean;
205 const auto& cov_B = target_voxel->cov;
207 Eigen::Vector4d transed_mean_A = delta * mean_A;
208 Eigen::Vector4d residual = mean_B - transed_mean_A;
210 Eigen::Matrix4d mahalanobis;
211 switch (mahalanobis_cache_mode) {
212 case FusedCovCacheMode::FULL:
213 mahalanobis = mahalanobis_full[i];
215 case FusedCovCacheMode::COMPACT:
216 mahalanobis = uncompact_cov(mahalanobis_compact[i]);
218 case FusedCovCacheMode::NONE: {
219 const auto& delta_l = linearization_point;
220 const Eigen::Matrix4d RCR = (cov_B + delta_l.matrix() * cov_A * delta_l.matrix().transpose());
221 mahalanobis.setZero();
222 mahalanobis.topLeftCorner<3, 3>() = RCR.topLeftCorner<3, 3>().inverse();
226 const double error = residual.transpose() * mahalanobis * residual;
232 Eigen::Matrix<double, 4, 6> J_target = Eigen::Matrix<double, 4, 6>::Zero();
233 J_target.block<3, 3>(0, 0) = -gtsam::SO3::Hat(transed_mean_A.head<3>());
234 J_target.block<3, 3>(0, 3) = Eigen::Matrix3d::Identity();
236 Eigen::Matrix<double, 4, 6> J_source = Eigen::Matrix<double, 4, 6>::Zero();
237 J_source.block<3, 3>(0, 0) = delta.linear() * gtsam::SO3::Hat(mean_A.template head<3>());
238 J_source.block<3, 3>(0, 3) = -delta.linear();
240 Eigen::Matrix<double, 6, 4> J_target_mahalanobis = J_target.transpose() * mahalanobis;
241 Eigen::Matrix<double, 6, 4> J_source_mahalanobis = J_source.transpose() * mahalanobis;
243 *H_target += J_target_mahalanobis * J_target;
244 *H_source += J_source_mahalanobis * J_source;
245 *H_target_source += J_target_mahalanobis * J_source;
246 *b_target += J_target_mahalanobis * residual;
247 *b_source += J_source_mahalanobis * residual;
252 if (is_omp_default() || num_threads == 1) {
253 return scan_matching_reduce_omp(perpoint_task, frame::size(*source), num_threads, H_target, H_source, H_target_source, b_target, b_source);
255 return scan_matching_reduce_tbb(perpoint_task, frame::size(*source), H_target, H_source, H_target_source, b_target, b_source);
Definition gaussian_voxelmap_cpu.hpp:73
Abstraction of LSQ-based scan matching constraints between point clouds.
Definition integrated_matching_cost_factor.hpp:19
Voxelized GICP matching cost factor Koide et al., "Voxelized GICP for Fast and Accurate 3D Point Clou...
Definition integrated_vgicp_factor.hpp:25
virtual size_t memory_usage() const override
Calculate the memory usage of this factor.
Definition integrated_vgicp_factor_impl.hpp:93
virtual void print(const std::string &s="", const gtsam::KeyFormatter &keyFormatter=gtsam::DefaultKeyFormatter) const override
Print the factor information.
Definition integrated_vgicp_factor_impl.hpp:80
IntegratedVGICPFactor_(gtsam::Key target_key, gtsam::Key source_key, const GaussianVoxelMap::ConstPtr &target_voxels, const std::shared_ptr< const SourceFrame > &source)
Create a binary VGICP factor between target and source poses.
Definition integrated_vgicp_factor_impl.hpp:21
Gaussian voxel that computes and stores voxel mean and covariance.
Definition gaussian_voxelmap_cpu.hpp:13