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_STICK_STATE_H
00017 #define PIK_STICK_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 #include "cloud_and_stick.h"
00027 #include <OpenTissue/core/math/math_is_number.h>
00028
00029 #ifdef USE_IMPORTANCE_SAMPLING
00030 #include <OpenTissue/core/math/big/big_cholesky.h>
00031 #include <iostream>
00032 #endif // USE_IMPORTANCE_SAMPLING
00033
00034
00035 #define HEAD 0
00036 #define LEFT_HAND 1
00037 #define RIGHT_HAND 2
00038 #define LEFT_FOOT 3
00039 #define RIGHT_FOOT 4
00040
00041 extern double convex_lambda;
00042
00043 typedef boost::numeric::ublas::triangular_matrix<double, boost::numeric::ublas::lower> triangular_matrix_type;
00044
00061 template <class observation_type>
00062 class pik_stick_state : public angle_state<observation_type>
00063 {
00064 public:
00065 pik_stick_state (const options &opts, const calibration &_calib, const bool _for_show = true)
00066 : angle_state<observation_type> (opts, _calib, _for_show),
00067 lambda (2)
00068 {
00069
00070 convex_lambda = opts.convex_lambda ();
00071
00072
00073 bool first_leaf = true;
00074 for (const_bone_iter bone = this->skeleton.begin (); bone != this->skeleton.end (); bone++)
00075 {
00076 if (!bone->is_leaf ())
00077 continue;
00078
00079 if (first_leaf)
00080 {
00081 first_leaf = false;
00082 }
00083 else
00084 {
00085 chain_type chain;
00086 chain.init (this->skeleton.root (), &(*bone));
00087 this->solver.add_chain (chain);
00088 }
00089 }
00090
00091
00092 num_end_effectors = 0;
00093 for (const_chain_iter iter = this->solver.chain_begin (); iter != this->solver.chain_end (); iter++)
00094 num_end_effectors ++;
00095
00096
00097 end_effectors.resize (num_end_effectors);
00098 get_end_effectors (end_effectors);
00099
00100
00101 for (unsigned int k = 0; k < lambda.size (); k++)
00102 lambda [k] = NaN;
00103 };
00104
00105 double predict (const observation_type &observation, const double variance_scale = 1.0)
00106 {
00107 stick_motion (observation);
00108
00109 double log_r = 0;
00110
00111 #ifdef USE_IMPORTANCE_SAMPLING
00112
00113 const double w = 10000.0;
00114 matrix_type J;
00115 compute_jacobian (this->solver.chain_begin (), this->solver.chain_end (),
00116 this->bone_begin (), this->bone_end (), J);
00117
00118 matrix_type H = w * (1.0 - convex_lambda) * prod (trans (J), J);
00119 const size_t N = H.size1 ();
00120 for (size_t k = 0; k < N; k++)
00121 H (k, k) += w * convex_lambda;
00122
00123
00124 triangular_matrix_type Lh (N, N);
00125 const size_t s = OpenTissue::math::big::cholesky_decompose (H, Lh);
00126 if (s == 0)
00127 {
00128
00129 gaussian1D g;
00130 solver_type::vector_type x (N);
00131
00132 const int max_rejects = 3;
00133 double norm_y = 0;
00134 for (int k = N-1; k >= 0; k--)
00135 {
00136 bool reject = false;
00137 int reject_count = 0;
00138 double yk, new_theta_k;
00139 do
00140 {
00141 if (reject_count < max_rejects)
00142 yk = g.random ();
00143 else
00144 yk = 0;
00145
00146
00147 double tmp_y = yk;
00148 for (size_t l = k+1; l < N; l++)
00149 tmp_y -= Lh (l, k) * x (l);
00150 x (k) = tmp_y / Lh (k, k);
00151
00152
00153 new_theta_k = this->theta (k) + x (k);
00154 if (new_theta_k < this->min_limits (k) || new_theta_k > this->max_limits (k))
00155 {
00156 reject = true;
00157 reject_count ++;
00158
00159
00160
00161 }
00162 else
00163 reject = false;
00164 }
00165 while (reject && reject_count <= max_rejects);
00166
00167 norm_y += square (yk);
00168 this->theta (k) = new_theta_k;
00169 }
00170 }
00171 else
00172 {
00173
00174 std::cerr << "pik_state::predict: could not perform Cholesky transform" << std::endl;
00175 }
00176 #endif // USE_IMPORTANCE_SAMPLING
00177
00178 return log_r;
00179 };
00180
00181 pik_stick_state& operator= (pik_stick_state &new_state)
00182 {
00183 angle_state<observation_type>::operator= (new_state);
00184 return *this;
00185 };
00186
00187 bool load (const std::string filename)
00188 {
00189 const bool success = angle_state<observation_type>::load (filename);
00190 return success;
00191 };
00192
00193 bool load (std::ifstream &file)
00194 {
00195 const bool success = angle_state<observation_type>::load (file);
00196
00197 return success;
00198 };
00199
00200 protected:
00201 size_t num_end_effectors;
00202 std::vector<double> lambda;
00203 static const double sigma = 0.0001;
00204 std::vector<vector3> end_effectors;
00205
00206 void stick_motion (const observation_type &observation)
00207 {
00208 const stick_type stick = observation.get_stick ();
00209
00210 gaussian1D gauss;
00211
00212
00213 for (unsigned int k = 0; k < lambda.size (); k++)
00214 {
00215 if (!is_number (lambda [k]))
00216 {
00217 const_chain_iter iter = this->solver.chain_begin ();
00218 for (unsigned int i = 0; i < k; i++)
00219 iter ++;
00220 const vector3 hand = iter->get_end_effector ()->absolute ().T ();
00221 dist2 (stick, hand, lambda [k]);
00222 }
00223 else
00224 {
00225 gaussian1D G (lambda [k], sigma);
00226 while (true)
00227 {
00228 const double l = G.random ();
00229 if (0.0 <= l && l <= 1.0)
00230 {
00231 lambda [k] = l;
00232 break;
00233 }
00234 }
00235 }
00236 }
00237
00238 for (unsigned int k = 0; k < end_effectors.size (); k++)
00239 end_effectors [k] = nearest_point_on_stick (stick, lambda [k]);
00240 set_end_effectors (end_effectors);
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 }
00252
00253 void set_end_effectors (const std::vector<vector3> &data)
00254 {
00255 this->compute_pose ();
00256
00257 int i = 0;
00258 for (chain_iter iter = this->solver.chain_begin (); iter != this->solver.chain_end (); iter++)
00259 iter->p_global () = data [i++] - this->root;
00260 this->solver.solve (&solver_type::default_SD_settings ());
00261
00262
00263 OpenTissue::kinematics::inverse::get_joint_parameters (*(this->solver.skeleton ()), this->theta);
00264
00265
00266 i = 0;
00267 for (chain_iter iter = this->solver.chain_begin (); iter != this->solver.chain_end (); iter++)
00268 iter->p_global () = iter->get_end_effector ()->absolute ().T ();
00269 };
00270
00271 void get_end_effectors (std::vector<vector3> &data)
00272 {
00273 this->compute_pose ();
00274
00275 int i = 0;
00276 for (const_chain_iter iter = this->solver.chain_begin (); iter != this->solver.chain_end (); iter++)
00277 data [i++] = iter->get_end_effector ()->absolute ().T () + this->root;
00278
00279 };
00280 };
00281
00282 #endif // PIK_STICK_STATE_H