OSVR Framework (Internal Development Docs)  0.6-1962-g59773924
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
VideoIMUFusionDevice.cpp
Go to the documentation of this file.
1 
11 // Copyright 2015 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 "VideoIMUFusionDevice.h"
30 #include <osvr/Util/EigenInterop.h>
31 #include <osvr/Util/Verbosity.h>
32 
33 // Generated JSON header file
34 #include "org_osvr_filter_videoimufusion_json.h"
35 
36 // Library/third-party includes
37 // - none
38 
39 // Standard includes
40 #include <iostream>
41 #include <cmath>
42 
43 static const OSVR_ChannelCount FUSED_SENSOR_ID = 0;
44 static const OSVR_ChannelCount TRANSFORMED_VIDEO_SENSOR_ID = 1;
45 static const OSVR_ChannelCount CAMERA_SENSOR_ID = 2;
46 
47 static const auto INTERVAL_BETWEEN_CAMERA_REPORTS = std::chrono::seconds(1);
49  std::string const &name,
50  std::string const &imuPath,
51  std::string const &videoPath,
52  VideoIMUFusionParams const &params)
53  : m_fusion(params) {
56 
57  osvrDeviceTrackerConfigure(opts, &m_trackerOut);
58 
60  OSVR_DeviceToken dev;
61  if (OSVR_RETURN_FAILURE ==
62  osvrAnalysisSyncInit(ctx, name.c_str(), opts, &dev, &m_clientCtx)) {
63  throw std::runtime_error("Could not initialize analysis plugin!");
64  }
65  m_dev = osvr::pluginkit::DeviceToken(dev);
66 
68  m_dev.sendJsonDescriptor(org_osvr_filter_videoimufusion_json);
69 
71  m_dev.registerUpdateCallback(this);
72 
74  osvrClientGetInterface(m_clientCtx, imuPath.c_str(), &m_imu);
76  m_imu, &VideoIMUFusionDevice::s_handleIMUData, this);
78  m_imu, &VideoIMUFusionDevice::s_handleIMUVelocity, this);
79 
80  osvrClientGetInterface(m_clientCtx, videoPath.c_str(), &m_videoTracker);
81 
83  m_videoTracker, &VideoIMUFusionDevice::s_handleVideoTrackerData, this);
84 }
85 
89  if (m_imu) {
90  osvrClientFreeInterface(m_clientCtx, m_imu);
91  m_imu = nullptr;
92  }
93  if (m_videoTracker) {
94  osvrClientFreeInterface(m_clientCtx, m_videoTracker);
95  m_imu = nullptr;
96  }
97 }
98 
99 OSVR_ReturnCode VideoIMUFusionDevice::update() {
100  if (m_shouldReportCamera()) {
101  m_nextCameraReport = our_clock::now() + INTERVAL_BETWEEN_CAMERA_REPORTS;
102 
103  osvrDeviceTrackerSendPose(m_dev, m_trackerOut,
104  &m_fusion.getLatestCameraPose(),
105  CAMERA_SENSOR_ID);
106  }
107  return OSVR_RETURN_SUCCESS;
108 }
109 
110 bool VideoIMUFusionDevice::m_shouldReportCamera() const {
111  if (m_fusion.running()) {
112  if (!m_reportedCamera || m_nextCameraReport < our_clock::now()) {
113  return true;
114  }
115  }
116  return false;
117 }
118 
119 void VideoIMUFusionDevice::s_handleIMUData(
120  void *userdata, const OSVR_TimeValue *timestamp,
121  const OSVR_OrientationReport *report) {
122  static_cast<VideoIMUFusionDevice *>(userdata)
123  ->handleIMUData(*timestamp, *report);
124 }
125 void VideoIMUFusionDevice::s_handleIMUVelocity(
126  void *userdata, const OSVR_TimeValue *timestamp,
127  const OSVR_AngularVelocityReport *report) {
128  static_cast<VideoIMUFusionDevice *>(userdata)
129  ->handleIMUVelocity(*timestamp, *report);
130 }
131 void VideoIMUFusionDevice::s_handleVideoTrackerData(
132  void *userdata, const OSVR_TimeValue *timestamp,
133  const OSVR_PoseReport *report) {
134  static_cast<VideoIMUFusionDevice *>(userdata)
135  ->handleVideoTrackerData(*timestamp, *report);
136 }
137 
138 void VideoIMUFusionDevice::handleIMUData(const OSVR_TimeValue &timestamp,
139  const OSVR_OrientationReport &report) {
140  m_fusion.handleIMUData(timestamp, report);
141  sendMainPoseReport();
142 }
143 void VideoIMUFusionDevice::handleIMUVelocity(
144  const OSVR_TimeValue &timestamp, const OSVR_AngularVelocityReport &report) {
145 
146  using namespace osvr::util::eigen_interop;
147  Eigen::Quaterniond q = map(report.state.incrementalRotation);
148  Eigen::Vector3d rot;
149  if (q.w() >= 1. || q.vec().isZero(1e-10)) {
150  rot = Eigen::Vector3d::Zero();
151  } else {
152 #if 0
153  auto magnitude = q.vec().blueNorm();
154  rot = (q.vec() / magnitude * (2. * std::atan2(magnitude, q.w()))) /
155  report.state.dt;
156 #else
157  auto angle = std::acos(q.w());
158  rot = q.vec().normalized() * angle * 2 / report.state.dt;
159 #endif
160  }
161 
162  m_fusion.handleIMUVelocity(timestamp, rot);
163  if (m_fusion.running()) {
164  sendMainPoseReport();
165  }
166  sendVelocityReport();
167 }
168 
169 void VideoIMUFusionDevice::handleVideoTrackerData(
170  const OSVR_TimeValue &timestamp, const OSVR_PoseReport &report) {
171  if (!m_fusion.running()) {
172  auto ts = OSVR_TimeValue{};
173  auto oriState = OSVR_OrientationState{};
174  auto ret = osvrGetOrientationState(m_imu, &ts, &oriState);
175  if (ret != OSVR_RETURN_SUCCESS) {
176  static int i = 0;
177  if (i == 20) {
178  std::cout << "\n\nWarning: Have received several video tracker "
179  "reports without receiving one from the IMU, "
180  "which shouldn't happen. Please try "
181  "disconnecting/reconnecting and restarting the "
182  "server, and if this re-occurs, double-check your "
183  "configuration files.\n"
184  << std::endl;
185  }
186  i++;
187  return;
188  }
189  m_fusion.handleVideoTrackerDataDuringStartup(timestamp, report,
190  oriState);
191  return;
192  }
193  m_fusion.handleVideoTrackerDataWhileRunning(timestamp, report);
194  sendMainPoseReport();
196  m_dev, m_trackerOut, &m_fusion.getLatestReorientedVideoPose(),
197  TRANSFORMED_VIDEO_SENSOR_ID, &timestamp);
198 }
199 
200 void VideoIMUFusionDevice::sendMainPoseReport() {
202  m_dev, m_trackerOut, &m_fusion.getLatestPose(), FUSED_SENSOR_ID,
203  &m_fusion.getLatestTime());
204 }
205 
206 void VideoIMUFusionDevice::sendVelocityReport() {
208  m_dev, m_trackerOut, &m_fusion.getLatestVelocity(), FUSED_SENSOR_ID,
209  &m_fusion.getLatestVelocityTime());
210 }
OSVR_PoseState const & getLatestCameraPose() const
OSVR_ReturnCode osvrRegisterAngularVelocityCallback(OSVR_ClientInterface iface, OSVR_AngularVelocityCallback cb, void *userdata)
Register a callback for AngularVelocity reports on an interface.
uint32_t OSVR_ChannelCount
The integer type specifying a number of channels/sensors or a channel/sensor index.
Definition: ChannelCountC.h:51
Wrapper class for OSVR_DeviceToken.
OSVR_ReturnCode osvrClientGetInterface(OSVR_ClientContext ctx, const char path[], OSVR_ClientInterface *iface)
Get the interface associated with the given path.
Definition: InterfaceC.cpp:37
OSVR_ReturnCode osvrClientFreeInterface(OSVR_ClientContext ctx, OSVR_ClientInterface iface)
Free an interface object before context closure.
Definition: InterfaceC.cpp:53
void handleVideoTrackerDataWhileRunning(const OSVR_TimeValue &timestamp, const OSVR_PoseReport &report)
OSVR_ReturnCode osvrRegisterOrientationCallback(OSVR_ClientInterface iface, OSVR_OrientationCallback cb, void *userdata)
Register a callback for Orientation reports on an interface.
A DeviceToken connects the generic device interaction code in PluginKit's C API with the workings of ...
Definition: DeviceToken.h:56
OSVR_AngularVelocityState state
The state itself.
OSVR_ReturnCode osvrRegisterPoseCallback(OSVR_ClientInterface iface, OSVR_PoseCallback cb, void *userdata)
Register a callback for Pose reports on an interface.
EIGEN_MAKE_ALIGNED_OPERATOR_NEW void handleIMUData(const OSVR_TimeValue &timestamp, const OSVR_OrientationReport &report)
A structure defining a quaternion, often a unit quaternion representing 3D rotation.
Definition: QuaternionC.h:49
OSVR_ReturnCode osvrDeviceTrackerSendPose(OSVR_DeviceToken dev, OSVR_TrackerDeviceInterface iface, OSVR_PoseState const *val, OSVR_ChannelCount sensor)
Report the full rigid body pose of a sensor, automatically generating a timestamp.
OSVR_PoseState const & getLatestReorientedVideoPose() const
Structure used internally to construct the desired type of device.
VideoIMUFusionDevice(OSVR_PluginRegContext ctx, std::string const &name, std::string const &imuPath, std::string const &videoPath, VideoIMUFusionParams const &params=VideoIMUFusionParams())
#define OSVR_RETURN_FAILURE
The "failure" value for an OSVR_ReturnCode.
Definition: ReturnCodesC.h:47
#define OSVR_RETURN_SUCCESS
The "success" value for an OSVR_ReturnCode.
Definition: ReturnCodesC.h:45
OSVR_DeviceInitOptions osvrDeviceCreateInitOptions(OSVR_PluginRegContext ctx)
Create a OSVR_DeviceInitOptions object.
void registerUpdateCallback(DeviceObjectType *object)
Given a pointer to your object that has a public OSVR_ReturnCode update() method, registers that inst...
void handleVideoTrackerDataDuringStartup(const OSVR_TimeValue &timestamp, const OSVR_PoseReport &report, const OSVR_OrientationState &orientation)
Report type for an orientation callback on a tracker interface.
OSVR_PoseState const & getLatestPose() const
Returns the latest (fusion result, if available) pose.
Internal, configured header file for verbosity macros.
Header for interoperation between the Eigen math library, the internal mini math library, and VRPN's quatlib.
OSVR_ReturnCode osvrDeviceTrackerSendPoseTimestamped(OSVR_DeviceToken dev, OSVR_TrackerDeviceInterface iface, OSVR_PoseState const *val, OSVR_ChannelCount sensor, OSVR_TimeValue const *timestamp)
Report the full rigid body pose of a sensor, using the supplied timestamp.
OSVR_ReturnCode osvrDeviceTrackerConfigure(OSVR_DeviceInitOptions opts, OSVR_TrackerDeviceInterface *iface)
Specify that your device will implement the Tracker interface.
OSVR_ReturnCode osvrGetOrientationState(OSVR_ClientInterface iface, struct OSVR_TimeValue *timestamp, OSVR_OrientationState *state)
Get Orientation state from an interface, returning failure if none \ * exists.
OSVR_EXTERN_C_BEGIN typedef void * OSVR_PluginRegContext
A context pointer passed in to your plugin's entry point and other locations of control flow transfer...
Report type for an angular velocity callback on a tracker interface.
Standardized, portable parallel to struct timeval for representing both absolute times and time inter...
Definition: TimeValueC.h:81
void sendJsonDescriptor(const char *json, size_t len)
Submit a JSON self-descriptor string for the device.
OSVR_ANALYSISPLUGINKIT_EXPORT OSVR_ReturnCode osvrAnalysisSyncInit(OSVR_PluginRegContext ctx, const char *name, OSVR_DeviceInitOptions options, OSVR_DeviceToken *device, OSVR_ClientContext *clientCtx)
Initialize a synchronous analysis device token with the options specified, also returning the associa...
Report type for a pose (position and orientation) callback on a tracker interface.
osvr::util::time::TimeValue const & getLatestTime() const
OSVR_ReturnCode osvrDeviceTrackerSendVelocityTimestamped(OSVR_DeviceToken dev, OSVR_TrackerDeviceInterface iface, OSVR_VelocityState const *val, OSVR_ChannelCount sensor, OSVR_TimeValue const *timestamp)
Report the linear and angular velocity of a sensor, using the supplied timestamp. ...