粒子滤波c语言源码解读
程序员文章站
2022-07-14 16:16:19
...
粒子滤波c语言源码解读
Information for an entire filter
typedef struct _pf_t
{
// This min and max number of samples
int min_samples, max_samples;
// Population size parameters
double pop_err, pop_z;
// The sample sets. We keep two sets and use [current_set]
// to identify the active set.
int current_set;
pf_sample_set_t sets[2];
// Running averages, slow and fast, of likelihood
double w_slow, w_fast;
// Decay rates for running averages
double alpha_slow, alpha_fast;
// Function used to draw random pose samples
pf_init_model_fn_t random_pose_fn;
void *random_pose_data;
double dist_threshold; //distance threshold in each axis over which the pf is considered to not be converged
int converged;
} pf_t;
重点需要理解粒子集pf_sample_set_t。首先,它是一个二维数组,也就是说它始终维护着“两个粒子集”;其次,它的每个粒子集又是一个结构体;还有它通常配合current_set确定当前所指向的粒子集是哪一个;两个粒子集的作用分别是计算权重(weighted)和重采样(resample)。
粒子集
typedef struct _pf_sample_set_t
{
// The samples
int sample_count;
pf_sample_t *samples;
// A kdtree encoding the histogram
pf_kdtree_t *kdtree;
// Clusters
int cluster_count, cluster_max_count;
pf_cluster_t *clusters;
// Filter statistics
pf_vector_t mean;
pf_matrix_t cov;
int converged;
} pf_sample_set_t;
重点需要理解pf_kdtree_t。K-D树是一个分类/搜索的多维(K维)数据结构。
K-D树结构
typedef struct
{
// Cell size
double size[3];
// The root node of the tree
pf_kdtree_node_t *root;
// The number of nodes in the tree
int node_count, node_max_count;
pf_kdtree_node_t *nodes;
// The number of leaf nodes in the tree
int leaf_count;
} pf_kdtree_t;
KD树由若干结点组成,结点结构如下:
typedef struct pf_kdtree_node
{
// Depth in the tree
int leaf, depth;
// Pivot dimension and value
int pivot_dim;
double pivot_value;
// The key for this node
int key[3];
// The value for this node
double value;
// The cluster label (leaf nodes)
int cluster;
// Child nodes
struct pf_kdtree_node *children[2];
} pf_kdtree_node_t;
对KD树初始化
pf_kdtree_t *self;
self = calloc(1, sizeof(pf_kdtree_t));
//make the resolution (size) as arguments
self->size[0] = xres;
self->size[1] = yres;
self->size[2] = (ares * M_PI / 180);
//self->size[0] = 0.50;
//self->size[1] = 0.50;
//self->size[2] = (10 * M_PI / 180);
self->root = NULL;
self->node_count = 0;
self->node_max_count = max_size; //通常是最大粒子数量
self->nodes = calloc(self->node_max_count, sizeof(pf_kdtree_node_t));
self->leaf_count = 0;
插入粒子位姿到KD树,更新根结点(root)
self->root = pf_kdtree_insert_node(self, NULL, self->root, key, value);
pf_kdtree_node_t *pf_kdtree_insert_node(pf_kdtree_t *self, pf_kdtree_node_t *parent,
pf_kdtree_node_t *node, int key[], double value)
{
int i;
int split, max_split;
// If the node doesnt exist yet...
if (node == NULL)
{
//assert(self->node_count < self->node_max_count);//if this happens, should expand the size of this kdtree
node = self->nodes + self->node_count++;
memset(node, 0, sizeof(pf_kdtree_node_t));
node->leaf = 1;
if (parent == NULL)
node->depth = 0;
else
node->depth = parent->depth + 1;
for (i = 0; i < 3; i++)
node->key[i] = key[i];
node->value = value;
self->leaf_count += 1;
}
// If the node exists, and it is a leaf node...
else if (node->leaf)
{
// If the keys are equal, increment the value
if (pf_kdtree_equal(self, key, node->key))
{
node->value += value;
}
// The keys are not equal, so split this node
else
{
// Find the dimension with the largest variance and do a mean
// split
max_split = 0;
node->pivot_dim = -1;
for (i = 0; i < 3; i++)
{
split = abs(key[i] - node->key[i]);
if (split > max_split)
{
max_split = split;
node->pivot_dim = i;
}
}
assert(node->pivot_dim >= 0);
node->pivot_value = (key[node->pivot_dim] + node->key[node->pivot_dim]) / 2.0;
if (key[node->pivot_dim] < node->pivot_value)
{
node->children[0] = pf_kdtree_insert_node(self, node, NULL, key, value);
node->children[1] = pf_kdtree_insert_node(self, node, NULL, node->key, node->value);
}
else
{
node->children[0] = pf_kdtree_insert_node(self, node, NULL, node->key, node->value);
node->children[1] = pf_kdtree_insert_node(self, node, NULL, key, value);
}
node->leaf = 0;
self->leaf_count -= 1;
}
}
// If the node exists, and it has children...
else
{
assert(node->children[0] != NULL);
assert(node->children[1] != NULL);
if (key[node->pivot_dim] < node->pivot_value)
pf_kdtree_insert_node(self, node, node->children[0], key, value);
else
pf_kdtree_insert_node(self, node, node->children[1], key, value);
}
return node;
}
下一篇: Java:ArrayList源码分析