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