libvisiontransfer  10.6.0
parameter.h
1 /*******************************************************************************
2  * Copyright (c) 2023 Allied Vision Technologies 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  inline 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 = isCommand() ? false : 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  bool ensureValidDefault();
271  bool ensureValidCurrent();
273  template<typename T> T enforceIncrement(T t);
275  template<typename T>
276  Parameter& setDefault(T t) {
277  defaultValue.setType(getType());
278  defaultValue.setValue(enforceIncrement(t));
279  ensureValidDefault();
280  return *this;
281  }
283  template<typename T>
284  Parameter& setRange(T mn, T mx) {
285  minValue.setType(type);
286  maxValue.setType(type);
287  minValue.setValue(mn);
288  maxValue.setValue(mx);
289  ensureValidDefault();
290  ensureValidCurrent();
291  return *this;
292  }
294  Parameter& unsetRange() {
295  minValue.setType(ParameterValue::ParameterType::TYPE_UNDEFINED);
296  maxValue.setType(ParameterValue::ParameterType::TYPE_UNDEFINED);
297  ensureValidDefault();
298  ensureValidCurrent();
299  return *this;
300  }
302  template<typename T>
303  Parameter& setIncrement(T t) {
304  incrementValue.setType(type);
305  incrementValue.setValue(t);
306  ensureValidDefault();
307  ensureValidCurrent();
308  return *this;
309  }
311  template<typename T>
312  Parameter& setCurrent(T t) {
313  currentValue.setType(getType());
314  currentValue.setValue(enforceIncrement(t));
315  ensureValidCurrent();
316  return *this;
317  }
319  Parameter& setCurrentFrom(const Parameter& from);
321  Parameter& setCurrentFromDefault();
323  template<typename T>
324  Parameter& setOptions(const std::vector<T>& opts, const std::vector<std::string>& descriptions) {
325  if (opts.size() != descriptions.size()) throw std::runtime_error("Option list and description list of mismatched size");
326  validOptions.clear();
327  validOptionDescriptions.clear();
328  for (unsigned int i=0; i<opts.size(); ++i) {
329  validOptions.push_back(ParameterValue().setType(type).setValue(opts[i]));
330  validOptionDescriptions.push_back(descriptions[i]);
331  }
332  ensureValidDefault();
333  ensureValidCurrent();
334  return *this;
335  }
337  template<typename T>
338  Parameter& setOptions(std::initializer_list<T> opts, std::initializer_list<std::string> descriptions) {
339  std::vector<T> tmpOpts(opts);
340  std::vector<std::string> tmpComm(descriptions);
341  return setOptions(tmpOpts, tmpComm);
342  }
344  template<typename T>
345  std::vector<T> getOptions() const {
346  std::vector<T> vec;
347  for (auto& o: validOptions) {
348  vec.push_back(o.getValue<T>());
349  }
350  return vec;
351  }
353  std::vector<std::string> getOptionDescriptions() const {
354  return validOptionDescriptions;
355  }
357  inline ParameterValue getCurrentParameterValue() {
358  if (hasCurrent()) {
359  return currentValue;
360  } else {
361  if (hasDefault()) {
362  return defaultValue;
363  } else {
364  throw std::runtime_error(std::string("Tried getCurrent(), but no value set and no default defined for ") + getUid());
365  }
366  }
367  }
369  template<typename T>
370  T getCurrent() const {
371  if (hasCurrent()) {
372  return currentValue.getValue<T>();
373  } else {
374  if (hasDefault()) {
375  return defaultValue.getValue<T>();
376  } else {
377  throw std::runtime_error(std::string("Tried getCurrent(), but no value set and no default defined for ") + getUid());
378  }
379  }
380  }
381  inline ParameterValue getDefaultParameterValue() {
382  return defaultValue;
383  }
385  template<typename T>
386  T getDefault() const {
387  return defaultValue.getValue<T>();
388  }
390  template<typename T>
391  T getMin() const {
392  return minValue.isDefined() ? (minValue.getValue<T>()) : (std::numeric_limits<T>::lowest());
393  }
395  template<typename T>
396  T getMax() const {
397  return maxValue.isDefined() ? (maxValue.getValue<T>()) : ((std::numeric_limits<T>::max)());
398  }
400  template<typename T>
401  T getIncrement() const {
402  return incrementValue.isDefined() ? (incrementValue.getValue<T>()) : internal::ConversionHelpers::toStringIfStringExpected<T>(1);
403  }
405  bool hasOptions() const {
406  return validOptions.size() > 0;
407  }
409  bool hasCurrent() const {
410  if (type == ParameterValue::ParameterType::TYPE_TENSOR) {
411  // For tensors: the data array must also have been set first
412  return currentValue.isDefined() && (currentValue.getTensorCurrentDataSize() == currentValue.getTensorNumElements());
413  } else {
414  return currentValue.isDefined();
415  }
416  }
418  bool hasDefault() const {
419  if (defaultValue.isTensor()) {
420  // For tensors: the data array must also have been set first
421  return defaultValue.isDefined() && (defaultValue.getTensorCurrentDataSize() == defaultValue.getTensorNumElements());
422  } else {
423  return defaultValue.isDefined();
424  }
425  }
427  bool hasRange() const {
428  return maxValue.isDefined();
429  }
431  bool hasIncrement() const {
432  return incrementValue.isDefined();
433  }
435  double at(unsigned int x) { return getCurrentParameterValue().tensorElementAt(x); }
437  double at(unsigned int y, unsigned int x) { return getCurrentParameterValue().tensorElementAt(y, x); }
439  double at(unsigned int z, unsigned int y, unsigned int x) { return getCurrentParameterValue().tensorElementAt(z, y, x); }
440 
441 
442 private:
443  std::string uid;
444  std::string name;
445  std::string modulename; // Broad association to a module (e.g. "settings", "cam0", "cam1", etc.)
446  std::string categoryname; // Free-form, module specific, category grouping (e.g. Aravis feature categories)
447  std::string description;
448  std::string unit;
449  ParameterValue::ParameterType type;
450 
451  ParameterValue defaultValue;
452  ParameterValue currentValue;
453  ParameterValue minValue; // minValue.isUndefined() until range has been set
454  ParameterValue maxValue;
455  ParameterValue incrementValue; // incrementValue.isUndefined() until increment set
456  std::vector<ParameterValue> validOptions;
457  std::vector<std::string> validOptionDescriptions;
458 
459  // The following fields are used in nvparamd (the master) and not set elsewhere
460  GovernorType governorType;
461  std::string governorString; // D-Bus address or shell command line, respectively
462  // 'oninit' action - ignore, or the same as on a change.
463  // This is only used in the parameter daemon, this variable need not be relayed.
464  bool invokeGovernorOnInit;
465 
466  ParameterAccessMode accessForConfig;
467  ParameterAccessMode accessForApi;
468 
469  ParameterInteractionHint interactionHint;
470  bool isModified;
471 };
472 
473 } // namespace param
474 } // namespace visiontransfer
475 
476 #endif
477 
478 
visiontransfer::internal::ConversionHelpers::anyToDouble
static double anyToDouble(T val)
Converts any type to a double.
Definition: conversionhelpers.h:71
visiontransfer::param::ParameterValue
Definition: parametervalue.h:59
visiontransfer::param::Parameter::setType
Parameter & setType(ParameterValue::ParameterType t)
Definition: parameter.h:260
visiontransfer::param::Parameter::setTensorData
Parameter & setTensorData(const std::vector< double > &data)
Definition: parameter.h:175
visiontransfer::param::Parameter
Definition: parameter.h:71
Allied Vision