OSVR Framework (Internal Development Docs)  0.6-1962-g59773924
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
EyeTrackerRemoteFactory.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
27 #include "RemoteHandlerInternals.h"
32 #include <osvr/Util/UniquePtr.h>
35 #include <osvr/Util/Verbosity.h>
37 
43 
44 // Library/third-party includes
45 #include <boost/lexical_cast.hpp>
46 #include <boost/any.hpp>
47 #include <boost/variant/get.hpp>
48 #include <boost/lexical_cast.hpp>
49 #include <boost/optional.hpp>
50 #include <json/value.h>
51 #include <json/reader.h>
52 
53 // Standard includes
54 #include <iostream>
55 #include <string>
56 
57 namespace osvr {
58 namespace client {
59 
61  public:
62  struct Options {
63  Options()
64  : reportDirection(false), reportBasePoint(false),
65  reportLocation2D(false), reportBlink(false), dirIface() {}
66  bool reportDirection;
67  bool reportBasePoint;
68  bool reportLocation2D;
69  bool reportBlink;
74  };
75 
76  EyeTrackerRemoteHandler(vrpn_ConnectionPtr const &conn,
77  std::string const &deviceName,
78  Options const &options,
79  boost::optional<OSVR_ChannelCount> sensor,
80  common::InterfaceList &ifaces)
81  : m_dev(common::createClientDevice(deviceName, conn)),
82  m_internals(ifaces), m_all(!sensor.is_initialized()),
83  m_opts(options), m_sensor(sensor) {
84  auto eyetracker = common::EyeTrackerComponent::create();
85  m_dev->addComponent(eyetracker);
86  eyetracker->registerEyeHandler(
87  [&](common::OSVR_EyeNotification const &data,
88  util::time::TimeValue const &timestamp) {
89  m_handleEyeTracking(data, timestamp);
90  });
91  OSVR_DEV_VERBOSE("Constructed an Eye Handler for " << deviceName);
92  }
93 
95  EyeTrackerRemoteHandler &
96  operator=(EyeTrackerRemoteHandler const &) = delete;
97 
100  }
101 
102  virtual void update() { m_dev->update(); }
103 
104  private:
105  void m_handleEyeTracking3d(common::OSVR_EyeNotification const &data,
106  util::time::TimeValue const &timestamp) {
107 
109  report.sensor = data.sensor;
110  report.state.directionValid = false;
111  report.state.basePointValid = false;
112  util::time::TimeValue timest = timestamp;
113  if (m_opts.reportDirection) {
114  report.state.directionValid =
115  m_opts.dirIface->getState<OSVR_DirectionReport>(
116  timest, report.state.direction);
117  }
118  if (m_opts.reportBasePoint) {
119  report.state.basePointValid =
120  m_opts.trackerIface->getState<OSVR_PositionReport>(
121  timest, report.state.basePoint);
122  }
123  if (!(report.state.basePointValid || report.state.directionValid)) {
124  return; // don't send an empty report.
125  }
126 
130 
131  m_internals.setStateAndTriggerCallbacks(timestamp, report);
132  }
133 
134  void m_handleEyeTracking2d(common::OSVR_EyeNotification const &data,
135  util::time::TimeValue const &timestamp) {
136 
137  if (!m_opts.reportLocation2D) {
138  return;
139  }
141  report.sensor = data.sensor;
142  bool locationValid = false;
143  util::time::TimeValue reportTime;
144 
145  locationValid =
146  m_opts.locationIface->getState<OSVR_Location2DReport>(
147  reportTime, report.state);
148  if (!locationValid) {
149  return; // don't send an empty report.
150  }
151 
155 
156  m_internals.setStateAndTriggerCallbacks(timestamp, report);
157  }
158 
159  void m_handleEyeBlink(common::OSVR_EyeNotification const &data,
160  util::time::TimeValue const &timestamp) {
161 
162  if (!m_opts.reportBlink) {
163  return;
164  }
166  report.sensor = data.sensor;
167  bool haveBlink = false;
168  util::time::TimeValue blinkTimestamp;
169 
170  haveBlink = m_opts.buttonIface->getState<OSVR_ButtonReport>(
171  blinkTimestamp, report.state);
172  if (!haveBlink) {
173  return; // don't send an empty report.
174  }
178 
179  m_internals.setStateAndTriggerCallbacks(timestamp, report);
180  }
181 
182  void m_handleEyeTracking(common::OSVR_EyeNotification const &data,
183  util::time::TimeValue const &timestamp) {
184  if (!m_all && *m_sensor != data.sensor) {
186  return;
187  }
188 
189  m_handleEyeTracking3d(data, timestamp);
190  m_handleEyeTracking2d(data, timestamp);
191  m_handleEyeBlink(data, timestamp);
192  }
193 
194  common::BaseDevicePtr m_dev;
195  RemoteHandlerInternals m_internals;
196  bool m_all;
197  Options m_opts;
198  boost::optional<OSVR_ChannelCount> m_sensor;
199  };
200 
201  EyeTrackerRemoteFactory::EyeTrackerRemoteFactory(
202  VRPNConnectionCollection const &conns)
203  : m_conns(conns) {}
204 
205  shared_ptr<RemoteHandler> EyeTrackerRemoteFactory::
207  common::InterfaceList &ifaces, common::ClientContext &ctx) {
208 
209  shared_ptr<RemoteHandler> ret;
210 
212 
213  auto const &myDescriptor = source.getDeviceElement().getDescriptor();
214  auto devicePath = source.getDevicePath();
215 
216  if (myDescriptor["interfaces"]["eyetracker"].isMember("direction")) {
217  opts.reportDirection = true;
218  const std::string iface = devicePath + "/direction";
220  // boost::lexical_cast<std::string>(source.getSensorNumberAsChannelCount())
221  opts.dirIface = ctx.getInterface(iface.c_str());
222  }
223  if (myDescriptor["interfaces"]["eyetracker"].isMember("tracker")) {
224  opts.reportBasePoint = true;
225  const std::string iface = devicePath + "/tracker/";
227  // boost::lexical_cast<std::string>(source.getSensorNumberAsChannelCount())
228  opts.trackerIface = ctx.getInterface(iface.c_str());
229  }
230 
231  if (myDescriptor["interfaces"]["eyetracker"].isMember("location2D")) {
232  opts.reportLocation2D = true;
233  const std::string iface = devicePath + "/location2D/";
235  // boost::lexical_cast<std::string>(source.getSensorNumberAsChannelCount())
236  opts.locationIface = ctx.getInterface(iface.c_str());
237  }
238  if (myDescriptor["interfaces"]["eyetracker"].isMember("button")) {
239  opts.reportBlink = true;
240  const std::string iface = devicePath + "/button/";
242  // boost::lexical_cast<std::string>(source.getSensorNumberAsChannelCount())
243  opts.buttonIface = ctx.getInterface(iface.c_str());
244  }
245 
246  if (source.hasTransform()) {
248  OSVR_DEV_VERBOSE(
249  "Ignoring transform found on route for Eye Tracker data!");
250  }
251 
252  auto const &devElt = source.getDeviceElement();
253 
254  ret.reset(new EyeTrackerRemoteHandler(
255  m_conns.getConnection(devElt), devElt.getFullDeviceName(), opts,
256  source.getSensorNumberAsChannelCount(), ifaces));
257  return ret;
258  }
259 
260 } // namespace client
261 } // namespace osvr
The result of resolving a tree node to a device: either an original source to connect to...
shared_ptr< ClientInterface > ClientInterfacePtr
Pointer for holding ClientInterface objects safely.
BaseDevicePtr createClientDevice(std::string const &name, vrpn_ConnectionPtr const &conn)
Factory function for a bare client device with no components/interfaces registered by default...
Header including PathTree.h and all additional headers needed to define related types.
Header to bring unique_ptr into the osvr namespace.
Report type for 2D location report.
Report type for a callback on a button interface.
osvr::common::ClientInterfacePtr getInterface(const char path[])
Creates an interface object for the given path. The context retains shared ownership.
::OSVR_TimeValue TimeValue
C++-friendly typedef for the OSVR_TimeValue structure.
Definition: TimeValue.h:48
std::string getDevicePath() const
Gets the full path of the device node.
static shared_ptr< EyeTrackerComponent > create(OSVR_ChannelCount numSensor=2)
Factory method.
Report type for 3D Direction vector.
Report type for a blink event.
EyeTrackerRemoteHandler & operator=(EyeTrackerRemoteHandler const &)=delete
Deleted assignment operator.
Report type for 2D location.
void setStateAndTriggerCallbacks(const OSVR_TimeValue &timestamp, ReportType const &report)
Set state and call callbacks for a report type.
Report type for 3D gaze report.
Internal, configured header file for verbosity macros.
Report type for a position callback on a tracker interface.
Standardized, portable parallel to struct timeval for representing both absolute times and time inter...
Definition: TimeValueC.h:81
Base class for remote device handler classes.
Definition: RemoteHandler.h:40
shared_ptr< RemoteHandler > operator()(common::OriginalSource const &source, common::InterfaceList &ifaces, common::ClientContext &ctx)