00001 #ifndef OPENTISSUE_DYNAMICS_MBD_UTIL_LIMITS_MBD_REACH_CONE_H
00002 #define OPENTISSUE_DYNAMICS_MBD_UTIL_LIMITS_MBD_REACH_CONE_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/dynamics/mbd/interfaces/mbd_sub_constraint_interface.h>
00013 #include <OpenTissue/core/math/math_constants.h>
00014
00015
00016 namespace OpenTissue
00017 {
00018 namespace mbd
00019 {
00020
00081 template< typename mbd_types >
00082 class ReachCone
00083 : public SubConstraintInterface<mbd_types>
00084 {
00085 public:
00086
00087 typedef typename mbd_types::math_policy math_policy;
00088 typedef typename mbd_types::math_policy::real_type real_type;
00089 typedef typename mbd_types::math_policy::size_type size_type;
00090 typedef typename mbd_types::math_policy::value_traits value_traits;
00091 typedef typename mbd_types::math_policy::vector3_type vector3_type;
00092 typedef typename mbd_types::math_policy::vector_range vector_range;
00093 typedef typename mbd_types::math_policy::idx_vector_range idx_vector_range;
00094 typedef typename mbd_types::math_policy::matrix_range matrix_range;
00095 typedef typename mbd_types::math_policy::vector_type vector_type;
00096 typedef typename mbd_types::math_policy::quaternion_type quaternion_type;
00097
00098 protected:
00099
00100 struct cone_constraint_type
00101 {
00102 real_type m_theta_err;
00103 vector3_type m_u;
00104 };
00105
00106 typedef typename std::vector<cone_constraint_type> constraint_container;
00107 typedef typename std::vector<vector3_type> normal_container;
00108
00109 constraint_container m_contraints;
00110
00111
00112 normal_container m_cone_normals;
00113
00114
00115
00116
00117
00118
00119 size_type m_cone_sides;
00120 size_type m_rows;
00121 vector_type m_gamma;
00122 vector_type m_solution;
00123
00124 public:
00125
00126 ReachCone()
00127 : m_cone_sides(0)
00128 , m_rows(0)
00129 , m_gamma(0)
00130 , m_solution(0)
00131 {}
00132
00133 virtual ~ReachCone(){}
00134
00135 public:
00136
00142 void add_cone(vector3_type const & n_local)
00143 {
00144 vector3_type n_unit = normalize(n_local);
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 if(n_unit(2)<value_traits::zero())
00155 {
00156 std::cout << "ReachCone::add_cone(): Inconsistent cone side, dropping it" << std::endl;
00157 return;
00158 }
00159 m_cone_normals.push_back(n_unit);
00160 m_contraints.push_back(cone_constraint_type());
00161 ++m_cone_sides;
00162 }
00163
00188 void evaluate(
00189 quaternion_type const & Q,
00190 vector3_type const & s_wcs,
00191 vector3_type const & s_local
00192 )
00193 {
00194
00195 m_rows = 0;
00196 for( size_type i=0;i<m_cone_sides;++i)
00197 {
00198
00199 vector3_type n_local = m_cone_normals[i];
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 real_type theta_err = n_local * s_local;
00211
00212
00213
00214
00215
00216
00217 if(theta_err<value_traits::zero())
00218 {
00219
00220
00221
00222 m_contraints[m_rows].m_theta_err = theta_err;
00223
00224
00225
00226
00227
00228 vector3_type n_wcs = Q.rotate(n_local);
00229 m_contraints[m_rows].m_u = cross(n_wcs , s_wcs);
00230 ++m_rows;
00231 }
00232 }
00233 }
00234
00235 size_type get_number_of_jacobian_rows() const {return m_rows;}
00236
00237 void get_linear_jacobian_A(matrix_range & J,size_type const & offset)const
00238 {
00239 size_type row = offset;
00240 for(size_type i=0;i<m_rows;++i,++row)
00241 {
00242 J(row,0) = value_traits::zero();
00243 J(row,1) = value_traits::zero();
00244 J(row,2) = value_traits::zero();
00245 }
00246 }
00247
00248 void get_linear_jacobian_B(matrix_range & J,size_type const & offset)const
00249 {
00250 size_type row = offset;
00251 for(size_type i=0;i<m_rows;++i,++row)
00252 {
00253 J(row,0) = value_traits::zero();
00254 J(row,1) = value_traits::zero();
00255 J(row,2) = value_traits::zero();
00256 }
00257 }
00258
00259 void get_angular_jacobian_A(matrix_range & J,size_type const & offset)const
00260 {
00261 size_type row = offset;
00262 for(size_type i=0;i<m_rows;++i,++row)
00263 {
00264 J(row,0) = -m_contraints[i].m_u(0);
00265 J(row,1) = -m_contraints[i].m_u(1);
00266 J(row,2) = -m_contraints[i].m_u(2);
00267 }
00268 }
00269
00270 void get_angular_jacobian_B(matrix_range & J,size_type const & offset)const
00271 {
00272 size_type row = offset;
00273 for(size_type i=0;i<m_rows;++i,++row)
00274 {
00275 J(row,0) = m_contraints[i].m_u(0);
00276 J(row,1) = m_contraints[i].m_u(1);
00277 J(row,2) = m_contraints[i].m_u(2);
00278 }
00279 }
00280
00281 void get_stabilization_term(vector_range & b_error,size_type const & offset)const
00282 {
00283 real_type k_cor = this->get_frames_per_second()*this->get_error_reduction_parameter();
00284 size_type row = offset;
00285 for(size_type i=0;i<m_rows;++i,++row)
00286 {
00287 b_error(row) = - k_cor*m_contraints[i].m_theta_err;
00288 }
00289 }
00290
00291 void get_low_limits(vector_range & lo,size_type const & offset)const
00292 {
00293 size_type row = offset;
00294 for(size_type i=0;i<m_rows;++i,++row)
00295 {
00296 lo(row) = value_traits::zero();
00297 }
00298 }
00299
00300 void get_high_limits(vector_range & hi,size_type const & offset)const
00301 {
00302 size_type row = offset;
00303 for(size_type i=0;i<m_rows;++i,++row)
00304 {
00305 hi(row) = OpenTissue::math::detail::highest<real_type>();
00306 }
00307 }
00308
00309 void get_dependency_indices(idx_vector_range & dep,size_type const & offset) const
00310 {
00311 size_type row = offset;
00312 for(size_type i=0;i<m_rows;++i,++row)
00313 {
00314 dep(row) = OpenTissue::math::detail::highest<size_type>();
00315 }
00316 }
00317
00318 void get_dependency_factors(vector_range & factors,size_type const & offset) const
00319 {
00320 size_type row = offset;
00321 for(size_type i=0;i<m_rows;++i,++row)
00322 {
00323 factors(row) = value_traits::zero();
00324 }
00325 }
00326
00327 void set_regularization(vector_range const & gamma,size_type const & offset)
00328 {
00329 math_policy::resize( m_gamma, m_rows);
00330 size_type row = offset;
00331 for(size_type i=0;i<m_rows;++i,++row)
00332 {
00333 assert(gamma(row)<=1 || !"ReachCone::set_regularization(): gamma value out of range");
00334 assert(gamma(row)>=0 || !"ReachCone::set_regularization(): gamma value out of range");
00335 m_gamma(i) = gamma(row);
00336 }
00337 }
00338
00339 void get_regularization(vector_range & gamma,size_type const & offset)const
00340 {
00341 size_type row = offset;
00342 if(m_gamma.size()==0)
00343 {
00344 for(size_type i=0;i<m_rows;++i,++row)
00345 gamma(row) = value_traits::zero();
00346 }
00347 else
00348 {
00349 for(size_type i=0;i<m_rows;++i,++row)
00350 gamma(row) = m_gamma(i);
00351 }
00352 }
00353
00354 void set_solution(vector_range const & solution,size_type const & offset)
00355 {
00356 assert(solution.size()==m_rows || !"ReachCone::set_solution(): solution array size did not match number of active cone constraints");
00357 math_policy::resize( m_solution, m_rows);
00358 size_type row = offset;
00359 for(size_type i=0;i<m_rows;++i,++row)
00360 m_solution(i) = solution(row);
00361 }
00362
00363 void get_solution(vector_range & solution,size_type const & offset)const
00364 {
00365 size_type row = offset;
00366 if(m_solution.size()==0)
00367 {
00368 for(size_type i=0;i<m_rows;++i,++row)
00369 solution(row) = value_traits::zero();
00370 }
00371 else
00372 {
00373 for(size_type i=0;i<m_rows;++i,++row)
00374 solution(row) = m_solution(i);
00375 }
00376 }
00377
00378 };
00379
00380 }
00381 }
00382
00383 #endif