vrpn  07.33
Virtual Reality Peripheral Network
vrpn_Tracker_NovintFalcon.C
Go to the documentation of this file.
1 // -*- c++ -*-
2 // This file provides an interface to a Novint Falcon.
3 // http://home.novint.com/products/novint_falcon.php
4 // It uses libnifalcon to communicate with the device.
5 // http://libnifalcon.nonpolynomial.org/
6 //
7 // File: vrpn_Tracker_NovintFalcon.C
8 // Author: Axel Kohlmeyer akohlmey@gmail.com
9 // Date: 2010-08-12
10 // Copyright: (C) 2010 Axel Kohlmeyer
11 // License: Boost Software License 1.0
12 // depends: libnifalcon-1.0.1+, libusb-1.0, boost 1.39, VRPN 07_27
13 // tested on: Linux x86_64 w/ gcc 4.4.1
14 
16 
17 #if defined(VRPN_USE_LIBNIFALCON)
18 #include "boost/array.hpp"
19 #include "boost/ptr_container/ptr_vector.hpp"
20 #include "boost/shared_ptr.hpp"
21 #include "falcon/core/FalconDevice.h"
22 #include "falcon/firmware/FalconFirmwareNovintSDK.h"
23 #include "falcon/grip/FalconGripFourButton.h"
24 #include "falcon/kinematic/FalconKinematicStamper.h"
25 #include "falcon/util/FalconFirmwareBinaryNvent.h"
26 
27 /**************************************************************************/
28 // number of retries for the I/O loop.
29 #define FALCON_NUM_RETRIES 10
30 
31 // define to activate additional messages about
32 // what the driver is currently trying to do.
33 #undef VERBOSE
34 
35 // define for detailed status tracking. very verbose.
36 #undef VERBOSE2
37 /**************************************************************************/
38 
39 // save us some typing
40 typedef boost::array<double, 3> d_vector;
41 
43 static d_vector operator+(const d_vector &a,const d_vector &b)
44 {
45  d_vector ret;
46  ret[0] = a[0] + b[0];
47  ret[1] = a[1] + b[1];
48  ret[2] = a[2] + b[2];
49  return ret;
50 }
51 
53 static d_vector operator-(const d_vector &a,const d_vector &b)
54 {
55  d_vector ret;
56  ret[0] = a[0] + b[0];
57  ret[1] = a[1] + b[1];
58  ret[2] = a[2] + b[2];
59  return ret;
60 }
61 
63 static double d_length(const d_vector &a)
64 {
65  double ret;
66  ret = a[0] * a[0];
67  ret += a[1] * a[1];
68  ret += a[2] * a[2];
69  return sqrt(ret);
70 }
71 
72 /*************************************************************************/
73 // compute time difference in microseconds.
74 static double timediff(struct timeval t1, struct timeval t2) {
75  return (t1.tv_usec - t2.tv_usec)*1.0 + 1000000.0 * (t1.tv_sec - t2.tv_sec);
76 }
77 
78 /*************************************************************************/
79 
80 class vrpn_NovintFalcon_Device
81 {
82 public:
83  vrpn_NovintFalcon_Device(int flags)
84  : m_flags(flags)
85  {
86  if (m_flags < 0) {
87  m_falconDevice = NULL;
88  return;
89  } else {
90  m_falconDevice = new libnifalcon::FalconDevice;
91  m_falconDevice->setFalconFirmware<libnifalcon::FalconFirmwareNovintSDK>();
92  }
93 
94  if (m_flags & KINE_STAMPER) {
95  m_falconDevice->setFalconKinematic<libnifalcon::FalconKinematicStamper>();
96  } else {
97  delete m_falconDevice;
98  m_falconDevice=NULL;
99  return;
100  }
101 
102  if (m_flags & GRIP_FOURBUTTON) {
103  m_falconDevice->setFalconGrip<libnifalcon::FalconGripFourButton>();
104  } else {
105  delete m_falconDevice;
106  m_falconDevice=NULL;
107  return;
108  }
109  }
110 
111  ~vrpn_NovintFalcon_Device() {
112 #ifdef VERBOSE
113  fprintf(stderr, "Closing Falcon device %d.\n", m_flags & MASK_DEVICEIDX);
114 #endif
115  if (m_falconDevice) {
116  m_falconDevice->close();
117  }
118  delete m_falconDevice;
119  m_flags=-1;
120  };
121 
122 public:
123  // open device, load firmware and calibrate.
124  bool init() {
125  if (!m_falconDevice)
126  return false;
127 
128  unsigned int count;
129  m_falconDevice->getDeviceCount(count);
130  int devidx = m_flags & MASK_DEVICEIDX;
131 
132 #ifdef VERBOSE
133  fprintf(stderr, "Trying to open Falcon device %d/%d.\n", devidx, count);
134 #endif
135  if (devidx < count) {
136  if (!m_falconDevice->open(devidx)) {
137  fprintf(stderr, "Cannot open falcon device %d - Lib Error Code: %d - Device Error Code: %d\n",
138  devidx, m_falconDevice->getErrorCode(), m_falconDevice->getFalconComm()->getDeviceErrorCode());
139  return false;
140  }
141  } else {
142  fprintf(stderr, "Trying to open non-existing Novint Falcon device %d\n", devidx);
143  return false;
144  }
145 
146  if (!m_falconDevice->isFirmwareLoaded()) {
147 #ifdef VERBOSE
148  fprintf(stderr, "Loading Falcon Firmware\n");
149 #endif
150  int i;
151  // 10 chances to load the firmware.
152  for (i=0; i<FALCON_NUM_RETRIES; ++i) {
153  if(!m_falconDevice->getFalconFirmware()->loadFirmware(false, libnifalcon::NOVINT_FALCON_NVENT_FIRMWARE_SIZE, const_cast<uint8_t*>(libnifalcon::NOVINT_FALCON_NVENT_FIRMWARE)))
154  {
155  fprintf(stderr, "Firmware loading attempt %d failed.\n", i);
156  // Completely close and reopen device and try again
157  m_falconDevice->close();
158  if(!m_falconDevice->open(devidx))
159  {
160  fprintf(stderr, "Cannot open falcon device %d - Lib Error Code: %d - Device Error Code: %d\n",
161  devidx, m_falconDevice->getErrorCode(), m_falconDevice->getFalconComm()->getDeviceErrorCode());
162  return false;
163  }
164  } else {
165 #ifdef VERBOSE
166  fprintf(stderr, "Falcon firmware successfully loaded.\n");
167 #endif
168  break;
169  }
170  }
171  } else {
172 #ifdef VERBOSE
173  fprintf(stderr, "Falcon Firmware already loaded.\n");
174 #endif
175  }
176 
177  int i;
178  bool message = false;
179  boost::shared_ptr<libnifalcon::FalconFirmware> f;
180  f=m_falconDevice->getFalconFirmware();
181  for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i) continue;
182  while(1) { // XXX: add timeout to declare device dead after a while.
183  f->setHomingMode(true);
184  for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i) continue;
185  if(!f->isHomed()) {
186  f->setLEDStatus(libnifalcon::FalconFirmware::RED_LED);
187  for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i) continue;
188  if (!message) {
189  fprintf(stderr, "Falcon not currently calibrated. Move control all the way out then push straight all the way in.\n");
190  message = true;
191  }
192  } else {
193  f->setLEDStatus(libnifalcon::FalconFirmware::BLUE_LED);
194  for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i) continue;
195 #ifdef VERBOSE
196  fprintf(stderr, "Falcon calibrated successfully.\n");
197 #endif
198  break;
199  }
200  }
201 
202  message = false;
203  while(1) { // XXX: add timeout to declare device dead after a while.
204  int i;
205 
206  for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i) continue;
207  d_vector pos = m_falconDevice->getPosition();
208  m_oldpos = pos;
209  vrpn_gettimeofday(&m_oldtime, NULL);
210 
211  if (!message) {
212  fprintf(stderr, "Move control all the way out until led turns green to activate device.\n");
213  message = true;
214  }
215  if (pos[2] > 0.170) { // XXX: value taken from libnifalcon test example
216  f->setLEDStatus(libnifalcon::FalconFirmware::GREEN_LED);
217  for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i) continue;
218 #ifdef VERBOSE
219  fprintf(stderr, "Falcon activated successfully.\n");
220 #endif
221  break;
222  }
223  }
224  return true;
225  };
226 
227  // query status of device.
228  bool get_status(vrpn_float64 *pos, vrpn_float64 *vel,
229  vrpn_float64 *quat, vrpn_float64 *vel_quat,
230  vrpn_float64 *vel_dt, unsigned char *buttons) {
231  if (!m_falconDevice)
232  return false;
233 
234  int i;
235  for (i=0; !m_falconDevice->runIOLoop() && i < FALCON_NUM_RETRIES; ++i) continue;
236  if ( i == FALCON_NUM_RETRIES )
237  return false;
238 
239  // we have no orientation of the effector.
240  // so we just pick one. to tell them apart
241  // more easily, we just give each a different
242  // orientation.
243  if (quat) {
244  switch (m_flags & MASK_DEVICEIDX) {
245  case 0:
246  quat[0] = 0.0;
247  quat[1] = 0.0;
248  quat[2] = 1.0;
249  quat[3] = 0.0;
250  break;
251  case 1:
252  quat[0] = 1.0;
253  quat[1] = 0.0;
254  quat[2] = 0.0;
255  quat[3] = 0.0;
256  break;
257  default:
258  quat[0] = 1.0;
259  quat[1] = 0.0;
260  quat[2] = 0.0;
261  quat[3] = 0.0;
262  break;
263  }
264  }
265 
266  if (vel_quat) {
267  vel_quat[0] = 0.0;
268  vel_quat[1] = 0.0;
269  vel_quat[2] = 0.0;
270  vel_quat[3] = 0.0;
271  }
272 
273  // update position information
274  d_vector my_pos = m_falconDevice->getPosition();
275  const double convert_pos = 1.0; // empirical. need to measure properly.
276  pos[0] = convert_pos * my_pos[0];
277  pos[1] = convert_pos * my_pos[1];
278  pos[2] = convert_pos * (my_pos[2]-0.125); // apply offset to make z axis data centered.
279 #ifdef VERBOSE2
280  fprintf(stderr, "position %5.3f %5.3f %5.3f\n", pos[0],pos[1],pos[2]);
281 #endif
282  if (vel) {
283  struct timeval current_time;
284  vrpn_gettimeofday(&current_time, NULL);
285  double deltat = timediff(current_time, m_oldtime);
286  *vel_dt= deltat;
287  if (deltat > 0) {
288  vel[0] = convert_pos * (my_pos[0] - m_oldpos[0]) / deltat;
289  vel[1] = convert_pos * (my_pos[1] - m_oldpos[1]) / deltat;
290  vel[2] = convert_pos * (my_pos[2] - m_oldpos[2]) / deltat;
291  } else {
292  vel[0] = 0.0;
293  vel[1] = 0.0;
294  vel[2] = 0.0;
295  }
296 #ifdef VERBOSE2
297  fprintf(stderr, "velocity %5.3f %5.3f %5.3f\n", vel[0],vel[1],vel[2]);
298 #endif
299  m_oldpos = my_pos;
300  m_oldtime.tv_sec = current_time.tv_sec;
301  m_oldtime.tv_usec = current_time.tv_usec;
302  }
303 
304  // update button information
305  unsigned int my_buttons = m_falconDevice->getFalconGrip()->getDigitalInputs();
306  if (m_flags & GRIP_FOURBUTTON) {
307  buttons[0] = (my_buttons & libnifalcon::FalconGripFourButton::CENTER_BUTTON) ? 1 : 0;
308  buttons[1] = (my_buttons & libnifalcon::FalconGripFourButton::PLUS_BUTTON) ? 1 : 0;
309  buttons[2] = (my_buttons & libnifalcon::FalconGripFourButton::MINUS_BUTTON) ? 1 : 0;
310  buttons[3] = (my_buttons & libnifalcon::FalconGripFourButton::FORWARD_BUTTON) ? 1 : 0;
311  }
312  return true;
313  };
314 
315  // set feedback force
316  bool set_force(const d_vector &force) {
317  if (!m_falconDevice)
318  return false;
319 
320  // update position information
321  m_falconDevice->setForce(force);
322  if(!m_falconDevice->runIOLoop())
323  return false;
324 
325  return true;
326  };
327 
328 protected:
329  int m_flags;
330  libnifalcon::FalconDevice *m_falconDevice;
331  d_vector m_oldpos;
332  struct timeval m_oldtime;
333 
334 private:
336  vrpn_NovintFalcon_Device() {};
338  vrpn_NovintFalcon_Device(const vrpn_NovintFalcon_Device &dev) {};
339 
340 public:
342  enum falconflags {
343  NONE = 0x0000, //< empty
344  MASK_DEVICEIDX = 0x000f, //< max. 15 falcons
345  KINE_STAMPER = 0x0010, //< stamper kinematics model
346  GRIP_FOURBUTTON = 0x0100 //< 4-button grip (the default)
347  };
348 };
349 
351 class ForceFieldEffect
352 {
353 public:
355  ForceFieldEffect() : m_active(false), m_time(0), m_cutoff(0.0), m_damping(0.9)
356  {
357  int i,j;
358  for (i=0; i < 3; i++) {
359  m_origin[i] = 0.0;
360  m_addforce[i] = 0.0;
361  for (j=0; j < 3; j++) {
362  m_jacobian[i][j] = 0.0;
363  }
364  }
365  };
366 
368  ~ForceFieldEffect() {}
369 
370 public:
372  void setForce(vrpn_float32 ori[3], vrpn_float32 frc[3], vrpn_float32 jac[3][3], vrpn_float32 rad) {
373  int i,j;
374  for (i=0; i < 3; i++) {
375  m_neworig[i] = ori[i];
376  m_newadd[i] = frc[i];
377  for (j=0; j < 3; j++) {
378  m_newjacob[i][j] = jac[i][j];
379  }
380  }
381  m_newcut = rad;
382  }
383 
385  void setDamping(double damp) {
386  m_damping = damp;
387  }
388 
390  virtual bool start() {
391  m_active = true;
392  m_time = 0.0;
393  // this will delay the effect until it
394  // is (re-)initialized with setForce()
395  m_cutoff = 0.0;
396  return m_active;
397  }
398 
400  virtual void stop() {
401  m_active = false;
402  }
403 
405  virtual bool isActive() const { return m_active; }
406 
408  d_vector calcForce(const d_vector &pos) {
409  d_vector force, offset;
410  force.assign(0.0);
411  if (m_active) {
412  // apply damping to effect values
413  const double mix = 1.0 - m_damping;
414  int i,j;
415  for (i=0; i < 3; i++) {
416  m_origin[i] = m_damping*m_origin[i] + mix*m_neworig[i];
417  m_addforce[i] = m_damping*m_addforce[i] + mix*m_newadd[i];
418  for (j=0; j < 3; j++) {
419  m_jacobian[i][j] = m_damping*m_jacobian[i][j] + mix*m_newjacob[i][j];
420  }
421  }
422  m_cutoff = m_damping*m_cutoff + mix*m_newcut;
423 
424  offset = pos - m_origin;
425  // no force too far away.
426  if (d_length(offset) > m_cutoff) {
427  return force;
428  }
429  // Compute the force, which is the constant force plus
430  // a force that varies as the effector position deviates
431  // from the origin of the force field. The Jacobian
432  // determines how the force changes in different directions
433  // away from the origin (generalizing spring forces of different
434  // magnitudes that constrain the Phantom to the point of the
435  // origin, to a line containing the origin, or to a plane
436  // containing the origin).
437  force = m_addforce;
438  for (i=0; i<3; ++i) {
439  for (j=0; j<3; ++j) {
440  force[i] += offset[j]*m_jacobian[i][j];
441  }
442  }
443  }
444  return force;
445  }
446 
447 protected:
448  bool m_active;
449  double m_time;
450  double m_cutoff;
451  d_vector m_origin;
452  d_vector m_addforce;
453  double m_jacobian[3][3];
454  double m_newcut;
455  d_vector m_neworig;
456  d_vector m_newadd;
457  double m_newjacob[3][3];
458  double m_damping;
459 };
460 
462 static int VRPN_CALLBACK handle_forcefield_change_message(void *userdata, vrpn_HANDLERPARAM p)
463 {
464  vrpn_Tracker_NovintFalcon *dev = (vrpn_Tracker_NovintFalcon *)userdata;
465  dev->update_forcefield_effect(p);
466  return 0;
467 }
468 
470 class vrpn_NovintFalcon_ForceObjects {
471 public:
472  boost::ptr_vector<ForceFieldEffect> m_FFEffects;
473 
474 protected:
475  d_vector m_curforce; //< collected force value
476  d_vector m_curpos; //< position for force calculation
477  d_vector m_curvel; //< velocity for force calculation
478 
479 public:
481  vrpn_NovintFalcon_ForceObjects() {
482  m_curforce.assign(0.0);
483  m_curpos.assign(0.0);
484  };
486  ~vrpn_NovintFalcon_ForceObjects() {};
487 public:
489  d_vector getObjForce(vrpn_float64 *pos, vrpn_float64 *vel) {
490  int i;
491 
492  for (i=0; i<3; ++i) {
493  m_curforce[i]=0.0;
494  m_curpos[i]=pos[i];
495  m_curvel[i]=vel[i];
496  }
497 
498  // force field objects
499  int nobj = m_FFEffects.size();
500  for (i=0; i<nobj; ++i) {
501  m_curforce = m_curforce + m_FFEffects[i].calcForce (m_curpos);
502  }
503  return m_curforce;
504  };
505 };
506 
508 vrpn_Tracker_NovintFalcon::vrpn_Tracker_NovintFalcon(const char *name,
509  vrpn_Connection *c,
510  const int devidx,
511  const char *grip,
512  const char *kine,
513  const char *damp)
514  : vrpn_Tracker(name, c), vrpn_Button_Filter(name, c),
515  vrpn_ForceDevice(name, c), m_dev(NULL), m_obj(NULL), m_update_rate(1000.0), m_damp(0.9)
516 {
517  m_devflags=vrpn_NovintFalcon_Device::MASK_DEVICEIDX & devidx;
518  if (grip != NULL) {
519  if (0 == strcmp(grip,"4-button")) {
520  m_devflags |= vrpn_NovintFalcon_Device::GRIP_FOURBUTTON;
522  } else {
523  fprintf(stderr, "WARNING: Unknown grip for Novint Falcon #%d: %s \n", devidx, grip);
524  m_devflags = -1;
525  return;
526  }
527  }
528 
529  if (kine != NULL) {
530  if (0 == strcmp(kine,"stamper")) {
531  m_devflags |= vrpn_NovintFalcon_Device::KINE_STAMPER;
532  } else {
533  fprintf(stderr, "WARNING: Unknown kinematic model for Novint Falcon #%d: %s \n", devidx, kine);
534  m_devflags = -1;
535  return;
536  }
537  }
538 
539  if (damp != NULL) {
540  vrpn_float64 val= atof(damp);
541  if (val >= 1.0 && val <= 10000.0) {
542  m_damp = 1.0 - 1.0/val;
543  } else {
544  fprintf(stderr, "WARNING: Ignoring illegal force effect damping factor: %g \n", val);
545  }
546  }
547  clear_values();
548 
549  if (register_autodeleted_handler(forcefield_message_id,
550  handle_forcefield_change_message, this, vrpn_ForceDevice::d_sender_id)) {
551  fprintf(stderr,"vrpn_Tracker_NovintFalcon:can't register force handler\n");
552  return;
553  }
554  vrpn_gettimeofday(&m_timestamp, NULL);
556 }
557 
558 void vrpn_Tracker_NovintFalcon::clear_values()
559 {
560  // nothing to do
561  if (m_devflags < 0) return;
562 
563  int i;
564  for (i=0; i <vrpn_Button::num_buttons; i++)
566 
567  if (m_obj) delete m_obj;
568  m_obj = new vrpn_NovintFalcon_ForceObjects;
569 
570  // add dummy effect object
571  ForceFieldEffect *ffe = new ForceFieldEffect;
572  ffe->setDamping(m_damp);
573  ffe->stop();
574  m_obj->m_FFEffects.push_back(ffe);
575 }
576 
577 vrpn_Tracker_NovintFalcon::~vrpn_Tracker_NovintFalcon()
578 {
579  if (m_dev)
580  delete m_dev;
581  if (m_obj)
582  delete m_obj;
583 }
584 
585 void vrpn_Tracker_NovintFalcon::reset()
586 {
587 
588  // nothing to do
589  if (m_devflags < 0) return;
590 
591  int ret, i;
592  clear_values();
593 
594  fprintf(stderr, "Resetting the NovintFalcon #%d\n",
595  vrpn_NovintFalcon_Device::MASK_DEVICEIDX & m_devflags);
596 
597  if (m_dev)
598  delete m_dev;
599 
600  m_dev = new vrpn_NovintFalcon_Device(m_devflags);
601  if (!m_dev) {
602 #ifdef VERBOSE
603  fprintf(stderr, "Device constructor failed!\n");
604 #endif
605  status = vrpn_TRACKER_FAIL;
606  return;
607  }
608 
609  if (!m_dev->init()) {
610 #ifdef VERBOSE
611  fprintf(stderr, "Device init failed!\n");
612 #endif
613  status = vrpn_TRACKER_FAIL;
614  return;
615  }
616 
617  fprintf(stderr, "Reset Completed.\n");
618  status = vrpn_TRACKER_SYNCING; // We're trying for a new reading
619 }
620 
621 int vrpn_Tracker_NovintFalcon::get_report(void)
622 {
623  if (!m_dev)
624  return 0;
625 
626  if (status == vrpn_TRACKER_SYNCING) {
627  if (m_dev->get_status(pos, vel, d_quat, vel_quat, &vel_quat_dt, buttons)) {
628  // if all buttons are pressed. we force a reset.
629  int i,j;
630  j=0;
631  for (i=0; i < num_buttons; i++)
632  j += buttons[i];
633  // all buttons pressed
634  if (j == num_buttons) {
635  status = vrpn_TRACKER_FAIL;
636  return 0;
637  }
638  } else {
639  status = vrpn_TRACKER_FAIL;
640  return 0;
641  }
642  }
643  status = vrpn_TRACKER_SYNCING;
644 
645 #ifdef VERBOSE2
646  print_latest_report();
647 #endif
648 
649  return 1;
650 }
651 
652 void vrpn_Tracker_NovintFalcon::send_report(void)
653 {
654  if (d_connection) {
655  char msgbuf[1000];
656  int len = vrpn_Tracker::encode_to(msgbuf);
657  if (d_connection->pack_message(len, m_timestamp, position_m_id, d_sender_id, msgbuf,
659  }
660  len = vrpn_Tracker::encode_vel_to(msgbuf);
661  if (d_connection->pack_message(len, m_timestamp, velocity_m_id, d_sender_id, msgbuf,
663  }
664  }
665 }
666 
667 void vrpn_Tracker_NovintFalcon::handle_forces(void)
668 {
669  if (!m_dev) return;
670  if (!m_obj) return;
671 
672  // we have just updated our published position and can use that
673  d_vector force= m_obj->getObjForce(pos,vel);
674  m_dev->set_force(force);
675 }
676 
677 
678 int vrpn_Tracker_NovintFalcon::update_forcefield_effect(vrpn_HANDLERPARAM p)
679 {
680  if (!m_obj) return 1;
681 
682  vrpn_float32 center[3];
683  vrpn_float32 force[3];
684  vrpn_float32 jacobian[3][3];
685  vrpn_float32 radius;
686 
687  decode_forcefield(p.buffer, p.payload_len, center, force, jacobian, &radius);
688  // XXX: only one force field effect. sufficient for VMD.
689  // we have just updated our published position and can use that
690  m_obj->m_FFEffects[0].start();
691  m_obj->m_FFEffects[0].setForce(center, force, jacobian, radius);
692  return 0;
693 }
694 
695 
696 void vrpn_Tracker_NovintFalcon::mainloop()
697 {
698  struct timeval current_time;
699  server_mainloop();
700 
701  // no need to report more often than we can poll the device
702  vrpn_gettimeofday(&current_time, NULL);
703  if ( timediff(current_time, m_timestamp) >= 1000000.0/m_update_rate) {
704 
705  // Update the time
706  m_timestamp.tv_sec = current_time.tv_sec;
707  m_timestamp.tv_usec = current_time.tv_usec;
708  switch(status)
709  {
713  if (get_report()) {
714  send_report();
716  handle_forces();
717  }
718  break;
720  reset();
721  break;
722 
723  case vrpn_TRACKER_FAIL:
724  fprintf(stderr, "NovintFalcon #%d failed, trying to reset (Try power cycle if more than 4 attempts made)\n",
725  vrpn_NovintFalcon_Device::MASK_DEVICEIDX & m_devflags);
726  status = vrpn_TRACKER_RESETTING;
727  break;
728 
729  default:
730  fprintf(stderr, "NovintFalcon #%d , unknown status message: %d)\n",
731  vrpn_NovintFalcon_Device::MASK_DEVICEIDX & m_devflags, status);
732  break;
733  }
734  }
735 }
736 
737 #endif
vrpn_BaseClassUnique::register_autodeleted_handler
int register_autodeleted_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
Registers a handler with the connection, and remembers to delete at destruction.
Definition: vrpn_BaseClass.C:503
vrpn_Tracker
Definition: vrpn_Tracker.h:49
vrpn_Button::report_changes
virtual void report_changes(void)
Definition: vrpn_Button.C:422
vrpn_Tracker::encode_to
virtual int encode_to(char *buf)
Definition: vrpn_Tracker.C:533
vrpn_Tracker::encode_vel_to
virtual int encode_vel_to(char *buf)
Definition: vrpn_Tracker.C:558
vrpn_HANDLERPARAM::payload_len
vrpn_int32 payload_len
Definition: vrpn_Connection.h:48
vrpn_Button::num_buttons
vrpn_int32 num_buttons
Definition: vrpn_Button.h:47
vrpn_CONNECTION_LOW_LATENCY
const vrpn_uint32 vrpn_CONNECTION_LOW_LATENCY
Definition: vrpn_Connection.h:122
vrpn_Button::buttons
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:44
vrpn_HANDLERPARAM::buffer
const char * buffer
Definition: vrpn_Connection.h:49
vrpn_HANDLERPARAM
This structure is what is passed to a vrpn_Connection message callback.
Definition: vrpn_Connection.h:44
vrpn_TRACKER_PARTIAL
const int vrpn_TRACKER_PARTIAL
Definition: vrpn_Tracker.h:38
vrpn_BaseClassUnique::d_sender_id
vrpn_int32 d_sender_id
Sender ID registered with the connection.
Definition: vrpn_BaseClass.h:228
vrpn_ForceDevice
Definition: vrpn_ForceDevice.h:39
vrpn_Connection
Generic connection class not specific to the transport mechanism.
Definition: vrpn_Connection.h:510
vrpn_TRACKER_FAIL
const int vrpn_TRACKER_FAIL
Definition: vrpn_Tracker.h:40
vrpn_TRACKER_RESETTING
const int vrpn_TRACKER_RESETTING
Definition: vrpn_Tracker.h:39
vrpn_gettimeofday
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
vrpn_Tracker::status
int status
Definition: vrpn_Tracker.h:129
vrpn_Button::lastbuttons
unsigned char lastbuttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:45
vrpn_TRACKER_SYNCING
const int vrpn_TRACKER_SYNCING
Definition: vrpn_Tracker.h:35
VRPN_CALLBACK
#define VRPN_CALLBACK
Definition: vrpn_Configure.h:647
vrpn_TRACKER_AWAITING_STATION
const int vrpn_TRACKER_AWAITING_STATION
Definition: vrpn_Tracker.h:36
vrpn_Tracker_NovintFalcon.h
vrpn_Button_Filter
All button servers should derive from this class, which provides the ability to turn any of the butto...
Definition: vrpn_Button.h:65