1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237 | /**
* @file ParameterList.h
*
* @author <a href="mailto:aschulz@informatik.hu-berlin.de">Alexander Schulz</a>
* @author <a href="mailto:krause@informatik.hu-berlin.de">Thomas Krause</a>
* This class is intendes as superclass of all Representations holding parameters that can be changed
* via the debug-console
*/
#ifndef _ParameterList_h_
#define _ParameterList_h_
#include <map>
#include <list>
#include <string>
// TODO: maybe it can be made prinable in the future
#include <ostream>
//#include <Tools/DataStructures/Printable.h>
#include <Tools/Debug/NaoTHAssert.h>
#include <Tools/Math/Common.h>
#include <Representations/Infrastructure/Configuration.h>
//NOTE: it would be goo for ParameterList to be naoth::Printable but it might lead to inheritance issues
class ParameterList
{
public:
class ConfigParameter {
public:
const std::string name;
ConfigParameter(const std::string& name) : name(name) {}
public:
virtual ~ConfigParameter() {}
virtual void syncWithConfig(naoth::Configuration& config, const std::string& group) = 0;
virtual void writeToConfig(naoth::Configuration& config, const std::string& group) const = 0;
virtual void print(std::ostream& stream) const = 0;
};
protected:
template<class T>
class Parameter : public ConfigParameter
{
public:
Parameter(const std::string& name) : ConfigParameter(name) {}
virtual ~Parameter() {}
virtual void syncWithConfig(naoth::Configuration& config, const std::string& group) {
T v;
if (config.get(group, name, v)) {
set(v);
} else {
config.setDefault(group, name, get());
}
}
virtual void writeToConfig(naoth::Configuration& config, const std::string& group) const {
config.set(group, name, get());
}
virtual void print(std::ostream& stream) const {
stream << name << "=" << get() << std::endl;
}
void operator=( const T& v ) { set(v); }
virtual void set(T v) = 0;
virtual T get() const = 0;
};
template<class T>
class DefaultParameter : public Parameter<T> {
protected:
T* value;
public:
DefaultParameter(const std::string& name, T* value) : Parameter<T>(name), value(value) {}
~DefaultParameter(){}
virtual void set(T v) { *value = v; }
virtual T get() const { ASSERT(value != NULL); return *value; }
};
template<class T>
class ParameterAngleDegrees : public Parameter<T> {
protected:
T* value;
public:
ParameterAngleDegrees(const std::string& name, T* value) : Parameter<T>(name), value(value) {}
~ParameterAngleDegrees(){}
virtual void set(T v) { *value = Math::fromDegrees(v); }
virtual T get() const { ASSERT(value != NULL); return Math::toDegrees(*value); }
};
template<class T, class P>
class CallbackMemberParameter : public DefaultParameter<T> {
protected:
P* parent;
void (P::*callback)(T v);
public:
CallbackMemberParameter(const std::string& name, T* value, void (P::*callback)(T v), P* parent)
: DefaultParameter<T>(name, value),
parent(parent),
callback(callback)
{}
virtual void set(T v) { (parent->*callback)(v); DefaultParameter<T>::set(v); }
};
protected:
// ACHTUNG: never copy the content of the parameter list
ParameterList(const ParameterList& /*obj*/) {}<--- Member variable 'ParameterList::name' is not initialized in the constructor.<--- Member variable 'ParameterList::parameters' is not initialized in the constructor.<--- Member variable 'ParameterList::possibly_changed' is not initialized in the constructor.
ParameterList& operator=( const ParameterList& /*other*/ ) { return *this; }<--- Member variable 'ParameterList::name' is not assigned a value in 'ParameterList::operator='.<--- Member variable 'ParameterList::parameters' is not assigned a value in 'ParameterList::operator='.<--- Member variable 'ParameterList::possibly_changed' is not assigned a value in 'ParameterList::operator='.
ParameterList(const std::string& name) : name(name), possibly_changed(true) {}<--- Class 'ParameterList' has a constructor with 1 argument that is not explicit. [+]Class 'ParameterList' has a constructor with 1 argument that is not explicit. Such constructors should in general be explicit for type safety reasons. Using the explicit keyword in the constructor means some mistakes when using the class can be avoided.
virtual ~ParameterList()
{
for (std::list<ConfigParameter*>::iterator iter = parameters.begin(); iter != parameters.end(); ++iter) {
delete *iter;
}
}
template<template<typename N> class T, typename N>
Parameter<N>& registerParameterT(const std::string& parameterName, N& parameter)
{
T<N>* parameterWrapper = new T<N>(parameterName, ¶meter);
parameters.push_back(parameterWrapper);
return *parameterWrapper;
}
template<typename N>
Parameter<N>& registerParameter(const std::string& parameterName, N& parameter) {
return registerParameterT<DefaultParameter,N>(parameterName, parameter);
}
template<typename N, class P>
Parameter<N>& registerParameter(const std::string& parameterName, N& parameter, void (P::*callback)(N))
{
CallbackMemberParameter<N,P>* parameterWrapper = new CallbackMemberParameter<N,P>(parameterName, ¶meter, callback, reinterpret_cast<P*> (this) );
parameters.push_back(parameterWrapper);
return *parameterWrapper;
}
// change some key characters, e.g. []
static std::string convertName(std::string name);
public:
void syncWithConfig();
void saveToConfig();
const std::string& getName() const { return name; }
// check if any parametsr were changed and reset the flag
bool check_changed() const {
bool change = possibly_changed;
possibly_changed = false;
return change;
}
void print(std::ostream& stream) const
{
for (std::list<ConfigParameter*>::const_iterator iter = parameters.begin(); iter != parameters.end(); ++iter) {
(**iter).print(stream);
}
}
private:
std::string name;
std::list<ConfigParameter*> parameters;
// TODO: du it on per parameter basis
mutable bool possibly_changed;
};
#define PARAMETER_REGISTER(parameter, ...) registerParameter(convertName(#parameter), parameter, ##__VA_ARGS__)
#define PARAMETER_ANGLE_REGISTER(parameter) registerParameterT<ParameterAngleDegrees>(convertName(#parameter), parameter)
#define PARAMETER_REGISTER_OPTIONS(parameter, target, ...) \
typedef decltype(target) callback_##parameter; \
std::map<decltype(parameter), callback_##parameter> options_##parameter = { __VA_ARGS__ }; \
void set_##parameter(decltype(parameter) v) { \
const auto& it = options_##parameter.find(v); \
if(it != options_##parameter.cend()) { target = it->second; } else { ASSERT_MSG(false, "Invalid value for parameter: " + convertName(#parameter)); } \
}
/*
IDEE: Macro, dass die Parameterregistrierung und evtl. zusätzliche Funktionen verwendet/implementiert
PARAMETER_REGISTER(var_name, default):
decltype(default) var_name = default;
static_params_map[#var_name] = lambda[]( registerParameter(convertName(#parameter), parameter, ##__VA_ARGS__) );
PARAMETER_REGISTER(var_name, default, setFn):
PARAMETER_REGISTER(var_name, default, options, ...):
PARAMETER_REGISTER(var_name, default, setFn, options, ...):
*/
/*
// NOTE: this is a example for the usage of the parameter list
namespace ParameterListTest
{
class MyExampleParameters: public ParameterList
{
public:
MyExampleParameters(): ParameterList("MyExampleParameters")
{
PARAMETER_REGISTER(boolParameter) = false;
PARAMETER_REGISTER(intParameter) = 42;
PARAMETER_REGISTER(doubleParameter) = 3.14;
PARAMETER_REGISTER(stringParameter) = "test"; // ms
PARAMETER_REGISTER(intParameter, &MyExampleParameters::setIntParameter) = 42;
PARAMETER_REGISTER(intParameter) = 1000;
PARAMETER_REGISTER(intParameterWithCallback, &MyExampleParameters::setIntParameter) = 1000;
// load from the file after registering all parameters
syncWithConfig();
}
virtual ~MyExampleParameters() {}
bool boolParameter;
int intParameter;
double doubleParameter;
std::string stringParameter;
int intParameterWithCallback;
inline void setIntParameter(int v) { std::cout << "old: " << intParameterWithCallback << " new: " << v << std::endl; }
} myExampleParameters;
};
//*/
#endif // _ParameterList_h_
|