Libbarrett
1.2.4
|
00001 /* 00002 * matrix.h 00003 * 00004 * Created on: Jan 13, 2010 00005 * Author: dc 00006 */ 00007 00008 #ifndef BARRETT_MATH_MATRIX_H_ 00009 #define BARRETT_MATH_MATRIX_H_ 00010 00011 00012 #include <iostream> 00013 #include <stdexcept> 00014 00015 #include <boost/type_traits/is_same.hpp> 00016 #include <boost/mpl/assert.hpp> 00017 #include <boost/mpl/if.hpp> 00018 #include <boost/mpl/or.hpp> 00019 00020 #include <libconfig.h++> 00021 00022 #include <Eigen/Core> 00023 #include <Eigen/Array> 00024 #include <gsl/gsl_vector.h> 00025 #include <gsl/gsl_matrix.h> 00026 00027 #include <barrett/math/traits.h> 00028 00029 00030 namespace barrett { 00031 namespace math { 00032 00033 00034 template<int R, int C, typename Units = void> class Matrix; 00035 00036 template<int R, typename Units = void> 00037 struct Vector { 00038 typedef math::Matrix<R,1, Units> type; 00039 }; 00040 00041 00042 template<int R, int C, typename Units> 00043 class Matrix : public Eigen::Matrix<double, R,C, Eigen::RowMajorBit> { 00044 public: 00045 typedef Eigen::Matrix<double, R,C, Eigen::RowMajorBit> Base; 00046 typedef Matrix<R,C, Units> type; 00047 00048 typedef typename boost::mpl::if_c< 00049 Base::IsVectorAtCompileTime, 00050 gsl_vector, 00051 gsl_matrix 00052 >::type gsl_type; 00053 00054 // TODO(dc): disable SIZE somehow for dynamic Matrices? 00055 static const size_t SIZE = R*C; 00056 00063 typedef Matrix<R,C> unitless_type; 00064 00065 00066 // Duplicate the non-inherited parts of Eigen's interface. 00067 // Matrix(); 00068 // explicit Matrix(int dim); 00069 // Matrix(int r, int c); 00070 Matrix(double x, double y); 00071 Matrix(double x, double y, double z); 00072 Matrix(double x, double y, double z, double w); 00073 explicit Matrix(const double* data); 00074 template<typename OtherDerived> 00075 Matrix(const Eigen::MatrixBase<OtherDerived>& other); 00076 00077 // EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Matrix); 00078 using Base::operator=; 00079 00080 // the default operator= does it wrong. 00081 inline Matrix& operator=(const Matrix& other) { 00082 if (this != &other) { 00083 // GSL stuff doen't need to be altered 00084 this->Base::operator=(other); 00085 } 00086 return *this; 00087 } 00088 00089 // make sure units match 00090 template<int OtherR, int OtherC, typename OtherUnits> 00091 inline Matrix<R,C, Units>& operator=(const Matrix<OtherR,OtherC, OtherUnits>& other) { 00092 BOOST_MPL_ASSERT(( boost::mpl::or_< 00093 boost::is_same<Units, void>, 00094 boost::is_same<void, OtherUnits>, 00095 boost::is_same<Units, OtherUnits> 00096 > )); 00097 00098 // GSL stuff doen't need to be altered 00099 this->Base::operator=(other); 00100 return *this; 00101 } 00102 00103 00104 template<typename OtherDerived> 00105 explicit Matrix(const Eigen::RotationBase<OtherDerived,Base::ColsAtCompileTime>& r); 00106 // template<typename OtherDerived> 00107 // Matrix& operator=(const Eigen::RotationBase<OtherDerived,Base::ColsAtCompileTime>& r); 00108 00109 // Additional ctors 00110 00117 explicit Matrix(double d = 0.0); 00118 explicit Matrix(int r, double d = 0.0); 00119 Matrix(int r, int c, double d = 0.0); 00120 explicit Matrix(const gsl_type* gslType); 00121 Matrix(const libconfig::Setting& setting); // deliberately non-explicit 00122 Matrix(const Matrix& a); // TODO(dc): make sure units match in a copy construction 00123 ~Matrix(); 00124 00125 // TODO(dc): add a ctor that doesn't initialize the data? 00126 00127 // TODO(dc): How does this need to change to support dynamically sized Matrices? 00128 static size_t serializedLength(); 00129 void serialize(char* dest) const; 00130 static Matrix<R,C, Units> unserialize(char* source); 00131 00132 void copyTo(gsl_type* gslType) const throw(std::logic_error); 00133 void copyFrom(const gsl_type* gslType) throw(std::logic_error); 00134 00135 void copyFrom(const libconfig::Setting& setting); 00136 00137 gsl_type* asGslType(); 00138 const gsl_type* asGslType() const; 00139 00140 protected: 00141 void resizeIfDynamic(int r, int c = 1); 00142 00143 void initGslType(gsl_vector* g); 00144 void initGslType(gsl_matrix* g); 00145 00146 void resizeToMatchIfDynamic(const gsl_vector* g); 00147 void resizeToMatchIfDynamic(const gsl_matrix* g); 00148 00149 void checkSize(const gsl_vector* g) const; 00150 void checkSize(const gsl_matrix* g) const; 00151 00152 void copyToHelper(gsl_vector* g) const; 00153 void copyToHelper(gsl_matrix* g) const; 00154 00155 void copyFromHelper(const gsl_vector* g); 00156 void copyFromHelper(const gsl_matrix* g); 00157 00158 gsl_type gsl; 00159 }; 00160 00161 00162 template<int R, int C, typename Units> 00163 std::ostream& operator<< (std::ostream& os, const Matrix<R,C, Units>& a); 00164 00165 00166 template<typename TraitsDerived> struct Traits<Eigen::MatrixBase<TraitsDerived> > { 00167 typedef Eigen::MatrixBase<TraitsDerived> MatrixBaseType; 00168 typedef typename MatrixBaseType::ConstantReturnType ConstantReturnType; 00169 00170 00171 static const bool IsDynamic = (MatrixBaseType::RowsAtCompileTime == Eigen::Dynamic || MatrixBaseType::ColsAtCompileTime == Eigen::Dynamic); 00172 static const bool RequiresAlignment = !IsDynamic; 00173 00174 00175 static const ConstantReturnType zero() { 00176 return MatrixBaseType::Zero(); 00177 } 00178 00179 static const ConstantReturnType zero(int r) { 00180 return MatrixBaseType::Zero(r); 00181 } 00182 00183 static const ConstantReturnType zero(int r, int c) { 00184 return MatrixBaseType::Zero(r,c); 00185 } 00186 00187 template<typename Derived> 00188 static void zero(Eigen::MatrixBase<Derived>& t) { 00189 t.setZero(); 00190 } 00191 00192 // matrix-matrix 00193 template<typename LDerived, typename RDerived> static 00194 const Eigen::CwiseBinaryOp< 00195 Eigen::ei_scalar_sum_op< 00196 typename Eigen::ei_traits<LDerived>::Scalar>, 00197 LDerived, 00198 RDerived 00199 > 00200 add(const Eigen::MatrixBase<LDerived>& l, const Eigen::MatrixBase<RDerived>& r) { 00201 return l + r; 00202 } 00203 00204 template<typename LDerived, typename RDerived> static 00205 const Eigen::CwiseBinaryOp< 00206 Eigen::ei_scalar_difference_op< 00207 typename Eigen::ei_traits<LDerived>::Scalar>, 00208 LDerived, 00209 RDerived 00210 > 00211 sub(const Eigen::MatrixBase<LDerived>& l, const Eigen::MatrixBase<RDerived>& r) { 00212 return l - r; 00213 } 00214 00215 template<typename LDerived, typename RDerived> static 00216 Eigen::CwiseBinaryOp< 00217 Eigen::ei_scalar_product_op< 00218 typename Eigen::ei_scalar_product_traits< 00219 typename Eigen::ei_traits<LDerived>::Scalar, 00220 typename Eigen::ei_traits<RDerived>::Scalar 00221 >::ReturnType 00222 >, 00223 LDerived, 00224 RDerived 00225 > 00226 mult(const Eigen::MatrixBase<LDerived>& l, const Eigen::MatrixBase<RDerived>& r) { 00227 return l.cwise() * r; 00228 } 00229 00230 template<typename LDerived, typename RDerived> static 00231 Eigen::CwiseBinaryOp< 00232 Eigen::ei_scalar_quotient_op<typename Eigen::ei_traits<LDerived>::Scalar>, 00233 LDerived, 00234 RDerived 00235 > 00236 div(const Eigen::MatrixBase<LDerived>& l, const Eigen::MatrixBase<RDerived>& r) { 00237 return l.cwise() / r; 00238 } 00239 00240 00241 // matrix-scalar 00242 template<typename Derived> static 00243 const Eigen::CwiseUnaryOp< 00244 Eigen::ei_scalar_add_op<typename Eigen::ei_traits<Derived>::Scalar>, 00245 Derived 00246 > 00247 add(const Eigen::MatrixBase<Derived>& l, double r) { 00248 return l.cwise() + r; 00249 } 00250 00251 template<typename Derived> static 00252 const Eigen::CwiseUnaryOp< 00253 Eigen::ei_scalar_add_op<typename Eigen::ei_traits<Derived>::Scalar>, 00254 Derived 00255 > 00256 add(double l, const Eigen::MatrixBase<Derived>& r) { 00257 return l + r.cwise(); 00258 } 00259 00260 template<typename Derived> static 00261 const Eigen::CwiseUnaryOp< 00262 Eigen::ei_scalar_add_op<typename Eigen::ei_traits<Derived>::Scalar>, 00263 Derived 00264 > 00265 sub(const Eigen::MatrixBase<Derived>& l, double r) { 00266 return l.cwise() - r; 00267 } 00268 00269 template<typename Derived> static 00270 const Eigen::CwiseUnaryOp< 00271 Eigen::ei_scalar_opposite_op<typename Eigen::ei_traits<Derived>::Scalar>, 00272 Derived 00273 > 00274 neg(const Eigen::MatrixBase<Derived>& t) { 00275 return -t; 00276 } 00277 00278 template<typename Derived> static 00279 // TODO(dc): this method returns random (uninitialized? deallocated?) values when it has the commented-out return type. i don't know why. 00280 // const Eigen::CwiseUnaryOp< 00281 // Eigen::ei_scalar_add_op<typename Eigen::ei_traits<Eigen::CwiseUnaryOp< 00282 // Eigen::ei_scalar_opposite_op<typename Eigen::ei_traits<Derived>::Scalar>, 00283 // Derived 00284 // > >::Scalar>, 00285 // Eigen::CwiseUnaryOp< 00286 // Eigen::ei_scalar_opposite_op<typename Eigen::ei_traits<Derived>::Scalar>, 00287 // Derived 00288 // > 00289 // > 00290 const typename MatrixBaseType::PlainMatrixType 00291 sub(double l, const Eigen::MatrixBase<Derived>& r) { 00292 return l + (-r).cwise(); 00293 } 00294 00295 template<typename Derived> static 00296 const Eigen::CwiseUnaryOp< 00297 Eigen::ei_scalar_multiple_op<typename Eigen::ei_traits<Derived>::Scalar>, 00298 Derived 00299 > 00300 mult(const Eigen::MatrixBase<Derived>& l, double r) { 00301 return l * r; 00302 } 00303 00304 template<typename Derived> static 00305 const Eigen::CwiseUnaryOp< 00306 Eigen::ei_scalar_multiple_op<typename Eigen::ei_traits<Derived>::Scalar>, 00307 Derived 00308 > 00309 mult(double l, const Eigen::MatrixBase<Derived>& r) { 00310 return l * r; 00311 } 00312 00313 template<typename Derived> static 00314 const Eigen::CwiseUnaryOp< 00315 Eigen::ei_scalar_quotient1_op<typename Eigen::ei_traits<Derived>::Scalar>, 00316 Derived 00317 > 00318 div(const Eigen::MatrixBase<Derived>& l, double r) { 00319 return l / r; 00320 } 00321 00322 template<typename Derived> static 00323 // TODO(dc): this method returns random (uninitialized? deallocated?) values when it has the commented-out return type. i don't know why. 00324 // const Eigen::CwiseUnaryOp< 00325 // Eigen::ei_scalar_multiple_op<typename Eigen::ei_traits<Eigen::CwiseUnaryOp< 00326 // Eigen::ei_scalar_inverse_op<typename Eigen::ei_traits<Derived>::Scalar>, 00327 // Derived 00328 // > >::Scalar>, 00329 // Eigen::CwiseUnaryOp< 00330 // Eigen::ei_scalar_inverse_op<typename Eigen::ei_traits<Derived>::Scalar>, 00331 // Derived 00332 // > 00333 // > 00334 const typename MatrixBaseType::PlainMatrixType 00335 div(double l, const Eigen::MatrixBase<Derived>& r) { 00336 return l * r.cwise().inverse(); 00337 } 00338 }; 00339 00340 00341 template<int R, int C, typename Units> struct Traits<Matrix<R,C, Units> > : 00342 public Traits<Eigen::MatrixBase<typename Matrix<R,C, Units>::Base> > { 00343 typedef typename Matrix<R,C, Units>::unitless_type unitless_type; 00344 }; 00345 00346 00347 } 00348 } 00349 00350 00351 // include template definitions 00352 #include <barrett/math/detail/matrix-inl.h> 00353 00354 00355 #endif /* BARRETT_MATH_MATRIX_H_ */