Skip to content

Commit

Permalink
improve knn performance (#70)
Browse files Browse the repository at this point in the history
* improve knn result collection

* optimize expmap
  • Loading branch information
koide3 authored Jun 21, 2024
1 parent 7e42a90 commit 0d3f5e6
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 28 deletions.
27 changes: 14 additions & 13 deletions include/small_gicp/ann/knn_result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct KnnResult {
/// @param indices Buffer to store indices (must be larger than k=max(N, num_neighbors))
/// @param distances Buffer to store distances (must be larger than k=max(N, num_neighbors))
/// @param num_neighbors Number of neighbors to search (must be -1 for static case N > 0)
explicit KnnResult(size_t* indices, double* distances, int num_neighbors = -1) : num_neighbors(num_neighbors), indices(indices), distances(distances) {
explicit KnnResult(size_t* indices, double* distances, int num_neighbors = -1) : capacity(num_neighbors), num_found_neighbors(0), indices(indices), distances(distances) {
if constexpr (N > 0) {
if (num_neighbors >= 0) {
std::cerr << "warning: Specifying dynamic num_neighbors=" << num_neighbors << " for a static KNN result container (N=" << N << ")" << std::endl;
Expand All @@ -53,12 +53,12 @@ struct KnnResult {
if constexpr (N > 0) {
return N;
} else {
return num_neighbors;
return capacity;
}
}

/// @brief Number of found neighbors.
size_t num_found() const { return std::distance(indices, std::find(indices, indices + buffer_size(), INVALID)); }
size_t num_found() const { return num_found_neighbors; }

/// @brief Worst distance in the result.
double worst_distance() const { return distances[buffer_size() - 1]; }
Expand All @@ -73,21 +73,22 @@ struct KnnResult {
indices[0] = index;
distances[0] = distance;
} else {
for (int i = buffer_size() - 1; i >= 0; i--) {
if (i == 0 || distance >= distances[i - 1]) {
indices[i] = index;
distances[i] = distance;
break;
}

indices[i] = indices[i - 1];
distances[i] = distances[i - 1];
int insert_loc = std::min<int>(num_found_neighbors, buffer_size() - 1);
for (; insert_loc > 0 && distance < distances[insert_loc - 1]; insert_loc--) {
indices[insert_loc] = indices[insert_loc - 1];
distances[insert_loc] = distances[insert_loc - 1];
}

indices[insert_loc] = index;
distances[insert_loc] = distance;
}

num_found_neighbors = std::min<int>(num_found_neighbors + 1, buffer_size());
}

public:
const int num_neighbors; ///< Maximum number of neighbors to search
const int capacity; ///< Maximum number of neighbors to search
int num_found_neighbors; ///< Number of found neighbors
size_t* indices; ///< Indices of neighbors
double* distances; ///< Distances to neighbors
};
Expand Down
2 changes: 1 addition & 1 deletion include/small_gicp/registration/optimizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ struct LevenbergMarquardtOptimizer {
bool success = false;
for (int j = 0; j < max_inner_iterations; j++) {
// Solve with damping
const Eigen::Matrix<double, 6, 1> delta = (H + lambda * Eigen ::Matrix<double, 6, 6>::Identity()).ldlt().solve(-b);
const Eigen::Matrix<double, 6, 1> delta = (H + lambda * Eigen::Matrix<double, 6, 6>::Identity()).ldlt().solve(-b);

// Validte new solution
const Eigen::Isometry3d new_T = result.T_target_source * se3_exp(delta);
Expand Down
23 changes: 9 additions & 14 deletions include/small_gicp/util/lie.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,28 +75,23 @@ inline Eigen::Quaterniond so3_exp(const Eigen::Vector3d& omega) {
/// @param a Twist vector [rx, ry, rz, tx, ty, tz]
/// @return SE3 matrix
inline Eigen::Isometry3d se3_exp(const Eigen::Matrix<double, 6, 1>& a) {
using std::cos;
using std::sin;
const Eigen::Vector3d omega = a.head<3>();

double theta = std::sqrt(omega.dot(omega));
const Eigen::Quaterniond so3 = so3_exp(omega);
const Eigen::Matrix3d Omega = skew(omega);
const Eigen::Matrix3d Omega_sq = Omega * Omega;
Eigen::Matrix3d V;
const double theta_sq = omega.dot(omega);
const double theta = std::sqrt(theta_sq);

Eigen::Isometry3d se3 = Eigen::Isometry3d::Identity();
se3.linear() = so3_exp(omega).toRotationMatrix();

if (theta < 1e-10) {
V = so3.matrix();
se3.translation() = se3.linear() * a.tail<3>();
/// Note: That is an accurate expansion!
} else {
const double theta_sq = theta * theta;
V = (Eigen::Matrix3d::Identity() + (1.0 - cos(theta)) / (theta_sq)*Omega + (theta - sin(theta)) / (theta_sq * theta) * Omega_sq);
const Eigen::Matrix3d Omega = skew(omega);
const Eigen::Matrix3d V = (Eigen::Matrix3d::Identity() + (1.0 - std::cos(theta)) / theta_sq * Omega + (theta - std::sin(theta)) / (theta_sq * theta) * Omega * Omega);
se3.translation() = V * a.tail<3>();
}

Eigen::Isometry3d se3 = Eigen::Isometry3d::Identity();
se3.linear() = so3.toRotationMatrix();
se3.translation() = V * a.tail<3>();

return se3;
}

Expand Down

0 comments on commit 0d3f5e6

Please sign in to comment.