mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-24 01:31:46 +00:00
[wpimath] Add tests for DARE overload with Q, R, and N matrices (#3472)
The autodiff headers weren't used by the tests, so they were removed.
This commit is contained in:
@@ -1,34 +0,0 @@
|
||||
#pragma once
|
||||
/// @file This header provides a single inclusion point for autodiff-related
|
||||
/// header files in the `drake/common` directory. Users should include this
|
||||
/// file. Including other individual headers such as `drake/common/autodiffxd.h`
|
||||
/// will generate a compile-time warning.
|
||||
|
||||
// In each header included below, it asserts that this macro
|
||||
// `DRAKE_COMMON_AUTODIFF_HEADER` is defined. If the macro is not defined, it
|
||||
// generates diagnostic warning messages.
|
||||
#define DRAKE_COMMON_AUTODIFF_HEADER
|
||||
|
||||
#include <Eigen/Core>
|
||||
#include <unsupported/Eigen/AutoDiff>
|
||||
|
||||
static_assert(EIGEN_VERSION_AT_LEAST(3, 3, 3),
|
||||
"Drake requires Eigen >= v3.3.3.");
|
||||
|
||||
// Do not alpha-sort the following block of hard-coded #includes, which is
|
||||
// protected by `clang-format on/off`.
|
||||
//
|
||||
// Rationale: We want to maximize the use of this header, `autodiff.h`, even
|
||||
// inside of the autodiff-related files to avoid any mistakes which might not be
|
||||
// detected. By centralizing the list here, we make sure that everyone will see
|
||||
// the correct order which respects the inter-dependencies of the autodiff
|
||||
// headers. This shields us from triggering undefined behaviors due to
|
||||
// order-of-specialization-includes-changed mistakes.
|
||||
//
|
||||
// clang-format off
|
||||
#include "drake/common/eigen_autodiff_limits.h"
|
||||
#include "drake/common/eigen_autodiff_types.h"
|
||||
#include "drake/common/autodiffxd.h"
|
||||
#include "drake/common/autodiff_overloads.h"
|
||||
// clang-format on
|
||||
#undef DRAKE_COMMON_AUTODIFF_HEADER
|
||||
@@ -1,203 +0,0 @@
|
||||
/// @file
|
||||
/// Overloads for STL mathematical operations on AutoDiffScalar.
|
||||
///
|
||||
/// Used via argument-dependent lookup (ADL). These functions appear
|
||||
/// in the Eigen namespace so that ADL can automatically choose between
|
||||
/// the STL version and the overloaded version to match the type of the
|
||||
/// arguments. The proper use would be e.g.
|
||||
///
|
||||
/// \code{.cc}
|
||||
/// void mymethod() {
|
||||
/// using std::isinf;
|
||||
/// isinf(myval);
|
||||
/// }
|
||||
/// \endcode{}
|
||||
///
|
||||
/// @note The if_then_else and cond functions for AutoDiffScalar are in
|
||||
/// namespace drake because cond is defined in namespace drake in
|
||||
/// "drake/common/cond.h" file.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef DRAKE_COMMON_AUTODIFF_HEADER
|
||||
// TODO(soonho-tri): Change to #error.
|
||||
#warning Do not directly include this file. Include "drake/common/autodiff.h".
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include "drake/common/cond.h"
|
||||
#include "drake/common/drake_assert.h"
|
||||
#include "drake/common/dummy_value.h"
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/// Overloads nexttoward to mimic std::nexttoward from <cmath>.
|
||||
template <typename DerType>
|
||||
double nexttoward(const Eigen::AutoDiffScalar<DerType>& from, long double to) {
|
||||
using std::nexttoward;
|
||||
return nexttoward(from.value(), to);
|
||||
}
|
||||
|
||||
/// Overloads round to mimic std::round from <cmath>.
|
||||
template <typename DerType>
|
||||
double round(const Eigen::AutoDiffScalar<DerType>& x) {
|
||||
using std::round;
|
||||
return round(x.value());
|
||||
}
|
||||
|
||||
/// Overloads isinf to mimic std::isinf from <cmath>.
|
||||
template <typename DerType>
|
||||
bool isinf(const Eigen::AutoDiffScalar<DerType>& x) {
|
||||
using std::isinf;
|
||||
return isinf(x.value());
|
||||
}
|
||||
|
||||
/// Overloads isfinite to mimic std::isfinite from <cmath>.
|
||||
template <typename DerType>
|
||||
bool isfinite(const Eigen::AutoDiffScalar<DerType>& x) {
|
||||
using std::isfinite;
|
||||
return isfinite(x.value());
|
||||
}
|
||||
|
||||
/// Overloads isnan to mimic std::isnan from <cmath>.
|
||||
template <typename DerType>
|
||||
bool isnan(const Eigen::AutoDiffScalar<DerType>& x) {
|
||||
using std::isnan;
|
||||
return isnan(x.value());
|
||||
}
|
||||
|
||||
/// Overloads floor to mimic std::floor from <cmath>.
|
||||
template <typename DerType>
|
||||
double floor(const Eigen::AutoDiffScalar<DerType>& x) {
|
||||
using std::floor;
|
||||
return floor(x.value());
|
||||
}
|
||||
|
||||
/// Overloads ceil to mimic std::ceil from <cmath>.
|
||||
template <typename DerType>
|
||||
double ceil(const Eigen::AutoDiffScalar<DerType>& x) {
|
||||
using std::ceil;
|
||||
return ceil(x.value());
|
||||
}
|
||||
|
||||
/// Overloads copysign from <cmath>.
|
||||
template <typename DerType, typename T>
|
||||
Eigen::AutoDiffScalar<DerType> copysign(const Eigen::AutoDiffScalar<DerType>& x,
|
||||
const T& y) {
|
||||
using std::isnan;
|
||||
if (isnan(x)) return (y >= 0) ? NAN : -NAN;
|
||||
if ((x < 0 && y >= 0) || (x >= 0 && y < 0))
|
||||
return -x;
|
||||
else
|
||||
return x;
|
||||
}
|
||||
|
||||
/// Overloads copysign from <cmath>.
|
||||
template <typename DerType>
|
||||
double copysign(double x, const Eigen::AutoDiffScalar<DerType>& y) {
|
||||
using std::isnan;
|
||||
if (isnan(x)) return (y >= 0) ? NAN : -NAN;
|
||||
if ((x < 0 && y >= 0) || (x >= 0 && y < 0))
|
||||
return -x;
|
||||
else
|
||||
return x;
|
||||
}
|
||||
|
||||
/// Overloads pow for an AutoDiffScalar base and exponent, implementing the
|
||||
/// chain rule.
|
||||
template <typename DerTypeA, typename DerTypeB>
|
||||
Eigen::AutoDiffScalar<
|
||||
typename internal::remove_all<DerTypeA>::type::PlainObject>
|
||||
pow(const Eigen::AutoDiffScalar<DerTypeA>& base,
|
||||
const Eigen::AutoDiffScalar<DerTypeB>& exponent) {
|
||||
// The two AutoDiffScalars being exponentiated must have the same matrix
|
||||
// type. This includes, but is not limited to, the same scalar type and
|
||||
// the same dimension.
|
||||
static_assert(
|
||||
std::is_same<
|
||||
typename internal::remove_all<DerTypeA>::type::PlainObject,
|
||||
typename internal::remove_all<DerTypeB>::type::PlainObject>::value,
|
||||
"The derivative types must match.");
|
||||
|
||||
internal::make_coherent(base.derivatives(), exponent.derivatives());
|
||||
|
||||
const auto& x = base.value();
|
||||
const auto& xgrad = base.derivatives();
|
||||
const auto& y = exponent.value();
|
||||
const auto& ygrad = exponent.derivatives();
|
||||
|
||||
using std::pow;
|
||||
using std::log;
|
||||
const auto x_to_the_y = pow(x, y);
|
||||
if (ygrad.isZero(std::numeric_limits<double>::epsilon()) ||
|
||||
ygrad.size() == 0) {
|
||||
// The derivative only depends on ∂(x^y)/∂x -- this prevents undefined
|
||||
// behavior in the corner case where ∂(x^y)/∂y is infinite when x = 0,
|
||||
// despite ∂y/∂v being 0.
|
||||
return Eigen::MakeAutoDiffScalar(x_to_the_y, y * pow(x, y - 1) * xgrad);
|
||||
}
|
||||
return Eigen::MakeAutoDiffScalar(
|
||||
// The value is x ^ y.
|
||||
x_to_the_y,
|
||||
// The multivariable chain rule states:
|
||||
// df/dv_i = (∂f/∂x * dx/dv_i) + (∂f/∂y * dy/dv_i)
|
||||
// ∂f/∂x is y*x^(y-1)
|
||||
y * pow(x, y - 1) * xgrad +
|
||||
// ∂f/∂y is (x^y)*ln(x)
|
||||
x_to_the_y * log(x) * ygrad);
|
||||
}
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
namespace drake {
|
||||
|
||||
/// Returns the autodiff scalar's value() as a double. Never throws.
|
||||
/// Overloads ExtractDoubleOrThrow from common/extract_double.h.
|
||||
template <typename DerType>
|
||||
double ExtractDoubleOrThrow(const Eigen::AutoDiffScalar<DerType>& scalar) {
|
||||
return static_cast<double>(scalar.value());
|
||||
}
|
||||
|
||||
/// Specializes common/dummy_value.h.
|
||||
template <typename DerType>
|
||||
struct dummy_value<Eigen::AutoDiffScalar<DerType>> {
|
||||
static constexpr Eigen::AutoDiffScalar<DerType> get() {
|
||||
constexpr double kNaN = std::numeric_limits<double>::quiet_NaN();
|
||||
DerType derivatives;
|
||||
derivatives.fill(kNaN);
|
||||
return Eigen::AutoDiffScalar<DerType>(kNaN, derivatives);
|
||||
}
|
||||
};
|
||||
|
||||
/// Provides if-then-else expression for Eigen::AutoDiffScalar type. To support
|
||||
/// Eigen's generic expressions, we use casting to the plain object after
|
||||
/// applying Eigen::internal::remove_all. It is based on the Eigen's
|
||||
/// implementation of min/max function for AutoDiffScalar type
|
||||
/// (https://bitbucket.org/eigen/eigen/src/10a1de58614569c9250df88bdfc6402024687bc6/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h?at=default&fileviewer=file-view-default#AutoDiffScalar.h-546).
|
||||
template <typename DerType1, typename DerType2>
|
||||
inline Eigen::AutoDiffScalar<
|
||||
typename Eigen::internal::remove_all<DerType1>::type::PlainObject>
|
||||
if_then_else(bool f_cond, const Eigen::AutoDiffScalar<DerType1>& x,
|
||||
const Eigen::AutoDiffScalar<DerType2>& y) {
|
||||
typedef Eigen::AutoDiffScalar<
|
||||
typename Eigen::internal::remove_all<DerType1>::type::PlainObject>
|
||||
ADS1;
|
||||
typedef Eigen::AutoDiffScalar<
|
||||
typename Eigen::internal::remove_all<DerType2>::type::PlainObject>
|
||||
ADS2;
|
||||
static_assert(std::is_same<ADS1, ADS2>::value,
|
||||
"The derivative types must match.");
|
||||
return f_cond ? ADS1(x) : ADS2(y);
|
||||
}
|
||||
|
||||
/// Provides special case of cond expression for Eigen::AutoDiffScalar type.
|
||||
template <typename DerType, typename... Rest>
|
||||
Eigen::AutoDiffScalar<
|
||||
typename Eigen::internal::remove_all<DerType>::type::PlainObject>
|
||||
cond(bool f_cond, const Eigen::AutoDiffScalar<DerType>& e_then, Rest... rest) {
|
||||
return if_then_else(f_cond, e_then, cond(rest...));
|
||||
}
|
||||
|
||||
} // namespace drake
|
||||
@@ -1,423 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// This file is a modification of Eigen-3.3.3's AutoDiffScalar.h file which is
|
||||
// available at
|
||||
// https://bitbucket.org/eigen/eigen/raw/67e894c6cd8f5f1f604b27d37ed47fdf012674ff/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h
|
||||
//
|
||||
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2017 Drake Authors
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef DRAKE_COMMON_AUTODIFF_HEADER
|
||||
// TODO(soonho-tri): Change to #error.
|
||||
#warning Do not directly include this file. Include "drake/common/autodiff.h".
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include <ostream>
|
||||
|
||||
#include <Eigen/Core>
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
#if !defined(DRAKE_DOXYGEN_CXX)
|
||||
// Explicit template specializations of Eigen::AutoDiffScalar for VectorXd.
|
||||
//
|
||||
// AutoDiffScalar tries to call internal::make_coherent to promote empty
|
||||
// derivatives. However, it fails to do the promotion when an operand is an
|
||||
// expression tree (i.e. CwiseBinaryOp). Our solution is to provide special
|
||||
// overloading for VectorXd and change the return types of its operators. With
|
||||
// this change, the operators evaluate terms immediately and return an
|
||||
// AutoDiffScalar<VectorXd> instead of expression trees (such as CwiseBinaryOp).
|
||||
// Eigen's implementation of internal::make_coherent makes use of const_cast in
|
||||
// order to promote zero sized derivatives. This however interferes badly with
|
||||
// our caching system and produces unexpected behaviors. See #10971 for details.
|
||||
// Therefore our implementation stops using internal::make_coherent and treats
|
||||
// scalars with zero sized derivatives as constants, as it should.
|
||||
//
|
||||
// We also provide overloading of math functions for AutoDiffScalar<VectorXd>
|
||||
// which return AutoDiffScalar<VectorXd> instead of an expression tree.
|
||||
//
|
||||
// See https://github.com/RobotLocomotion/drake/issues/6944 for more
|
||||
// information. See also drake/common/autodiff_overloads.h.
|
||||
//
|
||||
// TODO(soonho-tri): Next time when we upgrade Eigen, please check if we still
|
||||
// need these specializations.
|
||||
template <>
|
||||
class AutoDiffScalar<VectorXd>
|
||||
: public internal::auto_diff_special_op<VectorXd, false> {
|
||||
public:
|
||||
typedef internal::auto_diff_special_op<VectorXd, false> Base;
|
||||
typedef typename internal::remove_all<VectorXd>::type DerType;
|
||||
typedef typename internal::traits<DerType>::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real Real;
|
||||
|
||||
using Base::operator+;
|
||||
using Base::operator*;
|
||||
|
||||
AutoDiffScalar() {}
|
||||
|
||||
AutoDiffScalar(const Scalar& value, int nbDer, int derNumber)
|
||||
: m_value(value), m_derivatives(DerType::Zero(nbDer)) {
|
||||
m_derivatives.coeffRef(derNumber) = Scalar(1);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(runtime/explicit): Code from Eigen.
|
||||
AutoDiffScalar(const Real& value) : m_value(value) {
|
||||
if (m_derivatives.size() > 0) m_derivatives.setZero();
|
||||
}
|
||||
|
||||
AutoDiffScalar(const Scalar& value, const DerType& der)
|
||||
: m_value(value), m_derivatives(der) {}
|
||||
|
||||
template <typename OtherDerType>
|
||||
AutoDiffScalar(
|
||||
const AutoDiffScalar<OtherDerType>& other
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
,
|
||||
typename internal::enable_if<
|
||||
internal::is_same<
|
||||
Scalar, typename internal::traits<typename internal::remove_all<
|
||||
OtherDerType>::type>::Scalar>::value,
|
||||
void*>::type = 0
|
||||
#endif
|
||||
)
|
||||
: m_value(other.value()), m_derivatives(other.derivatives()) {
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& s, const AutoDiffScalar& a) {
|
||||
return s << a.value();
|
||||
}
|
||||
|
||||
AutoDiffScalar(const AutoDiffScalar& other)
|
||||
: m_value(other.value()), m_derivatives(other.derivatives()) {}
|
||||
|
||||
template <typename OtherDerType>
|
||||
inline AutoDiffScalar& operator=(const AutoDiffScalar<OtherDerType>& other) {
|
||||
m_value = other.value();
|
||||
m_derivatives = other.derivatives();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline AutoDiffScalar& operator=(const AutoDiffScalar& other) {
|
||||
m_value = other.value();
|
||||
m_derivatives = other.derivatives();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline AutoDiffScalar& operator=(const Scalar& other) {
|
||||
m_value = other;
|
||||
if (m_derivatives.size() > 0) m_derivatives.setZero();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const Scalar& value() const { return m_value; }
|
||||
inline Scalar& value() { return m_value; }
|
||||
|
||||
inline const DerType& derivatives() const { return m_derivatives; }
|
||||
inline DerType& derivatives() { return m_derivatives; }
|
||||
|
||||
inline bool operator<(const Scalar& other) const { return m_value < other; }
|
||||
inline bool operator<=(const Scalar& other) const { return m_value <= other; }
|
||||
inline bool operator>(const Scalar& other) const { return m_value > other; }
|
||||
inline bool operator>=(const Scalar& other) const { return m_value >= other; }
|
||||
inline bool operator==(const Scalar& other) const { return m_value == other; }
|
||||
inline bool operator!=(const Scalar& other) const { return m_value != other; }
|
||||
|
||||
friend inline bool operator<(const Scalar& a, const AutoDiffScalar& b) {
|
||||
return a < b.value();
|
||||
}
|
||||
friend inline bool operator<=(const Scalar& a, const AutoDiffScalar& b) {
|
||||
return a <= b.value();
|
||||
}
|
||||
friend inline bool operator>(const Scalar& a, const AutoDiffScalar& b) {
|
||||
return a > b.value();
|
||||
}
|
||||
friend inline bool operator>=(const Scalar& a, const AutoDiffScalar& b) {
|
||||
return a >= b.value();
|
||||
}
|
||||
friend inline bool operator==(const Scalar& a, const AutoDiffScalar& b) {
|
||||
return a == b.value();
|
||||
}
|
||||
friend inline bool operator!=(const Scalar& a, const AutoDiffScalar& b) {
|
||||
return a != b.value();
|
||||
}
|
||||
|
||||
template <typename OtherDerType>
|
||||
inline bool operator<(const AutoDiffScalar<OtherDerType>& b) const {
|
||||
return m_value < b.value();
|
||||
}
|
||||
template <typename OtherDerType>
|
||||
inline bool operator<=(const AutoDiffScalar<OtherDerType>& b) const {
|
||||
return m_value <= b.value();
|
||||
}
|
||||
template <typename OtherDerType>
|
||||
inline bool operator>(const AutoDiffScalar<OtherDerType>& b) const {
|
||||
return m_value > b.value();
|
||||
}
|
||||
template <typename OtherDerType>
|
||||
inline bool operator>=(const AutoDiffScalar<OtherDerType>& b) const {
|
||||
return m_value >= b.value();
|
||||
}
|
||||
template <typename OtherDerType>
|
||||
inline bool operator==(const AutoDiffScalar<OtherDerType>& b) const {
|
||||
return m_value == b.value();
|
||||
}
|
||||
template <typename OtherDerType>
|
||||
inline bool operator!=(const AutoDiffScalar<OtherDerType>& b) const {
|
||||
return m_value != b.value();
|
||||
}
|
||||
|
||||
inline const AutoDiffScalar<DerType> operator+(const Scalar& other) const {
|
||||
return AutoDiffScalar<DerType>(m_value + other, m_derivatives);
|
||||
}
|
||||
|
||||
friend inline const AutoDiffScalar<DerType> operator+(
|
||||
const Scalar& a, const AutoDiffScalar& b) {
|
||||
return AutoDiffScalar<DerType>(a + b.value(), b.derivatives());
|
||||
}
|
||||
|
||||
inline AutoDiffScalar& operator+=(const Scalar& other) {
|
||||
value() += other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename OtherDerType>
|
||||
inline const AutoDiffScalar<DerType> operator+(
|
||||
const AutoDiffScalar<OtherDerType>& other) const {
|
||||
const bool has_this_der = m_derivatives.size() > 0;
|
||||
const bool has_both_der = has_this_der && (other.derivatives().size() > 0);
|
||||
return MakeAutoDiffScalar(
|
||||
m_value + other.value(),
|
||||
has_both_der
|
||||
? VectorXd(m_derivatives + other.derivatives())
|
||||
: has_this_der ? m_derivatives : VectorXd(other.derivatives()));
|
||||
}
|
||||
|
||||
template <typename OtherDerType>
|
||||
inline AutoDiffScalar& operator+=(const AutoDiffScalar<OtherDerType>& other) {
|
||||
(*this) = (*this) + other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const AutoDiffScalar<DerType> operator-(const Scalar& b) const {
|
||||
return AutoDiffScalar<DerType>(m_value - b, m_derivatives);
|
||||
}
|
||||
|
||||
friend inline const AutoDiffScalar<DerType> operator-(
|
||||
const Scalar& a, const AutoDiffScalar& b) {
|
||||
return AutoDiffScalar<DerType>(a - b.value(), -b.derivatives());
|
||||
}
|
||||
|
||||
inline AutoDiffScalar& operator-=(const Scalar& other) {
|
||||
value() -= other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename OtherDerType>
|
||||
inline const AutoDiffScalar<DerType> operator-(
|
||||
const AutoDiffScalar<OtherDerType>& other) const {
|
||||
const bool has_this_der = m_derivatives.size() > 0;
|
||||
const bool has_both_der = has_this_der && (other.derivatives().size() > 0);
|
||||
return MakeAutoDiffScalar(
|
||||
m_value - other.value(),
|
||||
has_both_der
|
||||
? VectorXd(m_derivatives - other.derivatives())
|
||||
: has_this_der ? m_derivatives : VectorXd(-other.derivatives()));
|
||||
}
|
||||
|
||||
template <typename OtherDerType>
|
||||
inline AutoDiffScalar& operator-=(const AutoDiffScalar<OtherDerType>& other) {
|
||||
*this = *this - other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const AutoDiffScalar<DerType> operator-() const {
|
||||
return AutoDiffScalar<DerType>(-m_value, -m_derivatives);
|
||||
}
|
||||
|
||||
inline const AutoDiffScalar<DerType> operator*(const Scalar& other) const {
|
||||
return MakeAutoDiffScalar(m_value * other, m_derivatives * other);
|
||||
}
|
||||
|
||||
friend inline const AutoDiffScalar<DerType> operator*(
|
||||
const Scalar& other, const AutoDiffScalar& a) {
|
||||
return MakeAutoDiffScalar(a.value() * other, a.derivatives() * other);
|
||||
}
|
||||
|
||||
inline const AutoDiffScalar<DerType> operator/(const Scalar& other) const {
|
||||
return MakeAutoDiffScalar(m_value / other,
|
||||
(m_derivatives * (Scalar(1) / other)));
|
||||
}
|
||||
|
||||
friend inline const AutoDiffScalar<DerType> operator/(
|
||||
const Scalar& other, const AutoDiffScalar& a) {
|
||||
return MakeAutoDiffScalar(
|
||||
other / a.value(),
|
||||
a.derivatives() * (Scalar(-other) / (a.value() * a.value())));
|
||||
}
|
||||
|
||||
template <typename OtherDerType>
|
||||
inline const AutoDiffScalar<DerType> operator/(
|
||||
const AutoDiffScalar<OtherDerType>& other) const {
|
||||
const auto& this_der = m_derivatives;
|
||||
const auto& other_der = other.derivatives();
|
||||
const bool has_this_der = m_derivatives.size() > 0;
|
||||
const bool has_both_der = has_this_der && (other.derivatives().size() > 0);
|
||||
const double scale = 1. / (other.value() * other.value());
|
||||
return MakeAutoDiffScalar(
|
||||
m_value / other.value(),
|
||||
has_both_der ?
|
||||
VectorXd(this_der * other.value() - other_der * m_value) * scale :
|
||||
has_this_der ?
|
||||
VectorXd(this_der * other.value()) * scale :
|
||||
// has_other_der || has_neither
|
||||
VectorXd(other_der * -m_value) * scale);
|
||||
}
|
||||
|
||||
template <typename OtherDerType>
|
||||
inline const AutoDiffScalar<DerType> operator*(
|
||||
const AutoDiffScalar<OtherDerType>& other) const {
|
||||
const bool has_this_der = m_derivatives.size() > 0;
|
||||
const bool has_both_der = has_this_der && (other.derivatives().size() > 0);
|
||||
return MakeAutoDiffScalar(
|
||||
m_value * other.value(),
|
||||
has_both_der ? VectorXd(m_derivatives * other.value() +
|
||||
other.derivatives() * m_value)
|
||||
: has_this_der ? VectorXd(m_derivatives * other.value())
|
||||
: VectorXd(other.derivatives() * m_value));
|
||||
}
|
||||
|
||||
inline AutoDiffScalar& operator*=(const Scalar& other) {
|
||||
*this = *this * other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename OtherDerType>
|
||||
inline AutoDiffScalar& operator*=(const AutoDiffScalar<OtherDerType>& other) {
|
||||
*this = *this * other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline AutoDiffScalar& operator/=(const Scalar& other) {
|
||||
*this = *this / other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename OtherDerType>
|
||||
inline AutoDiffScalar& operator/=(const AutoDiffScalar<OtherDerType>& other) {
|
||||
*this = *this / other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
Scalar m_value;
|
||||
DerType m_derivatives;
|
||||
};
|
||||
|
||||
#define DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(FUNC, CODE) \
|
||||
inline const AutoDiffScalar<VectorXd> FUNC( \
|
||||
const AutoDiffScalar<VectorXd>& x) { \
|
||||
EIGEN_UNUSED typedef double Scalar; \
|
||||
CODE; \
|
||||
}
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
abs, using std::abs; return Eigen::MakeAutoDiffScalar(
|
||||
abs(x.value()), x.derivatives() * (x.value() < 0 ? -1 : 1));)
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
abs2, using numext::abs2; return Eigen::MakeAutoDiffScalar(
|
||||
abs2(x.value()), x.derivatives() * (Scalar(2) * x.value()));)
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
sqrt, using std::sqrt; Scalar sqrtx = sqrt(x.value());
|
||||
return Eigen::MakeAutoDiffScalar(sqrtx,
|
||||
x.derivatives() * (Scalar(0.5) / sqrtx));)
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
cos, using std::cos; using std::sin;
|
||||
return Eigen::MakeAutoDiffScalar(cos(x.value()),
|
||||
x.derivatives() * (-sin(x.value())));)
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
sin, using std::sin; using std::cos;
|
||||
return Eigen::MakeAutoDiffScalar(sin(x.value()),
|
||||
x.derivatives() * cos(x.value()));)
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
exp, using std::exp; Scalar expx = exp(x.value());
|
||||
return Eigen::MakeAutoDiffScalar(expx, x.derivatives() * expx);)
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
log, using std::log; return Eigen::MakeAutoDiffScalar(
|
||||
log(x.value()), x.derivatives() * (Scalar(1) / x.value()));)
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
tan, using std::tan; using std::cos; return Eigen::MakeAutoDiffScalar(
|
||||
tan(x.value()),
|
||||
x.derivatives() * (Scalar(1) / numext::abs2(cos(x.value()))));)
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
asin, using std::sqrt; using std::asin; return Eigen::MakeAutoDiffScalar(
|
||||
asin(x.value()),
|
||||
x.derivatives() * (Scalar(1) / sqrt(1 - numext::abs2(x.value()))));)
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
acos, using std::sqrt; using std::acos; return Eigen::MakeAutoDiffScalar(
|
||||
acos(x.value()),
|
||||
x.derivatives() * (Scalar(-1) / sqrt(1 - numext::abs2(x.value()))));)
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
atan, using std::atan; return Eigen::MakeAutoDiffScalar(
|
||||
atan(x.value()),
|
||||
x.derivatives() * (Scalar(1) / (1 + x.value() * x.value())));)
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
tanh, using std::cosh; using std::tanh; return Eigen::MakeAutoDiffScalar(
|
||||
tanh(x.value()),
|
||||
x.derivatives() * (Scalar(1) / numext::abs2(cosh(x.value()))));)
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
sinh, using std::sinh; using std::cosh;
|
||||
return Eigen::MakeAutoDiffScalar(sinh(x.value()),
|
||||
x.derivatives() * cosh(x.value()));)
|
||||
|
||||
DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY(
|
||||
cosh, using std::sinh; using std::cosh;
|
||||
return Eigen::MakeAutoDiffScalar(cosh(x.value()),
|
||||
x.derivatives() * sinh(x.value()));)
|
||||
|
||||
#undef DRAKE_EIGEN_AUTODIFFXD_DECLARE_GLOBAL_UNARY
|
||||
|
||||
// We have this specialization here because the Eigen-3.3.3's atan2
|
||||
// implementation for AutoDiffScalar does not make a return with properly sized
|
||||
// derivatives.
|
||||
inline const AutoDiffScalar<VectorXd> atan2(const AutoDiffScalar<VectorXd>& a,
|
||||
const AutoDiffScalar<VectorXd>& b) {
|
||||
const bool has_a_der = a.derivatives().size() > 0;
|
||||
const bool has_both_der = has_a_der && (b.derivatives().size() > 0);
|
||||
const double squared_hypot = a.value() * a.value() + b.value() * b.value();
|
||||
return MakeAutoDiffScalar(
|
||||
std::atan2(a.value(), b.value()),
|
||||
VectorXd((has_both_der
|
||||
? VectorXd(a.derivatives() * b.value() -
|
||||
a.value() * b.derivatives())
|
||||
: has_a_der ? VectorXd(a.derivatives() * b.value())
|
||||
: VectorXd(-a.value() * b.derivatives())) /
|
||||
squared_hypot));
|
||||
}
|
||||
|
||||
inline const AutoDiffScalar<VectorXd> pow(const AutoDiffScalar<VectorXd>& a,
|
||||
double b) {
|
||||
using std::pow;
|
||||
return MakeAutoDiffScalar(pow(a.value(), b),
|
||||
a.derivatives() * (b * pow(a.value(), b - 1)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace Eigen
|
||||
@@ -1,44 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
#include "drake/common/double_overloads.h"
|
||||
|
||||
namespace drake {
|
||||
/** @name cond
|
||||
Constructs conditional expression (similar to Lisp's cond).
|
||||
|
||||
@verbatim
|
||||
cond(cond_1, expr_1,
|
||||
cond_2, expr_2,
|
||||
..., ...,
|
||||
cond_n, expr_n,
|
||||
expr_{n+1})
|
||||
@endverbatim
|
||||
|
||||
The value returned by the above cond expression is @c expr_1 if @c cond_1 is
|
||||
true; else if @c cond_2 is true then @c expr_2; ... ; else if @c cond_n is
|
||||
true then @c expr_n. If none of the conditions are true, it returns @c
|
||||
expr_{n+1}.
|
||||
|
||||
@note This functions assumes that @p ScalarType provides @c operator< and the
|
||||
type of @c f_cond is the type of the return type of <tt>operator<(ScalarType,
|
||||
ScalarType)</tt>. For example, @c symbolic::Expression can be used as a @p
|
||||
ScalarType because it provides <tt>symbolic::Formula
|
||||
operator<(symbolic::Expression, symbolic::Expression)</tt>.
|
||||
|
||||
|
||||
@{
|
||||
*/
|
||||
template <typename ScalarType>
|
||||
ScalarType cond(const ScalarType& e) {
|
||||
return e;
|
||||
}
|
||||
template <typename ScalarType, typename... Rest>
|
||||
ScalarType cond(const decltype(ScalarType() < ScalarType()) & f_cond,
|
||||
const ScalarType& e_then, Rest... rest) {
|
||||
return if_then_else(f_cond, e_then, cond(rest...));
|
||||
}
|
||||
///@}
|
||||
} // namespace drake
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace drake {
|
||||
|
||||
constexpr int kQuaternionSize = 4;
|
||||
|
||||
constexpr int kSpaceDimension = 3;
|
||||
|
||||
constexpr int kRpySize = 3;
|
||||
|
||||
/// https://en.wikipedia.org/wiki/Screw_theory#Twist
|
||||
constexpr int kTwistSize = 6;
|
||||
|
||||
/// http://www.euclideanspace.com/maths/geometry/affine/matrix4x4/
|
||||
constexpr int kHomogeneousTransformSize = 16;
|
||||
|
||||
const int kRotmatSize = kSpaceDimension * kSpaceDimension;
|
||||
|
||||
} // namespace drake
|
||||
@@ -1,21 +0,0 @@
|
||||
/// @file
|
||||
/// Provides necessary operations on double to have it as a ScalarType in drake.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace drake {
|
||||
/// Provides if-then-else expression for double. The value returned by the
|
||||
/// if-then-else expression is @p v_then if @p f_cond is @c true. Otherwise, it
|
||||
/// returns @p v_else.
|
||||
|
||||
/// The semantics is similar but not exactly the same as C++'s conditional
|
||||
/// expression constructed by its ternary operator, @c ?:. In
|
||||
/// <tt>if_then_else(f_cond, v_then, v_else)</tt>, both of @p v_then and @p
|
||||
/// v_else are evaluated regardless of the evaluation of @p f_cond. In contrast,
|
||||
/// only one of @p v_then or @p v_else is evaluated in C++'s conditional
|
||||
/// expression <tt>f_cond ? v_then : v_else</tt>.
|
||||
inline double if_then_else(bool f_cond, double v_then, double v_else) {
|
||||
return f_cond ? v_then : v_else;
|
||||
}
|
||||
|
||||
} // namespace drake
|
||||
@@ -1,65 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
/** @file
|
||||
Provides a portable macro for use in generating compile-time warnings for
|
||||
use of code that is permitted but discouraged. */
|
||||
|
||||
#ifdef DRAKE_DOXYGEN_CXX
|
||||
/** Use `DRAKE_DEPRECATED("removal_date", "message")` to discourage use of
|
||||
certain APIs. It can be used on classes, typedefs, variables, non-static data
|
||||
members, functions, arguments, enumerations, and template specializations. When
|
||||
code refers to the deprecated item, a compile time warning will be issued
|
||||
displaying the given message, preceded by "DRAKE DEPRECATED: ". The Doxygen API
|
||||
reference will show that the API is deprecated, along with the message.
|
||||
|
||||
This is typically used for constructs that have been replaced by something
|
||||
better and it is good practice to suggest the appropriate replacement in the
|
||||
deprecation message. Deprecation warnings are conventionally used to convey to
|
||||
users that a feature they are depending on will be removed in a future release.
|
||||
|
||||
Every deprecation notice must include a date (as YYYY-MM-DD string) where the
|
||||
deprecated item is planned for removal. Future commits may change the date
|
||||
(e.g., delaying the removal) but should generally always reflect the best
|
||||
current expectation for removal.
|
||||
|
||||
Absent any other particular need, we prefer to use a deprecation period of
|
||||
three months by default, often rounded up to the next first of the month. So
|
||||
for code announced as deprecated on 2018-01-22 the removal_date would nominally
|
||||
be set to 2018-05-01.
|
||||
|
||||
Try to keep the date string immediately after the DRAKE_DEPRECATED macro name,
|
||||
even if the message itself must be wrapped to a new line:
|
||||
@code
|
||||
DRAKE_DEPRECATED("2038-01-19",
|
||||
"foo is being replaced with a safer, const-method named bar().")
|
||||
int foo();
|
||||
@endcode
|
||||
|
||||
Sample uses: @code
|
||||
// Attribute comes *before* declaration of a deprecated function or variable;
|
||||
// no semicolon is allowed.
|
||||
DRAKE_DEPRECATED("2038-01-19", "f() is slow; use g() instead.")
|
||||
int f(int arg);
|
||||
|
||||
// Attribute comes *after* struct, class, enum keyword.
|
||||
class DRAKE_DEPRECATED("2038-01-19", "Use MyNewClass instead.")
|
||||
MyClass {
|
||||
};
|
||||
|
||||
// Type alias goes before the '='.
|
||||
using NewType
|
||||
DRAKE_DEPRECATED("2038-01-19", "Use NewType instead.")
|
||||
= OldType;
|
||||
@endcode
|
||||
*/
|
||||
#define DRAKE_DEPRECATED(removal_date, message)
|
||||
|
||||
#else // DRAKE_DOXYGEN_CXX
|
||||
|
||||
#define DRAKE_DEPRECATED(removal_date, message) \
|
||||
[[deprecated( \
|
||||
"\nDRAKE DEPRECATED: " message \
|
||||
"\nThe deprecated code will be removed from Drake" \
|
||||
" on or after " removal_date ".")]]
|
||||
|
||||
#endif // DRAKE_DOXYGEN_CXX
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// TODO(jwnimmer-tri) Once we are in --std=c++17 mode as our minimum version,
|
||||
// we can remove this file and just say [[nodiscard]] directly everywhere.
|
||||
|
||||
#if defined(DRAKE_DOXYGEN_CXX) || __has_cpp_attribute(nodiscard)
|
||||
/** Synonym for [[nodiscard]], iff the current compiler supports it;
|
||||
see https://en.cppreference.com/w/cpp/language/attributes/nodiscard. */
|
||||
// NOLINTNEXTLINE(whitespace/braces)
|
||||
#define DRAKE_NODISCARD [[nodiscard]]
|
||||
#else
|
||||
#define DRAKE_NODISCARD
|
||||
#endif
|
||||
@@ -1,35 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace drake {
|
||||
|
||||
/// Provides a "dummy" value for a ScalarType -- a value that is unlikely to be
|
||||
/// mistaken for a purposefully-computed value, useful for initializing a value
|
||||
/// before the true result is available.
|
||||
///
|
||||
/// Defaults to using std::numeric_limits::quiet_NaN when available; it is a
|
||||
/// compile-time error to call the unspecialized dummy_value::get() when
|
||||
/// quiet_NaN is unavailable.
|
||||
///
|
||||
/// See autodiff_overloads.h to use this with Eigen's AutoDiffScalar.
|
||||
template <typename T>
|
||||
struct dummy_value {
|
||||
static constexpr T get() {
|
||||
static_assert(std::numeric_limits<T>::has_quiet_NaN,
|
||||
"Custom scalar types should specialize this struct");
|
||||
return std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct dummy_value<int> {
|
||||
static constexpr int get() {
|
||||
// D is for "Dummy". We assume as least 32 bits (per cppguide) -- if `int`
|
||||
// is larger than 32 bits, this will leave some fraction of the bytes zero
|
||||
// instead of 0xDD, but that's okay.
|
||||
return 0xDDDDDDDD;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace drake
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef DRAKE_COMMON_AUTODIFF_HEADER
|
||||
// TODO(soonho-tri): Change to #error.
|
||||
#warning Do not directly include this file. Include "drake/common/autodiff.h".
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
|
||||
// Eigen provides `numeric_limits<AutoDiffScalar<T>>` starting with v3.3.4.
|
||||
#if !EIGEN_VERSION_AT_LEAST(3, 3, 4) // Eigen Version < v3.3.4
|
||||
|
||||
namespace std {
|
||||
template <typename T>
|
||||
class numeric_limits<Eigen::AutoDiffScalar<T>>
|
||||
: public numeric_limits<typename T::Scalar> {};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // Eigen Version < v3.3.4
|
||||
@@ -1,38 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
/// @file
|
||||
/// This file contains abbreviated definitions for certain uses of
|
||||
/// AutoDiffScalar that are commonly used in Drake.
|
||||
/// @see also eigen_types.h
|
||||
|
||||
#ifndef DRAKE_COMMON_AUTODIFF_HEADER
|
||||
// TODO(soonho-tri): Change to #error.
|
||||
#warning Do not directly include this file. Include "drake/common/autodiff.h".
|
||||
#endif
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <Eigen/Core>
|
||||
|
||||
#include "drake/common/eigen_types.h"
|
||||
|
||||
namespace drake {
|
||||
|
||||
/// An autodiff variable with a dynamic number of partials.
|
||||
using AutoDiffXd = Eigen::AutoDiffScalar<Eigen::VectorXd>;
|
||||
|
||||
// TODO(hongkai-dai): Recursive template to get arbitrary gradient order.
|
||||
|
||||
/// An autodiff variable with `num_vars` partials.
|
||||
template <int num_vars>
|
||||
using AutoDiffd = Eigen::AutoDiffScalar<Eigen::Matrix<double, num_vars, 1> >;
|
||||
|
||||
/// A vector of `rows` autodiff variables, each with `num_vars` partials.
|
||||
template <int num_vars, int rows>
|
||||
using AutoDiffVecd = Eigen::Matrix<AutoDiffd<num_vars>, rows, 1>;
|
||||
|
||||
/// A dynamic-sized vector of autodiff variables, each with a dynamic-sized
|
||||
/// vector of partials.
|
||||
typedef AutoDiffVecd<Eigen::Dynamic, Eigen::Dynamic> AutoDiffVecXd;
|
||||
|
||||
} // namespace drake
|
||||
@@ -1,461 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
/// @file
|
||||
/// This file contains abbreviated definitions for certain specializations of
|
||||
/// Eigen::Matrix that are commonly used in Drake.
|
||||
/// These convenient definitions are templated on the scalar type of the Eigen
|
||||
/// object. While Drake uses `<T>` for scalar types across the entire code base
|
||||
/// we decided in this file to use `<Scalar>` to be more consistent with the
|
||||
/// usage of `<Scalar>` in Eigen's code base.
|
||||
/// @see also eigen_autodiff_types.h
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <Eigen/Core>
|
||||
|
||||
#include "drake/common/constants.h"
|
||||
#include "drake/common/drake_assert.h"
|
||||
#include "drake/common/drake_copyable.h"
|
||||
#include "drake/common/drake_deprecated.h"
|
||||
|
||||
namespace drake {
|
||||
|
||||
/// The empty column vector (zero rows, one column), templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Vector0 = Eigen::Matrix<Scalar, 0, 1>;
|
||||
|
||||
/// A column vector of size 1 (that is, a scalar), templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Vector1 = Eigen::Matrix<Scalar, 1, 1>;
|
||||
|
||||
/// A column vector of size 1 of doubles.
|
||||
using Vector1d = Eigen::Matrix<double, 1, 1>;
|
||||
|
||||
/// A column vector of size 2, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Vector2 = Eigen::Matrix<Scalar, 2, 1>;
|
||||
|
||||
/// A column vector of size 3, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Vector3 = Eigen::Matrix<Scalar, 3, 1>;
|
||||
|
||||
/// A column vector of size 4, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Vector4 = Eigen::Matrix<Scalar, 4, 1>;
|
||||
|
||||
/// A column vector of size 6.
|
||||
template <typename Scalar>
|
||||
using Vector6 = Eigen::Matrix<Scalar, 6, 1>;
|
||||
|
||||
/// A column vector templated on the number of rows.
|
||||
template <typename Scalar, int Rows>
|
||||
using Vector = Eigen::Matrix<Scalar, Rows, 1>;
|
||||
|
||||
/// A column vector of any size, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using VectorX = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>;
|
||||
|
||||
/// A vector of dynamic size templated on scalar type, up to a maximum of 6
|
||||
/// elements.
|
||||
template <typename Scalar>
|
||||
using VectorUpTo6 = Eigen::Matrix<Scalar, Eigen::Dynamic, 1, 0, 6, 1>;
|
||||
|
||||
/// A row vector of size 2, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using RowVector2 = Eigen::Matrix<Scalar, 1, 2>;
|
||||
|
||||
/// A row vector of size 3, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using RowVector3 = Eigen::Matrix<Scalar, 1, 3>;
|
||||
|
||||
/// A row vector of size 4, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using RowVector4 = Eigen::Matrix<Scalar, 1, 4>;
|
||||
|
||||
/// A row vector of size 6.
|
||||
template <typename Scalar>
|
||||
using RowVector6 = Eigen::Matrix<Scalar, 1, 6>;
|
||||
|
||||
/// A row vector templated on the number of columns.
|
||||
template <typename Scalar, int Cols>
|
||||
using RowVector = Eigen::Matrix<Scalar, 1, Cols>;
|
||||
|
||||
/// A row vector of any size, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using RowVectorX = Eigen::Matrix<Scalar, 1, Eigen::Dynamic>;
|
||||
|
||||
|
||||
/// A matrix of 2 rows and 2 columns, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Matrix2 = Eigen::Matrix<Scalar, 2, 2>;
|
||||
|
||||
/// A matrix of 3 rows and 3 columns, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Matrix3 = Eigen::Matrix<Scalar, 3, 3>;
|
||||
|
||||
/// A matrix of 4 rows and 4 columns, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Matrix4 = Eigen::Matrix<Scalar, 4, 4>;
|
||||
|
||||
/// A matrix of 6 rows and 6 columns, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Matrix6 = Eigen::Matrix<Scalar, 6, 6>;
|
||||
|
||||
/// A matrix of 2 rows, dynamic columns, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Matrix2X = Eigen::Matrix<Scalar, 2, Eigen::Dynamic>;
|
||||
|
||||
/// A matrix of 3 rows, dynamic columns, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Matrix3X = Eigen::Matrix<Scalar, 3, Eigen::Dynamic>;
|
||||
|
||||
/// A matrix of 4 rows, dynamic columns, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Matrix4X = Eigen::Matrix<Scalar, 4, Eigen::Dynamic>;
|
||||
|
||||
/// A matrix of 6 rows, dynamic columns, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Matrix6X = Eigen::Matrix<Scalar, 6, Eigen::Dynamic>;
|
||||
|
||||
/// A matrix of dynamic size, templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using MatrixX = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>;
|
||||
|
||||
/// A matrix of dynamic size templated on scalar type, up to a maximum of 6 rows
|
||||
/// and 6 columns. Rectangular matrices, with different number of rows and
|
||||
/// columns, are allowed.
|
||||
template <typename Scalar>
|
||||
using MatrixUpTo6 =
|
||||
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, 0, 6, 6>;
|
||||
|
||||
/// A quaternion templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Quaternion = Eigen::Quaternion<Scalar>;
|
||||
|
||||
/// An AngleAxis templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using AngleAxis = Eigen::AngleAxis<Scalar>;
|
||||
|
||||
/// An Isometry templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Isometry3 = Eigen::Transform<Scalar, 3, Eigen::Isometry>;
|
||||
|
||||
/// A translation in 3D templated on scalar type.
|
||||
template <typename Scalar>
|
||||
using Translation3 = Eigen::Translation<Scalar, 3>;
|
||||
|
||||
/// A column vector consisting of one twist.
|
||||
template <typename Scalar>
|
||||
using TwistVector = Eigen::Matrix<Scalar, kTwistSize, 1>;
|
||||
|
||||
/// A matrix with one twist per column, and dynamically many columns.
|
||||
template <typename Scalar>
|
||||
using TwistMatrix = Eigen::Matrix<Scalar, kTwistSize, Eigen::Dynamic>;
|
||||
|
||||
/// A six-by-six matrix.
|
||||
template <typename Scalar>
|
||||
using SquareTwistMatrix = Eigen::Matrix<Scalar, kTwistSize, kTwistSize>;
|
||||
|
||||
/// A column vector consisting of one wrench (spatial force) = `[r X f; f]`,
|
||||
/// where f is a force (translational force) applied at a point `P` and `r` is
|
||||
/// the position vector from a point `O` (called the "moment center") to point
|
||||
/// `P`.
|
||||
template <typename Scalar>
|
||||
using WrenchVector = Eigen::Matrix<Scalar, 6, 1>;
|
||||
|
||||
/// A column vector consisting of a concatenated rotational and translational
|
||||
/// force. The wrench is a special case of a SpatialForce. For a general
|
||||
/// SpatialForce the rotational force can be a pure torque or the accumulation
|
||||
/// of moments and need not necessarily be a function of the force term.
|
||||
template <typename Scalar>
|
||||
using SpatialForce
|
||||
DRAKE_DEPRECATED("2019-10-15", "Please use Vector6<> instead.")
|
||||
= Eigen::Matrix<Scalar, 6, 1>;
|
||||
|
||||
/// EigenSizeMinPreferDynamic<a, b>::value gives the min between compile-time
|
||||
/// sizes @p a and @p b. 0 has absolute priority, followed by 1, followed by
|
||||
/// Dynamic, followed by other finite values.
|
||||
///
|
||||
/// Note that this is a type-trait version of EIGEN_SIZE_MIN_PREFER_DYNAMIC
|
||||
/// macro in "Eigen/Core/util/Macros.h".
|
||||
template <int a, int b>
|
||||
struct EigenSizeMinPreferDynamic {
|
||||
// clang-format off
|
||||
static constexpr int value = (a == 0 || b == 0) ? 0 :
|
||||
(a == 1 || b == 1) ? 1 :
|
||||
(a == Eigen::Dynamic || b == Eigen::Dynamic) ? Eigen::Dynamic :
|
||||
a <= b ? a : b;
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
/// EigenSizeMinPreferFixed is a variant of EigenSizeMinPreferDynamic. The
|
||||
/// difference is that finite values now have priority over Dynamic, so that
|
||||
/// EigenSizeMinPreferFixed<3, Dynamic>::value gives 3.
|
||||
///
|
||||
/// Note that this is a type-trait version of EIGEN_SIZE_MIN_PREFER_FIXED macro
|
||||
/// in "Eigen/Core/util/Macros.h".
|
||||
template <int a, int b>
|
||||
struct EigenSizeMinPreferFixed {
|
||||
// clang-format off
|
||||
static constexpr int value = (a == 0 || b == 0) ? 0 :
|
||||
(a == 1 || b == 1) ? 1 :
|
||||
(a == Eigen::Dynamic && b == Eigen::Dynamic) ? Eigen::Dynamic :
|
||||
(a == Eigen::Dynamic) ? b :
|
||||
(b == Eigen::Dynamic) ? a :
|
||||
a <= b ? a : b;
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
/// MultiplyEigenSizes<a, b> gives a * b if both of a and b are fixed
|
||||
/// sizes. Otherwise it gives Eigen::Dynamic.
|
||||
template <int a, int b>
|
||||
struct MultiplyEigenSizes {
|
||||
static constexpr int value =
|
||||
(a == Eigen::Dynamic || b == Eigen::Dynamic) ? Eigen::Dynamic : a * b;
|
||||
};
|
||||
|
||||
/*
|
||||
* Determines if a type is derived from EigenBase<> (e.g. ArrayBase<>,
|
||||
* MatrixBase<>).
|
||||
*/
|
||||
template <typename Derived>
|
||||
struct is_eigen_type : std::is_base_of<Eigen::EigenBase<Derived>, Derived> {};
|
||||
|
||||
/*
|
||||
* Determines if an EigenBase<> has a specific scalar type.
|
||||
*/
|
||||
template <typename Derived, typename Scalar>
|
||||
struct is_eigen_scalar_same
|
||||
: std::integral_constant<
|
||||
bool, is_eigen_type<Derived>::value &&
|
||||
std::is_same<typename Derived::Scalar, Scalar>::value> {};
|
||||
|
||||
/*
|
||||
* Determines if an EigenBase<> type is a compile-time (column) vector.
|
||||
* This will not check for run-time size.
|
||||
*/
|
||||
template <typename Derived>
|
||||
struct is_eigen_vector
|
||||
: std::integral_constant<bool, is_eigen_type<Derived>::value &&
|
||||
Derived::ColsAtCompileTime == 1> {};
|
||||
|
||||
/*
|
||||
* Determines if an EigenBase<> type is a compile-time (column) vector of a
|
||||
* scalar type. This will not check for run-time size.
|
||||
*/
|
||||
template <typename Derived, typename Scalar>
|
||||
struct is_eigen_vector_of
|
||||
: std::integral_constant<
|
||||
bool, is_eigen_scalar_same<Derived, Scalar>::value &&
|
||||
is_eigen_vector<Derived>::value> {};
|
||||
|
||||
// TODO(eric.cousineau): A 1x1 matrix will be disqualified in this case, and
|
||||
// this logic will qualify it as a vector. Address the downstream logic if this
|
||||
// becomes an issue.
|
||||
/*
|
||||
* Determines if a EigenBase<> type is a compile-time non-column-vector matrix
|
||||
* of a scalar type. This will not check for run-time size.
|
||||
* @note For an EigenBase<> of the correct Scalar type, this logic is
|
||||
* exclusive to is_eigen_vector_of<> such that distinct specializations are not
|
||||
* ambiguous.
|
||||
*/
|
||||
template <typename Derived, typename Scalar>
|
||||
struct is_eigen_nonvector_of
|
||||
: std::integral_constant<
|
||||
bool, is_eigen_scalar_same<Derived, Scalar>::value &&
|
||||
!is_eigen_vector<Derived>::value> {};
|
||||
|
||||
// TODO(eric.cousineau): Add alias is_eigen_matrix_of = is_eigen_scalar_same if
|
||||
// appropriate.
|
||||
|
||||
/// This wrapper class provides a way to write non-template functions taking raw
|
||||
/// pointers to Eigen objects as parameters while limiting the number of copies,
|
||||
/// similar to `Eigen::Ref`. Internally, it keeps an instance of `Eigen::Ref<T>`
|
||||
/// and provides access to it via `operator*` and `operator->`.
|
||||
///
|
||||
/// The motivation of this class is to follow <a
|
||||
/// href="https://google.github.io/styleguide/cppguide.html#Reference_Arguments">GSG's
|
||||
/// "output arguments should be pointers" rule</a> while taking advantage of
|
||||
/// using `Eigen::Ref`. Here is an example.
|
||||
///
|
||||
/// @code
|
||||
/// // This function is taking an Eigen::Ref of a matrix and modifies it in
|
||||
/// // the body. This violates GSG's rule on output parameters.
|
||||
/// void foo(Eigen::Ref<Eigen::MatrixXd> M) {
|
||||
/// M(0, 0) = 0;
|
||||
/// }
|
||||
/// // At Call-site, we have:
|
||||
/// foo(M);
|
||||
/// foo(M.block(0, 0, 2, 2));
|
||||
///
|
||||
/// // We can rewrite the above function into the following using EigenPtr.
|
||||
/// void foo(EigenPtr<Eigen::MatrixXd> M) {
|
||||
/// (*M)(0, 0) = 0;
|
||||
/// }
|
||||
/// // Note that, call sites should be changed to:
|
||||
/// foo(&M);
|
||||
///
|
||||
/// // We need tmp to avoid taking the address of a temporary object such as the
|
||||
/// // return value of .block().
|
||||
/// auto tmp = M.block(0, 0, 2, 2);
|
||||
/// foo(&tmp);
|
||||
/// @endcode
|
||||
///
|
||||
/// Notice that methods taking an EigenPtr can mutate the entries of a matrix as
|
||||
/// in method `foo()` in the example code above, but cannot change its size.
|
||||
/// This is because `operator*` and `operator->` return an `Eigen::Ref<T>`
|
||||
/// object and only plain matrices/arrays can be resized and not expressions.
|
||||
/// This **is** the desired behavior, since resizing the block of a matrix or
|
||||
/// even a more general expression should not be allowed. If you do want to be
|
||||
/// able to resize a mutable matrix argument, then you must pass it as a
|
||||
/// `Matrix<T>*`, like so:
|
||||
/// @code
|
||||
/// void bar(Eigen::MatrixXd* M) {
|
||||
/// DRAKE_THROW_UNLESS(M != nullptr);
|
||||
/// // In this case this method only works with 4x3 matrices.
|
||||
/// if (M->rows() != 4 && M->cols() != 3) {
|
||||
/// M->resize(4, 3);
|
||||
/// }
|
||||
/// (*M)(0, 0) = 0;
|
||||
/// }
|
||||
/// @endcode
|
||||
///
|
||||
/// @note This class provides a way to avoid the `const_cast` hack introduced in
|
||||
/// <a
|
||||
/// href="https://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html#TopicPlainFunctionsFailing">Eigen's
|
||||
/// documentation</a>.
|
||||
template <typename PlainObjectType>
|
||||
class EigenPtr {
|
||||
public:
|
||||
typedef Eigen::Ref<PlainObjectType> RefType;
|
||||
|
||||
EigenPtr() : EigenPtr(nullptr) {}
|
||||
|
||||
/// Overload for `nullptr`.
|
||||
// NOLINTNEXTLINE(runtime/explicit) This conversion is desirable.
|
||||
EigenPtr(std::nullptr_t) {}
|
||||
|
||||
/// Constructs with a reference to the given matrix type.
|
||||
// NOLINTNEXTLINE(runtime/explicit) This conversion is desirable.
|
||||
EigenPtr(const EigenPtr& other) { assign(other); }
|
||||
|
||||
/// Constructs with a reference to another matrix type.
|
||||
/// May be `nullptr`.
|
||||
template <typename PlainObjectTypeIn>
|
||||
// NOLINTNEXTLINE(runtime/explicit) This conversion is desirable.
|
||||
EigenPtr(PlainObjectTypeIn* m) {
|
||||
if (m) {
|
||||
m_.set_value(m);
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs from another EigenPtr.
|
||||
template <typename PlainObjectTypeIn>
|
||||
// NOLINTNEXTLINE(runtime/explicit) This conversion is desirable.
|
||||
EigenPtr(const EigenPtr<PlainObjectTypeIn>& other) {
|
||||
// Cannot directly construct `m_` from `other.m_`.
|
||||
assign(other);
|
||||
}
|
||||
|
||||
EigenPtr& operator=(const EigenPtr& other) {
|
||||
// We must explicitly override this version of operator=.
|
||||
// The template below will not take precedence over this one.
|
||||
return assign(other);
|
||||
}
|
||||
|
||||
template <typename PlainObjectTypeIn>
|
||||
EigenPtr& operator=(const EigenPtr<PlainObjectTypeIn>& other) {
|
||||
return assign(other);
|
||||
}
|
||||
|
||||
/// @throws std::runtime_error if this is a null dereference.
|
||||
RefType& operator*() const { return get_reference(); }
|
||||
|
||||
/// @throws std::runtime_error if this is a null dereference.
|
||||
RefType* operator->() const { return &get_reference(); }
|
||||
|
||||
/// Returns whether or not this contains a valid reference.
|
||||
operator bool() const { return is_valid(); }
|
||||
|
||||
bool operator==(std::nullptr_t) const { return !is_valid(); }
|
||||
|
||||
bool operator!=(std::nullptr_t) const { return is_valid(); }
|
||||
|
||||
private:
|
||||
// Simple reassignable container without requirement of heap allocation.
|
||||
// This is used because `drake::optional<>` does not work with `Eigen::Ref<>`
|
||||
// because `Ref` deletes the necessary `operator=` overload for
|
||||
// `std::is_copy_assignable`.
|
||||
class ReassignableRef {
|
||||
public:
|
||||
DRAKE_NO_COPY_NO_MOVE_NO_ASSIGN(ReassignableRef)
|
||||
ReassignableRef() {}
|
||||
~ReassignableRef() {
|
||||
reset();
|
||||
}
|
||||
|
||||
// Reset value to null.
|
||||
void reset() {
|
||||
if (has_value_) {
|
||||
raw_value().~RefType();
|
||||
has_value_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Set value.
|
||||
template <typename PlainObjectTypeIn>
|
||||
void set_value(PlainObjectTypeIn* value_in) {
|
||||
if (has_value_) {
|
||||
raw_value().~RefType();
|
||||
}
|
||||
new (&raw_value()) RefType(*value_in);
|
||||
has_value_ = true;
|
||||
}
|
||||
|
||||
// Access to value.
|
||||
RefType& value() {
|
||||
DRAKE_ASSERT(has_value());
|
||||
return raw_value();
|
||||
}
|
||||
|
||||
// Indicates if it has a value.
|
||||
bool has_value() const { return has_value_; }
|
||||
|
||||
private:
|
||||
// Unsafe access to value.
|
||||
RefType& raw_value() { return reinterpret_cast<RefType&>(storage_); }
|
||||
|
||||
bool has_value_{};
|
||||
typename std::aligned_storage<sizeof(RefType), alignof(RefType)>::type
|
||||
storage_;
|
||||
};
|
||||
|
||||
// Use mutable, reassignable ref to permit pointer-like semantics (with
|
||||
// ownership) on the stack.
|
||||
mutable ReassignableRef m_;
|
||||
|
||||
// Consolidate assignment here, so that both the copy constructor and the
|
||||
// construction from another type may be used.
|
||||
template <typename PlainObjectTypeIn>
|
||||
EigenPtr& assign(const EigenPtr<PlainObjectTypeIn>& other) {
|
||||
if (other) {
|
||||
m_.set_value(&(*other));
|
||||
} else {
|
||||
m_.reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Consolidate getting a reference here.
|
||||
RefType& get_reference() const {
|
||||
if (!m_.has_value())
|
||||
throw std::runtime_error("EigenPtr: nullptr dereference");
|
||||
return m_.value();
|
||||
}
|
||||
|
||||
bool is_valid() const {
|
||||
return m_.has_value();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace drake
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <Eigen/Core>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "drake/common/drake_nodiscard.h"
|
||||
// #include "drake/common/text_logging.h"
|
||||
|
||||
namespace drake {
|
||||
|
||||
@@ -28,7 +28,7 @@ enum class MatrixCompareType { absolute, relative };
|
||||
* @return true if the two matrices are equal based on the specified tolerance.
|
||||
*/
|
||||
template <typename DerivedA, typename DerivedB>
|
||||
DRAKE_NODISCARD ::testing::AssertionResult CompareMatrices(
|
||||
[[nodiscard]] ::testing::AssertionResult CompareMatrices(
|
||||
const Eigen::MatrixBase<DerivedA>& m1,
|
||||
const Eigen::MatrixBase<DerivedB>& m2, double tolerance = 0.0,
|
||||
MatrixCompareType compare_type = MatrixCompareType::absolute) {
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace drake {
|
||||
|
||||
/// Documents the argument(s) as unused, placating GCC's -Wunused-parameter
|
||||
/// warning. This can be called within function bodies to mark that certain
|
||||
/// parameters are unused.
|
||||
///
|
||||
/// When possible, removing the unused parameter is better than placating the
|
||||
/// warning. However, in some cases the parameter is part of a virtual API or
|
||||
/// template concept that is used elsewhere, so we can't remove it. In those
|
||||
/// cases, this function might be an appropriate work-around.
|
||||
///
|
||||
/// Here's rough advice on how to fix Wunused-parameter warnings:
|
||||
///
|
||||
/// (1) If the parameter can be removed entirely, prefer that as the first
|
||||
/// choice. (This may not be possible if, e.g., a method must match some
|
||||
/// virtual API or template concept.)
|
||||
///
|
||||
/// (2) Unless the parameter name has acute value, prefer to omit the name of
|
||||
/// the parameter, leaving only the type, e.g.
|
||||
/// @code
|
||||
/// void Print(const State& state) override { /* No state to print. */ }
|
||||
/// @endcode
|
||||
/// changes to
|
||||
/// @code
|
||||
/// void Print(const State&) override { /* No state to print. */}
|
||||
/// @endcode
|
||||
/// This no longer triggers the warning and further makes it clear that a
|
||||
/// parameter required by the API is definitively unused in the function.
|
||||
///
|
||||
/// This is an especially good solution in the context of method
|
||||
/// definitions (vs declarations); the parameter name used in a definition
|
||||
/// is entirely irrelevant to Doxygen and most readers.
|
||||
///
|
||||
/// (3) When leaving the parameter name intact has acute value, it is
|
||||
/// acceptable to keep the name and mark it `unused`. For example, when
|
||||
/// the name appears as part of a virtual method's base class declaration,
|
||||
/// the name is used by Doxygen to document the method, e.g.,
|
||||
/// @code
|
||||
/// /** Sets the default State of a System. This default implementation is to
|
||||
/// set all zeros. Subclasses may override to use non-zero defaults. The
|
||||
/// custom defaults may be based on the given @p context, when relevant. */
|
||||
/// virtual void SetDefault(const Context<T>& context, State<T>* state) const {
|
||||
/// unused(context);
|
||||
/// state->SetZero();
|
||||
/// }
|
||||
/// @endcode
|
||||
///
|
||||
template <typename ... Args>
|
||||
void unused(const Args& ...) {}
|
||||
|
||||
} // namespace drake
|
||||
@@ -1,332 +0,0 @@
|
||||
/// @file
|
||||
/// Utilities for arithmetic on AutoDiffScalar.
|
||||
|
||||
// TODO(russt): rename methods to be GSG compliant.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <tuple>
|
||||
|
||||
#include <Eigen/Core>
|
||||
|
||||
#include "drake/common/autodiff.h"
|
||||
#include "drake/common/unused.h"
|
||||
|
||||
namespace drake {
|
||||
namespace math {
|
||||
|
||||
template <typename Derived>
|
||||
struct AutoDiffToValueMatrix {
|
||||
typedef typename Eigen::Matrix<typename Derived::Scalar::Scalar,
|
||||
Derived::RowsAtCompileTime,
|
||||
Derived::ColsAtCompileTime> type;
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
typename AutoDiffToValueMatrix<Derived>::type autoDiffToValueMatrix(
|
||||
const Eigen::MatrixBase<Derived>& auto_diff_matrix) {
|
||||
typename AutoDiffToValueMatrix<Derived>::type ret(auto_diff_matrix.rows(),
|
||||
auto_diff_matrix.cols());
|
||||
for (int i = 0; i < auto_diff_matrix.rows(); i++) {
|
||||
for (int j = 0; j < auto_diff_matrix.cols(); ++j) {
|
||||
ret(i, j) = auto_diff_matrix(i, j).value();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** `B = DiscardGradient(A)` enables casting from a matrix of AutoDiffScalars
|
||||
* to AutoDiffScalar::Scalar type, explicitly throwing away any gradient
|
||||
* information. For a matrix of type, e.g. `MatrixX<AutoDiffXd> A`, the
|
||||
* comparable operation
|
||||
* `B = A.cast<double>()`
|
||||
* should (and does) fail to compile. Use `DiscardGradient(A)` if you want to
|
||||
* force the cast (and explicitly declare that information is lost).
|
||||
*
|
||||
* This method is overloaded to permit the user to call it for double types and
|
||||
* AutoDiffScalar types (to avoid the calling function having to handle the
|
||||
* two cases differently).
|
||||
*
|
||||
* @see DiscardZeroGradient
|
||||
*/
|
||||
template <typename Derived>
|
||||
typename std::enable_if<
|
||||
!std::is_same<typename Derived::Scalar, double>::value,
|
||||
Eigen::Matrix<typename Derived::Scalar::Scalar, Derived::RowsAtCompileTime,
|
||||
Derived::ColsAtCompileTime, 0, Derived::MaxRowsAtCompileTime,
|
||||
Derived::MaxColsAtCompileTime>>::type
|
||||
DiscardGradient(const Eigen::MatrixBase<Derived>& auto_diff_matrix) {
|
||||
return autoDiffToValueMatrix(auto_diff_matrix);
|
||||
}
|
||||
|
||||
/// @see DiscardGradient().
|
||||
template <typename Derived>
|
||||
typename std::enable_if<
|
||||
std::is_same<typename Derived::Scalar, double>::value,
|
||||
const Eigen::MatrixBase<Derived>&>::type
|
||||
DiscardGradient(const Eigen::MatrixBase<Derived>& matrix) {
|
||||
return matrix;
|
||||
}
|
||||
|
||||
/// @see DiscardGradient().
|
||||
template <typename _Scalar, int _Dim, int _Mode, int _Options>
|
||||
typename std::enable_if<
|
||||
!std::is_same<_Scalar, double>::value,
|
||||
Eigen::Transform<typename _Scalar::Scalar, _Dim, _Mode, _Options>>::type
|
||||
DiscardGradient(const Eigen::Transform<_Scalar, _Dim, _Mode, _Options>&
|
||||
auto_diff_transform) {
|
||||
return Eigen::Transform<typename _Scalar::Scalar, _Dim, _Mode, _Options>(
|
||||
autoDiffToValueMatrix(auto_diff_transform.matrix()));
|
||||
}
|
||||
|
||||
/// @see DiscardGradient().
|
||||
template <typename _Scalar, int _Dim, int _Mode, int _Options>
|
||||
typename std::enable_if<std::is_same<_Scalar, double>::value,
|
||||
const Eigen::Transform<_Scalar, _Dim, _Mode,
|
||||
_Options>&>::type
|
||||
DiscardGradient(
|
||||
const Eigen::Transform<_Scalar, _Dim, _Mode, _Options>& transform) {
|
||||
return transform;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Initialize a single autodiff matrix given the corresponding value
|
||||
*matrix.
|
||||
*
|
||||
* Set the values of \p auto_diff_matrix to be equal to \p val, and for each
|
||||
*element i of \p auto_diff_matrix,
|
||||
* resize the derivatives vector to \p num_derivatives, and set derivative
|
||||
*number \p deriv_num_start + i to one (all other elements of the derivative
|
||||
*vector set to zero).
|
||||
*
|
||||
* \param[in] mat 'regular' matrix of values
|
||||
* \param[out] ret AutoDiff matrix
|
||||
* \param[in] num_derivatives the size of the derivatives vector @default the
|
||||
*size of mat
|
||||
* \param[in] deriv_num_start starting index into derivative vector (i.e.
|
||||
*element deriv_num_start in derivative vector corresponds to mat(0, 0)).
|
||||
*@default 0
|
||||
*/
|
||||
template <typename Derived, typename DerivedAutoDiff>
|
||||
void initializeAutoDiff(const Eigen::MatrixBase<Derived>& val,
|
||||
// TODO(#2274) Fix NOLINTNEXTLINE(runtime/references).
|
||||
Eigen::MatrixBase<DerivedAutoDiff>& auto_diff_matrix,
|
||||
Eigen::DenseIndex num_derivatives = Eigen::Dynamic,
|
||||
Eigen::DenseIndex deriv_num_start = 0) {
|
||||
using ADScalar = typename DerivedAutoDiff::Scalar;
|
||||
static_assert(static_cast<int>(Derived::RowsAtCompileTime) ==
|
||||
static_cast<int>(DerivedAutoDiff::RowsAtCompileTime),
|
||||
"auto diff matrix has wrong number of rows at compile time");
|
||||
static_assert(static_cast<int>(Derived::ColsAtCompileTime) ==
|
||||
static_cast<int>(DerivedAutoDiff::ColsAtCompileTime),
|
||||
"auto diff matrix has wrong number of columns at compile time");
|
||||
|
||||
if (num_derivatives == Eigen::Dynamic) num_derivatives = val.size();
|
||||
|
||||
auto_diff_matrix.resize(val.rows(), val.cols());
|
||||
Eigen::DenseIndex deriv_num = deriv_num_start;
|
||||
for (Eigen::DenseIndex i = 0; i < val.size(); i++) {
|
||||
auto_diff_matrix(i) = ADScalar(val(i), num_derivatives, deriv_num++);
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief The appropriate AutoDiffScalar gradient type given the value type and
|
||||
* the number of derivatives at compile time
|
||||
*/
|
||||
template <typename Derived, int Nq>
|
||||
using AutoDiffMatrixType = Eigen::Matrix<
|
||||
Eigen::AutoDiffScalar<Eigen::Matrix<typename Derived::Scalar, Nq, 1>>,
|
||||
Derived::RowsAtCompileTime, Derived::ColsAtCompileTime, 0,
|
||||
Derived::MaxRowsAtCompileTime, Derived::MaxColsAtCompileTime>;
|
||||
|
||||
/** \brief Initialize a single autodiff matrix given the corresponding value
|
||||
*matrix.
|
||||
*
|
||||
* Create autodiff matrix that matches \p mat in size with derivatives of
|
||||
*compile time size \p Nq and runtime size \p num_derivatives.
|
||||
* Set its values to be equal to \p val, and for each element i of \p
|
||||
*auto_diff_matrix, set derivative number \p deriv_num_start + i to one (all
|
||||
*other derivatives set to zero).
|
||||
*
|
||||
* \param[in] mat 'regular' matrix of values
|
||||
* \param[in] num_derivatives the size of the derivatives vector @default the
|
||||
*size of mat
|
||||
* \param[in] deriv_num_start starting index into derivative vector (i.e.
|
||||
*element deriv_num_start in derivative vector corresponds to mat(0, 0)).
|
||||
*@default 0
|
||||
* \return AutoDiff matrix
|
||||
*/
|
||||
template <int Nq = Eigen::Dynamic, typename Derived>
|
||||
AutoDiffMatrixType<Derived, Nq> initializeAutoDiff(
|
||||
const Eigen::MatrixBase<Derived>& mat,
|
||||
Eigen::DenseIndex num_derivatives = -1,
|
||||
Eigen::DenseIndex deriv_num_start = 0) {
|
||||
if (num_derivatives == -1) num_derivatives = mat.size();
|
||||
|
||||
AutoDiffMatrixType<Derived, Nq> ret(mat.rows(), mat.cols());
|
||||
initializeAutoDiff(mat, ret, num_derivatives, deriv_num_start);
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
template <typename Derived, typename Scalar>
|
||||
struct ResizeDerivativesToMatchScalarImpl {
|
||||
// TODO(#2274) Fix NOLINTNEXTLINE(runtime/references).
|
||||
static void run(Eigen::MatrixBase<Derived>&, const Scalar&) {}
|
||||
};
|
||||
|
||||
template <typename Derived, typename DerivType>
|
||||
struct ResizeDerivativesToMatchScalarImpl<Derived,
|
||||
Eigen::AutoDiffScalar<DerivType>> {
|
||||
using Scalar = Eigen::AutoDiffScalar<DerivType>;
|
||||
// TODO(#2274) Fix NOLINTNEXTLINE(runtime/references).
|
||||
static void run(Eigen::MatrixBase<Derived>& mat, const Scalar& scalar) {
|
||||
for (int i = 0; i < mat.size(); i++) {
|
||||
auto& derivs = mat(i).derivatives();
|
||||
if (derivs.size() == 0) {
|
||||
derivs.resize(scalar.derivatives().size());
|
||||
derivs.setZero();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
/** Resize derivatives vector of each element of a matrix to to match the size
|
||||
* of the derivatives vector of a given scalar.
|
||||
* \brief If the mat and scalar inputs are AutoDiffScalars, resize the
|
||||
* derivatives vector of each element of the matrix mat to match
|
||||
* the number of derivatives of the scalar. This is useful in functions that
|
||||
* return matrices that do not depend on an AutoDiffScalar
|
||||
* argument (e.g. a function with a constant output), while it is desired that
|
||||
* information about the number of derivatives is preserved.
|
||||
* \param mat matrix, for which the derivative vectors of the elements will be
|
||||
* resized
|
||||
* \param scalar scalar to match the derivative size vector against.
|
||||
*/
|
||||
template <typename Derived>
|
||||
// TODO(#2274) Fix NOLINTNEXTLINE(runtime/references).
|
||||
void resizeDerivativesToMatchScalar(Eigen::MatrixBase<Derived>& mat,
|
||||
const typename Derived::Scalar& scalar) {
|
||||
internal::ResizeDerivativesToMatchScalarImpl<
|
||||
Derived, typename Derived::Scalar>::run(mat, scalar);
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
/** \brief Helper for totalSizeAtCompileTime function (recursive)
|
||||
*/
|
||||
template <typename Head, typename... Tail>
|
||||
struct TotalSizeAtCompileTime {
|
||||
static constexpr int eval() {
|
||||
return Head::SizeAtCompileTime == Eigen::Dynamic ||
|
||||
TotalSizeAtCompileTime<Tail...>::eval() == Eigen::Dynamic
|
||||
? Eigen::Dynamic
|
||||
: Head::SizeAtCompileTime +
|
||||
TotalSizeAtCompileTime<Tail...>::eval();
|
||||
}
|
||||
};
|
||||
|
||||
/** \brief Helper for totalSizeAtCompileTime function (base case)
|
||||
*/
|
||||
template <typename Head>
|
||||
struct TotalSizeAtCompileTime<Head> {
|
||||
static constexpr int eval() { return Head::SizeAtCompileTime; }
|
||||
};
|
||||
|
||||
/** \brief Determine the total size at compile time of a number of arguments
|
||||
* based on their SizeAtCompileTime static members
|
||||
*/
|
||||
template <typename... Args>
|
||||
constexpr int totalSizeAtCompileTime() {
|
||||
return TotalSizeAtCompileTime<Args...>::eval();
|
||||
}
|
||||
|
||||
/** \brief Determine the total size at runtime of a number of arguments using
|
||||
* their size() methods (base case).
|
||||
*/
|
||||
constexpr Eigen::DenseIndex totalSizeAtRunTime() { return 0; }
|
||||
|
||||
/** \brief Determine the total size at runtime of a number of arguments using
|
||||
* their size() methods (recursive)
|
||||
*/
|
||||
template <typename Head, typename... Tail>
|
||||
Eigen::DenseIndex totalSizeAtRunTime(const Eigen::MatrixBase<Head>& head,
|
||||
const Tail&... tail) {
|
||||
return head.size() + totalSizeAtRunTime(tail...);
|
||||
}
|
||||
|
||||
/** \brief Helper for initializeAutoDiffTuple function (recursive)
|
||||
*/
|
||||
template <size_t Index>
|
||||
struct InitializeAutoDiffTupleHelper {
|
||||
template <typename... ValueTypes, typename... AutoDiffTypes>
|
||||
static void run(const std::tuple<ValueTypes...>& values,
|
||||
// TODO(#2274) Fix NOLINTNEXTLINE(runtime/references).
|
||||
std::tuple<AutoDiffTypes...>& auto_diffs,
|
||||
Eigen::DenseIndex num_derivatives,
|
||||
Eigen::DenseIndex deriv_num_start) {
|
||||
constexpr size_t tuple_index = sizeof...(AutoDiffTypes)-Index;
|
||||
const auto& value = std::get<tuple_index>(values);
|
||||
auto& auto_diff = std::get<tuple_index>(auto_diffs);
|
||||
auto_diff.resize(value.rows(), value.cols());
|
||||
initializeAutoDiff(value, auto_diff, num_derivatives, deriv_num_start);
|
||||
InitializeAutoDiffTupleHelper<Index - 1>::run(
|
||||
values, auto_diffs, num_derivatives, deriv_num_start + value.size());
|
||||
}
|
||||
};
|
||||
|
||||
/** \brief Helper for initializeAutoDiffTuple function (base case)
|
||||
*/
|
||||
template <>
|
||||
struct InitializeAutoDiffTupleHelper<0> {
|
||||
template <typename... ValueTypes, typename... AutoDiffTypes>
|
||||
static void run(const std::tuple<ValueTypes...>& values,
|
||||
const std::tuple<AutoDiffTypes...>& auto_diffs,
|
||||
Eigen::DenseIndex num_derivatives,
|
||||
Eigen::DenseIndex deriv_num_start) {
|
||||
unused(values, auto_diffs, num_derivatives, deriv_num_start);
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
/** \brief Given a series of Eigen matrices, create a tuple of corresponding
|
||||
*AutoDiff matrices with values equal to the input matrices and properly
|
||||
*initialized derivative vectors.
|
||||
*
|
||||
* The size of the derivative vector of each element of the matrices in the
|
||||
*output tuple will be the same, and will equal the sum of the number of
|
||||
*elements of the matrices in \p args.
|
||||
* If all of the matrices in \p args have fixed size, then the derivative
|
||||
*vectors will also have fixed size (being the sum of the sizes at compile time
|
||||
*of all of the input arguments),
|
||||
* otherwise the derivative vectors will have dynamic size.
|
||||
* The 0th element of the derivative vectors will correspond to the derivative
|
||||
*with respect to the 0th element of the first argument.
|
||||
* Subsequent derivative vector elements correspond first to subsequent elements
|
||||
*of the first input argument (traversed first by row, then by column), and so
|
||||
*on for subsequent arguments.
|
||||
*
|
||||
* \param args a series of Eigen matrices
|
||||
* \return a tuple of properly initialized AutoDiff matrices corresponding to \p
|
||||
*args
|
||||
*
|
||||
*/
|
||||
template <typename... Deriveds>
|
||||
std::tuple<AutoDiffMatrixType<
|
||||
Deriveds, internal::totalSizeAtCompileTime<Deriveds...>()>...>
|
||||
initializeAutoDiffTuple(const Eigen::MatrixBase<Deriveds>&... args) {
|
||||
Eigen::DenseIndex dynamic_num_derivs = internal::totalSizeAtRunTime(args...);
|
||||
std::tuple<AutoDiffMatrixType<
|
||||
Deriveds, internal::totalSizeAtCompileTime<Deriveds...>()>...>
|
||||
ret(AutoDiffMatrixType<Deriveds,
|
||||
internal::totalSizeAtCompileTime<Deriveds...>()>(
|
||||
args.rows(), args.cols())...);
|
||||
auto values = std::forward_as_tuple(args...);
|
||||
internal::InitializeAutoDiffTupleHelper<sizeof...(args)>::run(
|
||||
values, ret, dynamic_num_derivs, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace drake
|
||||
Reference in New Issue
Block a user