Go to the documentation of this file.00001 #ifndef OPENTISSUE_KINEMATICS_INVERSE_ESTIMATE_JOINTS_H
00002 #define OPENTISSUE_KINEMATICS_INVERSE_ESTIMATE_JOINTS_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_covariance.h>
00013 #include <OpenTissue/core/math/math_eigen_system_decomposition.h>
00014 #include <OpenTissue/core/math/math_compute_contiguous_angle_interval.h>
00015
00016 #include <boost/cast.hpp>
00017
00018 #include <vector>
00019
00020 namespace OpenTissue
00021 {
00022 namespace kinematics
00023 {
00024 namespace inverse
00025 {
00026
00039 template<typename sample_iterator, typename bone_type>
00040 inline void estimate_joint_type( sample_iterator const & begin, sample_iterator const & end, bone_type & bone)
00041 {
00042 typedef typename bone_type::math_types math_types;
00043 typedef typename bone_type::bone_traits bone_traits;
00044 typedef typename math_types::vector3_type V;
00045 typedef typename math_types::real_type T;
00046 typedef typename math_types::quaternion_type Q;
00047 typedef typename math_types::matrix3x3_type M;
00048 typedef typename math_types::value_traits value_traits;
00049
00050 T const too_tiny = boost::numeric_cast<T>(0.0001);
00051
00052 size_t const N = std::distance( begin, end);
00053
00054 std::vector<V> A;
00055 std::vector<T> angles;
00056 std::vector<T> phi_angles;
00057 std::vector<T> psi_angles;
00058 std::vector<T> theta_angles;
00059
00060 A.resize(N);
00061 angles.resize(N);
00062 phi_angles.resize(N);
00063 psi_angles.resize(N);
00064 theta_angles.resize(N);
00065
00066 size_t i = 0u;
00067 V rotation_axis = V(value_traits::zero(),value_traits::zero(),value_traits::zero());
00068
00069
00070 for(sample_iterator X = begin;X!=end;++X)
00071 {
00072
00073 OpenTissue::math::get_axis_angle(X->Q(), rotation_axis, angles[i]);
00074 OpenTissue::math::ZYZ_euler_angles(X->Q(), phi_angles[i], psi_angles[i], theta_angles[i]);
00075 A[i] = X->Q().v();
00076 rotation_axis += A[i];
00077 ++i;
00078 }
00079 rotation_axis = normalize(rotation_axis);
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 V m;
00090 M C;
00091
00092 OpenTissue::math::covariance( A.begin(), A.end(), m, C);
00093
00094 M R;
00095 V d;
00096
00097 OpenTissue::math::eigen(C, R, d);
00098
00099 size_t dimension = fabs( d(0) ) > too_tiny ? 1u :0u;
00100 dimension += fabs( d(1) ) > too_tiny ? 1u :0u;
00101 dimension += fabs( d(2) ) > too_tiny ? 1u :0u;
00102
00103 if(dimension == 0 )
00104 {
00105
00106 bone.type() = bone_traits::ball_type;
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 T const & phi = phi_angles[0];
00117 T const & psi = psi_angles[0];
00118 T const & theta = theta_angles[0];
00119
00123
00124
00125
00126 bone.theta(0) = phi;
00127 bone.theta(1) = psi;
00128 bone.theta(2) = theta;
00129
00130
00131 bone.min_joint_limit(0) = phi;
00132 bone.min_joint_limit(1) = psi;
00133 bone.min_joint_limit(2) = theta;
00134
00135 bone.max_joint_limit(0) = phi;
00136 bone.max_joint_limit(1) = psi;
00137 bone.max_joint_limit(2) = theta;
00138 }
00139 else if(dimension == 1 )
00140 {
00141 bone.type() = bone_traits::hinge_type;
00142
00143 bone.u() = rotation_axis;
00144
00145 T min_angle;
00146 T max_angle;
00147 OpenTissue::math::compute_contiguous_angle_interval(angles.begin(),angles.end(),min_angle,max_angle);
00148 bone.min_joint_limit(0) = min_angle;
00149 bone.max_joint_limit(0) = max_angle;
00150 }
00151 else if(dimension == 2 || dimension == 3)
00152 {
00153 bone.type() = bone_traits::ball_type;
00154
00155 T phi = value_traits::zero();
00156 T psi = value_traits::zero();
00157 T theta = value_traits::zero();
00158
00159 T phi_max = -value_traits::infinity();
00160 T psi_max = -value_traits::infinity();
00161 T theta_max = -value_traits::infinity();
00162
00163 T phi_min = value_traits::infinity();
00164 T psi_min = value_traits::infinity();
00165 T theta_min = value_traits::infinity();
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 OpenTissue::math::compute_contiguous_angle_interval( phi_angles.begin(), phi_angles.end(), phi_min,phi_max);
00185 OpenTissue::math::compute_contiguous_angle_interval( psi_angles.begin(), psi_angles.end(), psi_min,psi_max);
00186 OpenTissue::math::compute_contiguous_angle_interval( theta_angles.begin(), theta_angles.end(), theta_min,theta_max);
00187
00188 bone.min_joint_limit(0) = phi_min;
00189 bone.max_joint_limit(0) = phi_max;
00190 bone.theta(0) = (phi_min + phi_max)*value_traits::half();
00191
00192 bone.min_joint_limit(1) = psi_min;
00193 bone.max_joint_limit(1) = psi_max;
00194 bone.theta(1) = (psi_min + psi_max)*value_traits::half();
00195
00196 bone.min_joint_limit(2) = theta_min;
00197 bone.max_joint_limit(2) = theta_max;
00198 bone.theta(2) = (theta_min + theta_max)*value_traits::half();
00199 }
00200 }
00201
00216 template <typename blend_scheduler_type, typename skeleton_type >
00217 inline void estimate_joints(blend_scheduler_type & scheduler, skeleton_type & skeleton)
00218 {
00219 size_t const N = 100u;
00220
00221 typedef typename skeleton_type::bone_traits bone_traits;
00222 typedef typename bone_traits::transform_type transform_type;
00223 typedef typename skeleton_type::math_types math_types;
00224 typedef typename math_types::vector3_type V;
00225 typedef typename math_types::real_type T;
00226 typedef typename math_types::quaternion_type Q;
00227 typedef typename math_types::matrix3x3_type M;
00228 typedef typename math_types::coordsys_type coordsys_type;
00229 typedef typename math_types::value_traits value_traits;
00230 typedef std::vector< coordsys_type > samples_container;
00231
00232
00233 std::vector< samples_container > samples;
00234
00235 samples.resize( skeleton.size() );
00236 for(skeleton_type::bone_iterator bone = skeleton.begin();bone!=skeleton.end();++bone)
00237 {
00238 samples[bone->get_number()].resize( N );;
00239 }
00240
00241
00242 T duration = scheduler.compute_duration();
00243 T time_step = duration / (N-1);
00244 T time = value_traits::zero();
00245 for(size_t i = 0;i < N;++i)
00246 {
00247 scheduler.compute_pose(skeleton, time);
00248 for(skeleton_type::bone_iterator bone = skeleton.begin();bone!=skeleton.end();++bone)
00249 {
00250 samples[bone->get_number()][i] = bone_traits::convert( bone->relative() );
00251 }
00252 time += time_step;
00253 }
00254
00255
00256 for(skeleton_type::bone_iterator bone = skeleton.begin();bone!=skeleton.end();++bone)
00257 {
00258 estimate_joint_type( samples[bone->get_number()].begin(), samples[bone->get_number()].end(), *bone);
00259 }
00260 }
00261
00262 }
00263 }
00264 }
00265
00266
00267
00268 #endif