00001 #include "r2_gaze_ik.hpp"
00002
00003
00004 #include <kdl/frames.hpp>
00005
00006
00007 #include <Eigen/SVD>
00008
00009
00010 #include <cmath>
00011 #include <iostream>
00012
00013 namespace r2_gaze_controller
00014 {
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 template<typename _Matrix_Type_>
00070 bool pseudoInverse(const _Matrix_Type_ &a, _Matrix_Type_ &result, double
00071 epsilon = std::numeric_limits<typename _Matrix_Type_::Scalar>::epsilon())
00072 {
00073 if(a.rows()<a.cols())
00074 return false;
00075
00076 Eigen::JacobiSVD< _Matrix_Type_ > svd = a.jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV);
00077
00078 typename _Matrix_Type_::Scalar tolerance = epsilon * std::max(a.cols(), a.rows()) * svd.singularValues().array().abs().maxCoeff();
00079
00080 result = svd.matrixV() * _Matrix_Type_( (svd.singularValues().array().abs() > tolerance).select(svd.singularValues().array().inverse(), 0) ).asDiagonal() * svd.matrixU().adjoint();
00081 return true;
00082 }
00083
00084 struct Convert
00085 {
00086 static void toEigenVector(const KDL::Frame& in, Eigen::Vector3d& out)
00087 {
00088 for (int r=0; r < 3; r++) out(r) = in.p.data[r];
00089 }
00090
00091 static void toJntArray(const Eigen::VectorXd& in, KDL::JntArray& out)
00092 {
00093 out.data = in;
00094 }
00095 };
00096
00097 R2GazeIK::R2GazeIK(const KDL::Chain& chain) :
00098 chain(chain),
00099 fk(chain),
00100 jacobian_solver(chain),
00101 N(chain.getNrOfJoints()),
00102 Qinv(Eigen::VectorXd::Ones(N)),
00103 maxSolverAttempts(200),
00104 dt(0.1),
00105 p_d(Eigen::Vector3d::Zero()),
00106 p(Eigen::Vector3d::Zero()),
00107 e(Eigen::Vector3d::Zero()),
00108 J_partial(Jacobian::Zero(3,N)),
00109 Jw(Jacobian::Zero(3,N)),
00110 Jwt(Jacobian::Zero(N,3)),
00111 Jwt_inv(Jacobian::Zero(N,3)),
00112 q_kdl(N),
00113 J_kdl(N),
00114 del_q(N), q_local(N)
00115 {
00116 }
00117
00118 R2GazeIK::~R2GazeIK()
00119 {
00120
00121 }
00122
00123 void R2GazeIK::setWeightMatrix(const Eigen::VectorXd& w)
00124 {
00125 Qinv.diagonal() = w;
00126 }
00127
00128 void R2GazeIK::setWeightMatrix(const Eigen::MatrixXd& W)
00129 {
00130 Eigen::VectorXd w(W.diagonal());
00131 this->setWeightMatrix(w);
00132 }
00133
00134 double R2GazeIK::computeDelta(const Eigen::VectorXd& q, const KDL::Frame& desired_frame, Eigen::VectorXd& del_q)
00135 {
00136
00137 Convert::toEigenVector(desired_frame, p_d);
00138
00139
00140 Convert::toJntArray(q, q_kdl);
00141
00142
00143 KDL::Frame frame_actual;
00144 if (fk.JntToCart(q_kdl, frame_actual) < 0)
00145 {
00146 return -1;
00147 }
00148 Convert::toEigenVector(frame_actual, p);
00149
00150
00151 e = p_d - p;
00152
00153
00154 jacobian_solver.JntToJac(q_kdl, J_kdl);
00155
00156
00157 J_partial = J_kdl.data.topRows(3);
00158
00159
00160 Jw = J_partial * Qinv * J_partial.transpose();
00161 Jwt = Jw.transpose();
00162 pseudoInverse(Jwt, Jwt_inv);
00163
00164
00165 del_q = Qinv * J_partial.transpose() * Jwt_inv.transpose() * e;
00166 return e.transpose() * e;
00167 }
00168
00169 int R2GazeIK::computeSolution(const KDL::JntArray& q_act, const KDL::Frame& desired_frame, KDL::JntArray& q)
00170 {
00171 Eigen::VectorXd q_in(q_act.data), q_out(q_act.data);
00172 int ret = computeSolution(q_in, desired_frame, q_out);
00173 q.data = q_out;
00174 return ret;
00175 }
00176
00177 int R2GazeIK::computeSolution(const Eigen::VectorXd& q_act, const KDL::Frame& desired_frame, Eigen::VectorXd& q)
00178 {
00179
00180 q_local = q_act;
00181
00182
00183 double err = computeDelta(q_local, desired_frame, del_q);
00184
00185 if (err < 0) return -1;
00186
00187
00188 int attempts = 0;
00189 while ((err > 0.01) & (attempts < maxSolverAttempts))
00190 {
00191 q_local += dt * del_q;
00192 err = computeDelta(q_local, desired_frame, del_q);
00193 if (err < 0) return -1;
00194 attempts = attempts + 1;
00195 }
00196
00197 q = q_local;
00198
00199 if (attempts >= maxSolverAttempts) return -1;
00200 return 0;
00201 }
00202
00203 }