kuka_ikac.cpp
Go to the documentation of this file.
00001 // BETA VERSION, STILL BEING TESTED, BUT APPARENTLY ROBUST AND EFFICIENT.
00002 
00003 #include "kuka_ikac.h"
00004 using namespace Eigen;
00005 using namespace std;
00006 
00007 KukaIKAC::KukaIKAC() {
00008   //init class attributes if necessary
00009   //this->loop_rate = 2;//in [Hz]
00010 
00011   this->currentjoints_.resize(7);
00012 
00013   //string for port names
00014   std::string port_name;
00015 
00016   // [init publishers]
00017   port_name = ros::names::append(ros::this_node::getName(), "ikjoints"); 
00018   this->ik_joints_publisher_ = this->nh_.advertise<sensor_msgs::JointState>(port_name, 5);
00019   this->ik_joints_msg.position.resize(7);
00020   
00021   // [init subscribers]
00022   port_name = ros::names::append(ros::this_node::getName(), "joint_states"); 
00023   this->joint_states_subscriber = this->nh_.subscribe(port_name, 5, &KukaIKAC::joint_states_callback, this);
00024   
00025   // [init services]
00026   port_name = ros::names::append(ros::this_node::getName(), "wamik"); 
00027   this->kukaik_server = this->nh_.advertiseService(port_name, &KukaIKAC::kukaikCallback, this);
00028   
00029   port_name = ros::names::append(ros::this_node::getName(), "wamik_from_pose");
00030   this->kukaik_server_fromPose = this->nh_.advertiseService(port_name, &KukaIKAC::kukaikCallbackFromPose, this);
00031 
00032   // [init clients]
00033   port_name = ros::names::append(ros::this_node::getName(), "joints_move"); 
00034   joint_move_client = this->nh_.serviceClient<iri_wam_common_msgs::joints_move>(port_name);
00035   
00036   // [init action servers]
00037   
00038   // [init action clients] 
00039  
00040   // [init variables]
00041 
00042 /* KUKA LIGHTWEIGHT ROBOT INVERSE KINEMATICS. This code works apparently correct without crashes. But please test it carefully to ensure 
00043 its robustness and also that the parameters introduced are correct (if not, the solution given by this algorithm would not be correct.*/
00044 
00045   double PI=3.14159265;
00046   // links offsets. d7 is the TCP offset. Arbitrarly set to 0.1.
00047   d1=0.3100;
00048   d3=0.4000;
00049   d5=0.3900;
00050   d7=0.0785; // Tool center point offset. This should be modified with the correct value!!!
00051   
00052   // for debugging purposes, if checksol_=1, the forward kinematics is computed to check if the solution has 0 error.
00053   checksol_=1;
00054   
00055   //DH PARAMETERS - STANDARD CONVENTION (not CRAIG's convention!!)
00056   DHparam_.resize(7,3);  
00057   DHparam_ << 0.0,  PI/2.0, d1,
00058                     0.0, -PI/2.0, 0.0,
00059                     0.0, -PI/2.0, d3,
00060                     0.0,  PI/2.0, 0.0,
00061                     0.0,  PI/2.0, d5,
00062                     0.0, -PI/2.0, 0.0,
00063                     0.0, 0.0, d7; 
00064             
00065   // JOINT LIMITS---> TO BE MODIFIED!! note that if joints 3,5 or 7 have their limits out of the [-pi,pi] range, the function pi2pi should be modified.
00066   Qlim_.resize(7,2);
00067   Qlim_ << -2.97, 2.97,
00068           -0.47, 3.49,
00069           -2.97, 2.97,
00070           -2.09, 2.09,
00071           -2.97, 2.97,
00072           -2.09, 2.09,
00073           -2.97, 2.97;
00074           
00075   // STEP INDICATES THE VARIATION MAGNITUDE APPLIED TO JOINT 1 TO FIND THE FIRST SOLUTION
00076   step_ = 0.0005;
00077   
00078   // when a first solution is found, the elbow is rotated around the wrist-shoulder axis so as to obtain more solutions. These rotations
00079   //have a magnitude of 2*pi/IMAX_.
00080   IMAX_ = 100;
00081   
00082 }
00083 
00084 void KukaIKAC::ikPub(void)
00085 {
00086   for (int i=0;i<7;i++){
00087     this->ik_joints_msg.position[i]=joints_(i);
00088   }
00089     this->ik_joints_publisher_.publish(this->ik_joints_msg);
00090 }
00091 
00092 /*  [subscriber callbacks] */
00093 void KukaIKAC::joint_states_callback(const sensor_msgs::JointState::ConstPtr& msg) { 
00094 
00095   for(int i=0;i<7;i++)
00096     currentjoints_[i] = msg->position[i]; 
00097 
00098 }
00099 
00100 /*  [service callbacks] */
00101 bool KukaIKAC::kukaikCallbackFromPose(iri_wam_common_msgs::wamInverseKinematicsFromPose::Request &req, iri_wam_common_msgs::wamInverseKinematicsFromPose::Response &res){
00102 
00103   ROS_INFO("[KukaIKAC] User Given Current Joints %s (j1, j2, j3, j4, j5, j6, j7): [ %f, %f, %f, %f, %f, %f, %f ]",
00104             req.current_joints.header.frame_id.c_str(), 
00105             req.current_joints.position[0], 
00106             req.current_joints.position[1],
00107             req.current_joints.position[2],
00108             req.current_joints.position[3],
00109             req.current_joints.position[4],
00110             req.current_joints.position[5],
00111             req.current_joints.position[6]);
00112   
00113   ROS_INFO("[KukaIKAC] Received Pose from frame_id %s (x, y, z, qx, qy, qz, qw): [ %f, %f, %f, %f, %f, %f, %f ]",
00114             req.desired_pose.header.frame_id.c_str(), 
00115             req.desired_pose.pose.position.x, 
00116             req.desired_pose.pose.position.y,
00117             req.desired_pose.pose.position.z,
00118             req.desired_pose.pose.orientation.x,
00119             req.desired_pose.pose.orientation.y,
00120             req.desired_pose.pose.orientation.z,
00121             req.desired_pose.pose.orientation.w);
00122   
00123   // User defined current pose
00124   std::vector<double> currentjoints;
00125   for(int ii=0; ii<7; ii++)
00126     currentjoints[ii] = req.current_joints.position[ii]; 
00127 
00128   Quaternion<float> quat( req.desired_pose.pose.orientation.w, req.desired_pose.pose.orientation.x, req.desired_pose.pose.orientation.y, req.desired_pose.pose.orientation.z);
00129   Matrix3f mat = quat.toRotationMatrix();
00130 
00131   std::vector <double> desired_pose(16,0);
00132   std::vector <double> desired_joints(7,0);
00133 
00134   // Desired pose as a Homogeneous Transformation
00135   desired_pose[3] = req.desired_pose.pose.position.x;
00136   desired_pose[7] = req.desired_pose.pose.position.y;
00137   desired_pose[11] = req.desired_pose.pose.position.z;
00138   desired_pose[15] = 1;
00139   for(int i=0; i<12; i++){
00140    if(i%4 != 3){
00141      desired_pose[i] = mat(i/4,i%4);
00142    }
00143   }
00144   ROS_INFO("[KukaIKAC] Received HRt:\n [ \t%f %f %f %f\n\t %f %f %f %f\n\t %f %f %f %f\n\t %f %f %f %f\n",
00145             desired_pose[0], desired_pose[1], desired_pose[2], desired_pose[3],
00146             desired_pose[4], desired_pose[5], desired_pose[6], desired_pose[7],
00147             desired_pose[8], desired_pose[9], desired_pose[10], desired_pose[11],
00148             desired_pose[12], desired_pose[13], desired_pose[14], desired_pose[15]);
00149 
00150   if(!KukaIKAC::ik(desired_pose, currentjoints, desired_joints)){
00151       ROS_ERROR("[KukaIKAC] IK solution not found. Is pose out of configuration space?");
00152       return false;
00153   }else{
00154 
00155       ROS_INFO("[KukaIKAC] Service computed joints:\n %f %f %f %f %f %f %f\n", desired_joints.at(0), desired_joints.at(1), desired_joints.at(2), desired_joints.at(3), desired_joints.at(4), desired_joints.at(5), desired_joints.at(6));
00156     
00157       res.desired_joints.position.resize(7);
00158       joints_.resize(7);
00159       for(int i=0; i<7; i++){
00160         res.desired_joints.position[i] = desired_joints.at(i);
00161         joints_(i) = desired_joints.at(i);
00162       }
00163   }
00164   return true;
00165 }
00166 
00167 bool KukaIKAC::kukaikCallback(iri_wam_common_msgs::wamInverseKinematics::Request &req, iri_wam_common_msgs::wamInverseKinematics::Response &res){
00168 
00169   ROS_INFO("[KukaIKAC] Received Pose from frame_id %s (x, y, z, qx, qy, qz, qw): [ %f, %f, %f, %f, %f, %f, %f ]",
00170             req.pose.header.frame_id.c_str(), 
00171             req.pose.pose.position.x, 
00172             req.pose.pose.position.y,
00173             req.pose.pose.position.z,
00174             req.pose.pose.orientation.x,
00175             req.pose.pose.orientation.y,
00176             req.pose.pose.orientation.z,
00177             req.pose.pose.orientation.w);
00178   
00179   Quaternion<float> quat( req.pose.pose.orientation.w, req.pose.pose.orientation.x, req.pose.pose.orientation.y, req.pose.pose.orientation.z);
00180   Matrix3f mat = quat.toRotationMatrix();
00181 
00182   std::vector <double> pose(16,0);
00183   std::vector <double> joints(7,0);
00184 
00185   pose[3] = req.pose.pose.position.x;
00186   pose[7] = req.pose.pose.position.y;
00187   pose[11] = req.pose.pose.position.z;
00188   pose[15] = 1;
00189   for(int i=0; i<12; i++){
00190    if(i%4 != 3){
00191      pose[i] = mat(i/4,i%4);
00192    }
00193   }
00194   ROS_INFO("[KukaIKAC] Received HRt:\n [ \t%f %f %f %f\n\t %f %f %f %f\n\t %f %f %f %f\n\t %f %f %f %f\n",
00195             pose[0],pose[1],pose[2],pose[3],
00196             pose[4],pose[5],pose[6],pose[7],
00197             pose[8],pose[9],pose[10],pose[11],
00198             pose[12],pose[13],pose[14],pose[15]);
00199 
00200   if(!KukaIKAC::ik(pose, currentjoints_, joints)){
00201       ROS_ERROR("[KukaIKAC] IK solution not found. Is pose out of configuration space?");
00202       return false;
00203   }else{
00204 
00205       ROS_INFO("[KukaIKAC] Service computed joints:\n %f %f %f %f %f %f %f\n", joints.at(0), joints.at(1), joints.at(2), joints.at(3), joints.at(4), joints.at(5), joints.at(6));
00206     
00207       res.joints.position.resize(7);
00208       joints_.resize(7);
00209       for(int i=0;i<7;i++){
00210         res.joints.position[i] = joints.at(i);
00211         joints_(i)=joints.at(i);
00212       }
00213       res.joints.position[1] = joints.at(1)+1.57079;
00214       joints_(1) = joints.at(1)+1.57079;
00215   }
00216   return true;
00217 }
00218 
00219 /*  [action callbacks] */
00220 
00221 /*  [action requests] */
00222 
00223 
00224 bool KukaIKAC::ik(vector<double> pose, vector<double> currentjoints, vector<double>& joints){
00225     //ik solver: pose is the desired homogeneous transformation, formated as a 16x1 vector:[1st row + 2nd row + 3rd row + 4th row]
00226     //currentjoints is the current joints vector, and joints is the output of the inverse kinematics.
00227     // joints is the output vector, the solution chosen
00228 
00229 /* Convert current joints and goal to eigen vector structure*/
00230   MatrixXd T0(4,4);
00231   VectorXd cjoints(7), nextangles(7), qoptim(7);
00232   for(int i=0;i<16;i++)
00233      T0(i/4,i%4) = pose.at(i); 
00234 
00235   for(int i=0;i<7;i++)
00236      cjoints(i) = currentjoints.at(i);
00237 
00238         joints.resize(7);
00239         MatrixXd A(4,4);
00240         // first solution loop variables
00241         double i=0;
00242         bool initfound=false;
00243         bool breakloop=false;
00244         // variables to store solutions and auxiliar variables
00245         MatrixXd qsol(8,7);
00246         VectorXd sol(8);        
00247         qsol.fill(0.0);
00248         sol.fill(0.0);
00249         double q10=cjoints(0);
00250         MatrixXd qaux;
00251         Vector3f Xw;
00252         // we initialise the potential value of the solutions with a very high value
00253         double potq=100000.;
00254         
00255         printf("Solution found is that which minimizes a weighted norm of the joints variation, to insert another criterion, modify the function KukaIKAC::potentialfunction \n");
00256         printf("Variation on q0 at each step for obtaining first solution : %e", step_);
00257         printf(" \n Initial joints:\n %f %f %f %f %f %f %f\n", currentjoints.at(0), currentjoints.at(1), currentjoints.at(2), currentjoints.at(3), currentjoints.at(4), currentjoints.at(5), currentjoints.at(6));
00258 
00259         
00260         /* Look for the initial solution */
00261         while (!initfound & !breakloop){
00262                 /* q10 is the joint 1 value used to find a solution. Its first value is the current joint 1 value.*/
00263     KukaIKAC::getq1(cjoints,i,q10);
00264                 
00265                 if (q10<Qlim_(0,1) && q10>Qlim_(0,0)){
00266                 /* qsol is the solution matrix (up to 8 solutions) found with q10, sol is a vector indicating which solutions are valid
00267                 T0 is the objective homogeneous transformation*/
00268                       KukaIKAC::exactikine(T0,q10,cjoints,qsol,sol);
00269                       /* we eliminate solutions which are not valid*/
00270                       KukaIKAC::filtersols(qsol,sol);
00271                       if (sol.sum()!=0.){ /* if there is a valid solution, we break the loop, and we take representatives of each elbow-shoulder
00272                          configuration (what we call basic solutions). These solutions are then to be rotated around the wrist-shoulder axis*/
00273                               KukaIKAC::basicsols(qsol,qaux,sol);
00274                               initfound=true;
00275                       }
00276                 }else{
00277                   if (i*step_+cjoints(0)>Qlim_(0,1) && -i*step_+cjoints(0)<Qlim_(0,0)){
00278                     breakloop=true; // if we get out of joint 1 range without having found a solution, we stop to avoid infinite loop
00279                     printf("LOOP BREAK,q1 steps OUT OF RANGE \n");
00280                   }
00281                 }       
00282                 i=i+1.;
00283         }
00284 
00285 
00286 
00287         if (initfound){
00288 
00289                 /* If we found a first solution, we perform optimization with the above mentioned rotations*/
00290                 KukaIKAC::optimizesol(qaux,T0,qoptim,potq,cjoints);     
00291                   joints.clear();
00292                   joints.resize(7);
00293                   for(int i=0;i<7;i++)
00294                      joints[i] = qoptim(i);
00295                   
00296                   std::cout<<"\n best solution is: \n"<<qoptim.transpose();
00297 
00298 
00299                 if (checksol_==1){
00300                   MatrixXd T01,T12,T23,T34,T45,T56,T67,T07;
00301                   KukaIKAC::DHmatrix(DHparam_(0,1),DHparam_(0,0),DHparam_(0,2),qoptim(0),T01),
00302                   KukaIKAC::DHmatrix(DHparam_(1,1),DHparam_(1,0),DHparam_(1,2),qoptim(1),T12),
00303                   KukaIKAC::DHmatrix(DHparam_(2,1),DHparam_(2,0),DHparam_(2,2),qoptim(2),T23),
00304                   KukaIKAC::DHmatrix(DHparam_(3,1),DHparam_(3,0),DHparam_(3,2),qoptim(3),T34);
00305                   KukaIKAC::DHmatrix(DHparam_(4,1),DHparam_(4,0),DHparam_(4,2),qoptim(4),T45);
00306                   KukaIKAC::DHmatrix(DHparam_(5,1),DHparam_(5,0),DHparam_(5,2),qoptim(5),T56);
00307                   KukaIKAC::DHmatrix(DHparam_(6,1),DHparam_(6,0),DHparam_(6,2),qoptim(6),T67);
00308                   T07=T01*T12*T23*T34*T45*T56*T67;
00309                   std::cout<<"\n Result matrix error T0-Tout= \n"<<T0-T07<<std::endl;
00310                 }
00311 
00312 
00313                 return true;
00314         } else{
00315                   for(int i=0;i<7;i++)
00316                      joints[i] = cjoints(i);
00317                 printf("SOLUTION NOT FOUND, robot not moving \n ");
00318                 return false;
00319         }    
00320 
00321 
00322 }
00323 
00324 
00325 
00326 
00327 
00328 void KukaIKAC::filtersols(MatrixXd qsol,VectorXd& sol){
00329 // INPUT: qsol, Nx7 MatrixXd, where each row is a solution of the WAM inverse kinematics, not concerning joint limits
00330 // OUPUT: the same Nx7 matrix, plus a N-dimentional VectorXd "sol", whose ith value is 1 if the ith row of qsol respects joint limits, 0 otherwise
00331         sol.resize(qsol.rows());
00332         sol.fill(1.0);
00333         for (int i=0;i<qsol.rows();i++){
00334                 for (int j=0;j<7;j++){
00335                         if ((qsol(i,j)<Qlim_(j,0))|(qsol(i,j)>Qlim_(j,1))){
00336                                 sol(i)=0.0;
00337                         }       
00338                 }
00339         }
00340 }
00341 
00342 void KukaIKAC::DHmatrix(double alpha, double a, double d,double& theta, MatrixXd& T){
00343 // INPUT: alpha, a, d Denavit Hartenberg parameters, and theta, the rotation angle of a wam link (standard notation, not craig!!).
00344 // OUTPUT: T, the D-H matrix (MatrixXd format) calculated with those parameters and theta.
00345 T.resize(4,4);
00346 T.fill(0.0);
00347 T(0,0)= cos(theta); 
00348 T(0,1)=-sin(theta)*cos(alpha);
00349 T(0,2)=sin(theta)*sin(alpha);
00350 T(0,3)=a*cos(theta);
00351 T(1,0)=sin(theta);
00352 T(1,1)=cos(theta)*cos(alpha); 
00353 T(1,2)=-cos(theta)*sin(alpha); 
00354 T(1,3)=a*sin(theta); 
00355 T(2,1)=sin(alpha); 
00356 T(2,2)=cos(alpha);
00357 T(2,3)=d; 
00358 T(3,3)=1;
00359 
00360 }
00361 
00362 
00363 
00364 void KukaIKAC::exactikine(MatrixXd T0, double q10, VectorXd cjoints, MatrixXd& qsol,VectorXd&sol){
00365 /* this function computes analitically the 8 solutions of the inverse kinematics of the robot, with a fixed value of the first joint (treating the
00366 robot as a 6-dof robot.*/
00367 // INPUT: T0=MatrixXd, the desired homogeneous transformation.
00368 //        q10=double, a fixed value for the first joint.
00369 // OUTPUT: qsol=MatrixXd, a 8x7 matrix, each row corresponds to a solution of the inverse kinematics for the desired goal.
00370 //         sol=vector, indicating wether solution has been found or not for the fixed q1. Note it does not consider joint limits!
00371 
00372         double q30=cjoints(2);
00373         double c4,aux1,aux2,aux3,signq4;
00374         double PI=3.14159265;
00375         qsol.resize(8,7);
00376         MatrixXd q4sol4(2,2);
00377         MatrixXd q2sol2(2,2);
00378         MatrixXd Pw(4,1),Pwaux(3,1);
00379         MatrixXd T12,T23,T34,T01,T04;
00380         VectorXd q3(2);
00381         Vector2d q5;
00382         Vector2d q6;
00383         Vector2d q7;
00384 
00385         MatrixXd qout(8,7);
00386         qout.fill(0.0);
00387         int k;
00388 
00389         /* We compute the wrist position, and an auxiliar wrist position, due to the offset d1*/
00390         Pw=T0.block<4,1>(0,3)-d7*T0.block<4,1>(0,2);
00391         Pwaux=Pw.block<3,1>(0,0);
00392         Pwaux(2,0)=Pw(2,0)-d1;
00393         
00394         /*Computing elbow joint with cosinus theorem*/
00395         c4=(Pwaux.squaredNorm()-pow(d3,2.0)-pow(d5,2.0))/(2*d3*d5);
00396         if (abs(c4)<=1.0){
00397           q4sol4(0,1)=1.0;
00398           q4sol4(1,1)=1.0;
00399           q4sol4(0,0)=acos(c4);
00400           q4sol4(1,0)=-acos(c4);
00401         }else{
00402           q4sol4.fill(0.0);
00403           q4sol4(0,0)=-99.9999;
00404           q4sol4(1,0)=-99.9999;
00405         }
00406         
00407         KukaIKAC::DHmatrix(DHparam_(0,1),DHparam_(0,0),DHparam_(0,2),q10,T01);
00408                 for (int i4=0;i4<2;i4++){ /*for each joint 4 solution, we compute the rest of the angles. To do so, we use the equations
00409                   obtained by writing T12^(-1)·T01^(-1)·Pw=T23·T34·Pw4 (Pw4=wrist in frame 4: [0 0 d5 1]')*/
00410 
00411                         aux1=c4*d5+d3;
00412                         aux2=-cos(q10)*Pw(0,0)-sin(q10)*Pw(1,0);
00413                         aux3=Pw(2,0)-d1;        
00414                         KukaIKAC::soltrig(aux1, aux2, aux3, q2sol2);
00415                         KukaIKAC::DHmatrix(DHparam_(3,1),DHparam_(3,0),DHparam_(3,2),q4sol4(i4,0),T34);
00416                         signq4=q4sol4(i4,0)/abs(q4sol4(i4,0));
00417                                 for(int i2=0;i2<2;i2++){
00418                                         if (abs(cos(q4sol4(i4,0))-1.0)>0.000001){
00419                                           q3(i2)=pi2pi(0.5*PI*(-signq4+1.0)+atan2(-sin(q10)*Pw(0,0)+cos(q10)*Pw(1,0),sin(q10)*cos(q2sol2(i2,0))*Pw(1,0)+cos(q10)*cos(q2sol2(i2,0))*Pw(0,0)+sin(q2sol2(i2,0))*(Pw(2,0)-d1)));
00420                                         }else{ //then the elbow is in a straight line, we do not vary the joint 3 configuration
00421                                           q3(i2)=q30;             
00422                                         }
00423                                         KukaIKAC::DHmatrix(DHparam_(1,1),DHparam_(1,0),DHparam_(1,2),q2sol2(i2,0),T12);
00424                                         KukaIKAC::DHmatrix(DHparam_(2,1),DHparam_(2,0),DHparam_(2,2),q3(i2),T23);
00425                                         T04=T01*T12*T23*T34;
00426                                         KukaIKAC::sphericalikine(T0,T04,cjoints,q5,q6,q7);
00427                                         /*We write all the posible solutions in a 8x7 matrix, each row of it is a solution set. the vector sol indicates wether solutions have been found*/
00428                                         for (int i5=0;i5<2;i5++){
00429                                                 k=i4*4+i2*2+i5;
00430                                                 qsol(k,0)=q10;
00431                                                 qsol(k,1)=q2sol2(i2,0);
00432                                                 qsol(k,2)=q3(i2);
00433                                                 qsol(k,3)=q4sol4(i4,0);
00434                                                 qsol(k,4)=q5(i5);
00435                                                 qsol(k,5)=q6(i5);
00436                                                 qsol(k,6)=q7(i5);
00437                                                 sol(k)=q4sol4(i4,1)*q2sol2(i2,1);
00438                                         }
00439                                 }
00440                 }
00441 }
00442 
00443 
00444 
00445 void KukaIKAC::basicsols(MatrixXd qsol,MatrixXd& qaux,VectorXd sol){
00446 // INPUT:  qsol=a 8x7 matrix (MatrixXd), each row corresponds to a solution of the inverse kinematics for the desired goal.
00447 //         sol=vector, indicating wether solution has been found or not for the fixed q1. Suposed to consider joint limits.
00448            
00449 // OUTPUT: qaux=a Nx7 matrix (MatrixXd), each row corresponds to a solution of the inverse kinematics for the desired goal of those in qsol. With the 
00450 //      consideration that qaux only has one row for each pair of q2, q4 which gives a solution of the inverse kinematics for a given q1 
00451 //      (note there will usualy be 2 solutions for the spherical wrist for each of these couples {q2,q4}
00452 
00453         MatrixXd qauxiliar2;
00454         qauxiliar2.resize(4,7);
00455         qauxiliar2.fill(-99.9999);
00456         int nbasics=0;
00457         for (int i=0;i<qsol.rows()/2;i++){
00458                 if (sol(2*i)>0.0){
00459                         qauxiliar2.row(nbasics)=qsol.row(2*i);
00460                         nbasics=nbasics+1;
00461 
00462                 }else if (sol(2*i+1)>0.0){
00463                         qauxiliar2.row(nbasics)=qsol.row(2*i+1);
00464                         nbasics=nbasics+1;
00465                 }
00466         }
00467         qaux.resize(nbasics,7);
00468 
00469         for (int j=0;j<nbasics;j++){
00470                 qaux.row(j)=qauxiliar2.row(j);
00471         }
00472 }
00473 
00474 
00475 
00476 
00477 
00478 void KukaIKAC::optimizesol(MatrixXd q, MatrixXd T0, VectorXd& qoutput,double& potact,VectorXd qref){
00479 // INPUT q=qaux in basicsol function.
00480 //       T0=desired goal
00481 // OUPUT qoutput=the best solution, according to a desired optimization function, obtained by rotating the basic solutions around Origin-Wrist axis.
00482 //       potact=the value of the potential function for the solution chosen.
00483         /* q is the initial guess*/
00484         VectorXd PJa,qelbows;
00485         MatrixXd PJ(3,q.rows()); //PJ is the elbow cartesian point. each column corresponds to one basic solution
00486 
00487         printf("Rotations for each solution: %d",IMAX_);
00488 
00489         for (int ia=0;ia<q.rows();ia++){
00490                 qelbows=q.row(ia);
00491                 KukaIKAC::initialelbows(qelbows,T0,PJa); // we compute the initial elbows values
00492                 PJ.col(ia)=PJa;
00493         }
00494         
00495         double L=d7;
00496         MatrixXd T04;
00497         Matrix3d Mrot,Rn,I3;
00498         double phi,qn4,qn3,qn2,qn1,eps1,eps3,potq;
00499         Vector2d qn5,qn6,qn7;
00500         double PI=3.14159265;
00501         Vector3d v,CJ;
00502         VectorXd qn4b,sol,qbest;
00503         MatrixXd Pw,Pw2,Paux,T01,T12,T23,T34,Qaux;
00504         MatrixXd Qglobal(4*q.rows(),7); 
00505         qoutput=q.row(0);
00506         VectorXd offshoulder(3,1);
00507         offshoulder << 0.0,0.0,d1;
00508         Pw=T0.block<3,1>(0,3)-L*T0.block<3,1>(0,2);
00509         Pw2=T0.block<3,1>(0,3)-L*T0.block<3,1>(0,2)-offshoulder;
00510         double aux0=Pw2.norm();
00511         v=Pw2/aux0;     
00512         /*Compute q4*/
00513         KukaIKAC::skewop(Mrot,v);
00514         I3.setIdentity();
00515         double signq4;
00516         // we perform rotations around the wrist-shoulder(intersection of joints 2 and 3 axis) line
00517         for (int i=0;i<IMAX_;i++){
00518                 phi=2*PI*double(i)/double(IMAX_)*pow(-1,double(i));
00519                 Rn=I3+sin(phi)*Mrot+(1-cos(phi))*Mrot*Mrot;
00520 
00521                 Qglobal.fill(-9.9);
00522                 for (int nconfig=0;nconfig<q.rows();nconfig++){
00523                         qn4=q(nconfig,3);
00524                         Paux=PJ.block<3,1>(0,nconfig);
00525                         Paux(2)=Paux(2)-d1;
00526                         CJ=Rn*Paux;
00527                         CJ(2)=CJ(2)+d1;
00528                         Qaux.resize(4,7);
00529                         Qaux.fill(-9.9);
00530 
00531                                 /*Calculacte q2*/
00532                                 qn2=atan2(CJ(2)-d1,sqrt(pow(CJ(0),2.0)+pow(CJ(1),2.0)))-PI/2;
00533                                 /*Calculate q1*/
00534                                 qn1=atan2(CJ(1),CJ(0));
00535                                 /*Calculate q3*/
00536                                 signq4=qn4/abs(qn4);
00537                                 qn3=pi2pi(0.5*PI*(-signq4+1.0)+atan2(-sin(qn1)*Pw(0,0)+cos(qn1)*Pw(1,0),sin(qn1)*cos(qn2)*Pw(1,0)+cos(qn1)*cos(qn2)*Pw(0,0)+sin(qn2)*(Pw(2,0)-d1)));
00538                                 KukaIKAC::DHmatrix(DHparam_(0,1),DHparam_(0,0),DHparam_(0,2),qn1,T01);
00539                                 KukaIKAC::DHmatrix(DHparam_(1,1),DHparam_(1,0),DHparam_(1,2),qn2,T12);
00540                                 KukaIKAC::DHmatrix(DHparam_(2,1),DHparam_(2,0),DHparam_(2,2),qn3,T23);
00541                                 KukaIKAC::DHmatrix(DHparam_(3,1),DHparam_(3,0),DHparam_(3,2),qn4,T34);
00542                                 T04=T01*T12*T23*T34;
00543                                 
00544                                 KukaIKAC::sphericalikine(T0,T04,qref,qn5,qn6,qn7);
00545                                 eps1 = copysign(1.0, qn1);
00546                                 eps3 = copysign(1.0, qn3);                      
00547                                 Qaux<<qn1,qn2,qn3,qn4,qn5(0),qn6(0),qn7(0), //we obtain up to 4 solutions for each rotated point, which we add to the Qglobal matrix
00548                                         qn1,qn2,qn3,qn4,qn5(1),qn6(1),qn7(1),
00549                                         qn1-eps1*PI,-qn2,qn3-eps3*PI,qn4,qn5(0),qn6(0),qn7(0),
00550                                         qn1-eps1*PI,-qn2,qn3-eps3*PI,qn4,qn5(1),qn6(1),qn7(1);
00551 
00552 
00553                         Qglobal.row(4*nconfig)=Qaux.row(0);
00554                         Qglobal.row(4*nconfig+1)=Qaux.row(1);
00555                         Qglobal.row(4*nconfig+2)=Qaux.row(2);
00556                         Qglobal.row(4*nconfig+3)=Qaux.row(3);
00557                 }
00558                 // when we have all the possible solutions obtained from the basic solutions, we filter those which are valid
00559                 KukaIKAC::filtersols(Qglobal,sol);
00560                 // and we choose the best one according to the potential defined
00561                 KukaIKAC::bestsol(Qglobal,sol,qref,qbest,potq);
00562 
00563                 // if the potential found is better than the best we had, we update the solution:
00564                 if (potq<potact){
00565                         qoutput=qbest;
00566                         potact=potq;
00567 //                      std::cout<<"\n i="<<i<<", potact="<<potq<<"\n qoutput="<<qbest.transpose();
00568                 }
00569         }
00570 }
00571 
00572 
00573 
00574 
00575 void KukaIKAC::skewop(Matrix3d& M,Vector3d v){ //skew-simetric matrix of a vector
00576 M.fill(0.0);
00577 M(0,1)=-v(2);
00578 M(1,0)=v(2);
00579 M(0,2)=v(1);
00580 M(2,0)=-v(1);
00581 M(1,2)=-v(0);
00582 M(2,1)=v(0);
00583 }
00584 
00585 void KukaIKAC::getq1(VectorXd cjoints,float i,double& q10){
00586 q10=cjoints(0)+i*step_*pow(-1,i);       
00587 }
00588 
00589 double KukaIKAC::pi2pi(double x){ //[-Pi,Pi] centering value of an angle
00590   double PI=3.14159265; 
00591  while (x>PI || x<-PI){
00592     if (x>PI){
00593       x=x-2*PI;
00594     }
00595     if (x<-PI){
00596       x=x+2*PI;
00597     } 
00598   }
00599 return x;
00600 }
00601 
00602 
00603 
00604 void KukaIKAC::bestsol(MatrixXd qsol,VectorXd sol,VectorXd qref,VectorXd& q,double& potbest){
00605   //returns the best solution of a matrix of solutions (each row being a solution), according to the potentialfunction.
00606         potbest=100000; /*high initial potential value*/
00607         double potq;
00608         VectorXd qact;
00609         for(int i=1;i<qsol.rows();i++){
00610                 if (sol(i)!=0.0){
00611                         qact=qsol.block<1,7>(i,0);
00612                         KukaIKAC::potentialfunction(qref,qact,potq);
00613                         if (potq<potbest){
00614                                 q=qact;
00615                                 potbest=potq;
00616                         }
00617                 }
00618         }
00619 }
00620 
00621 
00622 
00623 
00624 void KukaIKAC::potentialfunction(VectorXd qref,VectorXd& q, double& potq){
00625   
00626 // ------------------IT IS VERY RECOMMENDED TO MODIFY THIS FUNCTION ACCORDING TO THE NEEDS OF THE USER---------------------
00627 // if you need help at making this function, do not hesitate to ask us!
00628 // INPUT: qref: taken as the current joint state of the robot
00629 //        q: the joint state q to be evaluated  
00630 // OUTPUT:   potq: the potential of the joint position q
00631 
00632 
00633 
00634 
00635         MatrixXd W(7,7);
00636         W.fill(0.0);
00637         W(0,0)=2.5;
00638         W(1,1)=2.0;
00639         W(2,2)=2.0;
00640         W(3,3)=1.5;
00641         W(4,4)=1.0;
00642         W(5,5)=1.0;
00643         W(6,6)=1.0;
00644 
00645         VectorXd qdif(7);
00646         
00647         qdif=q-qref;
00648         potq=qdif.transpose()*W*qdif;
00649 
00650 }
00651 
00652 
00653 
00654 
00655 
00656 void KukaIKAC::sphericalikine(MatrixXd T0,MatrixXd T4, VectorXd cjoints, Vector2d& q5,Vector2d& q6,Vector2d& q7){
00657         // This function solves the inverse kinematics of a spherical wrist like the kuka lightweight arm.
00658   
00659   MatrixXd Taux;
00660         Taux=T4.inverse()*T0;
00661         
00662         double c6,s6,q57;
00663         c6=Taux(2,2);
00664         double  pi=3.14159265;
00665         if (abs(c6)<0.99999){
00666          q7(0)=atan2(-Taux(2,1),Taux(2,0));
00667          q5(0)=atan2(-Taux(1,2),-Taux(0,2));
00668          s6=Taux(0,3)/(-cos(q5(0))*d7);
00669          q6(0)=atan2(s6,c6);
00670          q5(1)=pi2pi(q5(0)+pi);
00671          q6(1)=-q6(0);  
00672          q7(1)=pi2pi(q7(0)+pi);
00673         }else if(abs(c6<1.0) && abs(c6)>0.99999){
00674          //WRIST SINGULARITY - we keep q5 constant and we move q7.
00675          q57=atan2(Taux(1,0),Taux(0,0));
00676          q5(0)=cjoints(4);
00677          q7(0)=q57-q5(0);       
00678          q6(0)=0.0;
00679          q5(1)=pi2pi(q5(0)+pi);
00680          q6(1)=0.0;     
00681          q7(1)=pi2pi(q7(0)+pi);
00682         }else{
00683          q5(0)=-99.9999;
00684          q5(1)=-99.9999;
00685          q6(0)=-99.9999;
00686          q6(1)=-99.9999;
00687          q7(0)=-99.9999;
00688          q7(1)=-99.9999;
00689          std::cout<<"\n no solution spherical---------------------\n";
00690         }
00691 
00692 }
00693 
00694 
00695 
00696 void KukaIKAC::initialelbows(VectorXd q,MatrixXd T0,VectorXd& PJ){
00697         MatrixXd T01,T12,T23,T02,T03;
00698         KukaIKAC::DHmatrix(DHparam_(0,1),DHparam_(0,0),DHparam_(0,2),q(0),T01);
00699         KukaIKAC::DHmatrix(DHparam_(1,1),DHparam_(1,0),DHparam_(1,2),q(1),T12);
00700         KukaIKAC::DHmatrix(DHparam_(2,1),DHparam_(2,0),DHparam_(2,2),q(2),T23);
00701         T02=T01*T12;
00702         T03=T02*T23;
00703         VectorXd aux(4),PLaux(4);
00704         aux(0)=0.0;
00705         aux(1)=0.0;
00706         aux(2)=d3;
00707         aux(3)=1.0;
00708         PLaux=T02*aux;
00709         PJ=PLaux.block<3,1>(0,0);
00710 
00711 }
00712 
00713 
00714 
00715 void KukaIKAC::soltrig(double a, double b, double c, MatrixXd& q2sol2){
00716 /*solves the equation a = b*sin(x)+c*cos(x), the output is a 2x2 matrix, with its first column containing the 2 solutions and the second column
00717 an indicator of valid solution or not*/
00718         if (abs(b)<0.00000001 && abs(a/c)<1.0){
00719                 q2sol2(0,1)=1.;
00720                 q2sol2(1,1)=1.;
00721                 q2sol2(0,0)=acos(a/c);
00722                 q2sol2(1,0)=-acos(a/c);
00723     
00724 
00725         }else if (pow(c,2.)*pow(b,2)-pow(b,2.)*pow(a,2.)+pow(b,4.)<=0.00000001){
00726           
00727                 q2sol2(0,1)=0.;
00728                 q2sol2(1,1)=0.;
00729                 q2sol2(0,0)=-99.9999;
00730                 q2sol2(1,0)=-99.9999;
00731 
00732                 
00733         }else{
00734         
00735                 q2sol2(0,1)=1.;
00736                 q2sol2(1,1)=1.;
00737                 q2sol2(0,0)=atan2(-(-a+c*(a*c+sqrt(pow(c,2.)*pow(b,2.)-pow(b,2.)*pow(a,2.)+pow(b,4.)))/(pow(c,2.)+pow(b,2.)))/b,(a*c+sqrt(pow(c,2.)*pow(b,2.)-pow(b,2.)*pow(a,2.)+pow(b,4.)))/(pow(c,2.)+pow(b,2.)));
00738                 q2sol2(1,0)=atan2(-(-a-c*(-a*c+sqrt(pow(c,2.)*pow(b,2.)-pow(b,2.)*pow(a,2.)+pow(b,4.)))/(pow(c,2.)+pow(b,2.)))/b,-(-a*c+sqrt(pow(c,2.)*pow(b,2.)-pow(b,2.)*pow(a,2.)+pow(b,4.)))/(pow(c,2.)+pow(b,2.)));
00739         }
00740 }
00741 
00742 
00743 int main(int argc, char** argv) {
00744     ros::init(argc, argv, "wam_ik");
00745     KukaIKAC kuka_ikac;
00746     ros::Rate loop_rate(10);
00747     while(ros::ok()){
00748       ros::spinOnce();
00749       loop_rate.sleep(); 
00750     }
00751 
00752 }


iri_wam_ik
Author(s): Adria Colomer
autogenerated on Fri Dec 6 2013 20:07:41