latest version v1.9 - last update 10 Apr 2010 |
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