Kernel.h
Go to the documentation of this file.
1 // (C) Copyright Renaud Detry 2007-2015.
2 // Distributed under the GNU General Public License and under the
3 // BSD 3-Clause License (See accompanying file LICENSE.txt).
4 
5 /** @file */
6 
7 #ifndef NUKLEI_SPECIALIZED_KERNEL_H
8 #define NUKLEI_SPECIALIZED_KERNEL_H
9 
10 #include <iostream>
11 #include <boost/cast.hpp>
12 #include <boost/ptr_container/ptr_array.hpp>
13 
14 #include <nuklei/GenericKernel.h>
15 #include <nuklei/Descriptor.h>
16 #include <nuklei/Indenter.h>
17 
18 namespace nuklei {
19 
20  /** @brief Namespace containing kernel definitions. */
21  namespace kernel
22  {
23  class se3;
24  class base;
25 
26  //const bitfield_t EXACT = (1 << 0);
27 
28  /**
29  * @ingroup kernels
30  * @brief Polymorphic kernel class.
31  *
32  * This class serves as an abstract base for kernels defined on
33  * various subspaces of @f$ SE(3) @f$. See @ref kernels for a
34  * discussion of what a kernel is. See @ref programming_paradigm
35  * for an overview and motivation of the kernel class hierarchy.
36  *
37  * See @ref programming_paradigm for an explanation of why some of
38  * the methods begin with @p poly.
39  *
40  * In Nuklei, the kernel classes (kernel::base and its descendants) play the
41  * double role of representing kernels and points. For instance, there is no
42  * class specifically designed for holding an @f$ SE(3) @f$ point, the class
43  * kernel::se3 is used for that purpose.
44  */
45  class base
46  {
47  public:
48 
49  /** @brief NUKLEI_UNIQUE_PTR for kernel::base. */
50  typedef NUKLEI_UNIQUE_PTR< kernel::base > ptr;
51 
52  /** @brief Explicit query of a kernel's type. See @ref type for more info. */
53  typedef enum { R3 = 0, R3XS2, R3XS2P, SE3, UNKNOWN } Type;
54  /** @brief Explicit query of a kernel's type. See @ref type for more info. */
55  static const Type defaultType = SE3;
56  /** @brief Explicit query of a kernel's type. See @ref type for more info. */
57  static const std::string TypeNames[];
58  /** @} */
59 
60  protected:
61  base() : w_(1.), flag1_(0), bitfield_(0) {}
62 
63  base(const base& k) : w_(k.w_), flag1_(k.flag1_), bitfield_(k.bitfield_)
64  {
65  if (k.hasDescriptor()) desc_ = k.desc_->clone();
66  }
67 
68  base& operator=(const base& k)
69  {
70  w_ = k.w_;
71  flag1_ = k.flag1_;
72  bitfield_ = k.bitfield_;
73  // no problem with auto-assign here.
74  if (k.hasDescriptor()) desc_ = k.desc_->clone();
75  else desc_.reset();
76  return *this;
77  }
78 
79  public:
80  virtual ~base() {}
81 
82  virtual void assertConsistency() const = 0;
83 
84  /** @brief Calls polyPrint */
85  friend std::ostream& operator<<(std::ostream &out, const kernel::base &k);
86  /**
87  * @brief Prints the kernel parameters to the provided stream.
88  *
89  * The purpose of this method is debugging. It shouldn't be used
90  * for serialization.
91  */
92  virtual std::ostream& polyPrint(std::ostream &out) const = 0;
93 
94  /** @brief Weight-based kernel comparator. */
95  bool operator<(const kernel::base& k) const { return w_ < k.w_; }
96  /** @brief Weight-based kernel comparator. */
97  bool operator>(const kernel::base& k) const { return w_ > k.w_; }
98 
99  /** @brief Clone the kernel. */
100  virtual base::ptr clone() const = 0;
101  /** @brief Create a new kernel of the same type. */
102  virtual base::ptr create() const = 0;
103 
104  /** @brief Get the location component of the kernel. */
105  virtual Vector3 getLoc() const = 0;
106  /** @brief Set the location component of the kernel. */
107  virtual void setLoc(const Vector3 &v) = 0;
108 
109  /** @brief Get the location bandwidth. */
110  virtual coord_t getLocH() const = 0;
111  /** @brief Set the location bandwidth. */
112  virtual void setLocH(const coord_t h) = 0;
113  /**
114  * @brief Get the orientation bandwidth.
115  *
116  * This method is implemented in child classes. In classes that do not
117  * have an orientation (or a direction), this method returns 0.
118  */
119  virtual coord_t getOriH() const = 0;
120  /**
121  * @brief Set the orientation bandwidth.
122  *
123  * This method is implemented in child classes. In classes that do not
124  * have an orientation (or a direction), this method does nothing.
125  */
126  virtual void setOriH(const coord_t h) = 0;
127 
128  /** @brief Get the "kernel type", i.e., its domain of definition. */
129  virtual Type polyType() const = 0;
130 
131  /** @brief Evaluate the kernel at the location/orientation of @p k. */
132  virtual coord_t polyEval(const base &k) const = 0;
133  /** @brief Distance (from the origin) at which the value of the kernel becomes zero. */
134  virtual coord_t polyCutPoint() const = 0;
135  /** @brief Get a sample from the kernel. */
136  virtual base::ptr polySample() const = 0;
137  /**
138  * @brief Get an @f$ SE(3) @f$ sample from the kernel.
139  *
140  * Take a sample from the kernel. If the kernel is defined on a
141  * subspace of @f$ SE(3) @f$, make the sample @f$ SE(3) @f$ by
142  * selecting random values from a uniform distribution for the
143  * extra DOFs.
144  */
145  virtual NUKLEI_UNIQUE_PTR<kernel::se3> polySe3Sample() const = 0;
146  /**
147  * @brief Get an @f$ SE(3) @f$ version of the kernel.
148  *
149  * Take a sample from the kernel. If the kernel is defined on a
150  * subspace of @f$ SE(3) @f$, make it @f$ SE(3) @f$ by
151  * selecting random values from a uniform distribution for the
152  * extra DOFs.
153  */
154  virtual NUKLEI_UNIQUE_PTR<kernel::se3> polySe3Proj() const = 0;
155 
156  /**
157  * @addtogroup matrix_transfo
158  * @{
159  */
160  /**
161  * @brief Transforms @p *this with @p k and returns the
162  * result. (See @ref matrix_transfo.)
163  */
164  virtual base::ptr polyTransformedWith(const kernel::se3& k) const = 0;
165  /**
166  * @brief Transforms @p *this with @p k and sets @p *this to the
167  * result. (See @ref matrix_transfo.)
168  */
169  virtual void polyMakeTransformWith(const kernel::se3& k) = 0;
170  /**
171  * @brief Projects @p *this onto @p k and returns the
172  * result. (See @ref matrix_transfo.)
173  */
174  virtual base::ptr polyProjectedOn(const kernel::se3& k) const = 0;
175  /** @} */
176  /**
177  * @brief Interpolates between @p *this and @p k.
178  *
179  * For @p x = 0, this function returns @p *this. If @p x = 1, it
180  * returns @p k. For orientation, interpolation is done in
181  * Euclidean space. Slerp should be used instead. To be fixed
182  * soon.
183  */
185  const coord_t x = .5) const = 0;
186  /** @brief Used internally. */
187  virtual void polyUpdateWidth(const kernel::base& k,
188  const coord_t x = .5) = 0;
189  /**
190  * @brief Returns a std::pair containing the distance in
191  * position and orientation between @p *this and @p k.
192  */
193  virtual coord_pair polyDistanceTo(const kernel::base& k) const = 0;
194 
195  /**
196  * @brief Weight accessor for kernel::base. The accessor is used
197  * internally. Normal Nuklei users will generally not need it.
198  *
199  * Example:
200  * @code
201  * WeightAccessor wa;
202  * kernel::base& k = ...
203  * wa(k) == k.getWeight() // true
204  * @endcode
205  */
207  {
208  weight_t operator() (const base& k) const
209  { return k.w_; }
210  weight_t operator() (const base* k) const
211  { return k->w_; }
212  };
213 
214  /** @brief Returns this kernel's weight. */
215  weight_t getWeight() const { return w_; }
216  /** @brief Sets this kernel's weight. */
217  void setWeight(const weight_t w) { w_ = w; }
218 
219  bool hasDescriptor() const { return desc_.get() != NULL; }
220  Descriptor& getDescriptor()
221  { NUKLEI_ASSERT(hasDescriptor()); return *desc_; }
222  const Descriptor& getDescriptor() const
223  { NUKLEI_ASSERT(hasDescriptor()); return *desc_; }
224  void setDescriptor(const Descriptor& desc)
225  { desc_ = desc.clone(); }
226  void clearDescriptor() { desc_.reset(); }
227 
228  void setFlag(bitfield_t flag)
229  { bitfield_ |= flag; }
230  void resetFlag(bitfield_t flag)
231  { bitfield_ &= ~flag; }
232  bool getFlag(bitfield_t flag) const
233  { return (bitfield_ & flag) != 0; }
234 
235  protected:
236 
237  // The byte-size of this structure *must* be a multiple of 8.
238  // 32-bit Count:
239  // vtable ptr: 4;
240  // w_: 8;
241  // flag1_: 4;
242  // bitfield_: 4;
243  // desc_: 4;
244  // TOTAL: 24 ok.
245  // 64-bit Count:
246  // vtable ptr: 8;
247  // w_: 8;
248  // flag1_: 4;
249  // bitfield_: 4;
250  // desc_: 8;
251  // TOTAL: 32 ok.
252  // When not aligned, the kernel class behaves 2 times slower.
253 
254  weight_t w_;
255 
256  int flag1_;
257  bitfield_t bitfield_;
258 
259  NUKLEI_UNIQUE_PTR<Descriptor> desc_;
260 
261  friend class NUKLEI_SERIALIZATION_FRIEND_CLASSNAME;
262  template<class Archive>
263  void serialize(Archive &ar, const unsigned int version)
264  {
265  ar & NUKLEI_SERIALIZATION_NVP(w_);
266  ar & NUKLEI_SERIALIZATION_NVP(desc_);
267  }
268 
269  };
270 
271  inline kernel::base* new_clone(const kernel::base& k)
272  {
273  base::ptr c = k.clone();
274  return c.release();
275  }
276 
277  template<class T>
279  {
280  base::ptr clone() const
281  {
282  NUKLEI_TRACE_BEGIN();
283  return base::ptr(new T(*static_cast<const T*>(this)));
284  NUKLEI_TRACE_END();
285  }
286 
288  {
289  NUKLEI_TRACE_BEGIN();
290  return base::ptr(new T);
291  NUKLEI_TRACE_END();
292  }
293 
294  Vector3 getLoc() const
295  {
296  NUKLEI_TRACE_BEGIN();
297  return static_cast<const T*>(this)->loc_;
298  NUKLEI_TRACE_END();
299  }
300 
301  void setLoc(const Vector3 &v)
302  {
303  NUKLEI_TRACE_BEGIN();
304  static_cast<T*>(this)->loc_ = v;
305  NUKLEI_TRACE_END();
306  }
307 
308  std::ostream& polyPrint(std::ostream &out) const
309  {
310  NUKLEI_TRACE_BEGIN();
311  return static_cast<const T*>(this)->print(out);
312  NUKLEI_TRACE_END();
313  }
314 
315  Type polyType() const
316  {
317  NUKLEI_TRACE_BEGIN();
318  return static_cast<const T*>(this)->type();
319  NUKLEI_TRACE_END();
320  }
321 
322  coord_t polyEval(const base &k) const
323  {
324  NUKLEI_TRACE_BEGIN();
325  const T& down = dynamic_cast<const T&>(k);
326  return static_cast<const T*>(this)->eval(down);
327  NUKLEI_TRACE_END();
328  }
329 
331  {
332  NUKLEI_TRACE_BEGIN();
333  return static_cast<const T*>(this)->cutPoint();
334  NUKLEI_TRACE_END();
335  }
336 
338  {
339  NUKLEI_TRACE_BEGIN();
340  base::ptr s( new T(static_cast<const T*>(this)->sample()) );
341  return s;
342  NUKLEI_TRACE_END();
343  }
344 
345  NUKLEI_UNIQUE_PTR<kernel::se3> polySe3Sample() const;
346 
347  NUKLEI_UNIQUE_PTR<kernel::se3> polySe3Proj() const;
348 
350  {
351  NUKLEI_TRACE_BEGIN();
352  base::ptr s( new T(static_cast<const T*>(this)->projectedOn(k)) );
353  return s;
354  NUKLEI_TRACE_END();
355  }
356 
358  {
359  NUKLEI_TRACE_BEGIN();
360  base::ptr s( new T(static_cast<const T*>(this)->transformedWith(k)) );
361  return s;
362  NUKLEI_TRACE_END();
363  }
364 
366  {
367  NUKLEI_TRACE_BEGIN();
368  static_cast<T*>(this)->makeTransformWith(k);
369  NUKLEI_TRACE_END();
370  }
371 
373  const coord_t x) const
374  {
375  NUKLEI_TRACE_BEGIN();
376  const T& down = dynamic_cast<const T&>(k);
377  base::ptr s( new T(static_cast<const T*>(this)->linearInterpolation(down, x)) );
378  return s;
379  NUKLEI_TRACE_END();
380  }
381 
383  const coord_t x = .5)
384  {
385  NUKLEI_TRACE_BEGIN();
386  const T& down = dynamic_cast<const T&>(k);
387  static_cast<T*>(this)->updateWidth(down, x);
388  NUKLEI_TRACE_END();
389  }
390 
392  {
393  NUKLEI_TRACE_BEGIN();
394  const T& down = dynamic_cast<const T&>(k);
395  return static_cast<const T*>(this)->distanceTo(down);
396  NUKLEI_TRACE_END();
397  }
398 
399  protected:
401  };
402 
403  /** @ingroup kernels */
404  class se3 : public implementation_prototype<se3>
405  {
406  public:
407  typedef NUKLEI_UNIQUE_PTR<kernel::se3> ptr;
408 
412 
413  se3() :
414  loc_(Vector3::ZERO), ori_(Quaternion::IDENTITY),
415  loc_h_(0), ori_h_(0)
416  {}
417 
418  // Is this wise?
419  explicit se3(const kernel::base& k)
420  { *this = dynamic_cast<const kernel::se3&>(k); }
421 
422  void assertConsistency() const;
423 
424  std::ostream& print(std::ostream &out) const;
425 
426  coord_t getLocH() const { return loc_h_; }
427  void setLocH(const coord_t h) { loc_h_ = h; }
428  coord_t getOriH() const { return ori_h_; }
429  void setOriH(const coord_t h) { ori_h_ = h; }
430 
431  Type type() const;
432 
433  /**
434  * @brief Evaluates this kernel at pose @p k.
435  *
436  * This function returns
437  * @f[
438  * \mathcal K_{SE(3)}\left(\lambda, \theta ; \mu_t, \mu_r, \sigma_t, \sigma_r\right),
439  * @f]
440  * where the arguments of @f$ \mathcal K_{SE(3)} @f$ are respectively equal to @p
441  * k.loc_, @p k.ori_, @p this->loc_, @p this->ori_, @p this->loc_h_, @p
442  * this->ori_h_.
443  * See @ref kernels for the definition of @f$ \mathcal K_{SE(3)} @f$.
444  *
445  * <b>Note:</b> @p this->ori_h_ should be expressed in radians.
446  */
447  inline coord_t eval(const kernel::se3& k) const;
448  inline coord_t cutPoint() const;
449  /**
450  * @brief Returns a sample taken from this kernel.
451  *
452  * This function returns a sample @f$ (\lambda, \theta) @f$ drawn from
453  * @f[
454  * \mathcal K'_{SE(3)}\left(\lambda, \theta ; \mu_t, \mu_r, \sigma_t, \sigma_r\right),
455  * @f]
456  * where the four last arguments of @f$ \mathcal K'_{SE(3)} @f$ are respectively
457  * equal to @p this->loc_, @p this->ori_, @p this->loc_h_, @p
458  * this->ori_h_.
459  * See @ref kernels for the definition of @f$ \mathcal K'_{SE(3)} @f$.
460  *
461  * <b>Note:</b> @p this->ori_h_ should be expressed in radians.
462  */
463  kernel::se3 sample() const;
464  kernel::se3 se3Sample() const;
465  kernel::se3 se3Proj() const;
466 
467  kernel::se3 projectedOn(const kernel::se3& k) const;
468  kernel::se3 transformedWith(const kernel::se3& k) const;
469  void makeTransformWith(const kernel::se3& k);
470  kernel::se3 transformationFrom(const kernel::se3& k) const;
471  kernel::se3 inverseTransformation() const;
472 
473  kernel::se3 linearInterpolation(const kernel::se3& k,
474  const coord_t x) const;
475  void updateWidth(const kernel::se3& k,
476  const coord_t x = .5);
477  coord_pair distanceTo(const kernel::se3& k) const;
478 
479  /** @brief Kernel location. */
480  Vector3 loc_;
481  /** @brief Kernel orientation. */
482  Quaternion ori_;
483  /** @brief Location bandwidth. */
485  /** @brief Orientation bandwidth, in radians. */
487 
488  private:
489  friend class NUKLEI_SERIALIZATION_FRIEND_CLASSNAME;
490  template<class Archive>
491  void serialize(Archive &ar, const unsigned int version)
492  {
493  ar & NUKLEI_SERIALIZATION_MAKE_NVP
494  ( "base",
495  NUKLEI_SERIALIZATION_BASE(base) );
496  ar & NUKLEI_SERIALIZATION_NVP(loc_)
497  & NUKLEI_SERIALIZATION_NVP(ori_)
498  & NUKLEI_SERIALIZATION_NVP(loc_h_)
499  & NUKLEI_SERIALIZATION_NVP(ori_h_);
500  }
501  };
502 
503  /** @ingroup kernels */
504  template<class OriGrp>
505  class r3xs2_base : public implementation_prototype< r3xs2_base<OriGrp> >
506  {
507  public:
508  typedef NUKLEI_UNIQUE_PTR< kernel::r3xs2_base<OriGrp> > ptr;
509 
511  using Super::getWeight;
512  using Super::setWeight;
513  using Super::hasDescriptor;
514  using Super::getDescriptor;
515  using Super::setDescriptor;
516  using Super::getFlag;
517 
521 
522  r3xs2_base() :
523  loc_(Vector3::ZERO), dir_(Vector3::UNIT_X),
524  loc_h_(0), dir_h_(0)
525  {}
526 
527  // Is this wise?
528  explicit r3xs2_base(const kernel::base& k)
529  { *this = dynamic_cast<const kernel::r3xs2_base<OriGrp>&>(k); }
530 
531  void assertConsistency() const;
532 
533  std::ostream& print(std::ostream &out) const;
534 
535  coord_t getLocH() const { return loc_h_; }
536  void setLocH(const coord_t h) { loc_h_ = h; }
537  coord_t getOriH() const { return dir_h_; }
538  void setOriH(const coord_t h) { dir_h_ = h; }
539 
540  base::Type type() const;
541 
542  /**
543  * @brief Evaluates this kernel at pose @p k.
544  *
545  * <b>Note:</b> This doc describes the behavior of this method when @p
546  * OriGrp is groupS::s2p, i.e., when the object on which the method is
547  * called is of type kernel::r3xs2p.
548  *
549  * This function returns
550  * @f[
551  * \mathcal K_{RSA}\left(\lambda, \theta ; \mu_t, \mu_r, \sigma_t, \sigma_r\right),
552  * @f]
553  * where the arguments of @f$ \mathcal K_{RSA} @f$ are respectively equal to @p
554  * k.loc_, @p k.dir_, @p this->loc_, @p this->dir_, @p this->loc_h_, @p
555  * this->dir_h_.
556  * See @ref kernels for the definition of @f$ \mathcal K_{RSA} @f$.
557  *
558  * <b>Note:</b> @p this->dir_h_ should be expressed in radians.
559  */
560  inline coord_t eval(const kernel::r3xs2_base<OriGrp>& k) const;
561  inline coord_t cutPoint() const;
562  /**
563  * @brief Returns a sample taken from this kernel.
564  *
565  * <b>Note:</b> This doc describes the behavior of this method when @p
566  * OriGrp is groupS::s2p, i.e., when the object on which the method is
567  * called is of type kernel::r3xs2p.
568  *
569  * This function returns a sample @f$ (\lambda, \theta) @f$ drawn from
570  * @f[
571  * \mathcal K'_{RSA}\left(\lambda, \theta ; \mu_t, \mu_r, \sigma_t, \sigma_r\right),
572  * @f]
573  * where the four last arguments of @f$ \mathcal K'_{RSA} @f$ are respectively
574  * equal to @p this->loc_, @p this->dir_, @p this->loc_h_, @p
575  * this->dir_h_.
576  * See @ref kernels for the definition of @f$ \mathcal K'_{RSA} @f$.
577  *
578  * <b>Note:</b> @p this->dir_h_ should be expressed in radians.
579  */
581  kernel::se3 se3Sample() const;
582  kernel::se3 se3Proj() const;
583 
584  kernel::r3xs2_base<OriGrp> projectedOn(const kernel::se3& k) const;
585  kernel::r3xs2_base<OriGrp> transformedWith(const kernel::se3& k) const;
586  void makeTransformWith(const kernel::se3& k);
587 
588  kernel::r3xs2_base<OriGrp> linearInterpolation(const kernel::r3xs2_base<OriGrp>& k,
589  const coord_t x) const;
590  void updateWidth(const kernel::r3xs2_base<OriGrp>& k,
591  const coord_t x = .5);
592  coord_pair distanceTo(const kernel::r3xs2_base<OriGrp>& k) const;
593 
594  Vector3 loc_;
595  Vector3 dir_;
596  coord_t loc_h_;
597  coord_t dir_h_;
598 
599  private:
600  friend class NUKLEI_SERIALIZATION_FRIEND_CLASSNAME;
601  template<class Archive>
602  void serialize(Archive &ar, const unsigned int version)
603  {
604  ar & NUKLEI_SERIALIZATION_MAKE_NVP
605  ( "base",
606  NUKLEI_SERIALIZATION_BASE(base) );
607  ar & NUKLEI_SERIALIZATION_NVP(loc_)
608  & NUKLEI_SERIALIZATION_NVP(dir_)
609  & NUKLEI_SERIALIZATION_NVP(loc_h_)
610  & NUKLEI_SERIALIZATION_NVP(dir_h_);
611  }
612  };
613 
614  /**
615  * @ingroup kernels
616  * @brief @f$ \mathbb R^3 \times S^2 @f$
617  */
619  /**
620  * @ingroup kernels
621  * @brief @f$ \mathbb R^3 \times S^2_p @f$
622  */
624 
625  /** @ingroup kernels */
626  class r3 : public implementation_prototype<r3>
627  {
628  public:
629  typedef NUKLEI_UNIQUE_PTR<kernel::r3> ptr;
630 
633 
634  r3() :
635  loc_(Vector3::ZERO),
636  loc_h_(0)
637  {}
638 
639  // Is this wise?
640  explicit r3(const kernel::base& k)
641  { *this = dynamic_cast<const kernel::r3&>(k); }
642 
643  void assertConsistency() const;
644 
645  std::ostream& print(std::ostream &out) const;
646 
647  coord_t getLocH() const { return loc_h_; }
648  void setLocH(const coord_t h) { loc_h_ = h; }
649  coord_t getOriH() const { return 0.; }
650  void setOriH(const coord_t h) { }
651 
652  Type type() const;
653 
654  /**
655  * @brief Evaluates this kernel at pose @p k.
656  *
657  * This function returns
658  * @f[
659  * \mathcal K_{\mathbb R^3}\left(\lambda ; \mu_t, \sigma_t\right),
660  * @f]
661  * where the arguments of @f$ \mathcal K_{\mathbb R^3} @f$ are respectively equal to @p
662  * k.loc_, @p this->loc_, @p this->loc_h_.
663  * See @ref kernels for the definition of @f$ \mathcal K_{\mathbb R^3} @f$.
664  */
665  inline coord_t eval(const kernel::r3& k) const;
666  inline coord_t cutPoint() const;
667  /**
668  * @brief Returns a sample taken from this kernel.
669  *
670  * This function returns a sample @f$ \lambda @f$ drawn from
671  * @f[
672  * \mathcal K_{\mathbb R^3}\left(\lambda ; \mu_t, \sigma_t\right),
673  * @f]
674  * where the two last arguments of @f$ \mathcal K_{\mathbb R^3} @f$ are
675  * respectively equal to @p this->loc_, @p this->loc_h_.
676  * See @ref kernels for the definition of @f$ \mathcal K_{\mathbb R^3} @f$.
677  */
678  kernel::r3 sample() const;
679  kernel::se3 se3Sample() const;
680  kernel::se3 se3Proj() const;
681 
682  kernel::r3 projectedOn(const kernel::se3& k) const;
683  kernel::r3 transformedWith(const kernel::se3& k) const;
684  void makeTransformWith(const kernel::se3& k);
685 
686  kernel::r3 linearInterpolation(const kernel::r3& k,
687  const coord_t x) const;
688  void updateWidth(const kernel::r3& k,
689  const coord_t x = .5);
690  coord_pair distanceTo(const kernel::r3& k) const;
691 
692  Vector3 loc_;
693  coord_t loc_h_;
694 
695  private:
696  friend class NUKLEI_SERIALIZATION_FRIEND_CLASSNAME;
697  template<class Archive>
698  void serialize(Archive &ar, const unsigned int version)
699  {
700  ar & NUKLEI_SERIALIZATION_MAKE_NVP
701  ( "base",
702  NUKLEI_SERIALIZATION_BASE(base) );
703  ar & NUKLEI_SERIALIZATION_NVP(loc_)
704  & NUKLEI_SERIALIZATION_NVP(loc_h_);
705  }
706  };
707 
708  inline
709  coord_t se3::eval(const kernel::se3& k) const
710  {
711  coord_t r3e = PositionKernel::eval(loc_, loc_h_, k.loc_);
712  if (r3e < FLOATTOL) return 0;
713  else return r3e * OrientationKernel::eval(ori_, ori_h_, k.ori_);
714  }
715 
716  template<class OriGrp>
718  {
719  coord_t r3e = PositionKernel::eval(loc_, loc_h_, k.loc_);
720  if (r3e < FLOATTOL) return 0;
721  else return r3e * OrientationKernel::eval(dir_, dir_h_, k.dir_);
722  }
723 
724  inline
725  coord_t r3::eval(const kernel::r3& k) const
726  {
727  return PositionKernel::eval(loc_, loc_h_, k.loc_);
728  }
729 
730 
731  inline
732  coord_t se3::cutPoint() const
733  {
734  return PositionKernel::cut_point(loc_h_);
735  }
736 
737  template<class OriGrp>
738  coord_t r3xs2_base<OriGrp>::cutPoint() const
739  {
740  return PositionKernel::cut_point(loc_h_);
741  }
742 
743  inline
744  coord_t r3::cutPoint() const
745  {
746  return PositionKernel::cut_point(loc_h_);
747  }
748 
749 
750  // S2P defs. The lib will also compile if these are in the .cpp file.
751  // However, although execution will be fine under linux, it will fail
752  // on the mac (dynamic_cast throws STL bad cast exception when casting
753  // from base to r3xs2).
754 
755  template<class OriGrp>
756  void r3xs2_base<OriGrp>::assertConsistency() const
757  {
758  NUKLEI_TRACE_BEGIN();
759  NUKLEI_ASSERT(getWeight() >= 0);
760  NUKLEI_ASSERT(loc_h_ >= 0);
761  NUKLEI_ASSERT(dir_h_ >= 0);
762  NUKLEI_TRACE_END();
763  }
764 
765  template<> inline
766  std::ostream&
767  kernel::r3xs2_base<groupS::s2>::print(std::ostream &out) const
768  {
769  Indenter idt(out);
770  idt << "Kernel R^3 x S^2: [ weight = " << w_ << " ]" << std::endl;
771  {
772  Indenter idt2(out);
773  idt2 << "Location: " << loc_ << std::endl;
774  idt2 << "LocWidth: " << loc_h_ << std::endl;
775  idt2 << "Direction: " << dir_ << std::endl;
776  idt2 << "DirWidth: " << dir_h_ << std::endl;
777  }
778  return out;
779  }
780 
781  template<> inline
782  std::ostream&
783  kernel::r3xs2_base<groupS::s2p>::print(std::ostream &out) const
784  {
785  Indenter idt(out);
786  idt << "Kernel R^3 x S^2_+: [ weight = " << w_ << " ]" << std::endl;
787  {
788  Indenter idt2(out);
789  idt2 << "Location: " << loc_ << std::endl;
790  idt2 << "LocWidth: " << loc_h_ << std::endl;
791  idt2 << "Direction: " << dir_ << std::endl;
792  idt2 << "DirWidth: " << dir_h_ << std::endl;
793  }
794  return out;
795  }
796 
797  template<> inline
798  kernel::base::Type kernel::r3xs2_base<groupS::s2>::type() const
799  {
800  return R3XS2;
801  }
802 
803  template<> inline
804  kernel::base::Type kernel::r3xs2_base<groupS::s2p>::type() const
805  {
806  return R3XS2P;
807  }
808 
809  //template<class OriGrp>
810  //coord_t r3xs2_base<OriGrp>::eval(const kernel::r3xs2_base<OriGrp>& k) const
811  //cf. header.
812 
813  template<class OriGrp>
815  {
817 
818  typedef nuklei::sampler<PositionKernel> PositionSampler;
819  typedef nuklei::sampler<OrientationKernel> OrientationSampler;
820 
821  s.loc_ = PositionSampler::s(loc_, loc_h_);
822  s.dir_ = OrientationSampler::s(dir_, dir_h_);
823 
824  if (hasDescriptor()) s.setDescriptor(getDescriptor());
825  return s;
826  }
827 
828  template<class OriGrp>
830  {
831  kernel::r3xs2_base<OriGrp> r3xs2pk = sample();
832  kernel::se3 se3k;
833  se3k.loc_ = r3xs2pk.loc_;
834  se3k.ori_ = la::so3FromS2(r3xs2pk.dir_);
835  if (hasDescriptor()) se3k.setDescriptor(getDescriptor());
836  return se3k;
837  }
838 
839  template<> inline
842  {
843  kernel::r3xs2_base<groupS::s2> r3xs2pk = *this;
844  kernel::se3 se3k;
845  se3k.loc_ = r3xs2pk.loc_;
846  se3k.ori_ = la::so3FromS2(r3xs2pk.dir_);
847  if (hasDescriptor()) se3k.setDescriptor(getDescriptor());
848  return se3k;
849  }
850 
851  template<> inline
852  kernel::se3
853  kernel::r3xs2_base<groupS::s2p>::se3Proj() const
854  {
855  kernel::r3xs2_base<groupS::s2p> r3xs2pk = *this;
856  kernel::se3 se3k;
857  se3k.loc_ = r3xs2pk.loc_;
858  if (Random::uniformInt(2) == 0)
859  se3k.ori_ = la::so3FromS2(r3xs2pk.dir_);
860  else
861  se3k.ori_ = la::so3FromS2(-r3xs2pk.dir_);
862  if (hasDescriptor()) se3k.setDescriptor(getDescriptor());
863  return se3k;
864  }
865 
866  template<class OriGrp>
867  kernel::r3xs2_base<OriGrp> r3xs2_base<OriGrp>::projectedOn(const kernel::se3& k) const
868  {
869  kernel::r3xs2_base<OriGrp> p;
870  la::project(p.loc_, p.dir_, k.loc_, k.ori_, loc_, dir_);
871  if (hasDescriptor()) p.setDescriptor(getDescriptor());
872  return p;
873  }
874 
875  template<class OriGrp>
876  kernel::r3xs2_base<OriGrp> r3xs2_base<OriGrp>::transformedWith(const kernel::se3& k) const
877  {
878  kernel::r3xs2_base<OriGrp> p;
879  la::transform(p.loc_, p.dir_, k.loc_, k.ori_, loc_, dir_);
880  if (hasDescriptor()) p.setDescriptor(getDescriptor());
881  return p;
882  }
883 
884  template<class OriGrp>
885  void r3xs2_base<OriGrp>::makeTransformWith(const kernel::se3& k)
886  {
887  la::transform(loc_, dir_, k.loc_, k.ori_, loc_, dir_);
888  }
889 
890  template<> inline
891  kernel::r3xs2_base<groupS::s2>
892  kernel::r3xs2_base<groupS::s2>::linearInterpolation
893  (const kernel::r3xs2_base<groupS::s2>& k,
894  const coord_t x) const
895  {
896  NUKLEI_ASSERT(0 <= x && x <= 1);
897  kernel::r3xs2_base<groupS::s2> i;
898  i.loc_ = (1-x) * loc_ + x * k.loc_;
899  i.dir_ = la::normalized( (1-x) * dir_ + x * i.dir_ );
900  return i;
901  }
902 
903  template<> inline
904  kernel::r3xs2_base<groupS::s2p>
905  kernel::r3xs2_base<groupS::s2p>::linearInterpolation
906  (const kernel::r3xs2_base<groupS::s2p>& k,
907  const coord_t x) const
908  {
909  NUKLEI_ASSERT(0 <= x && x <= 1);
910  kernel::r3xs2_base<groupS::s2p> i;
911  i.loc_ = (1-x) * loc_ + x * k.loc_;
912  Vector3 d = k.dir_;
913  if (dir_.Dot(d) < 0) d = - d;
914  i.dir_ = la::normalized( (1-x) * dir_ + x * d );
915  return i;
916  }
917 
918  template<class OriGrp>
919  void
920  kernel::r3xs2_base<OriGrp>::updateWidth
921  (const kernel::r3xs2_base<OriGrp>& k,
922  const coord_t x)
923  {
924  loc_h_ = std::sqrt( (1-x) * loc_h_*loc_h_ +
925  x * std::pow(dist<groupS::r3>::d(loc_, k.loc_), 2) );
926  dir_h_ = std::sqrt( (1-x) * dir_h_*dir_h_ +
927  x * std::pow(dist<OriGrp>::d(dir_, k.dir_), 2) );
928  }
929 
930  template<class OriGrp>
931  coord_pair
932  kernel::r3xs2_base<OriGrp>::distanceTo(const kernel::r3xs2_base<OriGrp>& k) const
933  {
934  return std::make_pair(dist<groupS::r3>::d(loc_, k.loc_),
935  dist<OriGrp>::d(dir_, k.dir_));
936  }
937 
938 
939  template<class T>
940  NUKLEI_UNIQUE_PTR<kernel::se3>
942  {
943  NUKLEI_TRACE_BEGIN();
944  NUKLEI_UNIQUE_PTR<se3> p( new se3(static_cast<const T*>(this)->se3Sample()) );
945  return p;
946  NUKLEI_TRACE_END();
947  }
948 
949  template<class T>
950  NUKLEI_UNIQUE_PTR<kernel::se3>
952  {
953  NUKLEI_TRACE_BEGIN();
954  NUKLEI_UNIQUE_PTR<se3> p( new se3(static_cast<const T*>(this)->se3Proj()) );
955  return p;
956  NUKLEI_TRACE_END();
957  }
958 
959 
960  }
961 }
962 
963 #if BOOST_VERSION < 104100
964 
965 #else
966 
967 NUKLEI_SERIALIZATION_DECLARE_TYPE_WITH_NAME(nuklei::kernel::se3, "mdfh_kernel_se3")
968 NUKLEI_SERIALIZATION_DECLARE_TYPE_WITH_NAME(nuklei::kernel::r3xs2, "mdfh_kernel_r3xs2")
969 NUKLEI_SERIALIZATION_DECLARE_TYPE_WITH_NAME(nuklei::kernel::r3xs2p, "mdfh_kernel_r3xs2p")
970 NUKLEI_SERIALIZATION_DECLARE_TYPE_WITH_NAME(nuklei::kernel::r3, "mdfh_kernel_r3")
971 
972 #endif // BOOST_VERSION
973 
974 #endif
virtual void setLoc(const Vector3 &v)=0
Set the location component of the kernel.
Quaternion ori_
Kernel orientation.
Definition: Kernel.h:482
Type
Explicit query of a kernel's type. See Type Queries for more info.
Definition: Kernel.h:53
coord_t polyEval(const base &k) const
Evaluate the kernel at the location/orientation of k.
Definition: Kernel.h:322
coord_t ori_h_
Orientation bandwidth, in radians.
Definition: Kernel.h:486
virtual base::ptr polyLinearInterpolation(const kernel::base &k, const coord_t x=.5) const =0
Interpolates between *this and k.
virtual void setLocH(const coord_t h)=0
Set the location bandwidth.
base::ptr polyLinearInterpolation(const kernel::base &k, const coord_t x) const
Interpolates between *this and k.
Definition: Kernel.h:372
Public namespace.
Definition: Color.cpp:9
std::pair< coord_t, coord_t > coord_pair
Pair of coord_t.
Definition: Definitions.h:27
kernel::r3 sample() const
Returns a sample taken from this kernel.
Definition: Kernel.cpp:188
virtual void polyUpdateWidth(const kernel::base &k, const coord_t x=.5)=0
Used internally.
void setOriH(const coord_t h)
Set the orientation bandwidth.
Definition: Kernel.h:429
double weight_t
Type for particle weights.
Definition: Definitions.h:31
void setLoc(const Vector3 &v)
Set the location component of the kernel.
Definition: Kernel.h:301
coord_t eval(const kernel::se3 &k) const
Evaluates this kernel at pose k.
Definition: Kernel.h:709
virtual NUKLEI_UNIQUE_PTR< kernel::se3 > polySe3Proj() const =0
Get an version of the kernel.
Type polyType() const
Get the "kernel type", i.e., its domain of definition.
Definition: Kernel.h:315
virtual coord_t getLocH() const =0
Get the location bandwidth.
virtual Vector3 getLoc() const =0
Get the location component of the kernel.
coord_t eval(const kernel::r3 &k) const
Evaluates this kernel at pose k.
Definition: Kernel.h:725
coord_t eval(const kernel::r3xs2_base< OriGrp > &k) const
Evaluates this kernel at pose k.
Definition: Kernel.h:717
Definition: Kernel.h:404
void polyMakeTransformWith(const kernel::se3 &k)
Transforms *this with k and sets *this to the result. (See Operations on Poses.)
Definition: Kernel.h:365
Vector3 getLoc() const
Get the location component of the kernel.
Definition: Kernel.h:294
virtual base::ptr create() const =0
Create a new kernel of the same type.
base::ptr polyTransformedWith(const kernel::se3 &k) const
Transforms *this with k and returns the result. (See Operations on Poses.)
Definition: Kernel.h:357
Vector3 loc_
Kernel location.
Definition: Kernel.h:480
r3xs2_base< groupS::s2p > r3xs2p
Definition: Kernel.h:623
coord_t getLocH() const
Get the location bandwidth.
Definition: Kernel.h:647
static const Type defaultType
Explicit query of a kernel's type. See Type Queries for more info.
Definition: Kernel.h:55
Vector3 transform(const Vector3 &x, const Matrix3 &X, const Vector3 &y)
Returns .
virtual coord_pair polyDistanceTo(const kernel::base &k) const =0
Returns a std::pair containing the distance in position and orientation between *this and k.
virtual coord_t getOriH() const =0
Get the orientation bandwidth.
coord_t getLocH() const
Get the location bandwidth.
Definition: Kernel.h:426
std::ostream & polyPrint(std::ostream &out) const
Prints the kernel parameters to the provided stream.
Definition: Kernel.h:308
unsigned int bitfield_t
Type for bitfield.
Definition: Definitions.h:33
void setOriH(const coord_t h)
Set the orientation bandwidth.
Definition: Kernel.h:538
NUKLEI_UNIQUE_PTR< kernel::se3 > polySe3Sample() const
Get an sample from the kernel.
Definition: Kernel.h:941
void setLocH(const coord_t h)
Set the location bandwidth.
Definition: Kernel.h:427
virtual coord_t polyEval(const base &k) const =0
Evaluate the kernel at the location/orientation of k.
coord_t getOriH() const
Get the orientation bandwidth.
Definition: Kernel.h:649
virtual base::ptr polyTransformedWith(const kernel::se3 &k) const =0
Transforms *this with k and returns the result. (See Operations on Poses.)
weight_t getWeight() const
Returns this kernel's weight.
Definition: Kernel.h:215
virtual coord_t polyCutPoint() const =0
Distance (from the origin) at which the value of the kernel becomes zero.
#define NUKLEI_ASSERT(expression)
Throws an Error if expression is not true.
Definition: Common.h:113
Polymorphic kernel class.
Definition: Kernel.h:45
virtual base::ptr polySample() const =0
Get a sample from the kernel.
r3xs2_base< groupS::s2 > r3xs2
Definition: Kernel.h:618
static unsigned long int uniformInt(unsigned long int n)
This function returns a random integer from 0 to n-1 inclusive.
Definition: Random.cpp:195
base::ptr polyProjectedOn(const kernel::se3 &k) const
Projects *this onto k and returns the result. (See Operations on Poses.)
Definition: Kernel.h:349
void setOriH(const coord_t h)
Set the orientation bandwidth.
Definition: Kernel.h:650
void setLocH(const coord_t h)
Set the location bandwidth.
Definition: Kernel.h:536
void setWeight(const weight_t w)
Sets this kernel's weight.
Definition: Kernel.h:217
kernel::se3 sample() const
Returns a sample taken from this kernel.
Definition: Kernel.cpp:61
NUKLEI_UNIQUE_PTR< kernel::base > ptr
NUKLEI_UNIQUE_PTR for kernel::base.
Definition: Kernel.h:50
void polyUpdateWidth(const kernel::base &k, const coord_t x=.5)
Used internally.
Definition: Kernel.h:382
Definition: Kernel.h:505
base::ptr create() const
Create a new kernel of the same type.
Definition: Kernel.h:287
double coord_t
Type for point coordinates.
Definition: Definitions.h:25
bool operator>(const kernel::base &k) const
Weight-based kernel comparator.
Definition: Kernel.h:97
void setLocH(const coord_t h)
Set the location bandwidth.
Definition: Kernel.h:648
base::ptr polySample() const
Get a sample from the kernel.
Definition: Kernel.h:337
friend std::ostream & operator<<(std::ostream &out, const kernel::base &k)
Calls polyPrint.
Definition: Kernel.cpp:21
coord_pair polyDistanceTo(const kernel::base &k) const
Returns a std::pair containing the distance in position and orientation between *this and k.
Definition: Kernel.h:391
Definition: Kernel.h:626
coord_t loc_h_
Location bandwidth.
Definition: Kernel.h:484
kernel::r3xs2_base< OriGrp > sample() const
Returns a sample taken from this kernel.
Definition: Kernel.h:814
Weight accessor for kernel::base. The accessor is used internally. Normal Nuklei users will generally...
Definition: Kernel.h:206
virtual base::ptr polyProjectedOn(const kernel::se3 &k) const =0
Projects *this onto k and returns the result. (See Operations on Poses.)
Definition: GenericKernel.h:22
coord_t polyCutPoint() const
Distance (from the origin) at which the value of the kernel becomes zero.
Definition: Kernel.h:330
Definition: GenericKernel.h:38
virtual Type polyType() const =0
Get the "kernel type", i.e., its domain of definition.
NUKLEI_UNIQUE_PTR< kernel::se3 > polySe3Proj() const
Get an version of the kernel.
Definition: Kernel.h:951
coord_t getLocH() const
Get the location bandwidth.
Definition: Kernel.h:535
coord_t getOriH() const
Get the orientation bandwidth.
Definition: Kernel.h:428
static const std::string TypeNames[]
Explicit query of a kernel's type. See Type Queries for more info.
Definition: Kernel.h:57
virtual std::ostream & polyPrint(std::ostream &out) const =0
Prints the kernel parameters to the provided stream.
Definition: Kernel.h:278
coord_t getOriH() const
Get the orientation bandwidth.
Definition: Kernel.h:537
base::ptr clone() const
Clone the kernel.
Definition: Kernel.h:280
bool operator<(const kernel::base &k) const
Weight-based kernel comparator.
Definition: Kernel.h:95
virtual NUKLEI_UNIQUE_PTR< kernel::se3 > polySe3Sample() const =0
Get an sample from the kernel.
Vector3 project(const Vector3 &x, const Matrix3 &X, const Vector3 &z)
Returns .
virtual base::ptr clone() const =0
Clone the kernel.
virtual void polyMakeTransformWith(const kernel::se3 &k)=0
Transforms *this with k and sets *this to the result. (See Operations on Poses.)
virtual void setOriH(const coord_t h)=0
Set the orientation bandwidth.
Definition: Descriptor.h:19
© Copyright 2007-2013 Renaud Detry.
Distributed under the terms of the GNU General Public License (GPL).
(See accompanying file LICENSE.txt or copy at http://www.gnu.org/copyleft/gpl.html.)
Revised Sun Sep 13 2020 19:10:06.