coordSys - coordinate system manipulation library

NAME

BaseCS, Quat2CS, RotAxisCS, RotAngleCS, TransVectCS, TransCS, RotCS, TransRotCS, AlignZCS, AlignXCS, AlignYCS, ChainCS, InverseCS, RelativeCS, IsValidCS, IsInvalidCS, IsEqualCS, InvalidCS, PrintCS, FprintCS, ScanCS, FscanCS, SetPrintFormatCS, PrintQuatCS, FprintQuatCS, ScanQuatCS, FscanQuatCS, ConsGFSetCS, InsInGFSetCS, SetXAxisLengthCS, SetYAxisLengthCS, SetZAxisLengthCS,

SYNOPSIS

t_CS    BaseCS(void);       

t_V3d   RotAxisCS(t_CS cs);     
double  RotAngleCS(t_CS cs);   
t_V3d   TransVectCS(t_CS cs); 

t_CS    TransCS(t_CS cs, t_V3d trans); 
t_CS    RotCS(t_CS cs, t_V3d axis, double angle ); 
t_CS    TransRotCS(t_CS cs, t_V3d v, t_V3d axis, float angle); 

t_CS    AlignZCS(t_CS cs, t_V3d dir); 
t_CS    AlignXCS(t_CS cs, t_V3d dir);  
t_CS    AlignYCS(t_CS cs, t_V3d dir); 

t_CS    ChainCS(t_CS cs, t_CS cs2); 
t_CS    InverseCS(t_CS cs1);  
t_CS    RelativeCS(t_CS cs, t_CS cs2); 

int     IsValidCS(t_CS cs); 
int     IsInvalidCS(t_CS cs); 	 
int     IsEqualCS(t_CS cs1, t_CS cs2); 
t_CS    InvalidCS(void); 

void    PrintCS(t_CS cs);	 
void    FprintCS(t_CS cs, FILE *f); 
t_CS    ScanCS(void); 
t_CS    FscanCS(FILE * f); 
void    SetPrintFormatCS(char *); 

void    PrintQuatCS(t_CS cs); 
void    FprintQuatCS(t_CS cs, FILE * f); 
t_CS    ScanQuatCS(void);		      
t_CS    FscanQuatCS(FILE * f);	 

t_LLSet ConsGFSetCS(char * setName); 
void    InsInGFSetCS(t_CS cs, t_LLSet set); 
void    SetXAxisLengthCS(double len); 
void    SetYAxisLengthCS(double len); 
void    SetZAxisLengthCS(double len); 


DESCRIPTION

Introduction and overview.

The 'coordSys' library provides a set of function for manipulating coordinate systems in three-dimensional space. Poses in 3D space are expressed in terms of translations and rotations of coordinate systems. The coordinate system library can be used to compute and represent positions and orientations passed to a robot controller, to compute desired vantage points for a camera, to represent relative and absolute positions of objects etc.

The library defines a base (world ) coordinate system which is obtained by calling the BaseCS function. New coordinate systems (c-systems) are defined by translating (shifting) and/or rotating an existing c-system; The first user-defined c-system is a translation/rotation of the base system, eg.:

  t_CS cs1 = TransCS(BaseCS(),ConsV3d(1,1,0)); 

which creates a new coordinate system, translated in the xy-plane by (1,1). The axes of the system are parallel to base c-system's axes. From now-on new c-system can be defined relative to the 'cs1' c-systems:

  t_CS cs2 = TransCS(cs1,ConsV3d(0,0,2)); 
  t_CS cs3 = TransCS(BaseCS(),ConsV3d(1,1,2));   

Taking into account the definition of 'cs1', 'cs2' and 'cs3' define identical c-systems (such identities are tested by a call to IsEqualCS).

Translations and rotations are always defined in the c-system that is being transformed. In the example above we do not have to worry about this distinction because axes of 'cs1' and the base cs are parallel. After any rotation care must be taken:

  t_CS cs1 = RotCS(BaseCS(),ConsV3d(0,0,1), 45.0/180*V3PI); 
  t_CS cs1 = TransCS(cs1,ConsV3d(1,0,0); 
Rotation is defined by an axis of rotation an angle of rotation; the first command defines 'cs1' as rotated by 45 degrees (anti-clockwise) around z-axis (vector 0,0,1). The translation along the x-axis of 'cs1' corresponds to translation (sqrt(2)/2, sqrt(2)/2, 0) of the base c-system.

Defining coordinate systems. Transformations (reference).

BaseCS() returns the base (world )coordinate system. See Introduction and example 'exCircle' for typical use.

TransCS(cs,v) creates a new coordinate system translated by 'v' with respect to 'cs'. RotCS(cs,axis,a) creates a new coordinate system by rotating 'cs' about 'axis' by angle 'a' in radians. If the angle is not zero 'axis' must not be (close to) (0,0,0). In this case RotCS returns the 'invalid c-system' (see Error Handling section below). Both translation and rotation can be performed by a single call to TransRotCS(cs,v,axis,a) which is identical to peforming the translation and rotation sequentially.

The three functions AlignXCS(cs,dir), AlignYCS(cs,dir) and AlignZCS(cs,dir) specify rotations in the following way: The returned rotated 'cs_out' system has its x-axis (in the case of AlignXCS) aligned with direction 'dir' of 'cs'. The operation is implemented by rotating 'cs' around an axis of rotation perpendicular to both 'dir' and the axis that is being aligned.

Pose with respect to Base.

TransVectCS(cs) return the position of the origin of 'cs' with respect to base cs. Distance between origins (ie. positions) of two c_system is:

    MagnV3d(DiffV3d(TransVectCS(cs1),TransVectCS(cs2))); 

Functions RotAxisCS(cs) and RotAngleCS(cs) determine the axis and angle of rotation that the base cs must undergo to become cs.

Miscellanous

ChainCS(cs1,cs2) applies the transformation defined by 'cs2' on 'cs1'. Note that the operation is not commutative. RelativeCS(cs1,cs2) returns a c-system that would transform cs1 into cs2. Therefore

  cs2  ==  RelativeCS(cs,ChainsSC(cs,cs2); 

where the '==' should be read as 'equal up to the precision of floationg point calculations'. In example 'exCircle', RelavtiveCS() is part of the calculation to point an axis of a c-system towards the origin of another c-system.

IsEqualCS(cs1,cs2) test whether two coordinate system are identical. Note that two c-systems that can by shown algebraicly to be identical may fail this test due to finite precision of floating point numbers. The problem can be avoided by computing the transformation between the two sytems using the RelativeCS() function and then testing the magnitude of the translation vector and the rotation angle.

External Representation. Input and Output Functions.

Variables of the c-system type can be stored and read in from text files using the print/scan family of functions. Externally, the c-system is represented in the following form:

      CS as trans: 1 2 3   axis: 1 -2  1 angle:  0.7775 

Fprint(cs,f) writes c-system 'cs' to file 'f'. Print(cs) writes to standard output. Fscanf(f) returns a c-system object read from file f. Scanf() returns a c-system object read from standard input. Fscanf and Scanf return the 'invalid' c-system on failure, ie. when the file does not contain correctly formatted data, was not opened for reading etc. The .cs file can contain:

  - blank lines 
  - comment lines starting with '#'  
  - lines with c-system definitions.  

Lines with c-system definitions can contain arbitrary text after c-system specification. Whitespace characters are ignored, but the 'CS as trans:', axis:', 'angle:' must be present as shown in the examples (the scanning fucntions are case-sensitive). An example '.cs' file may look like:

#----- Marker  position for BoX_1 
#  all c-system are relative to base 
#  orientations express surface normals at the marker 
#  date: 1-Feb 
CS as trans: 1.2 3.1 3   axis: 0 0 1 angle:  1.57    # top  
CS as trans: 2   2.1 4   axis: 1 0 0 angle:  0.23    # white spot  

A '.cs' file is read in as follows:

    while(IsValidCS(cs=ScanCS())) 
    {        /* fails if  a/ nothing else on input  
             /*		  b/ incorrect format of CS data  
       /*--------  process cs here ----------  */ 
    } 

Functions PrintQuatCS(cs), FPrintQuatCS(cs, f), ScanQuatCS(), FscanQuatCS(f) work analogically to their conterparts for manipulation of '.cs' files but the output is stored as a quaternion pair. These functions should be used for debugging purposes or when the output of the library is intented for use with a similar packages requiring quaternion input.

Visualisation. GF output.

Functions ConsGFSetCS(setName) and InsInGFSetCS(cs,set) facilitate creation of '.gf' files. ConsGFSetCS(setName) creates a new 'gf' set. A c-system represented as its three basis vectors is appended to the set with each call to InsInGFSetCS(cs,set). The x,y,z axis are stored as 'colored 3D lines' with r,g,b colours respectively. The length of the lines can be set by the SetXAxisLengthCS(), SetYAxisLengthCS, SetZAxisLengthCS family of functions. The default is 1.0. The feature is useful if one of the axis of the c-system represents a look-direction. The set is written by a call to WriteLLSet(fName,set). If any of the functions above is called, than the 'gfLL.h' header file must be included before 'coordSys.h' and the the following libs must be linked in: libgfLL.a, libLL.a, libstrGM.a . The prototypes of the .gf functions are visible to the compiler only if the 'gfLL.h' header file is included before 'coordSys.h'. This arrangement makes sure that users who do not intend to use '.gf' functions do not have to link (and know about) the libraries listed in this paragraph.

The '.gf' representation of c-system can be analysed by the 3D visualisation package 'Xmgf'. A '.gf' file is created in the 'cs2gf' example. In general we recommend programs output information about c-systems in the '.cs' format and then use the 'cs2gf' tool to covnvert the output into the .gf format.

Error handling.

Failure of any operation of the library is indicated by returning an 'invalid' c-system object. The invalid c-system object plays the role the NULL pointer has in pointer operations. The NULL pointer is guaranteed not to point to any object; the internal quaternion representation of the invalid c-system object does not correspond to any translation and rotation.

Rotations (RotCS) fail if axis of rotation is incorrectly specified. Input and output operations may fail for a number of reasons. Functions IsValidCS(cs) and IsInvalidCS(cs) should be used to test return values, as shown in an example in the 'External Representation' section.

The 'invalid c-system' is obtained by a call to InvalidCS(). Users may therefore write functions returning c-system objects and indicate errors encountered during computation using error-handling mechanism of the library, eg. :

     if(some_error_occured) return InvalidCS(); 

Example exCircle.c

We present the source code of the example without further description. We attempted to place comments in the source to make it self-explanatory.


/*--------------------------------------------------------------------------*/ 
/* Author:  George (Jiri) Matas                     g.matas@ee.surrey.ac.uk 
            Pavel Andris,                           utrrandr@savba.sk       */ 
/*--------------------------------------------------------------------------*/ 
static char sccsid[]="@(#)exCircle.c	1.4	95/02/06 g.matas@ee.surrey.ac.uk"; 
   typedef char _s_foo[sizeof(sccsid)];/*stop gcc warning: unused var sccsid*/ 


/*--------------------------------------------------------------------------*/ 
/* Description: 
    generates a number of coordinate systems on circle. Each of the 
    c-systems points with its Z-axis towards the same 'look point'. 
    Most parametrs, eg. number of points on the circle, center and 
    radius of the circle, the 'look point' etc. can be defined on 
    the command line. 


    The c-system are output to .cs file. 


    More generally, the  example shows how to place c-system (eg. associated 
    with a camera) along an arbitrary trajectory with it Z-axis 
    (optical axis in the case of camera) pointing to a fixed 'look point' 
*/ 
/*--------------------------------------------------------------------------*/ 


#include "coordSys.h" 
#include "optionGM.h" 
#include <math.h> 


int main(int argc, char **argv)  
{  
  OptionInit(argv,&argc);                  /* see optionGM man page */ 
  {  
    t_V3d cenT = ConsV3d(0,0,0);  
		   /* default: circle center = base c-system origin */ 
    t_V3d look;    /* look point */ 


    char * out_file = OptionStr("o","-", ".gf file (output)");  
    double radius   = OptionDouble("r",1.0, "radius of the circle");  
    int    pts      = OptionInt("pts",8, "num. of points on circle");  


    OptionDoubleArr("cen",(double*)&cenT,3,"circle center");  


    look = cenT;                 /* default: look at the circle center */ 
    OptionDoubleArr("lp",(double*)&look,3,"look point for cs's on circle");  


    OptionCheck();  


    { 
      FILE * f = (out_file[0]=='-') ? stdout : fopen(out_file,"w");  
			            /* open .cs file, "-" is stdout */  
			   
      t_CS  cenCS  = TransCS(BaseCS(),cenT);  /* c-sytem of the circle center */ 
      t_CS  lookCS = TransCS(BaseCS(),look);  /* c-sytem of the loop point */ 
      int i; 


      if(NULL == f)  
        {fprintf(stderr,"can't open file: %s!\n",out_file);exit(1);} 


      cenCS = AlignZCS(cenCS,ScalV3d(cenT,-1)); 
               /* Point the Z-axis of circle center c-system at the origin */ 
               /* the circle is generated in a plane perpendicular         */ 
	       /* to this direction  */ 


      for(i=0;i<pts;i++) 
      { 
	double c     = cos(i/(double)pts * 2*V3PI); 
	double s     = sin(i/(double)pts * 2*V3PI);    
	t_CS  viewCS = TransCS(cenCS,ConsV3d(radius*c,radius*s,0)); 
		  /* generate point on circle                            */ 
		  /* change these lines if different trajectory required */ 


        t_CS  toLook = RelativeCS(viewCS,lookCS); 
	viewCS = AlignZCS(viewCS,TransVectCS(toLook));  
	    /* to make sure that  an arbitrary  point lies on a Z-axis    */ 
	    /* of 'viewCS' c-system we must get the point position in the */ 
	    /* c-system. RelativeCS does just that.                       */ 
            /* Then align the Z-axis using point posit. as  direction for */ 
	    /* the AlignZCS function */ 
		 
	FprintCS(viewCS,f);        /* save to file */ 
      } 
    } 
  } 
  return 0; 
} 
/*--------------------------------------------------------------------------*/ 

Example exTraject.c

Similar to the 'exCircle' example but positions of the c-systems are read from a file which is generated off-line. Sparsly commented; if in doubt, read the comments in exCircle.c.


/*--------------------------------------------------------------------------*/  
/* Author:  George (Jiri) Matas                     g.matas@ee.surrey.ac.uk */  
/*--------------------------------------------------------------------------*/  
static char sccsid[]="@(#)exTraject.c	1.1	95/02/06 g.matas@ee.surrey.ac.uk";  
typedef char _s_foo[sizeof(sccsid)]; /*stop gcc warning: unused var sccsid*/  


#include "coordSys.h" 
#include "optionGM.h"  
#include <math.h>  


/* 
  Description: move a c-system along a trajectory specified in a file.  
     Keep looking with Z-axis at the look point (see option).  
  For more, see exCircle.c 
*/ 


int main(int argc, char **argv) 
{  
  OptionInit(argv,&argc);                  /* see optionGM man page */ 
  {  
    t_V3d look = ConsV3d(0,0,0);                      /* look point */ 
    char * in_file =  OptionStr("i",NULL, "file with trajectory");  
    char * out_file = OptionStr("o","-",  ".cs file (output)");  


    OptionDoubleArr("lp",(double*)&look,3,"look point for cs's on circle");  


    OptionCompulsory("i"); 
    OptionCheck();  


    { 
      t_V3d view;                             /* viewpoint */ 
      t_CS  lookCS = TransCS(BaseCS(),look);  /* c-sytem of the loop point */ 


      FILE * f = (out_file[0]=='-') ? stdout : fopen(out_file,"w");  
      FILE * fi= ( in_file[0]=='-') ? stdin  : fopen(in_file,"r");  


      if(NULL==f ) {fprintf(stderr,"can't open file: %s!\n",out_file);exit(1);} 
      if(NULL==fi) {fprintf(stderr,"can't open file: %s!\n", in_file);exit(1);} 


      while(3 == fscanf(fi,"%lf %lf %lf",&view.x,&view.y,&view.z)) 
      { 
	t_CS  viewCS = TransCS(BaseCS(),view); 


        t_CS  toLook = RelativeCS(viewCS,lookCS); 
	viewCS = AlignZCS(viewCS,TransVectCS(toLook));  
		 
	FprintCS(viewCS,f);  
      } 
    } 
  } 
  return 0; 
} 
/*--------------------------------------------------------------------------*/ 

Example cs2gf.c


/*------------------------------------------------------------------------- */ 
/*  author: George (Jiri) Matas                     g.matas@ee.surrey.ac.uk */ 
/*--------------------------------------------------------------------------*/ 
static char sccsid[]="@(#)cs2gf.c	2.2	95/02/05 g.matas@ee.surrey.ac.uk"; 
   typedef char _s_foo[sizeof(sccsid)];/*stop gcc warning: unused var sccsid*/  


#include "gfLL.h" 
#include "coordSys.h" 
#include "optionGM.h" 


int main(int argc, char **argv)  
{  
  OptionInit(argv,&argc);  
  {  
    char * inp_file = OptionStr("i",NULL,".cs file (input)");  
    char * out_file = OptionStr("o","-", ".gf file (output)");  
    char * set_name = OptionStr("s","CoordSys", "gf set name ");  


    double xLen =     OptionDouble("x",1.0, "length of x-axis");    
    double yLen =     OptionDouble("y",1.0, "length of y-axis");  
    double zLen =     OptionDouble("z",1.0, "length of z-axis");  


    OptionCompulsory("i"); 
    OptionCheck(); 


    { 
      t_LLSet gfSet =  ConsGFSetCS(set_name); 
      t_CS cs; 
      FILE * f = (inp_file[0]=='-') ? stdin : fopen(inp_file,"r"); 


      if(NULL == f) 
        {fprintf(stderr,"can't open file: %s!\n",inp_file);exit(1);} 


      SetXAxisLengthCS(xLen); 
      SetYAxisLengthCS(yLen); 
      SetZAxisLengthCS(zLen); 


      while(IsValidCS(cs = FscanCS(f))) 
        InsInGFSetCS(cs,gfSet); 
     
      WriteLLSet(out_file,gfSet); 
    } 
  } 
  return 0; 
} 

Implementation. Possible Extensions.

Internally, each coordinate system is implemented as a quaternion pair. Users should not access the internal quaternion structure as it is not guaranted to remain unchanged. Functions described in this document are independent of the implementation. Users interested in quaternions per se should consult the 'quaterCS.h' and 'algeb.h' header files.

At present linking (attachment) of c-systems is not supported. For example, if a number of c-systems is used to describ various locations on a complex object and the object is moved, all the c-systems must be subjected to the appropriate transformation. This is easily accomplished by the ChainCS function, but nevertheless the programmer must not forget take care of the task. Implementation of c-system linking (attachment) would require that father c-systems are not destroyed before sons in the dependency tree. Such is system can be conveniently implemented in C++.

In the current implementation, every transformation creates a new c-system. In our opinion, the efficiency penalty incurred is justified. First, one can overwrite a c-system variable only by epxlicit assignment; accidental overwrite is threfore very unlikely. Calls do not need to take addresses of variables using the '&' operator which is inconvenient and easily forgotten. Last but not least the implentation is in the spirit of other UoS libs like vector2 and vector3, which is used in the implementation of this library.

Tools

The 'cs2gf' program, shown in the Example section convert .cs files into c-system origins and produces a .gf file which is drawn by Xmgf as a line connecting origins, ie the 'trajectory'.

SEE ALSO

vector3.
GF manipulation: gfLL (requires list the LL library (libLL.a) and strGM string library (libstrGM.a))
visualisation: Xmgf
other: optionGM (option parsing, used in examples; requires strGM.a)

BUGS

Functions of the 'Align.CS' family return the input c-system when the vector specifing the alignment direction is (0,0,0). This is probably more a bug than a feature, because a similar problem is treated differently in the RotCS function and because the (0,0,0) direction most likely indicates problems in the calling program.

Warning. The libstrGM.a string library used in the '.gf' manipulation routines requires standard C function 'sprintf' to behave as defined by ANSI C strandard, ie. returning the number of successfully converted arguments. On some UNIX systems, eg. SUN OS 4.x, the C standard lib contains K&R implementation of spprintf which returns its first argument. Under SUN OS, the ANSI compatible lib is in /usr/5lib.

AUTHOR

Library design by George Matas (g.matas@ee.surrey.ac.uk). Implementation by George Matas and Pavel Andris (utrrandr@savba.sk). Quaternion manipulation written by Peter Kurdel (utrrkurd@savba.sk). This document written by George Matas.
09-Feb-95. Automatically converted by man2html, written by G.Matas (g.matas@ee.surrey.ac.uk)