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
8 changes: 8 additions & 0 deletions multibody/plant/deformable_model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ DeformableBodyId DeformableModel<T>::RegisterDeformableBody(
"given model.",
model_instance_name, name));
}
if (this->plant().HasBodyNamed(name, model_instance)) {
const std::string& model_instance_name =
this->plant().GetModelInstanceName(model_instance);
throw std::logic_error(fmt::format(
"RegisterDeformableBody(): Model instance '{}' already contains a "
"body named '{}'. Body names must be unique within a given model.",
model_instance_name, name));
}
/* Register the geometry with SceneGraph. */
SceneGraph<T>& scene_graph = this->mutable_scene_graph();
const ScopedName scoped_name(
Expand Down
4 changes: 2 additions & 2 deletions multibody/plant/deformable_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ class DeformableModel final : public multibody::PhysicalModel<T> {
@throws std::exception if `this` %DeformableModel belongs to a continuous
MultibodyPlant.
@throws std::exception if the model instance does not exist.
@throws std::exception if a deformable body with the same name has already
been registered to the model instance.
@throws std::exception if a deformable body or rigid body with the same name
has already been registered to the model instance.
@throws std::exception if Finalize() has been called on the multibody plant
owning this deformable model. */
DeformableBodyId RegisterDeformableBody(
Expand Down
21 changes: 16 additions & 5 deletions multibody/plant/multibody_plant.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <utility>
#include <vector>

#include <fmt/format.h>

#include "drake/common/default_scalars.h"
#include "drake/common/drake_export.h"
#include "drake/common/random.h"
Expand Down Expand Up @@ -1429,8 +1431,9 @@ class MultibodyPlant final : public internal::MultibodyTreeSystem<T> {
///
/// @param[in] name
/// A string that identifies the new body to be added to `this` model. A
/// std::runtime_error is thrown if a body named `name` already is part of
/// @p model_instance. See HasBodyNamed(), RigidBody::name().
/// std::logic_error is thrown if a rigid or deformable body named `name`
/// already is part of @p model_instance. See HasBodyNamed(),
/// RigidBody::name().
/// @param[in] model_instance
/// A model instance index which this body is part of.
/// @param[in] M_BBo_B
Expand All @@ -1443,6 +1446,14 @@ class MultibodyPlant final : public internal::MultibodyTreeSystem<T> {
const std::string& name, ModelInstanceIndex model_instance,
const SpatialInertia<double>& M_BBo_B = SpatialInertia<double>::Zero()) {
DRAKE_MBP_THROW_IF_FINALIZED();
// Body names must be unique within a model instance across both rigid and
// deformable bodies.
if (deformable_model().HasBodyNamed(name, model_instance)) {
throw std::logic_error(fmt::format(
"Model instance '{}' already contains a body named '{}'. Body names "
"must be unique within a given model.",
GetModelInstanceName(model_instance), name));
}
// Add the actual RigidBody (Link) to the model.
const RigidBody<T>& body =
this->mutable_tree().AddLink(name, model_instance, M_BBo_B);
Expand Down Expand Up @@ -1475,9 +1486,9 @@ class MultibodyPlant final : public internal::MultibodyTreeSystem<T> {
///
/// @param[in] name
/// A string that identifies the new body to be added to `this` model. A
/// std::runtime_error is thrown if a body named `name` already is part of
/// the model in the default model instance. See HasBodyNamed(),
/// RigidBody::name().
/// std::logic_error is thrown if a rigid or deformable body named `name`
/// already is part of the model in the default model instance. See
/// HasBodyNamed(), RigidBody::name().
/// @param[in] M_BBo_B
/// The SpatialInertia of the new rigid body to be added to `this`
/// %MultibodyPlant, computed about the body frame origin `Bo` and expressed
Expand Down
28 changes: 28 additions & 0 deletions multibody/plant/test/deformable_model_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,34 @@ TEST_F(DeformableModelTest, DuplicatedNames) {
EXPECT_EQ(body1.body_id(), body1_id);
}

/* Rigid and deformable bodies must not share a name within a model instance. */
TEST_F(DeformableModelTest, ConflictingRigidAndDeformableNames) {
const double kRezHint = 0.5;
const ModelInstanceIndex instance0 = plant_->AddModelInstance("instance0");
const ModelInstanceIndex instance1 = plant_->AddModelInstance("instance1");

/* Rigid then deformable with the same name in one model instance throws. */
plant_->AddRigidBody("sphere", instance0,
SpatialInertia<double>::MakeUnitary());
DRAKE_EXPECT_THROWS_MESSAGE(
RegisterSphere(deformable_model_ptr_, kRezHint, RigidTransformd{},
instance0),
".*instance0.*already contains a body named 'sphere'.*");

/* Deformable then rigid with the same name in one model instance throws. */
RegisterSphere(deformable_model_ptr_, kRezHint, RigidTransformd{},
instance1);
DRAKE_EXPECT_THROWS_MESSAGE(
plant_->AddRigidBody("sphere", instance1,
SpatialInertia<double>::MakeUnitary()),
".*instance1.*already contains a body named 'sphere'.*");

/* The same name is allowed across different model instances. */
EXPECT_NO_THROW(plant_->AddRigidBody(
"sphere", plant_->AddModelInstance("instance2"),
SpatialInertia<double>::MakeUnitary()));
}

} // namespace
} // namespace internal
} // namespace multibody
Expand Down