Skip to content

Commit 8379db1

Browse files
committed
Changes to MbP and MbT
Passes all tests now (except space_xyz_floating_mobilizer is disabled)
1 parent 6184eb4 commit 8379db1

25 files changed

+550
-571
lines changed

multibody/plant/compliant_contact_manager.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ template <typename T>
4040
AccelerationsDueNonConstraintForcesCache<
4141
T>::AccelerationsDueNonConstraintForcesCache(const MultibodyTreeTopology&
4242
topology)
43-
: forces(topology.num_bodies(), topology.num_velocities()),
43+
: forces(topology.num_links(), topology.num_velocities()),
4444
abic(topology),
45-
Zb_Bo_W(topology.num_bodies()),
45+
Zb_Bo_W(topology.num_body_nodes()),
4646
aba_forces(topology),
4747
ac(topology) {}
4848

multibody/plant/multibody_plant.cc

+9-67
Original file line numberDiff line numberDiff line change
@@ -25,7 +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"
28+
#include "drake/multibody/topology/link_joint_graph.h"
2929
#include "drake/multibody/tree/prismatic_joint.h"
3030
#include "drake/multibody/tree/quaternion_floating_joint.h"
3131
#include "drake/multibody/tree/revolute_joint.h"
@@ -992,7 +992,7 @@ void MultibodyPlant<T>::SetFreeBodyPoseInAnchoredFrame(
992992
DRAKE_MBP_THROW_IF_NOT_FINALIZED();
993993
this->ValidateContext(context);
994994

995-
if (!internal_tree().get_topology().IsBodyAnchored(frame_F.body().index())) {
995+
if (!internal_tree().get_topology().IsLinkAnchored(frame_F.body().index())) {
996996
throw std::logic_error(
997997
"Frame '" + frame_F.name() + "' must be anchored to the world frame.");
998998
}
@@ -1016,17 +1016,17 @@ void MultibodyPlant<T>::CalcSpatialAccelerationsFromVdot(
10161016
internal_tree().CalcSpatialAccelerationsFromVdot(
10171017
context, internal_tree().EvalPositionKinematics(context),
10181018
internal_tree().EvalVelocityKinematics(context), known_vdot, A_WB_array);
1019-
// Permute BodyNodeIndex -> BodyIndex.
1019+
// Permute BodyNodeIndex -> LinkIndex.
10201020
// TODO(eric.cousineau): Remove dynamic allocations. Making this in-place
10211021
// still required dynamic allocation for recording permutation indices.
10221022
// Can change implementation once MultibodyTree becomes fully internal.
10231023
std::vector<SpatialAcceleration<T>> A_WB_array_node = *A_WB_array;
10241024
const internal::MultibodyTreeTopology& topology =
10251025
internal_tree().get_topology();
10261026
for (internal::BodyNodeIndex node_index(1);
1027-
node_index < topology.get_num_body_nodes(); ++node_index) {
1028-
const BodyIndex body_index = topology.get_body_node(node_index).body;
1029-
(*A_WB_array)[body_index] = A_WB_array_node[node_index];
1027+
node_index < topology.num_body_nodes(); ++node_index) {
1028+
const LinkIndex link_index = topology.get_body_node(node_index).link;
1029+
(*A_WB_array)[link_index] = A_WB_array_node[node_index];
10301030
}
10311031
}
10321032

@@ -1097,65 +1097,13 @@ void MultibodyPlant<T>::RenameModelInstance(ModelInstanceIndex model_instance,
10971097

10981098
template<typename T>
10991099
void MultibodyPlant<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-
*/
1100+
// After finalizing the base class, tree is read-only.
1101+
internal::MultibodyTreeSystem<T>::Finalize();
11551102

11561103
if (geometry_source_is_registered()) {
11571104
ApplyDefaultCollisionFilters();
11581105
}
1106+
11591107
FinalizePlantOnly();
11601108

11611109
// Make the manager of discrete updates.
@@ -1173,12 +1121,6 @@ void MultibodyPlant<T>::Finalize() {
11731121
"only supported for discrete models. Refer to MultibodyPlant's "
11741122
"documentation for further details.");
11751123
}
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();
11821124
}
11831125

11841126
template<typename T>

multibody/plant/multibody_plant.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -4348,9 +4348,10 @@ class MultibodyPlant : public internal::MultibodyTreeSystem<T> {
43484348
/// Returns the number of bodies in the model, including the "world" body,
43494349
/// which is always part of the model.
43504350
/// @see AddRigidBody().
4351-
int num_bodies() const {
4352-
return internal_tree().num_bodies();
4353-
}
4351+
int num_links() const { return internal_tree().num_links(); }
4352+
4353+
/// Alternate spelling for num_links(). Prefer num_links().
4354+
int num_bodies() const { return num_links(); }
43544355

43554356
/// Returns a constant reference to the body with unique index `body_index`.
43564357
/// @throws std::exception if `body_index` does not correspond to a body in
@@ -4364,7 +4365,7 @@ class MultibodyPlant : public internal::MultibodyTreeSystem<T> {
43644365
/// @throws std::exception if called pre-finalize.
43654366
bool IsAnchored(const Body<T>& body) const {
43664367
DRAKE_MBP_THROW_IF_NOT_FINALIZED();
4367-
return internal_tree().get_topology().IsBodyAnchored(body.index());
4368+
return internal_tree().get_topology().IsLinkAnchored(body.index());
43684369
}
43694370

43704371
/// @returns `true` if a body named `name` was added to the %MultibodyPlant.

multibody/plant/test/multibody_plant_test.cc

+33-32
Original file line numberDiff line numberDiff line change
@@ -1703,15 +1703,16 @@ GTEST_TEST(MultibodyPlantTest, ReversedWeldError) {
17031703
"extra", default_model_instance(), SpatialInertia<double>());
17041704
plant.WeldFrames(extra.body_frame(), plant.world_frame());
17051705

1706+
/* TODO(sherm1) This shouldn't throw at all. */
1707+
17061708
// The important property of this message is that it reports some identifier
17071709
// for the involved objects, so at least the developer can map those back to
17081710
// objects and deduce what API call was in error. If the details of the
17091711
// message change, update this check to match. If in future the error can be
17101712
// caught at the WeldFrames() step, so much the better. Modify this test to
17111713
// reflect that.
1712-
DRAKE_EXPECT_THROWS_MESSAGE(
1713-
plant.Finalize(),
1714-
".*already has a joint.*extra_welds_to_world.*joint.*not allowed.*");
1714+
DRAKE_EXPECT_THROWS_MESSAGE(plant.Finalize(),
1715+
".*Link.*not assigned a mobilizer.*");
17151716
}
17161717

17171718
// Utility to verify the subset of output ports we expect to be direct a
@@ -3508,7 +3509,7 @@ GTEST_TEST(SetRandomTest, SetDefaultWhenNoDistributionSpecified) {
35083509
// explicitly added).
35093510
const Body<double>& body1 =
35103511
plant.AddRigidBody("free body 1", SpatialInertia<double>::MakeUnitary());
3511-
plant.AddJoint<QuaternionFloatingJoint>("" + body1.name(),
3512+
plant.AddJoint<QuaternionFloatingJoint>(body1.name(),
35123513
plant.world_body(), {}, body1, {});
35133514
const std::string acrobot_file_name =
35143515
"drake/multibody/benchmarks/acrobot/acrobot.sdf";
@@ -4421,16 +4422,16 @@ GTEST_TEST(MultibodyPlantTest, GetNames) {
44214422
names = plant->GetPositionNames(false /* add_model_instance_prefix */,
44224423
false /* always_add_suffix */);
44234424
EXPECT_THAT(names, testing::ElementsAreArray(
4424-
{"iiwa_joint_1", "iiwa_joint_2",
4425-
"iiwa_joint_3", "iiwa_joint_4",
4426-
"iiwa_joint_5", "iiwa_joint_6",
4427-
"iiwa_joint_7", "iiwa_link_0_qw",
4425+
{"iiwa_joint_1", "iiwa_joint_2",
4426+
"iiwa_joint_3", "iiwa_joint_4",
4427+
"iiwa_joint_5", "iiwa_joint_6",
4428+
"iiwa_joint_7", "iiwa_link_0_qw",
44284429
"iiwa_link_0_qx", "iiwa_link_0_qy",
44294430
"iiwa_link_0_qz", "iiwa_link_0_x",
44304431
"iiwa_link_0_y", "iiwa_link_0_z",
4431-
"iiwa_joint_1", "iiwa_joint_2",
4432-
"iiwa_joint_3", "iiwa_joint_4",
4433-
"iiwa_joint_5", "iiwa_joint_6",
4432+
"iiwa_joint_1", "iiwa_joint_2",
4433+
"iiwa_joint_3", "iiwa_joint_4",
4434+
"iiwa_joint_5", "iiwa_joint_6",
44344435
"iiwa_joint_7"}));
44354436

44364437
names = plant->GetVelocityNames(iiwa0_instance);
@@ -4511,16 +4512,16 @@ GTEST_TEST(MultibodyPlantTest, GetNames) {
45114512
names = plant->GetVelocityNames(false /* add_model_instance_prefix */,
45124513
false /* always_add_suffix */);
45134514
EXPECT_THAT(names, testing::ElementsAreArray(
4514-
{"iiwa_joint_1", "iiwa_joint_2",
4515-
"iiwa_joint_3", "iiwa_joint_4",
4516-
"iiwa_joint_5", "iiwa_joint_6",
4517-
"iiwa_joint_7", "iiwa_link_0_wx",
4515+
{"iiwa_joint_1", "iiwa_joint_2",
4516+
"iiwa_joint_3", "iiwa_joint_4",
4517+
"iiwa_joint_5", "iiwa_joint_6",
4518+
"iiwa_joint_7", "iiwa_link_0_wx",
45184519
"iiwa_link_0_wy", "iiwa_link_0_wz",
45194520
"iiwa_link_0_vx", "iiwa_link_0_vy",
45204521
"iiwa_link_0_vz", "iiwa_joint_1",
4521-
"iiwa_joint_2", "iiwa_joint_3",
4522-
"iiwa_joint_4", "iiwa_joint_5",
4523-
"iiwa_joint_6", "iiwa_joint_7"}));
4522+
"iiwa_joint_2", "iiwa_joint_3",
4523+
"iiwa_joint_4", "iiwa_joint_5",
4524+
"iiwa_joint_6", "iiwa_joint_7"}));
45244525

45254526
names = plant->GetStateNames(iiwa0_instance);
45264527
EXPECT_THAT(names, testing::ElementsAreArray(
@@ -4590,26 +4591,26 @@ GTEST_TEST(MultibodyPlantTest, GetNames) {
45904591
names =
45914592
plant->GetStateNames(false /* add_model_instance_prefix */);
45924593
EXPECT_THAT(names, testing::ElementsAreArray(
4593-
{"iiwa_joint_1_q", "iiwa_joint_2_q",
4594-
"iiwa_joint_3_q", "iiwa_joint_4_q",
4595-
"iiwa_joint_5_q", "iiwa_joint_6_q",
4596-
"iiwa_joint_7_q", "iiwa_link_0_qw",
4594+
{"iiwa_joint_1_q", "iiwa_joint_2_q",
4595+
"iiwa_joint_3_q", "iiwa_joint_4_q",
4596+
"iiwa_joint_5_q", "iiwa_joint_6_q",
4597+
"iiwa_joint_7_q", "iiwa_link_0_qw",
45974598
"iiwa_link_0_qx", "iiwa_link_0_qy",
45984599
"iiwa_link_0_qz", "iiwa_link_0_x",
45994600
"iiwa_link_0_y", "iiwa_link_0_z",
4600-
"iiwa_joint_1_q", "iiwa_joint_2_q",
4601-
"iiwa_joint_3_q", "iiwa_joint_4_q",
4602-
"iiwa_joint_5_q", "iiwa_joint_6_q",
4603-
"iiwa_joint_7_q", "iiwa_joint_1_w",
4604-
"iiwa_joint_2_w", "iiwa_joint_3_w",
4605-
"iiwa_joint_4_w", "iiwa_joint_5_w",
4606-
"iiwa_joint_6_w", "iiwa_joint_7_w",
4601+
"iiwa_joint_1_q", "iiwa_joint_2_q",
4602+
"iiwa_joint_3_q", "iiwa_joint_4_q",
4603+
"iiwa_joint_5_q", "iiwa_joint_6_q",
4604+
"iiwa_joint_7_q", "iiwa_joint_1_w",
4605+
"iiwa_joint_2_w", "iiwa_joint_3_w",
4606+
"iiwa_joint_4_w", "iiwa_joint_5_w",
4607+
"iiwa_joint_6_w", "iiwa_joint_7_w",
46074608
"iiwa_link_0_wx", "iiwa_link_0_wy",
46084609
"iiwa_link_0_wz", "iiwa_link_0_vx",
46094610
"iiwa_link_0_vy", "iiwa_link_0_vz",
4610-
"iiwa_joint_1_w", "iiwa_joint_2_w",
4611-
"iiwa_joint_3_w", "iiwa_joint_4_w",
4612-
"iiwa_joint_5_w", "iiwa_joint_6_w",
4611+
"iiwa_joint_1_w", "iiwa_joint_2_w",
4612+
"iiwa_joint_3_w", "iiwa_joint_4_w",
4613+
"iiwa_joint_5_w", "iiwa_joint_6_w",
46134614
"iiwa_joint_7_w"}));
46144615

46154616
names = plant->GetActuatorNames(iiwa0_instance);

multibody/rational/rational_forward_kinematics.cc

+13-13
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,12 @@ RationalForwardKinematics::RationalForwardKinematics(
6666
// Initialize map_mobilizer_to_s_index_ to -1, where -1 indicates "no s
6767
// variable".
6868
map_mobilizer_to_s_index_ = std::vector<int>(tree.num_mobilizers(), -1);
69-
for (BodyIndex body_index(1); body_index < plant_.num_bodies();
70-
++body_index) {
71-
const internal::BodyTopology& body_topology =
72-
tree.get_topology().get_body(body_index);
69+
for (LinkIndex link_index(1); link_index < plant_.num_bodies();
70+
++link_index) {
71+
const internal::LinkTopology& link_topology =
72+
tree.get_topology().get_link(link_index);
7373
const internal::Mobilizer<double>* mobilizer =
74-
&(tree.get_mobilizer(body_topology.inboard_mobilizer));
74+
&(tree.get_mobilizer(link_topology.inboard_mobilizer));
7575
if (IsRevolute(*mobilizer)) {
7676
const symbolic::Variable s_angle(fmt::format("s[{}]", s_.size()));
7777
s_.push_back(s_angle);
@@ -230,18 +230,18 @@ RationalForwardKinematics::CalcChildBodyPoseAsMultilinearPolynomial(
230230
// X_F'M' = X_FM.inverse()
231231
// X_M'C' = X_PF.inverse()
232232
const internal::MultibodyTree<double>& tree = GetInternalTree(plant_);
233-
const internal::BodyTopology& parent_topology =
234-
tree.get_topology().get_body(parent);
235-
const internal::BodyTopology& child_topology =
236-
tree.get_topology().get_body(child);
233+
const internal::LinkTopology& parent_topology =
234+
tree.get_topology().get_link(parent);
235+
const internal::LinkTopology& child_topology =
236+
tree.get_topology().get_link(child);
237237
internal::MobilizerIndex mobilizer_index;
238238
bool is_order_reversed;
239-
if (parent_topology.parent_body.is_valid() &&
240-
parent_topology.parent_body == child) {
239+
if (parent_topology.parent_link.is_valid() &&
240+
parent_topology.parent_link == child) {
241241
is_order_reversed = true;
242242
mobilizer_index = parent_topology.inboard_mobilizer;
243-
} else if (child_topology.parent_body.is_valid() &&
244-
child_topology.parent_body == parent) {
243+
} else if (child_topology.parent_link.is_valid() &&
244+
child_topology.parent_link == parent) {
245245
is_order_reversed = false;
246246
mobilizer_index = child_topology.inboard_mobilizer;
247247
} else {

multibody/rational/rational_forward_kinematics_internal.cc

+10-10
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,24 @@ std::vector<BodyIndex> FindPath(const MultibodyPlant<double>& plant,
3535
}
3636
};
3737
while (!worklist.empty()) {
38-
BodyIndex current = worklist.front();
38+
LinkIndex current = worklist.front();
3939
worklist.pop();
4040
if (current == end) {
4141
break;
4242
}
43-
const BodyTopology& current_node = topology.get_body(current);
43+
const LinkTopology& current_node = topology.get_link(current);
4444
if (current != world_index()) {
45-
const BodyIndex parent = current_node.parent_body;
45+
const LinkIndex parent = current_node.parent_link;
4646
visit_edge(current, parent);
4747
}
48-
for (BodyIndex child : current_node.child_bodies) {
48+
for (LinkIndex child : current_node.child_links) {
4949
visit_edge(current, child);
5050
}
5151
}
5252

5353
// Retrieve the path in reverse order.
54-
std::vector<BodyIndex> path;
55-
for (BodyIndex current = end; ; current = ancestors.at(current)) {
54+
std::vector<LinkIndex> path;
55+
for (LinkIndex current = end; ; current = ancestors.at(current)) {
5656
path.push_back(current);
5757
if (current == start) {
5858
break;
@@ -71,16 +71,16 @@ std::vector<MobilizerIndex> FindMobilizersOnPath(
7171
mobilizers_on_path.reserve(path.size() - 1);
7272
const MultibodyTree<double>& tree = GetInternalTree(plant);
7373
for (int i = 0; i < static_cast<int>(path.size()) - 1; ++i) {
74-
const BodyTopology& body_topology = tree.get_topology().get_body(path[i]);
75-
if (path[i] != world_index() && body_topology.parent_body == path[i + 1]) {
74+
const LinkTopology& link_topology = tree.get_topology().get_link(path[i]);
75+
if (path[i] != world_index() && link_topology.parent_link == path[i + 1]) {
7676
// path[i] is the child of path[i+1] in MultibodyTreeTopology, they are
7777
// connected by path[i]'s inboard mobilizer.
78-
mobilizers_on_path.push_back(body_topology.inboard_mobilizer);
78+
mobilizers_on_path.push_back(link_topology.inboard_mobilizer);
7979
} else {
8080
// path[i] is the parent of path[i+1] in MultibodyTreeTopology, they are
8181
// connected by path[i+1]'s inboard mobilizer.
8282
mobilizers_on_path.push_back(
83-
tree.get_topology().get_body(path[i + 1]).inboard_mobilizer);
83+
tree.get_topology().get_link(path[i + 1]).inboard_mobilizer);
8484
}
8585
}
8686
return mobilizers_on_path;

multibody/rational/test/rational_forward_kinematics_test_utilities.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ IiwaTest::IiwaTest()
8282
iiwa_link_[i] =
8383
iiwa_->GetBodyByName("iiwa_link_" + std::to_string(i)).index();
8484
iiwa_joint_[i] =
85-
iiwa_tree_.get_topology().get_body(iiwa_link_[i]).inboard_mobilizer;
85+
iiwa_tree_.get_topology().get_link(iiwa_link_[i]).inboard_mobilizer;
8686
}
8787
}
8888

@@ -94,7 +94,7 @@ FinalizedIiwaTest::FinalizedIiwaTest()
9494
iiwa_link_[i] =
9595
iiwa_->GetBodyByName("iiwa_link_" + std::to_string(i)).index();
9696
iiwa_joint_[i] =
97-
iiwa_tree_.get_topology().get_body(iiwa_link_[i]).inboard_mobilizer;
97+
iiwa_tree_.get_topology().get_link(iiwa_link_[i]).inboard_mobilizer;
9898
}
9999
}
100100

0 commit comments

Comments
 (0)