forked from RobotLocomotion/drake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
contact_results.h
132 lines (109 loc) · 4.83 KB
/
contact_results.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#pragma once
#include <memory>
#include <utility>
#include <variant>
#include <vector>
#include "drake/common/copyable_unique_ptr.h"
#include "drake/common/default_scalars.h"
#include "drake/common/drake_copyable.h"
#include "drake/common/eigen_types.h"
#include "drake/multibody/plant/hydroelastic_contact_info.h"
#include "drake/multibody/plant/point_pair_contact_info.h"
namespace drake {
namespace multibody {
/**
A container class storing the contact results information for each contact
pair for a given state of the simulation. Note that copying this data structure
is expensive when `num_hydroelastic_contacts() > 0` because a deep copy is
performed.
@tparam_default_scalar
*/
template <typename T>
class ContactResults {
public:
ContactResults();
ContactResults(const ContactResults&);
ContactResults(ContactResults&&) = default;
ContactResults& operator=(const ContactResults&);
ContactResults& operator=(ContactResults&&) = default;
/** Returns the number of point pair contacts. */
int num_point_pair_contacts() const {
return static_cast<int>(point_pairs_info_.size());
}
/** Returns the number of hydroelastic contacts. */
int num_hydroelastic_contacts() const;
/** Retrieves the ith PointPairContactInfo instance. The input index i
must be in the range [0, `num_point_pair_contacts()` - 1] or this method
aborts. */
const PointPairContactInfo<T>& point_pair_contact_info(int i) const;
/** Retrieves the ith HydroelasticContactInfo instance. The input index i
must be in the range [0, `num_hydroelastic_contacts()` - 1] or this
method aborts. */
const HydroelasticContactInfo<T>& hydroelastic_contact_info(int i) const;
// The following methods should only be called by MultibodyPlant and testing
// fixtures and are undocumented rather than being made private with friends.
#ifndef DRAKE_DOXYGEN_CXX
/* Clears the set of contact information for when the old data becomes
invalid. */
void Clear();
/* Add a new contact pair result to `this`. */
void AddContactInfo(const PointPairContactInfo<T>& point_pair_info) {
point_pairs_info_.push_back(point_pair_info);
}
/* Add a new hydroelastic contact to `this`, assuming that `this` is not the
result of a copy operation (AddContactInfo() asserts that is the case). The
pointer must remain valid for the lifetime of this object. */
void AddContactInfo(
const HydroelasticContactInfo<T>* hydroelastic_contact_info);
#endif
private:
enum OwnershipMode { kAliasedPointers, kOwnsCopies };
OwnershipMode hydroelastic_contact_vector_ownership_mode() const {
return std::holds_alternative<
std::vector<const HydroelasticContactInfo<T>*>>(
hydroelastic_contact_info_)
? kAliasedPointers
: kOwnsCopies;
}
const std::vector<const HydroelasticContactInfo<T>*>&
hydroelastic_contact_vector_of_pointers() const {
return std::get<std::vector<const HydroelasticContactInfo<T>*>>(
hydroelastic_contact_info_);
}
std::vector<const HydroelasticContactInfo<T>*>&
hydroelastic_contact_vector_of_pointers() {
return std::get<std::vector<const HydroelasticContactInfo<T>*>>(
hydroelastic_contact_info_);
}
const std::vector<std::unique_ptr<HydroelasticContactInfo<T>>>&
hydroelastic_contact_vector_of_unique_ptrs() const {
return std::get<std::vector<std::unique_ptr<HydroelasticContactInfo<T>>>>(
hydroelastic_contact_info_);
}
std::vector<std::unique_ptr<HydroelasticContactInfo<T>>>&
hydroelastic_contact_vector_of_unique_ptrs() {
return std::get<std::vector<std::unique_ptr<HydroelasticContactInfo<T>>>>(
hydroelastic_contact_info_);
}
std::vector<PointPairContactInfo<T>> point_pairs_info_;
/* We use a variant type to keep from copying already owned data (from a
cache), i.e., the HydroelasticContactInfo, into this data structure, if
possible. By default, the variant stores the first type, i.e.,
std::vector<const HydroelasticContactInfo<T>*>. If this data structure is
copied, however, the variant changes to instead store the second type, a
vector of unique pointers. In that case, all of the underlying
HydroelasticContactInfo objects are copied and
AddContactInfo(const HydroelasticContactInfo*) can no longer be called on the
copy (see assertion in AddContactInfo).
Note that we jump through these hoops because storing ContactResults into
a cache entry requires that it be placed into a Value<ContactResults>, which
in turn requires that ContactResults be copyable.
*/
std::variant<std::vector<const HydroelasticContactInfo<T>*>,
std::vector<std::unique_ptr<HydroelasticContactInfo<T>>>>
hydroelastic_contact_info_;
};
} // namespace multibody
} // namespace drake
DRAKE_DECLARE_CLASS_TEMPLATE_INSTANTIATIONS_ON_DEFAULT_SCALARS(
class ::drake::multibody::ContactResults)