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 1.6.3