Apollo  6.0
Open source self driving car software
i_ransac.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2018 The Apollo Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *****************************************************************************/
16 #pragma once
17 
20 
21 #include <limits>
22 
23 namespace apollo {
24 namespace perception {
25 namespace common {
26 // Compute the number of trials for Ransac. Number of trials is chosen
27 // sufficiently high to ensure with a probability "confidence" that at
28 // least one of the random samples of data is free from outliers.
29 // "inlierprob" is the probability that any selected data point is an inlier
30 inline int IRansacTrials(int sample_size, double confidence,
31  double inlierprob) {
32  return inlierprob > 0.0
33  ? IRound(IDiv(ILog(1.0 - confidence),
34  ILog(1.0 - IPow(inlierprob, sample_size))))
35  : std::numeric_limits<int>::max();
36 }
37 
38 // Using Ransac to fit a model to data set which contains outliers
39 // The function needs 2n entries of scratch space in inliers
40 template <typename T, int l, int lp, int k, int s,
41  void (*HypogenFunc)(const T* x, const T* xp, T* model),
42  void (*CostFunc)(const T* model, const T* x, const T* xp, int n,
43  int* nr_liner, int* inliers, T* cost, T error_tol),
44  void (*RefitFunc)(T* x, T* xp, int* inliers, T* model, int n,
45  int nr_liner)>
46 bool RobustBinaryFitRansac(T* x, T* xp, int n, T* model, int* consensus_size,
47  int* inliers, T error_tol,
48  bool re_est_model_w_inliers = false,
49  bool adaptive_trial_count = false,
50  double confidence = 0.99, double inlierprob = 0.5,
51  int min_nr_inliers = s,
52  bool random_shuffle_inputs = false) {
53  const int kSize = s;
54  const int kLength = l;
55  const int kLp = lp;
56  const int kKsize = k;
57  int indices[kSize];
58  T samples_x[kLength * kSize];
59  T samples_xp[kLp * kSize];
60  T tmp_model[kKsize];
61  T cost = std::numeric_limits<T>::max();
62  T best_cost = std::numeric_limits<T>::max();
63 
64  if (n < min_nr_inliers) {
65  return false;
66  }
67 
68  double actual_inlierprob = 0.0, tmp_inlierprob;
69  int nr_trials = IRansacTrials(s, confidence, inlierprob);
70 
71  int nr_inliers = 0;
72  int rseed = I_DEFAULT_SEED;
73  int sample_count = 0;
74  int i, idxl, idxlp, il, ilp;
75  *consensus_size = 0; // initialize the size of the consensus set to zero
76  IZero(model, k); // initialize the model with zeros
77 
78  if (random_shuffle_inputs) {
79  IRandomizedShuffle(x, xp, n, l, lp, &rseed);
80  }
81 
82  while (nr_trials > sample_count) {
83  // generate random indices
84  IRandomSample(indices, s, n, &rseed);
85  // prepare data for model fitting
86  for (i = 0; i < s; ++i) {
87  idxl = indices[i] * l;
88  idxlp = indices[i] * lp;
89  il = i * l;
90  ilp = i * lp;
91  ICopy(x + idxl, samples_x + il, l);
92  ICopy(xp + idxlp, samples_xp + ilp, lp);
93  }
94 
95  // estimate model
96  HypogenFunc(samples_x, samples_xp, tmp_model);
97 
98  // validate model
99  CostFunc(tmp_model, x, xp, n, &nr_inliers, inliers + n, &cost, error_tol);
100  if ((nr_inliers > *consensus_size) ||
101  (nr_inliers == *consensus_size && cost < best_cost)) {
102  *consensus_size = nr_inliers;
103  best_cost = cost;
104  ICopy(tmp_model, model, k);
105  ICopy(inliers + n, inliers, *consensus_size); // record inlier indices
106  if (adaptive_trial_count) {
107  tmp_inlierprob = IDiv(static_cast<double>(*consensus_size), n);
108  if (tmp_inlierprob > actual_inlierprob) {
109  actual_inlierprob = tmp_inlierprob;
110  nr_trials = IRansacTrials(s, confidence, actual_inlierprob);
111  }
112  }
113  }
114  sample_count++;
115  }
116  bool succeeded = *consensus_size >= min_nr_inliers;
117 
118  if (succeeded && re_est_model_w_inliers && RefitFunc != nullptr) {
119  RefitFunc(x, xp, inliers, model, n, *consensus_size);
120  }
121  return succeeded;
122 }
123 
124 } // namespace common
125 } // namespace perception
126 } // namespace apollo
void ICopy(const T *src, T *dst, int n)
Definition: i_blas.h:27
int IRound(int a)
Definition: i_basic.h:197
PlanningContext is the runtime context in planning. It is persistent across multiple frames...
Definition: atomic_hash_map.h:25
float IPow(float a, float b)
Definition: i_basic.h:142
float ILog(float x)
Definition: i_basic.h:126
void IRandomizedShuffle(T *A, int n, int l, int *s)
Definition: i_rand.h:78
float IDiv(float a, float b)
Definition: i_basic.h:35
int IRansacTrials(int sample_size, double confidence, double inlierprob)
Definition: i_ransac.h:30
const int I_DEFAULT_SEED
Definition: i_rand.h:24
void IRandomSample(int *sample, int n, int pool_size, int *s)
Definition: i_rand.h:47
void IZero(T *a, int n)
Definition: i_blas.h:320
bool RobustBinaryFitRansac(T *x, T *xp, int n, T *model, int *consensus_size, int *inliers, T error_tol, bool re_est_model_w_inliers=false, bool adaptive_trial_count=false, double confidence=0.99, double inlierprob=0.5, int min_nr_inliers=s, bool random_shuffle_inputs=false)
Definition: i_ransac.h:46