- Aldebaran documentation |
- C++ Libraries |
- index

libalmath 2.8.7.4

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
qianim.h
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2016 Softbank Robotics. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the COPYING file.
5 */
6
7 #ifndef LIBALMATH_ALMATH_SCENEGRAPH_QIANIM_H
8 #define LIBALMATH_ALMATH_SCENEGRAPH_QIANIM_H
9
10 #include <almath/api.h>
11 #include <almath/scenegraph/qianim/unit.h>
12 #include <iterator>
13 #include <type_traits>
14 #include <boost/property_tree/ptree.hpp>
15 #include <boost/range/adaptor/map.hpp>
16 #include <boost/range/adaptor/filtered.hpp>
17 #include <functional>
18
19 namespace AL {
20 namespace qianim {
21
22 using ptree = boost::property_tree::ptree;
23
24 template<class T>
25 using optional = boost::optional<T>;
26
27 enum struct Side : bool {
28 left,
29 right
30 };
31
32 namespace V2 {
33
34 // Apply binary functor on each pair of adjacent iterators in the range
35 // [first, last).
36 template <typename InputIt, typename BinaryOperation>
37 BinaryOperation adjacent_for_each(InputIt first, InputIt last,
38 BinaryOperation binary_op) {
39 if (first == last)
40 return binary_op;
41 auto next = std::next(first);
42 while (next != last) {
43 binary_op(*first, *next);
44 first = next;
45 ++next;
46 }
47 return binary_op;
48 }
49
50 namespace Tangent {
51
52 // homogeneous to Key::frame()
53 // Note: this function does *not* check that the abscissa sign is consistent
54 // with the tangent side
55 template <typename T>
56 typename std::enable_if<std::is_floating_point<T>::value, T>::type
57 get_abscissa(const ptree &pt) {
58 return pt.get<T>("<xmlattr>.abscissaParam");
59 }
60
61 // Note: this function does *not* check that the abscissa sign is consistent
62 // with the tangent side
63 template <typename T>
64 typename std::enable_if<std::is_floating_point<T>::value>::type
65 put_abscissa(ptree &pt, T abscissa) {
66 pt.put<T>("<xmlattr>.abscissaParam", abscissa);
67 }
68
69 // homogeneous to Key::value()
70 template <typename T>
71 typename std::enable_if<std::is_floating_point<T>::value, T>::type
72 get_ordinate(const ptree &pt) {
73 return pt.get<T>("<xmlattr>.ordinateParam");
74 }
75
76 template <typename T>
77 typename std::enable_if<std::is_floating_point<T>::value>::type
78 put_ordinate(ptree &pt, T ordinate) {
79 pt.put<T>("<xmlattr>.ordinateParam", ordinate);
80 }
81
82 ALMATH_API Side get_side(const ptree &pt);
83 ALMATH_API void put_side(ptree &pt, Side side);
84 }
85
86 namespace Key {
87 // return true if the argument is a Key element
88 ALMATH_API bool is_key(const ptree::value_type &val);
89
90 // return key frame, which is non-negative
91 ALMATH_API int get_frame(const ptree &pt);
92 ALMATH_API void put_frame(ptree &pt, int frame);
93
94 ALMATH_API ptree::size_type erase_tangent(ptree &pt, Side side);
95
96 ALMATH_API optional<const ptree &> get_tangent_optional(const ptree &pt,
97 Side side);
98 ALMATH_API optional<ptree &> get_tangent_optional(ptree &pt, Side side);
99
100 inline const ptree &get_tangent(const ptree &pt, Side side) {
101 return get_tangent_optional(pt, side).value();
102 }
103
104 inline ptree &get_tangent(ptree &pt, Side side) {
105 return get_tangent_optional(pt, side).value();
106 }
107
108 ALMATH_API ptree &require_tangent(ptree &pt, Side side);
109
110 // Note: this function does *not* check that the abscissa sign is consistent
111 // with the tangent side
112 template <typename T>
113 typename std::enable_if<std::is_floating_point<T>::value, ptree &>::type
114 put_tangent(ptree &pt, Side side, T abscissa, T ordinate) {
115 ptree &tangent = require_tangent(pt, side);
116 Tangent::put_abscissa<T>(tangent, abscissa);
117 Tangent::put_ordinate<T>(tangent, ordinate);
118 return tangent;
119 }
120
121 template <typename T>
122 typename std::enable_if<std::is_floating_point<T>::value, T>::type
123 get_value(const ptree &pt) {
124 return pt.get<T>("<xmlattr>.value");
125 }
126
127 template <typename T>
128 typename std::enable_if<std::is_floating_point<T>::value>::type
129 put_value(ptree &pt, T value){
130 pt.put("<xmlattr>.value", value);
131 }
132
133
134 // throw if:
135 // an interval has non-positive duration
136 // an interval has a tangent with out of bounds abscissa
137 template <typename T>
138 typename std::enable_if<std::is_floating_point<T>::value>::type
139 check_cubic_bezier(int p0_frame, T, T p1_dframe, T,
140 T p2_dframe, T, int p3_frame, T) {
141 // interval duration, in frames
142 auto dframe = p3_frame - p0_frame;
143 if (dframe <= 0) {
144 throw std::invalid_argument(
145 "successive Key elements shall have increasing frame attributes");
146 }
147 if (p1_dframe < 0 || p1_dframe > dframe) {
148 throw std::invalid_argument(
149 "Key has right Tangent with out of bound abscissa attribute");
150 }
151 if (p2_dframe > 0 || p2_dframe < -dframe) {
152 throw std::invalid_argument(
153 "Key has left Tangent with out of bound abscissa attribute");
154 }
155 }
156
157 // Apply functor to cubic Bezier curve parameters
158 //
159 // The Bezier curve is defined by the four points read from two adjacent
160 // keys
161 //
162 // p0: (p0_frame , p0_value)
163 // p1: (p0_frame + p1_dframe, p0_value + p1_dvalue)
164 // p2: (p3_frame + p2_dframe, p3_value + p2_dvalue)
165 // p3: (p3_frame, p3_value)
166 //
167 // The functor has the following signature:
168 // void op(int p0_frame, Scalar p0_value,
169 // Scalar p1_dframe, Scalar p1_dvalue,
170 // Scalar p2_dframe, Scalar p2_dvalue,
171 // int p3_frame, Scalar p3_value)
172 //
173 template <typename Scalar, typename Functor>
174 typename std::enable_if<std::is_floating_point<Scalar>::value>::type
175 apply_cubic_bezier(const ptree &p0_key, const ptree &p3_key, Functor op) {
176 const ptree &p1_tangent = Key::get_tangent(p0_key, Side::right);
177 const ptree &p2_tangent = Key::get_tangent(p3_key, Side::left);
178 op(Key::get_frame(p0_key),
179 Key::get_value<Scalar>(p0_key),
180 Tangent::get_abscissa<Scalar>(p1_tangent),
181 Tangent::get_ordinate<Scalar>(p1_tangent),
182 Tangent::get_abscissa<Scalar>(p2_tangent),
183 Tangent::get_ordinate<Scalar>(p2_tangent),
184 Key::get_frame(p3_key),
185 Key::get_value<Scalar>(p3_key));
186 }
187 }
188
189 namespace ActuatorCurve {
190 // return true if the argument is an ActuatorCurve element
191 ALMATH_API bool is_actuatorcurve(const ptree::value_type &val);
192
193 // return actuator name
194 ALMATH_API std::string get_actuator(const ptree &pt);
195 ALMATH_API void put_actuator(ptree &pt, const std::string &name);
196
197 // return fps, which is positive
198 ALMATH_API int get_fps(const ptree &pt);
199 ALMATH_API void put_fps(ptree &pt, int fps);
200
201 ALMATH_API bool get_mute(const ptree &pt);
202 ALMATH_API void put_mute(ptree &pt, bool mute);
203
204 // return unit, which is not UNIT_UNKNOWN
205 ALMATH_API Unit get_unit(const ptree &pt);
206 ALMATH_API void put_unit(ptree &pt, Unit unit);
207
208 // Search for a Key element with the given frame.
209 // If found, return it, otherwise return an invalid optional.
210 // This function assumes the Key elements are sorted by increasing frame,
211 // which should be the case if the document is conforming.
212 ALMATH_API optional<const ptree &> get_key_optional(const ptree &pt,
213 int frame);
214 ALMATH_API optional<ptree &> get_key_optional(ptree &pt, int frame);
215
216 // Search for a Key element with the given frame.
217 // Throw if not found, otherwise return an invalid optional.
218 // This function assumes the Key elements are sorted by increasing frame,
219 // which should be the case if the document is conforming.
220 inline const ptree &get_key(const ptree &pt, int frame) {
221 return get_key_optional(pt, frame).value();
222 }
223 inline ptree &get_key(ptree &pt, int frame) {
224 return get_key_optional(pt, frame).value();
225 }
226
227 // Search for a Key element with the given frame.
228 // If found, return it, otherwise insert a new Key.
229 // This function assumes the Key elements are sorted by increasing frame,
230 // which should be the case if the document is conforming.
231 ALMATH_API ptree &require_key(ptree &pt, int frame);
232
233 // return the range of child Key elements, in document order.
234 // If the document is conforming, the keys are sorted by increasing frame.
235 inline auto get_keys(const ptree &pt)
236 -> boost::select_second_const_range<
237 decltype(boost::adaptors::filter(pt, Key::is_key))>
238 {
239 return boost::adaptors::values(boost::adaptors::filter(pt, Key::is_key));
240 }
241
242 inline auto get_keys(ptree &pt)
243 -> boost::select_second_mutable_range<
244 decltype(boost::adaptors::filter(pt, Key::is_key))> {
245 auto kv = boost::adaptors::filter(pt, Key::is_key);
246 return boost::adaptors::values(kv);
247 }
248
249 // throw if the curve does not describe a mathematical function as a
250 // sequence of cubic Bezier curves of positive duration
251 template <typename Scalar>
252 typename std::enable_if<std::is_floating_point<Scalar>::value>::type
253 check_cubic_bezier(const ptree &pt) {
254 auto keys = get_keys(pt);
255 adjacent_for_each(
256 keys.begin(), keys.end(),
257 [](const ptree &p0_key, const ptree &p3_key) {
258 Key::apply_cubic_bezier<Scalar>(p0_key, p3_key,
259 Key::check_cubic_bezier<Scalar>);
260 });
261 }
262 }
263
264 namespace Label {
265 // return true if the argument is a Label element
266 ALMATH_API bool is_label(const ptree::value_type &val);
267
268 using Key::get_frame;
269 using Key::put_frame;
270
271 ALMATH_API std::string get_value(const ptree &pt);
272 }
273
274 namespace Labels {
275 // return true if the argument is a Labels element
276 ALMATH_API bool is_labels(const ptree::value_type &val);
277
278 using ActuatorCurve::get_fps;
279 using ActuatorCurve::put_fps;
280
281 // Add a Label at the given frame, with the given value.
282 // Note that the specification requires the value to be UTF-8 encoded.
283 ALMATH_API ptree &add_label(ptree &pt, int frame, const std::string value);
284
285 // return the range of child Label elements, in document order.
286 // If the document is conforming, the Label elements are sorted by increasing
287 // frame.
288 inline auto get_labels(const ptree &pt)
289 -> boost::select_second_const_range<
290 decltype(boost::adaptors::filter(pt, Label::is_label))>
291 {
292 return boost::adaptors::values(boost::adaptors::filter(pt, Label::is_label));
293 }
294
295 // return the range of child Label elements, in document order.
296 inline auto get_labels(ptree &pt)
297 -> boost::select_second_mutable_range<
298 decltype(boost::adaptors::filter(pt, Label::is_label))> {
299 auto kv = boost::adaptors::filter(pt, Label::is_label);
300 return boost::adaptors::values(kv);
301 }
302 }
303
304 namespace Animation {
305 // return the range of child ActuatorCurve elements, in document order.
306 inline auto get_actuatorcurves(const ptree &pt)
307 -> boost::select_second_const_range<
308 decltype(boost::adaptors::filter(pt, ActuatorCurve::is_actuatorcurve))> {
309 return boost::adaptors::values(
310 boost::adaptors::filter(pt, ActuatorCurve::is_actuatorcurve));
311 }
312
313 inline auto get_actuatorcurves(ptree &pt)
314 -> boost::select_second_mutable_range<
315 decltype(boost::adaptors::filter(pt, ActuatorCurve::is_actuatorcurve))> {
316 auto kv = boost::adaptors::filter(pt, ActuatorCurve::is_actuatorcurve);
317 return boost::adaptors::values(kv);
318 }
319
320 // throw if version is not 2.0
321 ALMATH_API void check_version(const ptree &pt);
322
323 // throw if animation or one of its children is invalid
324 ALMATH_API void check_all(const ptree &pt);
325
326 ALMATH_API ptree &require_actuatorcurve(ptree &pt,
327 const std::string &actuator);
328
329 // return the range of child Labels elements, in document order.
330 inline auto get_labels(const ptree &pt)
331 -> boost::select_second_const_range<
332 decltype(boost::adaptors::filter(pt, Labels::is_labels))> {
333 return boost::adaptors::values(
334 boost::adaptors::filter(pt, Labels::is_labels));
335 }
336
337 ALMATH_API ptree &add_labels(ptree &pt);
338
339 }
340
341 // return the Animation element, checking its version
342 ALMATH_API ptree &get_animation(ptree &root);
343 ALMATH_API const ptree &get_animation(const ptree &root);
344 ALMATH_API ptree &require_animation(ptree &root);
345 }
346 }
347 }
348
349 #endif
AL::qianim::Side::left
AL::qianim::V2::ActuatorCurve::get_actuator
ALMATH_API std::string get_actuator(const ptree &pt)
AL::qianim::V2::Key::apply_cubic_bezier
std::enable_if< std::is_floating_point< Scalar >::value >::type apply_cubic_bezier(const ptree &p0_key, const ptree &p3_key, Functor op)
Definition: qianim.h:175
AL::qianim::V2::ActuatorCurve::get_mute
ALMATH_API bool get_mute(const ptree &pt)
AL::qianim::optional
boost::optional< T > optional
Definition: qianim.h:25
AL::qianim::Side::right
AL::qianim::V2::Key::put_tangent
std::enable_if< std::is_floating_point< T >::value, ptree & >::type put_tangent(ptree &pt, Side side, T abscissa, T ordinate)
Definition: qianim.h:114
AL::qianim::V2::Animation::get_labels
auto get_labels(const ptree &pt) -> boost::select_second_const_range< decltype(boost::adaptors::filter(pt, Labels::is_labels))>
Definition: qianim.h:330
AL::urdf::name
ALMATH_API std::string name(const ptree &pt)
AL::qianim::V2::Key::erase_tangent
ALMATH_API ptree::size_type erase_tangent(ptree &pt, Side side)
AL::qianim::V2::Label::is_label
ALMATH_API bool is_label(const ptree::value_type &val)
AL::qianim::V2::Labels::add_label
ALMATH_API ptree & add_label(ptree &pt, int frame, const std::string value)
AL::qianim::V2::Key::put_value
std::enable_if< std::is_floating_point< T >::value >::type put_value(ptree &pt, T value)
Definition: qianim.h:129
AL::qianim::V2::Animation::check_version
ALMATH_API void check_version(const ptree &pt)
AL::qianim::V2::Animation::require_actuatorcurve
ALMATH_API ptree & require_actuatorcurve(ptree &pt, const std::string &actuator)
AL::qianim::V2::ActuatorCurve::get_fps
ALMATH_API int get_fps(const ptree &pt)
AL::qianim::V2::Key::check_cubic_bezier
std::enable_if< std::is_floating_point< T >::value >::type check_cubic_bezier(int p0_frame, T, T p1_dframe, T, T p2_dframe, T, int p3_frame, T)
Definition: qianim.h:139
AL::qianim::V2::ActuatorCurve::require_key
ALMATH_API ptree & require_key(ptree &pt, int frame)
AL::qianim::V2::Tangent::put_abscissa
std::enable_if< std::is_floating_point< T >::value >::type put_abscissa(ptree &pt, T abscissa)
Definition: qianim.h:65
AL::qianim::V2::adjacent_for_each
BinaryOperation adjacent_for_each(InputIt first, InputIt last, BinaryOperation binary_op)
Definition: qianim.h:37
AL::qianim::V2::Animation::check_all
ALMATH_API void check_all(const ptree &pt)
AL::qianim::V2::Label::get_value
ALMATH_API std::string get_value(const ptree &pt)
Definition: qianim.h:123
AL::qianim::V2::Tangent::get_ordinate
std::enable_if< std::is_floating_point< T >::value, T >::type get_ordinate(const ptree &pt)
Definition: qianim.h:72
AL::qianim::V2::ActuatorCurve::is_actuatorcurve
ALMATH_API bool is_actuatorcurve(const ptree::value_type &val)
AL::qianim::V2::Tangent::put_side
ALMATH_API void put_side(ptree &pt, Side side)
AL::qianim::V2::ActuatorCurve::put_unit
ALMATH_API void put_unit(ptree &pt, Unit unit)
AL::qianim::V2::Labels::get_labels
auto get_labels(const ptree &pt) -> boost::select_second_const_range< decltype(boost::adaptors::filter(pt, Label::is_label))>
Definition: qianim.h:288
AL::qianim::V2::ActuatorCurve::check_cubic_bezier
std::enable_if< std::is_floating_point< Scalar >::value >::type check_cubic_bezier(const ptree &pt)
Definition: qianim.h:253
AL::qianim::V2::Key::get_tangent_optional
ALMATH_API optional< const ptree & > get_tangent_optional(const ptree &pt, Side side)
AL::qianim::V2::require_animation
ALMATH_API ptree & require_animation(ptree &root)
AL::qianim::V2::ActuatorCurve::put_fps
ALMATH_API void put_fps(ptree &pt, int fps)
AL::qianim::V2::Key::get_value
std::enable_if< std::is_floating_point< T >::value, T >::type get_value(const ptree &pt)
Definition: qianim.h:123
AL::qianim::V2::get_animation
ALMATH_API ptree & get_animation(ptree &root)
AL::qianim::V2::Key::is_key
ALMATH_API bool is_key(const ptree::value_type &val)
AL::qianim::V2::Animation::get_actuatorcurves
auto get_actuatorcurves(const ptree &pt) -> boost::select_second_const_range< decltype(boost::adaptors::filter(pt, ActuatorCurve::is_actuatorcurve))>
Definition: qianim.h:306
AL::qianim::V2::ActuatorCurve::put_actuator
ALMATH_API void put_actuator(ptree &pt, const std::string &name)
AL::qianim::V2::Key::put_frame
ALMATH_API void put_frame(ptree &pt, int frame)
unit.h
AL::qianim::V2::Key::get_tangent
const ptree & get_tangent(const ptree &pt, Side side)
Definition: qianim.h:100
AL::qianim::Unit
Unit
Definition: unit.h:15
AL::qianim::ptree
boost::property_tree::ptree ptree
Definition: qianim.h:22
AL::qianim::V2::ActuatorCurve::get_key
const ptree & get_key(const ptree &pt, int frame)
Definition: qianim.h:220
AL::qianim::V2::Tangent::get_side
ALMATH_API Side get_side(const ptree &pt)
AL::qianim::V2::Tangent::put_ordinate
std::enable_if< std::is_floating_point< T >::value >::type put_ordinate(ptree &pt, T ordinate)
Definition: qianim.h:78
AL::qianim::V2::ActuatorCurve::put_mute
ALMATH_API void put_mute(ptree &pt, bool mute)
AL::qianim::V2::Key::get_frame
ALMATH_API int get_frame(const ptree &pt)
AL::qianim::V2::Key::require_tangent
ALMATH_API ptree & require_tangent(ptree &pt, Side side)
AL::qianim::V2::Labels::is_labels
ALMATH_API bool is_labels(const ptree::value_type &val)
AL::qianim::V2::ActuatorCurve::get_unit
ALMATH_API Unit get_unit(const ptree &pt)
AL::qianim::Side
Side
Definition: qianim.h:27
AL::qianim::V2::Tangent::get_abscissa
std::enable_if< std::is_floating_point< T >::value, T >::type get_abscissa(const ptree &pt)
Definition: qianim.h:57
AL::qianim::V2::Animation::add_labels
ALMATH_API ptree & add_labels(ptree &pt)
AL::qianim::V2::ActuatorCurve::get_key_optional
ALMATH_API optional< const ptree & > get_key_optional(const ptree &pt, int frame)
AL::qianim::V2::ActuatorCurve::get_keys
auto get_keys(const ptree &pt) -> boost::select_second_const_range< decltype(boost::adaptors::filter(pt, Key::is_key))>
Definition: qianim.h:235