40 #include "com_osvr_VideoBasedHMDTracker_json.h"
43 #include <opencv2/core/core.hpp>
44 #include <opencv2/core/operations.hpp>
45 #include <opencv2/highgui/highgui.hpp>
46 #include <opencv2/imgproc/imgproc.hpp>
47 #include <json/value.h>
48 #include <json/reader.h>
50 #include <boost/noncopyable.hpp>
71 static const auto DEBUGGABLE_BEACONS = 34;
72 static const auto DATAPOINTS_PER_BEACON = 5;
74 class VideoBasedHMDTracker : boost::noncopyable {
77 osvr::vbtracker::ImageSourcePtr &&source,
81 : m_source(std::move(source)), m_vbtracker(params), m_params(params) {
82 if (params.numThreads > 0) {
84 cv::setNumThreads(params.numThreads);
94 DEBUGGABLE_BEACONS * DATAPOINTS_PER_BEACON);
97 std::ostringstream os;
98 os <<
"TrackedCamera" << devNumber <<
"_" << 0;
101 m_dev.initAsync(ctx, os.str(), opts);
104 m_dev.sendJsonDescriptor(com_osvr_VideoBasedHMDTracker_json);
107 m_dev.registerUpdateCallback(
this);
110 OSVR_ReturnCode update();
120 osvr::vbtracker::ImageSourcePtr m_source;
122 #ifdef VBHMD_SAVE_IMAGES
131 inline OSVR_ReturnCode VideoBasedHMDTracker::update() {
132 if (!m_source->ok()) {
140 if (!m_source->grab()) {
156 m_source->retrieve(m_frame, m_imageGray);
158 #ifdef VBHMD_SAVE_IMAGES
161 std::ostringstream fileName;
162 fileName << VBHMD_SAVE_IMAGES <<
"/";
163 fileName << std::setfill(
'0') << std::setw(4) << m_imageNum++;
165 if (!cv::imwrite(fileName.str(), m_frame)) {
166 std::cerr <<
"Could not write image to " << fileName.str() << std::endl;
174 static struct timeval last = {0, 0};
175 if (last.tv_sec == 0) {
176 vrpn_gettimeofday(&last, NULL);
178 static unsigned count = 0;
179 if (++count == 100) {
181 vrpn_gettimeofday(&now, NULL);
182 double duration = vrpn_TimevalDurationSeconds(now, last);
183 std::cout <<
"Video-based tracker: update rate " << count / duration
184 <<
" hz" << std::endl;
189 bool shouldSendDebug =
false;
190 m_vbtracker.processImage(
191 m_frame, m_imageGray, timestamp,
200 shouldSendDebug =
true;
203 if (shouldSendDebug && m_params.streamBeaconDebugInfo) {
204 double data[DEBUGGABLE_BEACONS * DATAPOINTS_PER_BEACON];
205 auto &debug = m_vbtracker.getFirstEstimator().getBeaconDebugData();
207 auto n = std::min(
size_t(DEBUGGABLE_BEACONS), debug.size());
208 for (std::size_t i = 0; i < n; ++i) {
209 double *buf = &data[i];
210 auto j = i * DATAPOINTS_PER_BEACON;
213 data[j] = debug[i].variance;
214 data[j + 1] = debug[i].measurement.x;
215 data[j + 2] = debug[i].measurement.y;
216 data[j + 3] = debug[i].residual.x;
217 data[j + 4] = debug[i].residual.y;
225 class HardwareDetection {
227 using CameraFactoryType = std::function<osvr::vbtracker::ImageSourcePtr()>;
228 using SensorSetupType = std::function<void(VideoBasedHMDTracker &)>;
229 HardwareDetection(CameraFactoryType camFactory, SensorSetupType setup,
233 : m_found(
false), m_cameraFactory(camFactory), m_sensorSetup(setup),
234 m_cameraID(cameraID), m_params(params) {}
240 auto src = m_cameraFactory();
241 if (!src || !src->ok()) {
242 if (!m_reportedNoCamera) {
243 m_reportedNoCamera =
true;
245 <<
"\nVideo-based tracker: Could not open the tracking "
246 "camera. If you intend to use it, make sure that "
247 "all cables to it are plugged in firmly.\n";
250 std::cout <<
"Video-based tracker: Windows users may need to "
257 "exit other camera-using applications or "
258 "activities until after the tracking camera is "
259 "turned on by this plugin. (This is the most "
260 "common cause of messages regarding the 'filter "
263 std::cout << std::endl;
267 std::cout <<
"Video-based tracker: Camera turned on!" << std::endl;
271 std::cout <<
"Opening camera " << m_cameraID << std::endl;
273 ctx,
new VideoBasedHMDTracker(ctx, std::move(src), m_cameraID,
275 m_sensorSetup(*newTracker);
282 bool m_found =
false;
283 bool m_reportedNoCamera =
false;
285 CameraFactoryType m_cameraFactory;
286 SensorSetupType m_sensorSetup;
292 class ConfiguredDeviceConstructor {
301 if (!r.parse(params, root)) {
302 std::cerr <<
"Could not parse parameters!" << std::endl;
310 int cameraID = root.get(
"cameraID", 0).asInt();
313 auto config = osvr::vbtracker::parseConfigParams(root);
317 auto backPanelFixedBeacon = [](int) {
return true; };
318 auto frontPanelFixedBeacon = [](
int id) {
319 return (
id == 16) || (
id == 17) || (
id == 19) || (
id == 20);
323 bool fakeImages =
false;
326 auto path = std::string{};
328 auto src = osvr::vbtracker::openImageFileSequence(path);
333 ctx,
new VideoBasedHMDTracker(ctx, std::move(src), cameraID,
335 auto camParams = osvr::vbtracker::getSimulatedHDKCameraParameters();
336 newTracker->vbtracker().addSensor(
337 osvr::vbtracker::createHDKLedIdentifierSimulated(0), camParams,
338 osvr::vbtracker::OsvrHdkLedLocations_SENSOR0,
339 osvr::vbtracker::OsvrHdkLedDirections_SENSOR0,
340 frontPanelFixedBeacon, 4, 2);
343 newTracker->vbtracker().addSensor(
344 osvr::vbtracker::createHDKLedIdentifierSimulated(1), camParams,
345 osvr::vbtracker::OsvrHdkLedLocations_SENSOR1,
346 osvr::vbtracker::OsvrHdkLedDirections_SENSOR1,
347 backPanelFixedBeacon, 4, 0);
351 bool isOculusCamera = (width == 376) && (height == 480);
355 auto cameraFactory = &osvr::vbtracker::openHDKCameraDirectShow;
364 auto cameraFactory = [=] {
365 return osvr::vbtracker::openOpenCVCamera(cameraID);
370 std::function<void(VideoBasedHMDTracker & newTracker)>
371 setupHDKParamsAndSensors;
373 if (config.includeRearPanel) {
374 setupHDKParamsAndSensors = [config](
375 VideoBasedHMDTracker &newTracker) {
376 osvr::vbtracker::setupSensorsIncludeRearPanel(
377 newTracker.vbtracker(), config);
382 setupHDKParamsAndSensors = [config](
383 VideoBasedHMDTracker &newTracker) {
384 osvr::vbtracker::setupSensorsWithoutRearPanel(
385 newTracker.vbtracker(), config);
391 context.registerHardwareDetectCallback(
new HardwareDetection(
392 cameraFactory, setupHDKParamsAndSensors, cameraID, config));
405 ctx,
"VideoBasedHMDTracker",
new ConfiguredDeviceConstructor);
uint32_t OSVR_ChannelCount
The integer type specifying a number of channels/sensors or a channel/sensor index.
Wrapper class for OSVR_DeviceToken.
void getNow(TimeValue &tv)
Set the given TimeValue to the current time.
void osvrTimeValueGetNow(OSVR_TimeValue *dest)
Gets the current time in the TimeValue. Parallel to gettimeofday.
C++ wrapper class for the opaque plugin context.
Structure used internally to construct the desired type of device.
double duration(TimeValue const &a, TimeValue const &b)
Get a double containing seconds between the time points.
#define OSVR_RETURN_FAILURE
The "failure" value for an OSVR_ReturnCode.
T * registerObjectForDeletion(OSVR_PluginRegContext ctx, T *obj)
Registers an object to be destroyed with delete when the plugin is unloaded.
General configuration parameters.
void registerDriverInstantiationCallback(OSVR_PluginRegContext ctx, const char driverName[], T functor)
Registers a function object to be called when the server is told to instantiate a driver by name with...
#define OSVR_RETURN_SUCCESS
The "success" value for an OSVR_ReturnCode.
OSVR_DeviceInitOptions osvrDeviceCreateInitOptions(OSVR_PluginRegContext ctx)
Create a OSVR_DeviceInitOptions object.
Header including the full PluginKit C++ interface.
OSVR_PLUGIN(com_osvr_VideoBasedHMDTracker)
OSVR_ReturnCode osvrDeviceAnalogSetValuesTimestamped(OSVR_DeviceToken dev, OSVR_AnalogDeviceInterface iface, OSVR_AnalogState val[], OSVR_ChannelCount chans, OSVR_TimeValue const *timestamp)
Report the value of multiple channels with the supplied timestamp.
A structure defining a 3D (6DOF) rigid body pose: translation and rotation.
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_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...
Standardized, portable parallel to struct timeval for representing both absolute times and time inter...
OSVR_ReturnCode osvrDeviceAnalogConfigure(OSVR_DeviceInitOptions opts, OSVR_AnalogDeviceInterface *iface, OSVR_ChannelCount numChan)
Specify that your device will implement the Analog interface.