Skip to content

Commit f518ef3

Browse files
author
Chien-Liang Fok
authored
Adds Ability to Clone a RigidBodyTree. (#4958)
* Adds ability to clone RigidBodyTree.
1 parent f678a55 commit f518ef3

15 files changed

+719
-4
lines changed

drake/multibody/BUILD

+53
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,38 @@ drake_cc_library(
9494
],
9595
)
9696

97+
drake_cc_library(
98+
name = "rigid_body_tree_compare_to_clone",
99+
testonly = 1,
100+
srcs = ["test/rigid_body_tree/rigid_body_tree_compare_to_clone.cc"],
101+
hdrs = ["test/rigid_body_tree/rigid_body_tree_compare_to_clone.h"],
102+
deps = [
103+
":rigid_body_actuator_compare_to_clone",
104+
":rigid_body_loop_compare_to_clone",
105+
":rigid_body_tree",
106+
],
107+
)
108+
109+
drake_cc_library(
110+
name = "rigid_body_actuator_compare_to_clone",
111+
testonly = 1,
112+
srcs = ["test/rigid_body_actuator_compare_to_clone.cc"],
113+
hdrs = ["test/rigid_body_actuator_compare_to_clone.h"],
114+
deps = [
115+
":rigid_body_tree",
116+
],
117+
)
118+
119+
drake_cc_library(
120+
name = "rigid_body_loop_compare_to_clone",
121+
testonly = 1,
122+
srcs = ["test/rigid_body_loop_compare_to_clone.cc"],
123+
hdrs = ["test/rigid_body_loop_compare_to_clone.h"],
124+
deps = [
125+
":rigid_body_tree",
126+
],
127+
)
128+
97129
# TODO(jwnimmer-tri) This is just some random program. Do we want to keep it?
98130
drake_cc_binary(
99131
name = "benchmark_rigid_body_tree",
@@ -175,6 +207,27 @@ drake_cc_googletest(
175207
],
176208
)
177209

210+
drake_cc_googletest(
211+
name = "rigid_body_tree_clone_test",
212+
srcs = ["test/rigid_body_tree/rigid_body_tree_clone_test.cc"],
213+
data = [
214+
":test_models",
215+
"//drake/automotive:models",
216+
"//drake/examples/Atlas:models",
217+
"//drake/examples/Pendulum:models",
218+
"//drake/examples/Valkyrie:models",
219+
],
220+
deps = [
221+
":rigid_body_tree_compare_to_clone",
222+
"//drake/common:eigen_matrix_compare",
223+
"//drake/multibody/parsers",
224+
"//drake/multibody/rigid_body_plant",
225+
"//drake/systems/analysis",
226+
"//drake/systems/primitives:constant_vector_source",
227+
"//drake/systems/primitives:signal_logger",
228+
],
229+
)
230+
178231
drake_cc_googletest(
179232
name = "rigid_body_tree_creation_test",
180233
srcs = ["test/rigid_body_tree/rigid_body_tree_creation_test.cc"],

drake/multibody/rigid_body_actuator.cc

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
#include "drake/multibody/rigid_body_actuator.h"
22

3+
#include <string>
4+
5+
#include "drake/common/text_logging.h"
6+
#include "drake/multibody/rigid_body.h"
7+
38
RigidBodyActuator::RigidBodyActuator(const std::string& name,
49
const RigidBody<double>* body,
510
double reduction,

drake/multibody/rigid_body_loop.cc

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "drake/multibody/rigid_body_loop.h"
22

33
#include "drake/common/eigen_autodiff_types.h"
4+
#include "drake/common/text_logging.h"
45

56
template <typename T>
67
RigidBodyLoop<T>::RigidBodyLoop(std::shared_ptr<RigidBodyFrame<T>> frameA,

drake/multibody/rigid_body_loop.h

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include <iostream>
34
#include <memory>
45

56
#include <Eigen/Dense>

drake/multibody/rigid_body_tree.cc

+98-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "drake/common/constants.h"
1414
#include "drake/common/eigen_autodiff_types.h"
1515
#include "drake/common/eigen_types.h"
16+
#include "drake/common/text_logging.h"
1617
#include "drake/math/autodiff.h"
1718
#include "drake/math/autodiff_gradient.h"
1819
#include "drake/math/gradient.h"
@@ -124,6 +125,91 @@ RigidBodyTree<T>::RigidBodyTree()
124125
template <typename T>
125126
RigidBodyTree<T>::~RigidBodyTree() {}
126127

128+
// For an explanation of why these SWIG preprocessor commands are needed, see
129+
// the comment immediately above the declaration of RigidBodyTree::Clone() in
130+
// rigid_body_tree.h.
131+
#ifndef SWIG
132+
template <>
133+
unique_ptr<RigidBodyTree<double>> RigidBodyTree<double>::Clone() const {
134+
auto clone = make_unique<RigidBodyTree<double>>();
135+
// The following is necessary to remove the world link from the clone. The
136+
// world link will be re-added when the bodies are cloned below.
137+
clone->bodies.clear();
138+
139+
clone->joint_limit_min = this->joint_limit_min;
140+
clone->joint_limit_max = this->joint_limit_max;
141+
clone->a_grav = this->a_grav;
142+
clone->B = this->B;
143+
clone->num_positions_ = this->num_positions_;
144+
clone->num_velocities_ = this->num_velocities_;
145+
clone->num_model_instances_ = this->num_model_instances_;
146+
clone->initialized_ = this->initialized_;
147+
148+
// Clones the rigid bodies.
149+
for (const auto& body : bodies) {
150+
clone->bodies.push_back(body->Clone());
151+
}
152+
153+
// Clones the joints and adds them to the cloned RigidBody objects.
154+
for (const auto& original_body : bodies) {
155+
const int body_index = original_body->get_body_index();
156+
if (body_index == RigidBodyTreeConstants::kWorldBodyIndex) {
157+
continue;
158+
}
159+
160+
RigidBody<double>* cloned_body = clone->get_mutable_body(body_index);
161+
DRAKE_DEMAND(cloned_body != nullptr);
162+
DRAKE_DEMAND(cloned_body->get_body_index() == body_index);
163+
164+
const RigidBody<double>* original_body_parent = original_body->get_parent();
165+
DRAKE_DEMAND(original_body_parent != nullptr);
166+
167+
const int parent_body_index = original_body_parent->get_body_index();
168+
169+
RigidBody<double>* cloned_body_parent =
170+
clone->get_mutable_body(parent_body_index);
171+
DRAKE_DEMAND(cloned_body_parent != nullptr);
172+
173+
cloned_body->add_joint(cloned_body_parent,
174+
original_body->getJoint().Clone());
175+
}
176+
177+
for (const auto& original_frame : frames) {
178+
const RigidBody<double>& original_frame_body =
179+
original_frame->get_rigid_body();
180+
const int cloned_frame_body_index =
181+
clone->FindBodyIndex(original_frame_body.get_name(),
182+
original_frame_body.get_model_instance_id());
183+
RigidBody<double>* cloned_frame_body =
184+
clone->get_mutable_body(cloned_frame_body_index);
185+
DRAKE_DEMAND(cloned_frame_body != nullptr);
186+
std::shared_ptr<RigidBodyFrame<double>> cloned_frame =
187+
original_frame->Clone(cloned_frame_body);
188+
clone->frames.push_back(cloned_frame);
189+
}
190+
191+
for (const auto& actuator : actuators) {
192+
const RigidBody<double>& cloned_body =
193+
clone->get_body(actuator.body_->get_body_index());
194+
clone->actuators.emplace_back(
195+
actuator.name_, &cloned_body, actuator.reduction_,
196+
actuator.effort_limit_min_, actuator.effort_limit_max_);
197+
}
198+
199+
for (const auto& loop : loops) {
200+
std::shared_ptr<RigidBodyFrame<double>> frame_a =
201+
clone->findFrame(loop.frameA_->get_name(),
202+
loop.frameA_->get_model_instance_id());
203+
std::shared_ptr<RigidBodyFrame<double>> frame_b =
204+
clone->findFrame(loop.frameB_->get_name(),
205+
loop.frameB_->get_model_instance_id());
206+
clone->loops.emplace_back(frame_a, frame_b, loop.axis_);
207+
}
208+
209+
return clone;
210+
}
211+
#endif
212+
127213
template <typename T>
128214
bool RigidBodyTree<T>::transformCollisionFrame(
129215
RigidBody<T>* body, const Eigen::Isometry3d& displace_transform) {
@@ -2760,11 +2846,16 @@ int RigidBodyTree<T>::FindIndexOfChildBodyOfJoint(const std::string& joint_name,
27602846

27612847
template <typename T>
27622848
const RigidBody<T>& RigidBodyTree<T>::get_body(int body_index) const {
2763-
DRAKE_DEMAND(body_index >= 0 &&
2764-
body_index < get_num_bodies());
2849+
DRAKE_DEMAND(body_index >= 0 && body_index < get_num_bodies());
27652850
return *bodies[body_index].get();
27662851
}
27672852

2853+
template <typename T>
2854+
RigidBody<T>* RigidBodyTree<T>::get_mutable_body(int body_index) {
2855+
DRAKE_DEMAND(body_index >= 0 && body_index < get_num_bodies());
2856+
return bodies[body_index].get();
2857+
}
2858+
27682859
template <typename T>
27692860
int RigidBodyTree<T>::get_num_bodies() const {
27702861
return static_cast<int>(bodies.size());
@@ -2776,6 +2867,11 @@ int RigidBodyTree<T>::get_number_of_bodies() const {
27762867
return get_num_bodies();
27772868
}
27782869

2870+
template <typename T>
2871+
int RigidBodyTree<T>::get_num_frames() const {
2872+
return static_cast<int>(frames.size());
2873+
}
2874+
27792875
// TODO(liang.fok) Remove this method prior to Release 1.0.
27802876
template <typename T>
27812877
RigidBody<T>* RigidBodyTree<T>::findJoint(const std::string& joint_name,

drake/multibody/rigid_body_tree.h

+34-2
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,21 @@ class RigidBodyTree {
113113

114114
virtual ~RigidBodyTree();
115115

116+
// The following preprocessor condition is necessary because wrapping method
117+
// Clone() in SWIG causes the following build error to occur:
118+
//
119+
// "call to implicitly-deleted copy constructor"
120+
//
121+
// Unfortunately, adding "%ignore RigidBodyTree<double>::Clone()" to
122+
// drake-distro/drake/bindings/swig/rbtree.i does not work.
123+
#ifndef SWIG
124+
/**
125+
* Returns a deep clone of this RigidBodyTree<double>. Currently, everything
126+
* *except* for collision and visual elements are cloned.
127+
*/
128+
std::unique_ptr<RigidBodyTree<double>> Clone() const;
129+
#endif
130+
116131
/**
117132
* Adds a new model instance to this `RigidBodyTree`. The model instance is
118133
* identified by a unique model instance ID, which is the return value of
@@ -1250,17 +1265,28 @@ class RigidBodyTree {
12501265
/**
12511266
* Returns the body at index @p body_index. Parameter @p body_index must be
12521267
* between zero and the number of bodies in this tree, which can be determined
1253-
* by calling RigidBodyTree::get_num_bodies(). Note that the body at
1254-
* index 0 represents the world.
1268+
* by calling RigidBodyTree::get_num_bodies().
12551269
*/
12561270
const RigidBody<T>& get_body(int body_index) const;
12571271

1272+
/**
1273+
* Returns the body at index @p body_index. Parameter @p body_index must be
1274+
* between zero and the number of bodies in this tree, which can be determined
1275+
* by calling RigidBodyTree::get_num_bodies().
1276+
*/
1277+
RigidBody<T>* get_mutable_body(int body_index);
1278+
12581279
/**
12591280
* Returns the number of bodies in this tree. This includes the one body that
12601281
* represents the world.
12611282
*/
12621283
int get_num_bodies() const;
12631284

1285+
/**
1286+
* Returns the number of frames in this tree.
1287+
*/
1288+
int get_num_frames() const;
1289+
12641290
DRAKE_DEPRECATED("Please use get_num_bodies().")
12651291
int get_number_of_bodies() const;
12661292

@@ -1434,6 +1460,12 @@ class RigidBodyTree {
14341460
*/
14351461
int get_num_actuators() const;
14361462

1463+
/**
1464+
* Returns whether this %RigidBodyTree is initialized. It is initialized after
1465+
* compile() is called.
1466+
*/
1467+
bool initialized() const { return initialized_; }
1468+
14371469
public:
14381470
Eigen::VectorXd joint_limit_min;
14391471
Eigen::VectorXd joint_limit_max;

drake/multibody/test/CMakeLists.txt

+8
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,12 @@ if (snopt_FOUND)
5050
add_ik_gtest(test_ik_traj)
5151
endif ()
5252

53+
add_library_with_exports(LIB_NAME drakeRigidBodyActuatorCompareToClone
54+
SOURCE_FILES rigid_body_actuator_compare_to_clone.cc)
55+
target_link_libraries(drakeRigidBodyActuatorCompareToClone drakeRBM)
56+
57+
add_library_with_exports(LIB_NAME drakeRigidBodyLoopCompareToClone
58+
SOURCE_FILES rigid_body_loop_compare_to_clone.cc)
59+
target_link_libraries(drakeRigidBodyLoopCompareToClone drakeRBM)
60+
5361
add_subdirectory(rigid_body_tree)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include "drake/multibody/test/rigid_body_actuator_compare_to_clone.h"
2+
3+
#include <memory>
4+
5+
#include "drake/common/text_logging.h"
6+
#include "drake/multibody/rigid_body.h"
7+
8+
namespace drake {
9+
namespace multibody {
10+
namespace test {
11+
namespace rigid_body_actuator {
12+
13+
bool CompareToClone(const RigidBodyActuator& original,
14+
const RigidBodyActuator& clone) {
15+
if (original.name_ != clone.name_) {
16+
drake::log()->debug(
17+
"CompareToClone(RigidBodyActuator): Names mismatch:\n"
18+
" - original: {}\n"
19+
" - clone: {}",
20+
original.name_, clone.name_);
21+
return false;
22+
}
23+
if (!original.body_->CompareToClone(*clone.body_)) {
24+
drake::log()->debug(
25+
"CompareToClone(RigidBodyActuator): Bodies mismatch.");
26+
return false;
27+
}
28+
if (original.reduction_ != clone.reduction_) {
29+
drake::log()->debug(
30+
"CompareToClone(RigidBodyActuator): Reduction mismatch:\n"
31+
" - original: {}\n"
32+
" - clone: {}",
33+
original.reduction_, clone.reduction_);
34+
return false;
35+
}
36+
if (original.effort_limit_min_ != clone.effort_limit_min_) {
37+
drake::log()->debug(
38+
"CompareToClone(RigidBodyActuator): Minimum effort limits mismatch:\n"
39+
" - original: {}\n"
40+
" - clone: {}",
41+
original.effort_limit_min_, clone.effort_limit_min_);
42+
return false;
43+
}
44+
if (original.effort_limit_max_ != clone.effort_limit_max_) {
45+
drake::log()->debug(
46+
"CompareToClone(RigidBodyActuator): Maximum effort limits mismatch:\n"
47+
" - original: {}\n"
48+
" - clone: {}",
49+
original.effort_limit_max_, clone.effort_limit_max_);
50+
return false;
51+
}
52+
return true;
53+
}
54+
55+
} // namespace rigid_body_actuator
56+
} // namespace test
57+
} // namespace multibody
58+
} // namespace drake
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
3+
#include "drake/multibody/rigid_body_actuator.h"
4+
5+
namespace drake {
6+
namespace multibody {
7+
namespace test {
8+
namespace rigid_body_actuator {
9+
10+
/**
11+
* This method compares the provided @p original and @p clone RigidBodyActuator
12+
* objects, which are clones, and verifies their correctness. Since this method
13+
* is intended to compare a clone, an *exact* match is performed. This method
14+
* will only return `true` if the provided %RigidBodyActuator is exactly the
15+
* same as its clone.
16+
*/
17+
bool CompareToClone(const RigidBodyActuator& original,
18+
const RigidBodyActuator& clone);
19+
20+
} // namespace rigid_body_actuator
21+
} // namespace test
22+
} // namespace multibody
23+
} // namespace drake

0 commit comments

Comments
 (0)