OSVR Framework (Internal Development Docs)  0.6-1962-g59773924
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
BeaconSetupData.cpp
Go to the documentation of this file.
1 
11 // Copyright 2016 Sensics, Inc.
12 //
13 // Licensed under the Apache License, Version 2.0 (the "License");
14 // you may not use this file except in compliance with the License.
15 // You may obtain a copy of the License at
16 //
17 // http://www.apache.org/licenses/LICENSE-2.0
18 //
19 // Unless required by applicable law or agreed to in writing, software
20 // distributed under the License is distributed on an "AS IS" BASIS,
21 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 // See the License for the specific language governing permissions and
23 // limitations under the License.
24 
25 // Internal Includes
26 #include "BeaconSetupData.h"
27 
28 // Library/third-party includes
29 #include <osvr/Util/Verbosity.h>
30 
31 // Standard includes
32 // - none
33 
34 namespace osvr {
35 namespace vbtracker {
36  namespace {
37  using vector_size_type = Vec3Vector::size_type;
38  struct VectorSizes {
39  vector_size_type minSize = 0;
40  vector_size_type maxSize = 0;
41  };
42  inline VectorSizes getMinMaxSetupDataSizes(TargetSetupData const &d) {
43  VectorSizes ret;
45  auto sizes = {d.patterns.size(),
46  d.locations.size(),
47  d.emissionDirections.size(),
48  d.baseMeasurementVariances.size(),
49  d.initialAutocalibrationErrors.size(),
50  d.isFixed.size()};
52  std::tie(ret.minSize, ret.maxSize) = std::minmax(sizes);
53  return ret;
54  }
55 
56  enum class BeaconPatternStatus {
57  PatternOK,
58  PatternEmpty,
59  PatternContainsInvalidCharacter
60  };
61  inline BeaconPatternStatus
62  judgeBeaconPattern(std::string const &pattern) {
63 
64  if (pattern.empty()) {
65  return BeaconPatternStatus::PatternEmpty;
66  }
67  if (pattern.find_first_not_of(".*") != std::string::npos) {
72  return BeaconPatternStatus::PatternContainsInvalidCharacter;
73  }
74  return BeaconPatternStatus::PatternOK;
75  }
76  class TargetDataChecker {
77  public:
78  using size_type = Vec3Vector::size_type;
79  TargetDataChecker(TargetSetupData &data, TargetDataSummary &summary)
80  : d(data), m_summary(summary),
81  m_sizes(getMinMaxSetupDataSizes(data)) {}
82 
85  void process(bool silent) {
87  for (size_type i = 0; i < m_sizes.minSize; ++i) {
88  if (disabledBeacon(i)) {
89  d.patterns[i].clear();
90  continue;
91  }
92  if (0 == m_patternLength) {
95  m_patternLength = d.patterns[i].size();
96  if (!silent) {
97  OSVR_DEV_VERBOSE("Determined that patterns are "
98  << m_patternLength
99  << " bits long.");
100  }
101  }
102  bool gotError = false;
103  checkPatternLength(i, gotError);
104  checkLocationValidity(i, gotError);
105  checkEmissionDirection(i, gotError);
106  checkMeasVariance(i, gotError);
107  checkAutocalib(i, gotError);
108 
109  if (!gotError) {
110  m_summary.validBeacons.push_back(wrapIndex(i));
111  }
112  }
113 
115  for (size_type i = m_sizes.minSize; i < m_sizes.maxSize; ++i) {
116 
120  bool gotError = false;
121  recordError(
122  i, "Mismatched vectors: Beacon ID exists "
123  "in at least one vector, but not in all vectors.");
124  if (inRange(i, d.patterns, "pattern")) {
125  if (disabledBeacon(i)) {
128  continue;
129  }
130  checkPatternLength(i, gotError);
131  }
132 
133  if (inRange(i, d.locations, "locations")) {
134  checkLocationValidity(i, gotError);
135  }
136 
137  if (inRange(i, d.emissionDirections,
138  "emissionDirections")) {
139  checkEmissionDirection(i, gotError);
140  }
141 
142  if (inRange(i, d.baseMeasurementVariances,
143  "baseMeasurementVariances")) {
144  checkMeasVariance(i, gotError);
145  }
146 
147  auto gotInitialAutocalib =
148  inRange(i, d.initialAutocalibrationErrors,
149  "initialAutocalibrationErrors");
150  auto gotIsFixed = inRange(i, d.isFixed, "isFixed");
151  if (gotInitialAutocalib && gotIsFixed) {
152  checkAutocalib(i, gotError);
153  }
154  }
155  }
156 
162  bool disabledBeacon(size_type i) {
163  switch (judgeBeaconPattern(d.patterns[i])) {
164  case BeaconPatternStatus::PatternEmpty:
165  m_summary.disabledByEmptyPattern.push_back(wrapIndex(i));
166  return true;
167  case BeaconPatternStatus::PatternContainsInvalidCharacter:
172  m_summary.disabledByPattern.push_back(wrapIndex(i));
173  return true;
174  case BeaconPatternStatus::PatternOK:
175  return false;
176  }
177  }
178 
179  void checkPatternLength(size_type i, bool &gotError) {
181  if (d.patterns[i].size() != m_patternLength) {
182  gotError = true;
183  recordError(i, "Pattern was non-empty and all legal "
184  "characters, but length did not match.");
185  }
186  }
187 
188  void checkLocationValidity(size_type i, bool &gotError) {
190  if (d.locations[i] == TargetSetupData::getBogusLocation()) {
191  gotError = true;
192  recordError(i, "Beacon location is still the bogus "
193  "'uninitialized' sentinel value.");
194  }
195  }
196 
197  void checkEmissionDirection(size_type i, bool &gotError) {
198  if (d.emissionDirections[i] == EmissionDirectionVec(0, 0, 0)) {
199  gotError = true;
200  recordError(
201  i,
202  "Beacon emission direction is zero - uninitialized.");
203  }
205  }
206 
207  void checkMeasVariance(size_type i, bool &gotError) {
208  if (d.baseMeasurementVariances.size() <= i) {
209  d.baseMeasurementVariances.resize(i + 1, 1.);
210  }
211  if (d.baseMeasurementVariances[i] <= 0) {
212  gotError = true;
213  recordError(
214  i, "Beacon base measurement variance is not positive.");
215  }
216  }
217  void checkAutocalib(size_type i, bool &gotError) {
218  if (d.isFixed[i]) {
219  // Just make sure this is normalized here in case they
220  // didn't use our helper function.
221  d.initialAutocalibrationErrors[i] = 0;
222  } else if (d.initialAutocalibrationErrors[i] == 0.) {
223  gotError = true;
224  recordError(i, "Beacon initial autocalib error is zero, "
225  "but not marked as fixed (so autocalib "
226  "process noise would apply, etc.)");
227  } else if (d.initialAutocalibrationErrors[i] < 0.) {
228 
229  gotError = true;
230  recordError(i,
231  "Beacon initial autocalib error is negative.");
232  }
233  }
235 
238  template <typename T>
239  bool inRange(size_type i, T &vec, std::string const &name) {
240  if (i < vec.size()) {
241  return true;
242  }
243 
244  recordError(i,
245  "Mismatched vectors: Beacon ID exists in at least "
246  "one vector, but not enough entries in the " +
247  name + " vector!");
248  return false;
249  }
250 
251  template <typename T> void recordError(size_type i, T &&arg) {
252  m_summary.errors.emplace_back(wrapIndex(i),
253  std::forward<T>(arg));
254  }
255 
256  static OneBasedBeaconId wrapIndex(size_type i) {
257  return makeOneBased(ZeroBasedBeaconId(i));
258  }
260 
261  private:
262  TargetSetupData &d;
263  TargetDataSummary &m_summary;
264  std::size_t m_patternLength = 0;
265  VectorSizes const m_sizes;
266  size_type m_minSize = 0;
267  size_type m_maxSize = 0;
268  };
269  } // namespace
270 
272  auto zeroId = makeZeroBased(beacon);
273  if (!(zeroId.value() < patterns.size())) {
275  return false;
276  }
277  return (judgeBeaconPattern(patterns[zeroId.value()]) ==
278  BeaconPatternStatus::PatternOK);
279  }
280 
282  if (!(beacon.value() < patterns.size())) {
285  return;
286  }
288  patterns[beacon.value()].clear();
289  }
290 
291  // Implementation of method in BeaconSetupData.h
292  TargetDataSummary TargetSetupData::cleanAndValidate(bool silent) {
293  TargetDataSummary ret;
294  TargetDataChecker checker(*this, ret);
295  checker.process(silent);
296  return ret;
297  }
298 } // namespace vbtracker
299 } // namespace osvr
static LocationPoint getBogusLocation()
void markBeaconInactive(ZeroBasedBeaconId beacon)
bool isBeaconActive(OneBasedBeaconId beacon)
Is the beacon active?
Internal, configured header file for verbosity macros.