libvisiontransfer  10.0.0
parameter.h
1 /*******************************************************************************
2  * Copyright (c) 2022 Nerian Vision GmbH
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *******************************************************************************/
14 
15 #ifndef VISIONTRANSFER_PARAMETER_H
16 #define VISIONTRANSFER_PARAMETER_H
17 
18 #include <string>
19 #include <vector>
20 #include <map>
21 
22 #include <cstring>
23 #include <sstream>
24 #include <iomanip>
25 #include <limits>
26 #include <memory>
27 
28 #include <visiontransfer/common.h>
29 #include <visiontransfer/parametervalue.h>
30 #include <visiontransfer/conversionhelpers.h>
31 
32 namespace visiontransfer {
33 namespace param {
34 
47 class VT_EXPORT Parameter {
48 public:
49  enum GovernorType {
50  GOVERNOR_NONE = 0,
51  GOVERNOR_SHELL = 1,
52  GOVERNOR_DBUS = 2
53  };
54 
55  enum ParameterAccessMode {
56  ACCESS_NONE = 0,
57  ACCESS_READONLY = 1,
58  ACCESS_READWRITE = 2
59  };
60 
61  enum ParameterInteractionHint {
62  INTERACTION_INVISIBLE = -1,
63  INTERACTION_INACTIVE = 0,
64  INTERACTION_ACTIVE = 1
65  };
66 
68  Parameter(): uid("undefined"), name("undefined"), governorType(GOVERNOR_NONE), invokeGovernorOnInit(false), accessForConfig(ACCESS_NONE), accessForApi(ACCESS_NONE), interactionHint(INTERACTION_ACTIVE), isModified(false) {}
70  Parameter(const std::string& uid);
72  std::string getUid() const { return uid; }
74  std::string getName() const { return name; }
76  std::string getModuleName() const { return modulename; }
78  std::string getCategoryName() const { return categoryname; }
80  std::string getDescription() const { return description; }
82  std::string getUnit() const { return unit; }
84  ParameterValue::ParameterType getType() const { return type; }
86  ParameterAccessMode getAccessForConfig() const { return accessForConfig; }
88  ParameterAccessMode getAccessForApi() const { return accessForApi; }
90  inline Parameter& setAccessForConfig(ParameterAccessMode mode) { accessForConfig = mode; return *this; }
92  inline Parameter& setAccessForApi(ParameterAccessMode mode) { accessForApi = mode; return *this; }
94  ParameterInteractionHint getInteractionHint() const { return interactionHint; }
96  inline Parameter& setInteractionHint(ParameterInteractionHint hint) { interactionHint = hint; return *this; }
98  bool getIsModified() const { return isModified; }
100  inline Parameter& setIsModified(bool mod) { isModified = mod; return *this; }
102  GovernorType getGovernorType() const { return governorType; }
104  std::string getGovernorString() const { return governorString; }
106  inline Parameter& setGovernor(GovernorType govType, const std::string& govStr) { governorType = govType; governorString = govStr; return *this; }
108  bool getInvokeGovernorOnInit() const { return invokeGovernorOnInit; }
110  Parameter& setInvokeGovernorOnInit(bool invoke) { invokeGovernorOnInit = invoke; return *this; }
114  std::string interpolateCommandLine(const ParameterValue& newVal);
116  bool isTensor() const { return type == ParameterValue::ParameterType::TYPE_TENSOR; }
118  bool isScalar() const { return type != ParameterValue::ParameterType::TYPE_TENSOR; }
120  bool isCommand() const { return currentValue.isCommand(); }
122  unsigned int getTensorDimension() const {
123  return currentValue.isDefined() ? currentValue.getTensorDimension() : defaultValue.getTensorDimension(); }
125  std::vector<unsigned int> getTensorShape() const {
126  return currentValue.isDefined() ? currentValue.getTensorShape() : defaultValue.getTensorShape();}
128  unsigned int getTensorNumElements() const {
129  return currentValue.isDefined() ? currentValue.getTensorNumElements() : defaultValue.getTensorNumElements();}
131  std::vector<double> getTensorData() const;
133  std::vector<double> getTensorDefaultData() const;
135  std::vector<double>& getTensorDataReference();
137  std::vector<double>& getTensorDefaultDataReference();
139  inline Parameter& setTensorData(const std::vector<double>& data) {
140  currentValue.setTensorData(data);
141  return *this;
142  }
144  inline Parameter& setTensorDefaultData(const std::vector<double>& data) {
145  defaultValue.setTensorData(data);
146  return *this;
147  }
148 #ifdef CV_MAJOR_VERSION
149 
150  inline Parameter& setTensorFromCvSize(const cv::Size& cvSize) {
151  if (currentValue.isDefined() && !(currentValue.isTensor())) {
152  throw std::runtime_error("Parameter::setTensorFromCvSize(): refused to overwrite existing non-tensor type");
153  }
154  if (isTensor() && (getTensorNumElements()!=0)) {
155  // Already a tensor; only allow replacement with Size if prior size was 2
156  if (getTensorNumElements() != 2) throw std::runtime_error("Parameter::setTensorFromSize(): refused to overwrite tensor with size != 2");
157  } else {
158  // Newly defined as a Tensor, set as two-element vector
159  setAsTensor({2});
160  }
161  std::vector<double> data = { (double) cvSize.width, (double) cvSize.height };
162  currentValue.setTensorData(data);
163  defaultValue.setTensorData(data);
164  return *this;
165  }
167  inline void setCvSizeFromTensor(cv::Size& cvSize) {
168  if (getTensorNumElements() != 2) throw std::runtime_error("Parameter::setCvSizeFromTensor(): refused to export Tensor of size!=2 to cv::Size");
169  auto val = getCurrentParameterValue();
170  cvSize = cv::Size((int) val.tensorElementAt(0), (int) val.tensorElementAt(1));
171  }
173  template<typename T>
174  inline Parameter& setTensorFromCvMat(const cv::Mat_<T>& cvMat) {
175  if (currentValue.isDefined() && !(currentValue.isTensor())) {
176  throw std::runtime_error("Parameter::setTensorFromCvMat(): refused to overwrite existing non-tensor type");
177  }
178  std::vector<unsigned int> dims = { (unsigned int) cvMat.rows, (unsigned int) cvMat.cols };
179  if (isTensor() && (getTensorNumElements()!=0)) {
180  // Already a tensor; only allow replacement with Mat data of matching size
181  if (getTensorNumElements() != dims[0]*dims[1]) throw std::runtime_error("Parameter::setTensorFromCvMat(): refused to overwrite tensor with cv::Mat of mismatching total size");
182  } else {
183  // Newly defined as a Tensor, copy the Cv shape
184  setAsTensor(dims);
185  }
186  // Not the fastest way, but less hassle than coping with array casts
187  std::vector<double> data;
188  for (unsigned int r=0; r<(unsigned int) cvMat.rows; ++r)
189  for (unsigned int c=0; c<(unsigned int) cvMat.cols; ++c) {
190  data.push_back((double) cvMat(r, c));
191  }
192  currentValue.setTensorData(data);
193  defaultValue.setTensorData(data);
194  return *this;
195  }
197  template<typename T>
198  inline void setCvMatFromTensor(cv::Mat_<T>& cvMat) {
199  if (getTensorDimension() != 2) {
200  std::ostringstream ss;
201  ss << "{";
202  for (unsigned int i=0; i<getTensorDimension(); ++i) {
203  ss << getTensorShape()[i] << ", ";
204  }
205  ss << "}";
206  ss << " " << getUid() << " " << ((int)getType());
207  throw std::runtime_error(std::string("Parameter::setCvMatFromTensor(): refused to export non-2D Tensor to cv::Mat, offending shape is: ")+ss.str());
208  }
209  auto& refData = getTensorDataReference();
210  cv::Mat_<T>(getTensorShape()[0], getTensorShape()[1], (T*)&refData[0]).copyTo(cvMat);
211  }
212 #endif // CV_MAJOR_VERSION
213 
214  inline Parameter& setName(const std::string& name) { this->name = name; return *this; }
216  inline Parameter& setModuleName(const std::string& n) { this->modulename = n; return *this; }
218  inline Parameter& setCategoryName(const std::string& n) { this->categoryname = n; return *this; }
220  inline Parameter& setDescription(const std::string& d) { this->description = d; return *this; }
222  inline Parameter& setUnit(const std::string& d) { this->unit = d; return *this; }
224  inline Parameter& setType(ParameterValue::ParameterType t) {
225  this->type = t;
226  // min, max, increment, options left undefined here
227  if (t==ParameterValue::ParameterType::TYPE_COMMAND) {
228  // Commands no not have to have an initialized prior value
229  defaultValue.setType(this->type);
230  currentValue.setType(this->type);
231  defaultValue.setValue("");
232  currentValue.setValue("");
233  }
234  return *this;
235  }
237  inline Parameter& setAsTensor(const std::vector<unsigned int>& shape) {
238  setType(ParameterValue::TYPE_TENSOR);
239  defaultValue.setTensorShape(shape);
240  currentValue.setTensorShape(shape);
241  return *this;
242  }
244  template<typename T>
245  bool isValidNewValue(T t) const {
246  if (validOptions.size()) {
247  // enum-style list of options
248  for (auto& o: validOptions) {
249  if (o.getValue<T>() == t) return true;
250  }
251  return false;
252  } else {
253  if ((type==ParameterValue::ParameterType::TYPE_INT) || (type==ParameterValue::ParameterType::TYPE_DOUBLE)) {
254  if (minValue.isUndefined() || maxValue.isUndefined()) {
255  // unlimited range numerical
256  return true;
257  } else {
258  // limited range numerical
260  return val>=minValue.getValue<double>() && val<=maxValue.getValue<double>();
261  }
262  } else {
263  // non-numerical, cannot range-restrict
264  return true;
265  }
266  }
267  }
269  template<typename T> T enforceIncrement(T t);
271  template<typename T>
273  if (isValidNewValue(t)) {
274  defaultValue.setType(this->type);
275  defaultValue.setValue(enforceIncrement(t));
276  } else throw std::runtime_error(std::string("Unchecked invalid default value ") + internal::ConversionHelpers::anyToString(t) + " for parameter " + getUid());
277  return *this;
278  }
280  template<typename T>
281  Parameter& setRange(T mn, T mx) {
282  minValue.setType(type);
283  maxValue.setType(type);
284  minValue.setValue(mn);
285  maxValue.setValue(mx);
286  return *this;
287  }
289  template<typename T>
291  incrementValue.setType(type);
292  incrementValue.setValue(t);
293  return *this;
294  }
296  template<typename T>
298  if (isValidNewValue(t)) {
299  currentValue.setType(this->type);
300  currentValue.setValue(enforceIncrement(t));
301  return *this;
302  } else throw std::runtime_error(std::string("Unchecked invalid value ") + internal::ConversionHelpers::anyToString(t) + " for parameter " + getUid());
303  }
305  Parameter& setCurrentFrom(const Parameter& from);
307  Parameter& setCurrentFromDefault();
309  template<typename T>
310  Parameter& setOptions(const std::vector<T>& opts, const std::vector<std::string>& descriptions) {
311  if (opts.size() != descriptions.size()) throw std::runtime_error("Option list and description list of mismatched size");
312  validOptions.clear();
313  for (unsigned int i=0; i<opts.size(); ++i) {
314  validOptions.push_back(ParameterValue().setType(type).setValue(opts[i]));
315  validOptionDescriptions.push_back(descriptions[i]);
316  }
317  return *this;
318  }
320  template<typename T>
321  Parameter& setOptions(std::initializer_list<T> opts, std::initializer_list<std::string> descriptions) {
322  std::vector<T> tmpOpts(opts);
323  std::vector<std::string> tmpComm(descriptions);
324  return setOptions(tmpOpts, tmpComm);
325  }
327  template<typename T>
328  std::vector<T> getOptions() const {
329  std::vector<T> vec;
330  for (auto& o: validOptions) {
331  vec.push_back(o.getValue<T>());
332  }
333  return vec;
334  }
336  std::vector<std::string> getOptionDescriptions() const {
337  return validOptionDescriptions;
338  }
341  if (hasCurrent()) {
342  return currentValue;
343  } else {
344  if (hasDefault()) {
345  return defaultValue;
346  } else {
347  throw std::runtime_error(std::string("Tried getCurrent(), but no value set and no default defined for ") + getUid());
348  }
349  }
350  }
352  template<typename T>
353  T getCurrent() const {
354  if (hasCurrent()) {
355  return currentValue.getValue<T>();
356  } else {
357  if (hasDefault()) {
358  return defaultValue.getValue<T>();
359  } else {
360  throw std::runtime_error(std::string("Tried getCurrent(), but no value set and no default defined for ") + getUid());
361  }
362  }
363  }
364  inline ParameterValue getDefaultParameterValue() {
365  return defaultValue;
366  }
368  template<typename T>
369  T getDefault() const {
370  return defaultValue.getValue<T>();
371  }
373  template<typename T>
374  T getMin() const {
375  return minValue.isDefined() ? (minValue.getValue<T>()) : (std::numeric_limits<T>::lowest());
376  }
378  template<typename T>
379  T getMax() const {
380  return maxValue.isDefined() ? (maxValue.getValue<T>()) : (std::numeric_limits<T>::max());
381  }
383  template<typename T>
384  T getIncrement() const {
385  return incrementValue.isDefined() ? (incrementValue.getValue<T>()) : internal::ConversionHelpers::toStringIfStringExpected<T>(1);
386  }
388  bool hasOptions() const {
389  return validOptions.size() > 0;
390  }
392  bool hasCurrent() const {
393  if (type == ParameterValue::ParameterType::TYPE_TENSOR) {
394  // For tensors: the data array must also have been set first
395  return currentValue.isDefined() && (currentValue.getTensorCurrentDataSize() == currentValue.getTensorNumElements());
396  } else {
397  return currentValue.isDefined();
398  }
399  }
401  bool hasDefault() const {
402  if (defaultValue.isTensor()) {
403  // For tensors: the data array must also have been set first
404  return defaultValue.isDefined() && (defaultValue.getTensorCurrentDataSize() == defaultValue.getTensorNumElements());
405  } else {
406  return defaultValue.isDefined();
407  }
408  }
410  bool hasRange() const {
411  return maxValue.isDefined();
412  }
414  bool hasIncrement() const {
415  return incrementValue.isDefined();
416  }
418  double at(unsigned int x) { return getCurrentParameterValue().tensorElementAt(x); }
420  double at(unsigned int y, unsigned int x) { return getCurrentParameterValue().tensorElementAt(y, x); }
422  double at(unsigned int z, unsigned int y, unsigned int x) { return getCurrentParameterValue().tensorElementAt(z, y, x); }
423 
424 
425 private:
426  std::string uid;
427  std::string name;
428  std::string modulename; // Broad association to a module (e.g. "settings", "cam0", "cam1", etc.)
429  std::string categoryname; // Free-form, module specific, category grouping (e.g. Aravis feature categories)
430  std::string description;
431  std::string unit;
432  ParameterValue::ParameterType type;
433 
434  ParameterValue defaultValue;
435  ParameterValue currentValue;
436  ParameterValue minValue; // minValue.isUndefined() until range has been set
437  ParameterValue maxValue;
438  ParameterValue incrementValue; // incrementValue.isUndefined() until increment set
439  std::vector<ParameterValue> validOptions;
440  std::vector<std::string> validOptionDescriptions;
441 
442  // The following fields are used in nvparamd (the master) and not set elsewhere
443  GovernorType governorType;
444  std::string governorString; // D-Bus address or shell command line, respectively
445  // 'oninit' action - ignore, or the same as on a change.
446  // This is only used in the parameter daemon, this variable need not be relayed.
447  bool invokeGovernorOnInit;
448 
449  ParameterAccessMode accessForConfig;
450  ParameterAccessMode accessForApi;
451 
452  ParameterInteractionHint interactionHint;
453  bool isModified;
454 };
455 
456 } // namespace param
457 } // namespace visiontransfer
458 
459 #endif
460 
461 
Parameter & setType(ParameterValue::ParameterType t)
Definition: parameter.h:224
Parameter & setOptions(std::initializer_list< T > opts, std::initializer_list< std::string > descriptions)
Definition: parameter.h:321
Parameter & setIncrement(T t)
Definition: parameter.h:290
Parameter & setIsModified(bool mod)
Definition: parameter.h:100
bool isValidNewValue(T t) const
Definition: parameter.h:245
Parameter & setTensorFromCvMat(const cv::Mat_< T > &cvMat)
Definition: parameter.h:174
unsigned int getTensorDimension() const
Definition: parameter.h:122
std::string getCategoryName() const
Definition: parameter.h:78
Parameter & setModuleName(const std::string &n)
Definition: parameter.h:216
std::string getUnit() const
Definition: parameter.h:82
std::string getDescription() const
Definition: parameter.h:80
ParameterValue getCurrentParameterValue()
Definition: parameter.h:340
double at(unsigned int x)
Definition: parameter.h:418
ParameterAccessMode getAccessForApi() const
Definition: parameter.h:88
ParameterInteractionHint getInteractionHint() const
Definition: parameter.h:94
static double anyToDouble(T val)
Converts any type to a double.
std::string getName() const
Definition: parameter.h:74
Parameter & setTensorDefaultData(const std::vector< double > &data)
Definition: parameter.h:144
Parameter & setOptions(const std::vector< T > &opts, const std::vector< std::string > &descriptions)
Definition: parameter.h:310
Parameter & setDescription(const std::string &d)
Definition: parameter.h:220
double at(unsigned int z, unsigned int y, unsigned int x)
Definition: parameter.h:422
double at(unsigned int y, unsigned int x)
Definition: parameter.h:420
std::vector< std::string > getOptionDescriptions() const
Definition: parameter.h:336
std::string getUid() const
Definition: parameter.h:72
Parameter & setInteractionHint(ParameterInteractionHint hint)
Definition: parameter.h:96
Parameter & setAccessForConfig(ParameterAccessMode mode)
Definition: parameter.h:90
Parameter & setAccessForApi(ParameterAccessMode mode)
Definition: parameter.h:92
std::string getModuleName() const
Definition: parameter.h:76
Parameter & setGovernor(GovernorType govType, const std::string &govStr)
Definition: parameter.h:106
std::vector< unsigned int > getTensorShape() const
Definition: parameter.h:125
ParameterValue::ParameterType getType() const
Definition: parameter.h:84
std::string getGovernorString() const
Definition: parameter.h:104
GovernorType getGovernorType() const
Definition: parameter.h:102
Parameter & setAsTensor(const std::vector< unsigned int > &shape)
Definition: parameter.h:237
static std::string anyToString(T val)
Converts any type to a string.
void setCvSizeFromTensor(cv::Size &cvSize)
Definition: parameter.h:167
Parameter & setUnit(const std::string &d)
Definition: parameter.h:222
void setCvMatFromTensor(cv::Mat_< T > &cvMat)
Definition: parameter.h:198
Parameter & setTensorData(const std::vector< double > &data)
Definition: parameter.h:139
Parameter & setRange(T mn, T mx)
Definition: parameter.h:281
unsigned int getTensorNumElements() const
Definition: parameter.h:128
std::vector< T > getOptions() const
Definition: parameter.h:328
bool getInvokeGovernorOnInit() const
Definition: parameter.h:108
Parameter & setTensorFromCvSize(const cv::Size &cvSize)
Definition: parameter.h:150
ParameterAccessMode getAccessForConfig() const
Definition: parameter.h:86
Parameter & setName(const std::string &name)
Definition: parameter.h:214
Parameter & setCategoryName(const std::string &n)
Definition: parameter.h:218
Parameter & setInvokeGovernorOnInit(bool invoke)
Definition: parameter.h:110
Nerian Vision Technologies