- 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
surgeon.h
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2017 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 // utility functions
8 #ifndef LIBALMATH_ALMATH_SCENEGRAPH_QIANIM_SURGEON_H
9 #define LIBALMATH_ALMATH_SCENEGRAPH_QIANIM_SURGEON_H
10
11 #include <almath/api.h>
12 #include <almath/scenegraph/qianim.h>
13 #include <boost/range/algorithm/for_each.hpp>
14 #include <memory>
15 #include <vector>
16
17 namespace AL {
18 namespace qianim {
19
20 namespace Tangent {
21
22 // migrate a v1 Tangent element of type "bezier" or "linear".
23 //
24 // In case of "bezier" that tangent is clamped if needed
25 //
26 // v1 Tangent elements of type "bezier_auto" should not exist:
27 // in this case there shall be no Tangent element.
28 // v1 Tangent elements of type "constant" are currently not supported,
29 // since I expect they are not used in practice.
30 ALMATH_API void migrate_v1_to_v2(ptree &tangent, float max_abs_abscissa,
31 Side side);
32 }
33
34 namespace Key {
35
36 // offset the frame attibute of the given Key element with the given value
37 ALMATH_API void offset_frame(ptree &key, int value);
38
39 ALMATH_API void migrate_smooth_symmetrical_v1_to_v2(ptree &key);
40
41 // migrate v1 tangents of Key element
42 //
43 // key: Key element to be modifed. It must have v1 tangents.
44 // prev_key: previous Key element, if any
45 // next_key: next Key element, if any
46 //
47 // Notes
48 //
49 // * tangent children elements of prev_key and next_key elements won't
50 // be used. As a consequence, it does not matter if those tangents are
51 // in v1 or v2 format.
52 //
53 // * in order to resolve BEZIER_AUTO tangents, the algorithm uses the
54 // difference of the frame attributes of prev_key, key and next_key.
55 // As a consequence, all three keys shall use the same convention
56 // (either be zero-based (like v1 Key) or one-based (like v2 Key).
57 //
58 // * if prev_key or next_key is missing, then "key" is the first or
59 // the last key (or both if the curve has a single key). In such
60 // a case, the Key is a local extremum and BEZIER_AUTO tangent
61 // resolution picks an horizontal tangent.
62 // Note that if the first Key right tangent is BEZIER_AUTO, the conversion
63 // to v2 introduces a behavior change:
64 // with v1, the BEZIER_AUTO resolution would have been done at runtime,
65 // using the actual robot posture as "prev_key" at frame 0/1.
66 // The resolved tangent might not have been horizontal. When converting
67 // to v2, we resolve the tangent at resolution time and the resulting
68 // tangent is horizontal.
69 //
70 // * "exterior tangents" (ie. the left Tangent of the first Key and the right
71 // Tangent of the last Key) are not really part of the Actuator curve.
72 // However, they are converted and kept if present.
73 ALMATH_API
74 void migrate_tangents_v1_to_v2(optional<const ptree &> prev_key,
75 ptree &key,
76 optional<const ptree &> next_key);
77
78 // migrate v1 tangents of all the Key elements from the range.
79 // Throw if the keys are not sorted by ascending frame attribute.
80 template <typename Keys>
81 void migrate_tangents_v1_to_v2(Keys keys) {
82 auto cur = boost::begin(keys);
83 if (cur == boost::end(keys))
84 return; // no key to migrate
85 optional<const ptree &> prev_key;
86 auto next = cur;
87 ++next;
88 while (next != boost::end(keys)) {
89 Key::migrate_tangents_v1_to_v2(prev_key, *cur, *next);
90 prev_key = *cur;
91 cur = next;
92 ++next;
93 }
94 Key::migrate_tangents_v1_to_v2(prev_key, *cur, optional<const ptree &>());
95 }
96
97 template <typename Keys>
98 void migrate_v1_to_v2(Keys keys) {
99 // beware: we cannot migrate the key frame and the tangents in the same loop
100 Key::migrate_tangents_v1_to_v2(keys);
101 boost::for_each(keys,
102 [] (ptree &key) {
103 Key::offset_frame(key, -1);
104 Key::migrate_smooth_symmetrical_v1_to_v2(key);});
105 }
106 }
107
108 namespace ActuatorCurve {
109
110 // convert a curve unit (typically degree <-> radian)
111 ALMATH_API void convert_unit(ptree &curve, Unit to, Unit from);
112
113 // add a unit if missing: "dimensionless" if the curve is named
114 // "LHand" or "RHand", "degree" otherwise.
115 //
116 // Note: maybe we could implement it another way when migrating a xar:
117 // from
118 // enum AL::ActuatorCurve::CurveUnit { UNKNOWN_UNIT = -1, DEGREE_UNIT, PERCENT_UNIT };
119 // defined line 48 in
120 // desktop/libraries/behavior/behaviormodel/behaviormodel/timeline/actuator_curve.h
121 // and
122 // enum AL::FMActuatorCurve::CurveUnit { UNKNOWN_UNIT = -1, DEGREE_UNIT, PERCENT_UNIT };
123 // defined line 30 in behavior/framemanager/src/fmActuatorCurve.h
124 // one sees that 0 means degrees and 1 means dimensionless.
125 //
126 // Yet, the names LHAnd and RHand are hardcoded in AR::BoxUtils::behaviorToAnimFile(...)
127 // defined line 45 in
128 // desktop/libraries/behavior/behavior_utils/behavior_utils/box_utils.h
129 ALMATH_API void fix_missing_unit(ptree &curve, bool verbose=false);
130
131 inline void migrate_v1_to_v2(ptree &curve) {
132 Key::migrate_v1_to_v2(V2::ActuatorCurve::get_keys(curve));
133 ActuatorCurve::fix_missing_unit(curve);
134 }
135
136 inline void migrate_xar_to_v2(ptree &curve, int fps) {
137 AL::qianim::V2::ActuatorCurve::put_fps(curve, fps);
138 Key::migrate_v1_to_v2(V2::ActuatorCurve::get_keys(curve));
139 ActuatorCurve::fix_missing_unit(curve);
140 // remove legacy attributes inherited from xar
141 auto &attr = curve.get_child("<xmlattr>");
142 attr.erase("name");
143 attr.erase("recordable");
144 }
145 }
146
147 // create an animation document from a XAR timeline
148 ALMATH_API ptree v2_root_from_xar_timeline(const ptree &xar_timeline);
149
150 // create an animation document for each timeline in a XAR
151 ALMATH_API std::vector<ptree> v2_roots_from_xar(const ptree &docroot);
152
153 // create an animation document from a V1 .qianim document
154 ALMATH_API ptree v2_root_from_v1_root(const ptree &v1_root);
155
156 }
157 }
158 #endif
AL::qianim::optional
boost::optional< T > optional
Definition: qianim.h:25
AL::qianim::Tangent::migrate_v1_to_v2
ALMATH_API void migrate_v1_to_v2(ptree &tangent, float max_abs_abscissa, Side side)
AL::qianim::ActuatorCurve::convert_unit
ALMATH_API void convert_unit(ptree &curve, Unit to, Unit from)
AL::qianim::Key::offset_frame
ALMATH_API void offset_frame(ptree &key, int value)
AL::qianim::ActuatorCurve::migrate_v1_to_v2
void migrate_v1_to_v2(ptree &curve)
Definition: surgeon.h:131
AL::qianim::V2::ActuatorCurve::put_fps
ALMATH_API void put_fps(ptree &pt, int fps)
AL::qianim::v2_root_from_xar_timeline
ALMATH_API ptree v2_root_from_xar_timeline(const ptree &xar_timeline)
AL::qianim::Key::migrate_tangents_v1_to_v2
ALMATH_API void migrate_tangents_v1_to_v2(optional< const ptree & > prev_key, ptree &key, optional< const ptree & > next_key)
AL::qianim::Key::migrate_smooth_symmetrical_v1_to_v2
ALMATH_API void migrate_smooth_symmetrical_v1_to_v2(ptree &key)
AL::qianim::v2_root_from_v1_root
ALMATH_API ptree v2_root_from_v1_root(const ptree &v1_root)
AL::qianim::Unit
Unit
Definition: unit.h:15
AL::qianim::ptree
boost::property_tree::ptree ptree
Definition: qianim.h:22
AL::qianim::ActuatorCurve::migrate_xar_to_v2
void migrate_xar_to_v2(ptree &curve, int fps)
Definition: surgeon.h:136
qianim.h
AL::qianim::ActuatorCurve::fix_missing_unit
ALMATH_API void fix_missing_unit(ptree &curve, bool verbose=false)
AL::qianim::v2_roots_from_xar
ALMATH_API std::vector< ptree > v2_roots_from_xar(const ptree &docroot)
AL::qianim::Key::migrate_v1_to_v2
void migrate_v1_to_v2(Keys keys)
Definition: surgeon.h:98
AL::qianim::Side
Side
Definition: qianim.h:27
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