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