KatanaKinematics6M90G.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2006 by Tiziano Mueller   *
00003  *   tiziano.mueller@neuronics.ch   *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 
00021 #include "KNI_InvKin/KatanaKinematics6M90G.h"
00022 #include "common/MathHelperFunctions.h"
00023 #include <algorithm>
00024 
00025 //#include <iostream>
00026 using namespace std;
00027 
00028 namespace KNI {
00029 
00030 const double KatanaKinematics6M90G::_tolerance = 0.001;
00031 const int KatanaKinematics6M90G::_nrOfPossibleSolutions = 8;
00032 
00033 void
00034 KatanaKinematics6M90G::DK(coordinates& solution, encoders const& current_encoders) const {
00035         using namespace KNI_MHF;
00036         // numering the angles starting by 0-5
00037 
00038         double x0, x1, x2, x3;
00039         double y0, y1, y2, y3;
00040         double z0, z1, z2, z3;
00041         double R13, R23, R33, R31, R32;
00042 
00043         angles current_angles(6);
00044         for(int z = 0; z < 6; ++z) {
00045                 current_angles[z] = enc2rad(current_encoders[z], _parameters[z].angleOffset, _parameters[z].epc, _parameters[z].encOffset, _parameters[z].rotDir);
00046 //              cout << "Motor " << z << ": " << endl;
00047 //              cout << "epc: " << _parameters[z].epc << endl;
00048 //              cout << "encOffset: " << _parameters[z].encOffset << endl;
00049 //              cout << "angleOffset: " << _parameters[z].angleOffset << endl;
00050 //              cout << "angleStop: " << _parameters[z].angleStop << endl;
00051 //              cout << "rotDir: " << _parameters[z].rotDir << endl;
00052         }
00053 
00054         // needs refactoring:
00055         current_angles[1] = current_angles[1] - M_PI/2.0;
00056         current_angles[2] = current_angles[2] - M_PI;
00057         current_angles[3] = M_PI - current_angles[3];
00058 
00059         coordinates pose(6);
00060 
00061         angles cx(current_angles.size()), sx(current_angles.size());
00062         angles::iterator cx_iter, sx_iter;
00063 
00064         angles angle = current_angles;
00065 
00066         angle[2] = angle[1]+angle[2];
00067         angle[3] = angle[2]+angle[3];
00068 
00069         cx_iter = cx.begin();
00070         sx_iter = sx.begin();
00071         std::transform(angle.begin(), angle.end(), sx_iter, unary_precalc_sin<double>() );
00072         std::transform(angle.begin(), angle.end(), cx_iter, unary_precalc_cos<double>() );
00073 
00074         R13 = (-1*cx[0]*cx[3]*cx[4])-(sx[0]*sx[4]);
00075         R23 = (-1*sx[0]*cx[3]*cx[4])+(cx[0]*sx[4]);
00076         R33 = sx[3]*cx[4];
00077         R31 = cx[3];
00078         R32 =(-1)*sx[3]*sx[4];
00079 
00080         //x
00081         x0 =  cx[0]*sx[1];
00082         x1 =  cx[0]*sx[2];
00083         x2 =  cx[0]*sx[3];
00084         x3 = -cx[0]*cx[3]*cx[4]-sx[0]*sx[4];
00085         pose[0] = x0*_length[0]+x1*_length[1]+x2*_length[2]+x3*_length[3];
00086 
00087         //y
00088         y0 = sx[0]*sx[1];
00089         y1 = sx[0]*sx[2];
00090         y2 = sx[0]*sx[3];
00091         y3 = -sx[0]*cx[3]*cx[4]+cx[0]*sx[4];
00092         pose[1] = y0*_length[0]+y1*_length[1]+y2*_length[2]+y3*_length[3];
00093 
00094         //z
00095         z0 = cx[1];
00096         z1 = cx[2];
00097         z2 = cx[3];
00098         z3 = cx[4]*sx[3];
00099         pose[2] = z0*_length[0]+z1*_length[1]+z2*_length[2]+z3*_length[3];
00100 
00101         // phi, theta, psi
00102         pose[4] = acos(R33);
00103         if(pose[4]==0) {
00104                 pose[3] = atan2(pose[1],pose[0]);
00105                 pose[5] = 0;
00106         } else if(pose[4]==M_PI) {
00107                 pose[3] = atan2(pose[1],pose[0])+M_PI/2;
00108                 pose[5] = M_PI/2;
00109         } else {
00110                 pose[3] = atan2(R13,-R23);
00111                 pose[5] = atan2(R31,R32);
00112         }
00113 
00114 
00115         std::swap(solution, pose);
00116 }
00117 
00118 void
00119 KatanaKinematics6M90G::init( metrics const& length, parameter_container const& parameters ) {
00120         assert( (length.size() == 4) && "You have to provide the metrics for exactly 4 links" ); // we have 4 links
00121         assert( (parameters.size() == 6) && "You have to provide exactly 5 motor parameters" ); // 5 motors are used for IK calculations
00122         _setLength( length );
00123         _setParameters ( parameters );
00124 }
00125 
00126 
00127 void
00128 KatanaKinematics6M90G::IK_theta234theta5(angles_calc& angle, const position &p_gr) const {
00129         using namespace KNI_MHF;
00130 
00131         angle.theta234 = -acotan( (  (p_gr.x * p_gr.z * cos(angle.theta1) ) -
00132                                      sqrt( ( -pow2(p_gr.z) ) *
00133                                            ( -pow2(_length[3]) + pow2(p_gr.x) + pow2(p_gr.z) ) * pow2(sin(angle.theta1))
00134                                          )
00135                                   ) / pow2(p_gr.z)
00136                                 );
00137 
00138         angle.theta5   = acos( p_gr.z/(_length[3]*sin(angle.theta234)) );
00139 
00140         if(p_gr.z==0) {
00141                 angle.theta234=0;
00142                 angle.theta5=angle.theta1-atan1(-p_gr.x,-p_gr.y);
00143         }
00144 
00145         bool griptest;
00146         griptest = GripperTest(p_gr, angle);
00147         if(!griptest) {
00148                 angle.theta5=-angle.theta5;
00149                 griptest=GripperTest(p_gr, angle);
00150                 if(!griptest) {
00151                         angle.theta234 = -acotan( (   ( p_gr.x * p_gr.z * cos(angle.theta1) ) +
00152                                                       sqrt( ( -pow2(p_gr.z) ) *
00153                                                             ( -pow2(_length[3]) + pow2(p_gr.x) + pow2(p_gr.z) ) * pow2(sin(angle.theta1))
00154                                                           )
00155                                                   ) / pow2(p_gr.z)
00156                                                 );
00157                         angle.theta5 =  acos( p_gr.z / (_length[3]*sin(angle.theta234)) );
00158                         if(p_gr.z==0) {
00159                                 angle.theta234=-M_PI;
00160                                 angle.theta5=atan1(p_gr.x,p_gr.y) - angle.theta1;
00161                         }
00162 
00163                         griptest=GripperTest(p_gr, angle);
00164                         if(!griptest) {
00165                                 angle.theta5=-angle.theta5;
00166                         }
00167                 }
00168         }
00169 
00170 }
00171 
00172 bool
00173 KatanaKinematics6M90G::GripperTest(const position &p_gr, const angles_calc &angle) const {
00174         using namespace KNI_MHF;
00175         double xgr2, ygr2, zgr2;
00176 
00177         xgr2 = -_length[3]*(cos(angle.theta1)*cos(angle.theta234)*cos(angle.theta5)+sin(angle.theta1)*sin(angle.theta5));
00178         ygr2 = -_length[3]*(sin(angle.theta1)*cos(angle.theta234)*cos(angle.theta5)-cos(angle.theta1)*sin(angle.theta5));
00179         zgr2 =  _length[3]*sin(angle.theta234)*cos(angle.theta5);
00180 
00181         if((pow2(p_gr.x-xgr2)+pow2(p_gr.y-ygr2)+pow2(p_gr.z-zgr2))>=_tolerance)
00182                 return false;
00183 
00184         return true;
00185 }
00186 
00187 void
00188 KatanaKinematics6M90G::IK_b1b2costh3_6MS(angles_calc &angle, const position &p) const {
00189         using namespace KNI_MHF;
00190 
00191         double xg, yg, zg;
00192         double d5 = _length[2] + _length[3];
00193         xg = p.x + ( _length[3] * cos(angle.theta1) * sin(angle.theta234) );
00194         yg = p.y + ( _length[3] * sin(angle.theta1) * sin(angle.theta234) );
00195         zg = p.z + ( _length[3]                     * cos(angle.theta234) );
00196 
00197 
00198         angle.b1 = xg*cos(angle.theta1) + yg*sin(angle.theta1) - d5*sin(angle.theta234);
00199         angle.b2 = zg - d5*cos(angle.theta234);
00200         angle.costh3 = -( pow2(angle.b1) + pow2(angle.b2) - pow2(_length[0]) - pow2(_length[1]) ) / ( 2.0*_length[0]*_length[1] );
00201 
00202 }
00203 
00204 void
00205 KatanaKinematics6M90G::thetacomp(angles_calc &angle, const position &p_m) const {
00206         using namespace KNI_MHF;
00207 
00208         angle.theta2 = -M_PI/2.0 - ( atan0(angle.b1,angle.b2)+atan0(_length[0]+_length[1]*cos(angle.theta3),_length[1]*sin(angle.theta3)) );
00209         angle.theta4 = angle.theta234-angle.theta2-angle.theta3;
00210 
00211         if(!PositionTest6MS(angle,p_m)) {
00212                 angle.theta2 = angle.theta2+M_PI;
00213                 angle.theta4 = angle.theta234-angle.theta2-angle.theta3;
00214         }
00215 
00216 }
00217 
00218 bool
00219 KatanaKinematics6M90G::PositionTest6MS(const angles_calc &a, const position &p) const {
00220         using namespace KNI_MHF;
00221         double temp, xm2, ym2, zm2;
00222 
00223         temp = _length[0]*sin(a.theta2)+_length[1]*sin(a.theta2+a.theta3)+_length[2]*sin(a.theta234);
00224         xm2 = cos(a.theta1)*temp;
00225         ym2 = sin(a.theta1)*temp;
00226         zm2 = _length[0]*cos(a.theta2)+_length[1]*cos(a.theta2+a.theta3)+_length[2]*cos(a.theta234);
00227 
00228         if((pow2(p.x-xm2)+pow2(p.y-ym2)+pow2(p.z-zm2))>=_tolerance)
00229                 return false;
00230 
00231         return true;
00232 }
00233 
00234 bool
00235 KatanaKinematics6M90G::angledef(angles_calc &a) const {
00236         using namespace KNI_MHF;
00237 
00238         // constants here. needs refactoring:
00239         a.theta2=anglereduce(a.theta2+M_PI/2.0);
00240         a.theta3=anglereduce(a.theta3+M_PI);
00241         a.theta4=anglereduce(M_PI-a.theta4);
00242         a.theta5=anglereduce(a.theta5);
00243 
00244         if(a.theta1>_parameters[0].angleStop) {
00245                 a.theta1=a.theta1-2.0*M_PI;
00246         }
00247         if(a.theta2>M_PI) {
00248                 a.theta2=a.theta2-2.0*M_PI;
00249         }
00250         if(a.theta5<_parameters[4].angleOffset) {
00251                 a.theta5=a.theta5+2.0*M_PI;
00252         }
00253 
00254         return AnglePositionTest(a);
00255 
00256 }
00257 
00258 bool
00259 KatanaKinematics6M90G::AnglePositionTest(const angles_calc &a) const {
00260 
00261         if( (a.theta1+0.0087<_parameters[0].angleOffset)||(a.theta1>_parameters[0].angleStop) )
00262                 return false;
00263 
00264         if( (a.theta2-0.0087>_parameters[1].angleOffset)||(a.theta2<_parameters[1].angleStop) )
00265                 return false;
00266 
00267         if( (a.theta3<_parameters[2].angleOffset)||(a.theta3>_parameters[2].angleStop) )
00268                 return false;
00269 
00270         if( (a.theta4<_parameters[3].angleOffset)||(a.theta4>_parameters[3].angleStop) )
00271                 return false;
00272 
00273         if( (a.theta5<_parameters[4].angleOffset)||(a.theta5>_parameters[4].angleStop) )
00274                 return false;
00275 
00276         return true;
00277 }
00278 
00279 
00280 
00281 
00282 void
00283 KatanaKinematics6M90G::IK(encoders::iterator solution, coordinates const& pose, encoders const& current_encoders) const {
00284         using namespace KNI_MHF;
00285 
00286         // pose: Winkel Deg->Rad
00287         // Alle 8 Loeungen werden in einem Array angle, welches aus 8 Structs besteht, gespeichert:
00288         // 0-3 fr theta1_1
00289         // 4-7 fr theta1_2
00290 
00291         // Declaration
00292         position p_gr;
00293         position p_m;
00294         angles_container angle(_nrOfPossibleSolutions);
00295 
00296         // calculation of the gripper vector
00297         p_gr.x = _length[3]*sin(pose[4])*sin(pose[3]);
00298         p_gr.y = -_length[3]*sin(pose[4])*cos(pose[3]);
00299         p_gr.z = _length[3]*cos(pose[4]);
00300 
00301         p_m.x = pose[0]-p_gr.x;
00302         p_m.y = pose[1]-p_gr.y;
00303         p_m.z = pose[2]-p_gr.z;
00304 
00305         // calculate theta1_1 and theta1_2
00306         angle[0].theta1 = atan1(p_m.x,p_m.y);
00307         angle[4].theta1 = angle[0].theta1+M_PI;
00308 
00309 
00310         // check the borders according to the settings
00311         if(angle[0].theta1>_parameters[0].angleStop)
00312                 angle[0].theta1=angle[0].theta1-2.0*M_PI;
00313 
00314         if(angle[0].theta1<_parameters[0].angleOffset)
00315                 angle[0].theta1=angle[0].theta1+2.0*M_PI;
00316 
00317         if(angle[4].theta1>_parameters[0].angleStop)
00318                 angle[4].theta1=angle[4].theta1-2.0*M_PI;
00319 
00320         if(angle[4].theta1<_parameters[0].angleOffset)
00321                 angle[4].theta1=angle[4].theta1+2.0*M_PI;
00322 
00323 
00324         //====THETA1_1==================
00325         //-------THETA234_1-------------
00326         IK_theta234theta5(angle[0], p_gr);
00327         IK_b1b2costh3_6MS(angle[0], p_m);
00328 
00329         angle[1]=angle[0];
00330         angle[0].theta3 =  acos(angle[0].costh3)-M_PI;
00331         thetacomp(angle[0], p_m);
00332         angle[1].theta3 =  -acos(angle[1].costh3)+M_PI;
00333         thetacomp(angle[1], p_m);
00334 
00335         //-------THETA234_2-------------
00336         angle[2].theta1=angle[0].theta1;
00337         angle[2].theta234=angle[0].theta234-M_PI;
00338         angle[2].theta5=M_PI-angle[0].theta5;
00339 
00340         IK_b1b2costh3_6MS(angle[2], p_m);
00341         angle[3]=angle[2];
00342         angle[2].theta3 =  acos(angle[2].costh3)-M_PI;
00343         thetacomp(angle[2], p_m);
00344         angle[3].theta3 =  -acos(angle[3].costh3)+M_PI;
00345         thetacomp(angle[3], p_m);
00346 
00347 
00348         //====THETA1_2==================
00349         //-------THETA234_1-------------
00350         IK_theta234theta5(angle[4], p_gr);
00351         IK_b1b2costh3_6MS(angle[4], p_m);
00352 
00353         angle[5]=angle[4];
00354         angle[4].theta3 =  acos(angle[4].costh3)-M_PI;
00355         thetacomp(angle[4], p_m);
00356         angle[5].theta3 =  -acos(angle[5].costh3)+M_PI;
00357         thetacomp(angle[5], p_m);
00358 
00359         //-------THETA234_2-------------
00360         angle[6].theta1=angle[4].theta1;
00361         angle[6].theta234=angle[4].theta234-M_PI;
00362         angle[6].theta5=M_PI-angle[4].theta5;
00363         IK_b1b2costh3_6MS(angle[6], p_m);
00364         angle[7]=angle[6];
00365         angle[6].theta3 =  acos(angle[6].costh3)-M_PI;
00366         thetacomp(angle[6], p_m);
00367         angle[7].theta3 =  -acos(angle[7].costh3)+M_PI;
00368         thetacomp(angle[7], p_m);
00369 
00370         for( ::std::vector<angles_calc>::iterator iter = angle.begin(); iter != angle.end(); /* do iter forward in body */ ) {
00371                 if( pow2(iter->costh3) <= 1.0) {
00372                         if(!angledef(*iter))
00373                                 iter = angle.erase(iter);
00374                         else
00375                                 ++iter;
00376                         continue;
00377                 }
00378                 iter = angle.erase(iter);
00379         }
00380 
00381 
00382         if(angle.size() == 0) {
00383                 throw NoSolutionException();
00384         }
00385 
00386         ::std::vector< ::std::vector<int> > PossibleTargetsInEncoders;
00387         for( ::std::vector<angles_calc>::iterator i = angle.begin(); i != angle.end(); ++i ) {
00388                 ::std::vector<int> solution(5);
00389 
00390                 solution[0] = rad2enc(i->theta1, _parameters[0].angleOffset, _parameters[0].epc, _parameters[0].encOffset, _parameters[0].rotDir);
00391                 solution[1] = rad2enc(i->theta2, _parameters[1].angleOffset, _parameters[1].epc, _parameters[1].encOffset, _parameters[1].rotDir);
00392                 solution[2] = rad2enc(i->theta3, _parameters[2].angleOffset, _parameters[2].epc, _parameters[2].encOffset, _parameters[2].rotDir);
00393                 solution[3] = rad2enc(i->theta4, _parameters[3].angleOffset, _parameters[3].epc, _parameters[3].encOffset, _parameters[3].rotDir);
00394                 solution[4] = rad2enc(i->theta5, _parameters[4].angleOffset, _parameters[4].epc, _parameters[4].encOffset, _parameters[4].rotDir);
00395 
00396                 PossibleTargetsInEncoders.push_back(solution);
00397         }
00398 
00399 
00400         ::std::vector< ::std::vector<int> >::const_iterator sol = KinematicsDefaultEncMinAlgorithm()(PossibleTargetsInEncoders.begin(), PossibleTargetsInEncoders.end(), current_encoders.begin(), current_encoders.end());
00401 
00402         assert( sol != PossibleTargetsInEncoders.end() && "All solutions are out of range");
00403 
00404 
00405         encoders::iterator gripper_encoder_iter = std::copy( (*sol).begin(), (*sol).end(), solution );
00406         *gripper_encoder_iter = current_encoders[5]; // copy gripper-encoders from current
00407 
00408 }
00409 
00410 
00411 
00412 } // NAMESPACE: KNI
00413 


kni
Author(s): Neuronics AG (see AUTHORS.txt); ROS wrapper by Martin Günther
autogenerated on Mon Oct 6 2014 10:45:32