forked from RobotLocomotion/drake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkinematics_vector.h
179 lines (147 loc) · 6.25 KB
/
kinematics_vector.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#pragma once
#include <initializer_list>
#include <optional>
#include <unordered_map>
#include <utility>
#include <vector>
#include "drake/common/drake_assert.h"
#include "drake/common/drake_copyable.h"
#include "drake/common/eigen_types.h"
#include "drake/geometry/geometry_ids.h"
#include "drake/math/rigid_transform.h"
namespace drake {
namespace geometry {
/** A %KinematicsVector is a container class used to report kinematics data for
registered frames and geometries (keyed by unique FrameId/GeometryId values)
to SceneGraph where the set of keys (FrameId/GeometryId) is usually constant
and the values (kinematics data) are varying. It is an internal class and one
should never interact with it directly. The template aliases FramePoseVector
and GeometryConfigurationVector that instantiate %KinematicsVector should be
used instead.
<!--
TODO(SeanCurtis-TRI): The FrameVelocityVector and FrameAccelerationVector
are still to come.
-->
```
template <typename T>
class MySystem : public LeafSystem<T> {
public:
MySystem() {
...
this->DeclareAbstractOutputPort(
&AllocInConstructorSystem::CalcFramePoseOutput);
...
}
private:
void CalcFramePoseOutput(const Context<T>& context,
geometry::FramePoseVector<T>* poses) const {
poses->clear();
for (int i = 0; i < static_cast<int>(frame_ids_.size()); ++i) {
poses->set_value(frame_ids_[i], poses_[i]);
}
}
std::vector<FrameId> frame_ids_;
std::vector<RigidTransform<T>> poses_;
};
```
If a System only ever emits a single frame/geometry (or small-constant-number
of frames/geometries), then there's a shorter alternative way to write a Calc
method, using an initializer_list:
```
void CalcFramePoseOutput(const Context<T>& context,
geometry::FramePoseVector<T>* poses) const {
const RigidTransform<T>& pose = ...;
*poses = {{frame_id_, pose}};
}
```
N.B. When the systems framework calls the `Calc` method, the value pointed to
by `poses` is in an unspecified state. The implementation of `Calc` must
always ensure that `poses` contains the correct value upon return, no matter
what value it started with. The easy ways to do this are to call either
`poses->clear()` or the assignment operator `*poses = ...`.
@tparam Id The key used to locate the kinematics data. Can be
FrameId or GeometryId.
@tparam KinematicsValue The underlying data type of the kinematics data (e.g.,
pose, configuration, or velocity).
The FramePoseVector and GeometryConfigurationVector classes are aliases of the
%KinematicsVector instantiated on specific data types (RigidTransform and
VectorX respectively). Each of these data types are templated on Eigen scalars.
All supported combinations of data type and scalar type are already available
to link against in the containing library. No other values for KinematicsValue
are supported.
Currently, the following data types with the following scalar types are
supported:
Alias | Instantiation | Scalar types
-------------------------------------|--------------------------------------------------|-------------
FramePoseVector<Scalar> | KinematicsVector<FrameId,RigidTransform<Scalar>> | double/AutoDiffXd/Expression
GeometryConfigurationVector<Scalar> | KinematicsVector<GeometryId, VectorX<Scalar>> | double/AutoDiffXd/Expression
*/
template <class Id, class KinematicsValue>
class KinematicsVector {
public:
DRAKE_DEFAULT_COPY_AND_MOVE_AND_ASSIGN(KinematicsVector)
/** Initializes the vector with no data .*/
KinematicsVector();
/** Initializes the vector using the given the keys and their corresponding
kinematics values. */
KinematicsVector(
std::initializer_list<std::pair<const Id, KinematicsValue>> init);
~KinematicsVector();
/** Resets the vector to the given keys and kinematics values .*/
KinematicsVector& operator=(
std::initializer_list<std::pair<const Id, KinematicsValue>> init);
/** Clears all values, resetting the size to zero. */
void clear();
/** Sets the kinematics `value` for the given `id`. */
void set_value(Id id, const KinematicsValue& value);
/** Returns number of ids(). */
int size() const {
DRAKE_ASSERT_VOID(CheckInvariants());
return size_;
}
/** Returns the value associated with the given `id`.
@throws std::exception if `id` is not in the specified set of ids. */
const KinematicsValue& value(Id id) const;
/** Reports true if the given id is a member of this data. */
bool has_id(Id id) const;
/** Provides a range object for all of the existing ids in the vector.
This is intended to be used as:
@code
for (Id id : this_vector.ids()) {
...
// Obtain the KinematicsValue of an id by `this_vector.value(id)`
...
}
@endcode
*/
std::vector<Id> ids() const;
private:
void CheckInvariants() const;
// Mapping from id to its corresponding kinematics value. If the map's
// optional value is nullopt, we treat it as if the map key were absent
// instead. We do this in order to avoid reallocating map nodes as we
// repeatedly clear() and then re-set_value() the same IDs over and over
// again.
// TODO(jwnimmer-tri) A better way to avoid map node allocations would be to
// replace this unordered_map with a flat_hash_map (where the entire storage
// is a single heap slab); in that case, the complicated implementation in
// the cc file would become simplified.
std::unordered_map<Id, std::optional<KinematicsValue>> values_;
// The count of non-nullopt items in values_. We could recompute this from
// values_, but we store it separately so that size() is still constant-time.
int size_{0};
};
/** Class for communicating _pose_ information to SceneGraph for registered
frames.
@tparam_default_scalar
*/
template <typename T>
using FramePoseVector = KinematicsVector<FrameId, math::RigidTransform<T>>;
/** Class for communicating _configuration_ information to SceneGraph for
registered deformable geometries.
@tparam_default_scalar
*/
template <typename T>
using GeometryConfigurationVector = KinematicsVector<GeometryId, VectorX<T>>;
} // namespace geometry
} // namespace drake