libvisiontransfer  10.8.0
parameter.cpp
1 /*******************************************************************************
2  * Copyright (c) 2024 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 #include <string>
16 #include <vector>
17 #include <cstring>
18 #include <sstream>
19 #include <set>
20 
21 #include <iostream>
22 
23 #include <visiontransfer/parameter.h>
24 
25 namespace visiontransfer {
26 namespace param {
27 
28 using namespace internal;
29 
30 class Parameter::Pimpl {
31 public:
32  Pimpl();
33  Pimpl(const std::string& uid);
34  Pimpl(const Pimpl& other);
35  static void copyData(Pimpl& dst, const Pimpl& src);
36  std::string getUid() const { return uid; }
37  std::string getName() const { return name; }
38  std::string getModuleName() const { return modulename; }
39  std::string getCategoryName() const { return categoryname; }
40  std::string getDescription() const { return description; }
41  std::string getUnit() const { return unit; }
42  inline ParameterValue::ParameterType getType() const { return type; }
43  ParameterAccessMode getAccessForConfig() const { return accessForConfig; }
44  ParameterAccessMode getAccessForApi() const { return accessForApi; }
45  inline Pimpl& setAccessForConfig(ParameterAccessMode mode) { accessForConfig = mode; return *this; }
46  inline Pimpl& setAccessForApi(ParameterAccessMode mode) { accessForApi = mode; return *this; }
47  ParameterInteractionHint getInteractionHint() const { return interactionHint; }
48  inline Pimpl& setInteractionHint(ParameterInteractionHint hint) { interactionHint = hint; return *this; }
49  bool getIsModified() const { return isModified; }
50  bool getIsPolled() const { return isPolledForUpdates; }
51  inline Pimpl& setIsPolled(bool mod) { isPolledForUpdates = isCommand() ? false : mod; return *this; }
52  inline Pimpl& setIsModified(bool mod) { isModified = isCommand() ? false : mod; return *this; }
53  GovernorType getGovernorType() const { return governorType; }
54  std::string getGovernorString() const { return governorString; }
55  inline Pimpl& setGovernor(GovernorType govType, const std::string& govStr) { governorType = govType; governorString = govStr; return *this; }
56  inline Pimpl& setGovernorPollString(const std::string& govStr) { governorPollString = govStr; return *this; }
57  bool getInvokeGovernorOnInit() const { return invokeGovernorOnInit; }
58  Pimpl& setInvokeGovernorOnInit(bool invoke) { invokeGovernorOnInit = invoke; return *this; }
59  std::string interpolateCommandLine(const ParameterValue& newVal, GovernorFunction fn = GOVERNOR_FN_CHANGE_VALUE);
60  bool isTensor() const { return type == ParameterValue::ParameterType::TYPE_TENSOR; }
61  bool isScalar() const { return type != ParameterValue::ParameterType::TYPE_TENSOR; }
62  bool isCommand() const { return currentValue.isCommand(); }
63  unsigned int getTensorDimension() const {
64  return currentValue.isDefined() ? currentValue.getTensorDimension() : defaultValue.getTensorDimension(); }
65  std::vector<unsigned int> getTensorShape() const {
66  return currentValue.isDefined() ? currentValue.getTensorShape() : defaultValue.getTensorShape();}
67  unsigned int getTensorNumElements() const {
68  return currentValue.isDefined() ? currentValue.getTensorNumElements() : defaultValue.getTensorNumElements();}
69  std::vector<double> getTensorData() const;
70  std::vector<double> getTensorDefaultData() const;
71  std::vector<double>& getTensorDataReference();
72  std::vector<double>& getTensorDefaultDataReference();
73  inline Pimpl& setTensorData(const std::vector<double>& data) {
74  currentValue.setTensorData(data);
75  return *this;
76  }
77  inline Pimpl& setTensorDefaultData(const std::vector<double>& data) {
78  defaultValue.setTensorData(data);
79  return *this;
80  }
81  inline Pimpl& setName(const std::string& name) { this->name = name; return *this; }
82  inline Pimpl& setModuleName(const std::string& n) { this->modulename = n; return *this; }
83  inline Pimpl& setCategoryName(const std::string& n) { this->categoryname = n; return *this; }
84  inline Pimpl& setDescription(const std::string& d) { this->description = d; return *this; }
85  inline Pimpl& setUnit(const std::string& d) { this->unit = d; return *this; }
86  inline Pimpl& setType(ParameterValue::ParameterType t) {
87  this->type = t;
88  // min, max, increment, options left undefined here
89  if (t==ParameterValue::ParameterType::TYPE_COMMAND) {
90  // Commands no not have to have an initialized prior value
91  defaultValue.setType(this->type);
92  currentValue.setType(this->type);
93  defaultValue.setValue("");
94  currentValue.setValue("");
95  }
96  return *this;
97  }
98  inline Pimpl& setAsTensor(const std::vector<unsigned int>& shape) {
99  setType(ParameterValue::TYPE_TENSOR);
100  defaultValue.setTensorShape(shape);
101  currentValue.setTensorShape(shape);
102  return *this;
103  }
104  template<typename T>
105  bool isValidNewValue(T t) const {
106  if (validOptions.size()) {
107  // enum-style list of options
108  for (auto& o: validOptions) {
109  if (o.getValue<T>() == t) return true;
110  }
111  return false;
112  } else {
113  if ((type==ParameterValue::ParameterType::TYPE_INT) || (type==ParameterValue::ParameterType::TYPE_DOUBLE)) {
114  if (minValue.isUndefined() || maxValue.isUndefined()) {
115  // unlimited range numerical
116  return true;
117  } else {
118  // limited range numerical
120  return val>=minValue.getValue<double>() && val<=maxValue.getValue<double>();
121  }
122  } else {
123  // non-numerical, cannot range-restrict
124  return true;
125  }
126  }
127  }
128  bool ensureValidDefault();
129  bool ensureValidCurrent();
130  template<typename T> T enforceIncrement(T t);
131  template<typename T>
132  Pimpl& setDefault(T t) {
133  defaultValue.setType(getType());
134  defaultValue.setValue(enforceIncrement(t));
135  ensureValidDefault();
136  return *this;
137  }
138  template<typename T>
139  Pimpl& setRange(T mn, T mx) {
140  minValue.setType(type);
141  maxValue.setType(type);
142  minValue.setValue(mn);
143  maxValue.setValue(mx);
144  ensureValidDefault();
145  ensureValidCurrent();
146  return *this;
147  }
148  Pimpl& unsetRange() {
149  minValue.setType(ParameterValue::ParameterType::TYPE_UNDEFINED);
150  maxValue.setType(ParameterValue::ParameterType::TYPE_UNDEFINED);
151  ensureValidDefault();
152  ensureValidCurrent();
153  return *this;
154  }
155  template<typename T>
156  Pimpl& setIncrement(T t) {
157  incrementValue.setType(type);
158  incrementValue.setValue(t);
159  ensureValidDefault();
160  ensureValidCurrent();
161  return *this;
162  }
163  template<typename T>
164  Pimpl& setCurrent(T t) {
165  currentValue.setType(getType());
166  currentValue.setValue(enforceIncrement(t));
167  ensureValidCurrent();
168  return *this;
169  }
170  Pimpl& setCurrentFrom(const Pimpl& from);
171  Pimpl& setCurrentFromDefault();
172  template<typename T>
173  Pimpl& setOptions(const std::vector<T>& opts, const std::vector<std::string>& descriptions) {
174  if (opts.size() != descriptions.size()) throw std::runtime_error("Option list and description list of mismatched size");
175  validOptions.clear();
176  validOptionDescriptions.clear();
177  for (unsigned int i=0; i<opts.size(); ++i) {
178  validOptions.push_back(ParameterValue().setType(type).setValue(opts[i]));
179  validOptionDescriptions.push_back(descriptions[i]);
180  }
181  ensureValidDefault();
182  ensureValidCurrent();
183  return *this;
184  }
185  template<typename T>
186  Pimpl& setOptions(std::initializer_list<T> opts, std::initializer_list<std::string> descriptions) {
187  std::vector<T> tmpOpts(opts);
188  std::vector<std::string> tmpComm(descriptions);
189  return setOptions(tmpOpts, tmpComm);
190  }
191  template<typename T>
192  std::vector<T> getOptions() const {
193  std::vector<T> vec;
194  for (auto& o: validOptions) {
195  vec.push_back(o.getValue<T>());
196  }
197  return vec;
198  }
199  std::vector<std::string> getOptionDescriptions() const {
200  return validOptionDescriptions;
201  }
202  inline ParameterValue getCurrentParameterValue() {
203  if (hasCurrent()) {
204  return currentValue;
205  } else {
206  if (hasDefault()) {
207  return defaultValue;
208  } else {
209  throw std::runtime_error(std::string("Tried getCurrent(), but no value set and no default defined for ") + getUid());
210  }
211  }
212  }
213  template<typename T>
214  T getCurrent() const {
215  if (hasCurrent()) {
216  return currentValue.getValue<T>();
217  } else {
218  if (hasDefault()) {
219  return defaultValue.getValue<T>();
220  } else {
221  throw std::runtime_error(std::string("Tried getCurrent(), but no value set and no default defined for ") + getUid());
222  }
223  }
224  }
225  inline ParameterValue getDefaultParameterValue() {
226  return defaultValue;
227  }
228  template<typename T>
229  T getDefault() const {
230  return defaultValue.getValue<T>();
231  }
232  template<typename T>
233  T getMin() const {
234  return minValue.isDefined() ? (minValue.getValue<T>()) : (std::numeric_limits<T>::lowest());
235  }
236  template<typename T>
237  T getMax() const {
238  return maxValue.isDefined() ? (maxValue.getValue<T>()) : ((std::numeric_limits<T>::max)());
239  }
240  template<typename T>
241  T getIncrement() const {
242  return incrementValue.isDefined() ? (incrementValue.getValue<T>()) : internal::ConversionHelpers::toStringIfStringExpected<T>(1);
243  }
244  bool hasOptions() const {
245  return validOptions.size() > 0;
246  }
247  bool hasCurrent() const {
248  if (type == ParameterValue::ParameterType::TYPE_TENSOR) {
249  // For tensors: the data array must also have been set first
250  return currentValue.isDefined() && (currentValue.getTensorCurrentDataSize() == currentValue.getTensorNumElements());
251  } else {
252  return currentValue.isDefined();
253  }
254  }
255  bool hasDefault() const {
256  if (defaultValue.isTensor()) {
257  // For tensors: the data array must also have been set first
258  return defaultValue.isDefined() && (defaultValue.getTensorCurrentDataSize() == defaultValue.getTensorNumElements());
259  } else {
260  return defaultValue.isDefined();
261  }
262  }
263  bool hasRange() const {
264  return maxValue.isDefined();
265  }
266  bool hasIncrement() const {
267  return incrementValue.isDefined();
268  }
269  double at(unsigned int x) { return getCurrentParameterValue().tensorElementAt(x); }
270  double at(unsigned int y, unsigned int x) { return getCurrentParameterValue().tensorElementAt(y, x); }
271  double at(unsigned int z, unsigned int y, unsigned int x) { return getCurrentParameterValue().tensorElementAt(z, y, x); }
272 
273 
274 private:
275  std::string uid;
276  std::string name;
277  std::string modulename; // Broad association to a module (e.g. "settings", "cam0", "cam1", etc.)
278  std::string categoryname; // Free-form, module specific, category grouping (e.g. Aravis feature categories)
279  std::string description;
280  std::string unit;
281  ParameterValue::ParameterType type;
282 
283  ParameterValue defaultValue;
284  ParameterValue currentValue;
285  ParameterValue minValue; // minValue.isUndefined() until range has been set
286  ParameterValue maxValue;
287  ParameterValue incrementValue; // incrementValue.isUndefined() until increment set
288  std::vector<ParameterValue> validOptions;
289  std::vector<std::string> validOptionDescriptions;
290 
291  // The following fields are used in nvparamd (the master) and not set elsewhere
292  GovernorType governorType;
293  std::string governorString; // D-Bus address or shell command line, respectively
294  std::string governorPollString; // '' (for polling)
295  // 'oninit' action - ignore, or the same as on a change.
296  // This is only used in the parameter daemon, this variable need not be relayed.
297  bool invokeGovernorOnInit;
298 
299  ParameterAccessMode accessForConfig;
300  ParameterAccessMode accessForApi;
301 
302  ParameterInteractionHint interactionHint;
303  bool isModified;
304  bool isPolledForUpdates;
305  bool isPollResult;
306 };
307 
308 // Pimpl members
309 
310 // static
311 void Parameter::Pimpl::copyData(Parameter::Pimpl& dst, const Parameter::Pimpl& src) {
312  dst.uid = src.uid;
313  dst.name = src.name;
314  dst.modulename = src.modulename;
315  dst.categoryname = src.categoryname;
316  dst.description = src.description;
317  dst.unit = src.unit;
318  dst.type = src.type;
319  dst.defaultValue = src.defaultValue;
320  dst.currentValue = src.currentValue;
321  dst.minValue = src.minValue;
322  dst.maxValue = src.maxValue;
323  dst.incrementValue = src.incrementValue;
324  dst.validOptions = src.validOptions;
325  dst.validOptionDescriptions = src.validOptionDescriptions;
326  dst.governorType = src.governorType;
327  dst.governorString = src.governorString;
328  dst.governorPollString = src.governorPollString;
329  dst.invokeGovernorOnInit = src.invokeGovernorOnInit;
330  dst.accessForConfig = src.accessForConfig;
331  dst.accessForApi = src.accessForApi;
332  dst.interactionHint = src.interactionHint;
333  dst.isModified = src.isModified;
334  dst.isPolledForUpdates = src.isPolledForUpdates;
335  dst.isPollResult = src.isPollResult;
336 }
337 
338 Parameter::Pimpl::Pimpl()
339 : uid("undefined"), name("undefined"), governorType(GOVERNOR_NONE), invokeGovernorOnInit(false), accessForConfig(ACCESS_NONE), accessForApi(ACCESS_NONE), interactionHint(INTERACTION_ACTIVE), isModified(false), isPolledForUpdates(false) {
340 }
341 
342 Parameter::Pimpl::Pimpl(const std::string& uid)
343 : uid(uid), name(uid), governorType(GOVERNOR_NONE), invokeGovernorOnInit(false), accessForConfig(ACCESS_NONE), accessForApi(ACCESS_NONE), interactionHint(INTERACTION_ACTIVE), isModified(false), isPolledForUpdates(false) {
344 }
345 Parameter::Pimpl::Pimpl(const Parameter::Pimpl& other) {
346  copyData(*this, other);
347 }
348 
349 std::string Parameter::Pimpl::interpolateCommandLine(const ParameterValue& newVal, GovernorFunction govFn) {
350  std::string result = (govFn==GOVERNOR_FN_CHANGE_VALUE) ? governorString : governorPollString;
351  std::set<char> subst{'P', 'O', 'N', 'E', 'D'};
352  std::ostringstream ss;
353  char what;
354  size_t where = -1;
355  while (true) {
356  int foundAt = -1;
357  int foundRightmost = -1;
358  what = 0;
359  for (auto ch: subst) {
360  std::string lookfor = "%";
361  lookfor += ch;
362  foundAt = (int) result.rfind(lookfor, where);
363  if (foundAt > foundRightmost) {
364  foundRightmost = foundAt;
365  what = ch;
366  }
367  }
368  if (foundRightmost >= 0) {
369  ss.str("");
370  switch(what) {
371  case 'P':
372  ss << "\"" << getUid() << "\"";
373  break;
374  case 'O':
375  if (isScalar()) {
376  ss << "\"" << getCurrent<std::string>() << "\"";
377  } else {
378  bool first = true;
379  for (auto e: getTensorData()) {
380  if (first) first = false;
381  else ss << " ";
382  ss << e;
383  }
384  }
385  break;
386  case 'E':
387  ss << getTensorDimension();
388  if (isTensor()) {
389  auto sh = getTensorShape();
390  for (auto d: sh) {
391  ss << " " << d;
392  }
393  }
394  break;
395  case 'D':
396  ss << newVal.getTensorDimension();
397  if (isTensor()) {
398  auto sh = newVal.getTensorShape();
399  for (auto d: sh) {
400  ss << " " << d;
401  }
402  }
403  break;
404  case 'N':
405  default:
406  if (newVal.isScalar()) {
407  ss << "\"" << newVal.getValue<std::string>() << "\"";
408  } else {
409  bool first = true;
410  for (auto e: newVal.getTensorData()) {
411  if (first) first = false;
412  else ss << " ";
413  ss << e;
414  }
415  }
416  break;
417  }
418  result.replace(foundRightmost, 2, ss.str());
419  }
420  if (where == 0) break; // cannot go further left
421  where = (foundRightmost > 0) ? foundRightmost-1 : 0;
422  }
423  return result;
424 }
425 
426 Parameter::Pimpl& Parameter::Pimpl::setCurrentFrom(const Parameter::Pimpl& from) {
427  if (isTensor()) {
428  if(currentValue.getTensorShape() != from.getTensorShape()) {
429  throw std::runtime_error("Cannot assign tensors with unequal shape");
430  }
431  setTensorData(from.getTensorData());
432  } else {
433  currentValue.setType(getType());
434  // always cache string
435  switch (getType()) {
436  case ParameterValue::ParameterType::TYPE_INT:
437  currentValue.setValue(from.getCurrent<int>()); break;
438  case ParameterValue::ParameterType::TYPE_DOUBLE:
439  currentValue.setValue(from.getCurrent<double>()); break;
440  case ParameterValue::ParameterType::TYPE_STRING:
441  case ParameterValue::ParameterType::TYPE_SAFESTRING:
442  case ParameterValue::ParameterType::TYPE_COMMAND:
443  currentValue.setValue(from.getCurrent<std::string>()); break;
444  break;
445  case ParameterValue::ParameterType::TYPE_BOOL:
446  currentValue.setValue(from.getCurrent<bool>()); break;
447  break;
448  case ParameterValue::ParameterType::TYPE_TENSOR:
449  break; // (handled above)
450  case ParameterValue::ParameterType::TYPE_UNDEFINED:
451  throw std::runtime_error("Cannot assign a value to an undefined parameter");
452  }
453  ensureValidCurrent();
454  }
455  return *this;
456 }
457 
458 Parameter::Pimpl& Parameter::Pimpl::setCurrentFromDefault() {
459  if (!hasDefault()) {
460  throw std::runtime_error(std::string("Cannot set current value from default - no default value set for ") + getUid());
461  }
462  switch (getType()) {
463  case ParameterValue::ParameterType::TYPE_INT:
464  currentValue.setType(getType());
465  currentValue.setValue(getDefault<int>());
466  break;
467  case ParameterValue::ParameterType::TYPE_DOUBLE:
468  currentValue.setType(getType());
469  currentValue.setValue(getDefault<double>());
470  break;
471  case ParameterValue::ParameterType::TYPE_STRING:
472  case ParameterValue::ParameterType::TYPE_SAFESTRING:
473  currentValue.setType(getType());
474  currentValue.setValue(getDefault<std::string>());
475  break;
476  case ParameterValue::ParameterType::TYPE_BOOL:
477  currentValue.setType(getType());
478  currentValue.setValue(getDefault<bool>());
479  break;
480  case ParameterValue::ParameterType::TYPE_TENSOR:
481  if (hasCurrent() && (currentValue.getTensorNumElements() != defaultValue.getTensorNumElements())) {
482  throw std::runtime_error(std::string("Mismatching current and default tensor sizes for ") + getUid());
483  }
484  currentValue.setType(getType());
485  currentValue.setTensorData(defaultValue.getTensorData());
486  break;
487  case ParameterValue::ParameterType::TYPE_COMMAND:
488  // Ignore commands for resetting to default value
489  break;
490  case ParameterValue::ParameterType::TYPE_UNDEFINED:
491  throw std::runtime_error("Cannot assign a value to an undefined parameter");
492  }
493  return *this;
494 }
495 
496 template<> VT_EXPORT bool Parameter::Pimpl::enforceIncrement(bool t) {
497  return t;
498 }
499 
500 template<> VT_EXPORT int Parameter::Pimpl::enforceIncrement(int t) {
501  if (hasIncrement() && ((getType()==ParameterValue::TYPE_INT) || (getType()==ParameterValue::TYPE_DOUBLE))) {
502  double val = t;
503  double inc = getIncrement<double>();
504  if (hasRange()) {
505  double min = getMin<double>();
506  return (int) (min + inc * ((int) (val-min)/inc));
507  } else {
508  return (int) (inc * ((int) val/inc));
509  }
510  } else {
511  return t;
512  }
513 }
514 
515 template<> VT_EXPORT double Parameter::Pimpl::enforceIncrement(double t) {
516  if (hasIncrement() && ((getType()==ParameterValue::TYPE_INT) || (getType()==ParameterValue::TYPE_DOUBLE))) {
517  double val = t;
518  double inc = getIncrement<double>();
519  if (hasRange()) {
520  double min = getMin<double>();
521  return min + inc * ((int) (val-min)/inc);
522  } else {
523  return inc * ((int) val/inc);
524  }
525  } else {
526  return t;
527  }
528 }
529 
530 template<> VT_EXPORT std::string Parameter::Pimpl::enforceIncrement(std::string t) {
531  if (hasIncrement() && ((getType()==ParameterValue::TYPE_INT) || (getType()==ParameterValue::TYPE_DOUBLE))) {
532  double val = ConversionHelpers::anyToDouble(t);
533  double inc = getIncrement<double>();
534  if (hasRange()) {
535  double min = getMin<double>();
536  return ConversionHelpers::anyToString(min + inc * ((int) (val-min)/inc));
537  } else {
538  return ConversionHelpers::anyToString(inc * ((int) val/inc));
539  }
540  } else {
541  return t;
542  }
543 }
544 
545 std::vector<double>& Parameter::Pimpl::getTensorDataReference() {
546  if (hasCurrent()) {
547  return currentValue.getTensorDataReference();
548  } else {
549  if (hasDefault()) {
550  return defaultValue.getTensorDataReference();
551  } else {
552  throw std::runtime_error("Tried getTensorDataReference(), but no value set and no default defined");
553  }
554  }
555 }
556 
557 std::vector<double> Parameter::Pimpl::getTensorData() const {
558  if (hasCurrent()) {
559  return currentValue.getTensorData();
560  } else {
561  if (hasDefault()) {
562  return defaultValue.getTensorData();
563  } else {
564  throw std::runtime_error("Tried getTensorData(), but no value set and no default defined");
565  }
566  }
567 }
568 
569 std::vector<double>& Parameter::Pimpl::getTensorDefaultDataReference() {
570  if (hasDefault()) {
571  return defaultValue.getTensorDataReference();
572  } else {
573  throw std::runtime_error("Tried getTensorDefaultDataReference(), but no value set and no default defined");
574  }
575 }
576 
577 std::vector<double> Parameter::Pimpl::getTensorDefaultData() const {
578  if (hasDefault()) {
579  return defaultValue.getTensorData();
580  } else {
581  throw std::runtime_error("Tried getTensorDefaultData(), but no default defined");
582  }
583 }
584 
585 bool Parameter::Pimpl::ensureValidDefault() {
586  if (!hasDefault()) return false; // Not set yet
587  if (isTensor() || isCommand()) return false; // Revision unsupported or not required
588  if (hasOptions()) {
589  std::string val = defaultValue.getValue<std::string>();
590  for (auto& o: validOptions) {
591  if (val == o.getValue<std::string>()) {
592  return false; // Valid value -> no revision needed
593  }
594  }
595  // Invalid default: select first enum option as a fallback
596  defaultValue.setValue<std::string>(validOptions[0].getValue<std::string>());
597  return true;
598  } else {
599  if ((type==ParameterValue::ParameterType::TYPE_INT) || (type==ParameterValue::ParameterType::TYPE_DOUBLE)) {
600  if (hasRange()) {
601  // Limited range, must check
602  double minVal = minValue.getValue<double>();
603  double maxVal = maxValue.getValue<double>();
604  double val = defaultValue.getValue<double>();
605  double incVal = enforceIncrement(val);
606  if (val < minVal) {
607  defaultValue.setValue<double>(minVal);
608  return true;
609  } else if (val > maxVal) {
610  defaultValue.setValue<double>(maxVal);
611  return true;
612  } else if (val != incVal) {
613  // Did not adhere to increment
614  defaultValue.setValue<double>(incVal);
615  return true;
616  }
617  return false;
618  } else {
619  // Unlimited range, no revision
620  return false;
621  }
622  } else {
623  // No range check for non-numerical parameter
624  return false;
625  }
626  }
627 }
628 
629 bool Parameter::Pimpl::ensureValidCurrent() {
630  if (!hasCurrent()) return false; // Not set yet
631  if (isTensor() || isCommand()) return false; // Revision unsupported or not required
632  if (hasOptions()) {
633  std::string val = currentValue.getValue<std::string>();
634  for (auto& o: validOptions) {
635  if (val == o.getValue<std::string>()) {
636  return false; // Valid value -> no revision needed
637  }
638  }
639  // Invalid current value: copy default if available and valid
640  if (hasDefault()) {
641  std::string defVal = defaultValue.getValue<std::string>();
642  for (auto& o: validOptions) {
643  if (defVal == o.getValue<std::string>()) {
644  currentValue.setValue<std::string>(defVal);
645  return true; // Default value is still valid for current option set
646  }
647  }
648  }
649  // The only venue left is to fall back to the first entry
650  currentValue.setValue<std::string>(validOptions[0].getValue<std::string>());
651  return true;
652  } else {
653  if ((type==ParameterValue::ParameterType::TYPE_INT) || (type==ParameterValue::ParameterType::TYPE_DOUBLE)) {
654  if (hasRange()) {
655  // Limited range, must check
656  double minVal = minValue.getValue<double>();
657  double maxVal = maxValue.getValue<double>();
658  double val = currentValue.getValue<double>();
659  double incVal = enforceIncrement(val);
660  if (val < minVal) {
661  currentValue.setValue<double>(minVal);
662  return true;
663  } else if (val > maxVal) {
664  currentValue.setValue<double>(maxVal);
665  return true;
666  } else if (val != incVal) {
667  // Did not adhere to increment
668  currentValue.setValue<double>(incVal);
669  return true;
670  }
671  return false;
672  } else {
673  // Unlimited range, no revision
674  return false;
675  }
676  } else {
677  // No range check for non-numerical parameter
678  return false;
679  }
680  }
681 }
682 
683 
684 
685 
686 //
687 //
688 // External (API) class
689 //
690 //
691 
692 Parameter::Parameter()
693 : pimpl(new Parameter::Pimpl()) {
694 }
695 Parameter::Parameter(const std::string& uid)
696 : pimpl(new Parameter::Pimpl(uid)) {
697 }
698 Parameter::Parameter(const Parameter& other)
699 : pimpl(new Parameter::Pimpl()) {
700  Parameter::Pimpl::copyData(*pimpl, *(other.pimpl));
701 }
702 Parameter::~Parameter() {
703  delete pimpl;
704 }
705 Parameter& Parameter::operator= (const Parameter& other) {
706  Parameter::Pimpl::copyData(*pimpl, *(other.pimpl));
707  return *this;
708 }
709 
710 std::string Parameter::getUid() const {
711  return pimpl->getUid();
712 }
713 std::string Parameter::getName() const {
714  return pimpl->getName();
715 }
716 std::string Parameter::getModuleName() const {
717  return pimpl->getModuleName();
718 }
719 std::string Parameter::getCategoryName() const {
720  return pimpl->getCategoryName();
721 }
722 std::string Parameter::getDescription() const {
723  return pimpl->getDescription();
724 }
725 std::string Parameter::getUnit() const {
726  return pimpl->getUnit();
727 }
728 ParameterValue::ParameterType Parameter::getType() const {
729  return pimpl->getType();
730 }
731 Parameter::ParameterAccessMode Parameter::getAccessForConfig() const {
732  return pimpl->getAccessForConfig();
733 }
734 Parameter::ParameterAccessMode Parameter::getAccessForApi() const {
735  return pimpl->getAccessForApi();
736 }
737 
738 Parameter& Parameter::setAccessForConfig(Parameter::ParameterAccessMode mode) {
739  pimpl->setAccessForConfig(mode);
740  return *this;
741 }
742 Parameter& Parameter::setAccessForApi(Parameter::ParameterAccessMode mode) {
743  pimpl->setAccessForApi(mode);
744  return *this;
745 }
746 Parameter::ParameterInteractionHint Parameter::getInteractionHint() const {
747  return pimpl->getInteractionHint();
748 }
749 Parameter& Parameter::setInteractionHint(Parameter::ParameterInteractionHint hint) {
750  pimpl->setInteractionHint(hint);
751  return *this;
752 }
753 bool Parameter::getIsModified() const {
754  return pimpl->getIsModified();
755 }
756 bool Parameter::getIsPolled() const {
757  return pimpl->getIsPolled();
758 }
759 Parameter& Parameter::setIsPolled(bool mod) {
760  pimpl->setIsPolled(mod);
761  return *this;
762 }
763 Parameter& Parameter::setIsModified(bool mod) {
764  pimpl->setIsModified(mod);
765  return *this;
766 }
767 Parameter::GovernorType Parameter::getGovernorType() const {
768  return pimpl->getGovernorType();
769 }
770 std::string Parameter::getGovernorString() const {
771  return pimpl->getGovernorString();
772 }
773 Parameter& Parameter::setGovernor(Parameter::GovernorType govType, const std::string& govStr) {
774  pimpl->setGovernor(govType, govStr);
775  return *this;
776 }
777 Parameter& Parameter::setGovernorPollString(const std::string& govStr) {
778  pimpl->setGovernorPollString(govStr);
779  return *this;
780 }
781 bool Parameter::getInvokeGovernorOnInit() const {
782  return pimpl->getInvokeGovernorOnInit();
783 }
784 Parameter& Parameter::setInvokeGovernorOnInit(bool invoke) {
785  pimpl->setInvokeGovernorOnInit(invoke);
786  return *this;
787 }
788 std::string Parameter::interpolateCommandLine(const ParameterValue& newVal, Parameter::GovernorFunction fn) {
789  return pimpl->interpolateCommandLine(newVal, fn);
790 }
791 bool Parameter::isTensor() const {
792  return pimpl->isTensor();
793 }
794 bool Parameter::isScalar() const {
795  return pimpl->isScalar();
796 }
797 bool Parameter::isCommand() const {
798  return pimpl->isCommand();
799 }
800 unsigned int Parameter::getTensorDimension() const {
801  return pimpl->getTensorDimension();
802 }
803 std::vector<unsigned int> Parameter::getTensorShape() const {
804  return pimpl->getTensorShape();
805 }
806 unsigned int Parameter::getTensorNumElements() const {
807  return pimpl->getTensorNumElements();
808 }
809 std::vector<double> Parameter::getTensorData() const {
810  return pimpl->getTensorData();
811 }
812 std::vector<double> Parameter::getTensorDefaultData() const {
813  return pimpl->getTensorDefaultData();
814 }
815 std::vector<double>& Parameter::getTensorDataReference() {
816  return pimpl->getTensorDataReference();
817 }
818 std::vector<double>& Parameter::getTensorDefaultDataReference() {
819  return pimpl->getTensorDefaultDataReference();
820 }
821 Parameter& Parameter::setTensorData(const std::vector<double>& data) {
822  pimpl->setTensorData(data);
823  return *this;
824 }
825 Parameter& Parameter::setTensorDefaultData(const std::vector<double>& data) {
826  pimpl->setTensorDefaultData(data);
827  return *this;
828 }
829 
830 Parameter& Parameter::setName(const std::string& name) {
831  pimpl->setName(name);
832  return *this;
833 }
834 Parameter& Parameter::setModuleName(const std::string& n) {
835  pimpl->setModuleName(n);
836  return *this;
837 }
838 Parameter& Parameter::setCategoryName(const std::string& n) {
839  pimpl->setCategoryName(n);
840  return *this;
841 }
842 Parameter& Parameter::setDescription(const std::string& d) {
843  pimpl->setDescription(d);
844  return *this;
845 }
846 Parameter& Parameter::setUnit(const std::string& d) {
847  pimpl->setUnit(d);
848  return *this;
849 }
850 Parameter& Parameter::setType(ParameterValue::ParameterType t) {
851  pimpl->setType(t);
852  return *this;
853 }
854 Parameter& Parameter::setAsTensor(const std::vector<unsigned int>& shape) {
855  pimpl->setAsTensor(shape);
856  return *this;
857 }
858 bool Parameter::ensureValidDefault() {
859  return pimpl->ensureValidDefault();
860 }
861 bool Parameter::ensureValidCurrent() {
862  return pimpl->ensureValidCurrent();
863 }
864 
865 // Specializations of isValidNewValue
866 template<> VT_EXPORT bool Parameter::isValidNewValue(int t) const { return pimpl->isValidNewValue<int>(t); }
867 template<> VT_EXPORT bool Parameter::isValidNewValue(bool t) const { return pimpl->isValidNewValue<bool>(t); }
868 template<> VT_EXPORT bool Parameter::isValidNewValue(double t) const { return pimpl->isValidNewValue<double>(t); }
869 template<> VT_EXPORT bool Parameter::isValidNewValue(std::string t) const { return pimpl->isValidNewValue<std::string>(t); }
870 
871 // Specializations of enforceIncrement
872 template<> VT_EXPORT int Parameter::enforceIncrement(int t) { return pimpl->enforceIncrement<int>(t); }
873 template<> VT_EXPORT bool Parameter::enforceIncrement(bool t) { return pimpl->enforceIncrement<bool>(t); }
874 template<> VT_EXPORT double Parameter::enforceIncrement(double t) { return pimpl->enforceIncrement<double>(t); }
875 template<> VT_EXPORT std::string Parameter::enforceIncrement(std::string t) { return pimpl->enforceIncrement<std::string>(t); }
876 
877 // Specializations of setDefault
878 template<> VT_EXPORT Parameter& Parameter::setDefault(int t) { pimpl->setDefault<int>(t); return *this; }
879 template<> VT_EXPORT Parameter& Parameter::setDefault(bool t) { pimpl->setDefault<bool>(t); return *this; }
880 template<> VT_EXPORT Parameter& Parameter::setDefault(double t) { pimpl->setDefault<double>(t); return *this; }
881 template<> VT_EXPORT Parameter& Parameter::setDefault(std::string t) { pimpl->setDefault<std::string>(t); return *this; }
882 
883 // Specializations of setRange
884 template<> VT_EXPORT Parameter& Parameter::setRange(int mn, int mx) { pimpl->setRange<int>(mn, mx); return *this; }
885 template<> VT_EXPORT Parameter& Parameter::setRange(bool mn, bool mx) { pimpl->setRange<bool>(mn, mx); return *this; }
886 template<> VT_EXPORT Parameter& Parameter::setRange(double mn, double mx) { pimpl->setRange<double>(mn, mx); return *this; }
887 template<> VT_EXPORT Parameter& Parameter::setRange(std::string mn, std::string mx) { pimpl->setRange<std::string>(mn, mx); return *this; }
888 
889 Parameter& Parameter::unsetRange() {
890  pimpl->unsetRange();
891  return *this;
892 }
893 
894 // Specializations of setIncrement
895 template<> VT_EXPORT Parameter& Parameter::setIncrement(int t) { pimpl->setIncrement<int>(t); return *this; }
896 template<> VT_EXPORT Parameter& Parameter::setIncrement(bool t) { pimpl->setIncrement<bool>(t); return *this; }
897 template<> VT_EXPORT Parameter& Parameter::setIncrement(double t) { pimpl->setIncrement<double>(t); return *this; }
898 template<> VT_EXPORT Parameter& Parameter::setIncrement(std::string t) { pimpl->setIncrement<std::string>(t); return *this; }
899 
900 // Specializations of setCurrent
901 template<> VT_EXPORT Parameter& Parameter::setCurrent(int t) { pimpl->setCurrent<int>(t); return *this; }
902 template<> VT_EXPORT Parameter& Parameter::setCurrent(bool t) { pimpl->setCurrent<bool>(t); return *this; }
903 template<> VT_EXPORT Parameter& Parameter::setCurrent(double t) { pimpl->setCurrent<double>(t); return *this; }
904 template<> VT_EXPORT Parameter& Parameter::setCurrent(std::string t) { pimpl->setCurrent<std::string>(t); return *this; }
905 
906 Parameter& Parameter::setCurrentFrom(const Parameter& from) {
907  pimpl->setCurrentFrom(*(from.pimpl));
908  return *this;
909 }
910 Parameter& Parameter::setCurrentFromDefault() {
911  pimpl->setCurrentFromDefault();
912  return *this;
913 }
914 
915 // Specializations of setOptions
916 template<> VT_EXPORT Parameter& Parameter::setOptions(const std::vector<int>& opts, const std::vector<std::string>& descriptions) { pimpl->setOptions<int>(opts, descriptions); return *this; }
917 template<> VT_EXPORT Parameter& Parameter::setOptions(const std::vector<bool>& opts, const std::vector<std::string>& descriptions) { pimpl->setOptions<bool>(opts, descriptions); return *this; }
918 template<> VT_EXPORT Parameter& Parameter::setOptions(const std::vector<double>& opts, const std::vector<std::string>& descriptions) { pimpl->setOptions<double>(opts, descriptions); return *this; }
919 template<> VT_EXPORT Parameter& Parameter::setOptions(const std::vector<std::string>& opts, const std::vector<std::string>& descriptions) { pimpl->setOptions<std::string>(opts, descriptions); return *this; }
920 
921 // Specializations of setOptions (initializer list)
922 template<> VT_EXPORT Parameter& Parameter::setOptions(std::initializer_list<int> opts, std::initializer_list<std::string> descriptions) { pimpl->setOptions<int>(opts, descriptions); return *this; }
923 template<> VT_EXPORT Parameter& Parameter::setOptions(std::initializer_list<bool> opts, std::initializer_list<std::string> descriptions) { pimpl->setOptions<bool>(opts, descriptions); return *this; }
924 template<> VT_EXPORT Parameter& Parameter::setOptions(std::initializer_list<double> opts, std::initializer_list<std::string> descriptions) { pimpl->setOptions<double>(opts, descriptions); return *this; }
925 template<> VT_EXPORT Parameter& Parameter::setOptions(std::initializer_list<std::string> opts, std::initializer_list<std::string> descriptions) { pimpl->setOptions<std::string>(opts, descriptions); return *this; }
926 
927 // Specializations of getOptions
928 template<> VT_EXPORT std::vector<int> Parameter::getOptions() const { return pimpl->getOptions<int>(); }
929 template<> VT_EXPORT std::vector<bool> Parameter::getOptions() const { return pimpl->getOptions<bool>(); }
930 template<> VT_EXPORT std::vector<double> Parameter::getOptions() const { return pimpl->getOptions<double>(); }
931 template<> VT_EXPORT std::vector<std::string> Parameter::getOptions() const { return pimpl->getOptions<std::string>(); }
932 
933 std::vector<std::string> Parameter::getOptionDescriptions() const {
934  return pimpl->getOptionDescriptions();
935 }
936 
937 ParameterValue Parameter::getCurrentParameterValue() {
938  return pimpl->getCurrentParameterValue();
939 }
940 ParameterValue Parameter::getDefaultParameterValue() {
941  return pimpl->getDefaultParameterValue();
942 }
943 
944 // Specializations of getCurrent
945 template<> VT_EXPORT int Parameter::getCurrent() const { return pimpl->getCurrent<int>(); }
946 template<> VT_EXPORT bool Parameter::getCurrent() const { return pimpl->getCurrent<bool>(); }
947 template<> VT_EXPORT double Parameter::getCurrent() const { return pimpl->getCurrent<double>(); }
948 template<> VT_EXPORT std::string Parameter::getCurrent() const { return pimpl->getCurrent<std::string>(); }
949 // Specializations of getDefault
950 template<> VT_EXPORT int Parameter::getDefault() const { return pimpl->getDefault<int>(); }
951 template<> VT_EXPORT bool Parameter::getDefault() const { return pimpl->getDefault<bool>(); }
952 template<> VT_EXPORT double Parameter::getDefault() const { return pimpl->getDefault<double>(); }
953 template<> VT_EXPORT std::string Parameter::getDefault() const { return pimpl->getDefault<std::string>(); }
954 // Specializations of getMin
955 template<> VT_EXPORT int Parameter::getMin() const { return pimpl->getMin<int>(); }
956 template<> VT_EXPORT bool Parameter::getMin() const { return pimpl->getMin<bool>(); }
957 template<> VT_EXPORT double Parameter::getMin() const { return pimpl->getMin<double>(); }
958 template<> VT_EXPORT std::string Parameter::getMin() const { return pimpl->getMin<std::string>(); }
959 // Specializations of getMax
960 template<> VT_EXPORT int Parameter::getMax() const { return pimpl->getMax<int>(); }
961 template<> VT_EXPORT bool Parameter::getMax() const { return pimpl->getMax<bool>(); }
962 template<> VT_EXPORT double Parameter::getMax() const { return pimpl->getMax<double>(); }
963 template<> VT_EXPORT std::string Parameter::getMax() const { return pimpl->getMax<std::string>(); }
964 // Specializations of getIncrement
965 template<> VT_EXPORT int Parameter::getIncrement() const { return pimpl->getIncrement<int>(); }
966 template<> VT_EXPORT bool Parameter::getIncrement() const { return pimpl->getIncrement<bool>(); }
967 template<> VT_EXPORT double Parameter::getIncrement() const { return pimpl->getIncrement<double>(); }
968 template<> VT_EXPORT std::string Parameter::getIncrement() const { return pimpl->getIncrement<std::string>(); }
969 
970 bool Parameter::hasOptions() const {
971  return pimpl->hasOptions();
972 }
973 bool Parameter::hasCurrent() const {
974  return pimpl->hasCurrent();
975 }
976 bool Parameter::hasDefault() const {
977  return pimpl->hasDefault();
978 }
979 bool Parameter::hasRange() const {
980  return pimpl->hasRange();
981 }
982 bool Parameter::hasIncrement() const {
983  return pimpl->hasIncrement();
984 }
985 
986 double Parameter::at(unsigned int x) {
987  return pimpl->at(x);
988 }
989 double Parameter::at(unsigned int y, unsigned int x) {
990  return pimpl->at(y, x);
991 }
992 double Parameter::at(unsigned int z, unsigned int y, unsigned int x) {
993  return pimpl->at(z, y, x);
994 }
995 
996 
997 } // namespace param
998 } // namespace visiontransfer
999 
visiontransfer::param::Parameter::setModuleName
VT_EXPORT Parameter & setModuleName(const std::string &n)
Definition: parameter.cpp:858
visiontransfer::param::Parameter::getInvokeGovernorOnInit
VT_EXPORT bool getInvokeGovernorOnInit() const
Definition: parameter.cpp:805
visiontransfer::param::Parameter::getInteractionHint
VT_EXPORT ParameterInteractionHint getInteractionHint() const
Definition: parameter.cpp:770
visiontransfer::internal::ConversionHelpers::anyToDouble
static double anyToDouble(T val)
Converts any type to a double.
Definition: conversionhelpers.h:74
visiontransfer::param::Parameter::setInteractionHint
VT_EXPORT Parameter & setInteractionHint(ParameterInteractionHint hint)
Definition: parameter.cpp:773
visiontransfer::param::ParameterValue
Definition: parametervalue.h:59
visiontransfer::param::Parameter::setName
VT_EXPORT Parameter & setName(const std::string &name)
Definition: parameter.cpp:854
visiontransfer::param::Parameter::setDefault
VT_EXPORT Parameter & setDefault(T t)
visiontransfer::param::Parameter::setOptions
VT_EXPORT Parameter & setOptions(const std::vector< T > &opts, const std::vector< std::string > &descriptions)
visiontransfer::param::Parameter::setTensorDefaultData
VT_EXPORT Parameter & setTensorDefaultData(const std::vector< double > &data)
Definition: parameter.cpp:849
visiontransfer::param::Parameter::setAsTensor
VT_EXPORT Parameter & setAsTensor(const std::vector< unsigned int > &shape)
Definition: parameter.cpp:878
visiontransfer::param::Parameter::setAccessForConfig
VT_EXPORT Parameter & setAccessForConfig(ParameterAccessMode mode)
Definition: parameter.cpp:762
visiontransfer::param::Parameter::setRange
VT_EXPORT Parameter & setRange(T mn, T mx)
visiontransfer::param::Parameter::getIsModified
VT_EXPORT bool getIsModified() const
Definition: parameter.cpp:777
visiontransfer::param::Parameter
Definition: parameter.h:71
visiontransfer::param::Parameter::interpolateCommandLine
VT_EXPORT std::string interpolateCommandLine(const ParameterValue &newVal, GovernorFunction fn=GOVERNOR_FN_CHANGE_VALUE)
Definition: parameter.cpp:812
visiontransfer::param::Parameter::setType
VT_EXPORT Parameter & setType(ParameterValue::ParameterType t)
Definition: parameter.cpp:874
visiontransfer::param::Parameter::setGovernor
VT_EXPORT Parameter & setGovernor(GovernorType govType, const std::string &govStr)
Definition: parameter.cpp:797
visiontransfer::param::Parameter::setIsPolled
VT_EXPORT Parameter & setIsPolled(bool mod)
Definition: parameter.cpp:783
visiontransfer::param::Parameter::setIsModified
VT_EXPORT Parameter & setIsModified(bool mod)
Definition: parameter.cpp:787
visiontransfer::param::Parameter::setTensorData
VT_EXPORT Parameter & setTensorData(const std::vector< double > &data)
Definition: parameter.cpp:845
visiontransfer::param::Parameter::setInvokeGovernorOnInit
VT_EXPORT Parameter & setInvokeGovernorOnInit(bool invoke)
Definition: parameter.cpp:808
visiontransfer::param::Parameter::setUnit
VT_EXPORT Parameter & setUnit(const std::string &d)
Definition: parameter.cpp:870
visiontransfer::param::Parameter::setCategoryName
VT_EXPORT Parameter & setCategoryName(const std::string &n)
Definition: parameter.cpp:862
visiontransfer::param::Parameter::getGovernorType
VT_EXPORT GovernorType getGovernorType() const
Definition: parameter.cpp:791
visiontransfer::param::Parameter::ensureValidDefault
VT_EXPORT bool ensureValidDefault()
Definition: parameter.cpp:882
visiontransfer::param::Parameter::setAccessForApi
VT_EXPORT Parameter & setAccessForApi(ParameterAccessMode mode)
Definition: parameter.cpp:766
visiontransfer::param::Parameter::setDescription
VT_EXPORT Parameter & setDescription(const std::string &d)
Definition: parameter.cpp:866
visiontransfer::param::Parameter::setGovernorPollString
VT_EXPORT Parameter & setGovernorPollString(const std::string &govStr)
Definition: parameter.cpp:801
Allied Vision