OSVR Framework (Internal Development Docs)  0.6-1962-g59773924
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
TrackingSystem.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 "TrackingSystem.h"
27 #include "ForEachTracked.h"
28 #include "RoomCalibration.h"
29 #include "SBDBlobExtractor.h"
30 #include "TrackedBody.h"
31 #include "TrackedBodyTarget.h"
32 #include "TrackingSystem_Impl.h"
33 #include "UndistortMeasurements.h"
34 
35 // Library/third-party includes
36 #include <boost/assert.hpp>
37 
38 #include <util/Stride.h>
39 
40 // Standard includes
41 #include <algorithm>
42 #include <iostream>
43 #include <iterator>
44 #include <stdexcept>
45 #include <string>
46 
47 static const auto ROOM_CALIBRATION_SKIP_BRIGHTS_CUTOFF = 4;
48 static const auto CALIBRATION_RANSAC_ITERATIONS = 8;
49 
50 namespace osvr {
51 namespace vbtracker {
52 
53  TrackingSystem::TrackingSystem(ConfigParams const &params)
54  : m_params(params), m_impl(new Impl(params)) {}
55 
56  TrackingSystem::~TrackingSystem() {}
57 
58  TrackedBody *TrackingSystem::createTrackedBody() {
59  auto newId = BodyId(static_cast<BodyId::wrapped_type>(m_bodies.size()));
60  BodyPtr newBody(new TrackedBody(*this, newId));
61  m_bodies.emplace_back(std::move(newBody));
62  return m_bodies.back().get();
63  }
64 
65  TrackedBodyTarget *TrackingSystem::getTarget(BodyTargetId target) {
66  return getBody(target.first).getTarget(target.second);
67  }
68 
69  TrackedBodyTarget const *
70  TrackingSystem::getTarget(BodyTargetId target) const {
71  return getBody(target.first).getTarget(target.second);
72  }
73 
74  ImageOutputDataPtr TrackingSystem::performInitialImageProcessing(
75  util::time::TimeValue const &tv, cv::Mat const &frame,
76  cv::Mat const &frameGray, CameraParameters const &camParams) {
77 
78  ImageOutputDataPtr ret(new ImageProcessingOutput);
79  ret->tv = tv;
80  ret->frame = frame;
81  ret->frameGray = frameGray;
82  ret->camParams = camParams.createUndistortedVariant();
83  auto rawMeasurements =
84  m_impl->blobExtractor->extractBlobs(ret->frameGray);
85  ret->ledMeasurements = undistortLeds(rawMeasurements, camParams);
86  return ret;
87  }
88 
89  LedUpdateCount const &
90  TrackingSystem::updateLedsFromVideoData(ImageOutputDataPtr &&imageData) {
92  m_updated.clear();
93  auto &updateCount = m_impl->updateCount;
94  updateCount.clear();
95 
98  m_impl->frame = imageData->frame;
99  m_impl->frameGray = imageData->frameGray;
100  m_impl->camParams = imageData->camParams;
101  m_impl->lastFrame = imageData->tv;
102 
104  forEachTarget(*this, [&](TrackedBodyTarget &target) {
105  auto usedMeasurements =
106  target.processLedMeasurements(imageData->ledMeasurements);
107  if (usedMeasurements != 0) {
108  updateCount[target.getQualifiedId()] = usedMeasurements;
109  }
110  });
111  return updateCount;
112  }
113 
114  BodyIndices const &
115  TrackingSystem::updateBodiesFromVideoData(ImageOutputDataPtr &&imageData) {
117  updateLedsFromVideoData(std::move(imageData));
118 
120  updatePoseEstimates();
121 
123  m_impl->triggerDebugDisplay(*this);
124 
125  return m_updated;
126  }
127  inline void
128  validateTargetPointerFromUpdateList(TrackedBodyTarget *targetPtr) {
129 
130  BOOST_ASSERT_MSG(targetPtr != nullptr, "We should never be "
131  "retrieving a nullptr for a "
132  "target with measurements!");
133  if (!targetPtr) {
134  throw std::logic_error("Logical impossibility: Couldn't "
135  "retrieve a valid pointer for a target "
136  "that we were just told updated its "
137  "LEDs from data this frame.");
138  }
139  }
140  void TrackingSystem::updatePoseEstimates() {
141  if (!isRoomCalibrationComplete()) {
143  calibrationVideoPhaseThree();
144  return;
145  }
146 
147  auto const &updateCount = m_impl->updateCount;
148  for (auto &bodyTargetWithMeasurements : updateCount) {
149  auto targetPtr = getTarget(bodyTargetWithMeasurements.first);
150  validateTargetPointerFromUpdateList(targetPtr);
151  auto &target = *targetPtr;
152 
154  auto &body = target.getBody();
155  util::time::TimeValue stateTime = {};
156  BodyState state;
157  auto newTime = m_impl->lastFrame;
158  auto validState =
159  body.getStateAtOrBefore(newTime, stateTime, state);
160  auto initialTime = stateTime;
161 
162  auto gotPose = target.updatePoseEstimateFromLeds(
163  m_impl->camParams, newTime, state, stateTime, validState);
164  if (gotPose) {
165  body.replaceStateSnapshot(initialTime, newTime, state);
166 #if 0
167  static auto s = ::util::Stride{101};
168  if (++s) {
169  std::cout << body.getState().position().transpose() << "\n";
170  }
171 #endif
172  m_updated.push_back(body.getId());
174  }
175  }
177  for (auto &body : m_bodies) {
181  body->pruneHistory(m_impl->lastFrame);
182  }
183  }
184 
185  void TrackingSystem::calibrationVideoPhaseThree() {
186  auto const &updateCount = m_impl->updateCount;
187  for (auto &bodyTargetWithMeasurements : updateCount) {
188  auto &bodyTargetId = bodyTargetWithMeasurements.first;
189  if (!m_impl->calib.wantVideoData(*this, bodyTargetId)) {
190  // If the room calibrator doesn't want video tracking data from
191  // this target, then move along.
192  continue;
193  }
194  auto targetPtr = getTarget(bodyTargetId);
195  validateTargetPointerFromUpdateList(targetPtr);
196  auto &target = *targetPtr;
197  Eigen::Vector3d xlate;
198  Eigen::Quaterniond quat;
199  auto gotPose = target.uncalibratedRANSACPoseEstimateFromLeds(
200  m_impl->camParams, xlate, quat,
201  ROOM_CALIBRATION_SKIP_BRIGHTS_CUTOFF, CALIBRATION_RANSAC_ITERATIONS);
202  if (gotPose) {
203  m_impl->calib.processVideoData(*this, bodyTargetId,
204  m_impl->lastFrame, xlate, quat);
205  }
206  }
207 
208  m_impl->calib.postCalibrationUpdate(*this);
209  }
210 
211  void
213  util::time::TimeValue const &tv,
214  Eigen::Quaterniond const &quat) {
215  m_impl->calib.processIMUData(*this, id, tv, quat);
216  m_impl->calib.postCalibrationUpdate(*this);
217  }
218 
219  void TrackingSystem::setCameraPose(Eigen::Isometry3d const &camPose) {
220  m_impl->haveCameraPose = true;
221  m_impl->cameraPose = camPose;
222  m_impl->cameraPoseInv = camPose.inverse();
223  }
224 
225  bool TrackingSystem::haveCameraPose() const {
226  return m_impl->haveCameraPose;
227  }
228 
229  Eigen::Isometry3d const &TrackingSystem::getCameraPose() const {
230  return m_impl->cameraPose;
231  }
232 
233  Eigen::Isometry3d const &TrackingSystem::getRoomToCamera() const {
234  return m_impl->cameraPoseInv;
235  }
236 
240 
242  if (m_impl->roomCalibCompleteCached) {
243  return true;
244  }
246  m_impl->roomCalibCompleteCached =
247  vbtracker::isRoomCalibrationComplete(*this);
248  return m_impl->roomCalibCompleteCached;
249  }
250 
251 } // namespace vbtracker
252 } // namespace osvr
bool uncalibratedRANSACPoseEstimateFromLeds(CameraParameters const &camParams, Eigen::Vector3d &xlate, Eigen::Quaterniond &quat, int skipBrightsCutoff=-1, std::size_t iterations=5)
std::size_t processLedMeasurements(LedMeasurementVec const &undistortedLeds)
::OSVR_TimeValue TimeValue
C++-friendly typedef for the OSVR_TimeValue structure.
Definition: TimeValue.h:48
LedUpdateCount const & updateLedsFromVideoData(ImageOutputDataPtr &&imageData)
BodyIndices const & updateBodiesFromVideoData(ImageOutputDataPtr &&imageData)
BodyTargetId getQualifiedId() const
Get a fully-qualified (within a tracking system) id for this target.
Eigen::Isometry3d const & getRoomToCamera() const
Standardized, portable parallel to struct timeval for representing both absolute times and time inter...
Definition: TimeValueC.h:81
void calibrationHandleIMUData(BodyId id, util::time::TimeValue const &tv, Eigen::Quaterniond const &quat)
Eigen::Isometry3d const & getCameraPose() const
This gets rTc - the pose of the camera in the room.