Bayes Filters Library
Another Kalman-like filter: the Unscented Kalman Filter

The following snippet code shows how to run an Unscented Kalman Filter (KF) using the implementation provided by the library.

1 /*
2  * Copyright (C) 2016-2019 Istituto Italiano di Tecnologia (IIT)
3  *
4  * This software may be modified and distributed under the terms of the
5  * BSD 3-Clause license. See the accompanying LICENSE file for details.
6  */
7 
15 #include <BayesFilters/utils.h>
17 
18 #include <string>
19 
20 #include <Eigen/Dense>
21 
22 using namespace bfl;
23 using namespace Eigen;
24 
25 
26 class UKFSimulation : public GaussianFilter
27 {
28 public:
29  UKFSimulation
30  (
31  Gaussian& initial_state,
32  std::unique_ptr<GaussianPrediction> prediction,
33  std::unique_ptr<GaussianCorrection> correction,
34  std::size_t simulation_steps
35  ) noexcept :
36  GaussianFilter(std::move(prediction), std::move(correction)),
37  predicted_state_(initial_state.dim_linear, initial_state.dim_circular),
38  corrected_state_(initial_state),
39  simulation_steps_(simulation_steps)
40  { }
41 
42 protected:
43  bool run_condition() override
44  {
45  if (step_number() < simulation_steps_)
46  return true;
47  else
48  return false;
49  }
50 
51 
52  bool initialization_step() override
53  {
54  return true;
55  }
56 
57 
58  void filtering_step() override
59  {
60  prediction().predict(corrected_state_, predicted_state_);
61  correction().freeze_measurements();
62  correction().correct(predicted_state_, corrected_state_);
63 
64  log();
65  }
66 
67 
68  std::vector<std::string> log_file_names(const std::string& folder_path, const std::string& file_name_prefix) override
69  {
70  return {folder_path + "/" + file_name_prefix + "_pred_mean",
71  folder_path + "/" + file_name_prefix + "_cor_mean"};
72  }
73 
74 
75  void log() override
76  {
77  logger(predicted_state_.mean().transpose(), corrected_state_.mean().transpose());
78  }
79 
80 private:
81  Gaussian predicted_state_;
82 
83  Gaussian corrected_state_;
84 
85  std::size_t simulation_steps_;
86 };
87 
88 
89 int main(int argc, char* argv[])
90 {
91  std::cout << "Running a UKF filter on a simulated target." << std::endl;
92 
93  const bool write_to_file = (argc > 1 ? std::string(argv[1]) == "ON" : false);
94  if (write_to_file)
95  std::cout << "Data is logged in the test folder with prefix testUKF." << std::endl;
96 
97 
98  /* A set of parameters needed to run an unscented Kalman filter in a simulated environment. */
99  Vector4d initial_simulated_state(10.0f, 0.0f, 10.0f, 0.0f);
100  std::size_t simulation_time = 100;
101  /* Initialize unscented transform parameters. */
102  double alpha = 1.0;
103  double beta = 2.0;
104  double kappa = 0.0;
105 
106 
107  /* Step 1 - Initialization */
108 
109  std::size_t state_size = 4;
110  Gaussian initial_state(state_size);
111  Vector4d initial_mean(4.0f, 0.04f, 15.0f, 0.4f);
112  Matrix4d initial_covariance;
113  initial_covariance << pow(0.05, 2), 0, 0, 0,
114  0, pow(0.05, 2), 0, 0,
115  0, 0, pow(0.01, 2), 0,
116  0, 0, 0, pow(0.01, 2);
117  initial_state.mean() = initial_mean;
118  initial_state.covariance() = initial_covariance;
119 
120 
121  /* Step 2 - Prediction */
122 
123  /* Step 2.1 - Define the state model. */
124 
125  /* Initialize a white noise acceleration state model. */
126  double T = 1.0f;
127  double tilde_q = 10.0f;
128 
129  std::unique_ptr<AdditiveStateModel> wna = utils::make_unique<WhiteNoiseAcceleration>(WhiteNoiseAcceleration::Dim::TwoD, T, tilde_q);
130 
131  /* Step 2.2 - Define the prediction step. */
132 
133  /* Initialize the unscented Kalman filter prediction step and pass the ownership of the state model */
134  std::unique_ptr<UKFPrediction> ukf_prediction = utils::make_unique<UKFPrediction>(std::move(wna), alpha, beta, kappa);
135 
136 
137  /* Step 3 - Correction */
138 
139  /* Step 3.1 - Define where the measurement are originated from (simulated in this case). */
140 
141  /* Initialize simulated target model with a white noise acceleration. */
142  std::unique_ptr<AdditiveStateModel> target_model = utils::make_unique<WhiteNoiseAcceleration>(WhiteNoiseAcceleration::Dim::TwoD, T, tilde_q);
143  std::unique_ptr<SimulatedStateModel> simulated_state_model = utils::make_unique<SimulatedStateModel>(std::move(target_model), initial_simulated_state, simulation_time);
144 
145  if (write_to_file)
146  simulated_state_model->enable_log("./", "testUKF");
147 
148  /* Step 3.2 - Initialize a measurement model (a linear sensor reading x and y coordinates). */
149  double sigma_x = 10.0;
150  double sigma_y = 10.0;
151  Eigen::MatrixXd R(2, 2);
152  R << std::pow(sigma_x, 2.0), 0.0,
153  0.0, std::pow(sigma_y, 2.0);
154 
155  std::unique_ptr<AdditiveMeasurementModel> simulated_linear_sensor = utils::make_unique<SimulatedLinearSensor>(std::move(simulated_state_model), SimulatedLinearSensor::LinearMatrixComponent{ 4, std::vector<std::size_t>{ 0, 2 } }, R);
156 
157  if (write_to_file)
158  simulated_linear_sensor->enable_log("./", "testUKF");
159 
160  /* Step 3.3 - Initialize the unscented Kalman filter correction step and pass the ownership of the measurement model. */
161  std::unique_ptr<UKFCorrection> ukf_correction = utils::make_unique<UKFCorrection>(std::move(simulated_linear_sensor), alpha, beta, kappa);
162 
163 
164  /* Step 4 - Assemble the unscented Kalman filter. */
165  std::cout << "Constructing unscented Kalman filter..." << std::flush;
166 
167  UKFSimulation ukf(initial_state, std::move(ukf_prediction), std::move(ukf_correction), simulation_time);
168 
169  if (write_to_file)
170  ukf.enable_log("./", "testUKF");
171 
172  std::cout << "done!" << std::endl;
173 
174 
175  /* Step 5 - Boot the filter. */
176  std::cout << "Booting unscented Kalman filter..." << std::flush;
177 
178  ukf.boot();
179 
180  std::cout << "completed!" << std::endl;
181 
182 
183  /* Step 6 - Run the filter and wait until it is closed. */
184  /* Note that since this is a simulation, the filter will end upon simulation termination. */
185  std::cout << "Running unscented Kalman filter..." << std::flush;
186 
187  ukf.run();
188 
189  std::cout << "waiting..." << std::flush;
190 
191  if (!ukf.wait())
192  return EXIT_FAILURE;
193 
194  std::cout << "completed!" << std::endl;
195 
196  return EXIT_SUCCESS;
197 }
bfl::GaussianFilter
Definition: GaussianFilter.h:21
sigma_point.h
bfl::LinearModel::LinearMatrixComponent
std::pair< std::size_t, std::vector< std::size_t > > LinearMatrixComponent
Pair of data representing.
Definition: LinearModel.h:37
GaussianFilter.h
SimulatedLinearSensor.h
bfl
Port of boost::any for C++11 compilers.
Definition: AdditiveMeasurementModel.h:13
bfl::WhiteNoiseAcceleration::Dim::TwoD
@ TwoD
utils.h
SimulatedStateModel.h
UKFCorrection.h
bfl::Gaussian
Definition: Gaussian.h:22
UKFPrediction.h
Gaussian.h
WhiteNoiseAcceleration.h