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 // automatically generated default method is always available
60 // and can be invoked to pre-initialize parameters
61 arilesVisit<ariles2::Defaults>(visitor, param);
62 real_member = 0.0;
63 integer_member_ = 12;
64 }
65 };
66
67
69 {
70 public:
71 // Eigen types are supported too, see below
72 Eigen::Vector3d eigen_vector_;
73 };
74
75
76 class MyClass : public ArilesBaseClass, // no need to inherit from ariles2::DefaultBase directly.
78 {
79// Declare entries, in this case we indicate inheritance from another
80// Ariles class (ArilesBaseClass) and a member from a non-Ariles class
81// (NonArilesBaseClass)
82#define ARILES2_ENTRIES(v) \
83 ARILES2_PARENT(v, ArilesBaseClass) \
84 ARILES2_ENTRY_(v, eigen_vector)
85 // Here ^ Ariles should not declare the inherited member, therefore we
86 // use 'ARILES2_ENTRY_' instead of 'ARILES2_TYPED_ENTRY_'.
87
88#include ARILES2_INITIALIZE
89
90
91 public:
92 ~MyClass() override = default; // added to suppress compiler warnings
93
94
96 {
97 // If you use your own method to initialize member variables,
98 // it is up to you to properly initialize all entries and
99 // parent classes.
100 // all parents at once
101 arilesVisitParents(visitor, param);
102 // or one by one (either option is sufficient)
103 ArilesBaseClass::arilesVisit(visitor, param);
104
105 // custom default values for some members
106 real_member = 100.0;
107 eigen_vector_.setZero();
108 }
109 };
110
111
113 {
114 // Some of the standard containers can be used with Ariles types.
115#define ARILES2_ENTRIES(v) \
116 ARILES2_TYPED_ENTRY_(v, my_class_vector, std::vector<MyClass>) \
117 ARILES2_TYPED_ENTRY_(v, ptr, std::shared_ptr<MyClass>)
118#include ARILES2_INITIALIZE
119
120 public:
121 virtual ~MyContainerClass() = default;
122 };
123} // namespace
124
125
126// ===============================================================
127// SERIALIZATION & DESERIALIZATION
128// ===============================================================
129
130#include <iostream> // std::cout
131
132
133// run with "demo_api_v2_ros2 --ros-args --params-file /demo_api_v2_ros2.yaml"
134int main(int argc, char *argv[])
135{
136 try
137 {
138 rclcpp::init(argc, argv);
139 const rclcpp::Node::SharedPtr nh = rclcpp::Node::make_shared(
140 "demo_api_v2_ros2",
141 // although ariles provides Declarator visitor, declaring
142 // parameters in general case is not possible since generic
143 // arrays are stored as maps with indices used as keys: size of
144 // such array is not know in advance so it is not possible to
145 // declare all the necessary indices
146 rclcpp::NodeOptions().allow_undeclared_parameters(true).automatically_declare_parameters_from_overrides(
147 true));
148
149 // read parameters loaded from file (demo_api_v2_ros2.yaml)
150 {
151 MyContainerClass my_container_class;
152
153 // access members as usual
154 my_container_class.my_class_vector_.emplace_back();
155 ariles2::apply<ariles2::Defaults>(my_container_class.my_class_vector_[0]);
156
157 /*
158 * output
159 my_class_vector:
160 - real_member: 100
161 integer_member: 12
162 eigen_vector: [0, 0, 0]
163 ptr:
164 is_null: true
165 */
166 ariles2::apply<ariles2::yaml_cpp::Writer>(std::cout, my_container_class);
167
168 // see demo_api_v2_ros2.yaml
169 ariles2::apply<ariles2::ros2param::Reader>(nh->get_node_parameters_interface(), my_container_class);
170
171 /*
172 * output
173 my_class_vector:
174 - real_member: 100
175 integer_member: 12
176 eigen_vector: [0, 0, 0]
177 - real_member: 110
178 integer_member: 1
179 eigen_vector: [0, 1, 0]
180 - real_member: 111
181 integer_member: 21
182 eigen_vector: [1, 1, 0]
183 ptr:
184 is_null: true
185 */
186 ariles2::apply<ariles2::yaml_cpp::Writer>(std::cout, my_container_class);
187 }
188
189 // writing & reading
190 {
191 MyContainerClass my_container_class;
192 my_container_class.ptr_ = std::make_shared<MyClass>();
193 ariles2::apply<ariles2::Defaults>(*my_container_class.ptr_);
194
195 my_container_class.my_class_vector_.emplace_back();
196 ariles2::apply<ariles2::Defaults>(my_container_class.my_class_vector_[0]);
197 my_container_class.my_class_vector_[0].real_member = 200;
198
199 ariles2::apply<ariles2::ros2param::Writer>(nh->get_node_parameters_interface(), my_container_class);
200 ariles2::apply<ariles2::ros2param::Reader>(nh->get_node_parameters_interface(), my_container_class);
201
202 /*
203 * output:
204 * - note that parameters loaded from file are preserved
205 * - it would be nice to drop old parameters, but it is impossible to undeclare them
206 my_class_vector:
207 - real_member: 200 # overridden
208 integer_member: 12
209 eigen_vector: [0, 0, 0]
210 - real_member: 110
211 integer_member: 1
212 eigen_vector: [0, 1, 0]
213 - real_member: 111
214 integer_member: 21
215 eigen_vector: [1, 1, 0]
216 ptr:
217 is_null: false # overridden
218 value: # added
219 real_member: 100
220 integer_member: 12
221 eigen_vector: [0, 0, 0]
222 */
223 ariles2::apply<ariles2::yaml_cpp::Writer>(std::cout, my_container_class);
224 }
225
226 // declaring
227 // - hardly useful, is going to declare my_class_vector_ to have only one member
228 // - declarator does not read parameters into an Ariles class, a
229 // separate pass with Reader visitor is needed
230 {
231 MyContainerClass my_container_class;
232 my_container_class.my_class_vector_.emplace_back();
233 ariles2::apply<ariles2::Defaults>(my_container_class.my_class_vector_[0]);
234 ariles2::apply<ariles2::ros2param::Declarator>(nh->get_node_parameters_interface(), my_container_class);
235 }
236
237 // missing parameters
238 // - an attempt to read missing parameters results in an exception
239 {
240 MyClass my_class;
241 try
242 {
243 ariles2::apply<ariles2::ros2param::Reader>(nh->get_node_parameters_interface(), my_class);
244 }
245 catch (const std::exception &e)
246 {
247 // "... Configuration file does not contain entry 'real_member'."
248 std::cout << e.what() << std::endl;
249 }
250 }
251 }
252 catch (const std::exception &e)
253 {
254 std::cout << e.what() << std::endl;
255 return (EXIT_FAILURE);
256 }
257
258 return (EXIT_SUCCESS);
259}
void arilesVisit(const ariles2::Defaults &visitor, const ariles2::Defaults::Parameters &param)
void arilesVisit(const ariles2::Defaults &visitor, const ariles2::Defaults::Parameters &param)
int main()