Skip to content

Commit c10e31d

Browse files
authored
Merge branch 'main' into main_implptr
2 parents 928086c + 3cc9adb commit c10e31d

16 files changed

Lines changed: 637 additions & 35 deletions

File tree

.github/ci/packages.apt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ python3-distutils
55
python3-pybind11
66
ruby-dev
77
swig
8+
python3-pybind11

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ find_package(ignition-cmake2 2.8.0 REQUIRED)
1515
# Configure the project
1616
#============================================================================
1717
set (c++standard 17)
18+
set (CMAKE_CXX_STANDARD 17)
1819
ign_configure_project(VERSION_SUFFIX pre1)
1920

2021
#============================================================================

include/ignition/math/Vector2.hh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ namespace ignition
126126
/// \return the result
127127
public: Vector2 Round()
128128
{
129-
this->data[0] = nearbyint(this->data[0]);
130-
this->data[1] = nearbyint(this->data[1]);
129+
this->data[0] = static_cast<T>(std::nearbyint(this->data[0]));
130+
this->data[1] = static_cast<T>(std::nearbyint(this->data[1]));
131131
return *this;
132132
}
133133

include/ignition/math/Vector3.hh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ namespace ignition
158158
/// \return the result
159159
public: Vector3 Round()
160160
{
161-
this->data[0] = nearbyint(this->data[0]);
162-
this->data[1] = nearbyint(this->data[1]);
163-
this->data[2] = nearbyint(this->data[2]);
161+
this->data[0] = static_cast<T>(std::nearbyint(this->data[0]));
162+
this->data[1] = static_cast<T>(std::nearbyint(this->data[1]));
163+
this->data[2] = static_cast<T>(std::nearbyint(this->data[2]));
164164
return *this;
165165
}
166166

include/ignition/math/Vector4.hh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,10 @@ namespace ignition
115115
/// \brief Round to near whole number.
116116
public: void Round()
117117
{
118-
this->data[0] = nearbyint(this->data[0]);
119-
this->data[1] = nearbyint(this->data[1]);
120-
this->data[2] = nearbyint(this->data[2]);
121-
this->data[3] = nearbyint(this->data[3]);
118+
this->data[0] = static_cast<T>(std::nearbyint(this->data[0]));
119+
this->data[1] = static_cast<T>(std::nearbyint(this->data[1]));
120+
this->data[2] = static_cast<T>(std::nearbyint(this->data[2]));
121+
this->data[3] = static_cast<T>(std::nearbyint(this->data[3]));
122122
}
123123

124124
/// \brief Get a rounded version of this vector

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ add_subdirectory(graph)
1919

2020
# Bindings subdirectories
2121
add_subdirectory(python)
22+
add_subdirectory(python_pybind11)
2223
add_subdirectory(ruby)

src/python/CMakeLists.txt

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ if (PYTHONLIBS_FOUND)
2626
set(SWIG_PY_LIB pymath)
2727
set(SWIG_PY_LIB_OUTPUT math)
2828

29-
set(CMAKE_SWIG_OUTDIR "${CMAKE_BINARY_DIR}/lib/python")
29+
set(CMAKE_SWIG_OUTDIR "${CMAKE_BINARY_DIR}/lib/python/swig")
3030
if(CMAKE_VERSION VERSION_GREATER 3.8.0)
3131
SWIG_ADD_LIBRARY(${SWIG_PY_LIB} LANGUAGE python SOURCES python.i)
3232
else()
@@ -77,12 +77,12 @@ if (PYTHONLIBS_FOUND)
7777
endif()
7878
else()
7979
# If not a system installation, respect local paths
80-
set(IGN_PYTHON_INSTALL_PATH ${IGN_LIB_INSTALL_DIR}/python)
80+
set(IGN_PYTHON_INSTALL_PATH ${IGN_LIB_INSTALL_DIR}/python/swig)
8181
endif()
8282

8383
set(IGN_PYTHON_INSTALL_PATH "${IGN_PYTHON_INSTALL_PATH}/ignition")
8484
install(TARGETS ${SWIG_PY_LIB} DESTINATION ${IGN_PYTHON_INSTALL_PATH})
85-
install(FILES ${CMAKE_BINARY_DIR}/lib/python/math.py DESTINATION ${IGN_PYTHON_INSTALL_PATH})
85+
install(FILES ${CMAKE_BINARY_DIR}/lib/python/swig/math.py DESTINATION ${IGN_PYTHON_INSTALL_PATH})
8686

8787
if (BUILD_TESTING)
8888
# Add the Python tests
@@ -113,18 +113,15 @@ if (PYTHONLIBS_FOUND)
113113
Temperature_TEST
114114
Triangle_TEST
115115
Triangle3_TEST
116-
Vector2_TEST
117-
Vector3_TEST
118116
Vector3Stats_TEST
119-
Vector4_TEST
120117
)
121118

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

126123
set(_env_vars)
127-
list(APPEND _env_vars "PYTHONPATH=${FAKE_INSTALL_PREFIX}/lib/python/")
124+
list(APPEND _env_vars "PYTHONPATH=${FAKE_INSTALL_PREFIX}/lib/python/swig")
128125
list(APPEND _env_vars "LD_LIBRARY_PATH=${FAKE_INSTALL_PREFIX}/lib:$ENV{LD_LIBRARY_PATH}")
129126
set_tests_properties(${test}.py PROPERTIES
130127
ENVIRONMENT "${_env_vars}")

src/python_pybind11/CMakeLists.txt

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
if(WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Debug")
2+
# pybind11 logic for setting up a debug build when both a debug and release
3+
# python interpreter are present in the system seems to be pretty much broken.
4+
# This works around the issue.
5+
set(PYTHON_LIBRARIES "${PYTHON_DEBUG_LIBRARIES}")
6+
endif()
7+
8+
set(PYBIND11_PYTHON_VERSION 3)
9+
10+
find_package(pybind11 2.2 QUIET)
11+
12+
if (${pybind11_FOUND})
13+
message(STATUS "Building pybind11 interfaces")
14+
# Split from main extension and converted to pybind11
15+
pybind11_add_module(math SHARED
16+
src/_ignition_math_pybind11.cc
17+
)
18+
19+
if(USE_SYSTEM_PATHS_FOR_PYTHON_INSTALLATION)
20+
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
21+
execute_process(
22+
COMMAND "${PYTHON_EXECUTABLE}" -c "if True:
23+
from distutils import sysconfig as sc
24+
print(sc.get_python_lib(plat_specific=True))"
25+
OUTPUT_VARIABLE Python3_SITEARCH
26+
OUTPUT_STRIP_TRAILING_WHITESPACE)
27+
else()
28+
# Get install variable from Python3 module
29+
# Python3_SITEARCH is available from 3.12 on, workaround if needed:
30+
find_package(Python3 COMPONENTS Interpreter)
31+
endif()
32+
33+
if(USE_DIST_PACKAGES_FOR_PYTHON)
34+
string(REPLACE "site-packages" "dist-packages" IGN_PYTHON_INSTALL_PATH ${Python3_SITEARCH})
35+
else()
36+
# custom cmake command is returning dist-packages
37+
string(REPLACE "dist-packages" "site-packages" IGN_PYTHON_INSTALL_PATH ${Python3_SITEARCH})
38+
endif()
39+
else()
40+
# If not a system installation, respect local paths
41+
set(IGN_PYTHON_INSTALL_PATH ${IGN_LIB_INSTALL_DIR}/python)
42+
endif()
43+
44+
set(IGN_PYTHON_INSTALL_PATH "${IGN_PYTHON_INSTALL_PATH}/ignition")
45+
46+
# Set the build location and install location for a CPython extension
47+
function(configure_build_install_location _library_name)
48+
# Install into test folder in build space for unit tests to import
49+
set_target_properties(${_library_name} PROPERTIES
50+
# Use generator expression to avoid prepending a build type specific directory on Windows
51+
LIBRARY_OUTPUT_DIRECTORY $<1:${CMAKE_CURRENT_BINARY_DIR}/test>
52+
RUNTIME_OUTPUT_DIRECTORY $<1:${CMAKE_CURRENT_BINARY_DIR}/test>)
53+
54+
# Install library for actual use
55+
install(TARGETS ${_library_name}
56+
DESTINATION "${IGN_PYTHON_INSTALL_PATH}/"
57+
)
58+
endfunction()
59+
60+
configure_build_install_location(math)
61+
62+
if (BUILD_TESTING)
63+
# Add the Python tests
64+
set(python_tests
65+
Vector2_TEST
66+
Vector3_TEST
67+
Vector4_TEST
68+
)
69+
70+
foreach (test ${python_tests})
71+
add_test(NAME ${test}.py COMMAND
72+
"${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/src/python_pybind11/test/${test}.py")
73+
74+
set(_env_vars)
75+
list(APPEND _env_vars "PYTHONPATH=${FAKE_INSTALL_PREFIX}/lib/python/")
76+
list(APPEND _env_vars "LD_LIBRARY_PATH=${FAKE_INSTALL_PREFIX}/lib:$ENV{LD_LIBRARY_PATH}")
77+
set_tests_properties(${test}.py PROPERTIES
78+
ENVIRONMENT "${_env_vars}")
79+
endforeach()
80+
81+
endif()
82+
endif()

src/python_pybind11/src/Vector2.hh

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Copyright (C) 2021 Open Source Robotics Foundation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
#ifndef IGNITION_MATH_PYTHON__VECTOR2D_HH_
19+
#define IGNITION_MATH_PYTHON__VECTOR2D_HH_
20+
21+
#include <sstream>
22+
#include <string>
23+
24+
#include <pybind11/pybind11.h>
25+
#include <pybind11/operators.h>
26+
27+
#include <ignition/math/Vector2.hh>
28+
29+
namespace py = pybind11;
30+
using namespace pybind11::literals;
31+
32+
namespace ignition
33+
{
34+
namespace math
35+
{
36+
namespace python
37+
{
38+
/// Define a pybind11 wrapper for an ignition::math::Vector2
39+
/**
40+
* \param[in] module a pybind11 module to add the definition to
41+
*/
42+
template<typename T>
43+
void defineMathVector2(py::module &m, const std::string &typestr)
44+
{
45+
using Class = ignition::math::Vector2<T>;
46+
auto toString = [](const Class &si) {
47+
std::stringstream stream;
48+
stream << si;
49+
return stream.str();
50+
};
51+
std::string pyclass_name = typestr;
52+
py::class_<Class>(m,
53+
pyclass_name.c_str(),
54+
py::buffer_protocol(),
55+
py::dynamic_attr())
56+
.def(py::init<>())
57+
.def(py::init<const T&, const T&>())
58+
.def(py::init<const Class>())
59+
.def("sum", &Class::Sum, "Return the sum of the values")
60+
.def("distance", &Class::Distance, "Calc distance to the given point")
61+
.def("length",
62+
&Class::Length,
63+
"Returns the length (magnitude) of the vector")
64+
.def("squared_length",
65+
&Class::SquaredLength,
66+
"Return the square of the length (magnitude) of the vector")
67+
.def("normalize", &Class::Normalize, "Normalize the vector length")
68+
.def("normalized", &Class::Normalized, "Return a normalized vector")
69+
.def("round",
70+
&Class::Round,
71+
"Round to near whole number, return the result.")
72+
.def("rounded", &Class::Rounded, "Get a rounded version of this vector")
73+
.def("set", &Class::Set, "Set the contents of the vector")
74+
.def("dot",
75+
&Class::Dot,
76+
"Return the dot product of this vector and another vector")
77+
.def("abs_dot", &Class::AbsDot,
78+
"Return the absolute dot product of this vector and "
79+
"another vector. This is similar to the Dot function, except the "
80+
"absolute value of each component of the vector is used.")
81+
.def("abs",
82+
&Class::Abs,
83+
"Get the absolute value of the vector")
84+
.def("max",
85+
py::overload_cast<const Class&>(&Class::Max),
86+
"Set this vector's components to the maximum of itself and the "
87+
"passed in vector")
88+
.def("max", py::overload_cast<>(&Class::Max, py::const_),
89+
"Get the maximum value in the vector")
90+
.def("min", py::overload_cast<const Class&>(&Class::Min),
91+
"Set this vector's components to the minimum of itself and the "
92+
"passed in vector")
93+
.def("min", py::overload_cast<>(&Class::Min, py::const_),
94+
"Get the minimum value in the vector")
95+
.def(py::self + py::self)
96+
.def(py::self += py::self)
97+
.def(py::self + T())
98+
.def(py::self += T())
99+
.def(py::self * py::self)
100+
.def(py::self *= py::self)
101+
.def(py::self * T())
102+
.def(py::self *= T())
103+
.def(py::self - py::self)
104+
.def(py::self -= py::self)
105+
.def(py::self - T())
106+
.def(py::self -= T())
107+
.def(py::self / py::self)
108+
.def(py::self /= py::self)
109+
.def(py::self / T())
110+
.def(py::self /= T())
111+
.def(py::self != py::self)
112+
.def(py::self == py::self)
113+
.def(-py::self)
114+
.def("equal", &Class::Equal, "Equal to operator")
115+
.def("is_finite",
116+
&Class::IsFinite,
117+
"See if a point is finite (e.g., not nan)")
118+
.def("correct", &Class::Correct, "Corrects any nan values")
119+
.def("x", py::overload_cast<>(&Class::X), "Get the x value.")
120+
.def("y", py::overload_cast<>(&Class::Y), "Get the y value.")
121+
.def("x", py::overload_cast<const T&>(&Class::X), "Set the x value.")
122+
.def("y", py::overload_cast<const T&>(&Class::Y), "Set the y value.")
123+
.def_readonly_static("ZERO", &Class::Zero, "math::Vector2(0, 0)")
124+
.def_readonly_static("ONE", &Class::One, "math::Vector2(1, 1)")
125+
.def_readonly_static("NAN", &Class::NaN, "math::Vector3(NaN, NaN)")
126+
.def("__copy__", [](const Class &self) {
127+
return Class(self);
128+
})
129+
.def("__deepcopy__", [](const Class &self, py::dict) {
130+
return Class(self);
131+
}, "memo"_a)
132+
.def("__getitem__",
133+
py::overload_cast<const std::size_t>(&Class::operator[], py::const_))
134+
.def("__setitem__",
135+
[](Class* vec, unsigned index, T val) { (*vec)[index] = val; })
136+
.def("__str__", toString)
137+
.def("__repr__", toString);
138+
}
139+
140+
} // namespace python
141+
} // namespace gazebo
142+
} // namespace ignition
143+
144+
#endif // IGNITION_MATH_PYTHON__VECTOR2D_HH_

0 commit comments

Comments
 (0)