Drake
Gradient.h
Go to the documentation of this file.
1 
5 #pragma once
6 
7 #include <Eigen/Core>
8 #include <Eigen/Dense>
9 #include <unsupported/Eigen/AutoDiff>
10 
12 
13 namespace Drake {
14 // todo: recursive template to get arbitrary gradient order
15 
16 // note: tried using template default values (e.g. Eigen::Dynamic), but they
17 // didn't seem to work on my mac clang
18 template <int num_vars>
19 using TaylorVard = Eigen::AutoDiffScalar<Eigen::Matrix<double, num_vars, 1> >;
20 template <int num_vars, int rows>
21 using TaylorVecd = Eigen::Matrix<TaylorVard<num_vars>, rows, 1>;
22 template <int num_vars, int rows, int cols>
23 using TaylorMatd = Eigen::Matrix<TaylorVard<num_vars>, rows, cols>;
24 
28 
32 template <typename Derived, int Nq>
33 using AutoDiffMatrixType = Eigen::Matrix<
34  Eigen::AutoDiffScalar<Eigen::Matrix<typename Derived::Scalar, Nq, 1> >,
35  Derived::RowsAtCompileTime, Derived::ColsAtCompileTime, 0,
36  Derived::MaxRowsAtCompileTime, Derived::MaxColsAtCompileTime>;
37 
46 template <typename Derived, typename DerivedGradient, typename DerivedAutoDiff>
48  const Eigen::MatrixBase<Derived> &val,
49  const Eigen::MatrixBase<DerivedGradient> &gradient,
50  Eigen::MatrixBase<DerivedAutoDiff> &auto_diff_matrix) {
51  static_assert(static_cast<int>(Derived::SizeAtCompileTime) ==
52  static_cast<int>(DerivedGradient::RowsAtCompileTime),
53  "gradient has wrong number of rows at compile time");
54  DRAKE_ASSERT(val.size() == gradient.rows() &&
55  "gradient has wrong number of rows at runtime");
57  ExpectedAutoDiffType;
58  static_assert(static_cast<int>(ExpectedAutoDiffType::RowsAtCompileTime) ==
59  static_cast<int>(DerivedAutoDiff::RowsAtCompileTime),
60  "auto diff matrix has wrong number of rows at compile time");
61  static_assert(static_cast<int>(ExpectedAutoDiffType::ColsAtCompileTime) ==
62  static_cast<int>(DerivedAutoDiff::ColsAtCompileTime),
63  "auto diff matrix has wrong number of columns at compile time");
64  static_assert(std::is_same<typename DerivedAutoDiff::Scalar,
65  typename ExpectedAutoDiffType::Scalar>::value,
66  "wrong auto diff scalar type");
67 
68  typedef typename Eigen::MatrixBase<DerivedGradient>::Index Index;
69  auto_diff_matrix.resize(val.rows(), val.cols());
70  auto num_derivs = gradient.cols();
71  for (Index row = 0; row < auto_diff_matrix.size(); row++) {
72  auto_diff_matrix(row).value() = val(row);
73  auto_diff_matrix(row).derivatives().resize(num_derivs, 1);
74  auto_diff_matrix(row).derivatives() = gradient.row(row).transpose();
75  }
76 }
77 
86 template <typename Derived, typename DerivedGradient>
89  const Eigen::MatrixBase<Derived> &val,
90  const Eigen::MatrixBase<DerivedGradient> &gradient) {
92  val.rows(), val.cols());
93  initializeAutoDiffGivenGradientMatrix(val, gradient, ret);
94  return ret;
95 }
96 
114 template <typename Derived, typename DerivedAutoDiff>
115 void initializeAutoDiff(const Eigen::MatrixBase<Derived> &val,
116  Eigen::MatrixBase<DerivedAutoDiff> &auto_diff_matrix,
117  Eigen::DenseIndex num_derivatives = Eigen::Dynamic,
118  Eigen::DenseIndex deriv_num_start = 0) {
119  using ADScalar = typename DerivedAutoDiff::Scalar;
120  static_assert(static_cast<int>(Derived::RowsAtCompileTime) ==
121  static_cast<int>(DerivedAutoDiff::RowsAtCompileTime),
122  "auto diff matrix has wrong number of rows at compile time");
123  static_assert(static_cast<int>(Derived::ColsAtCompileTime) ==
124  static_cast<int>(DerivedAutoDiff::ColsAtCompileTime),
125  "auto diff matrix has wrong number of columns at compile time");
126 
127  if (num_derivatives == Eigen::Dynamic) num_derivatives = val.size();
128 
129  auto_diff_matrix.resize(val.rows(), val.cols());
130  Eigen::DenseIndex deriv_num = deriv_num_start;
131  for (Eigen::DenseIndex i = 0; i < val.size(); i++) {
132  auto_diff_matrix(i) = ADScalar(val(i), num_derivatives, deriv_num++);
133  }
134 }
135 
153 template <int Nq = Eigen::Dynamic, typename Derived>
155  const Eigen::MatrixBase<Derived> &mat,
156  Eigen::DenseIndex num_derivatives = -1,
157  Eigen::DenseIndex deriv_num_start = 0) {
158  if (num_derivatives == -1) num_derivatives = mat.size();
159 
160  AutoDiffMatrixType<Derived, Nq> ret(mat.rows(), mat.cols());
161  initializeAutoDiff(mat, ret, num_derivatives, deriv_num_start);
162  return ret;
163 }
164 
165 // TODO(tkoolen) begin: move to different location?
166 namespace internal {
169 template <typename Head, typename... Tail>
171  static constexpr int eval() {
172  return Head::SizeAtCompileTime == Eigen::Dynamic ||
173  TotalSizeAtCompileTime<Tail...>::eval() == Eigen::Dynamic
174  ? Eigen::Dynamic
175  : Head::SizeAtCompileTime +
177  }
178 };
179 
182 template <typename Head>
184  static constexpr int eval() { return Head::SizeAtCompileTime; }
185 };
186 }
187 
191 template <typename... Args>
192 constexpr int totalSizeAtCompileTime() {
194 }
195 
199 constexpr Eigen::DenseIndex totalSizeAtRunTime() { return 0; }
200 
204 template <typename Head, typename... Tail>
205 Eigen::DenseIndex totalSizeAtRunTime(const Eigen::MatrixBase<Head> &head,
206  const Tail &... tail) {
207  return head.size() + totalSizeAtRunTime(tail...);
208 }
209 // TODO(tkoolen) end: move to different location?
210 
211 namespace internal {
214 template <size_t Index>
216  template <typename... ValueTypes, typename... AutoDiffTypes>
217  static void run(const std::tuple<ValueTypes...> &values,
218  std::tuple<AutoDiffTypes...> &auto_diffs,
219  Eigen::DenseIndex num_derivatives,
220  Eigen::DenseIndex deriv_num_start) {
221  constexpr size_t tuple_index = sizeof...(AutoDiffTypes)-Index;
222  const auto &value = std::get<tuple_index>(values);
223  auto &auto_diff = std::get<tuple_index>(auto_diffs);
224  auto_diff.resize(value.rows(), value.cols());
225  initializeAutoDiff(value, auto_diff, num_derivatives, deriv_num_start);
227  values, auto_diffs, num_derivatives, deriv_num_start + value.size());
228  }
229 };
230 
233 template <>
235  template <typename... ValueTypes, typename... AutoDiffTypes>
236  static void run(const std::tuple<ValueTypes...> &values,
237  const std::tuple<AutoDiffTypes...> &auto_diffs,
238  Eigen::DenseIndex num_derivatives,
239  Eigen::DenseIndex deriv_num_start) {
240  // empty
241  }
242 };
243 }
244 
267 template <typename... Deriveds>
268 std::tuple<
269  AutoDiffMatrixType<Deriveds, totalSizeAtCompileTime<Deriveds...>()>...>
270 initializeAutoDiffTuple(const Eigen::MatrixBase<Deriveds> &... args) {
271  Eigen::DenseIndex dynamic_num_derivs = totalSizeAtRunTime(args...);
272  std::tuple<
273  AutoDiffMatrixType<Deriveds, totalSizeAtCompileTime<Deriveds...>()>...>
274  ret(AutoDiffMatrixType<Deriveds, totalSizeAtCompileTime<Deriveds...>()>(
275  args.rows(), args.cols())...);
276  auto values = std::forward_as_tuple(args...);
277  internal::InitializeAutoDiffTupleHelper<sizeof...(args)>::run(
278  values, ret, dynamic_num_derivs, 0);
279  return ret;
280 }
281 }
Helper for initializeAutoDiffTuple function (recursive)
Definition: Gradient.h:215
static constexpr int eval()
Definition: Gradient.h:171
NOTE: The contents of this class are for the most part direct ports of drake/systems/plants//inverseK...
Definition: Function.h:14
Eigen::Matrix< Eigen::AutoDiffScalar< Eigen::Matrix< typename Derived::Scalar, Nq, 1 > >, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime, 0, Derived::MaxRowsAtCompileTime, Derived::MaxColsAtCompileTime > AutoDiffMatrixType
The appropriate AutoDiffScalar gradient type given the value type and the number of derivatives at co...
Definition: Gradient.h:36
constexpr Eigen::DenseIndex totalSizeAtRunTime()
Determine the total size at runtime of a number of arguments using their size() methods (base case)...
Definition: Gradient.h:199
std::tuple< AutoDiffMatrixType< Deriveds, totalSizeAtCompileTime< Deriveds... >)>... > initializeAutoDiffTuple(const Eigen::MatrixBase< Deriveds > &...args)
Given a series of Eigen matrices, create a tuple of corresponding AutoDiff matrices with values equal...
Definition: Gradient.h:270
constexpr int totalSizeAtCompileTime()
Determine the total size at compile time of a number of arguments based on their SizeAtCompileTime st...
Definition: Gradient.h:192
static constexpr int eval()
Definition: Gradient.h:184
#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
void initializeAutoDiff(const Eigen::MatrixBase< Derived > &val, Eigen::MatrixBase< DerivedAutoDiff > &auto_diff_matrix, Eigen::DenseIndex num_derivatives=Eigen::Dynamic, Eigen::DenseIndex deriv_num_start=0)
Initialize a single autodiff matrix given the corresponding value matrix.
Definition: Gradient.h:115
TaylorVecd< Eigen::Dynamic, Eigen::Dynamic > TaylorVecXd
Definition: Gradient.h:26
Provides Drake&#39;s assertion implementation.
Helper for totalSizeAtCompileTime function (recursive)
Definition: Gradient.h:170
void initializeAutoDiffGivenGradientMatrix(const Eigen::MatrixBase< Derived > &val, const Eigen::MatrixBase< DerivedGradient > &gradient, Eigen::MatrixBase< DerivedAutoDiff > &auto_diff_matrix)
Initializes an autodiff matrix given a matrix of values and gradient matrix.
Definition: Gradient.h:47
Eigen::AutoDiffScalar< Eigen::Matrix< double, num_vars, 1 > > TaylorVard
Definition: Gradient.h:19
TaylorVard< Eigen::Dynamic > TaylorVarXd
Definition: Gradient.h:25
TaylorMatd< Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic > TaylorMatXd
Definition: Gradient.h:27
Eigen::Matrix< TaylorVard< num_vars >, rows, 1 > TaylorVecd
Definition: Gradient.h:21
static void run(const std::tuple< ValueTypes... > &values, const std::tuple< AutoDiffTypes... > &auto_diffs, Eigen::DenseIndex num_derivatives, Eigen::DenseIndex deriv_num_start)
Definition: Gradient.h:236
Eigen::Matrix< TaylorVard< num_vars >, rows, cols > TaylorMatd
Definition: Gradient.h:23
static void run(const std::tuple< ValueTypes... > &values, std::tuple< AutoDiffTypes... > &auto_diffs, Eigen::DenseIndex num_derivatives, Eigen::DenseIndex deriv_num_start)
Definition: Gradient.h:217