Institut de Robòtica i Informàtica Industrial
KRD Group

The CuikSuite Project

link.c

Go to the documentation of this file.
00001 #include "link.h"
00002 #include "cpolyhedron.h"
00003 #include "varnames.h"
00004 
00005 #include <math.h>
00006 #include <string.h>
00007 
00016 void InitLink(char *name,Tlink *l)
00017 {
00018   unsigned int namel,i;
00019 
00020   namel=strlen(name);
00021   if (namel==0)
00022     l->name=NULL;
00023   else
00024     {
00025       NEW(l->name,namel+1,char);
00026       strcpy(l->name,name);
00027     }
00028 
00029   InitVector(sizeof(double *),CopyVoidPtr,DeleteVoidPtr,INIT_NUM_SHAPES,&(l->bodies));
00030 
00031   l->s=1;
00032   l->c=0;
00033   HTransformIdentity(&(l->R));
00034   
00035   for(i=0;i<3;i++)
00036     l->axisID[i]=NO_UINT;
00037 
00038   /*sum of the maximum coordinate value for all bodies in the link*/
00039   l->maxCoord=0.0;
00040 }
00041 
00042 void CopyLink(Tlink *l_dst,Tlink *l_src)
00043 {
00044   unsigned int i,n;
00045 
00046   if (l_src==NULL)
00047     l_dst->name=NULL;
00048   else
00049     {
00050       NEW(l_dst->name,strlen(l_src->name)+1,char);
00051       strcpy(l_dst->name,l_src->name);
00052     }
00053 
00054   InitVector(sizeof(double *),CopyVoidPtr,DeleteVoidPtr,INIT_NUM_SHAPES,&(l_dst->bodies));
00055 
00056   n=LinkNBodies(l_src);
00057   for(i=0;i<n;i++)
00058     AddBody2Link(GetLinkBody(i,l_src),l_dst);
00059   
00060   l_dst->c=l_src->c;
00061   l_dst->s=l_src->s;
00062   HTransformCopy(&(l_dst->R),&(l_src->R));
00063 
00064   for(i=0;i<3;i++)
00065     l_dst->axisID[i]=l_src->axisID[i];
00066 
00067   l_dst->maxCoord=l_src->maxCoord;
00068 }
00069 
00070 void AddBody2Link(Tcpolyhedron *b,Tlink *l)
00071 {
00072   Tcpolyhedron *bint;
00073 
00074   NEW(bint,1,Tcpolyhedron);
00075   CopyCPolyhedron(bint,b);
00076 
00077   NewVectorElement(&bint,&(l->bodies));
00078 
00079   l->maxCoord+=GetCPolyhedronMaxCoordinate(bint);
00080 }
00081 
00082 void ChangeLinkReferenceFrame(double **p1,double **p2,Tlink *l)
00083 {
00084   #if (ROT_REP!=2)
00085     /* This function has no effect when using quaternions.  */
00086     double v[3][3],n1,n2;
00087     unsigned int i,j;
00088     double s,c,d;
00089 
00090     /* Define the vectors from the points */
00091     n1=0;
00092     n2=0;
00093     for(i=0;i<3;i++)
00094       {
00095         v[0][i]=p1[1][i]-p1[0][i];
00096         v[1][i]=p2[1][i]-p2[0][i];
00097         n1+=v[0][i]*v[0][i];
00098         n2+=v[1][i]*v[1][i];
00099       }
00100     /* Normalize the vectors */
00101     n1=sqrt(n1);
00102     n2=sqrt(n2);
00103     for(i=0;i<3;i++)
00104       {
00105         v[0][i]/=n1;
00106         v[1][i]/=n2;
00107       }
00108 
00109     /*compute the cos/sin between the two vectors*/
00110     /*The dot product of the two vectors is the cosinus
00111       between the vectors*/
00112     c=0; 
00113     for(i=0;i<3;i++)
00114       c+=v[0][i]*v[1][i];
00115     
00116     if (fabs(c)<0.9) /*Ensure the two vectors are (by far) not aligned*/
00117       {
00118         /*The cross product of the two vectors is a vector
00119           orthogonal to the two vectors with norm the sinus
00120           of the angle between the vectors*/
00121         v[2][0]=v[0][1]*v[1][2]-v[0][2]*v[1][1];
00122         v[2][1]=v[0][2]*v[1][0]-v[0][0]*v[1][2];
00123         v[2][2]=v[0][0]*v[1][1]-v[0][1]*v[1][0];
00124         
00125         s=0;
00126         for(i=0;i<3;i++)
00127           s+=v[2][i]*v[2][i];
00128         s=sqrt(s);
00129         for(i=0;i<3;i++)
00130           v[2][i]/=s;
00131        
00132         l->c=c;
00133         l->s=s;
00134 
00135         /* Compute the inverse of the matrix with vector 'v' as colums
00136            (i.e., the inverse of the basis change) */
00137         d=(1/(s*s));
00138         for(j=0;j<3;j++)
00139           HTransformSetElement(0,j,d*(v[0][j]-c*v[1][j]),&(l->R));
00140         for(j=0;j<3;j++)
00141           HTransformSetElement(1,j,d*(v[1][j]-c*v[0][j]),&(l->R));
00142         for(j=0;j<3;j++)
00143           HTransformSetElement(2,j,v[2][j],&(l->R));
00144       }
00145   #endif
00146 }
00147 
00148 unsigned int LinkNBodies(Tlink *l)
00149 {
00150   return(VectorSize(&(l->bodies)));
00151 }
00152 
00153 Tcpolyhedron *GetLinkBody(unsigned int i,Tlink *l)
00154 {
00155   Tcpolyhedron **b;
00156 
00157   b=(Tcpolyhedron **)GetVectorElement(i,&(l->bodies));
00158   if (b==NULL)
00159     return(NULL);
00160   else
00161     return(*b);
00162 }
00163 
00164 char *GetLinkName(Tlink *l)
00165 {
00166   return(l->name);
00167 }
00168 
00169 #if (ROT_REP==0)
00170 void GenerateLinkRot(Tparameters *p,unsigned int lID,TCuikSystem *cs,Tlink *l)
00171 {
00172   if (!IsGroundLink(lID))
00173     {
00174       char *vname;
00175 
00176       /*If the cuiksytem already has the link variables (and thus the corresponding equations)
00177         there is nothing to be done. */
00178       
00179       NEW(vname,strlen(l->name)+100,char);
00180 
00181       LINK_ROT(vname,l->name,0,0);
00182 
00183       if (GetCSVariableID(vname,cs)==NO_UINT)
00184         {
00185           unsigned int i,j;
00186           Tinterval range;
00187           Tequation eqn;
00188           Tequation eq[3];
00189           unsigned int linkVars[9]; 
00190           Tvariable var;
00191 
00192           NewInterval(-1.0,1.0,&range);
00193           for(i=0;i<3;i++) /*vector*/
00194             {
00195               for(j=0;j<3;j++) /*component*/
00196                 {
00197                   LINK_ROT(vname,l->name,i,j);
00198                   NewVariable(SYSTEM_VAR,vname,&var);
00199                   SetVariableInterval(&range,&var);
00200                   linkVars[i*3+j]=AddVariable2CS(&var,cs);        
00201                   DeleteVariable(&var);
00202                 }
00203             }
00204 
00205           for(i=0;i<2+ROT_REDUNDANCY;i++)
00206             {
00207               GenerateNormEquation(linkVars[3*i+0],linkVars[3*i+1],linkVars[3*i+2],1.0,&eqn);
00208               AddEquation2CS(p,&eqn,cs);
00209               DeleteEquation(&eqn);
00210             } 
00211 
00212           /*ONLY ONE OF THE THREE FOLLOWING BLOCKS IS REQUIRED, THE OTHER TWO ARE REDUNDANT. */
00213           /*********************************************************************/
00214 
00215           GenerateDotProductEquation(linkVars[0],linkVars[1],linkVars[2], /* X */
00216                                      linkVars[3],linkVars[4],linkVars[5], /* Y */
00217                                      NO_UINT,l->c,&eqn);
00218           AddEquation2CS(p,&eqn,cs);
00219           DeleteEquation(&eqn);
00220 
00221 
00222           GenerateCrossProductEquations(linkVars[0],linkVars[1],linkVars[2], /* X */
00223                                         linkVars[3],linkVars[4],linkVars[5], /* Y */
00224                                         linkVars[6],linkVars[7],linkVars[8], /* Z */
00225                                         NO_UINT,l->s,eq);
00226           for(i=0;i<3;i++)
00227             {
00228               AddEquation2CS(p,&(eq[i]),cs);
00229               DeleteEquation(&(eq[i]));
00230             }
00231           /*********************************************************************/
00232 
00233           #if (ROT_REDUNDANCY==1)
00234           /*********************************************************************/
00235           
00236             GenerateDotProductEquation(linkVars[6],linkVars[7],linkVars[8], /* Z */
00237                                        linkVars[0],linkVars[1],linkVars[2], /* X */
00238                                        NO_UINT,0,&eqn);
00239             AddEquation2CS(p,&eqn,cs);
00240             DeleteEquation(&eqn);
00241             if (l->s==1) /*This second redundant equation is only used for orthogonal X-Y vectors */
00242               { 
00243                 GenerateCrossProductEquations(linkVars[6],linkVars[7],linkVars[8], /* Z */
00244                                               linkVars[0],linkVars[1],linkVars[2], /* X */
00245                                               linkVars[3],linkVars[4],linkVars[5], /* Y */
00246                                               NO_UINT,1.0,eq);
00247                 for(i=0;i<3;i++)
00248                   {
00249                     AddEquation2CS(p,&(eq[i]),cs);
00250                     DeleteEquation(&(eq[i]));
00251                   }
00252               }
00253           /*********************************************************************/
00254           #endif
00255 
00256           #if (ROT_REDUNDANCY==1) /*Redundancy is only used for orthogonal X-Y vectors */
00257           /*********************************************************************/
00258             GenerateDotProductEquation(linkVars[3],linkVars[4],linkVars[5], /* Y */
00259                                        linkVars[6],linkVars[7],linkVars[8], /* Z */
00260                                        NO_UINT,0,&eqn);
00261             AddEquation2CS(p,&eqn,cs);
00262             DeleteEquation(&eqn);
00263             
00264             
00265             if (l->s==1) /*This second redundant equation is only used for orthogonal X-Y vectors */
00266               { 
00267               GenerateCrossProductEquations(linkVars[3],linkVars[4],linkVars[5], /* Y */
00268                                             linkVars[6],linkVars[7],linkVars[8], /* Z */
00269                                             linkVars[0],linkVars[1],linkVars[2], /* X */
00270                                             NO_UINT,1.0,eq);
00271               for(i=0;i<3;i++)
00272                 {
00273                   AddEquation2CS(p,&(eq[i]),cs);
00274                   DeleteEquation(&(eq[i]));
00275                 }
00276             }
00277           /*********************************************************************/
00278           #endif
00279         }
00280 
00281       free(vname);
00282     }
00283 }
00284 
00285 void ApplyLinkRot(double sf,unsigned int sv,double *p,Tequation *eq,
00286                   TCuikSystem *cs,boolean groundLink,Tlink *l)
00287 {
00288   /*
00289   sf*sv*R(px py px) where R is defined from the linkVars (check that hasVars==TRUE) 
00290   */
00291   
00292   Tmonomial f;
00293   unsigned int i;
00294 
00295   InitMonomial(&f);
00296   if (groundLink)
00297     {
00298       for(i=0;i<3;i++)
00299         { 
00300           if (sv!=NO_UINT)
00301             AddVariable2Monomial(sv,1,&f);
00302           AddCt2Monomial(sf*p[i],&f);
00303           
00304           AddMonomial(&f,&(eq[i]));
00305           ResetMonomial(&f);
00306         }
00307     }
00308   else
00309     {
00310       unsigned int j;
00311       unsigned int linkVars[9]; 
00312       char *vname;
00313       double pInt[3];
00314 
00315       HTransformApply(p,pInt,&(l->R));
00316 
00317       NEW(vname,strlen(l->name)+100,char);
00318 
00319       for(i=0;i<3;i++)
00320         {
00321           for(j=0;j<3;j++)
00322             {
00323               LINK_ROT(vname,l->name,i,j);
00324               linkVars[i*3+j]=GetCSVariableID(vname,cs);
00325               if (linkVars[i*3+j]==NO_UINT)
00326                 Error("Undefined reference variable in ApplyLinkRotVar");
00327             }
00328         }
00329   
00330       for(i=0;i<3;i++)
00331         {
00332           for(j=0;j<3;j++)
00333             {
00334               if (fabs(pInt[j])>ZERO)
00335                 {
00336                   AddVariable2Monomial(linkVars[j*3+i],1,&f);
00337                   if (sv!=NO_UINT)
00338                     AddVariable2Monomial(sv,1,&f);
00339                   AddCt2Monomial(sf*pInt[j],&f);
00340                   
00341                   AddMonomial(&f,&(eq[i]));
00342                   ResetMonomial(&f);
00343                 }
00344             }
00345         }
00346       free(vname);
00347     }
00348   DeleteMonomial(&f);
00349 }
00350 
00351 void RegenerateLinkSolution(TCuikSystem *cs,double *sol,boolean groundLink,Tlink *l)
00352 {
00353   /* When using 9 variables all variables used to represent the
00354      rotation of the link are system variables and, thus, no
00355      dummy has to be computed.*/
00356 }
00357 
00358 void GetTransform2Link(TCuikSystem *cs,double *sol,boolean groundLink,
00359                        double *r,THTransform *t,Tlink *l)
00360 {
00361   if (groundLink)
00362     HTransformIdentity(t);
00363   else
00364     {
00365       unsigned int i,j,n;
00366       unsigned int linkVars[9]; 
00367       char *vname;
00368 
00369       NEW(vname,strlen(l->name)+100,char);
00370   
00371       for(i=0;i<3;i++)
00372         {
00373           for(j=0;j<3;j++)
00374             {
00375               LINK_ROT(vname,l->name,i,j);
00376               n=(j*3)+i;
00377               linkVars[n]=GetCSVariableID(vname,cs);
00378               if (linkVars[n]==NO_UINT)
00379                 Error("Undefined reference variable in ApplyLinkRotVar");
00380             }
00381         }
00382 
00383       /* Define the homogeneous transform using the rotation and the translation.*/
00384       HTransformIdentity(t);
00385       n=0;
00386       for(i=0;i<3;i++)
00387         {
00388           HTransformSetElement(i,AXIS_H,r[i],t);
00389           for(j=0;j<3;j++)
00390             HTransformSetElement(i,j,sol[linkVars[n++]],t);
00391         }
00392 
00393       /* Note that in the general case the reference frame for a link
00394          used to generate the equations (and, thus, the solutions)
00395          is not orthonormal, i.e., it is not a homogeneous transform.
00396 
00397          The use of matrix l->R makes it orthonormal since it recorves the
00398          reference frame used to define the bodies in global coordiantes.
00399 
00400          See ChangeLinkReferenceFrame
00401       */
00402       HTransformProduct(t,&(l->R),t);
00403       /* This ensures that the transformation is actually rigid 
00404          (fixes numerical errors and the error of taking the center
00405          of the solution box as a proper solution) */
00406       HTransformOrthonormalize(t,t);
00407 
00408       free(vname);
00409     }
00410 }
00411 
00412 #endif
00413 
00414 
00415 #if (ROT_REP==1)
00416 void GenerateLinkRot(Tparameters *p,unsigned int lID,TCuikSystem *cs,Tlink *l)
00417 {
00418   if (!IsGroundLink(lID))
00419     {
00420       char *vname;
00421 
00422       /*If the cuiksytem already has the link variables (and thus the corresponding equations)
00423         there is nothing to be done. */
00424 
00425       NEW(vname,strlen(l->name)+100,char);
00426   
00427       LINK_ROT2(vname,l->name,0,0);
00428 
00429       if (GetCSVariableID(vname,cs)==NO_UINT)
00430         {
00431           unsigned int i,j;
00432           Tinterval range;
00433           Tequation eqn;
00434           unsigned int linkVars[12]; 
00435           Tvariable var;
00436 
00437           NewInterval(-1.0,1.0,&range);
00438           /* vectors u,v,w,wp */
00439           for(i=0;i<4;i++) /*vector*/
00440             {
00441               for(j=0;j<3;j++) /*component*/
00442                 {
00443                   LINK_ROT2(vname,l->name,i,j);
00444                   NewVariable((i<2?SYSTEM_VAR:DUMMY_VAR),vname,&var);
00445                   SetVariableInterval(&range,&var);
00446                   linkVars[i*3+j]=AddVariable2CS(&var,cs);        
00447                   DeleteVariable(&var);
00448                 }
00449             }
00450 
00451           GenerateScaledSaddleEquation(l->s,linkVars[1],linkVars[5],linkVars[6],&eqn); 
00452           AddEquation2CS(p,&eqn,cs);
00453           DeleteEquation(&eqn);
00454 
00455           GenerateScaledSaddleEquation(l->s,linkVars[2],linkVars[3],linkVars[7],&eqn); 
00456           AddEquation2CS(p,&eqn,cs);
00457           DeleteEquation(&eqn);
00458 
00459           GenerateScaledSaddleEquation(l->s,linkVars[0],linkVars[4],linkVars[8],&eqn); 
00460           AddEquation2CS(p,&eqn,cs);
00461           DeleteEquation(&eqn);
00462 
00463           GenerateScaledSaddleEquation(l->s,linkVars[2],linkVars[4],linkVars[9],&eqn); 
00464           AddEquation2CS(p,&eqn,cs);
00465           DeleteEquation(&eqn);
00466 
00467           GenerateScaledSaddleEquation(l->s,linkVars[0],linkVars[5],linkVars[10],&eqn); 
00468           AddEquation2CS(p,&eqn,cs);
00469           DeleteEquation(&eqn);
00470 
00471           GenerateScaledSaddleEquation(l->s,linkVars[1],linkVars[3],linkVars[11],&eqn); 
00472           AddEquation2CS(p,&eqn,cs);
00473           DeleteEquation(&eqn);
00474 
00475           for(i=0;i<2;i++)
00476             {
00477               GenerateNormEquation(linkVars[3*i+0],linkVars[3*i+1],linkVars[3*i+2],1.0,&eqn);
00478               AddEquation2CS(p,&eqn,cs);
00479               DeleteEquation(&eqn);
00480             }
00481           
00482           GenerateDotProductEquation(linkVars[0],linkVars[1],linkVars[2], /* X */
00483                                      linkVars[3],linkVars[4],linkVars[5], /* Y */
00484                                      NO_UINT,l->c,&eqn);
00485           AddEquation2CS(p,&eqn,cs);
00486           DeleteEquation(&eqn);
00487         }
00488 
00489       free(vname);
00490     }
00491 }
00492 
00493 void ApplyLinkRot(double sf,unsigned int sv,double *p,Tequation *eq,
00494                   TCuikSystem *cs,boolean groundLink,Tlink *l)
00495 {
00496   /*
00497   sf*sv*R(px py px) where R is defined from the linkVars (check that hasVars==TRUE) 
00498   */
00499   
00500   Tmonomial f;
00501 
00502   InitMonomial(&f);
00503   if (groundLink)
00504     {
00505       unsigned int i;
00506 
00507       for(i=0;i<3;i++)
00508         {
00509           if (sv!=NO_UINT)
00510             AddVariable2Monomial(sv,1,&f);
00511           AddCt2Monomial(sf*p[i],&f);
00512           
00513           AddMonomial(&f,&(eq[i]));
00514           ResetMonomial(&f);
00515         }
00516     }
00517   else
00518     {
00519       unsigned int i,j,n;
00520       unsigned int linkVars[12]; 
00521       char *vname;
00522       double pInt[3];
00523 
00524       HTransformApply(p,pInt,&(l->R));
00525 
00526       NEW(vname,strlen(l->name)+100,char);
00527       
00528       for(i=0;i<4;i++) /*vector*/
00529         {
00530           for(j=0;j<3;j++) /*component*/
00531             {
00532               LINK_ROT2(vname,l->name,i,j);
00533               n=i*3+j;
00534               linkVars[n]=GetCSVariableID(vname,cs);
00535               if (linkVars[n]==NO_UINT)
00536                 Error("Undefined reference variable in ApplyLinkRotVar");
00537             }
00538         }
00539 
00540       for(i=0;i<3;i++) /*row*/
00541         {
00542           for(j=0;j<4;j++) /*column*/
00543             {
00544               if (fabs(pInt[(j<2?j:2)])>ZERO)
00545                 {
00546                   AddVariable2Monomial(linkVars[j*3+i],1,&f);
00547                   if (sv!=NO_UINT)
00548                     AddVariable2Monomial(sv,1,&f);
00549                   AddCt2Monomial((j==3?-1:1)*sf*pInt[(j<2?j:2)],&f);
00550                   
00551                   AddMonomial(&f,&(eq[i]));
00552                   ResetMonomial(&f);
00553                 }
00554             }
00555         }
00556 
00557       free(vname);
00558     }
00559   DeleteMonomial(&f);  
00560 }
00561 
00562 void RegenerateLinkSolution(TCuikSystem *cs,double *sol,boolean groundLink,Tlink *l)
00563 {
00564   if (!groundLink)
00565     {
00566       unsigned int i,j,n,vID[6];
00567       char *vname;
00568       double v[2][3];
00569 
00570       NEW(vname,strlen(l->name)+100,char);
00571   
00572       for(i=0;i<2;i++) /*vector (u,v)*/
00573         {
00574           for(j=0;j<3;j++) /*component (x,y,z)*/
00575             {
00576               LINK_ROT2(vname,l->name,i,j);
00577               n=GetCSVariableID(vname,cs);
00578               if (n==NO_UINT)
00579                 Error("Undefined reference variable in RegenerateLinkSolution");
00580 
00581               v[i][j]=sol[n];      
00582             }
00583         }      
00584 
00585       n=0;
00586       for(i=2;i<4;i++) /*vector (w,wp)*/
00587         {
00588           for(j=0;j<3;j++) /*component (x,y,z)*/
00589             {
00590               LINK_ROT2(vname,l->name,i,j);
00591               vID[n]=GetCSVariableID(vname,cs);
00592               if (vID[n]==NO_UINT)
00593                 Error("Undefined reference variable in RegenerateLinkSolution");
00594               n++;
00595             }
00596         }      
00597 
00598       /* compute w and wp from u and v (recall that u X v = w - wp)*/
00599       sol[vID[0]]=l->s*v[0][1]*v[1][2];
00600       sol[vID[1]]=l->s*v[0][2]*v[1][0];
00601       sol[vID[2]]=l->s*v[0][0]*v[1][1];
00602 
00603       sol[vID[3]]=l->s*v[0][2]*v[1][1];
00604       sol[vID[4]]=l->s*v[0][0]*v[1][2];
00605       sol[vID[5]]=l->s*v[0][1]*v[1][0];
00606       
00607       free(vname);
00608     }
00609 }
00610 
00611 void GetTransform2Link(TCuikSystem *cs,double *sol,boolean groundLink,
00612                        double *r,THTransform *t,Tlink *l)
00613 {
00614   if (groundLink)
00615     HTransformIdentity(t);
00616   else
00617     {
00618       unsigned int i,j,vID,vID2;
00619       char *vname;
00620 
00621       /*In general this function has been used before reaching this point but
00622         just in case....*/
00623       RegenerateLinkSolution(cs,sol,FALSE,l);
00624 
00625       NEW(vname,strlen(l->name)+100,char);
00626 
00627       HTransformIdentity(t);
00628       for(i=0;i<3;i++) /*vector (u,v,w) = column*/
00629         {
00630           HTransformSetElement(i,AXIS_H,r[i],t);
00631 
00632           for(j=0;j<3;j++) /*component = row*/
00633             {
00634               LINK_ROT2(vname,l->name,i,j);
00635               vID=GetCSVariableID(vname,cs);
00636               if (vID==NO_UINT)
00637                 Error("Undefined reference variable in ApplyLinkRotVar");
00638 
00639               if (i<2) /*The values of u,v can be directly set into the transform*/
00640                 HTransformSetElement(j,i,sol[vID],t);
00641               else
00642                 {
00643                   /* when considering w, we have to also use vector wp since
00644                      the third column of the rotation matrix is  w-wp*/
00645                   LINK_ROT2(vname,l->name,3,j); /*4th vector is wp*/
00646                   vID2=GetCSVariableID(vname,cs);
00647                   if (vID2==NO_UINT)
00648                     Error("Undefined reference variable in ApplyLinkRotVar");
00649 
00650                   HTransformSetElement(j,i,sol[vID]-sol[vID2],t);
00651                 }
00652             }
00653         }
00654 
00655       free(vname);
00656 
00657       /* Note that in the general case the reference frame for a link
00658          used to generate the equations (and, thus, the solutions)
00659          is not orthonormal, i.e., it is not a homogeneous transform.
00660 
00661          The use of matrix l->R makes it orthonormal since it recorves the
00662          reference frame used to define the bodies in global coordiantes.
00663 
00664          See ChangeLinkReferenceFrame
00665       */
00666       HTransformProduct(t,&(l->R),t);  
00667       /* This ensures that the transformation is actually rigid
00668          (fixes numerical errors and the error of taking the center
00669          of the solution box as a proper solution) */   
00670       HTransformOrthonormalize(t,t);
00671     }
00672 }
00673 #endif
00674 
00675 #if (ROT_REP==2)
00676 void GenerateLinkRot(Tparameters *p,unsigned int lID,TCuikSystem *cs,Tlink *l)
00677 {
00678   if (!IsGroundLink(lID))
00679     {
00680       char *vname;
00681 
00682       /*If the cuiksytem already has the link variables (and thus the corresponding equations)
00683         there is nothing to be done. */
00684 
00685       NEW(vname,strlen(l->name)+100,char);
00686       
00687       LINK_ROT3_E(vname,l->name,0,0);
00688 
00689       if (GetCSVariableID(vname,cs)==NO_UINT)
00690         {
00691           unsigned int i,j,n;
00692           Tinterval range,range2;
00693           Tequation eqn;
00694           unsigned int linkVars[10]; 
00695           unsigned int qVars[4];
00696           Tvariable var;
00697           Tmonomial f;
00698 
00699           NewInterval(-1.0,1.0,&range);
00700           NewInterval(0.0,1.0,&range2);
00701 
00702           n=0;
00703           for(i=0;i<4;i++)
00704             { 
00705               for(j=i;j<4;j++)
00706                 {
00707                   LINK_ROT3_E(vname,l->name,i,j);
00708                   NewVariable(DUMMY_VAR,vname,&var);
00709                   if (i==j)
00710                     SetVariableInterval(&range2,&var);
00711                   else
00712                     SetVariableInterval(&range,&var);
00713                   linkVars[n]=AddVariable2CS(&var,cs);
00714                   n++;
00715                   DeleteVariable(&var);
00716                 }
00717             }
00718           
00719           for(j=0;j<4;j++)
00720             {
00721               LINK_ROT3_Q(vname,l->name,j);
00722               NewVariable(SYSTEM_VAR,vname,&var);
00723               if (j==0)
00724                 SetVariableInterval(&range2,&var);
00725               else
00726                 SetVariableInterval(&range,&var);
00727               qVars[j]=AddVariable2CS(&var,cs);   
00728               DeleteVariable(&var);
00729             }
00730 
00731           /* Add the relation between the E variables (dummies) and the
00732             Q variables (system) */
00733           n=0;
00734           for(i=0;i<4;i++)
00735             { 
00736               for(j=i;j<4;j++)
00737                 {
00738                   /* When i=j (-> qVars[i]==qVars[j]) a parabola equation is generated! */
00739                   GenerateSaddleEquation(qVars[i],qVars[j],linkVars[n],&eqn);
00740                   AddEquation2CS(p,&eqn,cs);
00741                   DeleteEquation(&eqn);
00742                   n++;
00743                 }
00744             }
00745 
00746           /* norm of the Q (system) variables is 1 (we use the already introduced
00747              dummy e_i variables) */
00748           InitEquation(&eqn);
00749           InitMonomial(&f);
00750           
00751           AddVariable2Monomial(linkVars[0],1,&f);
00752           AddMonomial(&f,&eqn);ResetMonomial(&f);
00753           AddVariable2Monomial(linkVars[4],1,&f);
00754           AddMonomial(&f,&eqn);ResetMonomial(&f);
00755           AddVariable2Monomial(linkVars[7],1,&f);
00756           AddMonomial(&f,&eqn);ResetMonomial(&f);
00757           AddVariable2Monomial(linkVars[9],1,&f);
00758           AddMonomial(&f,&eqn);
00759 
00760           DeleteMonomial(&f);
00761 
00762           SetEquationCmp(EQU,&eqn);
00763           SetEquationValue(1,&eqn);
00764           SetEquationType(SYSTEM_EQ,&eqn);
00765 
00766           AddEquation2CS(p,&eqn,cs);
00767           DeleteEquation(&eqn);
00768                 
00769         }
00770       free(vname);
00771     }
00772 }
00773 
00774 void ApplyLinkRot(double sf,unsigned int sv,double *p,Tequation *eq,
00775                   TCuikSystem *cs,boolean groundLink,Tlink *l)
00776 {
00777   /*
00778   sf*sv*R(px py px) where R is defined from the linkVars (check that hasVars==TRUE) 
00779   */
00780   
00781   Tmonomial f;
00782   unsigned int i;
00783 
00784   /*Note that quaternions asume an orthonormal rotation matrix (i.e., we do not allow
00785     the change of the link reference)*/
00786 
00787   InitMonomial(&f);
00788   if (groundLink)
00789     {
00790       unsigned int j;
00791       
00792       double id[3][3]={{1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0}};
00793       /*
00794       double id[3][3]={{0.82559761618954,-0.52917109941051,-0.19587374426100}, 
00795                        {0.20084362075732, 0.59999081140825,-0.77438547650815}, 
00796                        {0.52730486072408, 0.59999081140825, 0.60163162324002}}; 
00797       */
00798       double ct;
00799 
00800       for(i=0;i<3;i++)
00801         { 
00802           ct=0.0;
00803           for(j=0;j<3;j++)
00804             ct+=id[i][j]*p[j];
00805 
00806           if (sv!=NO_UINT)
00807             AddVariable2Monomial(sv,1,&f);
00808           AddCt2Monomial(sf*ct,&f);
00809           
00810           AddMonomial(&f,&(eq[i]));
00811           ResetMonomial(&f);
00812         }
00813     }
00814   else
00815     {
00816       unsigned int i,j,n;
00817       unsigned int linkVars[10]; 
00818       char *vname;
00819       unsigned int map[2][3][3]={
00820         {{4,1,2},
00821          {1,0,5},
00822          {2,5,0}},
00823         {{7,8,6},
00824          {8,7,3},
00825          {6,3,4}}};
00826       double sg[2][3][3]={
00827         {{-1.0,+1.0,+1.0},
00828          {+1.0,-1.0,+1.0},
00829          {+1.0,+1.0,-1.0}},
00830         {{-1.0,-1.0,+1.0},
00831          {+1.0,-1.0,-1.0},
00832          {-1.0,+1.0,-1.0}}};
00833 
00834       NEW(vname,strlen(l->name)+100,char);
00835 
00836       n=0;
00837       for(i=0;i<4;i++)
00838         { 
00839           for(j=i;j<4;j++)
00840             {
00841               LINK_ROT3_E(vname,l->name,i,j);
00842               linkVars[n]=GetCSVariableID(vname,cs);
00843               if (linkVars[n]==NO_UINT)
00844                 Error("Undefined reference variable in ApplyLinkRot");
00845               n++;
00846             }
00847         }
00848 
00849       /* Diagonal elements */
00850       for(i=0;i<3;i++)
00851         {
00852            if (sv!=NO_UINT)
00853              AddVariable2Monomial(sv,1,&f);
00854            AddCt2Monomial(sf*p[i],&f);
00855 
00856           AddMonomial(&f,&(eq[i]));
00857           ResetMonomial(&f);
00858         }
00859 
00860       for(n=0;n<2;n++)
00861         {
00862           for(i=0;i<3;i++) /*row*/
00863             {
00864               for(j=0;j<3;j++) /*column*/
00865                 {
00866                   if (fabs(pInt[j])>ZERO)
00867                     {
00868                       AddVariable2Monomial(linkVars[map[n][i][j]],1,&f);
00869                       if (sv!=NO_UINT)
00870                         AddVariable2Monomial(sv,1,&f);
00871                       AddCt2Monomial(2.0*sg[n][i][j]*sf*p[j],&f);
00872                       
00873                       AddMonomial(&f,&(eq[i]));
00874                       ResetMonomial(&f);
00875                     }
00876                 }
00877             }
00878         }
00879 
00880       free(vname);
00881     }
00882   DeleteMonomial(&f);  
00883 }
00884 
00885 void RegenerateLinkSolution(TCuikSystem *cs,double *sol,boolean groundLink,Tlink *l)
00886 {
00887   if (!groundLink)
00888     {
00889       unsigned int i,j,n;
00890       double qVars[4];
00891       char *vname;
00892  
00893       NEW(vname,strlen(l->name)+100,char);
00894 
00895       for(j=0;j<4;j++)
00896         {
00897           LINK_ROT3_Q(vname,l->name,j);
00898           n=GetCSVariableID(vname,cs); 
00899           if (n==NO_UINT)
00900             Error("Undefined reference variable in RegenerateLinkSolution");
00901           qVars[j]=sol[n];
00902         }
00903 
00904       for(i=0;i<4;i++)
00905         {
00906           for(j=i;j<4;j++)
00907             {
00908               LINK_ROT3_E(vname,l->name,i,j);
00909               n=GetCSVariableID(vname,cs); 
00910               if (n==NO_UINT)
00911                 Error("Undefined reference variable in RegenerateLinkSolution");
00912           
00913               sol[n]=qVars[i]*qVars[j];
00914             }
00915         }
00916       free(vname);
00917     }
00918 }
00919 
00920 void GetTransform2Link(TCuikSystem *cs,double *sol,boolean groundLink,
00921                        double *r,THTransform *t,Tlink *l)
00922 {
00923   if (groundLink)
00924     HTransformIdentity(t);
00925   else
00926     {
00927       unsigned int i,j,n;
00928       char *vname;
00929       double e[4][4]; /* only the upper half is used */
00930 
00931       /*In general this function has been used before reaching this point but
00932         just in case....*/
00933       RegenerateLinkSolution(cs,sol,FALSE,l);
00934 
00935       NEW(vname,strlen(l->name)+100,char);
00936   
00937       for(i=0;i<4;i++)
00938         {
00939           for(j=i;j<4;j++)
00940             {
00941               LINK_ROT3_E(vname,l->name,i,j);
00942               n=GetCSVariableID(vname,cs); 
00943               if (n==NO_UINT)
00944                 Error("Undefined reference variable in GetTransform2Link");
00945               e[i][j]=2*sol[n];
00946             }
00947         }
00948 
00949       /* Define the homogeneous transform using the rotation and the translation.*/
00950       HTransformIdentity(t);
00951      
00952       HTransformSetElement(0,0,1-e[1][1]-e[2][2],t);
00953       HTransformSetElement(0,1,  e[0][1]-e[2][3],t);
00954       HTransformSetElement(0,2,  e[0][2]+e[1][3],t);
00955       HTransformSetElement(0,3,r[0],t);
00956 
00957       HTransformSetElement(1,0,  e[0][1]+e[2][3],t);
00958       HTransformSetElement(1,1,1-e[0][0]-e[2][2],t);
00959       HTransformSetElement(1,2,  e[1][2]-e[0][3],t);
00960       HTransformSetElement(1,3,r[1],t);
00961 
00962       HTransformSetElement(2,0,  e[0][2]-e[1][3],t);
00963       HTransformSetElement(2,1,  e[1][2]+e[0][3],t);
00964       HTransformSetElement(2,2,1-e[0][0]-e[1][1],t);
00965       HTransformSetElement(2,3,r[2],t);
00966       
00967       /* This ensures that the transformation is actually rigid */
00968       HTransformOrthonormalize(t,t);
00969 
00970       free(vname);
00971     }
00972 }
00973 #endif
00974 
00975 double GetLinkMaxCoordinate(Tlink *l)
00976 {
00977   return(l->maxCoord);
00978 }
00979 
00980 void PlotLink(Tplot3d *pt,double axesLength,Tlink *l)
00981 {
00982   unsigned int n;
00983 
00984   n=LinkNBodies(l);
00985 
00986   if (n>0)
00987     {
00988       unsigned int i;
00989 
00990       for(i=0;i<n;i++)
00991         PlotCPolyhedron(pt,GetLinkBody(i,l));
00992 
00993       if (axesLength>0)
00994         {
00995           double points[3][2]={{0,0},{0,0},{0,0}};
00996           Tcolor axesColor;
00997 
00998           for(i=0;i<3;i++)
00999             {
01000               NewColor((i==0?1:0),(i==1?1:0),(i==2?1:0),&axesColor);
01001               l->axisID[i]=StartNew3dObject(&axesColor,pt);
01002               DeleteColor(&axesColor);
01003 
01004               points[i][1]=axesLength;
01005               PlotVect3d(2,points[0],points[1],points[2],pt);
01006               points[i][1]=0;
01007 
01008               Close3dObject(pt);
01009             }
01010         }
01011       else
01012         {
01013           for(i=0;i<3;i++)
01014             l->axisID[i]=NO_UINT;
01015         }
01016     }
01017 }
01018 
01019 void MoveLink(Tplot3d *pt,TCuikSystem *cs,double *sol,
01020               double *r,Tlink *l)
01021 {
01022   unsigned int m;
01023   m=LinkNBodies(l);
01024 
01025   if (m>0)
01026     {
01027       /* Systems not included in any loop are not in the system -> can
01028          not be moved (can move freely)*/
01029 
01030       unsigned int i;
01031       THTransform t;
01032       Tcpolyhedron *bd;
01033           
01034       /* First we compute the transform to apply to all the bodies of the link */
01035       GetTransform2Link(cs,sol,FALSE,r,&t,l);
01036       
01037       for(i=0;i<3;i++)
01038         {
01039           if (l->axisID[i]!=NO_UINT)
01040             Move3dObject(l->axisID[i],&t,pt);
01041         }
01042 
01043       /*Apply the same transform to all the bodies in the link*/
01044       for(i=0;i<m;i++)
01045         {
01046           bd=GetLinkBody(i,l);
01047 
01048           MoveCPolyhedron(pt,&t,bd);
01049         }
01050       
01051       HTransformDelete(&t);
01052     }
01053 }
01054 
01055 void DeleteLink(Tlink *l)
01056 {
01057   unsigned int i,n;
01058   Tcpolyhedron *b;
01059 
01060   if (l->name!=NULL)
01061     free(l->name);
01062      
01063   /*Bodies are not deleted since mechanisms take care of them
01064     (here we only have IDs of the bodies)*/
01065 
01066   n=LinkNBodies(l);  
01067   for(i=0;i<n;i++)
01068     {
01069       b=GetLinkBody(i,l);
01070       DeleteCPolyhedron(b);
01071       free(b);
01072     }
01073   DeleteVector(&(l->bodies));
01074 
01075   HTransformDelete(&(l->R));
01076 }