From 22671876bde24676ff5f806c38efb37aaf7f2c25 Mon Sep 17 00:00:00 2001 From: "Addisu Z. Taddese" Date: Wed, 14 Jun 2023 23:19:11 -0500 Subject: [PATCH 1/2] Release 7.2.0 (#536) Signed-off-by: Addisu Z. Taddese --- CMakeLists.txt | 2 +- Changelog.md | 40 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0fe4e796..d4d0ce67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR) #============================================================================ # Initialize the project #============================================================================ -project(gz-math7 VERSION 7.1.0) +project(gz-math7 VERSION 7.2.0) #============================================================================ # Find gz-cmake diff --git a/Changelog.md b/Changelog.md index 09923138..97cdfbb6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,21 +1,53 @@ ## Gazebo Math 7.x -### Gazebo Math 7.1.0 +### Gazebo Math 7.2.0 (2023-06-14) + +1. Add tests to increase test coverage + * [Pull request #533](https://github.com/gazebosim/gz-math/pull/533) + +1. Forward ports + * [Pull request #530](https://github.com/gazebosim/gz-math/pull/530) + * [Pull request #526](https://github.com/gazebosim/gz-math/pull/526) + * [Pull request #522](https://github.com/gazebosim/gz-math/pull/522) + * [Pull request #520](https://github.com/gazebosim/gz-math/pull/520) + +1. Disable pybind11 on windows by default + * [Pull request #529](https://github.com/gazebosim/gz-math/pull/529) + +1. Add option to skip pybind11 and SWIG + * [Pull request #480](https://github.com/gazebosim/gz-math/pull/480) + +1. Custom PID error rate + * [Pull request #525](https://github.com/gazebosim/gz-math/pull/525) + +1. Garden bazel support + * [Pull request #523](https://github.com/gazebosim/gz-math/pull/523) + +1. Rename COPYING to LICENSE + * [Pull request #521](https://github.com/gazebosim/gz-math/pull/521) + +1. Infrastructure + * [Pull request #519](https://github.com/gazebosim/gz-math/pull/519) + +1. Fix link of installation tutorial to point to 7.1 version + * [Pull request #518](https://github.com/gazebosim/gz-math/pull/518) + +### Gazebo Math 7.1.0 (2022-11-15) 1. Adds bounds retrieval for TimeVarying grid class. * [Pull request #508](https://github.com/gazebosim/gz-math/pull/508) -### Gazebo Math 7.0.2 +### Gazebo Math 7.0.2 (2022-09-26) 1. Update to disable tests failing on arm64 * [Pull request #512](https://github.com/gazebosim/gz-math/pull/512) -### Gazebo Math 7.0.1 +### Gazebo Math 7.0.1 (2022-09-23) 1. Disable tests failing on arm64 * [Pull request #510](https://github.com/gazebosim/gz-math/pull/510) -### Gazebo Math 7.0.0 +### Gazebo Math 7.0.0 (2022-09-22) 1. Deprecated `Angle::Degree(double)` and `Angle::Radian(double)`. Use `Angle::SetDegree(double)` and `Angle::SetRadian(double)` instead. * [BitBucket pull request 326](https://osrf-migration.github.io/ignition-gh-pages/#!/ignitionrobotics/ign-math/pull-requests/326) From cf5d7f3c1b57d36665c66a01f8eaed50e3174593 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Sat, 1 Jul 2023 02:42:04 +0530 Subject: [PATCH 2/2] Added `std::optional MassMatrix()` functions for Box, Cylinder & Sphere (#538) * Added std::optional MassMatrix function to box, sphere & cylinder Signed-off-by: Jasmeet Singh * Used py::overload_cast with py::const_ for MassMatrix functions in py bindings Signed-off-by: Jasmeet Singh * Included in Cylinder, Sphere & Box headers Signed-off-by: Jasmeet Singh * Added unit tests for std::optional MassMatrix() for box, cylinder & sphere Signed-off-by: Jasmeet Singh * Added python tests for new MassMatrix() function for Box, sphere & Cylinder Signed-off-by: Jasmeet Singh * Included in detail Cylinder, Sphere & Box headers Signed-off-by: Jasmeet Singh --------- Signed-off-by: Jasmeet Singh --- include/gz/math/Box.hh | 9 +++++++++ include/gz/math/Cylinder.hh | 9 +++++++++ include/gz/math/Sphere.hh | 8 ++++++++ include/gz/math/detail/Box.hh | 16 ++++++++++++++++ include/gz/math/detail/Cylinder.hh | 21 +++++++++++++++++++++ include/gz/math/detail/Sphere.hh | 18 ++++++++++++++++++ src/Box_TEST.cc | 6 ++++++ src/Cylinder_TEST.cc | 6 ++++++ src/Sphere_TEST.cc | 6 ++++++ src/python_pybind11/src/Box.hh | 16 +++++++++++----- src/python_pybind11/src/Cylinder.hh | 16 +++++++++++----- src/python_pybind11/src/Sphere.hh | 16 +++++++++++----- src/python_pybind11/test/Box_TEST.py | 5 +++++ src/python_pybind11/test/Cylinder_TEST.py | 5 +++++ src/python_pybind11/test/Sphere_TEST.py | 5 +++++ 15 files changed, 147 insertions(+), 15 deletions(-) diff --git a/include/gz/math/Box.hh b/include/gz/math/Box.hh index 9412ca80..33551c17 100644 --- a/include/gz/math/Box.hh +++ b/include/gz/math/Box.hh @@ -17,6 +17,7 @@ #ifndef GZ_MATH_BOX_HH_ #define GZ_MATH_BOX_HH_ +#include #include #include #include @@ -189,6 +190,14 @@ namespace gz /// could be due to an invalid size (<=0) or density (<=0). public: bool MassMatrix(MassMatrix3 &_massMat) const; + /// \brief Get the mass matrix for this box. This function + /// is only meaningful if the box's size and material + /// have been set. + /// \return The computed mass matrix if parameters are valid + /// (radius > 0), (length > 0), and (density > 0). Otherwise + /// std::nullopt is returned. + public: std::optional< MassMatrix3 > MassMatrix() const; + /// \brief Get intersection between a plane and the box's edges. /// Edges contained on the plane are ignored. /// \param[in] _plane The plane against which we are testing intersection. diff --git a/include/gz/math/Cylinder.hh b/include/gz/math/Cylinder.hh index fe3cae47..1c3a124d 100644 --- a/include/gz/math/Cylinder.hh +++ b/include/gz/math/Cylinder.hh @@ -17,6 +17,7 @@ #ifndef GZ_MATH_CYLINDER_HH_ #define GZ_MATH_CYLINDER_HH_ +#include #include "gz/math/MassMatrix3.hh" #include "gz/math/Material.hh" #include "gz/math/Quaternion.hh" @@ -115,6 +116,14 @@ namespace gz /// (<=0). public: bool MassMatrix(MassMatrix3d &_massMat) const; + /// \brief Get the mass matrix for this cylinder. This function + /// is only meaningful if the cylinder's radius, length, and material + /// have been set. Optionally, set the rotational offset. + /// \return The computed mass matrix if parameters are valid + /// (radius > 0), (length > 0) and (density > 0). Otherwise + /// std::nullopt is returned. + public: std::optional< MassMatrix3 > MassMatrix() const; + /// \brief Check if this cylinder is equal to the provided cylinder. /// Radius, length, and material properties will be checked. public: bool operator==(const Cylinder &_cylinder) const; diff --git a/include/gz/math/Sphere.hh b/include/gz/math/Sphere.hh index 4ab73d68..4c0a7b43 100644 --- a/include/gz/math/Sphere.hh +++ b/include/gz/math/Sphere.hh @@ -17,6 +17,7 @@ #ifndef GZ_MATH_SPHERE_HH_ #define GZ_MATH_SPHERE_HH_ +#include #include "gz/math/MassMatrix3.hh" #include "gz/math/Material.hh" #include "gz/math/Quaternion.hh" @@ -77,6 +78,13 @@ namespace gz /// could be due to an invalid radius (<=0) or density (<=0). public: bool MassMatrix(MassMatrix3d &_massMat) const; + /// \brief Get the mass matrix for this sphere. This function + /// is only meaningful if the sphere's radius and material have been set. + /// \return The computed mass matrix if parameters are valid + /// (radius > 0) and (density > 0). Otherwise + /// std::nullopt is returned. + public: std::optional< MassMatrix3 > MassMatrix() const; + /// \brief Check if this sphere is equal to the provided sphere. /// Radius and material properties will be checked. public: bool operator==(const Sphere &_sphere) const; diff --git a/include/gz/math/detail/Box.hh b/include/gz/math/detail/Box.hh index 83087846..9b595098 100644 --- a/include/gz/math/detail/Box.hh +++ b/include/gz/math/detail/Box.hh @@ -19,6 +19,7 @@ #include "gz/math/Triangle3.hh" +#include #include #include #include @@ -310,6 +311,21 @@ bool Box::MassMatrix(MassMatrix3 &_massMat) const return _massMat.SetFromBox(this->material, this->size); } +///////////////////////////////////////////////// +template +std::optional< MassMatrix3 > Box::MassMatrix() const +{ + gz::math::MassMatrix3 _massMat; + + if(!_massMat.SetFromBox(this->material, this->size)) + { + return std::nullopt; + } + else + { + return std::make_optional(_massMat); + } +} ////////////////////////////////////////////////// template diff --git a/include/gz/math/detail/Cylinder.hh b/include/gz/math/detail/Cylinder.hh index f4db1b33..aaa6d69c 100644 --- a/include/gz/math/detail/Cylinder.hh +++ b/include/gz/math/detail/Cylinder.hh @@ -16,6 +16,9 @@ */ #ifndef GZ_MATH_DETAIL_CYLINDER_HH_ #define GZ_MATH_DETAIL_CYLINDER_HH_ + +#include + namespace gz { namespace math @@ -116,6 +119,24 @@ bool Cylinder::MassMatrix(MassMatrix3d &_massMat) const this->radius, this->rotOffset); } +////////////////////////////////////////////////// +template +std::optional < MassMatrix3 > Cylinder::MassMatrix() const +{ + gz::math::MassMatrix3 _massMat; + + if(!_massMat.SetFromCylinderZ( + this->material, this->length, + this->radius, this->rotOffset)) + { + return std::nullopt; + } + else + { + return std::make_optional(_massMat); + } +} + ////////////////////////////////////////////////// template T Cylinder::Volume() const diff --git a/include/gz/math/detail/Sphere.hh b/include/gz/math/detail/Sphere.hh index 597c7663..865c9659 100644 --- a/include/gz/math/detail/Sphere.hh +++ b/include/gz/math/detail/Sphere.hh @@ -17,6 +17,7 @@ #ifndef GZ_MATH_DETAIL_SPHERE_HH_ #define GZ_MATH_DETAIL_SPHERE_HH_ +#include #include "gz/math/Sphere.hh" namespace gz @@ -88,6 +89,23 @@ bool Sphere::MassMatrix(MassMatrix3d &_massMat) const return _massMat.SetFromSphere(this->material, this->radius); } +////////////////////////////////////////////////// +template +std::optional < MassMatrix3 > Sphere::MassMatrix() const +{ + gz::math::MassMatrix3 _massMat; + + if(!_massMat.SetFromSphere(this->material, this->radius)) + { + return std::nullopt; + } + else + { + return std::make_optional(_massMat); + } +} + + ////////////////////////////////////////////////// template T Sphere::Volume() const diff --git a/src/Box_TEST.cc b/src/Box_TEST.cc index f68f9e79..f8cd158c 100644 --- a/src/Box_TEST.cc +++ b/src/Box_TEST.cc @@ -498,4 +498,10 @@ TEST(BoxTest, Mass) box.MassMatrix(massMat); EXPECT_EQ(expectedMassMat, massMat); EXPECT_DOUBLE_EQ(expectedMassMat.Mass(), massMat.Mass()); + + auto massMatOpt = box.MassMatrix(); + ASSERT_NE(std::nullopt, massMatOpt); + EXPECT_EQ(expectedMassMat, *massMatOpt); + EXPECT_EQ(expectedMassMat.DiagonalMoments(), massMatOpt->DiagonalMoments()); + EXPECT_DOUBLE_EQ(expectedMassMat.Mass(), massMatOpt->Mass()); } diff --git a/src/Cylinder_TEST.cc b/src/Cylinder_TEST.cc index 5730a7fe..3811fd0f 100644 --- a/src/Cylinder_TEST.cc +++ b/src/Cylinder_TEST.cc @@ -136,4 +136,10 @@ TEST(CylinderTest, Mass) cylinder.MassMatrix(massMat); EXPECT_EQ(expectedMassMat, massMat); EXPECT_DOUBLE_EQ(expectedMassMat.Mass(), massMat.Mass()); + + auto massMatOpt = cylinder.MassMatrix(); + ASSERT_NE(std::nullopt, massMatOpt); + EXPECT_EQ(expectedMassMat, *massMatOpt); + EXPECT_EQ(expectedMassMat.DiagonalMoments(), massMatOpt->DiagonalMoments()); + EXPECT_DOUBLE_EQ(expectedMassMat.Mass(), massMatOpt->Mass()); } diff --git a/src/Sphere_TEST.cc b/src/Sphere_TEST.cc index 5996fbe1..80d612f1 100644 --- a/src/Sphere_TEST.cc +++ b/src/Sphere_TEST.cc @@ -129,6 +129,12 @@ TEST(SphereTest, Mass) sphere.MassMatrix(massMat); EXPECT_EQ(expectedMassMat, massMat); EXPECT_DOUBLE_EQ(expectedMassMat.Mass(), massMat.Mass()); + + auto massMatOpt = sphere.MassMatrix(); + ASSERT_NE(std::nullopt, massMatOpt); + EXPECT_EQ(expectedMassMat, *massMatOpt); + EXPECT_EQ(expectedMassMat.DiagonalMoments(), massMatOpt->DiagonalMoments()); + EXPECT_DOUBLE_EQ(expectedMassMat.Mass(), massMatOpt->Mass()); } ////////////////////////////////////////////////// diff --git a/src/python_pybind11/src/Box.hh b/src/python_pybind11/src/Box.hh index c78cab4f..109b19a2 100644 --- a/src/python_pybind11/src/Box.hh +++ b/src/python_pybind11/src/Box.hh @@ -105,11 +105,17 @@ void defineMathBox(py::module &m, const std::string &typestr) .def("set_density_from_mass", &Class::SetDensityFromMass, "Set the density of this box based on a mass value.") - .def("mass_matrix", - &Class::MassMatrix, - "Get the mass matrix for this box. This function " - "is only meaningful if the box's size and material " - "have been set.") + .def("mass_matrix", + py::overload_cast<>(&Class::MassMatrix, py::const_), + "Get the mass matrix for this box. This function " + "is only meaningful if the box's size and material " + "have been set.") + .def("mass_matrix", + py::overload_cast&> + (&Class::MassMatrix, py::const_), + "Get the mass matrix for this box. This function " + "is only meaningful if the box's size and material " + "have been set.") .def("intersections", [](const Class &self, const Plane &_plane) { diff --git a/src/python_pybind11/src/Cylinder.hh b/src/python_pybind11/src/Cylinder.hh index 8b788e43..49692044 100644 --- a/src/python_pybind11/src/Cylinder.hh +++ b/src/python_pybind11/src/Cylinder.hh @@ -97,11 +97,17 @@ void defineMathCylinder(py::module &m, const std::string &typestr) .def("set_density_from_mass", &Class::SetDensityFromMass, "Set the density of this box based on a mass value.") - .def("mass_matrix", - &Class::MassMatrix, - "Get the mass matrix for this box. This function " - "is only meaningful if the box's size and material " - "have been set.") + .def("mass_matrix", + py::overload_cast<>(&Class::MassMatrix, py::const_), + "Get the mass matrix for this box. This function " + "is only meaningful if the box's size and material " + "have been set.") + .def("mass_matrix", + py::overload_cast&> + (&Class::MassMatrix, py::const_), + "Get the mass matrix for this box. This function " + "is only meaningful if the box's size and material " + "have been set.") .def("__copy__", [](const Class &self) { return Class(self); }) diff --git a/src/python_pybind11/src/Sphere.hh b/src/python_pybind11/src/Sphere.hh index 2831ce35..f11b1a95 100644 --- a/src/python_pybind11/src/Sphere.hh +++ b/src/python_pybind11/src/Sphere.hh @@ -83,11 +83,17 @@ void defineMathSphere(py::module &m, const std::string &typestr) .def("set_density_from_mass", &Class::SetDensityFromMass, "Set the density of this box based on a mass value.") - .def("mass_matrix", - &Class::MassMatrix, - "Get the mass matrix for this box. This function " - "is only meaningful if the box's size and material " - "have been set.") + .def("mass_matrix", + py::overload_cast<>(&Class::MassMatrix, py::const_), + "Get the mass matrix for this box. This function " + "is only meaningful if the box's size and material " + "have been set.") + .def("mass_matrix", + py::overload_cast&> + (&Class::MassMatrix, py::const_), + "Get the mass matrix for this box. This function " + "is only meaningful if the box's size and material " + "have been set.") .def("__copy__", [](const Class &self) { return Class(self); }) diff --git a/src/python_pybind11/test/Box_TEST.py b/src/python_pybind11/test/Box_TEST.py index 058507fb..9e1a2f81 100644 --- a/src/python_pybind11/test/Box_TEST.py +++ b/src/python_pybind11/test/Box_TEST.py @@ -401,6 +401,11 @@ def test_mass(self): self.assertEqual(expectedMassMat, massMat) self.assertEqual(expectedMassMat.mass(), massMat.mass()) + massMat2 = box.mass_matrix() + self.assertEqual(expectedMassMat, massMat2) + self.assertEqual(expectedMassMat.diagonal_moments(), massMat2.diagonal_moments()) + self.assertEqual(expectedMassMat.mass(), massMat2.mass()) + if __name__ == '__main__': unittest.main() diff --git a/src/python_pybind11/test/Cylinder_TEST.py b/src/python_pybind11/test/Cylinder_TEST.py index de4f7780..8d64635e 100644 --- a/src/python_pybind11/test/Cylinder_TEST.py +++ b/src/python_pybind11/test/Cylinder_TEST.py @@ -114,6 +114,11 @@ def test_mass(self): self.assertEqual(expectedMassMat, massMat) self.assertEqual(expectedMassMat.mass(), massMat.mass()) + massMat2 = cylinder.mass_matrix() + self.assertEqual(expectedMassMat, massMat2) + self.assertEqual(expectedMassMat.diagonal_moments(), massMat2.diagonal_moments()) + self.assertEqual(expectedMassMat.mass(), massMat2.mass()) + if __name__ == '__main__': unittest.main() diff --git a/src/python_pybind11/test/Sphere_TEST.py b/src/python_pybind11/test/Sphere_TEST.py index afd75ab4..6e213bc9 100644 --- a/src/python_pybind11/test/Sphere_TEST.py +++ b/src/python_pybind11/test/Sphere_TEST.py @@ -108,6 +108,11 @@ def test_mass(self): self.assertEqual(expectedMassMat, massMat) self.assertEqual(expectedMassMat.mass(), massMat.mass()) + massMat2 = sphere.mass_matrix() + self.assertEqual(expectedMassMat, massMat2) + self.assertEqual(expectedMassMat.diagonal_moments(), massMat2.diagonal_moments()) + self.assertEqual(expectedMassMat.mass(), massMat2.mass()) + def test_volume_below(self): r = 2