Ariles
Loading...
Searching...
No Matches
demo_api_v2_ros2.cpp
Go to the documentation of this file.
1/**
2 @file
3 @author Alexander Sherikov
4
5 @copyright 2024 Alexander Sherikov, Licensed under the Apache License, Version 2.0.
6 (see @ref LICENSE or http://www.apache.org/licenses/LICENSE-2.0)
7
8 @brief
9*/
10// cppcheck-suppress-file duplInheritedMember
11
12
13// ============================================================================
14// HEADER INCLUSION
15// ============================================================================
16
17// `visitor` is an Ariles component which provides integration with a particular
18// 3rd party library.
21
22// `adapter` is an Ariles component which adds support for serialization of
23// certain type(s), e.g. Eigen types or Boost pointers.
25#include <ariles2/adapters/eigen.h>
28#include <ariles2/ariles.h>
29
30
31
32// ===============================================================
33// DEFINING TYPES
34// ===============================================================
35namespace
36{
38 // must inherit from ariles2::DefaultBase
40 {
41// Declare entries, in this case two numbers
42#define ARILES2_ENTRIES(v) \
43 ARILES2_TYPED_ENTRY(v, real_member, double) \
44 ARILES2_TYPED_ENTRY_(v, integer_member, int)
45// underscore ^ indicates that the name of the entry must be
46// 'integer_member_' instead of 'integer_member', this is useful if your
47// naming convention requires trailing underscores for member variables.
48
49// Initialize ariles
50#include ARILES2_INITIALIZE
51
52 public:
53 virtual ~ArilesBaseClass() = default; // added to suppress compiler warnings
54
55 // This method is called every time you deserialize a class. If
56 // omitted, the default automatically generated method is used.
57 void arilesVisit(const ariles2::Defaults & /*visitor*/, const ariles2::Defaults::Parameters & /*param*/)
58 {
59 real_member = 0.0;
60 integer_member_ = 12;
61 }
62 };
63
64
66 {
67 public:
68 // Eigen types are supported too, see below
69 Eigen::Vector3d eigen_vector_;
70 };
71
72
73 class MyClass : public ArilesBaseClass, // no need to inherit from ariles2::DefaultBase directly.
75 {
76// Declare entries, in this case we indicate inheritance from another
77// Ariles class (ArilesBaseClass) and a member from a non-Ariles class
78// (NonArilesBaseClass)
79#define ARILES2_ENTRIES(v) \
80 ARILES2_PARENT(v, ArilesBaseClass) \
81 ARILES2_ENTRY_(v, eigen_vector)
82 // Here ^ Ariles should not declare the inherited member, therefore we
83 // use 'ARILES2_ENTRY_' instead of 'ARILES2_TYPED_ENTRY_'.
84
85#include ARILES2_INITIALIZE
86
87
88 public:
89 ~MyClass() override = default; // added to suppress compiler warnings
90
91
93 {
94 // If you use your own method to initialize member variables,
95 // it is up to you to properly initialize all entries and
96 // parent classes.
97 // all parents at once
98 arilesVisitParents(visitor, param);
99 // or one by one (either option is sufficient)
100 ArilesBaseClass::arilesVisit(visitor, param);
101
102 // custom default values for some members
103 real_member = 100.0;
104 eigen_vector_.setZero();
105 }
106 };
107
108
110 {
111 // Some of the standard containers can be used with Ariles types.
112#define ARILES2_ENTRIES(v) \
113 ARILES2_TYPED_ENTRY_(v, my_class_vector, std::vector<MyClass>) \
114 ARILES2_TYPED_ENTRY_(v, ptr, std::shared_ptr<MyClass>)
115#include ARILES2_INITIALIZE
116
117 public:
118 virtual ~MyContainerClass() = default;
119 };
120} // namespace
121
122
123// ===============================================================
124// SERIALIZATION & DESERIALIZATION
125// ===============================================================
126
127#include <iostream> // std::cout
128
129
130// run with "demo_api_v2_ros2 --ros-args --params-file /demo_api_v2_ros2.yaml"
131int main(int argc, char *argv[])
132{
133 try
134 {
135 rclcpp::init(argc, argv);
136 const rclcpp::Node::SharedPtr nh = rclcpp::Node::make_shared(
137 "demo_api_v2_ros2",
138 // although ariles provides Declarator visitor, declaring
139 // parameters in general case is not possible since generic
140 // arrays are stored as maps with indices used as keys: size of
141 // such array is not know in advance so it is not possible to
142 // declare all the necessary indices
143 rclcpp::NodeOptions().allow_undeclared_parameters(true).automatically_declare_parameters_from_overrides(
144 true));
145
146 // read parameters loaded from file (demo_api_v2_ros2.yaml)
147 {
148 MyContainerClass my_container_class;
149
150 // access members as usual
151 my_container_class.my_class_vector_.emplace_back();
152 ariles2::apply<ariles2::Defaults>(my_container_class.my_class_vector_[0]);
153
154 /*
155 * output
156 my_class_vector:
157 - real_member: 100
158 integer_member: 12
159 eigen_vector: [0, 0, 0]
160 ptr:
161 is_null: true
162 */
163 ariles2::apply<ariles2::yaml_cpp::Writer>(std::cout, my_container_class);
164
165 // see demo_api_v2_ros2.yaml
166 ariles2::apply<ariles2::ros2param::Reader>(nh->get_node_parameters_interface(), my_container_class);
167
168 /*
169 * output
170 my_class_vector:
171 - real_member: 100
172 integer_member: 12
173 eigen_vector: [0, 0, 0]
174 - real_member: 110
175 integer_member: 1
176 eigen_vector: [0, 1, 0]
177 - real_member: 111
178 integer_member: 21
179 eigen_vector: [1, 1, 0]
180 ptr:
181 is_null: true
182 */
183 ariles2::apply<ariles2::yaml_cpp::Writer>(std::cout, my_container_class);
184 }
185
186 // writing & reading
187 {
188 MyContainerClass my_container_class;
189 my_container_class.ptr_ = std::make_shared<MyClass>();
190 ariles2::apply<ariles2::Defaults>(*my_container_class.ptr_);
191
192 my_container_class.my_class_vector_.emplace_back();
193 ariles2::apply<ariles2::Defaults>(my_container_class.my_class_vector_[0]);
194 my_container_class.my_class_vector_[0].real_member = 200;
195
196 ariles2::apply<ariles2::ros2param::Writer>(nh->get_node_parameters_interface(), my_container_class);
197 ariles2::apply<ariles2::ros2param::Reader>(nh->get_node_parameters_interface(), my_container_class);
198
199 /*
200 * output:
201 * - note that parameters loaded from file are preserved
202 * - it would be nice to drop old parameters, but it is impossible to undeclare them
203 my_class_vector:
204 - real_member: 200 # overridden
205 integer_member: 12
206 eigen_vector: [0, 0, 0]
207 - real_member: 110
208 integer_member: 1
209 eigen_vector: [0, 1, 0]
210 - real_member: 111
211 integer_member: 21
212 eigen_vector: [1, 1, 0]
213 ptr:
214 is_null: false # overridden
215 value: # added
216 real_member: 100
217 integer_member: 12
218 eigen_vector: [0, 0, 0]
219 */
220 ariles2::apply<ariles2::yaml_cpp::Writer>(std::cout, my_container_class);
221 }
222
223 // declaring
224 // - hardly useful, is going to declare my_class_vector_ to have only one member
225 // - declarator does not read parameters into an Ariles class, a
226 // separate pass with Reader visitor is needed
227 {
228 MyContainerClass my_container_class;
229 my_container_class.my_class_vector_.emplace_back();
230 ariles2::apply<ariles2::Defaults>(my_container_class.my_class_vector_[0]);
231 ariles2::apply<ariles2::ros2param::Declarator>(nh->get_node_parameters_interface(), my_container_class);
232 }
233
234 // missing parameters
235 // - an attempt to read missing parameters results in an exception
236 {
237 MyClass my_class;
238 try
239 {
240 ariles2::apply<ariles2::ros2param::Reader>(nh->get_node_parameters_interface(), my_class);
241 }
242 catch (const std::exception &e)
243 {
244 // "... Configuration file does not contain entry 'real_member'."
245 std::cout << e.what() << std::endl;
246 }
247 }
248 }
249 catch (const std::exception &e)
250 {
251 std::cout << e.what() << std::endl;
252 return (EXIT_FAILURE);
253 }
254
255 return (EXIT_SUCCESS);
256}
void arilesVisit(const ariles2::Defaults &, const ariles2::Defaults::Parameters &)
void arilesVisit(const ariles2::Defaults &visitor, const ariles2::Defaults::Parameters &param)
int main()