Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef PIK_STATE_H
00017 #define PIK_STATE_H
00018
00019 #define USE_IMPORTANCE_SAMPLING
00020 #define NDEBUG // Make uBLAS run less slow
00021
00022 #include "angle_state.h"
00023 #include "auxil.h"
00024 #include "options.h"
00025 #include "simulator.h"
00026
00027 #ifdef USE_IMPORTANCE_SAMPLING
00028 #include <OpenTissue/core/math/big/big_cholesky.h>
00029 #include <iostream>
00030 #endif // USE_IMPORTANCE_SAMPLING
00031
00032
00033 #define HEAD 0
00034 #define LEFT_HAND 1
00035 #define RIGHT_HAND 2
00036 #define LEFT_FOOT 3
00037 #define RIGHT_FOOT 4
00038
00039
00040 #define LINEAR_MOTION
00041
00042 extern double convex_lambda;
00043
00044 typedef boost::numeric::ublas::triangular_matrix<double, boost::numeric::ublas::lower> triangular_matrix_type;
00045
00046 inline
00047 vector3 fix (vector3 &curr)
00048 {
00049 return curr;
00050 }
00051
00052 inline
00053 vector3 linear_extrapolate (vector3 &curr, vector3 &prev)
00054 {
00055 return 2.0 * curr - prev;
00056 }
00057
00058 inline
00059 void add_noise (vector3 &v, gaussian1D &noise)
00060 {
00061 for (int k = 0; k < 3; k++)
00062 v [k] += noise.random ();
00063 }
00064
00081 template <class observation_type>
00082 class pik_state : public angle_state<observation_type>
00083 {
00084 public:
00085 pik_state (const options &opts, const calibration &_calib, const bool _for_show = true)
00086 : angle_state<observation_type> (opts, _calib, _for_show)
00087 {
00088
00089 convex_lambda = opts.convex_lambda ();
00090
00091
00092 for (const_bone_iter bone = this->skeleton.begin (); bone != this->skeleton.end (); bone++)
00093 {
00094 if (!bone->is_leaf ())
00095 continue;
00096
00097 chain_type chain;
00098 chain.init (this->skeleton.root (), &(*bone));
00099 this->solver.add_chain (chain);
00100
00101 #ifdef PELVIS
00102 chain_type chainp;
00103 chainp.init (this->skeleton.root (), &(*(bone->parent ())));
00104 this->solver.add_chain (chainp);
00105 #endif // PELVIS
00106 }
00107
00108
00109 #ifdef PELVIS
00110 {
00111 chain_type chain1;
00112 chain1.init (this->skeleton.root (), this->skeleton.get_bone (7));
00113 this->solver.add_chain (chain1);
00114
00115 chain_type chain2;
00116 chain2.init (this->skeleton.root (), this->skeleton.get_bone (8));
00117 this->solver.add_chain (chain2);
00118
00119 chain_type chain3;
00120 chain3.init (this->skeleton.root (), this->skeleton.get_bone (12));
00121 this->solver.add_chain (chain3);
00122 }
00123 #endif // PELVIS
00124
00125
00126 num_end_effectors = 0;
00127 for (const_chain_iter iter = this->solver.chain_begin (); iter != this->solver.chain_end (); iter++)
00128 num_end_effectors ++;
00129
00130 prev_end_effectors.resize (num_end_effectors);
00131 curr_end_effectors.resize (num_end_effectors);
00132
00133
00134 get_end_effectors (prev_end_effectors);
00135 get_end_effectors (curr_end_effectors);
00136 };
00137
00138 double predict (const observation_type &observation, const double variance_scale = 1.0)
00139 {
00140 #ifdef PELVIS
00141 pelvic_lift ();
00142 #endif // PELVIS
00143
00144 #ifdef LINEAR_MOTION
00145 linear_motion ();
00146 #endif // LINEAR_MOTION
00147
00148 double log_r = 0;
00149
00150 #ifdef USE_IMPORTANCE_SAMPLING
00151
00152
00153 const double w = 10000.0;
00154 matrix_type J;
00155 compute_jacobian (this->solver.chain_begin (), this->solver.chain_end (),
00156 this->bone_begin (), this->bone_end (), J);
00157
00158 matrix_type H = w * (1.0 - convex_lambda) * prod (trans (J), J);
00159 const size_t N = H.size1 ();
00160 for (size_t k = 0; k < N; k++)
00161 H (k, k) += w * convex_lambda;
00162
00163
00164 triangular_matrix_type Lh (N, N);
00165 const size_t s = OpenTissue::math::big::cholesky_decompose (H, Lh);
00166 if (s == 0)
00167 {
00168
00169 gaussian1D g;
00170 solver_type::vector_type x (N);
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 const int max_rejects = 3;
00198 double norm_y = 0;
00199 for (int k = N-1; k >= 0; k--)
00200 {
00201 bool reject = false;
00202 int reject_count = 0;
00203 double yk, new_theta_k;
00204 do
00205 {
00206 if (reject_count < max_rejects)
00207 yk = g.random ();
00208 else
00209 yk = 0;
00210
00211
00212 double tmp_y = yk;
00213 for (size_t l = k+1; l < N; l++)
00214 tmp_y -= Lh (l, k) * x (l);
00215 x (k) = tmp_y / Lh (k, k);
00216
00217
00218 new_theta_k = this->theta (k) + x (k);
00219 if (new_theta_k < this->min_limits (k) || new_theta_k > this->max_limits (k))
00220 {
00221 reject = true;
00222 reject_count ++;
00223
00224
00225
00226 }
00227 else
00228 reject = false;
00229 }
00230 while (reject && reject_count <= max_rejects);
00231
00232 norm_y += square (yk);
00233 this->theta (k) = new_theta_k;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 }
00253 else
00254 {
00255
00256 std::cerr << "pik_state::predict: could not perform Cholesky transform" << std::endl;
00257 }
00258 #endif // USE_IMPORTANCE_SAMPLING
00259
00260
00261
00262 for (size_t k = 0; k < num_end_effectors; k++)
00263 prev_end_effectors [k] = curr_end_effectors [k];
00264
00265
00266
00267
00268
00269
00270
00271
00272 return log_r;
00273 };
00274
00275 void pelvic_lift ()
00276 {
00277
00278 const matrix3 R = OpenTissue::math::Rx (-3.14159 / 8.0) * OpenTissue::math::Rz (0.25);
00279 gaussian1D root_noise (0, 0.1);
00280 vector3 tmp;
00281 do
00282 {
00283 tmp (0) = 0.1 * root_noise.random ();
00284 tmp (1) = 1.0 * root_noise.random ();
00285 tmp (2) = 7.5 * root_noise.random ();
00286 tmp = R * tmp;
00287 }
00288 while (tmp (2) + this->root (2) < 0.0);
00289 this->root += tmp;
00290
00291 set_end_effectors (prev_end_effectors);
00292 };
00293
00294 void linear_motion ()
00295 {
00296 get_end_effectors (curr_end_effectors);
00297
00298
00299
00300
00301 gaussian1D gauss (0, this->pred_noise);
00302 for (size_t k = 0; k < num_end_effectors; k++)
00303 {
00304 if (k == 0 || k > 2)
00305 prev_end_effectors [k] = curr_end_effectors [k];
00306 else
00307 prev_end_effectors [k] = 2.0 * curr_end_effectors [k] - prev_end_effectors [k];
00308
00309 if (k <= 2)
00310 for (size_t n = 0; n < prev_end_effectors [k].size (); n++)
00311 prev_end_effectors [k] [n] += gauss.random ();
00312 }
00313
00314 set_end_effectors (prev_end_effectors);
00315 };
00316
00317 pik_state& operator= (pik_state &new_state)
00318 {
00319 angle_state<observation_type>::operator= (new_state);
00320
00321
00322 for (size_t k = 0; k < prev_end_effectors.size (); k++)
00323 prev_end_effectors [k] = new_state.prev_end_effectors [k];
00324
00325 return *this;
00326 };
00327
00328 bool load (const std::string filename)
00329 {
00330 const bool success = angle_state<observation_type>::load (filename);
00331
00332 get_end_effectors (prev_end_effectors);
00333
00334 return success;
00335 };
00336
00337 bool load (std::ifstream &file)
00338 {
00339 const bool success = angle_state<observation_type>::load (file);
00340
00341 get_end_effectors (prev_end_effectors);
00342
00343 return success;
00344 };
00345
00346 protected:
00347 size_t num_end_effectors;
00348 std::vector<vector3> prev_end_effectors, curr_end_effectors;
00349
00350 void set_end_effectors (const std::vector<vector3> &data)
00351 {
00352 this->compute_pose ();
00353
00354 int i = 0;
00355 for (chain_iter iter = this->solver.chain_begin (); iter != this->solver.chain_end (); iter++)
00356 iter->p_global () = data [i++] - this->root;
00357 this->solver.solve (&solver_type::default_SD_settings ());
00358
00359
00360 OpenTissue::kinematics::inverse::get_joint_parameters (*(this->solver.skeleton ()), this->theta);
00361
00362
00363 i = 0;
00364 for (chain_iter iter = this->solver.chain_begin (); iter != this->solver.chain_end (); iter++)
00365
00366 iter->p_global () = iter->get_end_effector ()->absolute ().T ();
00367 };
00368
00369 void get_end_effectors (std::vector<vector3> &data)
00370 {
00371 this->compute_pose ();
00372
00373 int i = 0;
00374 for (const_chain_iter iter = this->solver.chain_begin (); iter != this->solver.chain_end (); iter++)
00375 data [i++] = iter->get_end_effector ()->absolute ().T () + this->root;
00376
00377 };
00378 };
00379
00380 #endif // PIK_STATE_H