Ariles
Loading...
Searching...
No Matches
reader.cpp
Go to the documentation of this file.
1/**
2 @file
3 @author Alexander Sherikov
4
5 @copyright 2018 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
11#include <boost/lexical_cast.hpp>
12
14
15#include "node_wrapper.h"
16
17
18namespace ariles2
19{
20 namespace ns_ros2param
21 {
23 {
24 protected:
25 std::vector<std::string> childs_;
26 const rclcpp::Parameter parameter_;
27
28 public:
29 using NodeBase::NodeBase;
30
31 ReaderNodeWrapper(const std::string &name, std::vector<std::string> childs)
32 : NodeBase(name, NodeBase::Type::ITERATED_MAP), childs_(childs.begin(), childs.end())
33 {
34 size_ = childs_.size();
35 }
36
37 const std::string &getChildName()
38 {
39 return (childs_[index_]);
40 }
41
42 explicit ReaderNodeWrapper(const rclcpp::Parameter &&parameter)
43 : NodeBase(NodeBase::Type::ARRAY), parameter_(parameter)
44 {
45 index_ = 0;
47
48 switch (parameter_.get_type())
49 {
50 case rclcpp::ParameterType::PARAMETER_BYTE_ARRAY:
51 size_ = parameter_.as_byte_array().size();
52 return;
53 case rclcpp::ParameterType::PARAMETER_BOOL_ARRAY:
54 size_ = parameter_.as_bool_array().size();
55 return;
56 case rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY:
57 size_ = parameter_.as_integer_array().size();
58 return;
59 case rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY:
60 size_ = parameter_.as_double_array().size();
61 return;
62 case rclcpp::ParameterType::PARAMETER_STRING_ARRAY:
63 size_ = parameter_.as_string_array().size();
64 return;
65 default:
66 CPPUT_THROW("Unexpected value type");
67 }
68 }
69
70 bool tryReadArray(int64_t &value)
71 {
72 if (isBuiltinArray())
73 {
74 switch (parameter_.get_type())
75 {
76 case rclcpp::ParameterType::PARAMETER_BYTE_ARRAY:
77 value = parameter_.as_byte_array()[index_];
78 return (true);
79 case rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY:
80 value = parameter_.as_integer_array()[index_];
81 return (true);
82 default:
83 CPPUT_THROW("Unexpected array value type");
84 }
85 }
86 return (false);
87 }
88
89 bool tryReadArray(double &value)
90 {
91 if (isBuiltinArray())
92 {
93 switch (parameter_.get_type())
94 {
95 case rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY:
96 value = parameter_.as_double_array()[index_];
97 return (true);
98 default:
99 CPPUT_THROW("Unexpected array value type");
100 }
101 }
102 return (false);
103 }
104
105 bool tryReadArray(std::string &value)
106 {
107 if (isBuiltinArray())
108 {
109 switch (parameter_.get_type())
110 {
111 case rclcpp::ParameterType::PARAMETER_STRING_ARRAY:
112 value = parameter_.as_string_array()[index_];
113 return (true);
114 default:
115 CPPUT_THROW("Unexpected array value type");
116 }
117 }
118 return (false);
119 }
120
121 bool tryReadArray(bool &value)
122 {
123 if (isBuiltinArray())
124 {
125 switch (parameter_.get_type())
126 {
127 case rclcpp::ParameterType::PARAMETER_BOOL_ARRAY:
128 value = parameter_.as_bool_array()[index_];
129 return (true);
130 default:
131 CPPUT_THROW("Unexpected array value type");
132 }
133 }
134 return (false);
135 }
136 };
137
138 namespace impl
139 {
140 class Reader : public serialization::NodeStackBase<ReaderNodeWrapper>
141 {
142 public:
143 // https://docs.ros2.org/latest/api/rclcpp/classrclcpp_1_1Node.html
144 rclcpp::node_interfaces::NodeParametersInterface::SharedPtr nh_;
145
146 std::vector<std::string> parameter_names_;
147
148 const std::string separator_ = ".";
149
150
151 public:
152 explicit Reader(const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr &nh)
153 {
154 nh_ = nh;
155 }
156
157
158 bool getParameter(rclcpp::Parameter &parameter) const
159 {
161 CPPUT_TRACE_VALUE(back().node_);
162
163 return (nh_->get_parameter(back().node_, parameter));
164 }
165
166
167 [[nodiscard]] bool isParameter() const
168 {
169 for (const std::string &name : parameter_names_)
170 {
171 if (back().node_ == name)
172 {
173 return (true);
174 }
175 }
176 return (false);
177 }
178
179 void reset()
180 {
181 clear();
182
183 parameter_names_ = std::move(nh_->list_parameters({}, std::numeric_limits<uint64_t>::max()).names);
184 }
185
186
187 [[nodiscard]] static bool isPrefix(const std::string &prefix, const std::string &name)
188 {
189 if (prefix.empty())
190 {
191 return (true); // zero prefix
192 }
193
194 if (prefix.size() <= name.size())
195 {
196 if (name.substr(0, prefix.size()) == prefix)
197 {
198 if (prefix.size() == name.size())
199 {
200 return (true); // name = prefix
201 }
202
203 if ('.' == name[prefix.size()])
204 {
205 return (true); // normal prefix
206 }
207 }
208 }
209
210 return (false);
211 }
212
213
214 [[nodiscard]] std::vector<std::string> listParameters() const
215 {
216 std::size_t substr_start = 0;
217
218 if (not empty())
219 {
220 substr_start = back().node_.size() + 1; // + 1 for dot
221 }
222
223 // is needed to avoid duplicates?
224 std::vector<std::string> names;
225 for (const std::string &name : parameter_names_)
226 {
227 if (isPrefix(back().node_, name))
228 {
229 const std::size_t substr_end = name.find('.', substr_start);
230 std::string name_part = name.substr(substr_start, substr_end - substr_start);
231
232 const std::vector<std::string>::iterator it =
233 std::lower_bound(names.begin(), names.end(), name_part);
234 if (it == names.end() or *it != name_part)
235 {
236 names.insert(it, std::move(name_part));
237 }
238 }
239 }
240
241 return (names);
242 }
243
245 {
246 for (const std::string &name : parameter_names_)
247 {
248 if (isPrefix(back().node_, name))
249 {
250 return (true);
251 }
252 }
253 return (false);
254 }
255
256 template <int t_expected_parameter_type, class t_Element>
257 void readElement(t_Element &element)
258 {
260 if (not back().tryReadArray(element))
261 {
262 rclcpp::Parameter parameter;
263 CPPUT_ASSERT(getParameter(parameter), std::string("Cannot read parameter: ") + back().node_);
264 CPPUT_ASSERT(t_expected_parameter_type == parameter.get_type(), "Unexpected parameter type.");
265 element = parameter.get_value<t_Element>();
266 }
267 }
268 };
269 } // namespace impl
270 } // namespace ns_ros2param
271} // namespace ariles2
272
273
274namespace ariles2
275{
276 namespace ns_ros2param
277 {
278 Reader::Reader(const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr &nh)
279 {
280 makeImplPtr(nh);
281 }
282
283
284 bool Reader::startRoot(const std::string &name)
285 {
287 CPPUT_TRACE_VALUE(name);
288
289 impl_->reset();
290 return (Parent::startRoot(name));
291 }
292
293
294 bool Reader::startMapEntry(const std::string &child_name)
295 {
297 if (impl_->empty())
298 {
299 impl_->emplace(child_name);
300 }
301 else
302 {
303 CPPUT_ASSERT(not impl_->back().isBuiltinArray(), "Unexpected parent type (builtin array).");
304
305 impl_->concatWithNodeAndEmplace(impl_->separator_, child_name);
306 }
307
308 return (impl_->hasParameterPrefix());
309 }
310
312 {
314 impl_->pop();
315 }
316
317
318
320 const SizeLimitEnforcementType limit_type,
321 const std::size_t min,
322 const std::size_t max)
323 {
325
326 std::vector<std::string> name_list = impl_->listParameters();
327
328 checkSize(limit_type, name_list.size(), min, max);
329
330 impl_->emplace(impl_->back().node_, std::move(name_list));
331 return (true);
332 }
333
334 bool Reader::startIteratedMapElement(std::string &entry_name)
335 {
337 if (impl_->back().isCompleted())
338 {
339 return (false);
340 }
341
342 entry_name = impl_->back().getChildName();
343 impl_->concatWithNodeAndEmplace(impl_->separator_, entry_name);
344
345 return (true);
346 }
347
349 {
350 impl_->pop();
351 ++(impl_->back().index_);
352 }
353
355 {
357 CPPUT_ASSERT(impl_->back().isCompleted(), "End of iterated map has not been reached.");
358 impl_->pop();
359 }
360
361
362 std::size_t Reader::startArray()
363 {
365
366 if (not impl_->empty() and impl_->isParameter())
367 {
368 rclcpp::Parameter values;
369 impl_->getParameter(values);
370 impl_->emplace(std::move(values));
371 }
372 else
373 {
374 impl_->emplace(impl_->back().node_, 0, impl_->listParameters().size());
375 }
376
377 return (impl_->back().size_);
378 }
379
381 {
383
384 CPPUT_ASSERT(not impl_->back().isCompleted(), "Internal error: array has more elements than expected.");
385 if (impl_->back().isNonBuiltinArray())
386 {
387 impl_->concatWithNodeAndEmplace(
388 impl_->separator_, boost::lexical_cast<std::string>(impl_->back().index_));
389 }
390 }
391
393 {
395 if (not impl_->back().isBuiltinArray())
396 {
397 impl_->pop();
398 }
399 impl_->shiftArray();
400 }
401
403 {
405 impl_->pop();
406 }
407
408
409
410#define ARILES2_BASIC_TYPE(type) \
411 void Reader::readElement(type &element) \
412 { \
413 int64_t tmp_value; \
414 impl_->readElement<rclcpp::ParameterType::PARAMETER_INTEGER>(tmp_value); \
415 CPPUT_ASSERT( \
416 tmp_value <= std::numeric_limits<type>::max() && tmp_value >= std::numeric_limits<type>::min(), \
417 "Value is out of range."); \
418 element = static_cast<type>(tmp_value); \
419 }
420
422
423#undef ARILES2_BASIC_TYPE
424
425
426#define ARILES2_BASIC_TYPE(type) \
427 void Reader::readElement(type &element) \
428 { \
429 CPPUT_TRACE_FUNCTION; \
430 int64_t tmp_value; \
431 impl_->readElement<rclcpp::ParameterType::PARAMETER_INTEGER>(tmp_value); \
432 CPPUT_ASSERT(tmp_value >= 0, "Expected positive value."); \
433 CPPUT_ASSERT(static_cast<uint64_t>(tmp_value) <= std::numeric_limits<type>::max(), "Value is too large."); \
434 element = static_cast<type>(tmp_value); \
435 }
436
438
439#undef ARILES2_BASIC_TYPE
440
441
442#define ARILES2_BASIC_TYPE(type) \
443 void Reader::readElement(type &element) \
444 { \
445 CPPUT_TRACE_FUNCTION; \
446 double tmp_value; \
447 impl_->readElement<rclcpp::ParameterType::PARAMETER_DOUBLE>(tmp_value); \
448 element = static_cast<type>(tmp_value); \
449 }
450
452
453#undef ARILES2_BASIC_TYPE
454
455
456 void Reader::readElement(std::string &element)
457 {
459 impl_->readElement<rclcpp::ParameterType::PARAMETER_STRING>(element);
460 }
461
462
463 void Reader::readElement(bool &element)
464 {
466 impl_->readElement<rclcpp::ParameterType::PARAMETER_BOOL>(element);
467 }
468 } // namespace ns_ros2param
469} // namespace ariles2
ReaderNodeWrapper(const std::string &name, std::vector< std::string > childs)
Definition reader.cpp:31
bool tryReadArray(std::string &value)
Definition reader.cpp:105
const std::string & getChildName()
Definition reader.cpp:37
std::vector< std::string > childs_
Definition reader.cpp:25
const rclcpp::Parameter parameter_
Definition reader.cpp:26
ReaderNodeWrapper(const rclcpp::Parameter &&parameter)
Definition reader.cpp:42
bool startIteratedMap(const SizeLimitEnforcementType=SIZE_LIMIT_NONE, const std::size_t=0, const std::size_t=0)
Definition reader.cpp:319
void endMapEntry()
endMapEntry from the current entry to its parent.
Definition reader.cpp:311
bool startIteratedMapElement(std::string &entry_name)
Definition reader.cpp:334
bool startMapEntry(const std::string &child_name)
startMapEntry to the entry with the given name
Definition reader.cpp:294
Reader(const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr &nh)
Constructor.
Definition reader.cpp:278
bool startRoot(const std::string &name)
Definition reader.cpp:284
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr nh_
Definition reader.cpp:144
Reader(const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr &nh)
Definition reader.cpp:152
bool getParameter(rclcpp::Parameter &parameter) const
Definition reader.cpp:158
void readElement(t_Element &element)
Definition reader.cpp:257
std::vector< std::string > parameter_names_
Definition reader.cpp:146
std::vector< std::string > listParameters() const
Definition reader.cpp:214
static bool isPrefix(const std::string &prefix, const std::string &name)
Definition reader.cpp:187
void checkSize(const SizeLimitEnforcementType limit_type, const std::size_t size=0, const std::size_t min=0, const std::size_t max=0) const
Definition read.h:47
virtual bool startRoot(const std::string &name)
Definition read.h:73
void readElement(std::complex< t_Scalar > &entry)
Definition read.h:357
#define CPPUT_THROW(...)
Definition exception.h:19
#define CPPUT_ASSERT(condition,...)
Definition exception.h:32
#define ARILES2_BASIC_REAL_TYPES_LIST
Definition helpers.h:59
#define ARILES2_BASIC_UNSIGNED_INTEGER_TYPES_LIST
Definition helpers.h:50
#define ARILES2_BASIC_SIGNED_INTEGER_TYPES_LIST
Definition helpers.h:37
#define CPPUT_MACRO_SUBSTITUTE(macro)
Definition misc.h:21
#define CPPUT_TRACE_FUNCTION
Definition trace.h:126
#define CPPUT_TRACE_VALUE(value)
Definition trace.h:127