22 overlap_rate(overlap_rate),
23 symmetric_neighbors(symmetric_neighbors),
24 feature_weight(feature_weight),
25 neighbor_weight(1 - feature_weight) {}
35 config.get<double>(
"feature_weight", 0.7),
36 config.get<int>(
"symmetric_neighbors", 10)) {}
41 a_current.resize(
a.size());
42 a_features.resize(
a.size());
43 b_features.resize(
b.size());
48 compute_features(
b, b_cm, b_features);
50 norm_feature_dists = compute_norm_dists(a_features, b_features);
56 const size_t n =
a.size();
58 for (
size_t i = 0; i < n; i++) {
85 [](
const auto&
a,
const auto&
b) { return a.cost < b.cost; });
86 size_t new_n =
static_cast<size_t>(overlap_rate * n);
87 new_n = std::max<size_t>(new_n, 1);
90 std::vector<icp::Vector> trimmed_current(new_n);
91 std::vector<icp::Vector> trimmed_b(new_n);
92 for (
size_t i = 0; i < new_n; i++) {
93 trimmed_current[i] = a_current[
matches[i].point];
101 Matrix N = Matrix::Zero();
102 for (
size_t i = 0; i < new_n; i++) {
103 N += (trimmed_current[i] - trimmed_cm) * (trimmed_b[i] - trimmed_b_cm).transpose();
106 auto svd = N.jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV);
109 Matrix R = V * U.transpose();
112 if (R.determinant() < 0) {
113 V = V * Eigen::DiagonalMatrix<double, 2>(1, -1);
114 R = V * U.transpose();
118 RBTransform step(trimmed_b_cm - R * trimmed_cm, R);
123 void FeatureAware::compute_matches() {
124 const size_t n =
a.size();
125 const size_t m =
b.size();
127 Eigen::MatrixXd norm_dists = compute_norm_dists(a_current,
b);
129 for (
size_t i = 0; i < n; i++) {
131 matches[i].cost = std::numeric_limits<double>::infinity();
132 for (
size_t j = 0; j < m; j++) {
133 double dist = norm_dists(i, j);
134 double feature_dist = norm_feature_dists(i, j);
135 double cost = neighbor_weight * dist + feature_weight * feature_dist;
145 void FeatureAware::compute_features(
const std::vector<Vector>& points,
Vector cm,
146 std::vector<FeatureVector>& features) {
147 for (
size_t i = 0; i < points.size(); i++) {
149 double cm_dist_p = (p - cm).norm();
151 FeatureVector feature(2 * symmetric_neighbors);
154 size_t lower = std::max((
size_t)0, i - symmetric_neighbors);
155 for (
size_t j = lower; j < i; j++) {
157 double cm_dist_q = (q - cm).norm();
158 feature[j - lower] = cm_dist_q - cm_dist_p;
161 size_t upper = std::min(points.size() - 1, i + symmetric_neighbors);
162 for (
size_t j = i + 1; j <= upper; j++) {
164 double cm_dist_q = (q - cm).norm();
165 feature[j - i - 1 + symmetric_neighbors] = cm_dist_q - cm_dist_p;
168 features[i] = feature;
FeatureAware(double overlap_rate, double feature_weight, int symmetric_neighbors)
void setup() override
Per-method setup code.
void iterate() override
Perform one iteration of ICP for the point clouds a and b provided with ICP::begin.
Configuration for ICP instances.
Interface for iterative closest points.
RBTransform transform
The current point cloud transformation that is being optimized.
std::vector< Vector > a
The source point cloud.
std::vector< Vector > b
The destination point cloud.
std::vector< Match > matches
The pairing of each point in a to its closest in b.
Vector get_centroid(const std::vector< Vector > &points)