00001 #ifndef OPENTISSUE_DYNAMICS_MBD_UTIL_JOINTS_MBD_SLIDER_JOINT_H
00002 #define OPENTISSUE_DYNAMICS_MBD_UTIL_JOINTS_MBD_SLIDER_JOINT_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/dynamics/mbd/interfaces/mbd_joint_interface.h>
00013 #include <OpenTissue/dynamics/mbd/limits/mbd_linear_joint_limit.h>
00014 #include <OpenTissue/dynamics/mbd/motors/mbd_linear_joint_motor.h>
00015 #include <OpenTissue/core/math/math_constants.h>
00016
00017
00018 namespace OpenTissue
00019 {
00020 namespace mbd
00021 {
00022
00023 template< typename mbd_types >
00024 class SliderJoint
00025 : public JointInterface<mbd_types>
00026 {
00027 public:
00028
00029 typedef typename mbd_types::math_policy math_policy;
00030 typedef typename mbd_types::math_policy::index_type size_type;
00031 typedef typename mbd_types::math_policy::real_type real_type;
00032 typedef typename mbd_types::math_policy::vector3_type vector3_type;
00033 typedef typename mbd_types::math_policy::matrix3x3_type matrix3x3_type;
00034 typedef typename mbd_types::math_policy::quaternion_type quaternion_type;
00035 typedef typename mbd_types::math_policy::vector_range vector_range;
00036 typedef typename mbd_types::math_policy::idx_vector_range idx_vector_range;
00037 typedef typename mbd_types::math_policy::matrix_range matrix_range;
00038 typedef typename mbd_types::math_policy::vector_type vector_type;
00039 typedef typename mbd_types::math_policy::value_traits value_traits;
00040
00041 typedef LinearJointMotor<mbd_types> linear_motor_type;
00042 typedef LinearJointLimit<mbd_types> linear_limit_type;
00043
00044
00045 protected:
00046
00047 vector3_type m_r_off_B;
00048 vector3_type m_r_off_wcs;
00049 vector3_type m_c;
00050 vector3_type m_half_cXt1;
00051 vector3_type m_half_cXt2;
00052 vector3_type m_t1;
00053 vector3_type m_t2;
00054 vector3_type m_u;
00055 real_type m_theta_error;
00056 quaternion_type m_Q_initial;
00057 quaternion_type m_Q_initial_conj;
00058 quaternion_type m_Q_error;
00059
00060 linear_limit_type * m_limit;
00061 linear_motor_type * m_motor;
00062
00063 size_type m_rows;
00064 size_type m_motor_offset;
00065 size_type m_limit_offset;
00066 vector_type m_gamma;
00067 vector_type m_solution;
00068
00069 public:
00070
00071
00077 real_type get_offset() const
00078 {
00079 assert(this->m_socketA || !"SliderJoint::get_offset(): socket A was null");
00080 assert(this->m_socketB || !"SliderJoint::get_offset(): socket B was null");
00081
00082
00083 vector3_type s_wcs = this->m_socketA->get_joint_axis_world();
00084
00085
00086 quaternion_type Q;
00087 this->m_socketB->get_body()->get_orientation(Q);
00088 vector3_type r_off_wcs = Q.rotate(m_r_off_B);
00089
00090
00091 vector3_type c,r_cm_A,r_cm_B;
00092 this->m_socketA->get_body()->get_position(r_cm_A);
00093 this->m_socketB->get_body()->get_position(r_cm_B);
00094 c = r_cm_B - r_cm_A;
00095
00096
00097
00098
00099 vector3_type r_disp = c - r_off_wcs;
00100
00101
00102
00103 return s_wcs * r_disp;
00104 }
00105
00113 real_type get_offset_rate() const
00114 {
00115 assert(this->m_socketA || !"SliderJoint::get_offset_rate(): socket A was null");
00116 assert(this->m_socketB || !"SliderJoint::get_offset_rate(): socket B was null");
00117
00118
00119
00120
00121
00122
00123 vector3_type v_cm_A,v_cm_B;
00124 this->m_socketA->get_body()->get_velocity(v_cm_A);
00125 this->m_socketB->get_body()->get_velocity(v_cm_B);
00126 return this->m_socketA->get_joint_axis_world()*(v_cm_A - v_cm_B);
00127 }
00128
00129 vector3_type get_slider_axis_world() const
00130 {
00131 return this->m_socketA->get_joint_axis_world();
00132 }
00133
00134 void set_limit(linear_limit_type const & limit)
00135 {
00136 m_limit = const_cast<linear_limit_type*>(&limit);
00137 }
00138
00139 void set_motor(linear_motor_type const & motor)
00140 {
00141 m_motor = const_cast<linear_motor_type*>(&motor);
00142 }
00143
00144 public:
00145
00146 SliderJoint()
00147 : m_limit(0)
00148 , m_motor(0)
00149 , m_rows(0)
00150 {}
00151
00152 virtual ~SliderJoint() {}
00153
00154 public:
00155
00156 void evaluate()
00157 {
00158 using std::acos;
00159
00160 m_rows = 0;
00161
00162 if(!(this->m_socketA && this->m_socketB))
00163 return;
00164
00165 m_rows = 5;
00166
00167 vector3_type s_A_wcs = this->m_socketA->get_joint_axis_world();
00168 vector3_type s_B_wcs = this->m_socketB->get_joint_axis_world();
00169 m_u = cross(s_A_wcs , s_B_wcs);
00170 m_t1 = this->m_socketA->get_axis1_world();
00171 m_t2 = this->m_socketA->get_axis2_world();
00172
00173
00174
00175 vector3_type r_cm_A;
00176 vector3_type r_cm_B;
00177 this->m_socketA->get_body()->get_position(r_cm_A);
00178 this->m_socketB->get_body()->get_position(r_cm_B);
00179
00180 m_c = r_cm_B - r_cm_A;
00181 m_half_cXt1 = cross(m_c , m_t1)/value_traits::two();
00182 m_half_cXt2 = cross(m_c , m_t2)/value_traits::two();
00183
00184
00185 m_theta_error = acos(s_A_wcs * s_B_wcs);
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 quaternion_type Q_cur;
00203 quaternion_type Q_A,Q_B;
00204 this->m_socketA->get_body()->get_orientation(Q_A);
00205 this->m_socketB->get_body()->get_orientation(Q_B);
00206
00207
00208
00209
00210
00211
00212
00213 Q_cur = conj(Q_B) % Q_A;
00214 m_Q_error = Q_cur % m_Q_initial_conj;
00215
00216
00217
00218
00219
00220
00221
00222 m_r_off_wcs = Q_B.rotate(m_r_off_B);
00223
00224
00225 m_limit_offset = 0;
00226 m_motor_offset = 0;
00227 if(m_limit)
00228 {
00229 m_limit->evaluate(
00230 get_offset()
00231 , get_slider_axis_world()
00232 , r_cm_A
00233 , r_cm_B
00234 );
00235 if(m_limit->is_active())
00236 {
00237 m_limit_offset = m_rows;
00238 ++m_rows;
00239 }
00240 }
00241 if(m_motor)
00242 {
00243 m_motor->evaluate(
00244 get_slider_axis_world()
00245 , r_cm_A
00246 , r_cm_B
00247 );
00248 if(m_motor->is_active())
00249 {
00250 m_motor_offset = m_rows;
00251 ++m_rows;
00252 }
00253 }
00254 }
00255
00256 size_type get_number_of_jacobian_rows() const {return m_rows;}
00257
00258 void get_linear_jacobian_A(matrix_range & J)const
00259 {
00260 assert(J.size1()==m_rows || !"SliderJoint::get_linear_jacobian_A(): incorrect dimensions");
00261 assert(J.size2()==3 || !"SliderJoint::get_linear_jacobian_A(): incorrect dimensions");
00262 J(0,0) = value_traits::zero(); J(0,1) = value_traits::zero(); J(0,2) = value_traits::zero();
00263 J(1,0) = value_traits::zero(); J(1,1) = value_traits::zero(); J(1,2) = value_traits::zero();
00264 J(2,0) = value_traits::zero(); J(2,1) = value_traits::zero(); J(2,2) = value_traits::zero();
00265 J(3,0) = m_t1(0); J(3,1) = m_t1(1); J(3,2) = m_t1(2);
00266 J(4,0) = m_t2(0); J(4,1) = m_t2(1); J(4,2) = m_t2(2);
00267 if(m_limit_offset)
00268 m_limit->get_linear_jacobian_A(J,m_limit_offset);
00269 if(m_motor_offset)
00270 m_motor->get_linear_jacobian_A(J,m_motor_offset);
00271 }
00272
00273 void get_linear_jacobian_B(matrix_range & J)const
00274 {
00275 assert(J.size1()==m_rows || !"SliderJoint::get_linear_jacobian_B(): incorrect dimensions");
00276 assert(J.size2()==3 || !"SliderJoint::get_linear_jacobian_B(): incorrect dimensions");
00277 J(0,0) = value_traits::zero(); J(0,1) = value_traits::zero(); J(0,2) = value_traits::zero();
00278 J(1,0) = value_traits::zero(); J(1,1) = value_traits::zero(); J(1,2) = value_traits::zero();
00279 J(2,0) = value_traits::zero(); J(2,1) = value_traits::zero(); J(2,2) = value_traits::zero();
00280 J(3,0) = -m_t1(0); J(3,1) = -m_t1(1); J(3,2) = -m_t1(2);
00281 J(4,0) = -m_t2(0); J(4,1) = -m_t2(1); J(4,2) = -m_t2(2);
00282 if(m_limit_offset)
00283 m_limit->get_linear_jacobian_B(J,m_limit_offset);
00284 if(m_motor_offset)
00285 m_motor->get_linear_jacobian_B(J,m_motor_offset);
00286 }
00287
00288 void get_angular_jacobian_A(matrix_range & J)const
00289 {
00290 assert(J.size1()==m_rows || !"SliderJoint::get_angular_jacobian_A(): incorrect dimensions");
00291 assert(J.size2()==3 || !"SliderJoint::get_angular_jacobian_A(): incorrect dimensions");
00292 J(0,0) = value_traits::one(); J(0,1) = value_traits::zero(); J(0,2) = value_traits::zero();
00293 J(1,0) = value_traits::zero(); J(1,1) = value_traits::one(); J(1,2) = value_traits::zero();
00294 J(2,0) = value_traits::zero(); J(2,1) = value_traits::zero(); J(2,2) = value_traits::one();
00295 J(3,0) = m_half_cXt1(0); J(3,1) = m_half_cXt1(1); J(3,2) = m_half_cXt1(2);
00296 J(4,0) = m_half_cXt2(0); J(4,1) = m_half_cXt2(1); J(4,2) = m_half_cXt2(2);
00297 if(m_limit_offset)
00298 m_limit->get_angular_jacobian_A(J,m_limit_offset);
00299 if(m_motor_offset)
00300 m_motor->get_angular_jacobian_A(J,m_motor_offset);
00301 }
00302
00303 void get_angular_jacobian_B(matrix_range & J)const
00304 {
00305 assert(J.size1()==m_rows || !"SliderJoint::get_angular_jacobian_B(): incorrect dimensions");
00306 assert(J.size2()==3 || !"SliderJoint::get_angular_jacobian_B(): incorrect dimensions");
00307 J(0,0) = -value_traits::one(); J(0,1) = value_traits::zero(); J(0,2) = value_traits::zero();
00308 J(1,0) = value_traits::zero(); J(1,1) = -value_traits::one(); J(1,2) = value_traits::zero();
00309 J(2,0) = value_traits::zero(); J(2,1) = value_traits::zero(); J(2,2) = -value_traits::one();
00310 J(3,0) = m_half_cXt1(0); J(3,1) = m_half_cXt1(1); J(3,2) = m_half_cXt1(2);
00311 J(4,0) = m_half_cXt2(0); J(4,1) = m_half_cXt2(1); J(4,2) = m_half_cXt2(2);
00312 if(m_limit_offset)
00313 m_limit->get_angular_jacobian_B(J,m_limit_offset);
00314 if(m_motor_offset)
00315 m_motor->get_angular_jacobian_B(J,m_motor_offset);
00316 }
00317
00318 void get_stabilization_term(vector_range & b_error)const
00319 {
00320 assert(b_error.size()==m_rows || !"SliderJoint::get_stabilization_term(): incorrect dimensions");
00321
00322 real_type k_cor = this->get_frames_per_second()*this->get_error_reduction_parameter();
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 b_error(0) = -2.*k_cor * m_Q_error.v()(0);
00352 b_error(1) = -2.*k_cor * m_Q_error.v()(1);
00353 b_error(2) = -2.*k_cor * m_Q_error.v()(2);
00354 vector3_type tmp = m_c - m_r_off_wcs;
00355 b_error(3) = k_cor * m_t1*tmp;
00356 b_error(4) = k_cor * m_t2*tmp;
00357 if(m_limit_offset)
00358 m_limit->get_stabilization_term(b_error,m_limit_offset);
00359 if(m_motor_offset)
00360 m_motor->get_stabilization_term(b_error,m_motor_offset);
00361 }
00362
00363 void get_low_limits(vector_range & lo)const
00364 {
00365 assert(lo.size()==m_rows || !"SliderJoint::get_low_limits(): incorrect dimensions");
00366 lo(0) = OpenTissue::math::detail::lowest<real_type>();
00367 lo(1) = OpenTissue::math::detail::lowest<real_type>();
00368 lo(2) = OpenTissue::math::detail::lowest<real_type>();
00369 lo(3) = OpenTissue::math::detail::lowest<real_type>();
00370 lo(4) = OpenTissue::math::detail::lowest<real_type>();
00371 if(m_limit_offset)
00372 m_limit->get_low_limits(lo,m_limit_offset);
00373 if(m_motor_offset)
00374 m_motor->get_low_limits(lo,m_motor_offset);
00375 }
00376
00377 void get_high_limits(vector_range & hi)const
00378 {
00379 assert(hi.size()==m_rows || !"SliderJoint::get_high_limits(): incorrect dimensions");
00380 hi(0) = OpenTissue::math::detail::highest<real_type>();
00381 hi(1) = OpenTissue::math::detail::highest<real_type>();
00382 hi(2) = OpenTissue::math::detail::highest<real_type>();
00383 hi(3) = OpenTissue::math::detail::highest<real_type>();
00384 hi(4) = OpenTissue::math::detail::highest<real_type>();
00385 if(m_limit_offset)
00386 m_limit->get_high_limits(hi,m_limit_offset);
00387 if(m_motor_offset)
00388 m_motor->get_high_limits(hi,m_motor_offset);
00389 }
00390
00391 void get_dependency_indices(idx_vector_range & dep)const
00392 {
00393 assert(dep.size()==m_rows || !"SliderJoint::get_dependency_indices(): incorrect dimensions");
00394 for(size_type i=0;i<m_rows;++i)
00395 dep(i) = OpenTissue::math::detail::highest<size_type>();
00396 }
00397
00398 void get_dependency_factors(vector_range & factors)const
00399 {
00400 assert(factors.size()==m_rows || !"SliderJoint::get_dependency_factors(): incorrect dimensions");
00401 for(size_type i=0;i<m_rows;++i)
00402 factors(i) = value_traits::zero();
00403 }
00404
00405 void set_regularization(vector_range const & gamma)
00406 {
00407 assert(gamma.size()==m_rows || !"SliderJoint::set_regularization(): incorrect dimensions");
00408 math_policy::resize( m_gamma, 5);
00409 for(size_type i=0;i<5;++i)
00410 {
00411 assert(gamma(i)<=1 || !"SliderJoint::set_regularization(): gamma was greater than 1");
00412 assert(gamma(i)>=0 || !"SliderJoint::set_regularization(): gamma was less than 0");
00413 m_gamma(i) = gamma(i);
00414 }
00415 if(m_limit_offset)
00416 m_limit->set_regularization(gamma,m_limit_offset);
00417 if(m_motor_offset)
00418 m_motor->set_regularization(gamma,m_motor_offset);
00419 }
00420
00421 void get_regularization(vector_range & gamma)const
00422 {
00423 assert(gamma.size()==m_rows || !"SliderJoint::get_regularization(): incorrect dimensions");
00424 if(m_gamma.size()==0)
00425 {
00426 for(size_type i=0;i<5;++i)
00427 gamma(i) = 0;
00428 }
00429 else
00430 {
00431 for(size_type i=0;i<5;++i)
00432 gamma(i) = m_gamma(i);
00433 }
00434 if(m_limit_offset)
00435 m_limit->get_regularization(gamma,m_limit_offset);
00436 if(m_motor_offset)
00437 m_motor->get_regularization(gamma,m_motor_offset);
00438 }
00439
00440 void set_solution(vector_range const & solution)
00441 {
00442 assert(solution.size()==m_rows || !"SliderJoint::set_solution(): incorrect dimensions");
00443
00444 math_policy::resize( m_solution, 5);
00445 for(size_type i=0;i<5;++i)
00446 m_solution(i) = solution(i);
00447 if(m_limit_offset)
00448 m_limit->set_solution(solution,m_limit_offset);
00449 if(m_motor_offset)
00450 m_motor->set_solution(solution,m_motor_offset);
00451 }
00452
00453 void get_solution(vector_range & solution)const
00454 {
00455 assert(solution.size()==m_rows || !"SliderJoint::get_solution(): incorrect dimensions");
00456 if(m_solution.size()==0)
00457 {
00458 for(size_type i=0;i<5;++i)
00459 solution(i) = value_traits::zero();
00460 }
00461 else
00462 {
00463 for(size_type i=0;i<5;++i)
00464 solution(i) = m_solution(i);
00465 }
00466 if(m_limit_offset)
00467 m_limit->get_solution(solution,m_limit_offset);
00468 if(m_motor_offset)
00469 m_motor->get_solution(solution,m_motor_offset);
00470 }
00471
00472 void calibration()
00473 {
00474 assert(this->m_socketA || !"SliderJoint::calibration(): socket A was null");
00475 assert(this->m_socketB || !"SliderJoint::calibration(): socket B was null");
00476
00477
00478 quaternion_type Q_A,Q_B;
00479 this->m_socketA->get_body()->get_orientation(Q_A);
00480 this->m_socketB->get_body()->get_orientation(Q_B);
00481
00482
00483
00484
00485
00486
00487
00488 m_Q_initial = conj(Q_B) % Q_A;
00489 m_Q_initial_conj = conj(m_Q_initial);
00490
00491
00492 vector3_type r_cm_A;
00493 vector3_type r_cm_B;
00494 this->m_socketA->get_body()->get_position(r_cm_A);
00495 this->m_socketB->get_body()->get_position(r_cm_B);
00496
00497
00498 m_c = r_cm_B - r_cm_A;
00499
00500
00501 m_r_off_B = conj(Q_B).rotate(m_c);
00502 }
00503
00504 };
00505
00506 }
00507 }
00508
00509 #endif