Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
vector_average.hpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2012, Willow Garage, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 namespace pcl
38 {
39  template <typename real, int dimension>
41  noOfSamples_ (0), accumulatedWeight_ (0),
42  mean_ (Eigen::Matrix<real, dimension, 1>::Identity ()),
43  covariance_ (Eigen::Matrix<real, dimension, dimension>::Identity ())
44  {
45  reset();
46  }
47 
48  template <typename real, int dimension>
50  {
51  noOfSamples_ = 0;
52  accumulatedWeight_ = 0.0;
53  mean_.fill(0);
54  covariance_.fill(0);
55  }
56 
57  template <typename real, int dimension>
58  inline void VectorAverage<real, dimension>::add(const Eigen::Matrix<real, dimension, 1>& sample, real weight) {
59  if (weight == 0.0f)
60  return;
61 
62  ++noOfSamples_;
63  accumulatedWeight_ += weight;
64  real alpha = weight/accumulatedWeight_;
65 
66  Eigen::Matrix<real, dimension, 1> diff = sample - mean_;
67  covariance_ = (1.0f-alpha)*(covariance_ + alpha * (diff * diff.transpose()));
68 
69  mean_ += alpha*(diff);
70 
71  //if (pcl_isnan(covariance_(0,0)))
72  //{
73  //cout << PVARN(weight);
74  //exit(0);
75  //}
76  }
77 
78  template <typename real, int dimension>
79  inline void VectorAverage<real, dimension>::doPCA(Eigen::Matrix<real, dimension, 1>& eigen_values, Eigen::Matrix<real, dimension, 1>& eigen_vector1,
80  Eigen::Matrix<real, dimension, 1>& eigen_vector2, Eigen::Matrix<real, dimension, 1>& eigen_vector3) const
81  {
82  // The following step is necessary for cases where the values in the covariance matrix are small
83  // In this case float accuracy is nor enough to calculate the eigenvalues and eigenvectors.
84  //Eigen::Matrix<double, dimension, dimension> tmp_covariance = covariance_.template cast<double>();
85  //Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double, dimension, dimension> > ei_symm(tmp_covariance);
86  //eigen_values = ei_symm.eigenvalues().template cast<real>();
87  //Eigen::Matrix<real, dimension, dimension> eigen_vectors = ei_symm.eigenvectors().template cast<real>();
88 
89  //cout << "My covariance is \n"<<covariance_<<"\n";
90  //cout << "My mean is \n"<<mean_<<"\n";
91  //cout << "My Eigenvectors \n"<<eigen_vectors<<"\n";
92 
93  Eigen::SelfAdjointEigenSolver<Eigen::Matrix<real, dimension, dimension> > ei_symm(covariance_);
94  eigen_values = ei_symm.eigenvalues();
95  Eigen::Matrix<real, dimension, dimension> eigen_vectors = ei_symm.eigenvectors();
96 
97  eigen_vector1 = eigen_vectors.col(0);
98  eigen_vector2 = eigen_vectors.col(1);
99  eigen_vector3 = eigen_vectors.col(2);
100  }
101 
102  template <typename real, int dimension>
103  inline void VectorAverage<real, dimension>::doPCA(Eigen::Matrix<real, dimension, 1>& eigen_values) const
104  {
105  // The following step is necessary for cases where the values in the covariance matrix are small
106  // In this case float accuracy is nor enough to calculate the eigenvalues and eigenvectors.
107  //Eigen::Matrix<double, dimension, dimension> tmp_covariance = covariance_.template cast<double>();
108  //Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double, dimension, dimension> > ei_symm(tmp_covariance, false);
109  //eigen_values = ei_symm.eigenvalues().template cast<real>();
110 
111  Eigen::SelfAdjointEigenSolver<Eigen::Matrix<real, dimension, dimension> > ei_symm(covariance_, false);
112  eigen_values = ei_symm.eigenvalues();
113  }
114 
115  template <typename real, int dimension>
116  inline void VectorAverage<real, dimension>::getEigenVector1(Eigen::Matrix<real, dimension, 1>& eigen_vector1) const
117  {
118  // The following step is necessary for cases where the values in the covariance matrix are small
119  // In this case float accuracy is nor enough to calculate the eigenvalues and eigenvectors.
120  //Eigen::Matrix<double, dimension, dimension> tmp_covariance = covariance_.template cast<double>();
121  //Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double, dimension, dimension> > ei_symm(tmp_covariance);
122  //eigen_values = ei_symm.eigenvalues().template cast<real>();
123  //Eigen::Matrix<real, dimension, dimension> eigen_vectors = ei_symm.eigenvectors().template cast<real>();
124 
125  //cout << "My covariance is \n"<<covariance_<<"\n";
126  //cout << "My mean is \n"<<mean_<<"\n";
127  //cout << "My Eigenvectors \n"<<eigen_vectors<<"\n";
128 
129  Eigen::SelfAdjointEigenSolver<Eigen::Matrix<real, dimension, dimension> > ei_symm(covariance_);
130  Eigen::Matrix<real, dimension, dimension> eigen_vectors = ei_symm.eigenvectors();
131  eigen_vector1 = eigen_vectors.col(0);
132  }
133 
134 
136  // Special cases for real=float & dimension=3 -> Partial specialization does not work with class templates. :( //
139  // float //
141  template <>
142  inline void VectorAverage<float, 3>::doPCA(Eigen::Matrix<float, 3, 1>& eigen_values, Eigen::Matrix<float, 3, 1>& eigen_vector1,
143  Eigen::Matrix<float, 3, 1>& eigen_vector2, Eigen::Matrix<float, 3, 1>& eigen_vector3) const
144  {
145  //cout << "Using specialized 3x3 version of doPCA!\n";
146  Eigen::Matrix<float, 3, 3> eigen_vectors;
147  eigen33(covariance_, eigen_vectors, eigen_values);
148  eigen_vector1 = eigen_vectors.col(0);
149  eigen_vector2 = eigen_vectors.col(1);
150  eigen_vector3 = eigen_vectors.col(2);
151  }
152  template <>
153  inline void VectorAverage<float, 3>::doPCA(Eigen::Matrix<float, 3, 1>& eigen_values) const
154  {
155  //cout << "Using specialized 3x3 version of doPCA!\n";
156  computeRoots (covariance_, eigen_values);
157  }
158  template <>
159  inline void VectorAverage<float, 3>::getEigenVector1(Eigen::Matrix<float, 3, 1>& eigen_vector1) const
160  {
161  //cout << "Using specialized 3x3 version of doPCA!\n";
162  Eigen::Vector3f::Scalar eigen_value;
163  Eigen::Vector3f eigen_vector;
164  eigen33(covariance_, eigen_value, eigen_vector);
165  eigen_vector1 = eigen_vector;
166  }
167 
169  // double //
171  template <>
172  inline void VectorAverage<double, 3>::doPCA(Eigen::Matrix<double, 3, 1>& eigen_values, Eigen::Matrix<double, 3, 1>& eigen_vector1,
173  Eigen::Matrix<double, 3, 1>& eigen_vector2, Eigen::Matrix<double, 3, 1>& eigen_vector3) const
174  {
175  //cout << "Using specialized 3x3 version of doPCA!\n";
176  Eigen::Matrix<double, 3, 3> eigen_vectors;
177  eigen33(covariance_, eigen_vectors, eigen_values);
178  eigen_vector1 = eigen_vectors.col(0);
179  eigen_vector2 = eigen_vectors.col(1);
180  eigen_vector3 = eigen_vectors.col(2);
181  }
182  template <>
183  inline void VectorAverage<double, 3>::doPCA(Eigen::Matrix<double, 3, 1>& eigen_values) const
184  {
185  //cout << "Using specialized 3x3 version of doPCA!\n";
186  computeRoots (covariance_, eigen_values);
187  }
188  template <>
189  inline void VectorAverage<double, 3>::getEigenVector1(Eigen::Matrix<double, 3, 1>& eigen_vector1) const
190  {
191  //cout << "Using specialized 3x3 version of doPCA!\n";
192  Eigen::Vector3d::Scalar eigen_value;
193  Eigen::Vector3d eigen_vector;
194  eigen33(covariance_, eigen_value, eigen_vector);
195  eigen_vector1 = eigen_vector;
196  }
197 } // END namespace
198