Drake
n_ary_state.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cmath>
4 #include <stdexcept>
5 #include <type_traits>
6 
7 #include <Eigen/Dense>
8 
10 #include "drake/core/Vector.h"
11 
12 namespace drake {
13 
14 using Drake::toEigen; // TODO(maddog) ...until Drake-->drake fully.
15 
25 template <class UnitVector>
26 class NAryState {
27  public:
28  // The Drake::Vector concept has no explicit way of recovering the
29  // ScalarType upon which the template was specialized, but through
30  // the miracle of decltype(), it can be done. std::decay<> is used
31  // to strip any CV or reference qualifiers off the type.
32  using UnitScalar =
33  typename std::decay<decltype(toEigen(UnitVector())(0))>::type;
34  // Required by Drake::Vector concept.
35  static const int RowsAtCompileTime = Eigen::Dynamic;
36  // Required by Drake::Vector concept.
37  typedef Eigen::Matrix<UnitScalar, RowsAtCompileTime, 1> EigenType;
38 
39  NAryState() : unit_size_(unit_size()), count_(UnitCountFromRows(0)) {}
40 
41  explicit NAryState(int count)
42  : unit_size_(unit_size()),
43  // Ensure correct internal count_ (i.e., -1 if UnitVector's size
44  // is zero).
45  count_(UnitCountFromRows(RowsFromUnitCount(count))),
46  combined_vector_(EigenType::Constant(RowsFromUnitCount(count), 1,
47  NAN)) {}
48 
54  int count() const { return count_; }
55 
58  void Append(const UnitVector& unit) {
59  if (unit_size_ == 0) {
60  // NOP --- in particular, count_ should remain at -1.
61  DRAKE_ASSERT(count_ == -1);
62  return;
63  }
64  // Enlarge combined_vector_ by size of the converted unit.
65  combined_vector_.conservativeResize(combined_vector_.rows() + unit_size_,
66  Eigen::NoChange);
67  // Copy unit's Eigen-rep into the tail-end of enlarged combined_vector_.
68  combined_vector_.bottomRows(unit_size_) = toEigen(unit);
69  // Keep track of the total unit count.
70  ++count_;
71  }
72 
77  UnitVector get(int pos) const {
78  if (unit_size_ > 0) {
79  if ((pos < 0) || (pos >= count_)) {
80  throw std::out_of_range("Position pos exceeds range [0, count()].");
81  }
82  }
83  const int row0 = pos * unit_size_;
84  return UnitVector(combined_vector_.block(row0, 0,
85  unit_size_, 1));
86  }
87 
92  void set(int pos, const UnitVector& unit) {
93  if (unit_size_ > 0) {
94  if ((pos < 0) || (pos >= count_)) {
95  throw std::out_of_range("Position pos exceeds range [0, count()].");
96  }
97  }
98  const int row0 = pos * unit_size_;
99  combined_vector_.block(row0, 0, unit_size_, 1) = toEigen(unit);
100  }
101 
102  // Required by Drake::Vector concept.
103  template <typename Derived>
104  // NOLINTNEXTLINE(runtime/explicit)
105  NAryState(const Eigen::MatrixBase<Derived>& initial)
106  : unit_size_(unit_size()),
107  count_(UnitCountFromRows(initial.rows())),
108  combined_vector_(initial) {
109  }
110 
111  // Required by Drake::Vector concept.
112  template <typename Derived>
113  NAryState& operator=(const Eigen::MatrixBase<Derived>& rhs) {
114  count_ = UnitCountFromRows(rhs.rows());
115  combined_vector_ = rhs;
116  return *this;
117  }
118 
119  // Required by Drake::Vector concept.
120  int size() const { return combined_vector_.rows(); }
121 
122  // Required by Drake::Vector concept.
123  friend EigenType toEigen(const NAryState<UnitVector>& vec) {
124  return vec.combined_vector_;
125  }
126 
129  static int unit_size() { return UnitVector().size(); }
130 
140  static int UnitCountFromRows(int rows) {
141  const int us { unit_size() };
142  if (us > 0) {
143  if ((rows % us) != 0) {
144  throw std::domain_error("Row count not a multiple of non-null unit.");
145  }
146  return rows / us;
147  }
148  return -1;
149  }
150 
157  static int RowsFromUnitCount(int count) {
158  const int us { unit_size() };
159  if (count >= 0) {
160  return count * us;
161  }
162  if (us != 0) {
163  throw std::domain_error("Negative count for non-null unit.");
164  }
165  return 0;
166  }
167 
168  private:
169  int unit_size_;
170  // count_ < 0 indicates "not counted", i.e., UnitVector is a null vector.
171  int count_;
172  EigenType combined_vector_;
173 };
174 
175 } // namespace drake
static int RowsFromUnitCount(int count)
Determines how many Eigen matrix rows will be needed to represent.
Definition: n_ary_state.h:157
void Append(const UnitVector &unit)
Appends the.
Definition: n_ary_state.h:58
friend EigenType toEigen(const NAryState< UnitVector > &vec)
Definition: n_ary_state.h:123
Definition: constants.h:3
NAryState is a Drake::Vector (concept implementation) which is a container of zero or more component ...
Definition: n_ary_state.h:26
static int unit_size()
Calculates the size (Eigen row count) of UnitVector, which is presumed to be fixed for all instances ...
Definition: n_ary_state.h:129
NAryState()
Definition: n_ary_state.h:39
NAryState(const Eigen::MatrixBase< Derived > &initial)
Definition: n_ary_state.h:105
int count() const
Definition: n_ary_state.h:54
NAryState & operator=(const Eigen::MatrixBase< Derived > &rhs)
Definition: n_ary_state.h:113
#define DRAKE_ASSERT(condition)
DRAKE_ASSERT(condition) is similar to the built-in assert(condition) from the C++ system header <cas...
Definition: drake_assert.h:35
static const int RowsAtCompileTime
Definition: n_ary_state.h:35
Provides Drake&#39;s assertion implementation.
NAryState(int count)
Definition: n_ary_state.h:41
Eigen::Matrix< UnitScalar, RowsAtCompileTime, 1 > EigenType
Definition: n_ary_state.h:37
typename std::decay< decltype(toEigen(UnitVector())(0))>::type UnitScalar
Definition: n_ary_state.h:33
int size() const
Definition: n_ary_state.h:120
static int UnitCountFromRows(int rows)
Determines how many.
Definition: n_ary_state.h:140
const Eigen::Matrix< ScalarType, Rows, 1 > & toEigen(const Eigen::Matrix< ScalarType, Rows, 1 > &vec)
Definition: Vector.h:61