Skip to content

Commit

Permalink
Add cone shape to SDFormat spec (gazebosim#1418)
Browse files Browse the repository at this point in the history
This adds the cone shape to the SDFormat spec for
geometry and the particle emitter in version 1.11 and 1.12.
The cone's central axis is aligned with the Z axis with its
origin at the midpoint of that central axis, similar to a
cylinder.

Signed-off-by: Benjamin Perseghetti <[email protected]>
Signed-off-by: Steve Peters <[email protected]>
Co-authored-by: Addisu Z. Taddese <[email protected]>
Co-authored-by: Alejandro Hernández Cordero <[email protected]>
Co-authored-by: Steve Peters <[email protected]>
Co-authored-by: Steve Peters <[email protected]>
  • Loading branch information
5 people authored May 24, 2024
1 parent 213814c commit e6adcd3
Show file tree
Hide file tree
Showing 35 changed files with 1,134 additions and 8 deletions.
108 changes: 108 additions & 0 deletions include/sdf/Cone.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright 2024 CogniPilot Foundation
* Copyright 2024 Open Source Robotics Foundation
* Copyright 2024 Rudis Laboratories
*
* 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 SDF_CONE_HH_
#define SDF_CONE_HH_

#include <optional>

#include <gz/math/Cone.hh>
#include <gz/math/Inertial.hh>
#include <gz/utils/ImplPtr.hh>
#include <sdf/Error.hh>
#include <sdf/Element.hh>
#include <sdf/sdf_config.h>

namespace sdf
{
// Inline bracket to help doxygen filtering.
inline namespace SDF_VERSION_NAMESPACE {
/// \brief Cone represents a cone shape, and is usually accessed
/// through a Geometry.
class SDFORMAT_VISIBLE Cone
{
/// \brief Constructor
public: Cone();

/// \brief Load the cone geometry based on a element pointer.
/// This is *not* the usual entry point. Typical usage of the SDF DOM is
/// through the Root object.
/// \param[in] _sdf The SDF Element pointer
/// \return Errors, which is a vector of Error objects. Each Error includes
/// an error code and message. An empty vector indicates no error.
public: Errors Load(ElementPtr _sdf);

/// \brief Get the cone's radius in meters.
/// \return The radius of the cone in meters.
public: double Radius() const;

/// \brief Set the cone's radius in meters.
/// \param[in] _radius The radius of the cone in meters.
public: void SetRadius(double _radius);

/// \brief Get the cone's length in meters.
/// \return The length of the cone in meters.
public: double Length() const;

/// \brief Set the cone's length in meters.
/// \param[in] _length The length of the cone in meters.
public: void SetLength(double _length);

/// \brief Get a pointer to the SDF element that was used during
/// load.
/// \return SDF element pointer. The value will be nullptr if Load has
/// not been called.
public: sdf::ElementPtr Element() const;

/// \brief Get the Gazebo Math representation of this cone.
/// \return A const reference to a gz::math::Sphered object.
public: const gz::math::Coned &Shape() const;

/// \brief Get a mutable Gazebo Math representation of this cone.
/// \return A reference to a gz::math::Coned object.
public: gz::math::Coned &Shape();

/// \brief Calculate and return the Inertial values for the cone. In
/// order to calculate the inertial properties, the function mutates the
/// object by updating its material properties.
/// \param[in] _density Density of the cone in kg/m^3
/// \return A std::optional with gz::math::Inertiald object or std::nullopt
public: std::optional<gz::math::Inertiald>
CalculateInertial(double _density);

/// \brief Create and return an SDF element filled with data from this
/// cone.
/// Note that parameter passing functionality is not captured with this
/// function.
/// \return SDF element pointer with updated cone values.
public: sdf::ElementPtr ToElement() const;

/// \brief Create and return an SDF element filled with data from this
/// cone.
/// Note that parameter passing functionality is not captured with this
/// function.
/// \param[out] _errors Vector of errors.
/// \return SDF element pointer with updated cone values.
public: sdf::ElementPtr ToElement(sdf::Errors &_errors) const;

/// \brief Private data pointer.
GZ_UTILS_IMPL_PTR(dataPtr)
};
}
}
#endif
15 changes: 15 additions & 0 deletions include/sdf/Geometry.hh
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace sdf
// Forward declare private data class.
class Box;
class Capsule;
class Cone;
class Cylinder;
class Ellipsoid;
class Heightmap;
Expand Down Expand Up @@ -79,6 +80,9 @@ namespace sdf

/// \brief A polyline geometry.
POLYLINE = 9,

/// \brief A polyline geometry.
CONE = 10,
};

/// \brief Geometry provides access to a shape, such as a Box. Use the
Expand Down Expand Up @@ -137,6 +141,17 @@ namespace sdf
/// \param[in] _capsule The capsule shape.
public: void SetCapsuleShape(const Capsule &_capsule);

/// \brief Get the cone geometry, or nullptr if the contained
/// geometry is not a cone.
/// \return Pointer to the visual's cone geometry, or nullptr if the
/// geometry is not a cone.
/// \sa GeometryType Type() const
public: const Cone *ConeShape() const;

/// \brief Set the cone shape.
/// \param[in] _cone The cone shape.
public: void SetConeShape(const Cone &_cone);

/// \brief Get the cylinder geometry, or nullptr if the contained
/// geometry is not a cylinder.
/// \return Pointer to the visual's cylinder geometry, or nullptr if the
Expand Down
3 changes: 3 additions & 0 deletions include/sdf/ParticleEmitter.hh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ namespace sdf

/// \brief An ellipsoid emitter.
ELLIPSOID = 3,

/// \brief An cone emitter.
CONE = 4,
};

/// \brief A description of a particle emitter, which can be attached
Expand Down
1 change: 1 addition & 0 deletions include/sdf/Visual.hh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <gz/math/Pose3.hh>
#include <gz/utils/ImplPtr.hh>
#include "sdf/Box.hh"
#include "sdf/Cone.hh"
#include "sdf/Cylinder.hh"
#include "sdf/Element.hh"
#include "sdf/Material.hh"
Expand Down
2 changes: 2 additions & 0 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pybind11_add_module(${BINDINGS_MODULE_NAME} MODULE
src/sdf/pyCamera.cc
src/sdf/pyCapsule.cc
src/sdf/pyCollision.cc
src/sdf/pyCone.cc
src/sdf/pyConvexDecomposition.cc
src/sdf/pyCylinder.cc
src/sdf/pyElement.cc
Expand Down Expand Up @@ -119,6 +120,7 @@ if (BUILD_TESTING AND NOT WIN32)
pyCamera_TEST
pyCapsule_TEST
pyCollision_TEST
pyCone_TEST
pyCylinder_TEST
pyElement_TEST
pyEllipsoid_TEST
Expand Down
2 changes: 2 additions & 0 deletions python/src/sdf/_gz_sdformat_pybind11.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "pyCamera.hh"
#include "pyCapsule.hh"
#include "pyCollision.hh"
#include "pyCone.hh"
#include "pyConvexDecomposition.hh"
#include "pyCylinder.hh"
#include "pyElement.hh"
Expand Down Expand Up @@ -86,6 +87,7 @@ PYBIND11_MODULE(BINDINGS_MODULE_NAME, m) {
sdf::python::defineCamera(m);
sdf::python::defineCapsule(m);
sdf::python::defineCollision(m);
sdf::python::defineCone(m);
sdf::python::defineConvexDecomposition(m);
sdf::python::defineContact(m);
sdf::python::defineCylinder(m);
Expand Down
60 changes: 60 additions & 0 deletions python/src/sdf/pyCone.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2024 CogniPilot Foundation
* Copyright 2024 Open Source Robotics Foundation
* Copyright 2024 Rudis Laboratories
*
* 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 "pyCone.hh"

#include <pybind11/pybind11.h>

#include "sdf/Cone.hh"

using namespace pybind11::literals;

namespace sdf
{
// Inline bracket to help doxygen filtering.
inline namespace SDF_VERSION_NAMESPACE {
namespace python
{
/////////////////////////////////////////////////
void defineCone(pybind11::object module)
{
pybind11::class_<sdf::Cone>(module, "Cone")
.def(pybind11::init<>())
.def(pybind11::init<sdf::Cone>())
.def("radius", &sdf::Cone::Radius,
"Get the cone's radius in meters.")
.def("set_radius", &sdf::Cone::SetRadius,
"Set the cone's radius in meters.")
.def("length", &sdf::Cone::Length,
"Get the cone's length in meters.")
.def("set_length", &sdf::Cone::SetLength,
"Set the cone's length in meters.")
.def(
"shape",
pybind11::overload_cast<>(&sdf::Cone::Shape, pybind11::const_),
pybind11::return_value_policy::reference,
"Get a mutable Gazebo Math representation of this Cone.")
.def("__copy__", [](const sdf::Cone &self) {
return sdf::Cone(self);
})
.def("__deepcopy__", [](const sdf::Cone &self, pybind11::dict) {
return sdf::Cone(self);
}, "memo"_a);
}
} // namespace python
} // namespace SDF_VERSION_NAMESPACE
} // namespace sdf
43 changes: 43 additions & 0 deletions python/src/sdf/pyCone.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2024 CogniPilot Foundation
* Copyright 2024 Open Source Robotics Foundation
* Copyright 2024 Rudis Laboratories
*
* 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_CONE_HH_
#define SDFORMAT_PYTHON_CONE_HH_

#include <pybind11/pybind11.h>

#include "sdf/Cone.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::Cone
/**
* \param[in] module a pybind11 module to add the definition to
*/
void defineCone(pybind11::object module);
} // namespace python
} // namespace SDF_VERSION_NAMESPACE
} // namespace sdf

#endif // SDFORMAT_PYTHON_CONE_HH_
8 changes: 8 additions & 0 deletions python/src/sdf/pyGeometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "sdf/Box.hh"
#include "sdf/Capsule.hh"
#include "sdf/Cone.hh"
#include "sdf/Cylinder.hh"
#include "sdf/Ellipsoid.hh"
#include "sdf/Geometry.hh"
Expand Down Expand Up @@ -61,6 +62,12 @@ void defineGeometry(pybind11::object module)
"geometry is not a capsule.")
.def("set_capsule_shape", &sdf::Geometry::SetCapsuleShape,
"Set the capsule shape.")
.def("cone_shape", &sdf::Geometry::ConeShape,
pybind11::return_value_policy::reference,
"Get the cone geometry, or None if the contained "
"geometry is not a cone.")
.def("set_cone_shape", &sdf::Geometry::SetConeShape,
"Set the cone shape.")
.def("cylinder_shape", &sdf::Geometry::CylinderShape,
pybind11::return_value_policy::reference,
"Get the cylinder geometry, or None if the contained "
Expand Down Expand Up @@ -101,6 +108,7 @@ void defineGeometry(pybind11::object module)
pybind11::enum_<sdf::GeometryType>(module, "GeometryType")
.value("EMPTY", sdf::GeometryType::EMPTY)
.value("BOX", sdf::GeometryType::BOX)
.value("CONE", sdf::GeometryType::CONE)
.value("CYLINDER", sdf::GeometryType::CYLINDER)
.value("PLANE", sdf::GeometryType::PLANE)
.value("SPHERE", sdf::GeometryType::SPHERE)
Expand Down
1 change: 1 addition & 0 deletions python/src/sdf/pyParticleEmitter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ void defineParticleEmitter(pybind11::object module)
pybind11::enum_<sdf::ParticleEmitterType>(particleEmitterModule, "ParticleEmitterType")
.value("POINT", sdf::ParticleEmitterType::POINT)
.value("BOX", sdf::ParticleEmitterType::BOX)
.value("CONE", sdf::ParticleEmitterType::CONE)
.value("CYLINDER", sdf::ParticleEmitterType::CYLINDER)
.value("ELLIPSOID", sdf::ParticleEmitterType::ELLIPSOID);
}
Expand Down
3 changes: 2 additions & 1 deletion python/test/pyCollision_TEST.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import copy
from gz_test_deps.math import Pose3d
from gz_test_deps.sdformat import (Box, Collision, Contact, Cylinder, Error,
from gz_test_deps.sdformat import (Box, Collision, Cone, Contact, Cylinder, Error,
Geometry, Plane, Surface, Sphere,
SDFErrorsException)
import gz_test_deps.sdformat as sdf
Expand Down Expand Up @@ -57,6 +57,7 @@ def test_default_construction(self):
self.assertNotEqual(None, collision.geometry())
self.assertEqual(sdf.GeometryType.EMPTY, collision.geometry().type())
self.assertEqual(None, collision.geometry().box_shape())
self.assertEqual(None, collision.geometry().cone_shape())
self.assertEqual(None, collision.geometry().cylinder_shape())
self.assertEqual(None, collision.geometry().plane_shape())
self.assertEqual(None, collision.geometry().sphere_shape())
Expand Down
Loading

0 comments on commit e6adcd3

Please sign in to comment.