gtsam  4.0.0
gtsam
NonlinearFactor.h
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2 
3  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4  * Atlanta, Georgia 30332-0415
5  * All Rights Reserved
6  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8  * See LICENSE for the license information
9 
10  * -------------------------------------------------------------------------- */
11 
19 // \callgraph
20 
21 #pragma once
22 
23 #include <gtsam/nonlinear/Values.h>
26 #include <gtsam/inference/Factor.h>
28 
29 #include <boost/serialization/base_object.hpp>
30 #include <boost/assign/list_of.hpp>
31 
36 #define ADD_CLONE_NONLINEAR_FACTOR(Derived) \
37  virtual gtsam::NonlinearFactor::shared_ptr clone() const { \
38  return boost::static_pointer_cast<gtsam::NonlinearFactor>( \
39  gtsam::NonlinearFactor::shared_ptr(new Derived(*this))); }
40 
41 namespace gtsam {
42 
43 using boost::assign::cref_list_of;
44 
45 /* ************************************************************************* */
46 
52 class GTSAM_EXPORT NonlinearFactor: public Factor {
53 
54 protected:
55 
56  // Some handy typedefs
57  typedef Factor Base;
58  typedef NonlinearFactor This;
59 
60 public:
61 
62  typedef boost::shared_ptr<This> shared_ptr;
63 
66 
69 
73  template<typename CONTAINER>
74  NonlinearFactor(const CONTAINER& keys) :
75  Base(keys) {}
76 
80 
82  virtual void print(const std::string& s = "",
83  const KeyFormatter& keyFormatter = DefaultKeyFormatter) const;
84 
86  virtual bool equals(const NonlinearFactor& f, double tol = 1e-9) const;
90 
92  virtual ~NonlinearFactor() {}
93 
94 
100  virtual double error(const Values& c) const = 0;
101 
103  virtual size_t dim() const = 0;
104 
115  virtual bool active(const Values& /*c*/) const { return true; }
116 
118  virtual boost::shared_ptr<GaussianFactor>
119  linearize(const Values& c) const = 0;
120 
127  virtual shared_ptr clone() const {
128  // TODO: choose better exception to throw here
129  throw std::runtime_error("NonlinearFactor::clone(): Attempting to clone factor with no clone() implemented!");
130  return shared_ptr();
131  }
132 
138  shared_ptr rekey(const std::map<Key,Key>& rekey_mapping) const;
139 
144  shared_ptr rekey(const std::vector<Key>& new_keys) const;
145 
146 }; // \class NonlinearFactor
147 
149 template<> struct traits<NonlinearFactor> : public Testable<NonlinearFactor> {
150 };
151 
152 /* ************************************************************************* */
163 class GTSAM_EXPORT NoiseModelFactor: public NonlinearFactor {
164 
165 protected:
166 
167  // handy typedefs
168  typedef NonlinearFactor Base;
169  typedef NoiseModelFactor This;
170 
171  SharedNoiseModel noiseModel_;
173 public:
174 
175  typedef boost::shared_ptr<This> shared_ptr;
176 
179 
181  virtual ~NoiseModelFactor() {}
182 
186  template<typename CONTAINER>
187  NoiseModelFactor(const SharedNoiseModel& noiseModel, const CONTAINER& keys) :
188  Base(keys), noiseModel_(noiseModel) {}
189 
190 protected:
191 
195  NoiseModelFactor(const SharedNoiseModel& noiseModel) : noiseModel_(noiseModel) {}
196 
197 public:
198 
200  virtual void print(const std::string& s = "",
201  const KeyFormatter& keyFormatter = DefaultKeyFormatter) const;
202 
204  virtual bool equals(const NonlinearFactor& f, double tol = 1e-9) const;
205 
207  virtual size_t dim() const {
208  return noiseModel_->dim();
209  }
210 
212  const SharedNoiseModel& noiseModel() const {
213  return noiseModel_;
214  }
215 
218  return noiseModel_;
219  }
220 
227  virtual Vector unwhitenedError(const Values& x,
228  boost::optional<std::vector<Matrix>&> H = boost::none) const = 0;
229 
234  Vector whitenedError(const Values& c) const;
235 
242  virtual double error(const Values& c) const;
243 
249  boost::shared_ptr<GaussianFactor> linearize(const Values& x) const;
250 
251 private:
252 
254  friend class boost::serialization::access;
255  template<class ARCHIVE>
256  void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
257  ar & boost::serialization::make_nvp("NonlinearFactor",
258  boost::serialization::base_object<Base>(*this));
259  ar & BOOST_SERIALIZATION_NVP(noiseModel_);
260  }
261 
262 }; // \class NoiseModelFactor
263 
264 
265 /* ************************************************************************* */
266 
275 template<class VALUE>
277 
278 public:
279 
280  // typedefs for value types pulled from keys
281  typedef VALUE X;
282 
283 protected:
284 
285  typedef NoiseModelFactor Base;
286  typedef NoiseModelFactor1<VALUE> This;
287 
288 public:
289 
292 
293  virtual ~NoiseModelFactor1() {}
294 
295  inline Key key() const { return keys_[0]; }
296 
302  NoiseModelFactor1(const SharedNoiseModel& noiseModel, Key key1) :
303  Base(noiseModel, cref_list_of<1>(key1)) {}
304 
308  virtual Vector unwhitenedError(const Values& x, boost::optional<std::vector<Matrix>&> H = boost::none) const {
309  if(this->active(x)) {
310  const X& x1 = x.at<X>(keys_[0]);
311  if(H) {
312  return evaluateError(x1, (*H)[0]);
313  } else {
314  return evaluateError(x1);
315  }
316  } else {
317  return Vector::Zero(this->dim());
318  }
319  }
320 
326  virtual Vector evaluateError(const X& x, boost::optional<Matrix&> H =
327  boost::none) const = 0;
328 
329 private:
330 
332  friend class boost::serialization::access;
333  template<class ARCHIVE>
334  void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
335  ar & boost::serialization::make_nvp("NoiseModelFactor",
336  boost::serialization::base_object<Base>(*this));
337  }
338 };// \class NoiseModelFactor1
339 
340 
341 /* ************************************************************************* */
344 template<class VALUE1, class VALUE2>
346 
347 public:
348 
349  // typedefs for value types pulled from keys
350  typedef VALUE1 X1;
351  typedef VALUE2 X2;
352 
353 protected:
354 
355  typedef NoiseModelFactor Base;
357 
358 public:
359 
364 
371  NoiseModelFactor2(const SharedNoiseModel& noiseModel, Key j1, Key j2) :
372  Base(noiseModel, cref_list_of<2>(j1)(j2)) {}
373 
374  virtual ~NoiseModelFactor2() {}
375 
377  inline Key key1() const { return keys_[0]; }
378  inline Key key2() const { return keys_[1]; }
379 
382  virtual Vector unwhitenedError(const Values& x, boost::optional<std::vector<Matrix>&> H = boost::none) const {
383  if(this->active(x)) {
384  const X1& x1 = x.at<X1>(keys_[0]);
385  const X2& x2 = x.at<X2>(keys_[1]);
386  if(H) {
387  return evaluateError(x1, x2, (*H)[0], (*H)[1]);
388  } else {
389  return evaluateError(x1, x2);
390  }
391  } else {
392  return Vector::Zero(this->dim());
393  }
394  }
395 
401  virtual Vector
402  evaluateError(const X1&, const X2&, boost::optional<Matrix&> H1 =
403  boost::none, boost::optional<Matrix&> H2 = boost::none) const = 0;
404 
405 private:
406 
408  friend class boost::serialization::access;
409  template<class ARCHIVE>
410  void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
411  ar & boost::serialization::make_nvp("NoiseModelFactor",
412  boost::serialization::base_object<Base>(*this));
413  }
414 }; // \class NoiseModelFactor2
415 
416 /* ************************************************************************* */
419 template<class VALUE1, class VALUE2, class VALUE3>
421 
422 public:
423 
424  // typedefs for value types pulled from keys
425  typedef VALUE1 X1;
426  typedef VALUE2 X2;
427  typedef VALUE3 X3;
428 
429 protected:
430 
431  typedef NoiseModelFactor Base;
433 
434 public:
435 
440 
448  NoiseModelFactor3(const SharedNoiseModel& noiseModel, Key j1, Key j2, Key j3) :
449  Base(noiseModel, cref_list_of<3>(j1)(j2)(j3)) {}
450 
451  virtual ~NoiseModelFactor3() {}
452 
454  inline Key key1() const { return keys_[0]; }
455  inline Key key2() const { return keys_[1]; }
456  inline Key key3() const { return keys_[2]; }
457 
460  virtual Vector unwhitenedError(const Values& x, boost::optional<std::vector<Matrix>&> H = boost::none) const {
461  if(this->active(x)) {
462  if(H)
463  return evaluateError(x.at<X1>(keys_[0]), x.at<X2>(keys_[1]), x.at<X3>(keys_[2]), (*H)[0], (*H)[1], (*H)[2]);
464  else
465  return evaluateError(x.at<X1>(keys_[0]), x.at<X2>(keys_[1]), x.at<X3>(keys_[2]));
466  } else {
467  return Vector::Zero(this->dim());
468  }
469  }
470 
476  virtual Vector
477  evaluateError(const X1&, const X2&, const X3&,
478  boost::optional<Matrix&> H1 = boost::none,
479  boost::optional<Matrix&> H2 = boost::none,
480  boost::optional<Matrix&> H3 = boost::none) const = 0;
481 
482 private:
483 
485  friend class boost::serialization::access;
486  template<class ARCHIVE>
487  void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
488  ar & boost::serialization::make_nvp("NoiseModelFactor",
489  boost::serialization::base_object<Base>(*this));
490  }
491 }; // \class NoiseModelFactor3
492 
493 /* ************************************************************************* */
496 template<class VALUE1, class VALUE2, class VALUE3, class VALUE4>
498 
499 public:
500 
501  // typedefs for value types pulled from keys
502  typedef VALUE1 X1;
503  typedef VALUE2 X2;
504  typedef VALUE3 X3;
505  typedef VALUE4 X4;
506 
507 protected:
508 
509  typedef NoiseModelFactor Base;
511 
512 public:
513 
518 
527  NoiseModelFactor4(const SharedNoiseModel& noiseModel, Key j1, Key j2, Key j3, Key j4) :
528  Base(noiseModel, cref_list_of<4>(j1)(j2)(j3)(j4)) {}
529 
530  virtual ~NoiseModelFactor4() {}
531 
533  inline Key key1() const { return keys_[0]; }
534  inline Key key2() const { return keys_[1]; }
535  inline Key key3() const { return keys_[2]; }
536  inline Key key4() const { return keys_[3]; }
537 
540  virtual Vector unwhitenedError(const Values& x, boost::optional<std::vector<Matrix>&> H = boost::none) const {
541  if(this->active(x)) {
542  if(H)
543  return evaluateError(x.at<X1>(keys_[0]), x.at<X2>(keys_[1]), x.at<X3>(keys_[2]), x.at<X4>(keys_[3]), (*H)[0], (*H)[1], (*H)[2], (*H)[3]);
544  else
545  return evaluateError(x.at<X1>(keys_[0]), x.at<X2>(keys_[1]), x.at<X3>(keys_[2]), x.at<X4>(keys_[3]));
546  } else {
547  return Vector::Zero(this->dim());
548  }
549  }
550 
556  virtual Vector
557  evaluateError(const X1&, const X2&, const X3&, const X4&,
558  boost::optional<Matrix&> H1 = boost::none,
559  boost::optional<Matrix&> H2 = boost::none,
560  boost::optional<Matrix&> H3 = boost::none,
561  boost::optional<Matrix&> H4 = boost::none) const = 0;
562 
563 private:
564 
566  friend class boost::serialization::access;
567  template<class ARCHIVE>
568  void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
569  ar & boost::serialization::make_nvp("NoiseModelFactor",
570  boost::serialization::base_object<Base>(*this));
571  }
572 }; // \class NoiseModelFactor4
573 
574 /* ************************************************************************* */
577 template<class VALUE1, class VALUE2, class VALUE3, class VALUE4, class VALUE5>
579 
580 public:
581 
582  // typedefs for value types pulled from keys
583  typedef VALUE1 X1;
584  typedef VALUE2 X2;
585  typedef VALUE3 X3;
586  typedef VALUE4 X4;
587  typedef VALUE5 X5;
588 
589 protected:
590 
591  typedef NoiseModelFactor Base;
593 
594 public:
595 
600 
610  NoiseModelFactor5(const SharedNoiseModel& noiseModel, Key j1, Key j2, Key j3, Key j4, Key j5) :
611  Base(noiseModel, cref_list_of<5>(j1)(j2)(j3)(j4)(j5)) {}
612 
613  virtual ~NoiseModelFactor5() {}
614 
616  inline Key key1() const { return keys_[0]; }
617  inline Key key2() const { return keys_[1]; }
618  inline Key key3() const { return keys_[2]; }
619  inline Key key4() const { return keys_[3]; }
620  inline Key key5() const { return keys_[4]; }
621 
624  virtual Vector unwhitenedError(const Values& x, boost::optional<std::vector<Matrix>&> H = boost::none) const {
625  if(this->active(x)) {
626  if(H)
627  return evaluateError(x.at<X1>(keys_[0]), x.at<X2>(keys_[1]), x.at<X3>(keys_[2]), x.at<X4>(keys_[3]), x.at<X5>(keys_[4]), (*H)[0], (*H)[1], (*H)[2], (*H)[3], (*H)[4]);
628  else
629  return evaluateError(x.at<X1>(keys_[0]), x.at<X2>(keys_[1]), x.at<X3>(keys_[2]), x.at<X4>(keys_[3]), x.at<X5>(keys_[4]));
630  } else {
631  return Vector::Zero(this->dim());
632  }
633  }
634 
640  virtual Vector
641  evaluateError(const X1&, const X2&, const X3&, const X4&, const X5&,
642  boost::optional<Matrix&> H1 = boost::none,
643  boost::optional<Matrix&> H2 = boost::none,
644  boost::optional<Matrix&> H3 = boost::none,
645  boost::optional<Matrix&> H4 = boost::none,
646  boost::optional<Matrix&> H5 = boost::none) const = 0;
647 
648 private:
649 
651  friend class boost::serialization::access;
652  template<class ARCHIVE>
653  void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
654  ar & boost::serialization::make_nvp("NoiseModelFactor",
655  boost::serialization::base_object<Base>(*this));
656  }
657 }; // \class NoiseModelFactor5
658 
659 /* ************************************************************************* */
662 template<class VALUE1, class VALUE2, class VALUE3, class VALUE4, class VALUE5, class VALUE6>
664 
665 public:
666 
667  // typedefs for value types pulled from keys
668  typedef VALUE1 X1;
669  typedef VALUE2 X2;
670  typedef VALUE3 X3;
671  typedef VALUE4 X4;
672  typedef VALUE5 X5;
673  typedef VALUE6 X6;
674 
675 protected:
676 
677  typedef NoiseModelFactor Base;
679 
680 public:
681 
686 
697  NoiseModelFactor6(const SharedNoiseModel& noiseModel, Key j1, Key j2, Key j3, Key j4, Key j5, Key j6) :
698  Base(noiseModel, cref_list_of<6>(j1)(j2)(j3)(j4)(j5)(j6)) {}
699 
700  virtual ~NoiseModelFactor6() {}
701 
703  inline Key key1() const { return keys_[0]; }
704  inline Key key2() const { return keys_[1]; }
705  inline Key key3() const { return keys_[2]; }
706  inline Key key4() const { return keys_[3]; }
707  inline Key key5() const { return keys_[4]; }
708  inline Key key6() const { return keys_[5]; }
709 
712  virtual Vector unwhitenedError(const Values& x, boost::optional<std::vector<Matrix>&> H = boost::none) const {
713  if(this->active(x)) {
714  if(H)
715  return evaluateError(x.at<X1>(keys_[0]), x.at<X2>(keys_[1]), x.at<X3>(keys_[2]), x.at<X4>(keys_[3]), x.at<X5>(keys_[4]), x.at<X6>(keys_[5]), (*H)[0], (*H)[1], (*H)[2], (*H)[3], (*H)[4], (*H)[5]);
716  else
717  return evaluateError(x.at<X1>(keys_[0]), x.at<X2>(keys_[1]), x.at<X3>(keys_[2]), x.at<X4>(keys_[3]), x.at<X5>(keys_[4]), x.at<X6>(keys_[5]));
718  } else {
719  return Vector::Zero(this->dim());
720  }
721  }
722 
728  virtual Vector
729  evaluateError(const X1&, const X2&, const X3&, const X4&, const X5&, const X6&,
730  boost::optional<Matrix&> H1 = boost::none,
731  boost::optional<Matrix&> H2 = boost::none,
732  boost::optional<Matrix&> H3 = boost::none,
733  boost::optional<Matrix&> H4 = boost::none,
734  boost::optional<Matrix&> H5 = boost::none,
735  boost::optional<Matrix&> H6 = boost::none) const = 0;
736 
737 private:
738 
740  friend class boost::serialization::access;
741  template<class ARCHIVE>
742  void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
743  ar & boost::serialization::make_nvp("NoiseModelFactor",
744  boost::serialization::base_object<Base>(*this));
745  }
746 }; // \class NoiseModelFactor6
747 
748 /* ************************************************************************* */
749 
750 } // \namespace gtsam
NoiseModelFactor2()
Default Constructor for I/O.
Definition: NonlinearFactor.h:363
virtual Vector unwhitenedError(const Values &x, boost::optional< std::vector< Matrix > & > H=boost::none) const
Calls the 2-key specific version of evaluateError, which is pure virtual so must be implemented in th...
Definition: NonlinearFactor.h:382
Nonlinear factor base class.
Definition: NonlinearFactor.h:52
A nonlinear sum-of-squares factor with a zero-mean noise model implementing the density Templated on...
Definition: NonlinearFactor.h:163
Key key1() const
methods to retrieve keys
Definition: NonlinearFactor.h:616
A non-templated config holding any types of Manifold-group elements.
This is the base class for all factor types.
Definition: Factor.h:51
virtual size_t dim() const
get the dimension of the factor (number of rows on linearization)
Definition: NonlinearFactor.h:207
void print(const Matrix &A, const string &s, ostream &stream)
print without optional string, must specify cout yourself
Definition: Matrix.cpp:140
A convenient base class for creating your own NoiseModelFactor with 3 variables.
Definition: NonlinearFactor.h:420
NonlinearFactor(const CONTAINER &keys)
Constructor from a collection of the keys involved in this factor.
Definition: NonlinearFactor.h:74
noiseModel::Base::shared_ptr SharedNoiseModel
Note, deliberately not in noiseModel namespace.
Definition: NoiseModel.h:1072
virtual Vector unwhitenedError(const Values &x, boost::optional< std::vector< Matrix > & > H=boost::none) const
Calls the 5-key specific version of evaluateError, which is pure virtual so must be implemented in th...
Definition: NonlinearFactor.h:624
NoiseModelFactor1(const SharedNoiseModel &noiseModel, Key key1)
Constructor.
Definition: NonlinearFactor.h:302
NoiseModelFactor3()
Default Constructor for I/O.
Definition: NonlinearFactor.h:439
virtual Vector unwhitenedError(const Values &x, boost::optional< std::vector< Matrix > & > H=boost::none) const
Calls the 3-key specific version of evaluateError, which is pure virtual so must be implemented in th...
Definition: NonlinearFactor.h:460
A convenient base class for creating your own NoiseModelFactor with 6 variables.
Definition: NonlinearFactor.h:663
Key key1() const
methods to retrieve keys
Definition: NonlinearFactor.h:454
virtual Vector unwhitenedError(const Values &x, boost::optional< std::vector< Matrix > & > H=boost::none) const
Calls the 1-key specific version of evaluateError, which is pure virtual so must be implemented in th...
Definition: NonlinearFactor.h:308
virtual Vector unwhitenedError(const Values &x, boost::optional< std::vector< Matrix > & > H=boost::none) const
Calls the 6-key specific version of evaluateError, which is pure virtual so must be implemented in th...
Definition: NonlinearFactor.h:712
The base class for all factors.
A non-templated config holding any types of Manifold-group elements.
Definition: Values.h:70
NoiseModelFactor()
Default constructor for I/O only.
Definition: NonlinearFactor.h:178
A helper that implements the traits interface for GTSAM types.
Definition: Testable.h:150
const SharedNoiseModel & noiseModel() const
access to the noise model
Definition: NonlinearFactor.h:212
Key key1() const
methods to retrieve keys
Definition: NonlinearFactor.h:533
Template to create a binary predicate.
Definition: Testable.h:110
virtual bool active(const Values &) const
Checks whether a factor should be used based on a set of values.
Definition: NonlinearFactor.h:115
NoiseModelFactor4(const SharedNoiseModel &noiseModel, Key j1, Key j2, Key j3, Key j4)
Constructor.
Definition: NonlinearFactor.h:527
NoiseModelFactor(const SharedNoiseModel &noiseModel)
Constructor - only for subclasses, as this does not set keys.
Definition: NonlinearFactor.h:195
A convenient base class for creating your own NoiseModelFactor with 2 variables.
Definition: NonlinearFactor.h:345
NoiseModelFactor6(const SharedNoiseModel &noiseModel, Key j1, Key j2, Key j3, Key j4, Key j5, Key j6)
Constructor.
Definition: NonlinearFactor.h:697
NoiseModelFactor(const SharedNoiseModel &noiseModel, const CONTAINER &keys)
Constructor.
Definition: NonlinearFactor.h:187
ValueType at(Key j) const
Retrieve a variable by key j.
Definition: Values-inl.h:343
Key key1() const
methods to retrieve both keys
Definition: NonlinearFactor.h:377
A manifold defines a space in which there is a notion of a linear tangent space that can be centered ...
Definition: concepts.h:30
A convenient base class for creating your own NoiseModelFactor with 5 variables.
Definition: NonlinearFactor.h:578
NoiseModelFactor1()
Default constructor for I/O only.
Definition: NonlinearFactor.h:291
virtual shared_ptr clone() const
Creates a shared_ptr clone of the factor - needs to be specialized to allow for subclasses.
Definition: NonlinearFactor.h:127
virtual ~NonlinearFactor()
Destructor.
Definition: NonlinearFactor.h:92
NonlinearFactor()
Default constructor for I/O only.
Definition: NonlinearFactor.h:68
NoiseModelFactor5()
Default Constructor for I/O.
Definition: NonlinearFactor.h:599
NoiseModelFactor2(const SharedNoiseModel &noiseModel, Key j1, Key j2)
Constructor.
Definition: NonlinearFactor.h:371
A convenient base class for creating your own NoiseModelFactor with 1 variable.
Definition: NonlinearFactor.h:276
virtual ~NoiseModelFactor()
Destructor.
Definition: NonlinearFactor.h:181
virtual Vector unwhitenedError(const Values &x, boost::optional< std::vector< Matrix > & > H=boost::none) const
Calls the 4-key specific version of evaluateError, which is pure virtual so must be implemented in th...
Definition: NonlinearFactor.h:540
Special class for optional Jacobian arguments.
NoiseModelFactor3(const SharedNoiseModel &noiseModel, Key j1, Key j2, Key j3)
Constructor.
Definition: NonlinearFactor.h:448
boost::shared_ptr< This > shared_ptr
Noise model.
Definition: NonlinearFactor.h:175
SharedNoiseModel get_noiseModel() const
Definition: NonlinearFactor.h:217
NoiseModelFactor5(const SharedNoiseModel &noiseModel, Key j1, Key j2, Key j3, Key j4, Key j5)
Constructor.
Definition: NonlinearFactor.h:610
NoiseModelFactor6()
Default Constructor for I/O.
Definition: NonlinearFactor.h:685
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:57
A convenient base class for creating your own NoiseModelFactor with 4 variables.
Definition: NonlinearFactor.h:497
Key key1() const
methods to retrieve keys
Definition: NonlinearFactor.h:703
NoiseModelFactor4()
Default Constructor for I/O.
Definition: NonlinearFactor.h:517
Global functions in a separate testing namespace.
Definition: chartTesting.h:28
boost::function< std::string(Key)> KeyFormatter
Typedef for a function to format a key, i.e. to convert it to a string.
Definition: Key.h:33