00001
00010 #ifndef GAUSSIAN_HPP_
00011 #define GAUSSIAN_HPP_
00012
00013 #include <string.h>
00014 #include "jmath/jblas.hpp"
00015 #include "jmath/indirectArray.hpp"
00016 #include "rtslam/rtslamException.hpp"
00017
00018 #define ENABLE_REINIT 0
00019
00020 namespace jafar {
00021 namespace rtslam {
00022
00023 #if ENABLE_REINIT
00024
00025
00026
00027
00028
00029
00030
00031 template<class V, class V2>
00032 void vec_indirect_init(ublas::vector_indirect<V> & vi, V2 & v, jblas::ind_array const & ia)
00033 {
00034 typename V::closure_type d(v);
00035 memcpy(&vi.data(), &d, sizeof(typename V::closure_type));
00036 vi.indirect() = ia;
00037 }
00038
00039 template<class M, class M2>
00040 void mat_indirect_init(ublas::matrix_indirect<M> & mi, M2 & m, jblas::ind_array const & ia1, jblas::ind_array const & ia2)
00041 {
00042 typename M::closure_type d(m);
00043 memcpy(&mi.data(), &d, sizeof(typename M::closure_type));
00044 mi.indirect1() = ia1;
00045 mi.indirect2() = ia2;
00046 }
00047 #endif
00048
00050
00052
00173 class Gaussian {
00174 public:
00178 typedef enum {
00179 REMOTE,
00180 LOCAL,
00181 UNCHANGED
00182 } storage_t;
00183
00184 private:
00185 bool hasNullCov_;
00186 std::size_t size_;
00187 storage_t storage_;
00188 jblas::vec x_local;
00189 jblas::sym_mat P_local;
00190 jblas::ind_array ia_;
00191 jblas::vec_indirect x_;
00192 jblas::sym_mat_indirect P_;
00193
00194 public:
00195
00196 #if ENABLE_REINIT
00197 void init(Gaussian & g)
00198 {
00199 vec_indirect_init(x_, g.x_.data().expression(), g.ia_);
00200 mat_indirect_init(P_, g.P_.data().expression(), g.ia_, g.ia_);
00201 }
00202 void init(jblas::vec & x, jblas::sym_mat & P, jblas::ind_array const & ia)
00203 {
00204 vec_indirect_init(x_, x, ia);
00205 mat_indirect_init(P_, P, ia, ia);
00206 }
00207 #endif
00208
00209 Gaussian() :
00210 hasNullCov_ (false),
00211 size_ (0),
00212 storage_ (LOCAL),
00213 x_local (0),
00214 P_local (0, 0),
00215 ia_ (0),
00216 x_ (x_local, ia_.all()),
00217 P_ (P_local, ia_.all(), ia_.all())
00218 {}
00219
00225 inline Gaussian(const size_t _size) :
00226 hasNullCov_ (false),
00227 size_ (_size),
00228 storage_ (LOCAL),
00229 x_local (size_),
00230 P_local (size_, size_),
00231 ia_ (size_),
00232 x_ (x_local, ia_.all()),
00233 P_ (P_local, ia_.all(), ia_.all())
00234 {
00235 clear();
00236 for (size_t i = 0; i < size_; i++)
00237 ia_(i) = i;
00238 }
00239
00240 #if ENABLE_REINIT
00241
00244 virtual void operator()(const size_t _size)
00245 {
00246 hasNullCov_ = false;
00247 size_ = _size;
00248 storage_ = LOCAL;
00249 x_local.resize(size_);
00250 P_local.resize(size_, size_);
00251 ia_ = jmath::ublasExtra::ia_set(0, size_);
00252 init(x_local, P_local, ia_);
00253
00254
00255 clear();
00256 }
00257 #endif
00258
00265 inline Gaussian(const jblas::vec & _x) :
00266 hasNullCov_ (true),
00267 size_ (_x.size()),
00268 storage_ (LOCAL),
00269 x_local (_x),
00270 P_local (size_, size_),
00271 ia_ (size_),
00272 x_ (x_local, ia_.all()),
00273 P_ (P_local, ia_.all(), ia_.all())
00274 {
00275 for (size_t i = 0; i < size_; i++)
00276 ia_(i) = i;
00277 }
00278
00279
00287 inline Gaussian(const jblas::vec& _x, const jblas::sym_mat& _P) :
00288 hasNullCov_ (false),
00289 size_ (_x.size()),
00290 storage_ (LOCAL),
00291 x_local (_x),
00292 P_local (_P),
00293 ia_ (size_),
00294 x_ (x_local, ia_.all()),
00295 P_ (P_local, ia_.all(), ia_.all())
00296 {
00297 JFR_ASSERT(_x.size() == _P.size1(), "gaussian::Gaussian():: x and P sizes do not match.");
00298 for (size_t i = 0; i < size_; i++)
00299 ia_(i) = i;
00300 }
00301
00302
00313
00314 inline Gaussian(const Gaussian & G, storage_t _storage = UNCHANGED) :
00315 hasNullCov_ (G.hasNullCov_),
00316 size_ (G.size_),
00317
00318 storage_(_storage == UNCHANGED ? G.storage_ : _storage),
00319 x_local (_storage == LOCAL ? G.x_ : G.x_local),
00320 P_local (_storage == LOCAL ? G.P_ : G.P_local),
00321 ia_ (_storage == LOCAL ? jafar::jmath::ublasExtra::ia_set(0, size_) : G.ia_),
00322 x_ (storage_ == LOCAL ? jblas::vec_indirect (x_local, ia_.all()) : G.x_),
00323 P_ (storage_ == LOCAL ? jblas::sym_mat_indirect (P_local, ia_.all(), ia_.all()) : G.P_)
00324 {
00325 }
00326
00327 #if ENABLE_REINIT
00328
00331 virtual void operator()(Gaussian & G, storage_t _storage = UNCHANGED)
00332 {
00333 hasNullCov_ = G.hasNullCov_;
00334 size_ = G.size_;
00335
00336 storage_ = (_storage == UNCHANGED ? G.storage_ : _storage);
00337 x_local = (_storage == LOCAL ? G.x_ : G.x_local);
00338 P_local = (_storage == LOCAL ? G.P_ : G.P_local);
00339 ia_ = (_storage == LOCAL ? jafar::jmath::ublasExtra::ia_set(0, size_) : G.ia_);
00340 if (storage_ == LOCAL) init(x_local, P_local, ia_.all()); else init(G);
00341
00342
00343 }
00344 #endif
00345
00358 inline Gaussian(Gaussian & G, const jblas::ind_array & _ia) :
00359 hasNullCov_ (false),
00360 size_ (_ia.size()),
00361 storage_ (REMOTE),
00362 x_local (0),
00363 P_local (0),
00364
00365 ia_(G.storage_ == LOCAL ? _ia : G.ia_.compose(_ia)),
00366 x_ (G.storage_ == LOCAL ? jblas::vec_indirect (G.x_local, ia_) : jblas::vec_indirect (G.x_.data(), ia_, 1) ),
00367 P_ (G.storage_ == LOCAL ? jblas::sym_mat_indirect (G.P_local, ia_, ia_) : jblas::sym_mat_indirect (G.P_.data(), ia_, ia_, 1))
00368 {
00369 }
00370
00371 #if ENABLE_REINIT
00372
00375 virtual void operator()(Gaussian & G, const jblas::ind_array & _ia)
00376 {
00377 hasNullCov_ = false;
00378 size_ = _ia.size();
00379 storage_ = REMOTE;
00380 x_local.resize(0);
00381 P_local.resize(0);
00382
00383 ia_ = (G.storage_ == LOCAL ? _ia : G.ia_.compose(_ia));
00384 if (G.storage_ == LOCAL) init(G.x_local, G.P_local, ia_); else init(G.x_.data().expression(), G.P_.data().expression(), ia_);
00385
00386
00387 }
00388 #endif
00389
00390
00401 inline Gaussian(jblas::vec & _x, jblas::sym_mat & _P, const jblas::ind_array& _ia) :
00402 hasNullCov_ (false),
00403 size_ (_ia.size()),
00404 storage_ (REMOTE),
00405 x_local (0),
00406 P_local (0),
00407 ia_ (_ia),
00408 x_ (_x, ia_),
00409 P_ (_P, ia_, ia_)
00410 {
00411 JFR_ASSERT(_x.size() == _P.size1(), "gaussian::Gaussian():: x and P sizes do not match.");
00412 }
00413
00414 #if ENABLE_REINIT
00415
00418 virtual void operator()(jblas::vec & _x, jblas::sym_mat & _P, const jblas::ind_array& _ia)
00419 {
00420 hasNullCov_ = false;
00421 size_ = _ia.size();
00422 storage_ = REMOTE;
00423 x_local.resize(0);
00424 P_local.resize(0);
00425 ia_ = _ia;
00426 init(_x, _P, ia_);
00427
00428
00429 JFR_ASSERT(_x.size() == _P.size1(), "gaussian::Gaussian():: x and P sizes do not match.");
00430 }
00431 #endif
00432
00433 void resize(size_t n, bool preserve = true)
00434 {
00435 JFR_ASSERT(storage_ == LOCAL, "cannot extend a LOCAL storage gaussian with size_t!");
00436 size_ = n;
00437 x_local.resize(size_, preserve);
00438 P_local.resize(size_, size_, preserve);
00439
00440 ia_ = jmath::ublasExtra::ia_set(0, size_);
00441 x_.indirect() = ia_;
00442 P_.indirect1() = ia_;
00443 P_.indirect2() = ia_;
00444
00445 }
00446
00447 void resize(const jblas::ind_array& _ia)
00448 {
00449 JFR_ASSERT(storage_ == REMOTE, "cannot extend a LOCAL storage gaussian with ind_array!");
00450 ia_ = _ia;
00451 size_ = ia_.size();
00452 x_.indirect() = ia_;
00453 P_.indirect1() = ia_;
00454 P_.indirect2() = ia_;
00455 }
00456
00457 void extend(size_t n)
00458 {
00459 resize(size_+n, true);
00460 }
00461
00462 void extend(const jblas::ind_array& _ia)
00463 {
00464 resize(jmath::ublasExtra::ia_union(ia_, _ia));
00465 }
00466
00467
00468
00469 inline bool hasNullCov() const { return hasNullCov_; }
00470 inline storage_t storage() const { return storage_; }
00471 inline size_t size() const { return size_; }
00472 inline jblas::ind_array & ia() { return ia_; }
00473 inline const jblas::ind_array & ia() const { return ia_; }
00474 inline jblas::vec_indirect & x() { return x_; }
00475 inline const jblas::vec_indirect & x() const { return x_; }
00476 inline jblas::sym_mat_indirect & P() { return P_; }
00477 inline const jblas::sym_mat_indirect & P() const { return P_; }
00478 inline double & x(size_t i) { return x_(i); }
00479 inline double & P(size_t i, size_t j) { return P_(i, j); }
00480
00481
00482 inline void storage(const storage_t & _s) {
00483 storage_ = _s;
00484 if (_s == REMOTE)
00485 hasNullCov_ = false;
00486 }
00487 inline void hasNullCov(bool _hasNullCov) {
00488 hasNullCov_ = _hasNullCov;
00489 }
00490 inline void x(const jblas::vec & _x) {
00491 JFR_ASSERT(_x.size() == size_, "gaussian.hpp: set_x: size mismatch.");
00492 x_.assign(_x);
00493 }
00494 inline void P(const jblas::sym_mat & _P) {
00495 JFR_ASSERT(_P.size1() == size_, "gaussian.hpp: set_P: size mismatch.");
00496 hasNullCov_ = false;
00497 P_.assign(_P);
00498 }
00499
00504 inline void std(const jblas::vec& _std) {
00505 JFR_ASSERT(_std.size() == P_.size1(), "gaussian.hpp: set_P: size mismatch.");
00506 hasNullCov_ = false;
00507 P_.assign(jblas::zero_mat(size_));
00508 for (std::size_t i = 0; i < size_; i++) {
00509 P_(i, i) = _std(i) * _std(i);
00510 }
00511 }
00512
00517 inline void std(double _std) {
00518 hasNullCov_ = false;
00519 P_.assign(jblas::zero_mat(size_));
00520 for (std::size_t i = 0; i < size_; i++) {
00521 P_(i, i) = _std * _std;
00522 }
00523 }
00524
00532 inline void P(const jblas::mat & M, const jblas::ind_array & ia1, const jblas::ind_array & ia2) {
00533 hasNullCov_ = false;
00534 project(P_local, ia1, ia2) = M;
00535 }
00536
00541 virtual void clear(void) {
00542 x_.assign(jblas::zero_vec(size_));
00543 P_.assign(jblas::zero_mat(size_, size_));
00544 }
00545
00546
00551 double probabilityDensity(const jblas::vec& v) const;
00552
00559 friend std::ostream& operator <<(std::ostream & s, Gaussian const & g_) {
00560
00561 if (g_.storage() == LOCAL) {
00562 if (g_.hasNullCov()) {
00563 s << std::endl << " .x : " << g_.x_ << std::endl;
00564 }
00565 else {
00566 s << std::endl << " .x : " << g_.x_ << std::endl;
00567 s << " .P : " << g_.P_;
00568 }
00569 }
00570 else {
00571 s << " .ia: " << g_.ia_ << std::endl;
00572 s << " .x : " << g_.x_ << std::endl;
00573 s << " .P : " << g_.P_;
00574 }
00575 return s;
00576 }
00577
00578 };
00579
00580 }
00581 }
00582
00583 #endif