00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef PARTICLE_FILTER_H
00017 #define PARTICLE_FILTER_H
00018
00019 #include <vector>
00020 #include <iostream>
00021 #include <fstream>
00022 #include <omp.h>
00023
00024 #include "simulator.h"
00025 #include "options.h"
00026 #include "auxil.h"
00027 #include "skeleton_state.h"
00028 #include "calibration.h"
00029
00030
00031 inline
00032 void normalise_weights (std::vector<double> &weights, double weights_sum = -1)
00033 {
00034 const size_t num_particles = weights.size ();
00035
00036
00037 if (weights_sum < 0)
00038 {
00039 weights_sum = weights [0];
00040 for (size_t k = 1; k < num_particles; k++)
00041 weights_sum += weights [k];
00042 }
00043
00044
00045 if (weights_sum > 0)
00046 for (size_t k = 0; k < num_particles; k++)
00047 weights [k] = weights [k] / weights_sum;
00048 else
00049 {
00050 const double w = 1.0 / (double)num_particles;
00051 for (size_t k = 0; k < num_particles; k++)
00052 weights [k] = w;
00053 }
00054 }
00055
00056 inline
00057 void normalise_log_weights (std::vector<double> &weights)
00058 {
00059 const size_t num_particles = weights.size ();
00060
00061
00062
00063 double max_weight = weights [0];
00064 for (size_t k = 1; k < num_particles; k++)
00065 max_weight = std::max (weights [k], max_weight);
00066
00067 for (size_t k = 0; k < num_particles; k++)
00068 weights [k] = exp (weights [k] - max_weight);
00069
00070
00071 double weights_sum = weights [0];
00072 for (size_t k = 1; k < num_particles; k++)
00073 weights_sum += weights [k];
00074
00075
00076 if (weights_sum > 0)
00077 for (size_t k = 0; k < num_particles; k++)
00078 weights [k] = weights [k] / weights_sum;
00079 else
00080 {
00081 const double w = 1.0 / (double)num_particles;
00082 for (size_t k = 0; k < num_particles; k++)
00083 weights [k] = w;
00084 }
00085
00086
00087
00088
00089
00090
00091
00092 }
00093
00094 template<typename state_type, typename observation_type>
00095 class particle_filter
00096 {
00097 protected:
00098 const size_t num_particles;
00099 std::vector<state_type*> states;
00100 std::vector<double> weights;
00101 const std::string output_directory;
00102 int frame;
00103
00104 public:
00105 particle_filter (const options &opts, const calibration &calib, const bool playback = false)
00106 : num_particles (opts.num_particles ()),
00107 states (num_particles),
00108 weights (num_particles, 1.0/(double)num_particles),
00109 output_directory (opts.output_directory ()),
00110 frame (opts.data_start_idx ())
00111 {
00112
00113 if (!playback)
00114 {
00115 for (size_t k = 0; k < num_particles; k++)
00116 {
00117 states [k] = new state_type (opts, calib, false);
00118
00119 }
00120 }
00121 }
00122
00123 virtual ~particle_filter ()
00124 {
00125 for (size_t k = 0; k < num_particles; k++)
00126 delete states [k];
00127 }
00128
00129 size_t get_num_particles () const
00130 {
00131 return num_particles;
00132 }
00133
00134 std::vector<state_type*>& get_states ()
00135 {
00136 return states;
00137 }
00138
00139 void save_weights (const char *filename)
00140 {
00141 std::ofstream file (filename);
00142 if (!file.is_open ())
00143 std::cerr << "particle_filter:save_weights: couldn't open '" << filename
00144 << "' for writing" << std::endl;
00145 else
00146 {
00147 for (size_t k = 0; k < this->num_particles; k++)
00148 file << weights [k] << " ";
00149 file.close ();
00150 }
00151 }
00152
00153 bool load_weights (const char *filename)
00154 {
00155 std::ifstream file (filename);
00156 if (!file.is_open ())
00157 {
00158 std::cerr << "particle_filter:load_weights: couldn't open '" << filename
00159 << "' for reading" << std::endl;
00160 return false;
00161 }
00162 else
00163 {
00164 for (size_t k = 0; k < this->num_particles; k++)
00165 file >> weights [k];
00166 file.close ();
00167 }
00168 return true;
00169 }
00170
00171 void save_states ()
00172 {
00173 const std::string pose_template = fullfile (output_directory, "states_%d.poses");
00174 char filename [200];
00175 sprintf (filename, pose_template.c_str (), frame);
00176
00177 std::ofstream file (filename);
00178 if (!file.is_open ())
00179 std::cerr << "particle_filter::save_states: could not open '" << filename
00180 << "' for writing" << std::endl;
00181 else
00182 {
00183 for (size_t k = 0; k < this->num_particles; k++)
00184 states [k]->save (file);
00185 }
00186 file.close ();
00187
00188 const std::string weight_template = fullfile (output_directory, "weights_%d.txt");
00189 sprintf (filename, weight_template.c_str (), frame);
00190 save_weights (filename);
00191
00192 const std::string spatial_template = fullfile (output_directory, "spatial_%d.poses");
00193 sprintf (filename, spatial_template.c_str (), frame);
00194 std::ofstream file2 (filename);
00195 if (!file2.is_open ())
00196 std::cerr << "particle_filter::save_states: could not open '" << filename
00197 << "' for writing" << std::endl;
00198 else
00199 {
00200 for (size_t k = 0; k < this->num_particles; k++)
00201 {
00202 for (const_bone_iter iter = states [k]->bone_begin ();
00203 iter != states [k]->bone_end (); iter++)
00204 {
00205 const vector3 p = iter->absolute ().T ();
00206 file2 << p (0) << " " << p (1) << " " << p (2) << " ";
00207 }
00208 file2 << std::endl;
00209 }
00210 }
00211 file2.close ();
00212
00213 frame ++;
00214 }
00215
00216 bool load_states ()
00217 {
00218 const std::string pose_template = fullfile (output_directory, "states_%d.poses");
00219 char filename [200];
00220 sprintf (filename, pose_template.c_str (), frame);
00221
00222 bool success = false;
00223 std::ifstream file (filename);
00224 if (!file.is_open ())
00225 std::cerr << "particle_filter::load_states: could not open '" << filename
00226 << "' for reading" << std::endl;
00227 else
00228 {
00229 success = true;
00230 for (size_t k = 0; k < this->num_particles; k++)
00231 states [k]->load (file);
00232 }
00233 file.close ();
00234
00235 if (success)
00236 {
00237 const std::string weight_template = fullfile (output_directory, "weights_%d.txt");
00238 sprintf (filename, weight_template.c_str (), frame);
00239 success = load_weights (filename);
00240
00241 frame ++;
00242 }
00243
00244 return success;
00245 }
00246
00247
00248
00249 virtual void refresh (const observation_type &observation) = 0;
00250 };
00251
00252 template<typename state_type, typename observation_type>
00253 class bootstrap : public particle_filter<state_type, observation_type>
00254 {
00255 public:
00256 bootstrap (const options &opts, const calibration &calib, const bool playback = false)
00257 : particle_filter<state_type, observation_type> (opts, calib, false),
00258 tmp_states (this->num_particles)
00259 {
00260 if (!playback)
00261 {
00262 for (size_t k = 0; k < this->num_particles; k++)
00263 this->tmp_states [k] = new state_type (opts, calib, false);
00264 }
00265 else
00266 {
00267 for (size_t k = 0; k < this->num_particles; k++)
00268 this->tmp_states [k] = NULL;
00269 }
00270 }
00271
00272 virtual ~bootstrap ()
00273 {
00274 for (size_t k = 0; k < this->num_particles; k++)
00275 if (this->tmp_states [k] != NULL)
00276 delete this->tmp_states [k];
00277 }
00278
00279
00280 void update_weights (const observation_type &observation)
00281 {
00282 #pragma omp parallel for
00283 for (size_t k = 0; k < this->num_particles; k++)
00284 this->weights [k] += measure_hypothesis (*this->states [k], observation);
00285
00286
00287 normalise_log_weights (this->weights);
00288 }
00289
00290 void update_particles (const observation_type &observation)
00291 {
00292 discrete dis (this->weights);
00293 for (size_t k = 0; k < this->num_particles; k++)
00294 *(this->tmp_states [k]) = *(this->states [dis.random ()]);
00295
00296 for (size_t k = 0; k < this->num_particles; k++)
00297 *(this->states [k]) = *(this->tmp_states [k]);
00298
00299 #pragma omp parallel for
00300 for (size_t k = 0; k < this->num_particles; k++)
00301 this->weights [k] = this->states [k]->predict (observation);
00302 }
00303
00304 virtual
00305 void refresh (const observation_type &observation)
00306 {
00307 update_particles (observation);
00308 update_weights (observation);
00309 }
00310
00311 virtual double measure_hypothesis (state_type &state, const observation_type &observation) = 0;
00312
00313 private:
00314 std::vector<state_type*> tmp_states;
00315 };
00316
00317 template<typename state_type, typename observation_type>
00318 class annealed_particle_filter : public particle_filter<state_type, observation_type>
00319 {
00320 public:
00321 annealed_particle_filter (const options &opts, const calibration &calib, const bool playback = false)
00322 : particle_filter<state_type, observation_type> (opts, calib, false),
00323 tmp_states (this->num_particles),
00324 num_annealing_steps (10),
00325 beta0 (1.0),
00326 beta_increment (1.1)
00327 {
00328 if (!playback)
00329 {
00330 for (size_t k = 0; k < this->num_particles; k++)
00331 this->tmp_states [k] = new state_type (opts, calib, false);
00332 }
00333 else
00334 {
00335 for (size_t k = 0; k < this->num_particles; k++)
00336 this->tmp_states [k] = NULL;
00337 }
00338 }
00339
00340 virtual ~annealed_particle_filter ()
00341 {
00342 for (size_t k = 0; k < this->num_particles; k++)
00343 if (this->tmp_states [k] != NULL)
00344 delete this->tmp_states [k];
00345 }
00346
00347
00348 void update_weights (const observation_type &observation, const double beta)
00349 {
00350 #pragma omp parallel for
00351 for (size_t k = 0; k < this->num_particles; k++)
00352 {
00353 const double tmp = measure_hypothesis (*this->states [k], observation);
00354 this->weights [k] += -pow (-tmp, beta);
00355 }
00356
00357
00358 normalise_log_weights (this->weights);
00359 }
00360
00361 void update_particles (const observation_type &observation, const double beta)
00362 {
00363 discrete dis (this->weights);
00364 for (size_t k = 0; k < this->num_particles; k++)
00365 *(this->tmp_states [k]) = *(this->states [dis.random ()]);
00366
00367 for (size_t k = 0; k < this->num_particles; k++)
00368 *(this->states [k]) = *(this->tmp_states [k]);
00369
00370 #pragma omp parallel for
00371 for (size_t k = 0; k < this->num_particles; k++)
00372 this->weights [k] = this->states [k]->predict (observation, beta);
00373 }
00374
00375 virtual
00376 void refresh (const observation_type &observation)
00377 {
00378 double beta = beta0;
00379 for (size_t k = 0; k < num_annealing_steps; k++)
00380 {
00381 update_particles (observation, beta);
00382 update_weights (observation, beta);
00383 beta *= beta_increment;
00384 }
00385 }
00386
00387 virtual double measure_hypothesis (state_type &state, const observation_type &observation) = 0;
00388
00389 private:
00390 std::vector<state_type*> tmp_states;
00391 const size_t num_annealing_steps;
00392 const double beta0, beta_increment;
00393 };
00394 #endif // PARTICLE_FILTER_H
00395