CartesianValues.cpp

Go to the documentation of this file.
00001 /* ============================================================
00002  *
00003  * This file is a part of RCI project
00004  *
00005  * Copyright (C) 2011 by Arne Nordmann <anordman at cor-lab dot uni-bielefeld dot de>
00006  *
00007  * This file may be licensed under the terms of the
00008  * GNU Lesser General Public License Version 3 (the ``LGPL''),
00009  * or (at your option) any later version.
00010  *
00011  * Software distributed under the License is distributed
00012  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
00013  * express or implied. See the LGPL for the specific language
00014  * governing rights and limitations.
00015  *
00016  * You should have received a copy of the LGPL along with this
00017  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
00018  * or write to the Free Software Foundation, Inc.,
00019  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  * The development of this software was supported by:
00022  *   CoR-Lab, Research Institute for Cognition and Robotics
00023  *     Bielefeld University
00024  *
00025  * ============================================================ */
00026 
00027 #include "CartesianValues.h"
00028 
00029 #include <iostream>
00030 #include <sstream>
00031 
00032 #include "boost/quaterion_conversions.h"
00033 
00034 using namespace nemo;
00035 using namespace boost;
00036 using namespace boost::math;
00037 
00038 namespace rci {
00039 
00040 CartesianTranslational::CartesianTranslational() :
00041         DataTransferObject(), ContainingDoubles(3, 0.0) {
00042 }
00043 
00044 CartesianTranslational::~CartesianTranslational() {
00045 }
00046 
00047 CartesianTranslational::CartesianTranslational(double valx, double valy,
00048         double valz) :
00049         DataTransferObject(), ContainingDoubles(3, 0.0) {
00050     this->_values[0] = valx;
00051     this->_values[1] = valy;
00052     this->_values[2] = valz;
00053 }
00054 
00055 CartesianTranslational::CartesianTranslational(
00056         const CartesianTranslational& transl) :
00057         DataTransferObject(), ContainingDoubles(3, 0.0) {
00058     this->_values[0] = transl.asDouble(0);
00059     this->_values[1] = transl.asDouble(1);
00060     this->_values[2] = transl.asDouble(2);
00061 }
00062 
00063 CartesianTranslational::CartesianTranslational(
00064         const CartesianTranslationalPtr& transl) :
00065         DataTransferObject(), ContainingDoubles(3, 0.0) {
00066     this->_values[0] = transl->asDouble(0);
00067     this->_values[1] = transl->asDouble(1);
00068     this->_values[2] = transl->asDouble(2);
00069 }
00070 
00071 CartesianTranslational::CartesianTranslational(const RealVector& values) :
00072         DataTransferObject(), ContainingDoubles(values) {
00073     if (values.dimension() != 3) {
00074         throw std::invalid_argument("Wrong number of values given (need 3).");
00075     }
00076 }
00077 
00078 double CartesianTranslational::x() const {
00079     return this->asDouble(0);
00080 }
00081 
00082 double CartesianTranslational::y() const {
00083     return this->asDouble(1);
00084 }
00085 
00086 double CartesianTranslational::z() const {
00087     return this->asDouble(2);
00088 }
00089 
00090 std::string CartesianTranslational::print() const {
00091     std::ostringstream outstream(std::ostringstream::out);
00092     outstream.precision(3); // Precision when printing double values
00093     outstream << "Translation<x=" << this->x() << ",y=" << this->y() << ",z="
00094             << this->z() << ">(m)";
00095     return outstream.str();
00096 }
00097 
00098 CartesianRotational::CartesianRotational() :
00099         DataTransferObject(), ContainingDoubles(4, 0.0), _quaternion() {
00100 }
00101 
00102 CartesianRotational::~CartesianRotational() {
00103 }
00104 
00105 CartesianRotational::CartesianRotational(double rotX, double rotY, double rotZ) :
00106         DataTransferObject(), ContainingDoubles(4, 0.0), _quaternion() {
00107     double qq0 = cos(rotX / 2) * cos(rotY / 2) * cos(rotZ / 2)
00108             + sin(rotX / 2) * sin(rotY / 2) * sin(rotZ / 2);
00109     double qq1 = sin(rotX / 2) * cos(rotY / 2) * cos(rotZ / 2)
00110             - cos(rotX / 2) * sin(rotY / 2) * sin(rotZ / 2);
00111     double qq2 = cos(rotX / 2) * sin(rotY / 2) * cos(rotZ / 2)
00112             + sin(rotX / 2) * cos(rotY / 2) * sin(rotZ / 2);
00113     double qq3 = cos(rotX / 2) * cos(rotY / 2) * sin(rotZ / 2)
00114             - sin(rotX / 2) * sin(rotY / 2) * cos(rotZ / 2);
00115 
00116     _quaternion = quaternion<double>(qq0, qq1, qq2, qq3);
00117 }
00118 
00119 CartesianRotational::CartesianRotational(double vala, double valb, double valc,
00120         double vald) :
00121         DataTransferObject(), ContainingDoubles(4, 0.0), _quaternion(vala, valb,
00122                 valc, vald) {
00123 }
00124 
00125 CartesianRotational::CartesianRotational(const RealVector& values) :
00126         DataTransferObject(), ContainingDoubles(4, 0.0), _quaternion(values[0],
00127                 values[1], values[2], values[3]) {
00128     if (values.dimension() != 4) {
00129         throw std::invalid_argument("Wrong number of values given (need 4).");
00130     }
00131 }
00132 
00133 CartesianRotational::CartesianRotational(
00134         const ::boost::math::quaternion<double> quaternion) :
00135         DataTransferObject(), ContainingDoubles(4, 0.0), _quaternion(quaternion) {
00136 }
00137 
00138 CartesianRotational::CartesianRotational(const CartesianRotational& rot) :
00139         DataTransferObject(), ContainingDoubles(4, 0.0), _quaternion(
00140                 rot.asDouble(0), rot.asDouble(1), rot.asDouble(2),
00141                 rot.asDouble(3)) {
00142 }
00143 
00144 CartesianRotational::CartesianRotational(const CartesianRotationalPtr& rot) :
00145         DataTransferObject(), ContainingDoubles(4, 0.0), _quaternion(
00146                 rot->asDouble(0), rot->asDouble(1), rot->asDouble(2),
00147                 rot->asDouble(3)) {
00148 }
00149 
00150 CartesianRotational::CartesianRotational(double rxx, double rxy, double rxz,
00151         double ryx, double ryy, double ryz, double rzx, double rzy, double rzz) :
00152         _quaternion() {
00153 
00154     R3_matrix<double> tmp;
00155     tmp.a11 = rxx;
00156     tmp.a12 = rxy;
00157     tmp.a13 = rxz;
00158     tmp.a21 = ryx;
00159     tmp.a22 = ryy;
00160     tmp.a23 = ryz;
00161     tmp.a31 = rzx;
00162     tmp.a32 = rzy;
00163     tmp.a33 = rzz;
00164 
00165     this->_quaternion = R3_rotation_to_quaternion(tmp);
00166 
00167     // Test for invalid quaternion
00168     // HACK - Perturb if in a pole
00169     bool valid = ((_quaternion.R_component_1() == _quaternion.R_component_1())
00170             && (_quaternion.R_component_2() == _quaternion.R_component_2())
00171             && (_quaternion.R_component_3() == _quaternion.R_component_3())
00172             && (_quaternion.R_component_4() == _quaternion.R_component_4()));
00173     while (!valid) {
00174         rxx *= 0.999;
00175         rxy *= 0.999;
00176         rxz *= 0.999;
00177         ryx *= 0.999;
00178         ryy *= 0.999;
00179         ryz *= 0.999;
00180         rzx *= 0.999;
00181         rzy *= 0.999;
00182         rzz *= 0.999;
00183         tmp.a11 = rxx;
00184         tmp.a12 = rxy;
00185         tmp.a13 = rxz;
00186         tmp.a21 = ryx;
00187         tmp.a22 = ryy;
00188         tmp.a23 = ryz;
00189         tmp.a31 = rzx;
00190         tmp.a32 = rzy;
00191         tmp.a33 = rzz;
00192         this->_quaternion = R3_rotation_to_quaternion(tmp);
00193         valid = ((_quaternion.R_component_1()
00194                 == _quaternion.R_component_1())
00195                 && (_quaternion.R_component_2() == _quaternion.R_component_2())
00196                 && (_quaternion.R_component_3() == _quaternion.R_component_3())
00197                 && (_quaternion.R_component_4() == _quaternion.R_component_4()));
00198     }
00199 
00200 }
00201 
00202 double CartesianRotational::q0() const {
00203     return this->_quaternion.R_component_1();
00204 }
00205 
00206 double CartesianRotational::q1() const {
00207     return this->_quaternion.R_component_2();
00208 }
00209 
00210 double CartesianRotational::q2() const {
00211     return this->_quaternion.R_component_3();
00212 }
00213 
00214 double CartesianRotational::q3() const {
00215     return this->_quaternion.R_component_4();
00216 }
00217 
00218 double CartesianRotational::a() const {
00219     return atan2(2 * (q0() * q1() + q2() * q3()),
00220             1 - 2 * (q1() * q1() + q2() * q2()));
00221 }
00222 
00223 double CartesianRotational::b() const {
00224     return asin(std::max(-1.0, std::min(1.0, 2 * (q0() * q2() - q3() * q1()))));
00225 }
00226 
00227 double CartesianRotational::c() const {
00228     return atan2(2 * (q0() * q3() + q1() * q2()),
00229             1 - 2 * (q2() * q2() + q3() * q3()));
00230 }
00231 
00232 nemo::RealVector CartesianRotational::asEulerAngles() const {
00233     RealVector vector(dim(3));
00234 
00235     vector[0] = this->a();
00236     vector[1] = this->b();
00237     vector[2] = this->c();
00238 
00239     return vector;
00240 }
00241 
00242 nemo::RealVector CartesianRotational::asAxisAngle() const {
00243     RealVector vector(dim(4));
00244 
00245     double f = sqrt(1 - q0() * q0());
00246 
00247     if (f < CartesianRotational::epsilon()) {
00248         return RealVector(dim(4), 0.0);
00249     }
00250 
00251     vector[0] = 2 * acos(q0());
00252     vector[1] = q1() / f;
00253     vector[2] = q2() / f;
00254     vector[3] = q3() / f;
00255 
00256     return vector;
00257 }
00258 
00259 nemo::RealVector CartesianRotational::asCompactAxisAngle() const {
00260     RealVector aa = this->asAxisAngle();
00261     return RealVector(aa[1] * aa[0], aa[2] * aa[0], aa[3] * aa[0]);
00262 }
00263 
00264 ::boost::math::quaternion<double> CartesianRotational::asQuaternion() const {
00265     return _quaternion;
00266 }
00267 
00268 RealVector CartesianRotational::asDoubleVector() const {
00269     RealVector vector(nemo::dim(4));
00270 
00271     vector[0] = this->q0();
00272     vector[1] = this->q1();
00273     vector[2] = this->q2();
00274     vector[3] = this->q3();
00275 
00276     return vector;
00277 }
00278 
00279 double CartesianRotational::asDouble(unsigned int index) const {
00280     switch (index) {
00281     case 0:
00282         return this->q0();
00283         break;
00284     case 1:
00285         return this->q1();
00286         break;
00287     case 2:
00288         return this->q2();
00289         break;
00290     case 3:
00291         return this->q3();
00292         break;
00293     default:
00294         throw std::invalid_argument(
00295                 "Rotational value expressed as quaternion, so index has to be between 0 and 3.");
00296     }
00297 }
00298 
00299 void CartesianRotational::setValue(double value) {
00300     throw std::runtime_error(
00301             "Multi-dimensional object, don`t know which value to set. Specify index.");
00302 }
00303 
00304 void CartesianRotational::setValue(unsigned int index, double value) {
00305     switch (index) {
00306     case 0:
00307         this->_quaternion = quaternion<double>(value,
00308                 _quaternion.R_component_2(), _quaternion.R_component_3(),
00309                 _quaternion.R_component_4());
00310         break;
00311     case 1:
00312         this->_quaternion = quaternion<double>(_quaternion.R_component_1(),
00313                 value, _quaternion.R_component_3(),
00314                 _quaternion.R_component_4());
00315         break;
00316     case 2:
00317         this->_quaternion = quaternion<double>(_quaternion.R_component_1(),
00318                 _quaternion.R_component_2(), value,
00319                 _quaternion.R_component_4());
00320         break;
00321     case 3:
00322         this->_quaternion = quaternion<double>(_quaternion.R_component_1(),
00323                 _quaternion.R_component_2(), _quaternion.R_component_3(),
00324                 value);
00325         break;
00326     default:
00327         throw std::range_error("Index exceeds dimensions.");
00328     }
00329 }
00330 
00331 std::string CartesianRotational::print() const {
00332     std::ostringstream outstream(std::ostringstream::out);
00333     outstream.precision(3); // Precision when printing double values
00334     outstream << "CartesianRotational<a=" << this->a() << ",b=" << this->b()
00335             << ",c=" << this->c() << ">(rad)";
00336     return outstream.str();
00337 }
00338 
00339 CartesianValue::CartesianValue() :
00340         DataTransferObject(), _transl(), _rot() {
00341 }
00342 
00343 CartesianValue::~CartesianValue() {
00344 }
00345 
00346 CartesianValue::CartesianValue(double valx, double valy, double valz,
00347         double vala, double valb, double valc, double vald) :
00348         DataTransferObject(), _transl(valx, valy, valz), _rot(vala, valb, valc,
00349                 vald) {
00350 }
00351 
00352 CartesianValue::CartesianValue(const CartesianValue& val) :
00353         DataTransferObject(), _transl(val._transl), _rot(val._rot) {
00354 }
00355 
00356 CartesianValue::CartesianValue(const CartesianTranslationalPtr& transl,
00357         const CartesianRotationalPtr& rot) :
00358         DataTransferObject(), _transl(transl), _rot(rot) {
00359 }
00360 
00361 CartesianValue::CartesianValue(const RealVector& values) :
00362         DataTransferObject(), _transl(), _rot() {
00363     if (values.dimension() != 7) {
00364         throw std::invalid_argument("Wrong number of values given (need 7).");
00365     }
00366     this->_transl = CartesianTranslational(values[0], values[1], values[2]);
00367     this->_rot = CartesianRotational(values[3], values[4], values[5],
00368             values[6]);
00369 }
00370 
00371 double CartesianValue::asDouble(unsigned int index) const {
00372     if (index > 6) {
00373         // Dimensions doesn`t agree, throw exception
00374     }
00375     if (index < 3) {
00376         return this->_transl.asDouble(index);
00377     } else {
00378         return this->_rot.asDouble(index - 3);
00379     }
00380 }
00381 
00382 RealVector CartesianValue::asDoubleVector() const {
00383     RealVector vector(dim(7));
00384 
00385     vector[0] = this->_transl.asDouble(0);
00386     vector[1] = this->_transl.asDouble(1);
00387     vector[2] = this->_transl.asDouble(2);
00388     vector[3] = this->_rot.asDouble(0);
00389     vector[4] = this->_rot.asDouble(1);
00390     vector[5] = this->_rot.asDouble(2);
00391     vector[6] = this->_rot.asDouble(3);
00392 
00393     return vector;
00394 }
00395 
00396 void CartesianValue::setValue(unsigned int index, double value) {
00397     if (index > 6) {
00398         throw std::range_error("Index exceeds dimensions");
00399     }
00400     if (index < 3) {
00401         this->_transl.setValue(index, value);
00402     } else {
00403         this->_rot.setValue(index - 3, value);
00404     }
00405 }
00406 
00407 double CartesianValue::x() const {
00408     return this->_transl.x();
00409 }
00410 
00411 double CartesianValue::y() const {
00412     return this->_transl.y();
00413 }
00414 
00415 double CartesianValue::z() const {
00416     return this->_transl.z();
00417 }
00418 
00419 double CartesianValue::q0() const {
00420     return this->_rot.q0();
00421 }
00422 
00423 double CartesianValue::q1() const {
00424     return this->_rot.q1();
00425 }
00426 
00427 double CartesianValue::q2() const {
00428     return this->_rot.q2();
00429 }
00430 
00431 double CartesianValue::q3() const {
00432     return this->_rot.q3();
00433 }
00434 
00435 double CartesianValue::a() const {
00436     return this->_rot.a();
00437 }
00438 
00439 double CartesianValue::b() const {
00440     return this->_rot.b();
00441 }
00442 
00443 double CartesianValue::c() const {
00444     return this->_rot.c();
00445 }
00446 
00447 unsigned int CartesianValue::getDimension() const {
00448     return 7;
00449 }
00450 
00451 }
Generated on Thu Aug 2 14:02:49 2012 for RCI by  doxygen 1.6.3