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

Vector2, 3 and 4 with pybind11 #280

Merged
merged 32 commits into from
Dec 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
5d07bc1
Vector2, 3 and 4 with pybind11
ahcorde Nov 5, 2021
5be5d76
Fixed some cmake issues and add docs
ahcorde Nov 15, 2021
e6da7ee
Merge branch 'ign-math6' into ahcorde/math/pybind11
ahcorde Nov 15, 2021
0fc8ce1
improve pybin11 cmake logic
ahcorde Nov 16, 2021
c79da0a
improved logic
ahcorde Nov 16, 2021
d2ae3ec
fixed cmake
ahcorde Nov 16, 2021
40d1fff
make linters happy
ahcorde Nov 16, 2021
5f2960c
make linters happy
ahcorde Nov 16, 2021
72e1e46
Added pybind11 minimum version
ahcorde Nov 19, 2021
7e76726
fixed cmake
ahcorde Nov 19, 2021
47122db
Fixed cmake
ahcorde Nov 19, 2021
de87b56
Fixed cmake
ahcorde Nov 19, 2021
690a636
Fixed windows warnings
ahcorde Nov 19, 2021
9c852f1
Fixed macos build
ahcorde Nov 19, 2021
d75b363
Windows warnings a separate PR
ahcorde Nov 22, 2021
575bbad
Merge branch 'ign-math6' into ahcorde/math/pybind11
ahcorde Nov 23, 2021
5082bdd
Merge branch 'ign-math6' into ahcorde/math/pybind11
ahcorde Nov 29, 2021
43aa6a2
fixed windows warnings
ahcorde Nov 30, 2021
41c5923
Merge branch 'ign-math6' into ahcorde/math/pybind11
scpeters Dec 8, 2021
7a13330
Removed download pybind11 in cmakelists
ahcorde Dec 9, 2021
1f3a560
Merge branch 'ahcorde/math/pybind11' of https://github.com/ignitionro…
ahcorde Dec 9, 2021
69ec3db
Follow code conventions
ahcorde Dec 10, 2021
0608228
fixed license
ahcorde Dec 10, 2021
0ce53e5
Fix
ahcorde Dec 10, 2021
384b0ca
fix
ahcorde Dec 10, 2021
b2196c3
fix
ahcorde Dec 10, 2021
ea51ad2
Fix vector2_TEST.py
ahcorde Dec 10, 2021
c45d889
Merge branch 'ign-math6' into ahcorde/math/pybind11
ahcorde Dec 15, 2021
7894311
Added feedback
ahcorde Dec 15, 2021
cf478a9
udpate vector3 test
ahcorde Dec 15, 2021
2e43780
fixed typo
ahcorde Dec 15, 2021
2f77fc0
feddback
ahcorde Dec 15, 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
1 change: 1 addition & 0 deletions .github/ci/packages.apt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ libeigen3-dev
libignition-cmake2-dev
ruby-dev
swig
python3-pybind11
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ find_package(ignition-cmake2 2.8.0 REQUIRED)
# Configure the project
#============================================================================
set (c++standard 17)
set (CMAKE_CXX_STANDARD 17)
ign_configure_project(VERSION_SUFFIX)

#============================================================================
Expand Down
4 changes: 2 additions & 2 deletions include/ignition/math/Vector2.hh
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ namespace ignition
/// \return the result
public: Vector2 Round()
{
this->data[0] = std::nearbyint(this->data[0]);
this->data[1] = std::nearbyint(this->data[1]);
this->data[0] = static_cast<T>(std::nearbyint(this->data[0]));
this->data[1] = static_cast<T>(std::nearbyint(this->data[1]));
return *this;
}

Expand Down
6 changes: 3 additions & 3 deletions include/ignition/math/Vector3.hh
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,9 @@ namespace ignition
/// \return the result
public: Vector3 Round()
{
this->data[0] = std::nearbyint(this->data[0]);
this->data[1] = std::nearbyint(this->data[1]);
this->data[2] = std::nearbyint(this->data[2]);
this->data[0] = static_cast<T>(std::nearbyint(this->data[0]));
this->data[1] = static_cast<T>(std::nearbyint(this->data[1]));
this->data[2] = static_cast<T>(std::nearbyint(this->data[2]));
return *this;
}

Expand Down
8 changes: 4 additions & 4 deletions include/ignition/math/Vector4.hh
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ namespace ignition
/// \brief Round to near whole number.
public: void Round()
{
this->data[0] = std::nearbyint(this->data[0]);
this->data[1] = std::nearbyint(this->data[1]);
this->data[2] = std::nearbyint(this->data[2]);
this->data[3] = std::nearbyint(this->data[3]);
this->data[0] = static_cast<T>(std::nearbyint(this->data[0]));
this->data[1] = static_cast<T>(std::nearbyint(this->data[1]));
this->data[2] = static_cast<T>(std::nearbyint(this->data[2]));
this->data[3] = static_cast<T>(std::nearbyint(this->data[3]));
}

/// \brief Get a rounded version of this vector
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ add_subdirectory(graph)

# Bindings subdirectories
add_subdirectory(python)
add_subdirectory(python_pybind11)
add_subdirectory(ruby)
11 changes: 4 additions & 7 deletions src/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ if (PYTHONLIBS_FOUND)
set(SWIG_PY_LIB pymath)
set(SWIG_PY_LIB_OUTPUT math)

set(CMAKE_SWIG_OUTDIR "${CMAKE_BINARY_DIR}/lib/python")
set(CMAKE_SWIG_OUTDIR "${CMAKE_BINARY_DIR}/lib/python/swig")
if(CMAKE_VERSION VERSION_GREATER 3.8.0)
SWIG_ADD_LIBRARY(${SWIG_PY_LIB} LANGUAGE python SOURCES python.i)
else()
Expand Down Expand Up @@ -77,12 +77,12 @@ if (PYTHONLIBS_FOUND)
endif()
else()
# If not a system installation, respect local paths
set(IGN_PYTHON_INSTALL_PATH ${IGN_LIB_INSTALL_DIR}/python)
set(IGN_PYTHON_INSTALL_PATH ${IGN_LIB_INSTALL_DIR}/python/swig)
endif()

set(IGN_PYTHON_INSTALL_PATH "${IGN_PYTHON_INSTALL_PATH}/ignition")
install(TARGETS ${SWIG_PY_LIB} DESTINATION ${IGN_PYTHON_INSTALL_PATH})
install(FILES ${CMAKE_BINARY_DIR}/lib/python/math.py DESTINATION ${IGN_PYTHON_INSTALL_PATH})
install(FILES ${CMAKE_BINARY_DIR}/lib/python/swig/math.py DESTINATION ${IGN_PYTHON_INSTALL_PATH})

if (BUILD_TESTING)
# Add the Python tests
Expand Down Expand Up @@ -124,18 +124,15 @@ if (PYTHONLIBS_FOUND)
Temperature_TEST
Triangle_TEST
Triangle3_TEST
Vector2_TEST
Vector3_TEST
Vector3Stats_TEST
Vector4_TEST
)

foreach (test ${python_tests})
add_test(NAME ${test}.py COMMAND
"${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/src/python/${test}.py")

set(_env_vars)
list(APPEND _env_vars "PYTHONPATH=${FAKE_INSTALL_PREFIX}/lib/python/")
list(APPEND _env_vars "PYTHONPATH=${FAKE_INSTALL_PREFIX}/lib/python/swig")
list(APPEND _env_vars "LD_LIBRARY_PATH=${FAKE_INSTALL_PREFIX}/lib:$ENV{LD_LIBRARY_PATH}")
set_tests_properties(${test}.py PROPERTIES
ENVIRONMENT "${_env_vars}")
Expand Down
82 changes: 82 additions & 0 deletions src/python_pybind11/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
if(WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Debug")
# pybind11 logic for setting up a debug build when both a debug and release
# python interpreter are present in the system seems to be pretty much broken.
# This works around the issue.
set(PYTHON_LIBRARIES "${PYTHON_DEBUG_LIBRARIES}")
endif()

set(PYBIND11_PYTHON_VERSION 3)

find_package(pybind11 2.2 QUIET)

if (${pybind11_FOUND})
message(STATUS "Building pybind11 interfaces")
# Split from main extension and converted to pybind11
pybind11_add_module(math SHARED
src/_ignition_math_pybind11.cc
)

if(USE_SYSTEM_PATHS_FOR_PYTHON_INSTALLATION)
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
execute_process(
COMMAND "${PYTHON_EXECUTABLE}" -c "if True:
from distutils import sysconfig as sc
print(sc.get_python_lib(plat_specific=True))"
OUTPUT_VARIABLE Python3_SITEARCH
OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
# Get install variable from Python3 module
# Python3_SITEARCH is available from 3.12 on, workaround if needed:
find_package(Python3 COMPONENTS Interpreter)
endif()

if(USE_DIST_PACKAGES_FOR_PYTHON)
string(REPLACE "site-packages" "dist-packages" IGN_PYTHON_INSTALL_PATH ${Python3_SITEARCH})
else()
# custom cmake command is returning dist-packages
string(REPLACE "dist-packages" "site-packages" IGN_PYTHON_INSTALL_PATH ${Python3_SITEARCH})
endif()
else()
# If not a system installation, respect local paths
set(IGN_PYTHON_INSTALL_PATH ${IGN_LIB_INSTALL_DIR}/python)
endif()

set(IGN_PYTHON_INSTALL_PATH "${IGN_PYTHON_INSTALL_PATH}/ignition")

# Set the build location and install location for a CPython extension
function(configure_build_install_location _library_name)
# Install into test folder in build space for unit tests to import
set_target_properties(${_library_name} PROPERTIES
# Use generator expression to avoid prepending a build type specific directory on Windows
LIBRARY_OUTPUT_DIRECTORY $<1:${CMAKE_CURRENT_BINARY_DIR}/test>
RUNTIME_OUTPUT_DIRECTORY $<1:${CMAKE_CURRENT_BINARY_DIR}/test>)

# Install library for actual use
install(TARGETS ${_library_name}
DESTINATION "${IGN_PYTHON_INSTALL_PATH}/"
)
endfunction()

configure_build_install_location(math)

if (BUILD_TESTING)
# Add the Python tests
set(python_tests
Vector2_TEST
Vector3_TEST
Vector4_TEST
)

foreach (test ${python_tests})
add_test(NAME ${test}.py COMMAND
"${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/src/python_pybind11/test/${test}.py")

set(_env_vars)
list(APPEND _env_vars "PYTHONPATH=${FAKE_INSTALL_PREFIX}/lib/python/")
list(APPEND _env_vars "LD_LIBRARY_PATH=${FAKE_INSTALL_PREFIX}/lib:$ENV{LD_LIBRARY_PATH}")
set_tests_properties(${test}.py PROPERTIES
ENVIRONMENT "${_env_vars}")
endforeach()

endif()
endif()
143 changes: 143 additions & 0 deletions src/python_pybind11/src/Vector2.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright (C) 2021 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#ifndef IGNITION_MATH_PYTHON__VECTOR2D_HH_
#define IGNITION_MATH_PYTHON__VECTOR2D_HH_

#include <string>

#include <pybind11/pybind11.h>
#include <pybind11/operators.h>

#include <ignition/math/Vector2.hh>

namespace py = pybind11;
using namespace pybind11::literals;

namespace ignition
{
namespace math
{
namespace python
{
/// Define a pybind11 wrapper for an ignition::math::Vector2
/**
* \param[in] module a pybind11 module to add the definition to
*/
template<typename T>
void defineMathVector2(py::module &m, const std::string &typestr)
{
using Class = ignition::math::Vector2<T>;
auto toString = [](const Class &si) {
std::stringstream stream;
stream << si;
return stream.str();
};
std::string pyclass_name = typestr;
py::class_<Class>(m,
pyclass_name.c_str(),
py::buffer_protocol(),
py::dynamic_attr())
.def(py::init<>())
.def(py::init<const T&, const T&>())
.def(py::init<const Class>())
.def("sum", &Class::Sum, "Return the sum of the values")
.def("distance", &Class::Distance, "Calc distance to the given point")
.def("length",
&Class::Length,
"Returns the length (magnitude) of the vector")
.def("squared_length",
&Class::SquaredLength,
"Return the square of the length (magnitude) of the vector")
.def("normalize", &Class::Normalize, "Normalize the vector length")
.def("normalized", &Class::Normalized, "Return a normalized vector")
.def("round",
&Class::Round,
"Round to near whole number, return the result.")
.def("rounded", &Class::Rounded, "Get a rounded version of this vector")
.def("set", &Class::Set, "Set the contents of the vector")
.def("dot",
&Class::Dot,
"Return the dot product of this vector and another vector")
.def("abs_dot", &Class::AbsDot,
"Return the absolute dot product of this vector and "
"another vector. This is similar to the Dot function, except the "
"absolute value of each component of the vector is used.")
.def("abs",
&Class::Abs,
"Get the absolute value of the vector")
.def("max",
py::overload_cast<const Class&>(&Class::Max),
"Set this vector's components to the maximum of itself and the "
"passed in vector")
.def("max", py::overload_cast<>(&Class::Max, py::const_),
"Get the maximum value in the vector")
.def("min", py::overload_cast<const Class&>(&Class::Min),
"Set this vector's components to the minimum of itself and the "
"passed in vector")
.def("min", py::overload_cast<>(&Class::Min, py::const_),
"Get the minimum value in the vector")
.def(py::self + py::self)
.def(py::self += py::self)
.def(py::self + T())
.def(py::self += T())
.def(py::self * py::self)
.def(py::self *= py::self)
.def(py::self * T())
.def(py::self *= T())
.def(py::self - py::self)
.def(py::self -= py::self)
.def(py::self - T())
.def(py::self -= T())
.def(py::self / py::self)
.def(py::self /= py::self)
.def(py::self / T())
.def(py::self /= T())
.def(py::self != py::self)
.def(py::self == py::self)
.def(-py::self)
.def("equal", &Class::Equal, "Equal to operator")
.def("is_finite",
&Class::IsFinite,
"See if a point is finite (e.g., not nan)")
.def("correct", &Class::Correct, "Corrects any nan values")
.def("x", py::overload_cast<>(&Class::X), "Get the x value.")
.def("y", py::overload_cast<>(&Class::Y), "Get the y value.")
.def("x", py::overload_cast<const T&>(&Class::X), "Set the x value.")
.def("y", py::overload_cast<const T&>(&Class::Y), "Set the y value.")
.def_readonly_static("ZERO", &Class::Zero, "math::Vector2(0, 0)")
.def_readonly_static("ONE", &Class::One, "math::Vector2(1, 1)")
.def_readonly_static("NAN", &Class::NaN, "math::Vector3(NaN, NaN)")
.def("__copy__", [](const Class &self) {
return Class(self);
})
.def("__deepcopy__", [](const Class &self, py::dict) {
return Class(self);
}, "memo"_a)
.def("__getitem__",
py::overload_cast<const std::size_t>(&Class::operator[], py::const_))
.def("__setitem__",
[](Class* vec, unsigned index, T val) { (*vec)[index] = val; })
.def("__str__", toString)
.def("__repr__", toString);
}

} // namespace python
} // namespace gazebo
} // namespace ignition

#endif // IGNITION_MATH_PYTHON__VECTOR2D_HH_
Loading