Skip to content

Commit db9cc70

Browse files
committed
Improve quantity example
1 parent 44c0ef2 commit db9cc70

File tree

2 files changed

+99
-25
lines changed

2 files changed

+99
-25
lines changed

example/rbd/quantity.example.cpp

Lines changed: 89 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,8 @@ namespace Variables {
3838
/*************** Define helper m-variables. ***************/
3939
inline constexpr auto NUM_LEGS = 4_idx;
4040

41-
inline constexpr auto LF = 0_idx;
42-
inline constexpr auto LH = 1_idx;
43-
inline constexpr auto RF = 2_idx;
44-
inline constexpr auto RH = 3_idx;
45-
46-
inline constexpr auto FOOT_FRAME_IDS = std::array{12UL, 22UL, 32UL, 42UL};
41+
inline auto FOOT_FRAME_NAMES = std::array{"LF_FOOT"s, "LH_FOOT"s, "RF_FOOT"s, "RH_FOOT"s};
42+
inline constexpr auto FOOT_FRAME_INDICES = std::array{12_idx, 22_idx, 32_idx, 42_idx};
4743

4844
UNGAR_LEAF_MVARIABLE(position, 3);
4945
UNGAR_LEAF_MVARIABLE(orientation, Q);
@@ -68,43 +64,103 @@ UNGAR_BRANCH_MVARIABLE(qv, q, v);
6864

6965
} // namespace Variables
7066

67+
/*************** Define custom quantity. ***************/
68+
/**
69+
* @brief To compute and get a quantity using \c Ungar::Robot, the following steps must be
70+
* followed:
71+
* 1) define the quantity;
72+
* 2) define a corresponding evaluator;
73+
* 3) define a corresponding getter.
74+
*/
75+
76+
/*======================================================================================*/
77+
/*~~~~~~~~~~~~~| PART I: QUANTITY |~~~~~~~~~~~~~*/
78+
/*======================================================================================*/
79+
/// @brief Ungar provides a convenient macro to simplify the definition of quantities.
7180
namespace Quantities {
7281

73-
UNGAR_MAKE_QUANTITY(foot_pose);
82+
UNGAR_MAKE_QUANTITY(frame_pose); // Quantity corresponding to the pose of a frame.
7483

7584
}
7685
} // namespace ANYmalB
7786

87+
/*======================================================================================*/
88+
/*~~~~~~~~~~~~~| PART II: EVALUATOR |~~~~~~~~~~~~~*/
89+
/*======================================================================================*/
90+
/// @brief Evaluators wrap Pinocchio's functionalities and provide the user with a
91+
/// minimal interface.
7892
namespace Ungar {
7993
namespace RBD {
8094

95+
/**
96+
* @brief Evaluators must implement a (possibly overloaded) function \c At computing
97+
* the desired quantity and returning \c void.
98+
*/
8199
template <typename _Scalar>
82-
struct Evaluator<ANYmalB::Quantities::foot_pose, _Scalar> {
100+
struct Evaluator<ANYmalB::Quantities::frame_pose, _Scalar> {
83101
void At(const auto& q) {
84-
namespace vs = ANYmalB::Variables;
85-
102+
// Compute the pose of each joint frame.
86103
pinocchio::forwardKinematics(model, data, q);
87-
for (const auto frameID : vs::FOOT_FRAME_IDS) {
88-
pinocchio::updateFramePlacement(model, data, frameID);
89-
}
90104
}
91105

92106
const pinocchio::ModelTpl<_Scalar>& model;
93107
pinocchio::DataTpl<_Scalar>& data;
94108
};
95109

110+
} // namespace RBD
111+
} // namespace Ungar
112+
113+
/*======================================================================================*/
114+
/*~~~~~~~~~~~~~| PART III: GETTER |~~~~~~~~~~~~~*/
115+
/*======================================================================================*/
116+
/// @brief Getters allow the user to easily retrieve desired quantities.
117+
namespace Ungar {
118+
namespace RBD {
119+
120+
/**
121+
* @brief Getters must implement a (possibly overloaded) function \c Get returning
122+
* the desired quantity.
123+
*/
96124
template <typename _Scalar>
97-
struct Getter<ANYmalB::Quantities::foot_pose, _Scalar> {
98-
const auto& Get(const index_t foot) const {
99-
namespace vs = ANYmalB::Variables;
125+
struct Getter<ANYmalB::Quantities::frame_pose, _Scalar> {
126+
const auto& Get(const index_t frameIndex) const {
127+
UNGAR_ASSERT(static_cast<index_t>(frameIndex) < model.nframes);
128+
129+
const size_t frameID = static_cast<size_t>(frameIndex);
100130

101-
return data.oMf[vs::FOOT_FRAME_IDS[static_cast<size_t>(foot)]];
131+
// Update the pose of the desired frame before returning it.
132+
pinocchio::updateFramePlacement(model, data, frameID);
133+
return data.oMf[frameID];
102134
}
103135

104-
auto& Get(const index_t foot) {
105-
namespace vs = ANYmalB::Variables;
136+
const auto& Get(const std::string& frameName) const {
137+
UNGAR_ASSERT(model.existFrame(frameName));
138+
139+
const size_t frameID = model.getFrameId(frameName);
140+
141+
// Update the pose of the desired frame before returning it.
142+
pinocchio::updateFramePlacement(model, data, frameID);
143+
return data.oMf[frameID];
144+
}
145+
146+
auto& Get(const index_t frameIndex) {
147+
UNGAR_ASSERT(static_cast<index_t>(frameIndex) < model.nframes);
148+
149+
const size_t frameID = static_cast<size_t>(frameIndex);
150+
151+
// Update the pose of the desired frame before returning it.
152+
pinocchio::updateFramePlacement(model, data, frameID);
153+
return data.oMf[frameID];
154+
}
155+
156+
auto& Get(const std::string& frameName) {
157+
UNGAR_ASSERT(model.existFrame(frameName));
158+
159+
const size_t frameID = model.getFrameId(frameName);
106160

107-
return data.oMf[vs::FOOT_FRAME_IDS[static_cast<size_t>(foot)]];
161+
// Update the pose of the desired frame before returning it.
162+
pinocchio::updateFramePlacement(model, data, frameID);
163+
return data.oMf[frameID];
108164
}
109165

110166
const pinocchio::ModelTpl<_Scalar>& model;
@@ -136,13 +192,21 @@ int main() {
136192
q_.Get(vs::position).setRandom();
137193
}
138194

139-
UNGAR_LOG(info, "Computing the pose of feet...");
140-
robot.Compute(qs::foot_pose).At(q);
195+
UNGAR_LOG(info, "Computing the pose of the feet...");
196+
robot.Compute(qs::frame_pose).At(q);
141197
UNGAR_LOG(info, "Done.");
142-
for (const auto foot : {vs::LF, vs::LH, vs::RF, vs::RH}) {
143-
UNGAR_LOG(info, "Pose of the {}-th foot:\n{}", foot, robot.Get(qs::foot_pose, foot));
198+
for (const auto i : enumerate(vs::NUM_LEGS) | cast_to<size_t>) {
199+
const auto [footFrameIndex, footFrameName] =
200+
std::pair{vs::FOOT_FRAME_INDICES[i], vs::FOOT_FRAME_NAMES[i]};
201+
[[maybe_unused]] const pinocchio::SE3 footFramePoseByIndex =
202+
robot.Get(qs::frame_pose, footFrameIndex);
203+
[[maybe_unused]] const pinocchio::SE3 footFramePoseByName =
204+
robot.Get(qs::frame_pose, footFrameName);
205+
206+
UNGAR_LOG(info, Utils::DASH_LINE_SEPARATOR);
207+
UNGAR_LOG(info, "Pose of the foot ('{}'):\n{}", footFrameName, footFramePoseByIndex);
208+
UNGAR_ASSERT(footFramePoseByIndex.isEqual(footFramePoseByName));
144209
}
145-
UNGAR_LOG(info, Utils::DASH_LINE_SEPARATOR);
146210

147211
return 0;
148212
}

include/ungar/rbd/robot.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,21 @@ class Robot {
5858
return RBD::Evaluator<quantity, _Scalar>{_model, *_data};
5959
}
6060

61+
decltype(auto) Get(auto quantity) const {
62+
const auto getter = RBD::Getter<quantity, _Scalar>{_model, *_data};
63+
return getter.Get();
64+
}
65+
6166
decltype(auto) Get(auto quantity, auto&&... args) const {
6267
const auto getter = RBD::Getter<quantity, _Scalar>{_model, *_data};
6368
return getter.Get(std::forward<decltype(args)>(args)...);
6469
}
6570

71+
decltype(auto) Get(auto quantity) {
72+
auto getter = RBD::Getter<quantity, _Scalar>{_model, *_data};
73+
return getter.Get();
74+
}
75+
6676
decltype(auto) Get(auto quantity, auto&&... args) {
6777
auto getter = RBD::Getter<quantity, _Scalar>{_model, *_data};
6878
return getter.Get(std::forward<decltype(args)>(args)...);

0 commit comments

Comments
 (0)