vrpn  07.33
Virtual Reality Peripheral Network
vrpn_Tracker_zSight.C
Go to the documentation of this file.
1 //
3 // Name: vrpn_Tracker_zSight.C
4 //
5 // Authors: David Borland
6 // Josep Maria Tomas Sanahuja
7 //
8 // EventLab at the University of Barcelona
9 //
10 // Description: VRPN tracker class for Sensics zSight HMD with built-in tracker. The tracker
11 // reports only orientation information, not position. It is interfaced to as
12 // a DirectX joystick, so VRPN_USE_DIRECTINPUT must be defined in
13 // vrpn_Configure.h to use it.
14 //
16 
17 #include "vrpn_Tracker_zSight.h"
18 
19 #if defined(_WIN32) && defined(VRPN_USE_DIRECTINPUT) && defined(VRPN_HAVE_ATLBASE)
20 
21 #include <math.h>
22 
23 // Convert from 2's complement, as per the Sensics zSight documentation
24 short FromTwos(unsigned short x) {
25  if ( x < 0x8000 ) {
26  return (short) x;
27  }
28  else {
29  x = x ^ 0xFFFF;
30  short y = (short) x;
31  if (y != 32767) {
32  y = y + 1;
33  }
34  y = -y;
35  return (short) y;
36  }
37 }
38 
39 vrpn_Tracker_zSight::vrpn_Tracker_zSight(const char* name, vrpn_Connection* c) :
40  vrpn_Tracker(name, c)
41 {
42  // Create a window handle
43  hWnd = CreateWindow("STATIC", "zSightWindow", WS_ICONIC, 0, 0, 10, 10, NULL, NULL, NULL, NULL);
44 
45  // Initialize DirectInput and acquire the device
46  if (FAILED(InitDevice())) {
47  fprintf(stderr,"vrpn_Tracker_zSight::vrpn_Tracker_zSight(): Failed to open device\n");
48  hWnd = NULL;
49  return;
50  }
51 
52  // VRPN stuff
54 }
55 
56 vrpn_Tracker_zSight::~vrpn_Tracker_zSight()
57 {
58  // Release the Sensics device if necessary
59  if (sensics) {
60  sensics->Unacquire();
61  }
62 }
63 
64 void vrpn_Tracker_zSight::mainloop()
65 {
66  // Call the generic server mainloop, since we are a server
67  server_mainloop();
68 
69  // Get latest data
70  get_report();
71 }
72 
73 void vrpn_Tracker_zSight::get_report()
74 {
75  // Get the current time
76  vrpn_gettimeofday(&timestamp, NULL);
77 
78  if (hWnd) {
79  HRESULT hr;
80  DIJOYSTATE2 js;
81  if (FAILED(hr = sensics->GetDeviceState(sizeof(DIJOYSTATE2), &js))) {
82  fprintf(stderr, "vrpn_Tracker_zSight::get_report(): Can't read tracker\n");
83  return;
84  }
85 
86  // No need to fill in position, as we donīt get position information
87 
88  // Get the orientation, as per the Sensics zSight documentation
89  float w = FromTwos((unsigned short) js.lRx) / 32768.0f;
90  float x = FromTwos((unsigned short) js.lRy) / 32768.0f;
91  float y = FromTwos((unsigned short) js.lX) / 32768.0f;
92  float z = FromTwos((unsigned short) js.lY) / 32768.0f;
93  float mag = sqrt(w*w + x*x + y*y + z*z);
94 
95  // Set for internal quat, as per the Sensics zSight documentation
96  d_quat[3] = w / mag;
97  d_quat[0] = x / mag;
98  d_quat[1] = y / mag;
99  d_quat[2] = -z / mag;
100  }
101 
102  // Send the data
103  send_report();
104 }
105 
106 void vrpn_Tracker_zSight::send_report()
107 {
108  if (d_connection) {
109  char msgbuf[1000];
110  int len = encode_to(msgbuf);
111  if (d_connection->pack_message(len, timestamp, position_m_id, d_sender_id, msgbuf,
113  fprintf(stderr,"vrpn_Tracker_zSight: cannot write message: tossing\n");
114  }
115  }
116 }
117 
118 HRESULT vrpn_Tracker_zSight::InitDevice()
119 {
120  HRESULT hr;
121 
122  // Register with the DirectInput subsystem and get a pointer to an IDirectInput interface we can use.
123  if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL),
125  IID_IDirectInput8,
126  (void**)&directInput, NULL))) {
127  fprintf(stderr, "vrpn_Tracker_zSight::InitDevice(): Cannot open DirectInput\n");
128  return hr;
129  }
130 
131  // Initialize the zSight device, which is implemented as a DirectInput joystick
132  if (FAILED(hr = directInput->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumSensicsCallback, this, DIEDFL_ATTACHEDONLY))) {
133  fprintf(stderr, "vrpn_Tracker_zSight::InitDevice(): Cannot enumerate device\n");
134  return hr;
135  }
136 
137  // Make sure we got the device we wanted
138  if (sensics == NULL) {
139  fprintf(stderr, "vrpn_Tracker_zSight::InitDevice(): No Sensics zSight device found\n");
140  return E_FAIL;
141  }
142 
143  // Set the data format
144  if (FAILED(hr = sensics->SetDataFormat(&c_dfDIJoystick2)))
145  {
146  fprintf(stderr, "vrpn_Tracker_zSight::InitDevice(): Cannot set data format\n");
147  sensics->Unacquire();
148  return hr;
149  }
150 
151  // Set the cooperative level
152  if (FAILED(hr = sensics->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND))) {
153  fprintf(stderr, "vrpn_Tracker_zSight::InitDevice(): Cannot set cooperative level\n");
154  sensics->Unacquire();
155  return hr;
156  }
157 
158  // Get the joystick axis object
159  if (FAILED(hr = sensics->EnumObjects(EnumObjectsCallback, this, DIDFT_AXIS))) {
160  fprintf(stderr, "vrpn_Tracker_zSight::InitDevice(): Cannot enumerate objects\n");
161  sensics->Unacquire();
162  return hr;
163  }
164 
165  // Acquire the joystick
166  if (FAILED(hr = sensics->Acquire())) {
167  char *reason;
168 
169  switch (hr) {
170 
171  case DIERR_INVALIDPARAM:
172  reason = "Invalid parameter";
173  break;
174 
175  case DIERR_NOTINITIALIZED:
176  reason = "Not initialized";
177  break;
178 
179  case DIERR_OTHERAPPHASPRIO:
180  reason = "Another application has priority";
181  break;
182 
183  default:
184  reason = "Unknown";
185  }
186 
187  fprintf(stderr, "vrpn_Tracker_zSight::InitDevice(): Cannot acquire device because %s\n", reason);
188  sensics->Unacquire();
189  return hr;
190  }
191 
192  return S_OK;
193 }
194 
195 BOOL CALLBACK vrpn_Tracker_zSight::EnumSensicsCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* selfPtr)
196 {
197  vrpn_Tracker_zSight* me = (vrpn_Tracker_zSight*)(selfPtr);
198  HRESULT hr;
199 
200  // Obtain an interface to the tracker
201  hr = me->directInput->CreateDevice(pdidInstance->guidInstance, &me->sensics, NULL);
202 
203  // Make sure it is a Sensics zSight device
204  if (SUCCEEDED(hr) == TRUE) {
205  if (strcmp(pdidInstance->tszProductName, "Sensics zSight HMD") != 0) {
206  me->sensics->Unacquire();
207  }
208  else {
209  return DIENUM_STOP;
210  }
211  }
212 
213  return DIENUM_CONTINUE;
214 }
215 
216 BOOL CALLBACK vrpn_Tracker_zSight::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* selfPtr)
217 {
218  vrpn_Tracker_zSight* me = (vrpn_Tracker_zSight*)(selfPtr);
219 
220  if (pdidoi->dwType & DIDFT_AXIS) {
221  DIPROPRANGE diprg;
222  ::memset(&diprg, 0, sizeof(DIPROPRANGE));
223  diprg.diph.dwSize = sizeof(DIPROPRANGE);
224  diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
225  diprg.diph.dwHow = DIPH_BYID;
226  diprg.diph.dwObj = pdidoi->dwType; // Specify the enumerated axis
227  diprg.lMin = 0;
228  diprg.lMax = 65535;
229 
230  // Set the range for the axis
231  if (FAILED(me->sensics->SetProperty(DIPROP_RANGE, &diprg.diph))) {
232  fprintf(stderr, "vrpn_Tracker_zSight::vrpn_Tracker_zSight(): Cannot set data range\n");
233  return DIENUM_STOP;
234  }
235  }
236 
237  return DIENUM_CONTINUE;
238 }
239 
240 #endif
vrpn_Tracker
Definition: vrpn_Tracker.h:49
DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION
Definition: vrpn_Configure.h:501
vrpn_CONNECTION_LOW_LATENCY
const vrpn_uint32 vrpn_CONNECTION_LOW_LATENCY
Definition: vrpn_Connection.h:122
vrpn_Connection
Generic connection class not specific to the transport mechanism.
Definition: vrpn_Connection.h:510
vrpn_gettimeofday
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
vrpn_Tracker::register_server_handlers
int register_server_handlers(void)
Definition: vrpn_Tracker.C:318
vrpn_Tracker_zSight.h