Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
92 changes: 61 additions & 31 deletions bindings/generated_docstrings/geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,22 @@ Parameter ``resolution_hint``:
guides the level of mesh refinement. It has length units (in
meters) and roughly corresponds to a typical edge length in the
resulting mesh. See hug_properties. This will be ignored for
geometry types that don't require tessellation.
geometry types that don't require tessellation. Must satisfy 0 <
``resolution_hint`` < ∞ (NaN and ±∞ rejected).

Parameter ``hydroelastic_modulus``:
A multiplier that maps penetration to pressure. See
hug_properties.
hug_properties. Must be > 0 (+∞ allowed; NaN rejected).

Parameter ``properties``:
The properties will be added to this property set.

Raises:
RuntimeError If ``properties`` already has properties with the
RuntimeError If ``resolution_hint`` or ``hydroelastic_modulus`` is
invalid, or if ``properties`` already has properties with the
names that this function would need to add.

Precondition:
0 < ``resolution_hint`` < ∞, 0 < ``hydroelastic_modulus``, and
``properties`` is not nullptr.)""";
} AddCompliantHydroelasticProperties;
// Symbol: drake::geometry::AddCompliantHydroelasticPropertiesForHalfSpace
Expand All @@ -102,21 +103,22 @@ thickness. This variant is required for hydroelastic half spaces.

Parameter ``slab_thickness``:
The distance from the half space boundary to its rigid core (this
helps define the extent field of the half space).
helps define the extent field of the half space). Must satisfy 0 <
``slab_thickness`` < ∞ (NaN and ±∞ rejected).

Parameter ``hydroelastic_modulus``:
A multiplier that maps penetration to pressure. See
hug_properties.
hug_properties. Must be > 0 (+∞ allowed; NaN rejected).

Parameter ``properties``:
The properties will be added to this property set.

Raises:
RuntimeError If ``properties`` already has properties with the
RuntimeError If ``slab_thickness`` or ``hydroelastic_modulus`` is
invalid, or if ``properties`` already has properties with the
names that this function would need to add.

Precondition:
0 < ``slab_thickness`` < ∞, 0 < ``hydroelastic_modulus``, and
``properties`` is not nullptr.)""";
} AddCompliantHydroelasticPropertiesForHalfSpace;
// Symbol: drake::geometry::AddContactMaterial
Expand All @@ -132,9 +134,10 @@ default values will be provided. Downstream consumers of the contact
materials can optionally provide defaults for missing properties.

Raises:
RuntimeError if ``dissipation`` is negative, ``point_stiffness``
is not positive, of any of the contact material properties have
already been defined in ``properties``.
RuntimeError if ``dissipation`` is present but not ≥ 0 (NaN is
rejected; +∞ is allowed), if ``point_stiffness`` is present but
not > 0 (NaN is rejected; +∞ is allowed), or if any of the contact
material properties have already been defined in ``properties``.

Precondition:
``properties`` is not nullptr.)""";
Expand All @@ -152,17 +155,19 @@ Parameter ``resolution_hint``:
guides the level of mesh refinement. It has length units (in
meters) and roughly corresponds to a typical edge length in the
resulting mesh. See hug_properties. This will be ignored for
geometry types that don't require tessellation.
geometry types that don't require tessellation. Must satisfy 0 <
``resolution_hint`` < ∞ (NaN and ±∞ rejected).

Parameter ``properties``:
The properties will be added to this property set.

Raises:
RuntimeError If ``properties`` already has properties with the
names that this function would need to add.
RuntimeError If ``resolution_hint`` is invalid or if
``properties`` already has properties with the names that this
function would need to add.

Precondition:
0 < ``resolution_hint`` < ∞ and ``properties`` is not nullptr.)""";
``properties`` is not nullptr.)""";
// Source: drake/geometry/proximity_properties.h
const char* doc_1args =
R"""(Overload, intended for shapes that don't get tessellated in their
Expand Down Expand Up @@ -890,17 +895,14 @@ Serialization" for background.)""";
const char* doc =
R"""(@name Hydroelastic Contact Properties

These properties affect hydroelastic contact only. For more detail,
including limits of the numeric parameters,
These properties affect hydroelastic contact only. Valid ranges for
each numeric parameter are documented on the corresponding field
below.

See also:
geometry∷AddRigidHydroelasticProperties,
geometry∷AddCompliantHydroelasticProperties,
geometry∷AddCompliantHydroelasticPropertiesForHalfSpace.

For more context,

See also:
geometry∷AddCompliantHydroelasticPropertiesForHalfSpace,
hug_properties. There are three valid options for
``compliance_type``: - "undefined": hydroelastic contact will not
be used. - "rigid": the default hydroelastic compliance type will
Expand All @@ -916,14 +918,18 @@ See also:
const char* doc =
R"""(@name General Contact Properties

These properties affect contact in general. For more detail, including
limits of the numeric parameters,
These properties affect contact in general. Valid ranges for each
numeric parameter are documented on the corresponding field below.

See also:
geometry∷AddContactMaterial, multibody∷CoulombFriction,
mbp_contact_modeling, mbp_dissipation_model. To be valid, either
both friction values must be populated, or neither. Friction
quantities are unitless.)""";
mbp_contact_modeling, mbp_dissipation_model. Dynamic Coulomb
friction coefficient (unitless).

To be valid, either both friction values must be populated, or
neither. When present, the value must be non-negative (``≥ 0``). +∞ is
allowed; NaN is not. Additional relationship constraints with
``static_friction`` are enforced by multibody∷CoulombFriction.)""";
} dynamic_friction;
// Symbol: drake::geometry::DefaultProximityProperties::hunt_crossley_dissipation
struct /* hunt_crossley_dissipation */ {
Expand All @@ -933,6 +939,9 @@ R"""(Controls energy dissipation from contact, for contact approximations
other than* multibody∷DiscreteContactApproximation∷kSap. Units are
seconds per meter.

When present, the value must be non-negative (``≥ 0``). +∞ is allowed;
NaN is not.

If a non-deformable geometry is missing a value for dissipation,
MultibodyPlant will generate a default value (based on
multibody∷MultibodyPlantConfig∷penetration_allowance). However, this
Expand All @@ -949,7 +958,11 @@ parameters specific to your model.)""";
struct /* hydroelastic_modulus */ {
// Source: drake/geometry/scene_graph_config.h
const char* doc =
R"""(A measure of material stiffness, in units of Pascals.)""";
R"""(A measure of material stiffness, in units of Pascals.

When present, the value must be strictly positive (``> 0``). +∞ is
allowed (it is mathematically equivalent to a rigid object); NaN is
not.)""";
} hydroelastic_modulus;
// Symbol: drake::geometry::DefaultProximityProperties::margin
struct /* margin */ {
Expand All @@ -961,6 +974,9 @@ for contact resolution whenever their distance is within δ₁ + δ₂. That
is, (speculative) contact constraints are added for objects at a
distance smaller than δ₁+δ₂.

When present, the value must satisfy ``0 ≤ margin < ∞`` (finite and
non-negative). NaN and ±∞ are not allowed.

Refer to hydro_margin for further details, including theory, examples,
recommended margin values and limitations.

Expand Down Expand Up @@ -996,6 +1012,9 @@ Collision Detection.
const char* doc =
R"""(A measure of material stiffness, in units of Newtons per meter.

When present, the value must be strictly positive (``> 0``). +∞ is
allowed; NaN is not.

If a non-deformable geometry is missing a value for stiffness,
MultibodyPlant will generate a default value (based on
multibody∷MultibodyPlantConfig∷penetration_allowance). However, this
Expand All @@ -1012,7 +1031,10 @@ parameters specific to your model.)""";
// Source: drake/geometry/scene_graph_config.h
const char* doc =
R"""(Controls energy damping from contact, *only for*
multibody∷DiscreteContactApproximation∷kSap. Units are seconds.)""";
multibody∷DiscreteContactApproximation∷kSap. Units are seconds.

When present, the value must satisfy ``0 ≤ relaxation_time < ∞``
(finite and non-negative). NaN and ±∞ are not allowed.)""";
} relaxation_time;
// Symbol: drake::geometry::DefaultProximityProperties::resolution_hint
struct /* resolution_hint */ {
Expand All @@ -1021,6 +1043,9 @@ multibody∷DiscreteContactApproximation∷kSap. Units are seconds.)""";
R"""(Controls how finely primitive geometries are tessellated, units of
meters.

When present, the value must satisfy ``0 < resolution_hint < ∞``
(finite and positive). NaN and ±∞ are not allowed.

While no single value is universally appropriate, this value was
selected based on the following idea. We're attempting to make
introducing novel manipulands as easy as possible. Considering a
Expand All @@ -1033,13 +1058,18 @@ appropriate for contact with a compliant gripper.)""";
// Source: drake/geometry/scene_graph_config.h
const char* doc =
R"""(For a halfspace, the thickness of compliant material to model, in
units of meters.)""";
units of meters.

When present, the value must satisfy ``0 < slab_thickness < ∞``
(finite and positive). NaN and ±∞ are not allowed.)""";
} slab_thickness;
// Symbol: drake::geometry::DefaultProximityProperties::static_friction
struct /* static_friction */ {
// Source: drake/geometry/scene_graph_config.h
const char* doc =
R"""(See also:
R"""(Static Coulomb friction coefficient (unitless).

See also:
dynamic_friction.)""";
} static_friction;
auto Serialize__fields() const {
Expand Down
4 changes: 1 addition & 3 deletions geometry/proximity_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1219,9 +1219,7 @@ class ProximityEngine<T>::Impl : public ShapeReifier {
unordered_map<GeometryId, unique_ptr<CollisionObjectd>>* objects) {
const double margin =
props.GetPropertyOrDefault<double>(kHydroGroup, kMargin, 0.0);
if (!(margin >= 0 && std::isfinite(margin))) {
throw std::logic_error("Margin must be non-negative and finite.");
}
ThrowIfInvalidMargin(margin);
ReifyData data{nullptr, id, props, X_WG, margin};
shape.Reify(this, &data);

Expand Down
87 changes: 73 additions & 14 deletions geometry/proximity_properties.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "drake/geometry/proximity_properties.h"

#include <array>
#include <cmath>
#include <string>

namespace drake {
Expand Down Expand Up @@ -79,6 +80,72 @@ std::string_view to_string(const HydroelasticType& type) {
return EnumToChars(type);
}

void ThrowIfInvalidHydroelasticModulus(double hydroelastic_modulus) {
// +∞ is allowed (equivalent to rigid); NaN is not (`!(nan > 0)`).
if (!(hydroelastic_modulus > 0)) {
throw std::logic_error(
fmt::format("The hydroelastic modulus must be positive; given {}",
hydroelastic_modulus));
}
}

void ThrowIfInvalidResolutionHint(double resolution_hint) {
if (!(std::isfinite(resolution_hint) && resolution_hint > 0)) {
throw std::logic_error(
fmt::format("The resolution_hint must be positive and finite; given {}",
resolution_hint));
}
}

void ThrowIfInvalidSlabThickness(double slab_thickness) {
if (!(std::isfinite(slab_thickness) && slab_thickness > 0)) {
throw std::logic_error(
fmt::format("The slab_thickness must be positive and finite; given {}",
slab_thickness));
}
}

void ThrowIfInvalidMargin(double margin) {
if (!(std::isfinite(margin) && margin >= 0)) {
throw std::logic_error(fmt::format(
"The margin must be non-negative and finite; given {}", margin));
}
}

void ThrowIfInvalidHuntCrossleyDissipation(double dissipation) {
// +∞ is allowed; NaN is not (`!(nan >= 0)`).
if (!(dissipation >= 0)) {
throw std::logic_error(fmt::format(
"The dissipation can't be negative; given {}", dissipation));
}
}

void ThrowIfInvalidRelaxationTime(double relaxation_time) {
if (!(std::isfinite(relaxation_time) && relaxation_time >= 0)) {
throw std::logic_error(fmt::format(
"The relaxation_time must be non-negative and finite; given {}",
relaxation_time));
}
}

void ThrowIfInvalidPointStiffness(double point_stiffness) {
// +∞ is allowed; NaN is not (`!(nan > 0)`).
if (!(point_stiffness > 0)) {
throw std::logic_error(fmt::format(
"The point_contact_stiffness must be strictly positive; given {}",
point_stiffness));
}
}

void ThrowIfInvalidFrictionCoefficient(double friction_coefficient) {
// +∞ is allowed; NaN is not (`!(nan >= 0)`).
if (!(friction_coefficient >= 0)) {
throw std::logic_error(
fmt::format("The friction coefficient can't be negative; given {}",
friction_coefficient));
}
}

} // namespace internal

void AddContactMaterial(
Expand All @@ -87,20 +154,13 @@ void AddContactMaterial(
ProximityProperties* properties) {
DRAKE_DEMAND(properties != nullptr);
if (dissipation.has_value()) {
if (*dissipation < 0) {
throw std::logic_error(fmt::format(
"The dissipation can't be negative; given {}", *dissipation));
}
internal::ThrowIfInvalidHuntCrossleyDissipation(*dissipation);
properties->AddProperty(internal::kMaterialGroup, internal::kHcDissipation,
*dissipation);
}

if (point_stiffness.has_value()) {
if (*point_stiffness <= 0) {
throw std::logic_error(fmt::format(
"The point_contact_stiffness must be strictly positive; given {}",
*point_stiffness));
}
internal::ThrowIfInvalidPointStiffness(*point_stiffness);
properties->AddProperty(internal::kMaterialGroup, internal::kPointStiffness,
*point_stiffness);
}
Expand All @@ -117,6 +177,7 @@ void AddContactMaterial(
void AddRigidHydroelasticProperties(double resolution_hint,
ProximityProperties* properties) {
DRAKE_DEMAND(properties != nullptr);
internal::ThrowIfInvalidResolutionHint(resolution_hint);
properties->AddProperty(internal::kHydroGroup, internal::kRezHint,
resolution_hint);
AddRigidHydroelasticProperties(properties);
Expand All @@ -138,11 +199,7 @@ void AddCompliantHydroelasticProperties(double hydroelastic_modulus,
// The bare minimum of defining a compliant geometry is to declare its
// compliance type. Downstream consumers (ProximityEngine) will determine
// if this is sufficient.
if (hydroelastic_modulus <= 0) {
throw std::logic_error(
fmt::format("The hydroelastic modulus must be positive; given {}",
hydroelastic_modulus));
}
internal::ThrowIfInvalidHydroelasticModulus(hydroelastic_modulus);
properties->AddProperty(internal::kHydroGroup, internal::kElastic,
hydroelastic_modulus);
properties->AddProperty(internal::kHydroGroup, internal::kComplianceType,
Expand All @@ -154,6 +211,7 @@ void AddCompliantHydroelasticProperties(double resolution_hint,
double hydroelastic_modulus,
ProximityProperties* properties) {
DRAKE_DEMAND(properties != nullptr);
internal::ThrowIfInvalidResolutionHint(resolution_hint);
properties->AddProperty(internal::kHydroGroup, internal::kRezHint,
resolution_hint);
AddCompliantHydroelasticProperties(hydroelastic_modulus, properties);
Expand All @@ -163,6 +221,7 @@ void AddCompliantHydroelasticPropertiesForHalfSpace(
double slab_thickness, double hydroelastic_modulus,
ProximityProperties* properties) {
DRAKE_DEMAND(properties != nullptr);
internal::ThrowIfInvalidSlabThickness(slab_thickness);
properties->AddProperty(internal::kHydroGroup, internal::kSlabThickness,
slab_thickness);
AddCompliantHydroelasticProperties(hydroelastic_modulus, properties);
Expand Down
Loading