Skip to content

Commit 1119fb5

Browse files
author
Chien-Liang Fok
committed
Adds ability to clone RigidBodyTree.
1 parent 27ebd4b commit 1119fb5

11 files changed

+620
-4
lines changed

drake/multibody/BUILD

+31
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@ drake_cc_library(
9898
],
9999
)
100100

101+
drake_cc_library(
102+
name = "rigid_body_tree_compare_to_clone",
103+
srcs = ["test/rigid_body_tree/rigid_body_tree_compare_to_clone.cc"],
104+
hdrs = ["test/rigid_body_tree/rigid_body_tree_compare_to_clone.h"],
105+
linkstatic = 1,
106+
deps = [
107+
":rigid_body_tree",
108+
],
109+
)
110+
101111
# TODO(jwnimmer-tri) This is just some random program. Do we want to keep it?
102112
drake_cc_binary(
103113
name = "benchmark_rigid_body_tree",
@@ -181,6 +191,27 @@ drake_cc_googletest(
181191
],
182192
)
183193

194+
drake_cc_googletest(
195+
name = "rigid_body_tree_clone_test",
196+
srcs = ["test/rigid_body_tree/rigid_body_tree_clone_test.cc"],
197+
data = [
198+
":test_models",
199+
"//drake/automotive:models",
200+
"//drake/examples/Atlas:models",
201+
"//drake/examples/Pendulum:models",
202+
"//drake/examples/Valkyrie:models",
203+
],
204+
deps = [
205+
":rigid_body_tree_compare_to_clone",
206+
"//drake/common:eigen_matrix_compare",
207+
"//drake/multibody/parsers",
208+
"//drake/multibody/rigid_body_plant",
209+
"//drake/systems/analysis",
210+
"//drake/systems/primitives:constant_vector_source",
211+
"//drake/systems/primitives:signal_logger",
212+
],
213+
)
214+
184215
drake_cc_googletest(
185216
name = "rigid_body_tree_creation_test",
186217
srcs = ["test/rigid_body_tree/rigid_body_tree_creation_test.cc"],

drake/multibody/rigid_body_actuator.cc

+46
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,
@@ -10,3 +15,44 @@ RigidBodyActuator::RigidBodyActuator(const std::string& name,
1015
reduction_(reduction),
1116
effort_limit_min_(effort_limit_min),
1217
effort_limit_max_(effort_limit_max) {}
18+
19+
bool RigidBodyActuator::CompareToClone(const RigidBodyActuator& other) const {
20+
if (this->name_ != other.name_) {
21+
drake::log()->debug(
22+
"RigidBodyActuator::CompareToClone(): Names mismatch:\n"
23+
" - this: {}\n"
24+
" - other: {}",
25+
this->name_, other.name_);
26+
return false;
27+
}
28+
if (!this->body_->CompareToClone(*other.body_)) {
29+
drake::log()->debug(
30+
"RigidBodyActuator::CompareToClone(): Bodies mismatch.");
31+
return false;
32+
}
33+
if (this->reduction_ != other.reduction_) {
34+
drake::log()->debug(
35+
"RigidBodyActuator::CompareToClone(): Reduction mismatch:\n"
36+
" - this: {}\n"
37+
" - other: {}",
38+
this->reduction_, other.reduction_);
39+
return false;
40+
}
41+
if (this->effort_limit_min_ != other.effort_limit_min_) {
42+
drake::log()->debug(
43+
"RigidBodyActuator::CompareToClone(): Minimum effort limits mismatch:\n"
44+
" - this: {}\n"
45+
" - other: {}",
46+
this->effort_limit_min_, other.effort_limit_min_);
47+
return false;
48+
}
49+
if (this->effort_limit_max_ != other.effort_limit_max_) {
50+
drake::log()->debug(
51+
"RigidBodyActuator::CompareToClone(): Maximum effort limits mismatch:\n"
52+
" - this: {}\n"
53+
" - other: {}",
54+
this->effort_limit_max_, other.effort_limit_max_);
55+
return false;
56+
}
57+
return true;
58+
}

drake/multibody/rigid_body_actuator.h

+8
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ class RigidBodyActuator {
3636
double effort_limit_min = -std::numeric_limits<double>::infinity(),
3737
double effort_limit_max = std::numeric_limits<double>::infinity());
3838

39+
/**
40+
* Compares this %RigidBodyActuator with a clone. Since this method is
41+
* intended to compare a clone, an *exact* match is performed. This method
42+
* will only return `true` if the provided `other` %RigidBodyActuator is
43+
* exactly the same as this %RigidBodyActuator.
44+
*/
45+
bool CompareToClone(const RigidBodyActuator& other) const;
46+
3947
const std::string name_;
4048
const RigidBody<double>* const body_;
4149
const double reduction_;

drake/multibody/rigid_body_loop.cc

+23
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,36 @@
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,
78
std::shared_ptr<RigidBodyFrame<T>> frameB,
89
const Eigen::Vector3d& axis)
910
: frameA_(frameA), frameB_(frameB), axis_(axis) {}
1011

12+
template <>
13+
bool RigidBodyLoop<double>::CompareToClone(const RigidBodyLoop<double>& other)
14+
const {
15+
if (!this->frameA_->CompareToClone(*other.frameA_)) {
16+
drake::log()->debug("RigidBodyLoop::CompareToClone(): FrameA mismatch.");
17+
return false;
18+
}
19+
if (!this->frameB_->CompareToClone(*other.frameB_)) {
20+
drake::log()->debug("RigidBodyLoop::CompareToClone(): FrameB mismatch.");
21+
return false;
22+
}
23+
if (this->axis_ != other.axis_) {
24+
drake::log()->debug(
25+
"RigidBodyLoop::CompareToClone(): Axes mismatch:\n"
26+
" - this: {}\n"
27+
" - other: {}",
28+
this->axis_.transpose(), other.axis_.transpose());
29+
return false;
30+
}
31+
return true;
32+
}
33+
1134
std::ostream& operator<<(std::ostream& os, const RigidBodyLoop<double>& obj) {
1235
os << "loop connects pt "
1336
<< obj.frameA_->get_transform_to_body().matrix().topRightCorner(3, 1)

drake/multibody/rigid_body_loop.h

+9
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>
@@ -44,6 +45,14 @@ class RigidBodyLoop {
4445
std::shared_ptr<RigidBodyFrame<T>> frameB,
4546
const Eigen::Vector3d& axis);
4647

48+
/**
49+
* Compares this %RigidBodyLoop with a clone. Since this method is intended to
50+
* compare a clone, an *exact* match is performed. This method will only
51+
* return `true` if the provided `other` %RigidBodyLoop is exactly the same as
52+
* this %RigidBodyLoop.
53+
*/
54+
bool CompareToClone(const RigidBodyLoop<double>& other) const;
55+
4756
const std::shared_ptr<RigidBodyFrame<T>> frameA_, frameB_;
4857
const Eigen::Vector3d axis_;
4958

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
@@ -1268,17 +1283,28 @@ class RigidBodyTree {
12681283
/**
12691284
* Returns the body at index @p body_index. Parameter @p body_index must be
12701285
* between zero and the number of bodies in this tree, which can be determined
1271-
* by calling RigidBodyTree::get_num_bodies(). Note that the body at
1272-
* index 0 represents the world.
1286+
* by calling RigidBodyTree::get_num_bodies().
12731287
*/
12741288
const RigidBody<T>& get_body(int body_index) const;
12751289

1290+
/**
1291+
* Returns the body at index @p body_index. Parameter @p body_index must be
1292+
* between zero and the number of bodies in this tree, which can be determined
1293+
* by calling RigidBodyTree::get_num_bodies().
1294+
*/
1295+
RigidBody<T>* get_mutable_body(int body_index);
1296+
12761297
/**
12771298
* Returns the number of bodies in this tree. This includes the one body that
12781299
* represents the world.
12791300
*/
12801301
int get_num_bodies() const;
12811302

1303+
/**
1304+
* Returns the number of frames in this tree.
1305+
*/
1306+
int get_num_frames() const;
1307+
12821308
#ifndef SWIG
12831309
DRAKE_DEPRECATED("Please use get_num_bodies().")
12841310
#endif
@@ -1458,6 +1484,12 @@ class RigidBodyTree {
14581484
*/
14591485
int get_num_actuators() const;
14601486

1487+
/**
1488+
* Returns whether this %RigidBodyTree is initialized. It is initialized after
1489+
* compile() is called.
1490+
*/
1491+
bool initialized() const { return initialized_; }
1492+
14611493
public:
14621494
Eigen::VectorXd joint_limit_min;
14631495
Eigen::VectorXd joint_limit_max;

drake/multibody/test/rigid_body_tree/CMakeLists.txt

+13
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,21 @@ if(Bullet_FOUND)
2323
target_link_libraries(rigid_body_collision_clique_test
2424
drakeMultibodyParsers
2525
drakeRBM)
26+
27+
drake_add_cc_test(NAME rigid_body_tree_clone_test SIZE small)
28+
target_link_libraries(rigid_body_tree_clone_test
29+
drakeMultibodyParsers
30+
drakeRigidBodyPlant
31+
drakeRigidBodyTreeCompareToClone
32+
drakeSystemAnalysis
33+
drakeSystemPrimitives)
2634
endif()
2735

36+
add_library_with_exports(LIB_NAME drakeRigidBodyTreeCompareToClone SOURCE_FILES
37+
rigid_body_tree_compare_to_clone.cc)
38+
target_link_libraries(drakeRigidBodyTreeCompareToClone
39+
drakeRBM)
40+
2841
drake_add_cc_test(NAME rigid_body_tree_creation_test SIZE medium)
2942
target_link_libraries(rigid_body_tree_creation_test
3043
drakeMultibodyParsers

0 commit comments

Comments
 (0)