Files
agv_pro_ros2/FAST_LIO/include/ikd-Tree/ikd_Tree.h
T

345 lines
10 KiB
C++

#pragma once
#include <stdio.h>
#include <queue>
#include <pthread.h>
#include <chrono>
#include <time.h>
#include <unistd.h>
#include <math.h>
#include <algorithm>
#include <memory.h>
#include <pcl/point_types.h>
#define EPSS 1e-6
#define Minimal_Unbalanced_Tree_Size 10
#define Multi_Thread_Rebuild_Point_Num 1500
#define DOWNSAMPLE_SWITCH true
#define ForceRebuildPercentage 0.2
#define Q_LEN 1000000
using namespace std;
// typedef pcl::PointXYZINormal PointType;
// typedef vector<PointType, Eigen::aligned_allocator<PointType>> PointVector;
struct BoxPointType
{
float vertex_min[3];
float vertex_max[3];
};
enum operation_set
{
ADD_POINT,
DELETE_POINT,
DELETE_BOX,
ADD_BOX,
DOWNSAMPLE_DELETE,
PUSH_DOWN
};
enum delete_point_storage_set
{
NOT_RECORD,
DELETE_POINTS_REC,
MULTI_THREAD_REC
};
template <typename PointType>
class KD_TREE
{
// using MANUAL_Q_ = MANUAL_Q<typename PointType>;
// using PointVector = std::vector<PointType>;
// using MANUAL_Q_ = MANUAL_Q<typename PointType>;
public:
using PointVector = std::vector<PointType, Eigen::aligned_allocator<PointType>>;
using Ptr = std::shared_ptr<KD_TREE<PointType>>;
struct KD_TREE_NODE
{
PointType point;
int division_axis;
int TreeSize = 1;
int invalid_point_num = 0;
int down_del_num = 0;
bool point_deleted = false;
bool tree_deleted = false;
bool point_downsample_deleted = false;
bool tree_downsample_deleted = false;
bool need_push_down_to_left = false;
bool need_push_down_to_right = false;
bool working_flag = false;
pthread_mutex_t push_down_mutex_lock;
float node_range_x[2], node_range_y[2], node_range_z[2];
float radius_sq;
KD_TREE_NODE *left_son_ptr = nullptr;
KD_TREE_NODE *right_son_ptr = nullptr;
KD_TREE_NODE *father_ptr = nullptr;
// For paper data record
float alpha_del;
float alpha_bal;
};
struct Operation_Logger_Type
{
PointType point;
BoxPointType boxpoint;
bool tree_deleted, tree_downsample_deleted;
operation_set op;
};
// static const PointType zeroP;
struct PointType_CMP
{
PointType point;
float dist = 0.0;
PointType_CMP(PointType p = PointType(), float d = INFINITY)
{
this->point = p;
this->dist = d;
};
bool operator<(const PointType_CMP &a) const
{
if (fabs(dist - a.dist) < 1e-10)
return point.x < a.point.x;
else
return dist < a.dist;
}
};
class MANUAL_HEAP
{
public:
MANUAL_HEAP(int max_capacity = 100)
{
cap = max_capacity;
heap = new PointType_CMP[max_capacity];
heap_size = 0;
}
~MANUAL_HEAP()
{
delete[] heap;
}
void pop()
{
if (heap_size == 0)
return;
heap[0] = heap[heap_size - 1];
heap_size--;
MoveDown(0);
return;
}
PointType_CMP top()
{
return heap[0];
}
void push(PointType_CMP point)
{
if (heap_size >= cap)
return;
heap[heap_size] = point;
FloatUp(heap_size);
heap_size++;
return;
}
int size()
{
return heap_size;
}
void clear()
{
heap_size = 0;
return;
}
private:
PointType_CMP *heap;
void MoveDown(int heap_index)
{
int l = heap_index * 2 + 1;
PointType_CMP tmp = heap[heap_index];
while (l < heap_size)
{
if (l + 1 < heap_size && heap[l] < heap[l + 1])
l++;
if (tmp < heap[l])
{
heap[heap_index] = heap[l];
heap_index = l;
l = heap_index * 2 + 1;
}
else
break;
}
heap[heap_index] = tmp;
return;
}
void FloatUp(int heap_index)
{
int ancestor = (heap_index - 1) / 2;
PointType_CMP tmp = heap[heap_index];
while (heap_index > 0)
{
if (heap[ancestor] < tmp)
{
heap[heap_index] = heap[ancestor];
heap_index = ancestor;
ancestor = (heap_index - 1) / 2;
}
else
break;
}
heap[heap_index] = tmp;
return;
}
int heap_size = 0;
int cap = 0;
};
class MANUAL_Q
{
private:
int head = 0, tail = 0, counter = 0;
Operation_Logger_Type q[Q_LEN];
bool is_empty;
public:
void pop()
{
if (counter == 0)
return;
head++;
head %= Q_LEN;
counter--;
if (counter == 0)
is_empty = true;
return;
}
Operation_Logger_Type front()
{
return q[head];
}
Operation_Logger_Type back()
{
return q[tail];
}
void clear()
{
head = 0;
tail = 0;
counter = 0;
is_empty = true;
return;
}
void push(Operation_Logger_Type op)
{
q[tail] = op;
counter++;
if (is_empty)
is_empty = false;
tail++;
tail %= Q_LEN;
}
bool empty()
{
return is_empty;
}
int size()
{
return counter;
}
};
private:
// Multi-thread Tree Rebuild
bool termination_flag = false;
bool rebuild_flag = false;
pthread_t rebuild_thread;
pthread_mutex_t termination_flag_mutex_lock, rebuild_ptr_mutex_lock, working_flag_mutex, search_flag_mutex;
pthread_mutex_t rebuild_logger_mutex_lock, points_deleted_rebuild_mutex_lock;
// queue<Operation_Logger_Type> Rebuild_Logger;
MANUAL_Q Rebuild_Logger;
PointVector Rebuild_PCL_Storage;
KD_TREE_NODE **Rebuild_Ptr = nullptr;
int search_mutex_counter = 0;
static void *multi_thread_ptr(void *arg);
void multi_thread_rebuild();
void start_thread();
void stop_thread();
void run_operation(KD_TREE_NODE **root, Operation_Logger_Type operation);
// KD Tree Functions and augmented variables
int Treesize_tmp = 0, Validnum_tmp = 0;
float alpha_bal_tmp = 0.5, alpha_del_tmp = 0.0;
float delete_criterion_param = 0.5f;
float balance_criterion_param = 0.7f;
float downsample_size = 0.2f;
bool Delete_Storage_Disabled = false;
KD_TREE_NODE *STATIC_ROOT_NODE = nullptr;
PointVector Points_deleted;
PointVector Downsample_Storage;
PointVector Multithread_Points_deleted;
void InitTreeNode(KD_TREE_NODE *root);
void Test_Lock_States(KD_TREE_NODE *root);
void BuildTree(KD_TREE_NODE **root, int l, int r, PointVector &Storage);
void Rebuild(KD_TREE_NODE **root);
int Delete_by_range(KD_TREE_NODE **root, BoxPointType boxpoint, bool allow_rebuild, bool is_downsample);
void Delete_by_point(KD_TREE_NODE **root, PointType point, bool allow_rebuild);
void Add_by_point(KD_TREE_NODE **root, PointType point, bool allow_rebuild, int father_axis);
void Add_by_range(KD_TREE_NODE **root, BoxPointType boxpoint, bool allow_rebuild);
void Search(KD_TREE_NODE *root, int k_nearest, PointType point, MANUAL_HEAP &q, float max_dist); //priority_queue<PointType_CMP>
void Search_by_range(KD_TREE_NODE *root, BoxPointType boxpoint, PointVector &Storage);
void Search_by_radius(KD_TREE_NODE *root, PointType point, float radius, PointVector &Storage);
bool Criterion_Check(KD_TREE_NODE *root);
void Push_Down(KD_TREE_NODE *root);
void Update(KD_TREE_NODE *root);
void delete_tree_nodes(KD_TREE_NODE **root);
void downsample(KD_TREE_NODE **root);
bool same_point(PointType a, PointType b);
float calc_dist(PointType a, PointType b);
float calc_box_dist(KD_TREE_NODE *node, PointType point);
static bool point_cmp_x(PointType a, PointType b);
static bool point_cmp_y(PointType a, PointType b);
static bool point_cmp_z(PointType a, PointType b);
public:
KD_TREE(float delete_param = 0.5, float balance_param = 0.6, float box_length = 0.2);
~KD_TREE();
void Set_delete_criterion_param(float delete_param)
{
delete_criterion_param = delete_param;
}
void Set_balance_criterion_param(float balance_param)
{
balance_criterion_param = balance_param;
}
void set_downsample_param(float downsample_param)
{
downsample_size = downsample_param;
}
void InitializeKDTree(float delete_param = 0.5, float balance_param = 0.7, float box_length = 0.2);
int size();
int validnum();
void root_alpha(float &alpha_bal, float &alpha_del);
void Build(PointVector point_cloud);
void Nearest_Search(PointType point, int k_nearest, PointVector &Nearest_Points, vector<float> &Point_Distance, float max_dist = INFINITY);
void Box_Search(const BoxPointType &Box_of_Point, PointVector &Storage);
void Radius_Search(PointType point, const float radius, PointVector &Storage);
int Add_Points(PointVector &PointToAdd, bool downsample_on);
void Add_Point_Boxes(vector<BoxPointType> &BoxPoints);
void Delete_Points(PointVector &PointToDel);
int Delete_Point_Boxes(vector<BoxPointType> &BoxPoints);
void flatten(KD_TREE_NODE *root, PointVector &Storage, delete_point_storage_set storage_type);
void acquire_removed_points(PointVector &removed_points);
BoxPointType tree_range();
PointVector PCL_Storage;
KD_TREE_NODE *Root_Node = nullptr;
int max_queue_size = 0;
};
// template <typename PointType>
// PointType KD_TREE<PointType>::zeroP = PointType(0,0,0);