-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Add a part of the new rigid registration method [FRICP] #6199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
yaoyx689
wants to merge
24
commits into
PointCloudLibrary:master
Choose a base branch
from
yaoyx689:add_fricp
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,392
−0
Open
Changes from 22 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
aefe5db
add a part of the FRICP (robust transformation estimation)
yaoyx689 213e84f
update
yaoyx689 f2f6dea
Correct format
yaoyx689 f5d0bda
Merge branch 'PointCloudLibrary:master' into add_fricp
duanbotu123 7c81280
add Anderson acceleration fricp.hpp etc.UPdate cmakelist
duanbotu123 d87a99e
fix bug
duanbotu123 574f036
fix bug
duanbotu123 266ab88
fix bug in test
duanbotu123 b1a1a7b
fix the bug of parameter
duanbotu123 d329abf
Update test
duanbotu123 3f9a439
repush
duanbotu123 3d70839
Merge branch 'PointCloudLibrary:master' into add_fricp
duanbotu123 8efff92
fix bug in clang-tidy,merge the new update in pcl
duanbotu123 3fc1db5
fix bug in clang-tidy,merge the new update in pcl
duanbotu123 34d5dc3
fix bug in clang-tidy again
duanbotu123 e8acb9f
fix bug in clang-tidy again
duanbotu123 d5bdecc
fix bug in clang-tidy again
duanbotu123 ee430dc
fix bug in clang-tidy again
duanbotu123 0fe5fdc
Merge branch 'PointCloudLibrary:master' into add_fricp
duanbotu123 08d883c
Address all review comments in PR 6199
duanbotu123 397b7f3
Fix FRICP KdTree/Search mismatch in test_registration_api
duanbotu123 b45c4ea
Update registration/include/pcl/registration/fricp.h
duanbotu123 6ba19c8
Apply PR6199 review fixes without build artifacts
duanbotu123 1e17bf6
Update registration/include/pcl/registration/fricp.h
duanbotu123 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
185 changes: 185 additions & 0 deletions
185
registration/include/pcl/registration/anderson_acceleration.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,185 @@ | ||
| #pragma once | ||
|
|
||
| #include <pcl/exceptions.h> | ||
| #include <pcl/memory.h> | ||
|
|
||
| #include <Eigen/Core> | ||
| #include <Eigen/QR> | ||
|
|
||
| #include <algorithm> | ||
| #include <cstddef> | ||
|
|
||
| namespace pcl { | ||
| namespace registration { | ||
|
|
||
| /** | ||
| * \brief Lightweight Anderson acceleration helper used to speed up fixed-point | ||
| * iterations in FRICP. | ||
| * | ||
| * The class stores a short history of the most recent residuals and solves the | ||
| * normal equations following the scheme described in "Fast and Robust Iterative | ||
| * Closest Point", Zhang et al., 2022. | ||
| * | ||
| * Only double precision is supported internally to maximise numerical stability. | ||
| */ | ||
| class AndersonAcceleration { | ||
| public: | ||
| AndersonAcceleration() = default; | ||
|
|
||
| /** | ||
| * \brief Initialise the accelerator with a circular buffer of size \a history. | ||
| * | ||
| * \param[in] history Number of previous iterates to keep (m in the paper). | ||
| * \param[in] dimension Dimensionality of the flattened state vector. | ||
| * \param[in] initial_state Pointer to the initial state (expects | ||
| * \a dimension doubles). | ||
| */ | ||
| inline void | ||
| init(std::size_t history, std::size_t dimension, const double* initial_state) | ||
| { | ||
| if ((history == 0) || (dimension == 0)) { | ||
| PCL_THROW_EXCEPTION(pcl::BadArgumentException, | ||
| "AndersonAcceleration::init expects non-zero sizes"); | ||
| } | ||
|
|
||
| history_length_ = history; | ||
| dimension_ = dimension; | ||
| iteration_ = 0; | ||
| column_index_ = 0; | ||
| initialized_ = true; | ||
|
|
||
| current_u_.resize(dimension_); | ||
| current_F_.resize(dimension_); | ||
| prev_dG_.setZero(dimension_, history_length_); | ||
| prev_dF_.setZero(dimension_, history_length_); | ||
| normal_eq_matrix_.setZero(history_length_, history_length_); | ||
| theta_.setZero(history_length_); | ||
| dF_scale_.setZero(history_length_); | ||
|
|
||
| current_u_ = Eigen::Map<const Eigen::VectorXd>(initial_state, dimension_); | ||
| } | ||
|
|
||
| inline bool | ||
| isInitialized() const | ||
| { | ||
| return initialized_; | ||
| } | ||
|
|
||
| inline std::size_t | ||
| history() const | ||
| { | ||
| return history_length_; | ||
| } | ||
|
|
||
| inline std::size_t | ||
| dimension() const | ||
| { | ||
| return dimension_; | ||
| } | ||
|
|
||
| inline void | ||
| replace(const double* state) | ||
| { | ||
| if (!initialized_) | ||
| return; | ||
| current_u_ = Eigen::Map<const Eigen::VectorXd>(state, dimension_); | ||
| } | ||
|
|
||
| inline void | ||
| reset(const double* state) | ||
| { | ||
| if (!initialized_) | ||
| return; | ||
| iteration_ = 0; | ||
| column_index_ = 0; | ||
| current_u_ = Eigen::Map<const Eigen::VectorXd>(state, dimension_); | ||
| } | ||
|
|
||
| /** | ||
| * \brief Apply one Anderson acceleration update. | ||
| * | ||
| * \param[in] next_state Flattened state obtained from the fixed-point iteration. | ||
| * \return Reference to the accelerated state vector. | ||
| */ | ||
| inline const Eigen::VectorXd& | ||
| compute(const double* next_state) | ||
| { | ||
| if (!initialized_) { | ||
| PCL_THROW_EXCEPTION(pcl::PCLException, | ||
| "AndersonAcceleration::compute called before init"); | ||
| } | ||
|
|
||
| Eigen::Map<const Eigen::VectorXd> G(next_state, dimension_); | ||
| current_F_ = G - current_u_; | ||
|
|
||
| constexpr double eps = 1e-14; | ||
|
|
||
| if (iteration_ == 0) { | ||
| prev_dF_.col(0) = -current_F_; | ||
| prev_dG_.col(0) = -G; | ||
| current_u_ = G; | ||
| } | ||
| else { | ||
| prev_dF_.col(column_index_) += current_F_; | ||
| prev_dG_.col(column_index_) += G; | ||
|
|
||
| double scale = std::max(eps, prev_dF_.col(column_index_).norm()); | ||
| dF_scale_(column_index_) = scale; | ||
| prev_dF_.col(column_index_) /= scale; | ||
|
|
||
| const std::size_t m_k = std::min(history_length_, iteration_); | ||
|
|
||
| if (m_k == 1) { | ||
| theta_(0) = 0.0; | ||
| const double dF_norm = prev_dF_.col(column_index_).norm(); | ||
| normal_eq_matrix_(0, 0) = dF_norm * dF_norm; | ||
| if (dF_norm > eps) { | ||
| theta_(0) = (prev_dF_.col(column_index_) / dF_norm).dot(current_F_ / dF_norm); | ||
| } | ||
| } | ||
| else { | ||
| // update Gram matrix row/column corresponding to the newest column | ||
| const Eigen::VectorXd new_inner_prod = prev_dF_.col(column_index_).transpose() * | ||
| prev_dF_.block(0, 0, dimension_, m_k); | ||
| normal_eq_matrix_.block(column_index_, 0, 1, m_k) = new_inner_prod.transpose(); | ||
| normal_eq_matrix_.block(0, column_index_, m_k, 1) = new_inner_prod; | ||
|
|
||
| cod_.compute(normal_eq_matrix_.block(0, 0, m_k, m_k)); | ||
| theta_.head(m_k) = | ||
| cod_.solve(prev_dF_.block(0, 0, dimension_, m_k).transpose() * current_F_); | ||
| } | ||
|
|
||
| const Eigen::ArrayXd scaled_theta = | ||
| theta_.head(m_k).array() / dF_scale_.head(m_k).array(); | ||
| current_u_ = G - prev_dG_.block(0, 0, dimension_, m_k) * scaled_theta.matrix(); | ||
|
|
||
| column_index_ = (column_index_ + 1) % history_length_; | ||
| prev_dF_.col(column_index_) = -current_F_; | ||
| prev_dG_.col(column_index_) = -G; | ||
| } | ||
|
|
||
| ++iteration_; | ||
| return current_u_; | ||
| } | ||
|
|
||
| private: | ||
| std::size_t history_length_{0}; | ||
| std::size_t dimension_{0}; | ||
| std::size_t iteration_{0}; | ||
| std::size_t column_index_{0}; | ||
| bool initialized_{false}; | ||
|
|
||
| Eigen::VectorXd current_u_; | ||
| Eigen::VectorXd current_F_; | ||
| Eigen::MatrixXd prev_dG_; | ||
| Eigen::MatrixXd prev_dF_; | ||
| Eigen::MatrixXd normal_eq_matrix_; | ||
| Eigen::VectorXd theta_; | ||
| Eigen::VectorXd dF_scale_; | ||
| Eigen::CompleteOrthogonalDecomposition<Eigen::MatrixXd> cod_; | ||
|
|
||
| PCL_MAKE_ALIGNED_OPERATOR_NEW | ||
| }; | ||
|
|
||
| } // namespace registration | ||
| } // namespace pcl | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a compile-time type mismatch:
prev_dF_.col(...).transpose() * prev_dF_.block(...)is a 1×m_k row vector, but it is being stored in anEigen::VectorXd(m_k×1). This should be anEigen::RowVectorXd(or explicitly transpose the product) so the subsequent assignments tonormal_eq_matrix_match dimensions.