Bayes Filters Library
GaussianMixture.cpp
Go to the documentation of this file.
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 
9 
10 using namespace bfl;
11 using namespace Eigen;
12 
13 
15  GaussianMixture(1, 1, 0, false)
16 { }
17 
18 
19 GaussianMixture::GaussianMixture(const std::size_t components, const std::size_t dim) noexcept :
20  GaussianMixture(components, dim, 0, false)
21 { }
22 
23 
25 (
26  const std::size_t components,
27  const std::size_t dim_linear,
28  const std::size_t dim_circular,
29  const bool use_quaternion
30 ) noexcept :
31  components(components),
32  use_quaternion(use_quaternion),
33  dim_circular_component(use_quaternion ? 4 : 1),
34  dim(dim_linear + dim_circular * dim_circular_component),
35  dim_linear(dim_linear),
36  dim_circular(dim_circular),
37  dim_noise(0),
38  dim_covariance(use_quaternion ? dim_linear + dim_circular * (dim_circular_component - 1) : dim),
39  mean_(dim, components),
40  covariance_(dim_covariance, dim_covariance * components),
41  weight_(components)
42 {
43  for (int i = 0; i < this->components; ++i)
44  weight_(i) = 1.0 / this->components;
45 
46  /* Note:
47  When using use_quaternion == false, the hypothesis is that there are dim_circular
48  independent states each belonging to the manifold S1 (i.e. dim_circular angles).
49  In this implementation they are treated as belonging to R^(dim_circular).
50  Hence, the size of the covariance matrix is dim_covariance x (dim_covariance * components)
51  where dim_covariance = dim.
52 
53  When using use_quaternion == true, instead the hypothesis is that there are dim_circular
54  quaternions in the state, each belonging to the manifold S3.
55  In this case, dim_circular_component = 4, since they are represented using 4 numbers.
56  However, the covariance is represented using rotation vectors in R^3 that belong to the tangent
57  space of the quaternion manifold. Hence, the size of the covariance matrix is
58  dim_covariance x (dim_covariance * components) where dim_covariance = dim_linear + dim_circular * 3.
59  */
60 
61 }
62 
63 
64 void GaussianMixture::resize(const std::size_t components, const std::size_t dim_linear, const std::size_t dim_circular)
65 {
66  std::size_t new_dim = dim_linear + dim_circular * dim_circular_component;
67  std::size_t new_dim_covariance = use_quaternion ? dim_linear + dim_circular * (dim_circular_component - 1) : new_dim;
68 
69  if ((this->dim_linear == dim_linear) && (this->dim_circular == dim_circular) && (this->components == components))
70  return;
71  else if ((this->dim == new_dim) && (this->components != components))
72  {
73  mean_.conservativeResize(NoChange, components);
74  covariance_.conservativeResize(NoChange, dim_covariance * components);
75  weight_.conservativeResize(components);
76  }
77  else
78  {
79  // In any other case, it does not make sense to do conservative resize
80  // since either old data is truncated or new data is incomplete
81  mean_.resize(new_dim, components);
82  covariance_.resize(new_dim_covariance, new_dim_covariance * components);
83  weight_.resize(components);
84  }
85 
86  this->components = components;
87  this->dim = new_dim;
88  this->dim_covariance = new_dim_covariance;
89  this->dim_linear = dim_linear;
90  this->dim_circular = dim_circular;
91 }
92 
93 
94 Ref<MatrixXd> GaussianMixture::mean()
95 {
96  return mean_;
97 }
98 
99 
100 Ref<VectorXd> GaussianMixture::mean(const std::size_t i)
101 {
102  return mean_.col(i);
103 }
104 
105 
106 double& GaussianMixture::mean(const std::size_t i, const std::size_t j)
107 {
108  return mean_(j, i);
109 }
110 
111 
112 const Ref<const MatrixXd> GaussianMixture::mean() const
113 {
114  return mean_;
115 }
116 
117 
118 const Ref<const VectorXd> GaussianMixture::mean(const std::size_t i) const
119 {
120  return mean_.col(i);
121 }
122 
123 
124 const double& GaussianMixture::mean(const std::size_t i, const std::size_t j) const
125 {
126  return mean_(j, i);
127 }
128 
129 
131 {
132  return covariance_;
133 }
134 
135 
136 Ref<MatrixXd> GaussianMixture::covariance(const std::size_t i)
137 {
138  return covariance_.middleCols(this->dim_covariance * i, this->dim_covariance);
139 }
140 
141 
142 double& GaussianMixture::covariance(const std::size_t i, const std::size_t j, const std::size_t k)
143 {
144  return covariance_(j, (this->dim_covariance * i) + k);
145 }
146 
147 
148 const Ref<const MatrixXd> GaussianMixture::covariance() const
149 {
150  return covariance_;
151 }
152 
153 
154 const Ref<const MatrixXd> GaussianMixture::covariance(const std::size_t i) const
155 {
156  return covariance_.middleCols(this->dim_covariance * i, this->dim_covariance);
157 }
158 
159 
160 const double& GaussianMixture::covariance(const std::size_t i, const std::size_t j, const std::size_t k) const
161 {
162  return covariance_(j, (this->dim_covariance * i) + k);
163 }
164 
165 
166 Ref<VectorXd> GaussianMixture::weight()
167 {
168  return weight_;
169 }
170 
171 
172 double& GaussianMixture::weight(const std::size_t i)
173 {
174  return weight_(i);
175 }
176 
177 
178 const Ref<const VectorXd> GaussianMixture::weight() const
179 {
180  return weight_;
181 }
182 
183 
184 const double& GaussianMixture::weight(const std::size_t i) const
185 {
186  return weight_(i);
187 }
188 
189 
190 bool GaussianMixture::augmentWithNoise(const Eigen::Ref<const Eigen::MatrixXd>& noise_covariance_matrix)
191 {
192  /* Augment each state with a noise component having zero mean
193  and given covariance matrix. */
194 
195  /* Check that covariance matrix is square. */
196  if (noise_covariance_matrix.rows() != noise_covariance_matrix.cols())
197  return false;
198 
199  dim_noise = noise_covariance_matrix.rows();
200  dim += dim_noise;
201  dim_covariance += dim_noise;
202 
203  /* Add zero mean noise to each mean. */
204  mean_.conservativeResize(dim, NoChange);
205  mean_.bottomRows(dim_noise) = MatrixXd::Zero(dim_noise, components);
206 
207  /* Resize covariance matrix. */
208  covariance_.conservativeResizeLike(MatrixXd::Zero(dim_covariance, dim_covariance * components));
209 
210  /* Move old covariance matrices from right to left to avoid aliasing.
211 
212  Note that the covariance matrix of the 0-th coomponent,
213  i.e. in the top-left corner of the matrix covariance_,
214  is already in the correct place.
215  */
216  std::size_t dim_old = use_quaternion ? dim_linear + dim_circular * (dim_circular_component - 1) : dim_linear + dim_circular;
217  for (std::size_t i = 0; i < (components - 1); i++)
218  {
219  std::size_t i_index = components - 1 - i;
220 
221  Ref<MatrixXd> new_block = covariance_.block(0, i_index * dim_covariance, dim_old, dim_old);
222  Ref<MatrixXd> old_block = covariance_.block(0, i_index * dim_old, dim_old, dim_old);
223 
224  /* Swap columns from to right to left to avoid aliasing. */
225  for (std::size_t j = 0; j < dim_old; j++)
226  {
227  std::size_t j_index = dim_old - 1 - j;
228 
229  new_block.col(j_index).swap(old_block.col(j_index));
230  }
231  }
232 
233  for (std::size_t i = 0; i < components; i++)
234  {
235  /* Copy the noise covariance matrix in the bottom-right block of each covariance matrix. */
236  covariance_.block(dim_old, i * dim_covariance + dim_old, dim_noise, dim_noise) = noise_covariance_matrix;
237 
238  /* Clean part of the matrix that should be zero. */
239  covariance_.block(0, i * dim_covariance + dim_old, dim_old, dim_noise) = MatrixXd::Zero(dim_old, dim_noise);
240 
241  /* The part in covariance_.block(dim_old, i * dim_covariance, dim_noise, dim_old) was set to 0 when doing
242  covariance_.conservativeResizeLike(MatrixXd::Zero(dim_covariance, dim_covariance * components));
243  since it is appended in order to expand the matrix. */
244  }
245 
246  return true;
247 }
bfl::GaussianMixture::GaussianMixture
GaussianMixture() noexcept
Definition: GaussianMixture.cpp:14
bfl
Port of boost::any for C++11 compilers.
Definition: AdditiveMeasurementModel.h:13
bfl::GaussianMixture::mean
Eigen::Ref< Eigen::MatrixXd > mean()
Definition: GaussianMixture.cpp:94
GaussianMixture.h
bfl::GaussianMixture::covariance
Eigen::Ref< Eigen::MatrixXd > covariance()
Definition: GaussianMixture.cpp:130
bfl::GaussianMixture::resize
virtual void resize(const std::size_t components, const std::size_t dim_linear, const std::size_t dim_circular=0)
Definition: GaussianMixture.cpp:64
bfl::GaussianMixture::augmentWithNoise
bool augmentWithNoise(const Eigen::Ref< const Eigen::MatrixXd > &noise_covariance_matrix)
Definition: GaussianMixture.cpp:190
bfl::GaussianMixture
Definition: GaussianMixture.h:20
bfl::GaussianMixture::weight
Eigen::Ref< Eigen::VectorXd > weight()
Definition: GaussianMixture.cpp:166