Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement iDynTree base type type_caster for pybind11 bindings #931

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
8a40642
Implement raw buffer constructor for the Position class
GiulioRomualdi Nov 6, 2021
f2f6237
Implement pybind11 type_caster for iDynTree core types
GiulioRomualdi Nov 6, 2021
c46a4bf
Use pybidn11 typecaster in the already existing bindings
GiulioRomualdi Nov 6, 2021
030066e
Make rotation and position property readable and writable in the pybi…
GiulioRomualdi Nov 6, 2021
c955175
Update the pybind11 tests
GiulioRomualdi Nov 8, 2021
a6c3058
Update the CHANGELOG
GiulioRomualdi Nov 8, 2021
899643b
Update CHANGELOG.md
GiulioRomualdi Nov 23, 2021
ecc64ad
Improve the idyntree_type_caster structs
GiulioRomualdi Nov 25, 2021
f60121c
Revert "Use pybidn11 typecaster in the already existing bindings"
GiulioRomualdi Nov 25, 2021
97faee1
Use pybind11 typecaster in the already existing bindings
GiulioRomualdi Nov 25, 2021
4a5509a
Revert "Implement raw buffer constructor for the Position class"
GiulioRomualdi Nov 25, 2021
2f7fa5b
Fix type 'struct type_caster' violates one definition rule [-Wodr] bu…
GiulioRomualdi Nov 25, 2021
7037767
Rename idyntree_type_caster.h into idyntree_vector_casters.h
GiulioRomualdi Nov 25, 2021
97236d6
Bugfix th the idyntree_vector_casters load functions
GiulioRomualdi Nov 25, 2021
b3df484
Use a single namespace conversion in the idyntree_vector_casters.h
GiulioRomualdi Nov 25, 2021
6a0db62
Create idyntree-pybind11 library
GiulioRomualdi Nov 25, 2021
0b3b349
Define the iDynTreeBindings project only if IDYNTREE_BINDINGS_BUILD_S…
GiulioRomualdi Nov 25, 2021
7552d12
Fix style in VectorCasters.h file
GiulioRomualdi Nov 25, 2021
c746633
Fix style in bindings/pybind11/idyntree_core.cpp file
GiulioRomualdi Nov 25, 2021
376690f
Revert "Update the pybind11 tests"
GiulioRomualdi Nov 25, 2021
a7522fe
Update of the python tests
GiulioRomualdi Nov 25, 2021
f04e844
Implement baseVectorDefinition and baseMatrixDefinition in bindings/p…
GiulioRomualdi Nov 25, 2021
c16496f
Bugfix in VectorCasters.h
GiulioRomualdi Nov 25, 2021
609923d
Uniform pybind11 target_link_libraries
GiulioRomualdi Nov 25, 2021
25d5728
Implement the test for pybind11 type_caster
GiulioRomualdi Nov 25, 2021
ec7c8f6
Merge remote-tracking branch 'origin/devel' into pybind11/type_caster
GiulioRomualdi Nov 26, 2021
9258e6b
Fix typo in pybind11/CMakeLists.txt
GiulioRomualdi Nov 26, 2021
58f5fca
Fix style in VectorCasters.h
GiulioRomualdi Nov 28, 2021
10658f3
Fix WORKING_DIRECTORY of pybind11 tests
GiulioRomualdi Nov 28, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion bindings/pybind11/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ pybind11_add_module(pybind11_idyntree SYSTEM idyntree.cpp
error_utilities.h error_utilities.cpp
idyntree_model.h idyntree_model.cpp
idyntree_sensors.h idyntree_sensors.cpp
idyntree_modelio_urdf.h idyntree_modelio_urdf.cpp)
idyntree_modelio_urdf.h idyntree_modelio_urdf.cpp
idyntree_type_caster.h)

target_link_libraries(pybind11_idyntree PUBLIC idyntree-core
idyntree-model
Expand Down
274 changes: 60 additions & 214 deletions bindings/pybind11/idyntree_core.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "idyntree_core.h"
#include "idyntree_type_caster.h"

#include <iDynTree/Core/Axis.h>
#include <iDynTree/Core/Direction.h>
Expand All @@ -24,144 +25,14 @@ namespace bindings {
namespace {
namespace py = ::pybind11;

void vectorDynSizeClassDefinition(py::class_<VectorDynSize>& vector) {
vector.def(py::init())
.def(py::init<unsigned>())
.def("__getitem__", py::overload_cast<const std::size_t>(
&VectorDynSize::operator(), py::const_))
.def("__setitem__",
[](VectorDynSize& the_vector, std::size_t index, double new_value) {
the_vector(index) = new_value;
})
.def(
"__iter__",
[](const VectorDynSize& s) {
return py::make_iterator(s.begin(), s.end());
},
py::keep_alive<
0, 1>() /* Essential: keep object alive while iterator exists */)
.def("__len__", &VectorDynSize::size)
.def("set_zero", &VectorDynSize::zero)
.def("resize", &VectorDynSize::resize)
.def("__repr__", &VectorDynSize::toString)
.def_buffer([](VectorDynSize& v) -> py::buffer_info {
return py::buffer_info(
v.data(), /* Pointer to buffer */
sizeof(double), /* Size of one scalar */
py::format_descriptor<double>::format(), /* Python struct-style
format descriptor */
1, /* Number of dimensions */
{v.size()}, /* Buffer dimensions */
{sizeof(double)} /* Strides (in bytes) for each index */
);
});
}

template <unsigned size>
void createFixSizeVector(pybind11::module& module,
const std::string& class_name) {
py::class_<VectorFixSize<size>>(module, class_name.c_str(),
py::buffer_protocol())
.def(py::init())
.def("__getitem__", py::overload_cast<const std::size_t>(
&VectorFixSize<size>::operator(), py::const_))
.def("__setitem__",
[](VectorFixSize<size>& the_vector, std::size_t index,
double new_value) { the_vector(index) = new_value; })
.def("__len__", &VectorFixSize<size>::size)
.def(
"__iter__",
[](const VectorFixSize<size>& s) {
return py::make_iterator(s.begin(), s.end());
},
py::keep_alive<
0, 1>() /* Essential: keep object alive while iterator exists */)
.def("set_zero", &VectorFixSize<size>::zero)
.def("__repr__", &VectorFixSize<size>::toString)
.def_buffer([](VectorFixSize<size>& v) -> py::buffer_info {
return py::buffer_info(
v.data(), /* Pointer to buffer */
sizeof(double), /* Size of one scalar */
py::format_descriptor<double>::format(), /* Python struct-style
format descriptor */
1, /* Number of dimensions */
{v.size()}, /* Buffer dimensions */
{sizeof(double)} /* Strides (in bytes) for each index */
);
});
}

void matrixDynSizeClassDefinition(py::class_<MatrixDynSize>& matrix) {
matrix.def(py::init())
.def(py::init<unsigned, unsigned>())
.def("__getitem__",
[](MatrixDynSize& matrix,
std::pair<std::size_t, std::size_t> indices) {
return matrix.getVal(indices.first, indices.second);
})
.def("__setitem__",
[](MatrixDynSize& matrix,
std::pair<std::size_t, std::size_t> indices, double item) {
return matrix.setVal(indices.first, indices.second, item);
})
.def("rows", &MatrixDynSize::rows)
.def("cols", &MatrixDynSize::cols)
.def("set_zero", &MatrixDynSize::zero)
.def("resize", &MatrixDynSize::resize)
.def("__repr__", &MatrixDynSize::toString)
.def_buffer([](MatrixDynSize& m) -> py::buffer_info {
return py::buffer_info(
m.data(), /* Pointer to buffer */
sizeof(double), /* Size of one scalar */
py::format_descriptor<double>::format(), /* Python struct-style
format descriptor */
2, /* Number of dimensions */
{m.rows(), m.cols()}, /* Buffer dimensions */
{sizeof(double) * m.cols(), /* Strides (in bytes) for each index */
sizeof(double)});
});
}

template <unsigned rows, unsigned cols>
void createFixSizeMatrix(pybind11::module& module,
const std::string& class_name) {
py::class_<MatrixFixSize<rows, cols>>(module, class_name.c_str(),
py::buffer_protocol())
.def(py::init())
.def("__getitem__",
[](MatrixFixSize<rows, cols>& matrix,
std::pair<std::size_t, std::size_t> indices) {
return matrix.getVal(indices.first, indices.second);
})
.def("__setitem__",
[](MatrixFixSize<rows, cols>& matrix,
std::pair<std::size_t, std::size_t> indices, double item) {
return matrix.setVal(indices.first, indices.second, item);
})
.def("rows", &MatrixFixSize<rows, cols>::rows)
.def("cols", &MatrixFixSize<rows, cols>::cols)
.def("set_zero", &MatrixFixSize<rows, cols>::zero)
.def("__repr__", &MatrixFixSize<rows, cols>::toString)
.def_buffer([](MatrixFixSize<rows, cols>& m) -> py::buffer_info {
return py::buffer_info(
m.data(), /* Pointer to buffer */
sizeof(double), /* Size of one scalar */
py::format_descriptor<double>::format(), /* Python struct-style
format descriptor */
2, /* Number of dimensions */
{m.rows(), m.cols()}, /* Buffer dimensions */
{sizeof(double) * m.cols(), /* Strides (in bytes) for each index */
sizeof(double)});
});
}

void transformClassDefinition(py::class_<Transform>& transform) {
transform.def(py::init())
.def(py::init<const Rotation&, const Position&>())
.def(py::init<const MatrixFixSize<4, 4>&>())
.def_static("Identity", &Transform::Identity)
.def_property_readonly("rotation", &Transform::getRotation)
.def_property_readonly("position", &Transform::getPosition)
.def_property("rotation", &Transform::getRotation, &Transform::setRotation)
.def_property("position", &Transform::getPosition, &Transform::setPosition)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 spaces here.

.def("inverse", &Transform::inverse)
.def(py::self * py::self)
.def(
Expand All @@ -179,89 +50,64 @@ void transformClassDefinition(py::class_<Transform>& transform) {
} // namespace

void iDynTreeCoreBindings(pybind11::module& module) {
// Vectors and matrices.
py::class_<VectorDynSize> vector_dyn(module, "VectorDynSize",
py::buffer_protocol());
vectorDynSizeClassDefinition(vector_dyn);
createFixSizeVector<3>(module, "Vector3");
createFixSizeVector<4>(module, "Vector4");
createFixSizeVector<6>(module, "Vector6");

py::class_<MatrixDynSize> matrix_dyn(module, "MatrixDynSize",
py::buffer_protocol());
matrixDynSizeClassDefinition(matrix_dyn);
createFixSizeMatrix<3, 3>(module, "Matrix3x3");
createFixSizeMatrix<4, 4>(module, "Matrix4x4");
createFixSizeMatrix<6, 6>(module, "Matrix6x6");

// Positions, Rotations and Transforms.
py::class_<PositionRaw, VectorFixSize<3>>(module, "_PositionRaw")
// Do not expose constructor as we do not want users to use this class.
.def("__repr__", &PositionRaw::toString);

py::class_<Position, PositionRaw>(module, "Position")
GiulioRomualdi marked this conversation as resolved.
Show resolved Hide resolved
.def(py::init())
.def(py::init<double, double, double>())
.def(py::self + py::self)
.def(py::self - py::self)
.def(-py::self)
.def_static("Zero", &Position::Zero);

py::class_<RotationRaw, MatrixFixSize<3, 3>>(module, "_RotationRaw")
// Do not expose constructor as we do not want users to use this class.
.def("__repr__", &RotationRaw::toString);

py::class_<Rotation, RotationRaw>(module, "Rotation")
.def(py::init())
.def(py::init<double, double, double, //
double, double, double, //
double, double, double>())
.def("inverse", &Rotation::inverse)
.def(py::self * py::self)
.def(
"__mul__",
[](const Rotation& r, const Position& p) -> Position {
return r * p;
},
py::is_operator())
.def_static("Identity", &Rotation::Identity);

py::class_<Transform> transform(module, "Transform");
transformClassDefinition(transform);

// Other classes.
py::class_<Direction, VectorFixSize<3>>(module, "Direction")
.def(py::init<double, double, double>());

py::class_<Axis>(module, "Axis")
.def(py::init<const Direction&, const Position&>())
.def_property("direction", &Axis::getDirection, &Axis::setDirection)
.def_property("origin", &Axis::getOrigin, &Axis::setOrigin)
.def("__repr__", &Axis::toString);

py::class_<RotationalInertiaRaw, MatrixFixSize<3, 3>>(module,
"RotationalInertia")
.def(py::init());

py::class_<SpatialInertiaRaw>(module, "_SpatialInertiaRaw")
.def("from_rotational_inertia_wrt_center_of_mass",
&SpatialInertiaRaw::fromRotationalInertiaWrtCenterOfMass)
.def("get_mass", &SpatialInertiaRaw::getMass)
.def("get_center_of_mass", &SpatialInertiaRaw::getCenterOfMass)
.def("get_rotational_inertia_wrt_frame_origin",
&SpatialInertiaRaw::getRotationalInertiaWrtFrameOrigin)
.def("get_rotational_inertia_wrt_center_of_mass",
&SpatialInertiaRaw::getRotationalInertiaWrtCenterOfMass);

py::class_<SpatialInertia, SpatialInertiaRaw>(module, "SpatialInertia")
.def(py::init())
.def(py::init<double, const PositionRaw&, const RotationalInertiaRaw&>())
.def_static("Zero", &SpatialInertia::Zero)
.def("as_matrix", &SpatialInertia::asMatrix)
.def(py::self + py::self)
.def("__repr__", [](const SpatialInertia& inertia) {
return inertia.asMatrix().toString();
});
py::class_<Rotation>(module, "Rotation")
.def(py::init())
.def(py::init<double,
double,
double, //
double,
double,
double, //
double,
double,
double>())
GiulioRomualdi marked this conversation as resolved.
Show resolved Hide resolved
.def("inverse", &Rotation::inverse)
.def(py::self * py::self)
.def(
"__mul__",
[](const Rotation& r, const Position& p) -> Position { return r * p; },
py::is_operator())
.def_static("Identity", &Rotation::Identity)
.def("__repr__", &Rotation::toString)
.def("to_numpy",
[](const Rotation& impl) {
iDynTree::Matrix3x3 m(impl.data(), 3, 3);
return m;
})
.def("__getitem__",
[](const Rotation& matrix, std::pair<std::size_t, std::size_t> indices) {
return matrix.getVal(indices.first, indices.second);
});

py::class_<Transform> transform(module, "Transform");
transformClassDefinition(transform);

// Other classes.
py::class_<Axis>(module, "Axis")
.def(py::init<const Direction&, const Position&>())
.def_property("direction", &Axis::getDirection, &Axis::setDirection)
.def_property("origin", &Axis::getOrigin, &Axis::setOrigin)
.def("__repr__", &Axis::toString);

py::class_<SpatialInertiaRaw>(module, "_SpatialInertiaRaw")
.def("from_rotational_inertia_wrt_center_of_mass",
&SpatialInertiaRaw::fromRotationalInertiaWrtCenterOfMass)
.def("get_mass", &SpatialInertiaRaw::getMass)
.def("get_center_of_mass", &SpatialInertiaRaw::getCenterOfMass)
.def("get_rotational_inertia_wrt_frame_origin",
&SpatialInertiaRaw::getRotationalInertiaWrtFrameOrigin)
.def("get_rotational_inertia_wrt_center_of_mass",
&SpatialInertiaRaw::getRotationalInertiaWrtCenterOfMass);

py::class_<SpatialInertia, SpatialInertiaRaw>(module, "SpatialInertia")
.def(py::init())
.def(py::init<double, const PositionRaw&, const RotationalInertiaRaw&>())
.def_static("Zero", &SpatialInertia::Zero)
.def("as_matrix", &SpatialInertia::asMatrix)
.def(py::self + py::self)
.def("__repr__",
[](const SpatialInertia& inertia) { return inertia.asMatrix().toString(); });
}
} // namespace bindings
} // namespace iDynTree
1 change: 1 addition & 0 deletions bindings/pybind11/idyntree_model.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "idyntree_model.h"
#include "idyntree_type_caster.h"

#include "error_utilities.h"

Expand Down
2 changes: 1 addition & 1 deletion bindings/pybind11/idyntree_modelio_urdf.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "idyntree_modelio_urdf.h"

#include "error_utilities.h"
#include "idyntree_type_caster.h"

#include <string>
#include <iDynTree/ModelIO/ModelExporter.h>
Expand Down
1 change: 1 addition & 0 deletions bindings/pybind11/idyntree_sensors.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "idyntree_sensors.h"
#include "error_utilities.h"
#include "idyntree_type_caster.h"

#include <pybind11/operators.h>
#include <pybind11/pybind11.h>
Expand Down
Loading