LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiCoordinateTransformation.h

00001 /*
00002  * Copyright (C) 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 
00024 /*--------------------------------------------------------------------
00025  * project ....: LTI-Lib: Image Processing and Computer Vision Library
00026  * file .......: ltiCoordinateTransformation.h
00027  * authors ....: Christoph Meyer, Florian Bley
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 1.10.2004
00030  * revisions ..: $Id: ltiCoordinateTransformation.h,v 1.4 2006/02/08 12:15:21 ltilib Exp $
00031  */
00032 
00033 #ifndef _LTI_COORDINATE_TRANSFORMATION_H_
00034 #define _LTI_COORDINATE_TRANSFORMATION_H_
00035 
00036 
00037 #include "ltiMatrix.h"
00038 #include "ltiVector.h"
00039 #include "ltiLinearAlgebraFunctor.h"           // parentclass
00040 #include "ltiConstants.h"                      // for Pi
00041 
00042 using namespace std;
00043 
00044 namespace lti {
00045   /**
00046    * This class transforms the coordinates of a 3D point between two coordinate systems.
00047    * These two coordinate systems are both of cartesian type, but they are rotated
00048    * and/or displaced to each other.
00049    *
00050    * Inner- vs. Outer-coordinate-system:<br>
00051    * The two systems will be called outer- and the inner-coordinate-
00052    * system. The inner system is rotated and/or displaced to the outer one. Let's take a
00053    * look at a common example. We have a room which is our global reference frame. A 
00054    * mobile robot can be navigated in this room. On top of the robot, a stereo-camera is 
00055    * placed on a pan-tilt unit.<br>
00056    * Our goal is to transform a point from the cameras coordinate system to the global 
00057    * reference frame. To do this we need two instances of this class.<br> 
00058    * 1. the camera and the robot: the camera is the inner system and the robot is the 
00059    *    outer system. The inner system has a fixed displacement and a variable
00060    *    orientation, which can be changed by the pan-tilt unit.<br>
00061    * 2. the robot and the room: here the robot is the inner system and the room is the
00062    *    outer one.
00063    *
00064    * To perform a transformation, we need the following parameters (all <b> float </b>):
00065    *   - The position of the origin (0,0,0) of the inner system in respect to the outer 
00066    *     coordinate system as a 3D lti::vector. Short: Displacement from outer to inner.
00067    *   - The three angles in degree of axis-rotations, which are defined as follows:
00068    *       - alpha: degree to rotate the inner system around the inner x-axis
00069    *       - beta:  degree to rotate the inner system around the inner y-axis
00070    *       - gamma: degree to rotate the inner system around the inner z-axis
00071    *
00072    * It is important, that you rotate your inner coordinate system axis in the 
00073    * right-hand-screw-rule in chronological order!<br>
00074    * That means:<br>
00075    * Take your right hand (difficult job) and orientate your thumb in the
00076    * positive direction of the inner-axis around which you want to rotate. When
00077    * your remaining fingers are not racked, they will point around this axis and point
00078    * in direction of positive angles.<br>    
00079    * Attention:<br> 
00080    * Rotating in chronological order means to rotate the axis in the order x, y, z.
00081    * Otherwise you will get wrong results.
00082    * If you rotate around all three axis, beta and gamma can not be seen directly, 
00083    * so you definitely have to calculate the angles one after the other.
00084    *
00085    * Here is how the transformation is performed:<br>
00086    * For each angle / axis-rotation, a rotation matrix will be calculated. Matrix A 
00087    * contains the rotation around the x axis, B around y and C around z.
00088    * The transformed vector \c vT arises by multiplying the untransformed vector \c v with these   
00089    * matrices:    <tt>vT = C*B*A*v + displacement.</tt><br>
00090    * In order to save calculation time for subsequent transformations, the three matrices 
00091    * will be multiplied to D=C*B*A, hence only the following will be computed when you 
00092    * call the apply-method:     <tt>vT = D*v + displacement.</tt>
00093    *
00094    * Here is how to set/initialize the parameters:
00095    * After creating an object of the parameter class you have to call the function
00096    * coordinateTransformation::parameters::initParameters to set/initialize the parameters.. In this method, the rotation matrix D will be
00097    * calculated. Take a look at the code example below.<br> 
00098    * Alternatives:<br>
00099    *    - You can directly set the 3x3 total-rotation-matrix D called 
00100    *      coordinateTransformation::parameters::mRotateAroundXYZAxis
00101    *      and the displacement-vector called coordinateTransformation::parameters::vDisplace, 
00102    *      which are both public members. Just pay no attention to the function 
00103    *      coordinateTransformation::parameters::initParameters and to the grim face 
00104    *      of the C++ guru standing behind you.
00105    *    - Or you can also set the displacement-vector, call the method
00106    *      coordinateTransformation::parameters::defineTransformationMatrices to set the 
00107    *      three matrices A, B and C and call the method 
00108    *      coordinateTransformation::parameters::calculateTotalRotationMatrix to 
00109    *      calculate the matrix D.
00110    *
00111    *
00112    * Example:<br>
00113    * We have a robot with a stereo camera on it, which is standing in a room (our global
00114    * reference frame).
00115    * 1. The camera is placed 0.3 meters right and 0.25 meters in front of the origin of
00116    *    our global reference frame.
00117    * 2. The robot points in z-direction, the y-axis of our global frame points to the
00118    *    ceiling, so the x-axis points to the left.
00119    * 3. The camera looks 15 degrees to the right and 45 degrees to the ground.
00120    *
00121    * Our displacement-vector is: (-0.3, 0, 0.25).
00122    * To get the rotation-angles we first have to rotate the camera around the x-axis:<br>
00123    * => alpha = -45 degrees.<br>
00124    * Then we have to rotate around the y-axis:<br>
00125    * => beta = +15 degrees.<br>
00126    * We do not have a rotation around z.<br>
00127    *
00128    * So here is the code:
00129    * \code
00130    *    lti::coordinateTransformation coordTransform;
00131    *    lti::coordinateTransformation::parameters transformParam;
00132    *    float fSystemsDisplacement[3] =  {-0.3, 0, 0.25};
00133    *    lti::vector<float>  vDisplace(3,fSystemsDisplacement);
00134    *
00135    *    transformParam.initParameters(-45, 15, 0, vDisplace);
00136    *    coordTransform.setParameters(transformParam);
00137    *
00138    *    float fPoint[3] = {u, v, w};
00139    *    lti::vector<float>  vPoint(3,fPoint);
00140    *    std::cout << "The point: " << vPoint << " in the inner system:" << std::endl;
00141    *    coordTransform.apply(vPoint);
00142    *    std::cout << "has the position :" << vPoint << " in the outer system." << std::endl;
00143    * \endcode
00144    */
00145 
00146   class coordinateTransformation : public linearAlgebraFunctor {
00147   public:
00148 
00149     /**
00150      * ------------------------------------------------------------------ start of parameters
00151      * The parameters for the class coordinateTransformation
00152      */
00153     class parameters : public linearAlgebraFunctor::parameters {
00154     public:
00155       // -------------------------------------------------------------
00156       // Constructors & Destructor
00157       // ------------------------------------------------
00158       /**
00159        * Default constructor
00160        */
00161       parameters();
00162 
00163       /**
00164        * Copy constructor
00165        * @param other the parameters object to be copied
00166        */
00167       parameters(const parameters& other);
00168 
00169       /**
00170        * Destructor
00171        */
00172       ~parameters();
00173 
00174 
00175       // ------------------------------------------------
00176       // methods of parameters
00177       // ------------------------------------------------
00178       /**
00179        * Returns name of this type
00180        */
00181       const char* getTypeName() const;
00182 
00183       /**
00184        * Copy the contents of a parameters object
00185        * @param other the parameters object to be copied
00186        * @return a reference to this parameters object
00187        */
00188       parameters& copy(const parameters& other);
00189 
00190       /**
00191        * Copy the contents of a parameters object
00192        * @param other the parameters object to be copied
00193        * @return a reference to this parameters object
00194        */
00195       parameters& operator=(const parameters& other);
00196 
00197       /**
00198        * Returns a pointer to a clone of the parameters
00199        */
00200       virtual functor::parameters* clone() const;
00201 
00202       /**
00203        * Write the parameters in the given ioHandler
00204        * @param handler the ioHandler to be used
00205        * @param complete if true (the default) the enclosing begin/end will
00206        *        be also written, otherwise only the data block will be written.
00207        * @return true if write was successful
00208        */
00209       virtual bool write(ioHandler& handler,const bool complete=true) const;
00210 
00211       /**
00212        * Read the parameters from the given ioHandler
00213        * @param handler the ioHandler to be used
00214        * @param complete if true (the default) the enclosing begin/end will
00215        *        be also written, otherwise only the data block will be written.
00216        * @return true if write was successful
00217        */
00218       virtual bool read(ioHandler& handler,const bool complete=true);
00219 
00220 #     ifdef _LTI_MSC_6
00221       /**
00222        * This function is required by MSVC only, as a workaround for a
00223        * very awful bug, which exists since MSVC V.4.0, and still by
00224        * V.6.0 with all bugfixes (so called "service packs") remains
00225        * there...  This method is also public due to another bug, so please
00226        * NEVER EVER call this method directly: use read() instead
00227        */
00228       bool readMS(ioHandler& handler,const bool complete=true);
00229 
00230       /**
00231        * This function is required by MSVC only, as a workaround for a
00232        * very awful bug, which exists since MSVC V.4.0, and still by
00233        * V.6.0 with all bugfixes (so called "service packs") remains
00234        * there...  This method is also public due to another bug, so please
00235        * NEVER EVER call this method directly: use write() instead
00236        */
00237       bool writeMS(ioHandler& hamRotateAroundXYZAxisndler,const bool complete=true) const;
00238 #     endif
00239 
00240 
00241     public:
00242       /**
00243        * This method has to be called by the user to initialize the parameters.
00244        * 
00245        * The parameters:
00246        *  - fAngleXAxisRotation, fAngleYAxisRotation and fAngleZAxisRotation
00247        *    represent the three angles (in degree) of the rotation of the inner coordinate system
00248        *    in respect to the outer system (explanation is given above).
00249        *  - vDisplacement represents the displacement between the two coordinate systems
00250        *    as a vector (x,y,z) from the origin of the outer system to the
00251        *    origin of the inner system.
00252        *
00253        * A note for the interested reader:
00254        * Internally, the parameter-class calculates three matrices <b>A, B and C</b> from 
00255        * the three angles and a the total-rotation-matrix
00256        * <b>D=C*B*A</b>(see introduction), in order to reduce calculation time for the
00257        * following point transformations. This way, the apply method doesn't have to 
00258        * calculate this matrix each time a point has to be transformed.
00259        */
00260       virtual bool initParameters(float fAngleXAxisRotation,
00261                                   float fAngleYAxisRotation,
00262                                   float fAngleZAxisRotation,
00263                                   vector<float> vDisplacement);
00264 
00265       /**
00266        * This method is called by initParameters
00267        * and calculates the three rotation-matrices <b>A, B and C</b>.
00268        * <b>A</b> contains the rotation around x, <b>B</b> around y and
00269        * <b>C</b> around z. 
00270        */
00271       virtual bool defineTransformationMatrices(float falpha,
00272                                                 float fbeta,
00273                                                 float fgamma);
00274 
00275       /**
00276        * This method is called by initParameters,
00277        * and calculates the total-rotation-matrix by multiplying the three
00278        * rotation-matrices: D=C*B*A
00279        */
00280       virtual bool calculateTotalRotationMatrix(void);
00281 
00282 
00283 
00284       // ------------------------------------------------
00285       // the parameters
00286       // ------------------------------------------------
00287     public:
00288       /**
00289        * The three rotation-matrices (3x3) <b>A, B and C</b>
00290        * for the rotation around each axis.
00291        */
00292       typedef matrix<float> transformMatrix;
00293       transformMatrix mRotateAroundXAxis,
00294                       mRotateAroundYAxis,
00295                       mRotateAroundZAxis;
00296 
00297     public:
00298       /**
00299        * The total-rotation-matrix(3x3) <b>D=C*B*A</b>(see introduction)
00300        * which rotates a vector around all three axes. This matrix is
00301        * calculated when you initialize the parameters with the method
00302        * initParameters. You also can set this 3x3 matrix directly.
00303        */
00304       transformMatrix mRotateAroundXYZAxis;
00305 
00306       /**
00307        * The displacement between the two coordinate systems, described by
00308        * a vector (x,y,z) from the origin (0,0,0) of the outer system to the
00309        * origin of the inner system. You can set this
00310        * parameter when you initialize the parameters with the method
00311        * initParameters, or you can set it directly.
00312        */
00313       vector<float> vDisplace;
00314 
00315     public:
00316 
00317 
00318     };/**
00319        * ------------------------------------------------------------------ End of Parameters
00320        */
00321 
00322 
00323     
00324     // ------------------------------------------------
00325     // Constructors & Destructor
00326     // ------------------------------------------------
00327     /**
00328      * Default constructor
00329      */
00330     coordinateTransformation();
00331 
00332     /**
00333      * Construct a functor using the given parameters
00334      */
00335     coordinateTransformation(const parameters& par);
00336 
00337     /**
00338      * Copy constructor
00339      * @param other the object to be copied
00340      */
00341     coordinateTransformation(const coordinateTransformation& other);
00342 
00343     /**
00344      * Destructor
00345      */
00346     virtual ~coordinateTransformation();
00347 
00348     
00349     // ------------------------------------------------
00350     // methods of class coordinateTransformation
00351     // ------------------------------------------------
00352     /**
00353      * Returns the name of this type ("coordinateTransformation")
00354      */
00355     virtual const char* getTypeName() const;
00356 
00357     /**
00358      * Transforms a given point ( as vector \e srcdest ) in the inner
00359      * coordinate system (e.g. camera) to a point (also \e srcdest) in the outer
00360      * coordinate system (e.g. robot).
00361      * @param srcdest vector with the source data. The result will be left here too.
00362      * @return true if apply successful or false otherwise.
00363      */
00364     bool apply(vector<float>& srcdest) const;
00365 
00366     /**
00367      * Transforms a given point ( as vector \e src ) in the inner
00368      * coordinate system (e.g. camera) to a point (also \e dest) in the outer
00369      * coordinate system (e.g. robot).
00370      * Operates on a copy of the given %parameters.
00371      * @param src vector with the source data.
00372      * @param dest vector where the result will be left.
00373      * @return true if apply successful or false otherwise.
00374      */
00375     bool apply(const vector<float>& src, vector<float>& dest) const;
00376 
00377     /**
00378      * Copy data of "other" functor.
00379      * @param other the functor to be copied
00380      * @return a reference to this functor object
00381      */
00382     coordinateTransformation& copy(const coordinateTransformation& other);
00383 
00384     /**
00385      * Alias for copy member
00386      * @param other the functor to be copied
00387      * @return a reference to this functor object
00388      */
00389     coordinateTransformation& operator=(const coordinateTransformation& other);
00390 
00391     /**
00392      * Returns a pointer to a clone of this functor.
00393      */
00394     virtual functor* clone() const;
00395 
00396     /**
00397      * Returns used parameters.
00398      */
00399     const parameters& getParameters() const;
00400 
00401   };
00402 }
00403 
00404 #endif

Generated on Sat Apr 10 15:25:17 2010 for LTI-Lib by Doxygen 1.6.1