1 //
2 // All components of Drake are licensed under the BSD 3-Clause License
3 // shown below. Where noted in the source code, some portions may
4 // be subject to other permissive, non-viral licenses.
5 //
6 // Copyright 2012-2016 Robot Locomotion Group @ CSAIL
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are
11 // met:
12 //
13 // Redistributions of source code must retain the above copyright notice,
14 // this list of conditions and the following disclaimer.  Redistributions
15 // in binary form must reproduce the above copyright notice, this list of
16 // conditions and the following disclaimer in the documentation and/or
17 // other materials provided with the distribution.  Neither the name of
18 // the Massachusetts Institute of Technology nor the names of its
19 // contributors may be used to endorse or promote products derived from
20 // this software without specific prior written permission.
21 //
22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 //
34 
35 #pragma once
36 
37 /// @file
38 /// Provides pybind11 `type_caster`s for Eigen geometric types.
39 /// N.B. This uses some of pybind's coding conventions.
40 ///
41 /// See http://pybind11.readthedocs.io/en/stable/advanced/cast/custom.html for
42 /// more details on custom type casters.
43 
44 #include <string>
45 #include <utility>
46 
47 #include <Eigen/Dense>
48 #include "pybind11/eigen.h"
49 
50 namespace dart {
51 namespace python {
52 namespace detail {
53 
54 // Implements a `type_caster<>` specialization used to convert types using a
55 // specific wrapping policy.
56 // @tparam Wrapper
57 //  Struct which must provide `Type`, `WrappedType`, `unwrap`, and `wrap`.
58 // @tparam copy_only
59 //  This may only pass between C++ and Python as copies, not references.
60 // See `eigen_wrapper_*` structs below for more details.
61 template <typename Wrapper>
62 struct type_caster_wrapped {
63   using Type = typename Wrapper::Type;
64   using WrappedType = typename Wrapper::WrappedType;
65   using WrappedTypeCaster = ::pybind11::detail::type_caster<WrappedType>;
66 
67   // Python to C++.
loadtype_caster_wrapped68   bool load(::pybind11::handle src, bool converter) {
69     WrappedTypeCaster caster;
70     if (!caster.load(src, converter)) {
71       return false;
72     }
73     value_ = Wrapper::unwrap(caster.operator WrappedType&());
74     loaded_ = true;
75     return true;
76   }
77 
78   // See `pybind11/eigen.h`, `type_caster<>` implementations.
79   // N.B. Do not use `PYBIND11_TYPE_CASTER(...)` so we can avoid casting
80   // garbage values.
81   operator Type&() {
82     assert(loaded_);
83     return value_;
84   }
85   template <typename T> using cast_op_type =
86       ::pybind11::detail::movable_cast_op_type<T>;
87   static constexpr auto name = WrappedTypeCaster::props::descriptor;
88 
89   // C++ to Python.
90   template <typename TType>
casttype_caster_wrapped91   static ::pybind11::handle cast(TType&& src, ::pybind11::return_value_policy policy,
92       ::pybind11::handle parent) {
93     if (policy == ::pybind11::return_value_policy::reference ||
94         policy == ::pybind11::return_value_policy::reference_internal) {
95       // N.B. We must declare a local `static constexpr` here to prevent
96       // linking errors. This does not appear achievable with
97       // `constexpr char[]`, so we use `::pybind11::detail::descr`.
98       // See `pybind11/pybind11.h`, `cpp_function::initialize(...)` for an
99       // example.
100       static constexpr auto original_name = Wrapper::original_name;
101       throw ::pybind11::cast_error(
102           std::string("Can only pass ") + original_name.text +
103           " by value.");
104     }
105     return WrappedTypeCaster::cast(
106         Wrapper::wrap(std::forward<TType>(src)), policy, parent);
107   }
108 
109  private:
110   bool loaded_{false};
111   Type value_;
112 };
113 
114 // Wrapper for Eigen::Translation<>, to be used as first parameter to
115 // `type_caster_wrapped`.
116 // Since there are not many special operations for a translation vector, we
117 // shall return it as a nominal vector.
118 template <typename T, int Dim>
119 struct wrapper_eigen_translation {
120   using Type = Eigen::Translation<T, Dim>;
121   using WrappedType = Eigen::Matrix<T, Dim, 1>;
122   static constexpr auto original_name = ::pybind11::detail::_("Eigen::Translation<>");
unwrapwrapper_eigen_translation123   static Type unwrap(const WrappedType& arg_wrapped) {
124     return Type(arg_wrapped);
125   }
wrapwrapper_eigen_translation126   static WrappedType wrap(const Type& arg) {
127     return arg.vector();
128   }
129 };
130 
131 // N.B. Since `Isometry3<>` and `Eigen::Quaternion<>` have more
132 // complicated structures, they are registered as types in `eigen_geometry_py`.
133 
134 }  // namespace detail
135 }  // namespace python
136 }  // namespace dart
137 
138 namespace pybind11 {
139 namespace detail {
140 
141 template <typename T, int Dim>
142 struct type_caster<Eigen::Translation<T, Dim>>
143     : public dart::python::detail::type_caster_wrapped<
144         dart::python::detail::wrapper_eigen_translation<T, Dim>> {};
145 
146 }  // namespace detail
147 }  // namespace pybind11
148