From 1d4cf25312463f69f355084a1919fb3f58d1a8de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Hern=C3=A1ndez=20Cordero?= Date: Fri, 8 Apr 2022 19:07:45 +0200 Subject: [PATCH 1/2] Added Mesh Python interface (#942) Signed-off-by: ahcorde --- python/CMakeLists.txt | 2 + python/src/sdf/_ignition_sdformat_pybind11.cc | 2 + python/src/sdf/pyMesh.cc | 73 +++++++++++ python/src/sdf/pyMesh.hh | 41 ++++++ python/test/pyMesh_TEST.py | 117 ++++++++++++++++++ 5 files changed, 235 insertions(+) create mode 100644 python/src/sdf/pyMesh.cc create mode 100644 python/src/sdf/pyMesh.hh create mode 100644 python/test/pyMesh_TEST.py diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 1331d950f..57e28269e 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -40,6 +40,7 @@ pybind11_add_module(sdformat SHARED src/sdf/_ignition_sdformat_pybind11.cc src/sdf/pyBox.cc src/sdf/pyError.cc + src/sdf/pyMesh.cc src/sdf/pyParserConfig.cc src/sdf/pySphere.cc ) @@ -63,6 +64,7 @@ if (BUILD_TESTING) set(python_tests pyBox_TEST pyError_TEST + pyMesh_TEST pyParserConfig_TEST pySphere_TEST ) diff --git a/python/src/sdf/_ignition_sdformat_pybind11.cc b/python/src/sdf/_ignition_sdformat_pybind11.cc index 391e167b5..98fb1265f 100644 --- a/python/src/sdf/_ignition_sdformat_pybind11.cc +++ b/python/src/sdf/_ignition_sdformat_pybind11.cc @@ -18,6 +18,7 @@ #include "pyBox.hh" #include "pyError.hh" +#include "pyMesh.hh" #include "pyParserConfig.hh" #include "pySphere.hh" @@ -26,6 +27,7 @@ PYBIND11_MODULE(sdformat, m) { sdf::python::defineBox(m); sdf::python::defineError(m); + sdf::python::defineMesh(m); sdf::python::defineParserConfig(m); sdf::python::defineSphere(m); } diff --git a/python/src/sdf/pyMesh.cc b/python/src/sdf/pyMesh.cc new file mode 100644 index 000000000..85705f874 --- /dev/null +++ b/python/src/sdf/pyMesh.cc @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 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. + */ + +#include "pyMesh.hh" + +#include + +#include "sdf/ParserConfig.hh" +#include "sdf/Mesh.hh" + +using namespace pybind11::literals; + +namespace sdf +{ +// Inline bracket to help doxygen filtering. +inline namespace SDF_VERSION_NAMESPACE { +namespace python +{ +///////////////////////////////////////////////// +void defineMesh(pybind11::object module) +{ + pybind11::class_(module, "Mesh") + .def(pybind11::init<>()) + .def(pybind11::init()) + .def("uri", &sdf::Mesh::Uri, + "Get the mesh's URI.") + .def("set_uri", &sdf::Mesh::SetUri, + "Set the mesh's URI.") + .def("file_path", &sdf::Mesh::FilePath, + "The path to the file where this element was loaded from.") + .def("set_file_path", &sdf::Mesh::SetFilePath, + "Set the path to the file where this element was loaded from.") + .def("scale", &sdf::Mesh::Scale, + "Get the mesh's scale factor.") + .def("set_scale", &sdf::Mesh::SetScale, + "Set the mesh's scale factor.") + .def("submesh", &sdf::Mesh::Submesh, + "A submesh, contained with the mesh at the specified URI, may " + "optionally be specified. If specified, this submesh should be used " + "instead of the entire mesh.") + .def("set_submesh", &sdf::Mesh::SetSubmesh, + "Set the mesh's submesh. See Submesh() for more information.") + .def("center_submesh", &sdf::Mesh::CenterSubmesh, + "Get whether the submesh should be centered at 0,0,0. This will " + "effectively remove any transformations on the submesh before the " + "poses from parent links and models are applied. The return value is " + "only applicable if a SubMesh has been specified.") + .def("set_center_submesh", &sdf::Mesh::SetCenterSubmesh, + "Set whether the submesh should be centered. See CenterSubmesh() " + "for more information.") + .def("__copy__", [](const sdf::Mesh &self) { + return sdf::Mesh(self); + }) + .def("__deepcopy__", [](const sdf::Mesh &self, pybind11::dict) { + return sdf::Mesh(self); + }, "memo"_a); +} +} // namespace python +} // namespace SDF_VERSION_NAMESPACE +} // namespace sdf diff --git a/python/src/sdf/pyMesh.hh b/python/src/sdf/pyMesh.hh new file mode 100644 index 000000000..60ea35180 --- /dev/null +++ b/python/src/sdf/pyMesh.hh @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 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 SDFORMAT_PYTHON_MESH_HH_ +#define SDFORMAT_PYTHON_MESH_HH_ + +#include + +#include "sdf/Mesh.hh" + +#include "sdf/config.hh" + +namespace sdf +{ +// Inline bracket to help doxygen filtering. +inline namespace SDF_VERSION_NAMESPACE { +namespace python +{ +/// Define a pybind11 wrapper for an sdf::Mesh +/** + * \param[in] module a pybind11 module to add the definition to + */ +void defineMesh(pybind11::object module); +} // namespace python +} // namespace SDF_VERSION_NAMESPACE +} // namespace sdf + +#endif // SDFORMAT_PYTHON_MESH_HH_ diff --git a/python/test/pyMesh_TEST.py b/python/test/pyMesh_TEST.py new file mode 100644 index 000000000..2c2383c73 --- /dev/null +++ b/python/test/pyMesh_TEST.py @@ -0,0 +1,117 @@ +# Copyright (C) 2022 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. + +import copy +from sdformat import Mesh +from ignition.math import Vector3d +import unittest + + +class MeshTEST(unittest.TestCase): + + def test_default_construction(self): + mesh = Mesh() + + self.assertEqual("", mesh.file_path()) + self.assertEqual("", mesh.uri()) + self.assertEqual("", mesh.submesh()) + self.assertTrue(Vector3d(1, 1, 1) == mesh.scale()) + self.assertFalse(mesh.center_submesh()) + + + def test_assigment(self): + mesh = Mesh() + mesh.set_uri("banana") + mesh.set_submesh("watermelon") + mesh.set_center_submesh(True) + mesh.set_scale(Vector3d(0.5, 0.6, 0.7)) + mesh.set_file_path("/pear") + + mesh2 = mesh + self.assertEqual("banana", mesh2.uri()) + self.assertEqual("watermelon", mesh2.submesh()) + self.assertEqual(Vector3d(0.5, 0.6, 0.7), mesh2.scale()) + self.assertTrue(mesh2.center_submesh()) + self.assertEqual("/pear", mesh2.file_path()) + + mesh.set_file_path("/apple") + self.assertEqual("/apple", mesh2.file_path()) + + mesh.set_scale(Vector3d(0.3, 0.2, 0.4)) + self.assertEqual(Vector3d(0.3, 0.2, 0.4), mesh2.scale()) + + mesh.set_center_submesh(False) + self.assertFalse(mesh2.center_submesh()) + + mesh.set_submesh("melon") + self.assertEqual("melon", mesh2.submesh()) + + mesh.set_uri("pineapple") + self.assertEqual("pineapple", mesh2.uri()) + + + def test_deepcopy_construction(self): + mesh = Mesh() + mesh.set_uri("banana") + mesh.set_submesh("watermelon") + mesh.set_center_submesh(True) + mesh.set_scale(Vector3d(0.5, 0.6, 0.7)) + mesh.set_file_path("/pear") + + mesh2 = copy.deepcopy(mesh) + self.assertEqual("banana", mesh2.uri()) + self.assertEqual("watermelon", mesh2.submesh()) + self.assertEqual(Vector3d(0.5, 0.6, 0.7), mesh2.scale()) + self.assertTrue(mesh2.center_submesh()) + self.assertEqual("/pear", mesh2.file_path()) + + mesh.set_file_path("/apple") + mesh.set_scale(Vector3d(0.3, 0.2, 0.4)) + mesh.set_center_submesh(False) + mesh.set_submesh("melon") + mesh.set_uri("pineapple") + + self.assertEqual("banana", mesh2.uri()) + self.assertEqual("watermelon", mesh2.submesh()) + self.assertEqual(Vector3d(0.5, 0.6, 0.7), mesh2.scale()) + self.assertTrue(mesh2.center_submesh()) + self.assertEqual("/pear", mesh2.file_path()) + + + def test_set(self): + mesh = Mesh() + + self.assertEqual("", mesh.uri()) + mesh.set_uri("http://myuri.com") + self.assertEqual("http://myuri.com", mesh.uri()) + + self.assertEqual("", mesh.submesh()) + mesh.set_submesh("my_submesh") + self.assertEqual("my_submesh", mesh.submesh()) + + self.assertTrue(Vector3d(1, 1, 1) == mesh.scale()) + mesh.set_scale(Vector3d(0.2, 1.4, 7.8)) + self.assertTrue(Vector3d(0.2, 1.4, 7.8) == mesh.scale()) + + self.assertFalse(mesh.center_submesh()) + mesh.set_center_submesh(True) + self.assertTrue(mesh.center_submesh()) + + self.assertEqual("", mesh.file_path()) + mesh.set_file_path("/mypath") + self.assertEqual("/mypath", mesh.file_path()) + + +if __name__ == '__main__': + unittest.main() From 66c16093d9de14d0e795975e492129f3debe3973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Hern=C3=A1ndez=20Cordero?= Date: Sat, 9 Apr 2022 01:46:44 +0200 Subject: [PATCH 2/2] Fixes MacOS Python tests (#957) Set PYTHONPATH in macOS workflow Signed-off-by: ahcorde --- .github/workflows/macos.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 7df08f33a..a8dac0422 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -39,7 +39,9 @@ jobs: - run: mkdir build - name: cmake working-directory: build - run: cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/Cellar/${PACKAGE}/HEAD + run: | + export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python + cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/Cellar/${PACKAGE}/HEAD - run: make working-directory: build - run: make test