Config.h
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <cstdlib>
5#include <list>
6#include <map>
7#include <memory>
8#include <sstream>
9#include <string>
10#include <type_traits>
11#include <variant>
12#include <vector>
13
14#include <Eigen/Core>
15#include <Eigen/Geometry>
16
19
20#include <cxxabi.h>
21
23{
24 template <typename T>
25 std::string
27 {
28 int status;
29 std::string tname = typeid(T).name();
30 char* demangled_name = abi::__cxa_demangle(tname.c_str(), NULL, NULL, &status);
31 if (status == 0)
32 {
33 tname = demangled_name;
34 std::free(demangled_name);
35 }
36 return tname;
37 }
38
39 /// The variant type of the config map
40 using var_t = std::variant<bool,
41 float,
42 std::uint32_t,
43 std::int32_t,
44 std::list<bool>,
45 std::list<float>,
46 std::list<std::uint32_t>,
47 std::list<std::int32_t>,
50 std::string,
54
55 /**
56 * @brief The ConfigTag is used when setting a config value.
57 * It allows for checks whether the same config value is defined multiple times on the
58 * same hierarchy.
59 * The hierarchy is: Custom overwrites Profiles
60 */
61 enum ConfigTag : int
62 {
63 Invalid = -1,
66 };
67
68 /**
69 * @brief The ConfigItemWithMetadata struct packs the data together with the
70 * tag and a isRead flag.
71 */
84
85 std::string tagName(ConfigTag tag);
86
87 /**
88 * @brief The Config class is the base class of all specialized configurations that have a
89 * direct key -> value mapping.
90 * Direct instantiation is always possible, if this mapping is all that is needed.
91 * A Config in read-only and only ConfigParser can change the contents.
92 */
93 class Config
94 {
95 friend class ConfigParser; // For setters
96 friend class ControllerConfig; // Needed to copy controller configurations
97
98 public:
99 Config();
100
101 virtual ~Config() = default;
102
103 /**
104 * @brief Get a Bool typed Config attribute by name
105 * @param name the name of this Config attribute
106 * @throws ConfigElementNotFoundError if there is no Bool value to this key
107 * @return the value
108 */
109 bool getBool(const std::string name);
110
111 /**
112 * @brief Get a Float typed Config attribute by name
113 * @param name the name of this Config attribute
114 * @throws ConfigElementNotFoundError if there is no Float value to this key
115 * @return the value
116 */
117 float getFloat(const std::string name);
118
119 /**
120 * @brief Get a Uint (std::uint32_t) typed Config attribute by name
121 * @param name the name of this Config attribute
122 * @throws ConfigElementNotFoundError if there is no Uint value to this key
123 * @return the value
124 */
125 std::uint32_t getUint(const std::string name);
126
127 /**
128 * @brief Get a Int (std::int32_t) typed Config attribute by name
129 * @param name the name of this Config attribute
130 * @throws ConfigElementNotFoundError if there is no Int value to this key
131 * @return the value
132 */
133 std::int32_t getInt(const std::string name);
134
135 /**
136 * @brief Get a LinearConvertedValue typed Config attribute by name
137 * @param name the name of this Config attribute
138 * @throws ConfigElementNotFoundError if there is no LinearConvertedValue to this key
139 * @return the value
140 */
141 types::LinearConfig getLinearConfig(const std::string name);
142
143 /**
144 * @brief Get a ModularConvertedValue typed Config attribute by name
145 * @param name the name of this Config attribute
146 * @throws ConfigElementNotFoundError if there is no ModularConvertedValue to this key
147 * @return the value
148 */
150
151 /**
152 * @brief Get a String typed Config attribute by name
153 * @param name the name of this Config attribute
154 * @throws ConfigElementNotFoundError if there is no String value to this key
155 * @return the value
156 */
157 std::string getString(const std::string name);
158
159 /**
160 * @brief Get a BoolList (std::list<bool>) typed Config attribute by name
161 * @param name the name of this Config attribute
162 * @throws ConfigElementNotFoundError if there is no BoolList value to this key
163 * @return the value
164 */
165 std::list<bool> getBoolList(const std::string name);
166
167 /**
168 * @brief Get a FloatList (std::list<float>) typed Config attribute by name
169 * @param name the name of this Config attribute
170 * @throws ConfigElementNotFoundError if there is no FloatList value to this key
171 * @return the value
172 */
173 std::list<float> getFloatList(const std::string name);
174
175 /**
176 * @brief Get a UIntList (std::list<std::uint32_t>) typed Config attribute by name
177 * @param name the name of this Config attribute
178 * @throws ConfigElementNotFoundError if there is no UIntList value to this key
179 * @return the value
180 */
181 std::list<std::uint32_t> getUintList(const std::string name);
182
183 /**
184 * @brief Get a IntList (std::list<std::int32_t>) typed Config attribute by name
185 * @param name the name of this Config attribute
186 * @throws ConfigElementNotFoundError if there is no IntList value to this key
187 * @return the value
188 */
189 std::list<std::int32_t> getIntList(const std::string name);
190
191 /**
192 * @brief Get a Matrix by name
193 * @param name the name of this Config attribute
194 * @throws ConfigElementNotFoundError if there is no matrix to this key with
195 * the correct type, width and height
196 * @return the value
197 */
198 template <typename Type, int Rows, int Columns>
200 getMatrix(const std::string name)
201 {
203
205
206 if (Rows != mVal.rows())
207 {
208 std::stringstream ss;
209 ss << "The matrix has the wrong dimension: rows in config: " << mVal.rows()
210 << " , rows in getter " << Rows;
211 throw ConfigElementNotFoundError(ss.str());
212 }
213 if (Columns != mVal.cols())
214 {
215 std::stringstream ss;
216 ss << "The matrix has the wrong dimension: columns in config: " << mVal.cols()
217 << " , columns in getter " << Columns;
218 throw ConfigElementNotFoundError(ss.str());
219 }
221
222 return {mat};
223 }
224
225 /**
226 * @brief This method is called once the device has read the configuration data it needs.
227 * In this method it should be checked, whether there are entries in this Config
228 * (including config objects that are stored in the Config).
229 * @return true iff all items in this config have been read
230 */
231 virtual bool checkAllItemsRead(std::vector<std::string>& errors) const;
232
233 /**
234 * @brief Print this configuration. Works recursively.
235 * @param s the stream to append the output to
236 * @param indention the indentation (=level of recursion)
237 */
238 virtual void print(std::stringstream& s, int indention) const;
239
240 /**
241 * @brief This method is called when the config is completely read form the HardwareConfig file.
242 * It starts the tracking of which item is read from this Config object.
243 */
244 virtual void onParsingFinished();
245
246 private:
247 // declare copy constructor and assignment operator as public, so that copying is not allowed
248 Config(const Config&) = default;
249 Config& operator=(const Config&) = default;
250
251 protected:
252 std::map<std::string, ConfigItemWithMetadata> items;
253
254 // Can only be accessed by ConfigParser
255 void setBool(const std::string name, bool value, ConfigTag tag);
256 void setFloat(const std::string name, float value, ConfigTag tag);
257 void setUint(const std::string name, std::uint32_t value, ConfigTag tag);
258 void setInt(const std::string name, std::int32_t value, ConfigTag tag);
259 void setLinearConfig(const std::string name, types::LinearConfig&& value, ConfigTag tag);
260 void setModularConvertedValueConfig(const std::string name,
262 ConfigTag tag);
263 void setString(const std::string name, std::string value, ConfigTag tag);
264
265 void setBoolList(const std::string name, std::list<bool> value, ConfigTag tag);
266 void setFloatList(const std::string name, std::list<float> value, ConfigTag tag);
267 void setUintList(const std::string name, std::list<std::uint32_t> value, ConfigTag tag);
268 void setIntList(const std::string name, std::list<std::int32_t> value, ConfigTag tag);
269
270 template <class T>
271 void
272 set(const std::string name, T value, ConfigTag tag)
273 {
274 auto it = items.find(name);
275 if (it != items.end())
276 {
277 ConfigItemWithMetadata item = it->second;
278 if (item.tag == tag)
279 {
280 throw ConfigInsertError("Config Node with name " + name +
281 " is defined multiple times in " + tagName(tag) +
282 " nodes");
283 }
284 else if (item.tag > tag)
285 {
286 // The config nodes have been parsed in the wrong order.
287 // But the new node should not overwrite the old one
288 // So we just return and don't change the entry
289 return;
290 }
291 }
292
293 // Handle partial overrides in types that support it
294 if constexpr (std::is_same_v<types::LinearConfig, T>)
295 {
296 auto oldItem = get_nothrow<T>(name);
297 if (oldItem.has_value())
298 {
299 items[name] =
300 ConfigItemWithMetadata(var_t(oldItem.value().overrideWith(value)), tag);
301 }
302 else
303 {
304 items[name] = ConfigItemWithMetadata(var_t(value), tag);
305 }
306 }
307 else // Base case: Full override
308 {
309 items[name] = ConfigItemWithMetadata(var_t(value), tag);
310 }
311 }
312
313 template <typename T>
314 std::optional<T>
315 get_nothrow(const std::string name)
316 {
317 auto it = items.find(name);
318 if (it == items.end())
319 {
320 return {};
321 }
322 it->second.isRead = true;
323 if (const T* val = std::get_if<T>(&(it->second.data)))
324 {
325 return {*val};
326 }
327 return {};
328 }
329
330 template <typename T>
331 T
332 get(const std::string name)
333 {
334 auto it = items.find(name);
335 if (it == items.end())
336 {
337 throw ConfigElementNotFoundError("Config item with name " + name + " and type " +
338 type_name<T>() + " not found (name not found)");
339 }
340 it->second.isRead = true;
341 if (const T* val = std::get_if<T>(&(it->second.data)))
342 {
343 return *val;
344 }
345 throw ConfigElementNotFoundError("Config item with name " + name + " and type " +
346 type_name<T>() + " not found (types do not match)");
347 }
348 };
349
350 /**
351 * @brief Config with additional Config objects for controllers
352 */
354 {
355 friend class ConfigParser;
356 friend class DeviceConfig;
357
358 public:
360 {
361 }
362
363 Config& getControllerConfig(const std::string controllerName);
364
365 protected:
367
368 /**
369 * @brief Add a Config for a controller with name
370 * @param controllerName name of the controller
371 * @param controllerConfig Config object
372 */
373 void addControllerConfig(const std::string controllerName,
374 std::shared_ptr<Config> controllerConfig);
375
376 std::map<std::string, std::shared_ptr<Config>> controllerConfigs;
377 };
378
379 /**
380 * @brief Create an error message that prints part of the current Config object to make
381 * it easiier to find the place with the erro rin the xml file
382 * @param message The message that should be printed
383 * @param context The Config object that should serve as context
384 * @return
385 */
386 std::string createErrorMessageWithContext(std::string message, const Config& context);
387
388} // namespace armarx::control::hardware_config
#define float
Definition 16_Level.h:22
The ConfigElementNotFoundError class represents an error that is thrown when trying to get a config v...
Definition Errors.h:25
The ConfigInsertError class represents an error that is thrown if an attempt is mode to set a config ...
Definition Errors.h:13
The Config class is the base class of all specialized configurations that have a direct key -> value ...
Definition Config.h:94
void setModularConvertedValueConfig(const std::string name, types::ModularConvertedValueConfig &&value, ConfigTag tag)
Definition Config.cpp:235
std::list< std::int32_t > getIntList(const std::string name)
Get a IntList (std::list<std::int32_t>) typed Config attribute by name.
Definition Config.cpp:70
std::string getString(const std::string name)
Get a String typed Config attribute by name.
Definition Config.cpp:46
Eigen::Matrix< Type, Rows, Columns > getMatrix(const std::string name)
Get a Matrix by name.
Definition Config.h:200
void setInt(const std::string name, std::int32_t value, ConfigTag tag)
Definition Config.cpp:223
virtual void print(std::stringstream &s, int indention) const
Print this configuration.
Definition Config.cpp:121
types::LinearConfig getLinearConfig(const std::string name)
Get a LinearConvertedValue typed Config attribute by name.
Definition Config.cpp:34
void setBool(const std::string name, bool value, ConfigTag tag)
Definition Config.cpp:205
float getFloat(const std::string name)
Get a Float typed Config attribute by name.
Definition Config.cpp:16
T get(const std::string name)
Definition Config.h:332
virtual void onParsingFinished()
This method is called when the config is completely read form the HardwareConfig file.
Definition Config.cpp:315
void setFloatList(const std::string name, std::list< float > value, ConfigTag tag)
Definition Config.cpp:255
void set(const std::string name, T value, ConfigTag tag)
Definition Config.h:272
std::list< bool > getBoolList(const std::string name)
Get a BoolList (std::list<bool>) typed Config attribute by name.
Definition Config.cpp:52
types::ModularConvertedValueConfig getModularConvertedValueConfig(const std::string &name)
Get a ModularConvertedValue typed Config attribute by name.
Definition Config.cpp:40
std::uint32_t getUint(const std::string name)
Get a Uint (std::uint32_t) typed Config attribute by name.
Definition Config.cpp:22
virtual bool checkAllItemsRead(std::vector< std::string > &errors) const
This method is called once the device has read the configuration data it needs.
Definition Config.cpp:76
bool getBool(const std::string name)
Get a Bool typed Config attribute by name.
Definition Config.cpp:10
std::list< std::uint32_t > getUintList(const std::string name)
Get a UIntList (std::list<std::uint32_t>) typed Config attribute by name.
Definition Config.cpp:64
void setString(const std::string name, std::string value, ConfigTag tag)
Definition Config.cpp:243
std::map< std::string, ConfigItemWithMetadata > items
Definition Config.h:252
void setUint(const std::string name, std::uint32_t value, ConfigTag tag)
Definition Config.cpp:217
void setLinearConfig(const std::string name, types::LinearConfig &&value, ConfigTag tag)
Definition Config.cpp:229
std::optional< T > get_nothrow(const std::string name)
Definition Config.h:315
std::list< float > getFloatList(const std::string name)
Get a FloatList (std::list<float>) typed Config attribute by name.
Definition Config.cpp:58
void setUintList(const std::string name, std::list< std::uint32_t > value, ConfigTag tag)
Definition Config.cpp:261
void setBoolList(const std::string name, std::list< bool > value, ConfigTag tag)
Definition Config.cpp:249
void setIntList(const std::string name, std::list< std::int32_t > value, ConfigTag tag)
Definition Config.cpp:267
void setFloat(const std::string name, float value, ConfigTag tag)
Definition Config.cpp:211
std::int32_t getInt(const std::string name)
Get a Int (std::int32_t) typed Config attribute by name.
Definition Config.cpp:28
Config with additional Config objects for controllers.
Definition Config.h:354
void addControllerConfig(const std::string controllerName, std::shared_ptr< Config > controllerConfig)
Add a Config for a controller with name.
Definition Config.cpp:284
std::map< std::string, std::shared_ptr< Config > > controllerConfigs
Definition Config.h:376
Config & getControllerConfig(const std::string controllerName)
Definition Config.cpp:273
The LinearConfig class represents a linear conversion and has a factor and offset.
Definition Types.h:17
std::string createErrorMessageWithContext(std::string message, const Config &context)
Create an error message that prints part of the current Config object to make it easiier to find the ...
Definition Config.cpp:325
ConfigTag
The ConfigTag is used when setting a config value.
Definition Config.h:62
std::variant< bool, float, std::uint32_t, std::int32_t, std::list< bool >, std::list< float >, std::list< std::uint32_t >, std::list< std::int32_t >, types::LinearConfig, types::ModularConvertedValueConfig, std::string, Eigen::Matrix< float, Eigen::Dynamic, Eigen::Dynamic >, Eigen::Matrix< std::uint32_t, Eigen::Dynamic, Eigen::Dynamic >, Eigen::Matrix< std::int32_t, Eigen::Dynamic, Eigen::Dynamic > > var_t
The variant type of the config map.
Definition Config.h:40
std::string tagName(ConfigTag tag)
Definition Config.cpp:301
The ConfigItemWithMetadata struct packs the data together with the tag and a isRead flag.
Definition Config.h:73