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

The CuikSuite Project

joint.c

Go to the documentation of this file.
00001 #include "joint.h"
00002 
00003 #include "error.h"
00004 #include "defines.h"
00005 #include "geom.h"
00006 #include "varnames.h"
00007 
00008 #include <math.h>
00009 #include <string.h>
00010 
00019 void NewFreeJoint(unsigned int id,
00020                   unsigned int linkID1,Tlink *link1,
00021                   unsigned int linkID2,Tlink *link2,
00022                   Tjoint *j)
00023 {
00024   unsigned int i,k;
00025 
00026   if (linkID1==linkID2)
00027     Error("Setting up a joint on a single link");
00028 
00029   j->t=FREE_JOINT;
00030   
00031   j->id=id;
00032 
00033   j->linkID[0]=linkID1;
00034   j->linkID[1]=linkID2;
00035   j->link[0]=link1;
00036   j->link[1]=link2;
00037   
00038   for(i=0;i<6;i++)
00039     {
00040       for(k=0;k<3;k++)
00041         j->points[i][k]=0.0;
00042     }
00043 
00044   for(i=0;i<3;i++)
00045     {
00046       for(k=0;k<3;k++)
00047         j->normals[i][k]=0.0;
00048     }
00049 
00050   j->hasLimits=FALSE;
00051   j->avoidLimits=FALSE;
00052   j->avoidLimitsWeight=0.0;
00053   NewInterval(-INF,INF,&(j->range));
00054   NewInterval(-INF,INF,&(j->range2));
00055 
00056   j->obj3d=NO_UINT;
00057   j->rad=0;
00058   j->length=0;
00059   NewColor(0,0,0,&(j->color));
00060 
00061   HTransformIdentity(&(j->trs));
00062 }
00063 
00064 void NewFixJoint(unsigned int id,
00065                  unsigned int linkID1,Tlink *link1,
00066                  unsigned int linkID2,Tlink *link2,
00067                  THTransform *t,
00068                  Tjoint *j)
00069 {
00070   unsigned int i,k;
00071 
00072   if (linkID1==linkID2)
00073     Error("Setting up a joint on a single link");
00074 
00075   j->t=FIX_JOINT;
00076   
00077   HTransformCopy(&(j->trs),t);
00078 
00079   j->id=id;
00080 
00081   j->linkID[0]=linkID1;
00082   j->linkID[1]=linkID2;
00083   j->link[0]=link1;
00084   j->link[1]=link2;
00085   
00086   /*
00087     The translation form link1 to link2 is used in loops.
00088     We store it in points[0] to speed up the access 
00089     (see GenerateJointEquationsInBranch)
00090    */
00091   j->points[0][0]=HTransformGetElement(0,3,t);
00092   j->points[0][1]=HTransformGetElement(1,3,t);
00093   j->points[0][2]=HTransformGetElement(2,3,t);
00094 
00095   for(i=1;i<4;i++)
00096     {
00097       for(k=0;k<3;k++)
00098         j->points[i][k]=0.0;
00099     }
00100 
00101   for(i=0;i<2;i++)
00102     {
00103       for(k=0;k<3;k++)
00104         j->normals[i][k]=0.0;
00105     }
00106 
00107 
00108   j->hasLimits=FALSE;
00109   j->avoidLimits=FALSE;
00110   j->avoidLimitsWeight=0.0;
00111   NewInterval(-INF,INF,&(j->range));
00112   NewInterval(-INF,INF,&(j->range2));
00113 
00114   j->obj3d=NO_UINT;
00115   j->rad=0;
00116   j->length=0;
00117   NewColor(0,0,0,&(j->color));
00118 }
00119 
00120 void NewRevoluteJoint(unsigned int id,
00121                       unsigned int linkID1,Tlink *link1,
00122                       unsigned int linkID2,Tlink *link2,
00123                       double **points,
00124                       boolean hasLimits,Tinterval *range,double **rPoints,
00125                       boolean avoidLimits,double avoidLimitsWeight,
00126                       Tjoint *j)
00127 {
00128   unsigned int i,k;
00129   double nr;
00130 
00131   if (linkID1==linkID2)
00132     Error("Setting up a joint on a single link");
00133 
00134   j->t=REV_JOINT;
00135 
00136   j->id=id;
00137 
00138   j->linkID[0]=linkID1;
00139   j->linkID[1]=linkID2;
00140   j->link[0]=link1;
00141   j->link[1]=link2;
00142 
00143   for(i=0;i<4;i++)
00144     {
00145       for(k=0;k<3;k++)
00146         j->points[i][k]=points[i][k];
00147     }
00148 
00149   /* compute the normalized vectors along the rotation axis */
00150   for(i=0;i<2;i++)
00151     {
00152       nr=0.0;
00153       for(k=0;k<3;k++)
00154         {
00155           j->normals[i][k]=points[2*i+1][k]-points[2*i][k];
00156           nr+=(j->normals[i][k]*j->normals[i][k]);
00157         }
00158       nr=sqrt(nr);
00159       for(k=0;k<3;k++)
00160         j->normals[i][k]/=nr;
00161     }
00162 
00163   j->hasLimits=hasLimits;
00164 
00165   if (j->hasLimits)
00166     {
00167       double c;
00168       double center;
00169       THTransform t,rx,a;
00170       double zero[3]={0,0,0};
00171 
00172       for(i=0;i<2;i++)
00173         {
00174           /*normalize the reference vectors*/
00175           nr=0.0;
00176           for(k=0;k<3;k++)
00177             {
00178               j->vrange[i][k]=rPoints[i][k]-points[2*i][k];
00179               nr+=(j->vrange[i][k]*j->vrange[i][k]);
00180             }
00181           nr=sqrt(nr);
00182           for(k=0;k<3;k++)
00183             j->vrange[i][k]/=nr;
00184 
00185           /*Test that the rotation vectors are orthogonal to the rotation axes*/
00186           c=0; /*cosinus between the two vectors*/
00187           for(k=0;k<3;k++)
00188             c+=(j->vrange[i][k]*j->normals[i][k]);
00189 
00190           if (fabs(c)>ZERO)
00191             Error("Rotation axes and rotation reference vectors are not orthonormal (Revolute Joint)");
00192         }
00193 
00194       /*Copy of the range for the rotation angle*/
00195       CopyInterval(&(j->range),range);
00196 
00197       /*We offset the range so that it is zero-centered*/
00198       center=IntervalCenter(&(j->range));
00199       IntervalOffset(&(j->range),-center,&(j->range));
00200 
00201       /* Since we moved the rotation range to make it zero-centered, we 
00202          have to rotate the reference vectors accordingly. 
00203          In this way, the angle between the reference vectors is changed in the same
00204          way as the offset applied to the range interval. */
00205       /* The rotation is around the vector defining the revolute joint for
00206          the current link. This rotation is defined by rotating the axis vector
00207          to the X axis, rotating around X and then rotating the vector back
00208          to the its original position.*/
00209 
00210       HTransformX2Vect(1,1,zero,j->normals[0],&t); /* this rotates X to the
00211                                                       revolute axis vector*/
00212       HTransformRx(center,&rx); /*rotation around X*/
00213       
00214       HTransformInverse(&t,&a); /*this rotates the axis vector to X*/
00215       HTransformProduct(&rx,&a,&a);
00216       HTransformProduct(&t,&a,&a);
00217       
00218       HTransformApply(j->vrange[0],j->vrange[0],&a); 
00219       
00220       HTransformDelete(&a);
00221       HTransformDelete(&rx);
00222       HTransformDelete(&t);
00223 
00224       j->avoidLimits=avoidLimits;
00225       j->avoidLimitsWeight=avoidLimitsWeight;
00226     }
00227   else
00228     {
00229       /*Set some empty information for the range (not used)*/
00230       NewInterval(-INF,INF,&(j->range));
00231       for(i=0;i<2;i++)
00232         {
00233           for(k=0;k<3;k++)
00234             j->vrange[i][k]=0.0;
00235         }
00236       j->avoidLimits=FALSE;
00237       j->avoidLimitsWeight=0;
00238     }
00239 
00240   NewInterval(-INF,INF,&(j->range2));
00241 
00242   j->obj3d=NO_UINT;
00243   j->rad=0;
00244   j->length=0;
00245   NewColor(0,0,0,&(j->color));  
00246   HTransformIdentity(&(j->trs));
00247 }
00248 
00249 
00250 void NewUniversalJoint(unsigned int id,
00251                        unsigned int linkID1,Tlink *link1,
00252                        unsigned int linkID2,Tlink *link2,
00253                        double **points,
00254                        boolean hasLimits,
00255                        Tinterval*range1,Tinterval *range2,double **rPoints,
00256                        boolean avoidLimits,double avoidLimitsWeight,
00257                        Tjoint *j)
00258 {
00259   unsigned int i,k;
00260   double nr;
00261 
00262   if (linkID1==linkID2)
00263     Error("Setting up a joint on a single link");
00264 
00265   j->t=UNV_JOINT;
00266 
00267   j->id=id;
00268 
00269   j->linkID[0]=linkID1;
00270   j->linkID[1]=linkID2;
00271   j->link[0]=link1;
00272   j->link[1]=link2;
00273 
00274   for(i=0;i<4;i++)
00275     {
00276       for(k=0;k<3;k++)
00277         j->points[i][k]=points[i][k];
00278     }
00279 
00280   /* compute the normalized vectors along the rotation axis */
00281   for(i=0;i<2;i++)
00282     {
00283       nr=0.0;
00284       for(k=0;k<3;k++)
00285         {
00286           j->normals[i][k]=points[2*i+1][k]-points[2*i][k];
00287           nr+=(j->normals[i][k]*j->normals[i][k]);
00288         }
00289       nr=sqrt(nr);
00290       for(k=0;k<3;k++)
00291         j->normals[i][k]/=nr;
00292     }
00293 
00294   j->hasLimits=hasLimits;
00295 
00296   if (j->hasLimits)
00297     {
00298       double c;
00299       double center;
00300       THTransform t,rx,a;
00301       double zero[3]={0,0,0};
00302       Tinterval *rd,*rs; 
00303 
00304       for(i=0;i<2;i++)
00305         {
00306           /*normalize the reference vectors*/
00307           nr=0.0;
00308           for(k=0;k<3;k++)
00309             {
00310               j->vrange[i][k]=rPoints[i][k]-points[2*i][k];
00311               nr+=(j->vrange[i][k]*j->vrange[i][k]);
00312             }
00313           nr=sqrt(nr);
00314           for(k=0;k<3;k++)
00315             j->vrange[i][k]/=nr;
00316 
00317           /*Test that the rotation vectors are orthogonal to the rotation axes*/
00318           c=0; /*cosinus between the two vectors*/
00319           for(k=0;k<3;k++)
00320             c+=(j->vrange[i][k]*j->normals[i][k]);
00321 
00322           if (fabs(c)>ZERO)
00323             Error("Rotation axes and rotation reference vectors are not orthonormal (Universal Joint)");
00324 
00325           
00326         }
00327 
00328       /*Copy of the ranges for the 2 rotation angles*/
00329       /*and we offset them so that they are zero-centered*/
00330       for(k=0;k<3;k++)
00331         {
00332           if (k==0)
00333             {
00334               rs=range1;
00335               rd=&(j->range);
00336             }
00337           else
00338             {
00339               rs=range2;
00340               rd=&(j->range2);
00341             }
00342 
00343           CopyInterval(rd,rs);
00344           /*We offset the ranges so that they are zero-centered*/
00345           center=IntervalCenter(rd);
00346           IntervalOffset(rd,-center,rd);
00347           
00348           /* Since we moved the rotation range to make it zero-centered, we 
00349              have to rotate ONE of the the reference vectors accordingly. 
00350              In this way, the angle between the reference vectors is changed in the same
00351              way as the offset applied to the range interval. */
00352           /* The rotation is around the vector defining the revolute joint for
00353              the current link. This rotation is defined by rotating the axis vector
00354              to the X axis, rotating around X and then rotating the vector back
00355              to the its original position.*/
00356           HTransformX2Vect(1,1,zero,j->normals[k],&t); /*this rotates X to to the
00357                                                  revolute axis vector*/
00358           HTransformRx(center,&rx); /*rotation around X*/
00359           
00360           HTransformInverse(&t,&a); /*this rotates the axis vector to X*/
00361           HTransformProduct(&rx,&a,&a);
00362           HTransformProduct(&t,&a,&a);
00363           
00364           HTransformApply(j->vrange[k],j->vrange[k],&a);
00365       
00366           HTransformDelete(&a);
00367           HTransformDelete(&rx);
00368           HTransformDelete(&t);
00369         }
00370       j->avoidLimits=avoidLimits;
00371       j->avoidLimitsWeight=avoidLimitsWeight;
00372     }
00373   else
00374     {
00375       /*Set some empty information for the range (not used)*/
00376       NewInterval(-INF,INF,&(j->range));
00377       NewInterval(-INF,INF,&(j->range2));
00378       for(i=0;i<2;i++)
00379         {
00380           for(k=0;k<3;k++)
00381             j->vrange[i][k]=0.0;
00382         }
00383       j->avoidLimits=FALSE;
00384       j->avoidLimitsWeight=0.0;
00385     }
00386 
00387   j->obj3d=NO_UINT;
00388   j->rad=0;
00389   j->length=0;
00390   NewColor(0,0,0,&(j->color));  
00391   HTransformIdentity(&(j->trs));
00392 }
00393 
00394 void NewSphericalJoint(unsigned int id,
00395                        unsigned int linkID1,Tlink *link1,
00396                        unsigned int linkID2,Tlink *link2,
00397                        double **points,
00398                        boolean hasLimits,double range,double **rPoints,
00399                        boolean avoidLimits,double avoidLimitsWeight,
00400                        Tjoint *j)
00401 {
00402   unsigned int i,k;
00403   double nr;
00404 
00405   if (linkID1==linkID2)
00406     Error("Setting up a joint on a single link");
00407 
00408   j->t=SPH_JOINT;
00409 
00410   j->id=id;
00411 
00412   j->linkID[0]=linkID1;
00413   j->linkID[1]=linkID2;
00414   j->link[0]=link1;
00415   j->link[1]=link2;
00416 
00417   /*for spherical joints only one point in each link is given, we replicate
00418     if as two points. */
00419   for(k=0;k<3;k++)
00420     {
00421       j->points[0][k]=points[0][k];
00422       j->points[1][k]=points[0][k];
00423     }
00424   for(k=0;k<3;k++)
00425     {
00426       j->points[2][k]=points[2][k];
00427       j->points[3][k]=points[2][k];
00428     }
00429 
00430   j->hasLimits=hasLimits;
00431 
00432   if (j->hasLimits)
00433     {
00434       NewInterval(-range,range,&(j->range));
00435       /*normalize the reference vectors*/
00436       for(i=0;i<2;i++)
00437         {
00438           nr=0.0;
00439           for(k=0;k<3;k++)
00440             {
00441               j->vrange[i][k]=rPoints[i][k]-points[2*i][k];
00442               nr+=(j->vrange[i][k]*j->vrange[i][k]);
00443             }
00444           nr=sqrt(nr);
00445           for(k=0;k<3;k++)
00446             j->vrange[i][k]/=nr;
00447         }
00448       j->avoidLimits=avoidLimits;
00449       j->avoidLimitsWeight=avoidLimitsWeight;
00450     }
00451   else
00452     {
00453       /*Set some empty information for the range (not used)*/
00454       NewInterval(-INF,INF,&(j->range));
00455       for(i=0;i<2;i++)
00456         {
00457           for(k=0;k<3;k++)
00458             j->vrange[i][k]=0.0;
00459         }
00460       j->avoidLimits=FALSE;
00461       j->avoidLimitsWeight=0.0;
00462     }
00463 
00464   NewInterval(-INF,INF,&(j->range2));
00465 
00466   j->obj3d=NO_UINT;
00467   j->rad=0;
00468   j->length=0;
00469   NewColor(0,0,0,&(j->color));  
00470   HTransformIdentity(&(j->trs));
00471 }
00472 
00473 void NewPrismaticJoint(unsigned int id,
00474                        unsigned int linkID1,Tlink *link1,
00475                        unsigned int linkID2,Tlink *link2,
00476                        double **points,Tinterval *range,
00477                        boolean avoidLimits,double avoidLimitsWeight,
00478                        Tjoint *j)
00479 {
00480   unsigned int i,k;
00481   double nr;
00482 
00483   if (linkID1==linkID2)
00484     Error("Setting up a joint on a single link");
00485 
00486   j->t=PRS_JOINT;
00487 
00488   j->id=id;
00489 
00490   j->linkID[0]=linkID1;
00491   j->linkID[1]=linkID2;
00492   j->link[0]=link1;
00493   j->link[1]=link2;
00494 
00495   for(i=0;i<4;i++)
00496     {
00497       for(k=0;k<3;k++)
00498         j->points[i][k]=points[i][k];
00499     }
00500 
00501   for(i=0;i<2;i++)
00502     {
00503       nr=0.0;
00504       for(k=0;k<3;k++)
00505         {
00506           j->normals[i][k]=points[2*i+1][k]-points[2*i][k];
00507           nr+=(j->normals[i][k]*j->normals[i][k]);
00508         }
00509       nr=sqrt(nr);
00510       for(k=0;k<3;k++)
00511         j->normals[i][k]/=nr;
00512     }
00513 
00514   j->hasLimits=TRUE;
00515   CopyInterval(&(j->range),range);
00516 
00517   /*This information is not used for the prismatic joint*/
00518   for(i=0;i<2;i++)
00519     {
00520       for(k=0;k<3;k++)
00521         j->vrange[i][k]=0.0;
00522     }
00523 
00524   NewInterval(-INF,INF,&(j->range2));
00525 
00526   j->obj3d=NO_UINT;
00527   j->rad=0;
00528   j->length=0;
00529   NewColor(0,0,0,&(j->color));  
00530   HTransformIdentity(&(j->trs));
00531 
00532   j->avoidLimits=avoidLimits;
00533   j->avoidLimitsWeight=avoidLimitsWeight;
00534 }
00535 
00536 void NewSphSphJoint(unsigned int id,
00537                     unsigned int linkID1,Tlink *link1,
00538                     unsigned int linkID2,Tlink *link2,
00539                     double **points,
00540                     double l,double r,
00541                     Tcolor *color,
00542                     Tjoint *j)
00543 {
00544   unsigned int i,k;
00545 
00546   if (linkID1==linkID2)
00547     Error("Setting up a joint on a single link");
00548 
00549   j->t=SPH_SPH_JOINT;
00550 
00551   j->id=id;
00552 
00553   j->linkID[0]=linkID1;
00554   j->linkID[1]=linkID2;
00555   j->link[0]=link1;
00556   j->link[1]=link2;
00557 
00558   /*for spherical joints only one point in each link is given, we replicate
00559     if as two points. */
00560   for(k=0;k<3;k++)
00561     {
00562       j->points[0][k]=points[0][k];
00563       j->points[1][k]=points[0][k];
00564     }
00565   for(k=0;k<3;k++)
00566     {
00567       j->points[2][k]=points[1][k];
00568       j->points[3][k]=points[1][k];
00569     }
00570 
00571   j->hasLimits=FALSE;
00572   j->avoidLimits=FALSE;
00573 
00574   /*Set some empty information for the range (not used)*/
00575   NewInterval(-INF,INF,&(j->range));
00576   NewInterval(-INF,INF,&(j->range2));
00577   for(i=0;i<2;i++)
00578     {
00579       for(k=0;k<3;k++)
00580         j->vrange[i][k]=0.0;
00581     }
00582 
00583   j->obj3d=NO_UINT;
00584   j->rad=r;
00585   j->length=l;
00586   CopyColor(&(j->color),color);  
00587   HTransformIdentity(&(j->trs));
00588 }
00589 
00590 void NewInPatchJoint(unsigned int id,
00591                      unsigned int linkID1,Tlink *link1,
00592                      unsigned int linkID2,Tlink *link2,
00593                      double **points,
00594                      double **patch,
00595                      boolean avoidLimits,double avoidLimitsWeight,
00596                      Tjoint *j)
00597 {
00598   unsigned int k;
00599   double aux[3],t1[3],t2[3];
00600   double n1,n2;
00601   double p[3][3];
00602   Tinterval tx,ty,tz,a;
00603 
00604   if (linkID1==linkID2)
00605     Error("Setting up a joint on a single link");
00606 
00607   j->t=IN_PATCH_JOINT;
00608 
00609   j->id=id;
00610 
00611   j->linkID[0]=linkID1;
00612   j->linkID[1]=linkID2;
00613   j->link[0]=link1;
00614   j->link[1]=link2;
00615   
00616   /*Store the 2 points defining the point and normal on the first link*/
00617   for(k=0;k<3;k++)
00618     {
00619       j->points[0][k]=points[0][k];
00620       j->points[1][k]=points[1][k]-points[0][k];
00621     }
00622 
00623   /*Store the 4 points defining the patch in the second link. Actually we do
00624     not directly store the points but differences between them*/
00625 
00626   for(k=0;k<3;k++)
00627     {
00628       j->points[2][k]=patch[0][k];
00629       j->points[3][k]=patch[2][k]-patch[0][k];
00630       j->points[4][k]=patch[1][k]-patch[0][k];
00631       j->points[5][k]=patch[0][k]-patch[1][k]-patch[2][k]+patch[3][k];
00632     }
00633 
00634   /* Size of the sides of the patch: must be larger than 0 */
00635   n1=DotProduct(j->points[3],j->points[3]);
00636   n2=DotProduct(j->points[4],j->points[4]);
00637 
00638   if ((n1<ZERO)||(n2<ZERO))
00639     Error("Patch is too small");
00640 
00641   /*Store information to recover the normal at any point in the patch*/
00642   CrossProduct(j->points[3],j->points[4],j->normals[0]);
00643 
00644   CrossProduct(j->points[3],j->points[5],j->normals[1]);
00645 
00646   CrossProduct(j->points[5],j->points[4],j->normals[2]);
00647 
00648   /*Check if the input points correctly define a patch.
00649     Points defining a patch are given as
00650               p2------p3
00651               |       |
00652               |       |
00653               p0------p1
00654     Thus, in a correct patch vector p0->p3 is enclosed in 
00655     vectors p0->p2 and p0->p1.
00656     We check if this is so ensuring that angle p2-p0-p3 has the
00657     same sign as angle p3-p0-p1
00658    */
00659   for(k=0;k<3;k++)
00660     aux[k]=patch[3][k]-patch[0][k]; /*This is p0->p3*/
00661 
00662   if ((DotProduct(aux,j->points[3])<ZERO)||
00663       (DotProduct(aux,j->points[4])<ZERO))
00664     Error("Patch with overlapping points");
00665 
00666   CrossProduct(j->points[3],aux,t1); /* t1=(p0->p2) x (p0->p3) */
00667   CrossProduct(aux,j->points[4],t2); /* t2=(p0->p3) x (p0->p1) */
00668   
00669   /* Now we check that the above vectors have the same orientation */
00670   if (DotProduct(t1,t2)<ZERO)
00671     Error("Patch points given in the wrong order");
00672 
00673   /*Now we compute the minimum/maximum values of the norm of the normal vector*/
00674   for(k=0;k<3;k++)
00675     {
00676       p[k][0]=j->normals[0][k];
00677       p[k][1]=t1[k];
00678       p[k][2]=t2[k];
00679     }
00680 
00681   ComputeBoundingBox3d(3,p[0],p[1],p[2],&tx,&ty,&tz);
00682   IntervalPow(&tx,2,&(j->normRange));
00683   IntervalPow(&ty,2,&a);
00684   IntervalAdd(&(j->normRange),&a,&(j->normRange));
00685   IntervalPow(&tz,2,&a);
00686   IntervalAdd(&(j->normRange),&a,&(j->normRange));
00687   IntervalSqrt(&(j->normRange),&(j->normRange));
00688   
00689   if (LowerLimit(&(j->normRange))<ZERO)
00690     Error("The lower limit for the norm vector bounds for a IN_PATCH_JOINT should not be zero.");
00691 
00692   /*Now we store the avoid limit information, if any*/
00693   j->hasLimits=TRUE; /*Limits are given by the patch*/
00694   j->avoidLimits=avoidLimits;
00695   j->avoidLimitsWeight=avoidLimitsWeight;
00696 }
00697 
00698 void CopyJoint(Tjoint *j_dst,Tjoint *j_src)
00699 {
00700   unsigned int i,k;
00701 
00702   j_dst->t=j_src->t;
00703 
00704   j_dst->id=j_src->id;
00705 
00706   for(i=0;i<2;i++)
00707     {
00708       j_dst->linkID[i]=j_src->linkID[i];
00709       j_dst->link[i]=j_src->link[i];
00710     }
00711 
00712   for(i=0;i<6;i++)
00713     {
00714       for(k=0;k<3;k++)
00715         j_dst->points[i][k]=j_src->points[i][k];
00716     }
00717 
00718   for(i=0;i<3;i++)
00719     {
00720       for(k=0;k<3;k++)
00721         j_dst->normals[i][k]=j_src->normals[i][k];
00722     }
00723 
00724   j_dst->hasLimits=j_src->hasLimits;
00725   j_dst->avoidLimits=j_src->avoidLimits;
00726   j_dst->avoidLimitsWeight=j_src->avoidLimitsWeight;
00727 
00728   CopyInterval(&(j_dst->normRange),&(j_src->normRange));
00729 
00730   CopyInterval(&(j_dst->range),&(j_src->range)); 
00731   CopyInterval(&(j_dst->range2),&(j_src->range2)); 
00732 
00733   for(i=0;i<2;i++)
00734     {
00735       for(k=0;k<3;k++)
00736         j_dst->vrange[i][k]=j_src->vrange[i][k];
00737     }
00738 
00739   j_dst->obj3d=j_src->obj3d;
00740   j_dst->rad=j_src->rad;
00741   j_dst->length=j_src->length;
00742   CopyColor(&(j_dst->color),&(j_src->color));
00743 
00744   HTransformCopy(&(j_dst->trs),&(j_src->trs));
00745 }
00746 
00747 unsigned int GetJointType(Tjoint *j)
00748 {
00749   return(j->t);
00750 }
00751 
00752 unsigned int GetJointID(Tjoint *j)
00753 {
00754   return(j->id);
00755 }
00756 
00757 unsigned int JointFromID(Tjoint *j)
00758 {
00759   return(j->linkID[0]);
00760 }
00761 
00762 Tlink *JointFrom(Tjoint *j)
00763 {
00764   return(j->link[0]);
00765 }
00766 
00767 unsigned int JointToID(Tjoint *j)
00768 {
00769   return(j->linkID[1]);
00770 }
00771 
00772 Tlink *JointTo(Tjoint *j)
00773 {
00774   return(j->link[1]);
00775 }
00776 
00777 void GetJointPoint(unsigned int link,unsigned int point,double *p,Tjoint *j)
00778 {
00779   unsigned int i,k;
00780 
00781   i=link*2+point;
00782 
00783   for(k=0;k<3;k++)
00784     p[k]=j->points[i][k];
00785 }
00786 
00787 boolean LimitedJoint(Tjoint *j)
00788 {
00789   return(j->hasLimits);
00790 }
00791 
00792 Tinterval *GetJointRange(Tjoint *j)
00793 { 
00794   return(&(j->range));
00795 }
00796 
00797 Tinterval *GetJointSecondRange(Tjoint *j)
00798 { 
00799   return(&(j->range2));
00800 }
00801 
00802 signed int GetJointDOF(Tjoint *j)
00803 {
00804   signed int ndof;
00805 
00806   switch(j->t)
00807     {
00808       case FREE_JOINT:
00809         ndof=6;
00810         break;
00811       case FIX_JOINT:
00812         ndof=0;
00813         break;
00814       case PRS_JOINT:
00815         ndof=1;
00816         break;
00817       case SPH_JOINT:
00818         ndof=3;
00819         break;
00820       case REV_JOINT:
00821         ndof=1;
00822         break;
00823       case UNV_JOINT:
00824         ndof=2;
00825         break;
00826       case SPH_SPH_JOINT:
00827         ndof=5;
00828         break;
00829       case IN_PATCH_JOINT:
00830         ndof=2;
00831         break;
00832     default:
00833       Error("Undefined joint type in GetJointDOF");
00834     }
00835   return(ndof);
00836 }
00837 
00838 double GetJointLength(Tjoint *j)
00839 {
00840   if (j->t!=SPH_SPH_JOINT)
00841     Error("The length is only defined for spherical-spherical composite joints");
00842 
00843   return(j->length);
00844 }
00845 
00846 THTransform *GetJointTransform(Tjoint *j)
00847 {
00848   if (j->t!=FIX_JOINT)
00849     Error("The transform is only defined for spherical-spherical composite joints");
00850 
00851   return(&(j->trs));
00852 }
00853 
00854 void GenerateJointRangeEquations(Tparameters *p,TCuikSystem *cs,Tjoint *j)
00855 {
00856   /* Equations associated with the joint (not joint equations as in the paper :) */
00857 
00858   char *vname;
00859   unsigned int i,k,id,nv;
00860   Tequation eq[3],eq1;
00861   Tinterval rangeOne,rangeInf;
00862   Tmonomial f;
00863   unsigned int jointVars[4][3]; /*Reference vector used in REVOLUTE and SPHERICAL joints*/
00864   Tvariable var;
00865   char *ln1,*ln2;
00866   Tinterval ic;
00867   double r;
00868   
00869   NewInterval(-1.0,1.0,&rangeOne);
00870   NewInterval(-INF,INF,&rangeInf);
00871 
00872   InitMonomial(&f);
00873 
00874   ln1=GetLinkName(j->link[0]);
00875   ln2=GetLinkName(j->link[1]);
00876 
00877   NEW(vname,strlen(ln1)+strlen(ln2)+100,char);
00878 
00879   switch(j->t)
00880     {
00881     case FREE_JOINT:
00882       /*We generate 3 new variables representing the (unlimited) displacement from
00883         the origin of the first link to the origin of the second link.
00884         No equations constraint these variables. */
00885       for(k=0;k<3;k++)
00886         {
00887           FREE_JOINT_VAR(vname,j->id,j->linkID[0],ln1,j->linkID[1],ln2,k);
00888           
00889           NewVariable(SECONDARY_VAR,vname,&var);
00890           SetVariableInterval(&rangeInf,&var);
00891 
00892           AddVariable2CS(&var,cs);
00893           
00894           DeleteVariable(&var);
00895         }
00896       break;
00897 
00898     case FIX_JOINT:
00899       break;
00900 
00901     case PRS_JOINT:
00902       /*Add one variable for the displacement along the prismatic axis*/
00903       PRS_JOINT_VAR(vname,j->id,ln1,ln2);
00904       
00905       NewVariable(SYSTEM_VAR,vname,&var);
00906       SetVariableInterval(&(j->range),&var);
00907 
00908       nv=AddVariable2CS(&var,cs);
00909 
00910       DeleteVariable(&var);
00911 
00912       if (j->avoidLimits)
00913         {
00914           r=IntervalSize(&(j->range))/2;
00915           AddTerm2SearchCriterion(j->avoidLimitsWeight/(r*r),nv,
00916                                   IntervalCenter(&(j->range)),cs);
00917         }
00918 
00919       break;
00920    
00921     case UNV_JOINT:
00922     case REV_JOINT:
00923     case SPH_JOINT:
00924       if (j->hasLimits)
00925         {
00926           /*We define two vectors normal to the rotation axis, one attached
00927             to link1 (k==0) and another attached to link2 (k==1)*/
00928           for(k=0;k<2;k++)
00929             { 
00930               /*Define the variables for the rotation reference vectors*/
00931               for(i=0;i<3;i++)
00932                 {             
00933                   InitEquation(&(eq[i]));
00934                   SetEquationValue(0.0,&(eq[i]));
00935 
00936                   if (j->t==REV_JOINT)
00937                     ROT_JOINT_VAR_REF(vname,j->id,k,ln1,ln2,i);
00938                   else
00939                     {
00940                       if (j->t==SPH_JOINT)
00941                         SPH_JOINT_VAR_REF(vname,j->id,k,ln1,ln2,i);
00942                       else
00943                         UNV_JOINT_VAR_REF(vname,j->id,k,ln1,ln2,i);
00944                     }
00945 
00946                   NewVariable(SECONDARY_VAR,vname,&var);
00947                   SetVariableInterval(&rangeOne,&var);
00948 
00949                   id=AddVariable2CS(&var,cs);
00950 
00951                   DeleteVariable(&var);
00952 
00953                   jointVars[k][i]=id;
00954                   AddVariable2Monomial(id,1,&f);
00955                   AddMonomial(&f,&(eq[i]));
00956                   ResetMonomial(&f);
00957                 }
00958 
00959               ApplyLinkRot(-1.0,NO_UINT,j->vrange[k],eq,cs,IsGroundLink(j->linkID[k]),j->link[k]);
00960 
00961               for(i=0;i<3;i++)
00962                 {
00963                   SetEquationCmp(EQU,&(eq[i]));
00964                   SetEquationType(SYSTEM_EQ,&(eq[i]));
00965 
00966                   AddEquation2CS(p,&(eq[i]),cs);
00967                   DeleteEquation(&(eq[i]));
00968                 }
00969             }  
00970 
00971           if (j->t==UNV_JOINT)
00972             {
00973               /* The angles for a universal joint are defined from the two vectors
00974                  defining the two copunctual, orthogonal rotation axis towards the
00975                  two reference vectors given by the user.
00976                  The first angle is from the 1st reference vector to the second rotation vector.
00977                  The second angle is from the 2nd reference vector to the 1st rotation vector.
00978 
00979                  Above we defined variables for the two reference vectors. Below we
00980                  retrive the variable identifiers for the two vectors defining the
00981                  copunctual, orthogonal rotation axis (those variables are defined
00982                  in function GenerateJointEquationsInBranch.
00983               */
00984               for(k=2;k<4;k++)
00985                 {
00986                   for(i=0;i<3;i++)
00987                     {  
00988                       UNV_JOINT_VAR(vname,j->id,ln1,ln2,k-2,i);
00989                       jointVars[k][i]=GetCSVariableID(vname,cs);
00990                     }
00991                 }
00992               
00993               for(k=0;k<2;k++)
00994                 {
00995                   GenerateDotProductEquation(jointVars[3-k][0],jointVars[3-k][1],jointVars[3-k][2],
00996                                              jointVars[k][0],jointVars[k][1],jointVars[k][2],
00997                                              NO_UINT,0,&eq1);
00998                    
00999                   COS_VAR_UNI(vname,j->id,ln1,ln2,k);
01000                   NewVariable(SECONDARY_VAR,vname,&var);
01001                   if (k==0)
01002                     IntervalCosinus(&(j->range),&ic);
01003                   else
01004                     IntervalCosinus(&(j->range2),&ic);
01005                   SetVariableInterval(&ic,&var);
01006                   DeleteInterval(&ic);
01007                   id=AddVariable2CS(&var,cs);
01008                   DeleteVariable(&var);
01009                    
01010                   AddVariable2Monomial(id,1,&f);
01011                   AddCt2Monomial(-1,&f);
01012                   AddMonomial(&f,&eq1);
01013                   ResetMonomial(&f);
01014                    
01015                   SetEquationCmp(EQU,&eq1);
01016                   SetEquationType(SYSTEM_EQ,&eq1);
01017                   AddEquation2CS(p,&eq1,cs);
01018                   DeleteEquation(&eq1);
01019 
01020                   if (j->avoidLimits)
01021                     {
01022                       r=IntervalSize(&ic);
01023                       AddTerm2SearchCriterion(j->avoidLimitsWeight/(r*r),id,1,cs);
01024                     }
01025                 }
01026             }
01027           else
01028             {
01029               GenerateDotProductEquation(jointVars[0][0],jointVars[0][1],jointVars[0][2],
01030                                          jointVars[1][0],jointVars[1][1],jointVars[1][2],
01031                                          NO_UINT,0,&eq1);
01032               
01033               COS_VAR(vname,j->id,ln1,ln2);
01034               NewVariable(SECONDARY_VAR,vname,&var);
01035               IntervalCosinus(&(j->range),&ic);
01036               SetVariableInterval(&ic,&var);
01037               DeleteInterval(&ic);
01038               id=AddVariable2CS(&var,cs);
01039               DeleteVariable(&var);
01040               
01041               AddVariable2Monomial(id,1,&f);
01042               AddCt2Monomial(-1,&f);
01043               AddMonomial(&f,&eq1);
01044               ResetMonomial(&f);
01045               
01046               SetEquationCmp(EQU,&eq1);
01047               SetEquationType(SYSTEM_EQ,&eq1);
01048               AddEquation2CS(p,&eq1,cs);
01049               DeleteEquation(&eq1);
01050 
01051               if (j->avoidLimits)
01052                 {
01053                   r=IntervalSize(&ic);
01054                   AddTerm2SearchCriterion(j->avoidLimitsWeight/(r*r),id,1,cs);
01055                 }
01056             }
01057           
01058         }
01059       break;
01060 
01061     case SPH_SPH_JOINT:
01062       /*We assume non-constrained spherical-spherical joints*/
01063       break;
01064 
01065     case IN_PATCH_JOINT:
01066       /*In patch joints are limited by the 4 points defining the patch. These limits
01067         are implicitly given by the ranges for the control variables giving the patch. */
01068       if (j->avoidLimits)
01069         {
01070           IN_PATCH_JOINT_CTRL_VAR(vname,j->id,ln1,ln2,0);
01071           nv=GetCSVariableID(vname,cs);
01072           AddTerm2SearchCriterion(j->avoidLimitsWeight,nv,0.5,cs);
01073           
01074           IN_PATCH_JOINT_CTRL_VAR(vname,j->id,ln1,ln2,1);
01075           nv=GetCSVariableID(vname,cs);
01076           AddTerm2SearchCriterion(j->avoidLimitsWeight,nv,0.5,cs);
01077         }
01078       break;
01079     default:
01080       Error("Undefined joint type in GenerateJointRangeEquations");
01081     }
01082 
01083   DeleteInterval(&rangeOne);
01084   DeleteInterval(&rangeInf);
01085 
01086   free(vname);
01087   DeleteMonomial(&f);
01088 }
01089 
01090 void GenerateJointEquationsInBranch(double s,TCuikSystem *cs,Tequation *eq,Tjoint *j)
01091 {
01092 
01093   char *l1name,*l2name,*vname;
01094   unsigned int i,vID,d;
01095   Tmonomial f;
01096 
01097   l1name=GetLinkName(j->link[0]);
01098   l2name=GetLinkName(j->link[1]);
01099 
01100   switch (j->t)
01101     {
01102     case FREE_JOINT:
01103 
01104       NEW(vname,strlen(l1name)+strlen(l2name)+100,char);
01105       InitMonomial(&f);
01106       for(i=0;i<3;i++)
01107         {
01108           FREE_JOINT_VAR(vname,j->id,j->linkID[0],l1name,j->linkID[1],l2name,i);
01109           
01110           vID=GetCSVariableID(vname,cs);
01111           if (vID==NO_UINT)
01112             Error("Undefined FREE_JOINT variable in GenerateTransEquationsFromBranch");
01113       
01114           AddVariable2Monomial(vID,1,&f);
01115           AddCt2Monomial(s,&f);
01116           AddMonomial(&f,&(eq[i]));
01117           ResetMonomial(&f);
01118         }
01119       DeleteMonomial(&f);
01120       free(vname);
01121 
01122       break;
01123 
01124     case FIX_JOINT:
01125       /*The translation part of the homogeneous transform between the two links has
01126         been stored in points[0] (see NewFixJoint). We apply it here.
01127         The rotation constraints are imposed in GenerateJointEquations. */
01128       ApplyLinkRot( s,NO_UINT,j->points[0],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01129       break;
01130 
01131     case UNV_JOINT:
01132     case REV_JOINT:
01133     case SPH_JOINT:
01134       ApplyLinkRot( s,NO_UINT,j->points[0],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01135       ApplyLinkRot(-s,NO_UINT,j->points[2],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01136       break;
01137 
01138     case PRS_JOINT:
01139       ApplyLinkRot( s,NO_UINT,j->points[0],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01140                   
01141       NEW(vname,strlen(l1name)+strlen(l2name)+100,char);
01142       PRS_JOINT_VAR(vname,j->id,l1name,l2name);
01143       d=GetCSVariableID(vname,cs);
01144       free(vname);
01145       if (d==NO_UINT)
01146         Error("Undefined PRS_JOINT variable in GenerateTransEquationsFromBranch");
01147       
01148       ApplyLinkRot( s,d,j->normals[0],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01149 
01150       ApplyLinkRot(-s,NO_UINT,j->points[2],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01151       break;
01152 
01153     case SPH_SPH_JOINT:
01154       ApplyLinkRot( s,NO_UINT,j->points[0],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01155 
01156       NEW(vname,strlen(l1name)+strlen(l2name)+100,char);
01157       InitMonomial(&f);
01158       for(i=0;i<3;i++)
01159         { 
01160           SPH_SPH_JOINT_VAR(vname,j->id,l1name,l2name,i);
01161           
01162           vID=GetCSVariableID(vname,cs);
01163           if (vID==NO_UINT)
01164             Error("Undefined SPH_SPH_JOINT variable in GenerateTransEquationsFromBranch");
01165 
01166           AddVariable2Monomial(vID,1,&f);
01167           AddCt2Monomial(s*j->length,&f);
01168           AddMonomial(&f,&(eq[i]));
01169           ResetMonomial(&f);
01170         }
01171       DeleteMonomial(&f);
01172       free(vname);
01173 
01174       ApplyLinkRot(-s,NO_UINT,j->points[2],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01175       break;
01176      
01177     case IN_PATCH_JOINT:
01178       ApplyLinkRot( s,NO_UINT,j->points[0],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01179       ApplyLinkRot(-s,NO_UINT,j->points[2],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01180       
01181       NEW(vname,strlen(l1name)+strlen(l2name)+100,char);
01182       for(i=0;i<3;i++)
01183         {
01184           IN_PATCH_JOINT_CTRL_VAR(vname,j->id,l1name,l2name,i);
01185           vID=GetCSVariableID(vname,cs);
01186           if (vID==NO_UINT)
01187             Error("Undefined IN_PATCH_JOINT variable in GenerateTransEquationsFromBranch");
01188 
01189           ApplyLinkRot(-s,vID,j->points[3+i],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01190         }
01191       free(vname);
01192       break;
01193 
01194     default:
01195       Error("Unkownd joint type"); 
01196     }
01197 }
01198 
01199 void GenerateJointEquations(Tparameters *p,double maxCoord,
01200                             TCuikSystem *cs,Tjoint *j)
01201 {
01202   double v[3];
01203   unsigned int i,k;
01204   Tequation eq[3],eq1;
01205   char *ln1,*ln2,*vname;
01206   Tinterval rangeOne,rangeInf,rangeZeroOne;     
01207   Tmonomial f;
01208   unsigned int vID[3]; /* variables generated */
01209   unsigned int vIDuni[2][3]; /* for the universal joints 2 vectors are generated */
01210   unsigned int l; /*scale variable of the normal vectors in the patch joint*/
01211   Tvariable var;
01212 
01213   ln1=GetLinkName(j->link[0]);
01214   ln2=GetLinkName(j->link[1]);
01215 
01216   NEW(vname,strlen(ln1)+strlen(ln2)+100,char);
01217 
01218   NewInterval(-1,1,&rangeOne);
01219   NewInterval(0,1,&rangeZeroOne);
01220 
01221   InitMonomial(&f);
01222 
01223   switch(j->t)
01224     {
01225     case FREE_JOINT:
01226       NewInterval(-maxCoord,maxCoord,&rangeInf);
01227       for(i=0;i<3;i++)
01228         {
01229           FREE_JOINT_VAR(vname,j->id,j->linkID[0],ln1,j->linkID[1],ln2,i);
01230           
01231           NewVariable(SYSTEM_VAR,vname,&var);
01232           SetVariableInterval(&rangeInf,&var);
01233           AddVariable2CS(&var,cs);
01234               
01235           DeleteVariable(&var);
01236         }
01237       break;
01238 
01239     case FIX_JOINT: 
01240       /* link1 * transform = link2 * identity */
01241       /* link1 * transform - link2 * identity = 0 */
01242       for(i=0;i<3;i++)
01243         {    
01244           for(k=0;k<3;k++)
01245             InitEquation(&(eq[k]));
01246 
01247           for(k=0;k<3;k++)
01248             v[k]=HTransformGetElement(k,i,&(j->trs));
01249 
01250           ApplyLinkRot(1,NO_UINT,v,eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01251 
01252           v[0]=v[1]=v[2]=0;
01253           v[i]=1;
01254 
01255           ApplyLinkRot(-1,NO_UINT,v,eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01256           
01257           for(k=0;k<3;k++)
01258             {
01259               SetEquationType(SYSTEM_EQ,&(eq[k]));
01260               SetEquationCmp(EQU,&(eq[k]));
01261               AddEquation2CS(p,&(eq[k]),cs);
01262               DeleteEquation(&(eq[k])); 
01263             }
01264         }
01265       break;
01266 
01267     case PRS_JOINT:
01268       /* The three reference vectors (X,Y,Z) for the two links 
01269          are the same when transformed to global coordinates. */
01270       for(k=0;k<3;k++)
01271         InitEquation(&(eq[k]));
01272       
01273       for(i=0;i<3;i++)
01274         {
01275           v[0]=v[1]=v[2]=0.0;
01276           v[i]=1.0;
01277 
01278           for(k=0;k<3;k++)
01279             InitEquation(&(eq[k]));
01280           
01281           for(k=0;k<2;k++)
01282             ApplyLinkRot((k==0?+1.0:-1.0),NO_UINT,v,eq,cs,IsGroundLink(j->linkID[k]),j->link[k]);
01283 
01284           for(k=0;k<3;k++)
01285             {
01286               SetEquationType(SYSTEM_EQ,&(eq[k]));
01287               SetEquationCmp(EQU,&(eq[k]));
01288               AddEquation2CS(p,&(eq[k]),cs);
01289               DeleteEquation(&(eq[k])); 
01290             }
01291         }
01292       break;
01293       
01294     case REV_JOINT:
01295       /* The vector defining the rotation axis is the same as seen from the two links. */
01296       for(k=0;k<3;k++)
01297         InitEquation(&(eq[k]));
01298 
01299       for(k=0;k<2;k++) /* for the two links involved in the joint */
01300         ApplyLinkRot((k==0?+1.0:-1.0),NO_UINT,j->normals[k],eq,cs,IsGroundLink(j->linkID[k]),j->link[k]);
01301 
01302       for(k=0;k<3;k++)
01303         {
01304           SetEquationType(SYSTEM_EQ,&(eq[k]));
01305           SetEquationCmp(EQU,&(eq[k]));
01306           AddEquation2CS(p,&(eq[k]),cs);
01307           DeleteEquation(&(eq[k])); 
01308         }
01309       break;
01310 
01311     case UNV_JOINT:
01312       /* Two vectors one attached to link1 and another attached to link2 */
01313       for(i=0;i<2;i++)
01314         {
01315           for(k=0;k<3;k++)
01316             InitEquation(&(eq[k]));
01317 
01318           ApplyLinkRot(1,NO_UINT,j->normals[i],eq,cs,IsGroundLink(j->linkID[i]),j->link[i]);
01319 
01320           for(k=0;k<3;k++)
01321             {
01322               UNV_JOINT_VAR(vname,j->id,ln1,ln2,i,k);
01323               
01324               NewVariable(SECONDARY_VAR,vname,&var);
01325               SetVariableInterval(&rangeOne,&var);
01326               
01327               vIDuni[i][k]=AddVariable2CS(&var,cs);
01328               
01329               DeleteVariable(&var);
01330 
01331               AddCt2Monomial(-1.0,&f);
01332               AddVariable2Monomial(vIDuni[i][k],1,&f);
01333               AddMonomial(&f,&(eq[k]));
01334               ResetMonomial(&f);
01335 
01336               SetEquationType(SYSTEM_EQ,&(eq[k]));
01337               SetEquationCmp(EQU,&(eq[k]));
01338               AddEquation2CS(p,&(eq[k]),cs);
01339               DeleteEquation(&(eq[k])); 
01340             }
01341           
01342         }
01343 
01344       /* the two vectors must be orthogonal */
01345       GenerateDotProductEquation(vIDuni[0][0],vIDuni[0][1],vIDuni[0][2],
01346                                  vIDuni[1][0],vIDuni[1][1],vIDuni[1][2],
01347                                  NO_UINT,0,&eq1);
01348       AddEquation2CS(p,&eq1,cs);
01349       DeleteEquation(&eq1);
01350       break;
01351 
01352     case SPH_JOINT:
01353       /*spherical joints introduce no joint equations (all the constraints of
01354         a spherical joint are in the loop equations.*/
01355       break;
01356 
01357     case SPH_SPH_JOINT:
01358       /* We define a  vector (with norm 1) along the sph-sph axis. These variables are
01359          later used in the loops. */
01360       for(i=0;i<3;i++)
01361         {
01362           SPH_SPH_JOINT_VAR(vname,j->id,ln1,ln2,i);  
01363           
01364           NewVariable(SYSTEM_VAR,vname,&var);
01365           SetVariableInterval(&rangeOne,&var);
01366           
01367           vID[i]=AddVariable2CS(&var,cs);
01368           
01369           DeleteVariable(&var);
01370         }
01371       GenerateNormEquation(vID[0],vID[1],vID[2],1.0,&eq1);
01372       AddEquation2CS(p,&eq1,cs);
01373       DeleteEquation(&eq1); 
01374 
01375       break;
01376 
01377     case IN_PATCH_JOINT:
01378       for(i=0;i<3;i++)
01379         {
01380           IN_PATCH_JOINT_CTRL_VAR(vname,j->id,ln1,ln2,i);
01381 
01382           NewVariable((i<2?SYSTEM_VAR:DUMMY_VAR),vname,&var);
01383           SetVariableInterval(&rangeZeroOne,&var);
01384 
01385           vID[i]=AddVariable2CS(&var,cs);
01386 
01387           DeleteVariable(&var);
01388         }
01389 
01390       GenerateSaddleEquation(vID[0],vID[1],vID[2],&eq1);
01391       AddEquation2CS(p,&eq1,cs);
01392       DeleteEquation(&eq1);
01393       
01394       for(k=0;k<3;k++)
01395         InitEquation(&(eq[k]));
01396       
01397       IN_PATCH_JOINT_SCALE_VAR(vname,j->id,ln1,ln2);
01398 
01399       NewVariable(SYSTEM_VAR,vname,&var);
01400       SetVariableInterval(&(j->normRange),&var);
01401       l=AddVariable2CS(&var,cs);
01402       DeleteVariable(&var);
01403 
01404       ApplyLinkRot( 1,l,j->points[1],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01405 
01406       ApplyLinkRot(-1,NO_UINT,j->normals[0],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01407       ApplyLinkRot(-1, vID[0],j->normals[1],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01408       ApplyLinkRot(-1, vID[1],j->normals[2],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01409 
01410       for(k=0;k<3;k++)
01411         {
01412           SetEquationType(SYSTEM_EQ,&(eq[k]));
01413           SetEquationCmp(EQU,&(eq[k]));
01414           AddEquation2CS(p,&(eq[k]),cs);
01415           DeleteEquation(&(eq[k])); 
01416         }
01417 
01418       break;
01419 
01420     default:
01421       Error("Unknown joint type in GenerateJointEquations");
01422     }
01423 
01424   free(vname);
01425   DeleteInterval(&rangeOne);
01426   DeleteMonomial(&f);
01427 }
01428 
01429 
01430 void RegenerateJointSolution(TCuikSystem *cs,double *sol,Tjoint *j)
01431 {
01432   unsigned int i;
01433   unsigned int vID[3];
01434   char *vname,*ln1,*ln2;
01435 
01436   ln1=GetLinkName(j->link[0]);
01437   ln2=GetLinkName(j->link[1]);
01438 
01439   NEW(vname,strlen(ln1)+strlen(ln2)+100,char);
01440 
01441   switch(j->t)
01442     {
01443       case IN_PATCH_JOINT:
01444         for(i=0;i<3;i++)
01445           {
01446             IN_PATCH_JOINT_CTRL_VAR(vname,j->id,ln1,ln2,i);
01447             vID[i]=GetCSVariableID(vname,cs);
01448           }
01449         
01450         sol[vID[2]]=sol[vID[0]]*sol[vID[1]];
01451 
01452         break;
01453     }
01454 
01455   free(vname);
01456 }
01457 
01458 double GetJointMaxCoordinate(Tjoint *j)
01459 {
01460   double mc;
01461 
01462   switch(j->t)
01463     {
01464     case SPH_SPH_JOINT:
01465       mc=j->length;
01466       break;
01467     case PRS_JOINT:
01468       {
01469         double l,u;
01470 
01471         l=fabs(LowerLimit(&(j->range)));
01472         u=fabs(UpperLimit(&(j->range)));
01473         mc=(l>u?l:u);
01474       }
01475       break;
01476     default:
01477       mc=0.0;
01478     }
01479 
01480   return(mc);
01481 }
01482 
01483 void PlotJoint(Tplot3d *pt,Tjoint *j)
01484 {
01485   if ((j->t==SPH_SPH_JOINT)&&
01486       (j->rad>0)) /*sph_slj joints with 0 radius are hidden (used in fix joints)*/
01487     {
01488       double zero[3]={0,0,0};
01489       double end[3]={0,0,0};
01490       
01491       end[0]=j->length;
01492 
01493       j->obj3d=StartNew3dObject(&(j->color),pt);
01494       PlotSphere(j->rad*1.5,0,0,0,pt);
01495       PlotCylinder(j->rad,zero,end,pt);
01496       PlotSphere(j->rad*1.5,end[0],end[1],end[2],pt);
01497       Close3dObject(pt);
01498     }
01499 }
01500 
01501 void MoveJoint(Tplot3d *pt,TCuikSystem *cs,double *sol,
01502                double **r,Tjoint *j)
01503 {
01504   if (j->t==SPH_SPH_JOINT)
01505     {
01506       THTransform t;
01507       double p[2][3];
01508       unsigned int k,i;
01509       double d,n;
01510 
01511       /*We use the anchor points of the spherical-spherical composite
01512         joint to the links to define the rotation/translation of the
01513         X aligned cylinder generated in PlotJoint */
01514       for(k=0;k<2;k++)
01515         {
01516           GetTransform2Link(cs,sol,IsGroundLink(j->linkID[k]),r[j->linkID[k]],
01517                             &t,j->link[k]);
01518           
01519           for(i=0;i<3;i++)
01520             HTransformApply(j->points[2*k],p[k],&t);
01521           
01522           HTransformDelete(&t);
01523         }
01524       /*normalize the distance between p0 and p1 so that no deformation is produced
01525         in the X axis of the cylinder (the length is already set when plotting) */
01526       n=0;
01527       for(k=0;k<3;k++)
01528         {
01529           d=p[1][k]-p[0][k];
01530           n+=(d*d);
01531         }
01532       n=sqrt(n);
01533 
01534       for(k=0;k<3;k++)
01535         p[1][k]=p[0][k]+(p[1][k]-p[0][k])/n;
01536 
01537       HTransformX2Vect(1,1,p[0],p[1],&t);
01538       
01539       Move3dObject(j->obj3d,&t,pt);
01540       
01541       HTransformDelete(&t);
01542     }
01543 }
01544 
01545 void DeleteJoint(Tjoint *j)
01546 {
01547   DeleteInterval(&(j->range));  
01548   DeleteInterval(&(j->range2));  
01549   HTransformDelete(&(j->trs));
01550 }