libalmath  2.8.7.4
 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>
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
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  }
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
101  boost::for_each(keys,
102  [] (ptree &key) {
103  Key::offset_frame(key, -1);
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) {
134 }
135 
136 inline void migrate_xar_to_v2(ptree &curve, int fps) {
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
boost::optional< T > optional
Definition: qianim.h:25
ALMATH_API void migrate_v1_to_v2(ptree &tangent, float max_abs_abscissa, Side side)
ALMATH_API void convert_unit(ptree &curve, Unit to, Unit from)
ALMATH_API void offset_frame(ptree &key, int value)
void migrate_v1_to_v2(ptree &curve)
Definition: surgeon.h:131
ALMATH_API void put_fps(ptree &pt, int fps)
ALMATH_API ptree v2_root_from_xar_timeline(const ptree &xar_timeline)
ALMATH_API void migrate_tangents_v1_to_v2(optional< const ptree & > prev_key, ptree &key, optional< const ptree & > next_key)
ALMATH_API void migrate_smooth_symmetrical_v1_to_v2(ptree &key)
ALMATH_API ptree v2_root_from_v1_root(const ptree &v1_root)
boost::property_tree::ptree ptree
Definition: qianim.h:22
void migrate_xar_to_v2(ptree &curve, int fps)
Definition: surgeon.h:136
ALMATH_API void fix_missing_unit(ptree &curve, bool verbose=false)
ALMATH_API std::vector< ptree > v2_roots_from_xar(const ptree &docroot)
void migrate_v1_to_v2(Keys keys)
Definition: surgeon.h:98
auto get_keys(const ptree &pt) -> boost::select_second_const_range< decltype(boost::adaptors::filter(pt, Key::is_key))>
Definition: qianim.h:235