-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
transform.h
228 lines (175 loc) · 6.44 KB
/
transform.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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#pragma once
#include <optional>
#include <string>
#include "drake/common/name_value.h"
#include "drake/common/schema/rotation.h"
#include "drake/common/schema/stochastic.h"
#include "drake/math/rigid_transform.h"
namespace drake {
namespace schema {
/** @defgroup schema_transform Configuring transforms
@ingroup stochastic_systems
@{
This page describes how to use classes such as schema::Rotation and
schema::Transform to denote stochastic quantities, as a bridge between loading
a scenario specification and populating the corresponding math::RigidTransform
quantities.
The broader concepts are discussed at @ref schema_stochastic. Here, we cover
details related to rotations and transforms in particular.
We'll explain uses of schema::Rotation and schema::Transform using their
matching YAML syntax as parsed by yaml::YamlReadArchive.
# Rotations
This shows the syntax for a schema::Rotation.
When no details are given, the default rotation is the identity matrix:
```
rotation: {}
```
For clarity, you may also specify `Identity` variant tag explicitly.
This version and the above version have exactly the same effect:
```
rotation: !Identity {}
```
To specify roll, pitch, yaw angles using math::RollPitchYaw conventions, use
`Rpy` as the variant tag:
```
rotation: !Rpy
deg: [10.0, 20.0, 30.0]
```
To specify a rotation angle and axis in the sense of Eigen::AngleAxis, use
`AngleAxis` as the variant tag:
```
rotation: !AngleAxis
angle_deg: 10.0
axis: [0.0, 1.0, 0.0]
```
You may also use YAML's flow style to fit everything onto a single line.
These one-line spellings are the equivalent to those above.
```
rotation: !Rpy { deg: [10.0, 20.0, 30.0] }
```
```
rotation: !AngleAxis { angle_deg: 10.0, axis: [0.0, 1.0, 0.0] }
```
## Stochastic Rotations
To specify a stochastic rotation sampled from a uniform distribution over
SO(3):
```
rotation: !Uniform {}
```
The other available representations also accept stochastic distributions for
their values:
```
rotation: !Rpy
deg: !UniformVector
min: [ 0.0, 10.0, 20.0]
max: [30.0, 40.0, 50.0]
```
Or:
```
rotation: !AngleAxis
angle_deg: !Uniform
min: 8.0
max: 10.0
axis: !UniformVector
min: [0.0, 0.9, 0.0]
max: [0.1, 1.0, 0.0]
```
For an explanation of `!Uniform`, `!UniformVector`, and other available options
(%Gaussian, etc.) for scalar and vector quantities, see @ref schema_stochastic.
# Transforms
This shows the syntax for a schema::Transform. A transform is merely a
translation and rotation, optionally with a some given string as a base_frame.
```
transform:
translation: [1.0, 2.0, 3.0]
rotation: !Rpy { deg: [10.0, 20.0, 30.0] }
```
Or:
```
transform:
base_frame: foo
translation: [0.0, 0.0, 1.0]
rotation: !Identity {}
```
## Stochastic Transforms
Either or both of the rotational or translation component can be stochastic:
```
transform:
translation: !UniformVector
min: [-1.0, -1.0, -1.0]
max: [ 1.0, 1.0, 1.0]
rotation: !Uniform {}
```
For an explanation of `!Uniform`, `!UniformVector`, and other available options
(%Gaussian, etc.) for scalar and vector quantities, see @ref schema_stochastic.
@} */
/// A specification for a 3d rotation and translation, optionally with respect
/// to a base frame.
///
/// For an overview of configuring stochastic transforms, see
/// @ref schema_transform and @ref schema_stochastic.
///
/// See @ref serialize_tips for implementation details, especially the
/// unusually public member fields.
class Transform {
public:
DRAKE_DEFAULT_COPY_AND_MOVE_AND_ASSIGN(Transform)
/// Constructs the Identity transform.
Transform() = default;
/// Constructs the given transform.
explicit Transform(const math::RigidTransformd&);
/// Sets the rotation field to the given deterministic RPY, in degrees.
void set_rotation_rpy_deg(const Eigen::Vector3d& rpy_deg) {
rotation.set_rpy_deg(rpy_deg);
}
/// Returns true iff this is fully deterministic.
bool IsDeterministic() const;
/// If this is deterministic, retrieves its value.
/// @throws exception if this is not fully deterministic.
math::RigidTransformd GetDeterministicValue() const;
/// Returns the symbolic form of this rotation. If this is deterministic,
/// the result will contain no variables. If this is random, the result will
/// contain one or more random variables, based on the distributions in use.
math::RigidTransform<symbolic::Expression> ToSymbolic() const;
/// Returns the mean of this rotation. If this is deterministic, the result
/// is the same as GetDeterministicValue. If this is random, note that the
/// mean here is simply defined as setting all of the random variables
/// individually to their mean. Various other measures of the resulting
/// RigidTransform (e.g., the distribution of one of the Euler angles) may
/// not necessarily match that measure on the returned value.
math::RigidTransformd Mean() const;
/// Samples this Transform. If this is deterministic, the result is the same
/// as GetDeterministicValue.
math::RigidTransformd Sample(RandomGenerator* generator) const;
template <typename Archive>
void Serialize(Archive* a) {
a->Visit(DRAKE_NVP(base_frame));
a->Visit(DRAKE_NVP(translation));
// Visit the `rotation` field as if it were optional, to allow it to be
// missing during a schema transition window.
// TODO(anzu#4772) Once rotation_rpy_deg is gone, this should be
// `Visit(MakeNameValue("rotation", &rotation.value))` instead.
std::optional<Rotation::Variant> maybe_rotation = rotation.value;
a->Visit(MakeNameValue("rotation", &maybe_rotation));
if (maybe_rotation) {
rotation.value = *maybe_rotation;
}
// Visit the legacy `rotation_rpy_deg` field as an empty optional, to allow
// it to be read and obeyed (but not written) during a transition window.
// TODO(anzu#4772) Remove this compatibility shim once nothing is using it.
std::optional<Eigen::Vector3d> maybe_rpy;
a->Visit(MakeNameValue("rotation_rpy_deg", &maybe_rpy));
if (maybe_rpy) {
this->set_rotation_rpy_deg(*maybe_rpy);
}
}
/// An optional base frame name for this transform. When left unspecified,
/// the default depends on the semantics of the enclosing struct.
std::optional<std::string> base_frame;
/// A translation vector, in meters.
DistributionVectorVariant<3> translation{Eigen::Vector3d::Zero()};
/// A variant that allows for several ways to specify a rotation.
Rotation rotation;
};
} // namespace schema
} // namespace drake