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;
75 
77  {
78  }
79 
82  bool isRead;
83  };
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 
204  auto mVal = get<Eigen::Matrix<Type, Eigen::Dynamic, Eigen::Dynamic>>(name);
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:
366  ControllerConfig(const ControllerConfig& orig);
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
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:273
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:16
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:244
armarx::control::hardware_config::ConfigItemWithMetadata::data
var_t data
Definition: Config.h:80
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:855
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:315
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:325
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:301
armarx::control::hardware_config::types::ModularConvertedValueConfig
Definition: Types.h:66
armarx::control::hardware_config::ConfigItemWithMetadata::tag
ConfigTag tag
Definition: Config.h:81
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:315
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:252
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:93
armarx::control::hardware_config::ControllerConfig::ControllerConfig
ControllerConfig()
Definition: Config.h:359
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:332
armarx::control::hardware_config::ConfigItemWithMetadata::ConfigItemWithMetadata
ConfigItemWithMetadata(var_t data, ConfigTag tag)
Definition: Config.h:76
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:38
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:376
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:200
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:353
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:284
armarx::control::hardware_config::Config::set
void set(const std::string name, T value, ConfigTag tag)
Definition: Config.h:272
armarx::control::hardware_config::ConfigItemWithMetadata::isRead
bool isRead
Definition: Config.h:82