/* ----------------------------------------------------------------- */ /* 'ZDVClass.cc' */ /* Denavit- Hartenberg- Class */ /* */ /* last modified 07/04/2003 */ /* provides functions and data for the calculatings */ /* for cathesian coordinates according to the theory of */ /* Denavit and Hartenberg */ /* */ /* */ /* (C) Jochen Zimmermann */ /* ----------------------------------------------------------------- */ #include "ZHeaders.h" /* //Headerfile is included by ZHeaders.h #include "ZDVClass.h" /**/ //constructor //initialises members DenavitHartenberg::DenavitHartenberg():LinearAlgebra() { int i,j; for(i=0;i<10;i++) trigotable[i]=0; for(i=0;i<NUMBEROFSERVOS;i++) servoposition[i]=0; rows=columns=4; /* for(i=0;i<4;i++) for(j=0;j<4;j++) matrix[i][j]= 0;*/ } //non-standard constructor for initialisation-during-creation DenavitHartenberg::DenavitHartenberg(double *bufmatrix, const int * const servopos, bool docalc, bool left):LinearAlgebra() { int i,j; for(i=0;i<10;i++) trigotable[i]=0; rows=columns=4; /* for(i=0;i<4;i++) for(j=0;j<4;j++) matrix[i][j]= 0; */ for(i=0;i<NUMBEROFSERVOS;i++) servoposition[i]=servopos[i]; if(docalc) GetDVMatrix(bufmatrix,left); } //function to retrieve looked-up sine-value //(in comments is a recursive algorithm, slower but less memory consumption) //(the table is adjusted to servo-angles: 72�==128 (Servoangle)) double DenavitHartenberg::ServoSin(int servopos) { /* //recursive function for angles from 0-90(0-160) degrees //(approx. 102.5�s per call) //make all angles positive (not likely to happen in application) if(servopos< 0) return ServoSin(servopos+640); //2*PI- periodicity if(servopos>= 640) return ServoSin(servopos-640); //PI- symmetry if(servopos>= 320) return (ServoSin(servopos-320)*(-1.0)); //PI/2- symmetry if(servopos> 160) return ServoSin(320-servopos); //return from table return (double)sinlookup[servopos];*/ //non- recursive function for angles from 0-360(0-640) degrees //(approx. 24�s per call) servopos=servopos%640; if(servopos<0) servopos+=640; return (double)sinlookup[servopos]; } //function to retrieve looked-up cosine-value using sine-function // 90�==160(Servoangle) double DenavitHartenberg::ServoCos(int servopos) { return ServoSin(160+servopos); } //method 'assembles' thigh-matrix out of trigotable bool DenavitHartenberg::CalcMatrixThigh(bool left) { //calculates the DV- Matrix out of the given servopositions /* MATRIX left: MATRIX right: _ _ _ _ | | | | | ae -af b 60ae+35a | | ae -af b 60ae+35a | | | | | | be -bf -a 60be+35b+28 | | be -bf -a 60be+35b-28 | | | | | | f e 0 60f | | f e 0 60f | | | | | | 0 0 0 1 | | 0 0 0 1 | |_ _| |_ _| */ //first index=line, second index=column matrix[0][0]= trigotable[0] *trigotable[2]; matrix[0][1]=-trigotable[0] *trigotable[3]; matrix[0][2]= trigotable[1]; matrix[0][3]=60*matrix[0][0]+35*trigotable[0]; matrix[1][0]= trigotable[1] *trigotable[2]; matrix[1][1]=-trigotable[1] *trigotable[3]; matrix[1][2]=-trigotable[0]; matrix[1][3]=60*matrix[1][0]+35*trigotable[1]+28.0; matrix[2][0]=trigotable[3]; matrix[2][1]=trigotable[2]; matrix[2][2]=0.0; matrix[2][3]=60*trigotable[3]; matrix[3][0]=0.0; matrix[3][1]=0.0; matrix[3][2]=0.0; matrix[3][3]=1.0; if(!left) { matrix[1][3]-=56.0; } return(true); } //method 'assembles' inverted thigh-matrix out of trigotable bool DenavitHartenberg::CalcMatrixThighInv(bool left) { //calculates the DV- Matrix out of the given servopositions /* MATRIX left: MATRIX right: _ _ _ _ | | | | | ae be f -35e-60+28be | | ae be f -35e-60-28be | | | | | | -af -bf e 35f+28bf | | -af -bf e 35f-28bf | | | | | | b -a 0 +28a | | b -a 0 -28a | | | | | | 0 0 0 1 | | 0 0 0 1 | |_ _| |_ _| */ //first index=line, second index=column matrix[0][0]= trigotable[0] *trigotable[2]; matrix[0][1]=-trigotable[1] *trigotable[2]; matrix[0][2]= trigotable[3]; matrix[0][3]=-35*trigotable[2]-60-28*matrix[0][1]; matrix[1][0]=-trigotable[0] *trigotable[3]; matrix[1][1]=-trigotable[1] *trigotable[3]; matrix[1][2]= trigotable[2]; matrix[1][3]= 35*trigotable[3] -28*matrix[1][1]; matrix[2][0]= trigotable[1]; matrix[2][1]=-trigotable[0]; matrix[2][2]=0.0; matrix[2][3]=-28*matrix[2][1]; matrix[3][0]=0.0; matrix[3][1]=0.0; matrix[3][2]=0.0; matrix[3][3]=1.0; if(!left) { matrix[0][3]+=56*matrix[0][1]; matrix[1][3]+=56*matrix[1][1]; matrix[2][3]+=56*matrix[2][1]; } return(true); } //method 'assembles' foot-matrix out of trigotable bool DenavitHartenberg::CalcMatrixFoot(bool left) { //calculates the DV- Matrix out of the given servopositions /* MATRIX left: MATRIX right: _ _ _ _ | | | | | aiu+bh -ahu+bi av a(35(u+1)+65o+60e) | | aiu+bh -ahu+bi av a(35(u+1)+65o+60e) | | | | | | biu-ah -bhu-ai bv b(35(u+1)+65o+60e)+28 | | biu-ah -bhu-ai bv b(35(u+1)+65o+60e)-28 | | | | | | iv -hv -u 35v+65p+60f | | iv -hv -u 35v+65p+60f | | | | | | 0 0 0 1 | | 0 0 0 1 | |_ _| |_ _| */ //first index=line, second index=column matrix[0][0]= trigotable[0] *trigotable[4] *trigotable[8] +trigotable[1]*trigotable[5]; matrix[0][1]=-trigotable[0] *trigotable[5] *trigotable[8] +trigotable[1]*trigotable[4]; matrix[0][2]= trigotable[0] *trigotable[9]; matrix[0][3]= trigotable[0]*(35*(1+trigotable[8])+65*trigotable[6]+60*trigotable[2]); matrix[1][0]= trigotable[1] *trigotable[4] *trigotable[8] -trigotable[0]*trigotable[5]; matrix[1][1]=-trigotable[1] *trigotable[5] *trigotable[8] -trigotable[0]*trigotable[4]; matrix[1][2]= trigotable[1] *trigotable[9]; matrix[1][3]= trigotable[1]*(35*(1+trigotable[8])+65*trigotable[6]+60*trigotable[2])+28.0; matrix[2][0]= trigotable[4] *trigotable[9]; matrix[2][1]=-trigotable[5] *trigotable[9]; matrix[2][2]=-trigotable[8]; matrix[2][3]=35*trigotable[9]+65*trigotable[7]+60*trigotable[3]; matrix[3][0]=0.0; matrix[3][1]=0.0; matrix[3][2]=0.0; matrix[3][3]=1.0; if(!left) { matrix[1][3]-=56.0; } return(true); } //method 'assembles' inverted foot-matrix out of trigotable bool DenavitHartenberg::CalcMatrixFootInv(bool left) { //calculates the DV- Matrix out of the given servopositions /* MATRIX left: MATRIX right: _ _ _ _ | | | | | aiu+bh biu-ah +iv -i(35(u+1)+60o+65e) | | aiu+bh biu-ah +iv -i(35(u+1)+60o+65e) | | -28(biu-ah) | | +28(biu-ah) | | -ahu+bi -bhu-ai -hv -h(35(u+1)+65o+60e) | | -ahu+bi -bhu-ai -hv -h(35(u+1)+65o+60e) | | -28(-bhu-ai) | | +28(-bhu-ai) | | av bv -u 35v+65p+60f | | av bv -u 35v+65p+60f | | -28bv | | +28bv | | 0 0 0 1 | | 0 0 0 1 | |_ _| |_ _| */ //first index=line, second index=column matrix[0][0]= trigotable[0] *trigotable[4] *trigotable[8] +trigotable[1]*trigotable[5]; matrix[0][1]= trigotable[1] *trigotable[4] *trigotable[8] -trigotable[0]*trigotable[5]; matrix[0][2]= trigotable[4] *trigotable[9]; matrix[0][3]=-trigotable[4]*(35*(1+trigotable[8])+60*trigotable[6]+65*trigotable[2])-28*(matrix[0][1]); matrix[1][0]=-trigotable[0] *trigotable[5] *trigotable[8] +trigotable[1]*trigotable[4]; matrix[1][1]=-trigotable[1] *trigotable[5] *trigotable[8] -trigotable[0]*trigotable[4]; matrix[1][2]=-trigotable[5] *trigotable[9]; matrix[1][3]= trigotable[5]*(35*(1+trigotable[8])+60*trigotable[6]+65*trigotable[2])-28*(matrix[1][1]); matrix[2][0]= trigotable[0] *trigotable[9]; matrix[2][1]= trigotable[1] *trigotable[9]; matrix[2][2]=-trigotable[8]; matrix[2][3]=-35*trigotable[9]-60*trigotable[7]-65*trigotable[3]-28*(matrix[2][1]); matrix[3][0]=0.0; matrix[3][1]=0.0; matrix[3][2]=0.0; matrix[3][3]=1.0; if(!left) { matrix[0][3]+=56*(matrix[0][1]); matrix[1][3]+=56*(matrix[1][1]); matrix[2][3]+=56*(matrix[2][1]); } return(true); } //method 'assembles' shank-matrix out of trigotable bool DenavitHartenberg::CalcMatrixShank(bool left) { //calculates the DV- Matrix out of the given servopositions /* MATRIX left: MATRIX right: _ _ _ _ | | | | | ao -ap b a*(65o+60e+35) | | ao -ap b a*(65o+60e+35) | | | | | | bo -bp -a b*(65o+60e+35)+28 | | bo -bp -a b*(65o+60e+35)-28 | | | | | | p o 0 65p+60f | | p o 0 65p+60f | | | | | | 0 0 0 1 | | 0 0 0 1 | |_ _| |_ _| */ //first index=line, second index=column matrix[0][0]= trigotable[0]*trigotable[6]; matrix[0][1]=-trigotable[0]*trigotable[7]; matrix[0][2]= trigotable[1]; matrix[0][3]= trigotable[0]*(65*trigotable[6]+60*trigotable[2]+35); matrix[1][0]= trigotable[1]*trigotable[6]; matrix[1][1]=-trigotable[1]*trigotable[7]; matrix[1][2]=-trigotable[0]; matrix[1][3]= trigotable[1]*(65*trigotable[6]+60*trigotable[2]+35)+28; matrix[2][0]= trigotable[7]; matrix[2][1]= trigotable[6]; matrix[2][2]= 0.0; matrix[2][3]= 65*trigotable[7]+60*trigotable[3]; matrix[3][0]= 0.0; matrix[3][1]= 0.0; matrix[3][2]= 0.0; matrix[3][3]= 1.0; if(!left) { matrix[1][3]-=56.0; } return(true); } //method 'assembles' inverted shank-matrix out of trigotable bool DenavitHartenberg::CalcMatrixShankInv(bool left) { //calculates the DV- Matrix out of the given servopositions /* MATRIX left: MATRIX right: _ _ _ _ | | | | | ao bo p -35o-60e-65-28bo | | ao bo p -35o-60e-65+28bo | | | | | | -ap -bp o 35p+60f+65+28bp | | -ap -bp o 35p+60f+65-28bp | | | | | | b -a 0 +28a | | b -a 0 -28a | | | | | | 0 0 0 1 | | 0 0 0 1 | |_ _| |_ _| */ //first index=line, second index=column matrix[0][0]= trigotable[0]*trigotable[6]; matrix[0][1]= trigotable[1]*trigotable[6]; matrix[0][2]= trigotable[7]; matrix[0][3]=-35*trigotable[6]-60*trigotable[2]-65-28*matrix[0][1]; matrix[1][0]=-trigotable[0]*trigotable[7]; matrix[1][1]=-trigotable[1]*trigotable[7]; matrix[1][2]= trigotable[6]; matrix[1][3]= 35*trigotable[7]+60*trigotable[3]-28*matrix[1][1]; matrix[2][0]= trigotable[1]; matrix[2][1]=-trigotable[0]; matrix[2][2]= 0.0; matrix[2][3]= -28*matrix[2][1]; matrix[3][0]= 0.0; matrix[3][1]= 0.0; matrix[3][2]= 0.0; matrix[3][3]= 1.0; if(!left) { matrix[0][3]+=56*matrix[0][1]; matrix[1][3]+=56*matrix[1][1]; matrix[2][3]+=56*matrix[2][1]; } return(true); } //method calculates the trigotable for matrix-assembling //method is performance optimised bool DenavitHartenberg::CalcTrigoTable(int whichservo) { //-------control variabels-----------// int i,j; if(whichservo%2) j=1; //left leg else j=0; //right leg if(whichservo<-1) i=1; //inverted else i=0; //not inverted //--------------------always needed---------------------// trigotable[0]=ServoCos(servoposition[RHIPS+j]-128); //a trigotable[1]=ServoSin(servoposition[RHIPS+j]-128); //b //--------------casesensitive calculation---------------// switch(whichservo) { case -8: case 8: case -9: case 9: trigotable[2]=ServoCos(servoposition[RHIPB+j+4*i]-128);//e trigotable[3]=ServoSin(servoposition[RHIPB+j+4*i]-128);//f trigotable[4]=ServoCos(servoposition[RANKS+j]-128); //i trigotable[5]=ServoSin(servoposition[RANKS+j]-128); //h trigotable[6]=ServoCos(servoposition[RHIPB+j+2*i]+servoposition[RKNEE+j+2*i]-256); //o trigotable[7]=ServoSin(servoposition[RHIPB+j+2*i]+servoposition[RKNEE+j+2*i]-256); //p trigotable[8]=ServoCos(servoposition[RHIPB+j]+servoposition[RKNEE+j]+servoposition[RANKB+j]-384); //u trigotable[9]=ServoSin(servoposition[RHIPB+j]+servoposition[RKNEE+j]+servoposition[RANKB+j]-384); //v break; case -4: case 4: case -5: case 5: trigotable[2]=ServoCos(servoposition[RHIPB+j+2*i]-128);//e trigotable[3]=ServoSin(servoposition[RHIPB+j+2*i]-128);//f trigotable[6]=ServoCos(servoposition[RHIPB+j]+servoposition[RKNEE+j]-256); //o trigotable[7]=ServoSin(servoposition[RHIPB+j]+servoposition[RKNEE+j]-256); //p break; case -2: case 2: case -3: case 3: trigotable[2]=ServoCos(servoposition[RHIPB+j]-128);//e trigotable[3]=ServoSin(servoposition[RHIPB+j]-128);//f break; default: return false; //all other cases not implemented or needed } return true; }; //method to retrieve private member 'matrix' void DenavitHartenberg::GetDVMatrix(double *bufmatrix,int whichservo) { int i,j; Calc(whichservo); for(i=0;i<4;i++) for(j=0;j<4;j++) bufmatrix[i*4+j]=matrix[i][j]; return; } //method to branch calculation enquiry from higer level //which matrix to calculate is decided by servo-defines DenavitHartenberg& DenavitHartenberg::Calc(int whichservo) { //this function distributes the calculation //negative "whichservos" retrieve the inverted matrix //matrix inversion is not performed in code online but externally precalculated int i,j; bool left; rows=columns=4; //get new values Servo* servo=Servo::GetTheInstance(); servo->Get(servoposition); if(whichservo%2) left = true; else left = false; if(CalcTrigoTable(whichservo)) switch(whichservo) { case 2: //Thigh matrix case 3:CalcMatrixThigh(left); break; case 4: //Shank matrix case 5:CalcMatrixShank(left); break; case 8: //Foot matrix case 9:CalcMatrixFoot (left); break; case -2: //inverted Thigh matrix case -3:CalcMatrixThighInv(left); break; case -4: //inverted Shank matrix case -5:CalcMatrixShankInv(left); break; case -8: //inverted Foot matrix case -9:CalcMatrixFootInv (left); break; } else for(i=0;i<4;i++) for(j=0;j<4;j++) //Body matrix is identity matrix for all other cases when whichservo==odd and ZeroMatrix when whichservo==even if(i==j) matrix[i][j]=(whichservo%2); else matrix[i][j]=0; return *this; } //operator '=' had to be re-overloaded after inheriting as it is not passed over DenavitHartenberg& DenavitHartenberg::operator = (const LinearAlgebra& tocopy) { int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) matrix[i][j]=tocopy.matrix[i][j]; rows=tocopy.rows; columns=tocopy.columns; return *this; } //look-up table for servo-sine (consumes 2.5kB memory) const float DenavitHartenberg::sinlookup[640]={ 0.000000,0.009817,0.019634,0.029448,0.039260,0.049068,0.058871,0.068668, 0.078459,0.088242,0.098017,0.107782,0.117537,0.127281,0.137012,0.146730, 0.156434,0.166123,0.175796,0.185452,0.195090,0.204710,0.214309,0.223888, 0.233445,0.242980,0.252492,0.261979,0.271440,0.280876,0.290285,0.299665, 0.309017,0.318339,0.327630,0.336890,0.346117,0.355311,0.364470,0.373595, 0.382683,0.391735,0.400749,0.409724,0.418660,0.427555,0.436409,0.445221, 0.453990,0.462716,0.471397,0.480032,0.488621,0.497163,0.505657,0.514103, 0.522499,0.530844,0.539138,0.547381,0.555570,0.563706,0.571788,0.579815, 0.587785,0.595699,0.603556,0.611354,0.619094,0.626774,0.634393,0.641952, 0.649448,0.656882,0.664252,0.671559,0.678801,0.685977,0.693087,0.700131, 0.707107,0.714015,0.720854,0.727623,0.734323,0.740951,0.747508,0.753993, 0.760406,0.766745,0.773010,0.779201,0.785317,0.791357,0.797321,0.803208, 0.809017,0.814748,0.820401,0.825975,0.831470,0.836884,0.842217,0.847470, 0.852640,0.857729,0.862734,0.867657,0.872496,0.877251,0.881921,0.886507, 0.891007,0.895421,0.899748,0.903989,0.908143,0.912210,0.916188,0.920078, 0.923880,0.927592,0.931215,0.934748,0.938191,0.941544,0.944806,0.947977, 0.951057,0.954044,0.956940,0.959744,0.962455,0.965074,0.967599,0.970031, 0.972370,0.974615,0.976766,0.978823,0.980785,0.982653,0.984427,0.986105, 0.987688,0.989177,0.990569,0.991867,0.993068,0.994175,0.995185,0.996099, 0.996917,0.997640,0.998266,0.998795,0.999229,0.999566,0.999807,0.999952, 1.000000,0.999952,0.999807,0.999566,0.999229,0.998795,0.998266,0.997640, 0.996917,0.996099,0.995185,0.994175,0.993068,0.991867,0.990569,0.989177, 0.987688,0.986105,0.984427,0.982653,0.980785,0.978823,0.976766,0.974615, 0.972370,0.970031,0.967599,0.965074,0.962455,0.959744,0.956940,0.954044, 0.951057,0.947977,0.944806,0.941544,0.938191,0.934748,0.931215,0.927592, 0.923880,0.920078,0.916188,0.912210,0.908143,0.903989,0.899748,0.895421, 0.891007,0.886507,0.881921,0.877251,0.872496,0.867657,0.862734,0.857729, 0.852640,0.847470,0.842217,0.836884,0.831470,0.825975,0.820401,0.814748, 0.809017,0.803208,0.797321,0.791357,0.785317,0.779201,0.773010,0.766745, 0.760406,0.753993,0.747508,0.740951,0.734323,0.727623,0.720854,0.714015, 0.707107,0.700131,0.693087,0.685977,0.678801,0.671559,0.664252,0.656882, 0.649448,0.641952,0.634393,0.626774,0.619094,0.611354,0.603556,0.595699, 0.587785,0.579815,0.571788,0.563706,0.555570,0.547381,0.539138,0.530844, 0.522499,0.514103,0.505657,0.497163,0.488621,0.480032,0.471397,0.462716, 0.453990,0.445221,0.436409,0.427555,0.418660,0.409724,0.400749,0.391735, 0.382683,0.373595,0.364470,0.355311,0.346117,0.336890,0.327630,0.318339, 0.309017,0.299665,0.290285,0.280876,0.271440,0.261979,0.252492,0.242980, 0.233445,0.223888,0.214309,0.204710,0.195090,0.185452,0.175796,0.166123, 0.156434,0.146730,0.137012,0.127281,0.117537,0.107782,0.098017,0.088242, 0.078459,0.068668,0.058871,0.049068,0.039260,0.029448,0.019634,0.009817, 0.000000,-0.009817,-0.019634,-0.029448,-0.039260,-0.049068,-0.058871,-0.068668 , -0.078459,-0.088242,-0.098017,-0.107782,-0.117537,-0.127281,-0.137012,-0.146730, -0.156434,-0.166123,-0.175796,-0.185452,-0.195090,-0.204710,-0.214309,-0.223888, -0.233445,-0.242980,-0.252492,-0.261979,-0.271440,-0.280876,-0.290285,-0.299665, -0.309017,-0.318339,-0.327630,-0.336890,-0.346117,-0.355311,-0.364470,-0.373595, -0.382683,-0.391735,-0.400749,-0.409724,-0.418660,-0.427555,-0.436409,-0.445221, -0.453990,-0.462716,-0.471397,-0.480032,-0.488621,-0.497163,-0.505657,-0.514103, -0.522499,-0.530844,-0.539138,-0.547381,-0.555570,-0.563706,-0.571788,-0.579815, -0.587785,-0.595699,-0.603556,-0.611354,-0.619094,-0.626774,-0.634393,-0.641952, -0.649448,-0.656882,-0.664252,-0.671559,-0.678801,-0.685977,-0.693087,-0.700131, -0.707107,-0.714015,-0.720854,-0.727623,-0.734323,-0.740951,-0.747508,-0.753993, -0.760406,-0.766745,-0.773010,-0.779201,-0.785317,-0.791357,-0.797321,-0.803208, -0.809017,-0.814748,-0.820401,-0.825975,-0.831470,-0.836884,-0.842217,-0.847470, -0.852640,-0.857729,-0.862734,-0.867657,-0.872496,-0.877251,-0.881921,-0.886507, -0.891007,-0.895421,-0.899748,-0.903989,-0.908143,-0.912210,-0.916188,-0.920078, -0.923880,-0.927592,-0.931215,-0.934748,-0.938191,-0.941544,-0.944806,-0.947977, -0.951057,-0.954044,-0.956940,-0.959744,-0.962455,-0.965074,-0.967599,-0.970031, -0.972370,-0.974615,-0.976766,-0.978823,-0.980785,-0.982653,-0.984427,-0.986105, -0.987688,-0.989177,-0.990569,-0.991867,-0.993068,-0.994175,-0.995185,-0.996099, -0.996917,-0.997640,-0.998266,-0.998795,-0.999229,-0.999566,-0.999807,-0.999952, -1.000000,-0.999952,-0.999807,-0.999566,-0.999229,-0.998795,-0.998266,-0.997640, -0.996917,-0.996099,-0.995185,-0.994175,-0.993068,-0.991867,-0.990569,-0.989177, -0.987688,-0.986105,-0.984427,-0.982653,-0.980785,-0.978823,-0.976766,-0.974615, -0.972370,-0.970031,-0.967599,-0.965074,-0.962455,-0.959744,-0.956940,-0.954044, -0.951057,-0.947977,-0.944806,-0.941544,-0.938191,-0.934748,-0.931215,-0.927592, -0.923880,-0.920078,-0.916188,-0.912210,-0.908143,-0.903989,-0.899748,-0.895421, -0.891007,-0.886507,-0.881921,-0.877251,-0.872496,-0.867657,-0.862734,-0.857729, -0.852640,-0.847470,-0.842217,-0.836884,-0.831470,-0.825975,-0.820401,-0.814748, -0.809017,-0.803208,-0.797321,-0.791357,-0.785317,-0.779201,-0.773010,-0.766745, -0.760406,-0.753993,-0.747508,-0.740951,-0.734323,-0.727623,-0.720854,-0.714015, -0.707107,-0.700131,-0.693087,-0.685977,-0.678801,-0.671559,-0.664252,-0.656882, -0.649448,-0.641952,-0.634393,-0.626774,-0.619094,-0.611354,-0.603556,-0.595699, -0.587785,-0.579815,-0.571788,-0.563706,-0.555570,-0.547381,-0.539138,-0.530844, -0.522499,-0.514103,-0.505657,-0.497163,-0.488621,-0.480032,-0.471397,-0.462716, -0.453990,-0.445221,-0.436409,-0.427555,-0.418660,-0.409724,-0.400749,-0.391735, -0.382683,-0.373595,-0.364470,-0.355311,-0.346117,-0.336890,-0.327630,-0.318339, -0.309017,-0.299665,-0.290285,-0.280876,-0.271440,-0.261979,-0.252492,-0.242980, -0.233445,-0.223888,-0.214309,-0.204710,-0.195090,-0.185452,-0.175796,-0.166123, -0.156434,-0.146730,-0.137012,-0.127281,-0.117537,-0.107782,-0.098017,-0.088242, -0.078459,-0.068668,-0.058871,-0.049068,-0.039260,-0.029448,-0.019634,-0.009817};