Skip to content

Commit

Permalink
Provide access to owning MBPlant from any MBElement. (#12380)
Browse files Browse the repository at this point in the history
  • Loading branch information
sherm1 authored Nov 20, 2019
1 parent 6e45230 commit aca4f0a
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
21 changes: 21 additions & 0 deletions multibody/plant/test/multibody_plant_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1566,6 +1566,27 @@ TEST_F(SplitPendulum, MassMatrix) {
EXPECT_NEAR(M(0, 0), Io, 1.0e-6);
}

// Verify that we can obtain the owning MultibodyPlant from one of its
// MultibodyElements, and that we get a proper error message if we try
// this for an element that isn't owned by a MultibodyPlant.
TEST_F(SplitPendulum, GetMultibodyPlantFromElement) {
const MultibodyPlant<double>& pins_plant = pin_->GetParentPlant();
EXPECT_EQ(&pins_plant, &plant_);

// Create an element-owning MBTreeSystem that _is not_ an MBPlant.
struct MyMBSystem : public internal::MultibodyTreeSystem<double> {
MyMBSystem() {
rigid_body = &mutable_tree().AddBody<RigidBody>(SpatialInertia<double>());
Finalize();
}
const RigidBody<double>* rigid_body{};
} mb_system;

DRAKE_EXPECT_THROWS_MESSAGE(
mb_system.rigid_body->GetParentPlant(), std::logic_error,
".*multibody element.*not owned by.*MultibodyPlant.*");
}

// Verifies we can parse link collision geometries and surface friction.
GTEST_TEST(MultibodyPlantTest, ScalarConversionConstructor) {
const std::string full_name = drake::FindResourceOrThrow(
Expand Down
26 changes: 26 additions & 0 deletions multibody/tree/multibody_element.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
namespace drake {
namespace multibody {

template <typename T>
class MultibodyPlant;

namespace internal {
// This is a class used by MultibodyTree internals to create the implementation
// for a particular joint object.
Expand Down Expand Up @@ -58,6 +61,29 @@ class MultibodyElement {
/// element belongs.
ModelInstanceIndex model_instance() const { return model_instance_;}

/// Returns the MultibodyPlant that owns this %MultibodyElement.
///
/// @note You can only invoke this method if you have a definition of
/// %MultibodyPlant available. That is, you must include
/// `drake/multibody/plant/multibody_plant.h` in the translation unit that
/// invokes this method; multibody_element.h cannot do that for you.
///
/// @throws std::logic_error if there is no %MultibodyPlant owner.
template <typename MultibodyPlantDeferred = MultibodyPlant<T>>
const MultibodyPlantDeferred& GetParentPlant() const {
HasParentTreeOrThrow();

const auto plant = dynamic_cast<const MultibodyPlantDeferred*>(
&get_parent_tree().tree_system());

if (plant == nullptr) {
throw std::logic_error(
"This multibody element was not owned by a MultibodyPlant.");
}

return *plant;
}

protected:
/// Default constructor made protected so that sub-classes can still declare
/// their default constructors if they need to.
Expand Down
7 changes: 7 additions & 0 deletions multibody/tree/multibody_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -2331,6 +2331,13 @@ class MultibodyTree {
}
//@}

/// Returns the MultibodyTreeSystem that owns this MultibodyTree.
/// @pre There is an owning MultibodyTreeSystem.
const MultibodyTreeSystem<T>& tree_system() const {
DRAKE_DEMAND(tree_system_ != nullptr);
return *tree_system_;
}

/// (Internal use only) Informs the MultibodyTree how to access its resources
/// within a Context.
void set_tree_system(MultibodyTreeSystem<T>* tree_system) {
Expand Down

0 comments on commit aca4f0a

Please sign in to comment.