Skip to content

Commit 52c0177

Browse files
committed
Adds SpanningForest builder.
1 parent ad67378 commit 52c0177

19 files changed

+4686
-951
lines changed

multibody/contact_solvers/test/multibody_sim_driver.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ class MultibodySimDriver {
4343
// MultibodyPlant::Finalize() and Simulator::Initialize().
4444
void Initialize();
4545

46-
// @pre BuildModel() must have been called.
46+
// @pre BuildForest() must have been called.
4747
const MultibodyPlant<double>& plant() const {
4848
DRAKE_DEMAND(plant_ != nullptr);
4949
return *plant_;
5050
}
5151

52-
// @pre BuildModel() must have been called.
52+
// @pre BuildForest() must have been called.
5353
MultibodyPlant<double>& mutable_plant() {
5454
DRAKE_DEMAND(plant_ != nullptr);
5555
return *plant_;

multibody/plant/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ drake_cc_library(
137137
"//multibody/contact_solvers/sap",
138138
"//multibody/fem",
139139
"//multibody/hydroelastics:hydroelastic_engine",
140+
"//multibody/topology:multibody_topology",
140141
"//multibody/tree",
141142
"//systems/framework:diagram_builder",
142143
"//systems/framework:leaf_system",

multibody/plant/multibody_plant.cc

+65-6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "drake/multibody/plant/hydroelastic_traction_calculator.h"
2626
#include "drake/multibody/plant/make_discrete_update_manager.h"
2727
#include "drake/multibody/plant/slicing_and_indexing.h"
28+
#include "drake/multibody/topology/spanning_forest_model.h"
2829
#include "drake/multibody/tree/prismatic_joint.h"
2930
#include "drake/multibody/tree/quaternion_floating_joint.h"
3031
#include "drake/multibody/tree/revolute_joint.h"
@@ -328,7 +329,6 @@ MultibodyPlant<T>::MultibodyPlant(
328329
// it less brittle.
329330
visual_geometries_.emplace_back(); // Entries for the "world" body.
330331
collision_geometries_.emplace_back();
331-
332332
DeclareSceneGraphPorts();
333333
}
334334

@@ -889,7 +889,7 @@ template <typename T>
889889
std::vector<const Body<T>*> MultibodyPlant<T>::GetBodiesWeldedTo(
890890
const Body<T>& body) const {
891891
const std::set<BodyIndex> island =
892-
internal_tree().multibody_graph().FindBodiesWeldedTo(body.index());
892+
internal_tree().link_joint_graph().FindLinksWeldedTo(body.index());
893893
// Map body indices to pointers.
894894
std::vector<const Body<T>*> sub_graph_bodies;
895895
for (BodyIndex body_index : island) {
@@ -1097,8 +1097,61 @@ void MultibodyPlant<T>::RenameModelInstance(ModelInstanceIndex model_instance,
10971097

10981098
template<typename T>
10991099
void MultibodyPlant<T>::Finalize() {
1100-
// After finalizing the base class, tree is read-only.
1101-
internal::MultibodyTreeSystem<T>::Finalize();
1100+
/* Given the user-defined directed graph of Links and Joints, decide how we're
1101+
going to model this using a spanning forest comprised of
1102+
- bodies and their mobilizers, paired as "mobilized bodies" (mobods) and
1103+
directed by inboard/outboard edges, and
1104+
- added constraints where needed to close kinematic loops in the graph.
1105+
The modeler sorts the mobilized bodies into depth-first order.
1106+
1107+
Every Link will be modeled with one "primary" body and possibly several
1108+
"shadow" bodies. Every Joint will be modeled with a mobilizer, with the
1109+
Joint's parent/child connections mapped to the mobilizer's inboard/outboard
1110+
connection or to the reverse, as necessary for the mobilizers to form a
1111+
properly-directed tree. Every body in the tree must have a path in the
1112+
inboard direction connecting it to World. If necessary, additional "floating"
1113+
(6 dof) or "weld" (0 dof) mobilizers are added to make the final connection
1114+
to World.
1115+
1116+
During the modeling process, the LinkJointGraph is augmented to have
1117+
additional elements to provide an interface to the additional elements that
1118+
were required to build the model. Below, we will augment the MultibodyPlant
1119+
elements to match, so that advanced users can use the familiar Plant API to
1120+
access and control these elements. */
1121+
this->mutable_tree().BuildSpanningForest();
1122+
1123+
/* Add Links, Joints, and Constraints that were created during the modeling
1124+
process. */
1125+
1126+
const internal::LinkJointGraph& graph = internal_tree().link_joint_graph();
1127+
unused(graph);
1128+
1129+
/* TODO(sherm1) why not use MbP as the LinkJointGraph and do away with
1130+
the extra class? Then we wouldn't have to repeat these additions.
1131+
// Added floating mobods are in the order the new joints were added so
1132+
// the index we get in the plant should match the one stored with the mobod.
1133+
for (auto index : graph.added_floating_mobods()) {
1134+
const internal::SpanningForestModel::Mobod& floating_mobod =
1135+
model.mobods()[index];
1136+
const JointIndex floating = AddFloatingJointToWorld(floating_mobod);
1137+
DRAKE_DEMAND(floating == floating_mobod.joint_index);
1138+
}
1139+
1140+
// Shadow mobods are in the order the new bodies were added so the body
1141+
// index should match.
1142+
for (auto index : model.shadow_mobods()) {
1143+
const internal::SpanningForestModel::Mobod shadow_mobod = model.mobods()[index];
1144+
const BodyIndex shadow = AddShadowBody(shadow_mobod);
1145+
DRAKE_DEMAND(shadow == shadow_mobod.link_index_);
1146+
}
1147+
1148+
// The modeler only knows about constraints it adds so there is no
1149+
// indexing correspondence.
1150+
for (auto& loop_constraint : model.added_constraints()) {
1151+
const ConstraintIndex constraint =
1152+
AddLoopClosingConstraint(loop_constraint);
1153+
}
1154+
*/
11021155

11031156
if (geometry_source_is_registered()) {
11041157
ApplyDefaultCollisionFilters();
@@ -1120,6 +1173,12 @@ void MultibodyPlant<T>::Finalize() {
11201173
"only supported for discrete models. Refer to MultibodyPlant's "
11211174
"documentation for further details.");
11221175
}
1176+
1177+
/* The Plant is complete now. Next, build an efficient computational
1178+
representation structured in accordance with `model`. */
1179+
1180+
// After finalizing the base class, tree is read-only.
1181+
internal::MultibodyTreeSystem<T>::Finalize();
11231182
}
11241183

11251184
template<typename T>
@@ -1342,7 +1401,7 @@ void MultibodyPlant<T>::ApplyDefaultCollisionFilters() {
13421401
}
13431402
// We explicitly exclude collisions within welded subgraphs.
13441403
std::vector<std::set<BodyIndex>> subgraphs =
1345-
internal_tree().multibody_graph().FindSubgraphsOfWeldedBodies();
1404+
internal_tree().link_joint_graph().FindSubgraphsOfWeldedLinks();
13461405
for (const auto& subgraph : subgraphs) {
13471406
// Only operate on non-trivial weld subgraphs.
13481407
if (subgraph.size() <= 1) { continue; }
@@ -3558,7 +3617,7 @@ void MultibodyPlant<T>::RemoveUnsupportedScalars(
35583617
template <typename T>
35593618
std::vector<std::set<BodyIndex>>
35603619
MultibodyPlant<T>::FindSubgraphsOfWeldedBodies() const {
3561-
return internal_tree().multibody_graph().FindSubgraphsOfWeldedBodies();
3620+
return internal_tree().link_joint_graph().FindSubgraphsOfWeldedLinks();
35623621
}
35633622

35643623
template <typename T>

multibody/plant/multibody_plant.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
#include "drake/multibody/plant/discrete_update_manager.h"
2727
#include "drake/multibody/plant/multibody_plant_config.h"
2828
#include "drake/multibody/plant/physical_model.h"
29-
#include "drake/multibody/topology/multibody_graph.h"
29+
#include "drake/multibody/topology/link_joint_graph.h"
30+
#include "drake/multibody/topology/spanning_forest_model.h"
3031
#include "drake/multibody/tree/force_element.h"
3132
#include "drake/multibody/tree/multibody_tree-inl.h"
3233
#include "drake/multibody/tree/multibody_tree_system.h"
@@ -4958,7 +4959,7 @@ class MultibodyPlant : public internal::MultibodyTreeSystem<T> {
49584959
/// @} <!-- Introspection -->
49594960

49604961
#ifndef DRAKE_DOXYGEN_CXX
4961-
// Internal-only access to MultibodyGraph::FindSubgraphsOfWeldedBodies();
4962+
// Internal-only access to LinkJointGraph::FindSubgraphsOfWeldedBodies();
49624963
// TODO(calderpg-tri) Properly expose this method (docs/tests/bindings).
49634964
std::vector<std::set<BodyIndex>> FindSubgraphsOfWeldedBodies() const;
49644965
#endif

multibody/topology/BUILD.bazel

+8-5
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,26 @@ package(
1111
)
1212

1313
drake_cc_library(
14-
name = "multibody_graph",
14+
name = "multibody_topology",
1515
srcs = [
16-
"multibody_graph.cc",
16+
"link_joint_graph.cc",
17+
"spanning_forest_model.cc",
1718
],
1819
hdrs = [
19-
"multibody_graph.h",
20+
"link_joint_graph.h",
21+
"spanning_forest_model.h",
2022
],
2123
deps = [
24+
"//common:copyable_unique_ptr",
2225
"//common:sorted_pair",
2326
"//multibody/tree:multibody_tree_indexes",
2427
],
2528
)
2629

2730
drake_cc_googletest(
28-
name = "multibody_graph_test",
31+
name = "link_joint_graph_test",
2932
deps = [
30-
":multibody_graph",
33+
":multibody_topology",
3134
"//common/test_utilities:expect_throws_message",
3235
],
3336
)

0 commit comments

Comments
 (0)