Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

lukaskins.c

Go to the documentation of this file.
00001 /*
00002   lukaskins.c
00003 
00004   Modification history:
00005 
00006   15-May-2001  FMP changed kinematicsType to KINEMATICS_BOTH
00007   4-May-2001  FMP fixed undef's, which were defs
00008   16-Apr-2001  FMP created from Lukas du Plessis' figure
00009   */
00010 
00011 /*
00012   These kinematics are for Lukas du Plessis' planar parallel mechanism:
00013 
00014        A--------B
00015       / \        \       ^
00016      /   \        \      |
00017     /     \        \     y
00018    /       \        \    |
00019   C---------D--------E   +-- x -->
00020 
00021   where C is the origin;
00022   the x and y directions are to the left and up, respectively, and z is
00023   out of the page;
00024   AC, AD, and BE are struts whose length can be controlled;
00025   C, D, and E are fixed points; and
00026   AB is a fixed-length strut.
00027 
00028   The kinematics use variables named from the figure, where single capital
00029   letters indicate vertex points (e.g., A, B); single capital letters
00030   followed by lowercase x or y indicate the x or y coordinate of the vertex
00031   point, respectively, with respect to the origin C; double capital letters
00032   indicate the length of sides (e.g., AB, BE); and triple lowercase letters
00033   indicate angles (e.g., bae, the angle between BA and AC).
00034 
00035   Changing the lengths of AC, AD, and BE result in points A and B moving
00036   about. Point B is the controlled point, and the three Cartesian variables
00037   are Bx, By, and the angle of AB relative to the horizontal (x) axis,
00038   called theta. This is the angle of rotation of B about the z axis,
00039   In the above figure theta (not labeled) is 0.
00040 
00041   The arguments to the kinematics functions are named "pos" for the 
00042   Cartesian EmcPose type, and "joints" for the joint (strut length) array.
00043   The association between these names and names from the figure are:
00044 
00045   pos->tran.x = Bx
00046   pos->tran.y = By
00047   pos->c      = theta
00048 
00049   The inverse kinematics have no singularities. Any values for Bx, By, and
00050   theta will yield numerical results. Of course, these may be beyond the
00051   strut length limits, but there are no singular effects like infinite speed.
00052 
00053   The forward kinematics have two singularities. The first occurs when
00054   struts AC and AD are not long enough to span base length CD and the
00055   triangle inquality is violated. The second occurs when struts AB and BE
00056   are not long enough to span the distance between points A and E.
00057 
00058   The forward kinematics flags, referred to in kinematicsForward and
00059   set in kinematicsInverse, let the forward kinematics select between
00060   multiple valid solutions of B and theta for a given set of strut
00061   values. The two types of solutions correspond to
00062 
00063   a) "head" point A is above (as in figure) or below x axis;
00064   b) "elbow" point B is up (as in figure) or down.
00065 
00066   Bit 0 of fflags selects between (a), with 0 = above, 1 = below;
00067   bit 1 of fflags selects between (b), with 0 = up, 1 = down.
00068 
00069   The inverse kinematics flags let the inverse kinematics select between
00070   multiple valid solutions of strut lengths for given Cartesian values
00071   for B and theta. There are no multiple solutions: B and theta constrain
00072   the strut lengths completely. So, the inverse flags are ignored.
00073  */
00074 
00075 #include "emcmot.h"             /* these decls */
00076 #include <math.h>
00077 
00078 /* ident tag */
00079 #ifndef __GNUC__
00080 #ifndef __attribute__
00081 #define __attribute__(x)
00082 #endif
00083 #endif
00084 
00085 /* define the constant strut lengths here */
00086 #define CD 10.0
00087 #define DE 4.0
00088 #define AB 8.7
00089 
00090 #define sq(x) ((x)*(x))
00091 
00092 /*
00093   forward kinematics takes three strut lengths and computes Bx, By,
00094   and theta, as pos->tran.x,y, and pos->c, respectively. The forward
00095   flags are used to resolve head above/below and elbow up/down. The
00096   inverse flags are not set since there are no ambiguities going from
00097   world to joint coordinates.
00098 */
00099 int kinematicsForward(const double * joints,
00100                       EmcPose * pos,
00101                       const KINEMATICS_FORWARD_FLAGS * fflags,
00102                       KINEMATICS_INVERSE_FLAGS * iflags)
00103 {
00104 #define AC (joints[0])
00105 #define AD (joints[1])
00106 #define BE (joints[2])
00107 #define Bx (pos->tran.x)
00108 #define By (pos->tran.y)
00109 #define theta (pos->c)
00110   double temp;
00111   double CE;
00112   double AE;
00113   double Ax, Ay;
00114   double bae;
00115   double aec;
00116 
00117   Ax = (sq(AC) + sq(CD) - sq(AD)) / (2.0 * CD);
00118   temp = sq(AC) - sq(Ax);
00119   if (temp < 0.0) {
00120     return -1;
00121   }
00122   Ay = sqrt(temp);
00123   if (*fflags % 2) {
00124     Ay = -Ay;                   /* head below */
00125   }
00126 
00127   CE = CD + DE;
00128   AE = sqrt(sq(Ay) + sq(CE - Ax));
00129   temp = (sq(AB) + sq(AE) - sq(BE)) / (2.0 * AB * AE);
00130   if (temp < -1.0 ||
00131       temp > +1.0) {
00132     return -1;
00133   }
00134   bae = acos(temp);
00135   if ((*fflags >> 1) % 2) {
00136     bae = -bae;                 /* elbow down */
00137   }
00138   /* else elbow up */
00139   aec = atan2(Ay, CE - Ax);
00140   theta = bae - aec;
00141   Bx = Ax + AB * cos(theta);
00142   By = Ay + AB * sin(theta);
00143 
00144   /* pos->tran.x,y are Bx, By resp.; pos->c is theta; they're
00145      already done via #define, so no assignment necessary. We'll
00146      set the others to 0. */
00147   pos->tran.z = 0.0;
00148   pos->a = 0.0;
00149   pos->b = 0.0;
00150 
00151   return 0;
00152 
00153 #undef AC
00154 #undef AD
00155 #undef BE
00156 #undef Bx
00157 #undef By
00158 #undef theta
00159 }
00160 
00161 int kinematicsInverse(const EmcPose * pos,
00162                       double * joints,
00163                       const KINEMATICS_INVERSE_FLAGS * iflags,
00164                       KINEMATICS_FORWARD_FLAGS * fflags)
00165 {
00166 #define AC (joints[0])
00167 #define AD (joints[1])
00168 #define BE (joints[2])
00169 #define Bx (pos->tran.x)
00170 #define By (pos->tran.y)
00171 #define theta (pos->c)
00172   double CE;
00173   double Ax;
00174   double Ay;
00175 
00176   CE = CD + DE;
00177   BE = sqrt(sq(Bx - CE) + sq(By));
00178   Ax = Bx - AB * cos(theta);
00179   Ay = By - AB * sin(theta);
00180   AC = sqrt(sq(Ax) + sq(Ay));
00181   AD = sqrt(sq(CD - Ax) + sq(Ay));
00182 
00183   /* AC, AD, and BE are joints[0,1,2], resp.; they're already 
00184      done via #define, so no assignment necessary */
00185 
00186   /* set fflags to appropriately for given B and theta */
00187   *fflags = 0;
00188   if (Ay < 0.0) {
00189     *fflags = 1;                /* head below */
00190   }
00191   /* use sign of cross product EB X BA for elbow; positive is
00192      elbow up */
00193   if ((Bx - CE) * (Ay - By) - By * (Ax - Bx) < 0.0) {
00194     *fflags += 2;
00195   }
00196     
00197   return 0;
00198 
00199 #undef AC
00200 #undef AD
00201 #undef BE
00202 #undef Bx
00203 #undef By
00204 #undef theta
00205 }
00206 
00207 /* the inverse kinematics have no singularities, so kinematicsHome gives
00208    the world position preferences, and fills in the joint values */
00209 int kinematicsHome(EmcPose * world,
00210                    double * joint,
00211                    KINEMATICS_FORWARD_FLAGS * fflags,
00212                    KINEMATICS_INVERSE_FLAGS * iflags)
00213 {
00214   *fflags = 0;
00215   *iflags = 0;
00216 
00217   return kinematicsInverse(world, joint, iflags, fflags);
00218 }
00219 
00220 KINEMATICS_TYPE kinematicsType()
00221 {
00222   return KINEMATICS_BOTH;
00223 }

Generated on Sun Dec 2 15:27:41 2001 for EMC by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001