vrpn 07.35
Virtual Reality Peripheral Network
Loading...
Searching...
No Matches
vrpn_Tracker.C
Go to the documentation of this file.
1#include <ctype.h> // for isspace
2#include <stdio.h> // for fprintf, stderr, NULL, etc
3#include <string.h> // for memcpy, strlen, strncmp, etc
4
5// NOTE: a vrpn tracker must call user callbacks with tracker data (pos and
6// ori info) which represent the transformation xfSourceFromSensor.
7// This means that the pos info is the position of the origin of
8// the sensor coord sys in the source coord sys space, and the
9// quat represents the orientation of the sensor relative to the
10// source space (ie, its value rotates the source's axes so that
11// they coincide with the sensor's)
12
13// Include vrpn_Shared.h _first_ to avoid conflicts with sys/time.h
14// and unistd.h
15#include "vrpn_Shared.h" // for timeval, vrpn_buffer, etc
16
17#ifdef _WIN32
18#ifndef _WIN32_WCE
19#include <io.h>
20#endif
21#endif
22
23#include "vrpn_RedundantTransmission.h" // for vrpn_RedundantTransmission
24#include "vrpn_Tracker.h"
25#include "quat.h"
26
27#if defined(VRPN_USE_LIBUSB_1_0)
28#include <libusb.h> // for libusb_close, etc
29#endif
30
31#ifndef VRPN_CLIENT_ONLY
32#include "vrpn_Serial.h" // for vrpn_close_commport, etc
33#endif
34
35static const char *default_tracker_cfg_file_name = "vrpn_Tracker.cfg";
36// this is used unless we pass in a path & file name into the vrpn_TRACKER
37// constructor
38
39#define vrpn_ser_tkr_MAX_TIME_INTERVAL \
40 (2000000) // max time between reports (usec)
41
42//#define VERBOSE
43// #define READ_HISTOGRAM
44
46 const char *tracker_cfg_file_name)
47 : vrpn_BaseClass(name, c)
48 , unit2sensor(NULL)
49 , unit2sensor_quat(NULL)
50 , num_unit2sensors(0)
51{
52 FILE *config_file;
54
55 // Set the current time to zero, just to have something there
56 timestamp.tv_sec = 0;
57 timestamp.tv_usec = 0;
58
59 // Set the watchdog time to zero, which will disable it unless it is used
60 watchdog_timestamp.tv_sec = 0;
61 watchdog_timestamp.tv_usec = 0;
62
63 // Set the sensor to 0 just to have something in there.
64 d_sensor = 0;
65
66 // Set the position to the origin and the orientation to identity
67 // just to have something there in case nobody fills them in later
68 pos[0] = pos[1] = pos[2] = 0.0;
69 d_quat[0] = d_quat[1] = d_quat[2] = 0.0;
70 d_quat[3] = 1.0;
71
72 // Set the velocity to zero and the orientation to identity
73 // just to have something there in case nobody fills them in later
74 vel[0] = vel[1] = vel[2] = 0.0;
75 vel_quat[0] = vel_quat[1] = vel_quat[2] = 0.0;
76 vel_quat[3] = 1.0;
77 vel_quat_dt = 1;
78
79 // Set the acceleration to zero and the orientation to identity
80 // just to have something there in case nobody fills them in later
81 acc[0] = acc[1] = acc[2] = 0.0;
82 acc_quat[0] = acc_quat[1] = acc_quat[2] = 0.0;
83 acc_quat[3] = 1.0;
84 acc_quat_dt = 1;
85
86#ifdef DESKTOP_PHANTOM_DEFAULTS
87 // Defaults for Desktop Phantom.
88 tracker2room[0] = tracker2room[1] = 0.0;
89 tracker2room[2] = -0.28;
90#else
91 // Set the room to tracker and sensor to unit transforms to identity
92 tracker2room[0] = tracker2room[1] = tracker2room[2] = 0.0;
93#endif
95 tracker2room_quat[3] = 1.0;
96
97 num_sensors = 1;
98
99#ifdef DESKTOP_PHANTOM_DEFAULTS
100 // Defaults for Desktop Phantom.
101 workspace_min[0] = workspace_min[1] = -0.2;
102 workspace_min[2] = -0.1;
103 workspace_max[0] = workspace_max[1] = workspace_max[2] = 0.2;
104#else
105 workspace_min[0] = workspace_min[1] = workspace_min[2] = -0.5;
106 workspace_max[0] = workspace_max[1] = workspace_max[2] = 0.5;
107#endif
108 // replace defaults with values from tracker config file
109 // if it exists
110 if (tracker_cfg_file_name == NULL) { // the default argument value
111 tracker_cfg_file_name = default_tracker_cfg_file_name;
112 }
113 if ((config_file = fopen(tracker_cfg_file_name, "r")) == NULL) {
114 // Can't find the config file
115 // Complain only if we are using the a non-default config file
116 // (Since most people don't use any config file at all,
117 // and would be confused to see an error about not being
118 // able to open the default config file)
119 if (tracker_cfg_file_name != default_tracker_cfg_file_name) {
120 fprintf(stderr, "vrpn_Tracker: Can't find config file %s\n",
121 tracker_cfg_file_name);
122 }
123 }
124 else if (read_config_file(config_file, name)) {
125 fprintf(
126 stderr,
127 "vrpn_Tracker: Found config file %s, but cannot read info for %s\n",
128 tracker_cfg_file_name, name);
129 fclose(config_file);
130 }
131 else { // no problems
132 fprintf(stderr, "vrpn_Tracker: Read room and sensor info from %s\n",
133 tracker_cfg_file_name);
134 fclose(config_file);
135 }
136}
137
139{
140 // Register this tracker device and the needed message types
141 if (d_connection) {
143 d_connection->register_message_type("vrpn_Tracker Pos_Quat");
145 d_connection->register_message_type("vrpn_Tracker Velocity");
146 accel_m_id =
147 d_connection->register_message_type("vrpn_Tracker Acceleration");
149 d_connection->register_message_type("vrpn_Tracker To_Room");
151 d_connection->register_message_type("vrpn_Tracker Unit_To_Sensor");
153 "vrpn_Tracker Request_Tracker_To_Room");
155 "vrpn_Tracker Request_Unit_To_Sensor");
157 d_connection->register_message_type("vrpn_Tracker Workspace");
159 "vrpn_Tracker Request_Tracker_Workspace");
161 d_connection->register_message_type("vrpn_Tracker set_update_rate");
163 d_connection->register_message_type("vrpn_Tracker Reset_Origin");
164 }
165 return 0;
166}
167
168// virtual
169// Delete all of the unit2sensor position and quaternion entries.
171{
172 if (unit2sensor != NULL) {
173 try {
174 delete[] unit2sensor;
175 } catch (...) {
176 fprintf(stderr, "vrpn_Tracker::~vrpn_Tracker(): delete failed\n");
177 return;
178 }
179 }
180 if (unit2sensor_quat != NULL) {
181 try {
182 delete[] unit2sensor_quat;
183 } catch (...) {
184 fprintf(stderr, "vrpn_Tracker::~vrpn_Tracker(): delete failed\n");
185 return;
186 }
187 }
189}
190
191// Make sure we have enough unit2sensor elements in the array.
192// Returns false if we run out of memory, true otherwise.
194{
195 unsigned i;
196 ++num; // Just to make sure we don't fall prey to off-by-one indexing
197 // errors.
198 if (num > num_unit2sensors) {
199 // Make sure we allocate in large chunks, rather than one at a time.
200 if (num < 2 * num_unit2sensors) {
201 num = 2 * num_unit2sensors;
202 }
203
204 // Allocate new space for the two lists.
205 vrpn_Tracker_Pos *newlist;
206 try { newlist = new vrpn_Tracker_Pos[num]; }
207 catch (...) { return false; }
208 vrpn_Tracker_Quat *newqlist;
209 try { newqlist = new vrpn_Tracker_Quat[num]; }
210 catch (...) { return false; }
211
212 // Copy all of the existing elements.
213 for (i = 0; i < num_unit2sensors; i++) {
214 memcpy(newlist[i], unit2sensor[i], sizeof(vrpn_Tracker_Pos));
215 memcpy(newqlist[i], unit2sensor_quat[i], sizeof(vrpn_Tracker_Quat));
216 }
217
218 // Initialize all of the new elements
219 for (i = num_unit2sensors; i < num; i++) {
220 newlist[i][0] = newlist[i][1] = newlist[i][2] = 0.0;
221 newqlist[i][0] = 0.0;
222 newqlist[i][1] = 0.0;
223 newqlist[i][2] = 0.0;
224 newqlist[i][3] = 1.0;
225 }
226
227 // Switch the new lists in for the old, and delete the old.
228 if (unit2sensor != NULL) {
229 try {
230 delete[] unit2sensor;
231 } catch (...) {
232 fprintf(stderr, "vrpn_Tracker::ensure_enough_unit2sensors(): delete failed\n");
233 return false;
234 }
235 }
236 if (unit2sensor_quat != NULL) {
237 try {
238 delete[] unit2sensor_quat;
239 } catch (...) {
240 fprintf(stderr, "vrpn_Tracker::ensure_enough_unit2sensors(): delete failed\n");
241 return false;
242 }
243 }
244 unit2sensor = newlist;
245 unit2sensor_quat = newqlist;
246 num_unit2sensors = num;
247 }
248 return true;
249}
250
251int vrpn_Tracker::read_config_file(FILE *config_file, const char *tracker_name)
252{
253
254 char line[512]; // line read from input file
255 vrpn_int32 num_sens;
256 vrpn_int32 which_sensor;
257 float f[14];
258 int i, j;
259
260 // Read lines from the file until we run out
261 while (fgets(line, sizeof(line), config_file) != NULL) {
262 // Make sure the line wasn't too long
263 if (strlen(line) >= sizeof(line) - 1) {
264 fprintf(stderr, "Line too long in config file: %s\n", line);
265 return -1;
266 }
267 // find tracker name in file
268 if ((!(strncmp(line, tracker_name, strlen(tracker_name)))) &&
269 (isspace(line[strlen(tracker_name)]))) {
270 // get the tracker2room xform and the workspace volume
271 if (fgets(line, sizeof(line), config_file) == NULL) break;
272 if (sscanf(line, "%f%f%f", &f[0], &f[1], &f[2]) != 3) break;
273 if (fgets(line, sizeof(line), config_file) == NULL) break;
274 if (sscanf(line, "%f%f%f%f", &f[3], &f[4], &f[5], &f[6]) != 4)
275 break;
276 if (fgets(line, sizeof(line), config_file) == NULL) break;
277 if (sscanf(line, "%f%f%f%f%f%f", &f[7], &f[8], &f[9], &f[10],
278 &f[11], &f[12]) != 6)
279 break;
280
281 for (i = 0; i < 3; i++) {
282 tracker2room[i] = f[i];
283 workspace_min[i] = f[i + 7];
284 workspace_max[i] = f[i + 10];
285 }
286 for (i = 0; i < 4; i++)
287 tracker2room_quat[i] = f[i + 3];
288 // get the number of sensors
289 if (fgets(line, sizeof(line), config_file) == NULL) break;
290 if (sscanf(line, "%d", &num_sens) != 1) break;
291 if (!ensure_enough_unit2sensors(num_sens + 1)) {
292 fprintf(stderr, "Out of memory\n");
293 return -1;
294 }
295 for (i = 0; i < num_sens; i++) {
296 // get which sensor this xform is for
297 if (fgets(line, sizeof(line), config_file) == NULL) break;
298 if (sscanf(line, "%d", &which_sensor) != 1) break;
299 if (!ensure_enough_unit2sensors(which_sensor + 1)) {
300 fprintf(stderr, "Out of memory\n");
301 return -1;
302 }
303 // get the sensor to unit xform
304 if (fgets(line, sizeof(line), config_file) == NULL) break;
305 if (sscanf(line, "%f%f%f", &f[0], &f[1], &f[2]) != 3) break;
306 if (fgets(line, sizeof(line), config_file) == NULL) break;
307 if (sscanf(line, "%f%f%f%f", &f[3], &f[4], &f[5], &f[6]) != 4)
308 break;
309 for (j = 0; j < 3; j++) {
310 unit2sensor[which_sensor][j] = f[j];
311 }
312 for (j = 0; j < 4; j++) {
313 unit2sensor_quat[which_sensor][j] = f[j + 3];
314 }
315 }
316 num_sensors = num_sens;
317 return 0; // success
318 }
319 }
320 fprintf(stderr, "Error reading or %s not found in config file\n",
321 tracker_name);
322 return -1;
323}
324
326{
327 printf("----------------------------------------------------\n");
328 printf("Sensor :%d\n", d_sensor);
329 printf("Timestamp :%ld:%ld\n", timestamp.tv_sec,
330 static_cast<long>(timestamp.tv_usec));
331 printf("Framecount:%d\n", frame_count);
332 printf("Pos :%lf, %lf, %lf\n", pos[0], pos[1], pos[2]);
333 printf("Quat :%lf, %lf, %lf, %lf\n", d_quat[0], d_quat[1], d_quat[2],
334 d_quat[3]);
335}
336
338{
339 if (d_connection) {
341 this, d_sender_id)) {
342 fprintf(stderr, "vrpn_Tracker:can't register t2r handler\n");
343 return -1;
344 }
346 this, d_sender_id)) {
347 fprintf(stderr, "vrpn_Tracker:can't register u2s handler\n");
348 return -1;
349 }
352 d_sender_id)) {
353 fprintf(stderr, "vrpn_Tracker: "
354 "Can't register workspace handler\n");
355 return -1;
356 }
357 }
358 else {
359 return -1;
360 }
361 return 0;
362}
363
364// put copies of vector and quat into arrays passed in
365void vrpn_Tracker::get_local_t2r(vrpn_float64 *vec, vrpn_float64 *quat)
366{
367 int i;
368 for (i = 0; i < 3; i++)
369 vec[i] = tracker2room[i];
370 for (i = 0; i < 4; i++)
371 quat[i] = tracker2room_quat[i];
372}
373
374// put copies of vector and quat into arrays passed in
375void vrpn_Tracker::get_local_u2s(vrpn_int32 sensor, vrpn_float64 *vec,
376 vrpn_float64 *quat)
377{
378 ensure_enough_unit2sensors(sensor + 1);
379 int i;
380 for (i = 0; i < 3; i++)
381 vec[i] = unit2sensor[sensor][i];
382 for (i = 0; i < 4; i++)
383 quat[i] = unit2sensor_quat[sensor][i];
384}
385
387{
388 struct timeval current_time;
389 char msgbuf[1000];
390 vrpn_int32 len;
391 vrpn_Tracker *me = (vrpn_Tracker *)userdata; // == this normally
392
393 p = p; // Keep the compiler from complaining
394
395 vrpn_gettimeofday(&current_time, NULL);
396 me->timestamp.tv_sec = current_time.tv_sec;
397 me->timestamp.tv_usec = current_time.tv_usec;
398
399 // our t2r transform was read in by the constructor
400
401 // send t2r transform
402 if (me->d_connection) {
403 len = me->encode_tracker2room_to(msgbuf);
404 if (me->d_connection->pack_message(
405 len, me->timestamp, me->tracker2room_m_id, me->d_sender_id,
406 msgbuf, vrpn_CONNECTION_RELIABLE)) {
407 fprintf(stderr, "vrpn_Tracker: cannot write t2r message\n");
408 }
409 }
410 return 0;
411}
412
414{
415 struct timeval current_time;
416 char msgbuf[1000];
417 vrpn_int32 len;
418 vrpn_int32 i;
420
421 p = p; // Keep the compiler from complaining
422
423 vrpn_gettimeofday(&current_time, NULL);
424 me->timestamp.tv_sec = current_time.tv_sec;
425 me->timestamp.tv_usec = current_time.tv_usec;
426
427 // our u2s transforms were read in by the constructor
428
429 if (me->d_connection) {
431 for (i = 0; i < me->num_sensors; i++) {
432 me->d_sensor = i;
433 // send u2s transform
434 len = me->encode_unit2sensor_to(msgbuf);
435 if (me->d_connection->pack_message(
436 len, me->timestamp, me->unit2sensor_m_id, me->d_sender_id,
437 msgbuf, vrpn_CONNECTION_RELIABLE)) {
438 fprintf(stderr, "vrpn_Tracker: cannot write u2s message\n");
439 }
440 }
441 }
442 return 0;
443}
444
446{
447 struct timeval current_time;
448 char msgbuf[1000];
449 vrpn_int32 len;
451
452 p = p; // Keep the compiler from complaining
453
454 vrpn_gettimeofday(&current_time, NULL);
455 me->timestamp.tv_sec = current_time.tv_sec;
456 me->timestamp.tv_usec = current_time.tv_usec;
457
458 // our workspace was read in by the constructor
459
460 if (me->d_connection) {
461 len = me->encode_workspace_to(msgbuf);
462 if (me->d_connection->pack_message(len, me->timestamp,
464 msgbuf, vrpn_CONNECTION_RELIABLE)) {
465 fprintf(stderr, "vrpn_Tracker: cannot write workspace message\n");
466 }
467 }
468 return 0;
469}
470
478{
479 char *bufptr = buf;
480 int buflen = 1000;
481 int i;
482
483 // Encode the position part of the transformation.
484 for (i = 0; i < 3; i++) {
485 vrpn_buffer(&bufptr, &buflen, tracker2room[i]);
486 }
487
488 // Encode the quaternion part of the transformation.
489 for (i = 0; i < 4; i++) {
490 vrpn_buffer(&bufptr, &buflen, tracker2room_quat[i]);
491 }
492
493 // Return the number of characters sent.
494 return 1000 - buflen;
495}
496
507{
508 char *bufptr = buf;
509 int buflen = 1000;
510 int i;
511
512 // Encode the sensor number, then put a filler in32 to re-align
513 // to the 64-bit boundary.
514 vrpn_buffer(&bufptr, &buflen, d_sensor);
515 vrpn_buffer(&bufptr, &buflen, (vrpn_int32)(0));
516
517 // Encode the position part of the transformation.
518 for (i = 0; i < 3; i++) {
519 vrpn_buffer(&bufptr, &buflen, unit2sensor[d_sensor][i]);
520 }
521
522 // Encode the quaternion part of the transformation.
523 for (i = 0; i < 4; i++) {
524 vrpn_buffer(&bufptr, &buflen, unit2sensor_quat[d_sensor][i]);
525 }
526
527 // Return the number of characters sent.
528 return 1000 - buflen;
529}
530
532{
533 char *bufptr = buf;
534 int buflen = 1000;
535
536 vrpn_buffer(&bufptr, &buflen, workspace_min[0]);
537 vrpn_buffer(&bufptr, &buflen, workspace_min[1]);
538 vrpn_buffer(&bufptr, &buflen, workspace_min[2]);
539
540 vrpn_buffer(&bufptr, &buflen, workspace_max[0]);
541 vrpn_buffer(&bufptr, &buflen, workspace_max[1]);
542 vrpn_buffer(&bufptr, &buflen, workspace_max[2]);
543
544 return 1000 - buflen;
545}
546
547// NOTE: you need to be sure that if you are sending vrpn_float64 then
548// the entire array needs to remain aligned to 8 byte boundaries
549// (malloced data and static arrays are automatically alloced in
550// this way). Assumes that there is enough room to store the
551// entire message. Returns the number of characters sent.
553{
554 char *bufptr = buf;
555 int buflen = 1000;
556
557 // Message includes: long sensor, long scrap, vrpn_float64 pos[3],
558 // vrpn_float64 quat[4]
559 // Byte order of each needs to be reversed to match network standard
560
561 vrpn_buffer(&bufptr, &buflen, d_sensor);
562 vrpn_buffer(&bufptr, &buflen,
563 d_sensor); // This is just to take up space to align
564
565 vrpn_buffer(&bufptr, &buflen, pos[0]);
566 vrpn_buffer(&bufptr, &buflen, pos[1]);
567 vrpn_buffer(&bufptr, &buflen, pos[2]);
568
569 vrpn_buffer(&bufptr, &buflen, d_quat[0]);
570 vrpn_buffer(&bufptr, &buflen, d_quat[1]);
571 vrpn_buffer(&bufptr, &buflen, d_quat[2]);
572 vrpn_buffer(&bufptr, &buflen, d_quat[3]);
573
574 return 1000 - buflen;
575}
576
578{
579 char *bufptr = buf;
580 int buflen = 1000;
581
582 // Message includes: long unitNum, vrpn_float64 vel[3], vrpn_float64
583 // vel_quat[4]
584 // Byte order of each needs to be reversed to match network standard
585
586 vrpn_buffer(&bufptr, &buflen, d_sensor);
587 vrpn_buffer(&bufptr, &buflen,
588 d_sensor); // This is just to take up space to align
589
590 vrpn_buffer(&bufptr, &buflen, vel[0]);
591 vrpn_buffer(&bufptr, &buflen, vel[1]);
592 vrpn_buffer(&bufptr, &buflen, vel[2]);
593
594 vrpn_buffer(&bufptr, &buflen, vel_quat[0]);
595 vrpn_buffer(&bufptr, &buflen, vel_quat[1]);
596 vrpn_buffer(&bufptr, &buflen, vel_quat[2]);
597 vrpn_buffer(&bufptr, &buflen, vel_quat[3]);
598
599 vrpn_buffer(&bufptr, &buflen, vel_quat_dt);
600
601 return 1000 - buflen;
602}
603
605{
606 char *bufptr = buf;
607 int buflen = 1000;
608
609 // Message includes: long unitNum, vrpn_float64 acc[3], vrpn_float64
610 // acc_quat[4]
611 // Byte order of each needs to be reversed to match network standard
612
613 vrpn_buffer(&bufptr, &buflen, d_sensor);
614 vrpn_buffer(&bufptr, &buflen,
615 d_sensor); // This is just to take up space to align
616
617 vrpn_buffer(&bufptr, &buflen, acc[0]);
618 vrpn_buffer(&bufptr, &buflen, acc[1]);
619 vrpn_buffer(&bufptr, &buflen, acc[2]);
620
621 vrpn_buffer(&bufptr, &buflen, acc_quat[0]);
622 vrpn_buffer(&bufptr, &buflen, acc_quat[1]);
623 vrpn_buffer(&bufptr, &buflen, acc_quat[2]);
624 vrpn_buffer(&bufptr, &buflen, acc_quat[3]);
625
626 vrpn_buffer(&bufptr, &buflen, acc_quat_dt);
627
628 return 1000 - buflen;
629}
630
632 vrpn_int32 sensors, vrpn_float64 Hz)
633 : vrpn_Tracker(name, c)
634 , update_rate(Hz)
635 , d_redundancy(NULL)
636{
637 num_sensors = sensors;
639 // Nothing left to do
640}
641
643{
644 struct timeval current_time;
645 char msgbuf[1000];
646 vrpn_int32 i, len;
647
648 // Call the generic server mainloop routine, since this is a server
650
651 // See if its time to generate a new report
652 vrpn_gettimeofday(&current_time, NULL);
653 if (vrpn_TimevalDuration(current_time, timestamp) >=
654 1000000.0 / update_rate) {
655
656 // Update the time
657 timestamp.tv_sec = current_time.tv_sec;
658 timestamp.tv_usec = current_time.tv_usec;
659
660 // Send messages for all sensors if we have a connection
661 if (d_redundancy) {
662 for (i = 0; i < num_sensors; i++) {
663 d_sensor = i;
664
665 // Pack position report
666 len = encode_to(msgbuf);
668 d_sender_id, msgbuf,
670 fprintf(stderr,
671 "NULL tracker: can't write message: tossing\n");
672 }
673
674 // Pack velocity report
675 len = encode_vel_to(msgbuf);
677 d_sender_id, msgbuf,
679 fprintf(stderr,
680 "NULL tracker: can't write message: tossing\n");
681 }
682
683 // Pack acceleration report
684 len = encode_acc_to(msgbuf);
686 d_sender_id, msgbuf,
688 fprintf(stderr,
689 "NULL tracker: can't write message: tossing\n");
690 }
691 }
692 }
693 else if (d_connection) {
694 for (i = 0; i < num_sensors; i++) {
695 d_sensor = i;
696
697 // Pack position report
698 len = encode_to(msgbuf);
700 d_sender_id, msgbuf,
702 fprintf(stderr,
703 "NULL tracker: can't write message: tossing\n");
704 }
705
706 // Pack velocity report
707 len = encode_vel_to(msgbuf);
709 d_sender_id, msgbuf,
711 fprintf(stderr,
712 "NULL tracker: can't write message: tossing\n");
713 }
714
715 // Pack acceleration report
716 len = encode_acc_to(msgbuf);
718 d_sender_id, msgbuf,
720 fprintf(stderr,
721 "NULL tracker: can't write message: tossing\n");
722 }
723 }
724 }
725 }
726}
727
729{
730 d_redundancy = t;
731}
732
734 vrpn_int32 sensors, vrpn_float64 Hz,
735 vrpn_float64 axisX, vrpn_float64 axisY,
736 vrpn_float64 axisZ, vrpn_float64 spinRateHz)
737 : vrpn_Tracker(name, c)
738 , update_rate(Hz)
739 , x(axisX)
740 , y(axisY)
741 , z(axisZ)
742 , spin_rate_Hz(spinRateHz)
743{
744 num_sensors = sensors;
746
747 // Get the time we started
748 vrpn_gettimeofday(&start, NULL);
749
750 // If the spin rate is set to be negative, then invert the
751 // axis and set it to positive.
752 if (spin_rate_Hz < 0) {
753 spin_rate_Hz *= -1;
754 x *= -1;
755 y *= -1;
756 z *= -1;
757 }
758
759 // Set the pose velocity to match the axis we're spinning
760 // about and our rate of spin. It will remain the same
761 // throughout the run. Make the dt such that we spin by
762 // less than half a rotation each delta, so we don't alias
763 // our speed. Scale rotation by this dt.
764 double dt;
765 if (spin_rate_Hz == 0) {
766 dt = 1.0;
767 } else {
768 dt = 0.9 * (0.5/spin_rate_Hz);
769 }
770 q_from_axis_angle(vel_quat, x, y, z, dt * spin_rate_Hz * 2*Q_PI);
771 vel_quat_dt = dt;
772}
773
775{
776 struct timeval current_time;
777 char msgbuf[1000];
778 vrpn_int32 i, len;
779
780 // Call the generic server mainloop routine, since this is a server
782
783 // See if its time to generate a new report
784 vrpn_gettimeofday(&current_time, NULL);
785 if (vrpn_TimevalDurationSeconds(current_time, timestamp) >=
786 1.0 / update_rate) {
787
788 // Update the time
789 timestamp.tv_sec = current_time.tv_sec;
790 timestamp.tv_usec = current_time.tv_usec;
791
792 // Figure out our new pose.
793 double duration = vrpn_TimevalDurationSeconds(current_time, start);
794 q_from_axis_angle(d_quat, x, y, z, duration * spin_rate_Hz * 2*Q_PI);
795
796 // Send messages for all sensors if we have a connection
797 if (d_connection) {
798 for (i = 0; i < num_sensors; i++) {
799 d_sensor = i;
800
801 // Pack position report
802 len = encode_to(msgbuf);
804 d_sender_id, msgbuf,
806 fprintf(stderr,
807 "NULL tracker: can't write message: tossing\n");
808 }
809
810 // Pack velocity report
811 len = encode_vel_to(msgbuf);
813 d_sender_id, msgbuf,
815 fprintf(stderr,
816 "NULL tracker: can't write message: tossing\n");
817 }
818
819 // Pack acceleration report
820 len = encode_acc_to(msgbuf);
822 d_sender_id, msgbuf,
824 fprintf(stderr,
825 "NULL tracker: can't write message: tossing\n");
826 }
827 }
828 }
829 }
830}
831
833 vrpn_int32 sensors)
834 : vrpn_Tracker(name, c)
835{
836 num_sensors = sensors;
838 // Nothing left to do
839}
840
842{
843 // Call the generic server mainloop routine, since this is a server
845}
846
847int vrpn_Tracker_Server::report_pose(const int sensor, const struct timeval t,
848 const vrpn_float64 position[3],
849 const vrpn_float64 quaternion[4],
850 const vrpn_uint32 class_of_service)
851{
852 char msgbuf[1000];
853 vrpn_int32 len;
854
855 // Update the time
856 timestamp.tv_sec = t.tv_sec;
857 timestamp.tv_usec = t.tv_usec;
858
859 // Send messages for all sensors if we have a connection
860 if (sensor >= num_sensors) {
861 send_text_message("Sensor number too high", timestamp, vrpn_TEXT_ERROR);
862 return -1;
863 }
864 else if (!d_connection) {
866 return -1;
867 }
868 else {
869 d_sensor = sensor;
870
871 // Pack position report
872 memcpy(pos, position, sizeof(pos));
873 memcpy(d_quat, quaternion, sizeof(d_quat));
874 len = encode_to(msgbuf);
876 d_sender_id, msgbuf, class_of_service)) {
877 fprintf(stderr,
878 "vrpn_Tracker_Server: can't write message: tossing\n");
879 return -1;
880 }
881 }
882 return 0;
883}
884
886 const int sensor, const struct timeval t, const vrpn_float64 position[3],
887 const vrpn_float64 quaternion[4], const vrpn_float64 interval,
888 const vrpn_uint32 class_of_service)
889{
890 char msgbuf[1000];
891 vrpn_int32 len;
892
893 // Update the time
894 timestamp.tv_sec = t.tv_sec;
895 timestamp.tv_usec = t.tv_usec;
896
897 // Send messages for all sensors if we have a connection
898 if (sensor >= num_sensors) {
899 send_text_message("Sensor number too high", timestamp, vrpn_TEXT_ERROR);
900 return -1;
901 }
902 else if (!d_connection) {
904 return -1;
905 }
906 else {
907 d_sensor = sensor;
908
909 // Pack velocity report
910 memcpy(vel, position, sizeof(pos));
911 memcpy(vel_quat, quaternion, sizeof(d_quat));
912 vel_quat_dt = interval;
913 len = encode_vel_to(msgbuf);
915 d_sender_id, msgbuf, class_of_service)) {
916 fprintf(stderr,
917 "vrpn_Tracker_Server: can't write message: tossing\n");
918 return -1;
919 }
920 }
921
922 return 0;
923}
924
926 const int sensor, const struct timeval t, const vrpn_float64 position[3],
927 const vrpn_float64 quaternion[4], const vrpn_float64 interval,
928 const vrpn_uint32 class_of_service)
929{
930 char msgbuf[1000];
931 vrpn_int32 len;
932
933 // Update the time
934 timestamp.tv_sec = t.tv_sec;
935 timestamp.tv_usec = t.tv_usec;
936
937 // Send messages for all sensors if we have a connection
938 if (sensor >= num_sensors) {
939 send_text_message("Sensor number too high", timestamp, vrpn_TEXT_ERROR);
940 return -1;
941 }
942 else if (!d_connection) {
944 return -1;
945 }
946 else {
947 d_sensor = sensor;
948
949 // Pack acceleration report
950 memcpy(acc, position, sizeof(pos));
951 memcpy(acc_quat, quaternion, sizeof(d_quat));
952 acc_quat_dt = interval;
953 len = encode_acc_to(msgbuf);
955 msgbuf, class_of_service)) {
956 fprintf(stderr,
957 "vrpn_Tracker_Server: can't write message: tossing\n");
958 return -1;
959 }
960 }
961
962 return 0;
963}
964
965#ifndef VRPN_CLIENT_ONLY
967 const char *port, long baud)
968 : vrpn_Tracker(name, c)
969 , serial_fd(-1)
970{
972 // Find out the port name and baud rate
973 if (port == NULL) {
974 fprintf(stderr, "vrpn_Tracker_Serial: NULL port name\n");
976 return;
977 } else {
978 vrpn_strcpy(portname, port);
979 }
980 baudrate = baud;
981
982 // Open the serial port we're going to use
984 fprintf(stderr, "vrpn_Tracker_Serial: Cannot Open serial port\n");
986 }
987
988 // Reset the tracker and find out what time it is
991}
992
994{
995 if (serial_fd >= 0) {
997 serial_fd = -1;
998 }
999}
1000
1002{
1003 // Send the message on the connection
1004 if (d_connection) {
1005 char msgbuf[1000];
1006 int len = encode_to(msgbuf);
1008 d_sender_id, msgbuf,
1010 fprintf(stderr, "Tracker: cannot write message: tossing\n");
1011 }
1012 }
1013 else {
1014 fprintf(stderr, "Tracker: No valid connection\n");
1015 }
1016}
1017
1024{
1026
1027 switch (status) {
1030 case vrpn_TRACKER_PARTIAL: {
1031 // It turns out to be important to get the report before checking
1032 // to see if it has been too long since the last report. This is
1033 // because there is the possibility that some other device running
1034 // in the same server may have taken a long time on its last pass
1035 // through mainloop(). Trackers that are resetting do this. When
1036 // this happens, you can get an infinite loop -- where one tracker
1037 // resets and causes the other to timeout, and then it returns the
1038 // favor. By checking for the report here, we reset the timestamp
1039 // if there is a report ready (ie, if THIS device is still operating).
1040
1041 while (get_report()) { // While we get reports, continue to send them.
1042 send_report();
1043 };
1044
1045 struct timeval current_time;
1046 vrpn_gettimeofday(&current_time, NULL);
1047 int time_lapsed; /* The time since the last report */
1048
1049 // Watchdog timestamp is implemented by Polhemus Liberty driver.
1050 // XXX All trackers should be modified to use this, or it to not.
1051 // If the watchdog timestamp is zero, use the last timestamp to check.
1052 if (watchdog_timestamp.tv_sec == 0) {
1053 time_lapsed = vrpn_TimevalDuration(current_time, timestamp);
1054 }
1055 else { // The watchdog_timestamp is being used
1056 time_lapsed =
1058 }
1059
1060 if (time_lapsed > vrpn_ser_tkr_MAX_TIME_INTERVAL) {
1061 char errmsg[1024];
1062 sprintf(errmsg, "Tracker failed to read... current_time=%ld:%ld, "
1063 "timestamp=%ld:%ld\n",
1064 current_time.tv_sec,
1065 static_cast<long>(current_time.tv_usec), timestamp.tv_sec,
1066 static_cast<long>(timestamp.tv_usec));
1067 send_text_message(errmsg, current_time, vrpn_TEXT_ERROR);
1069 }
1070 } break;
1071
1073 reset();
1074 break;
1075
1076 case vrpn_TRACKER_FAIL:
1077 send_text_message("Tracker failed, trying to reset (Try power cycle if "
1078 "more than 4 attempts made)",
1080 if (serial_fd >= 0) {
1082 serial_fd = -1;
1083 }
1085 fprintf(
1086 stderr,
1087 "vrpn_Tracker_Serial::mainloop(): Cannot Open serial port\n");
1089 }
1091 break;
1092 }
1093}
1094
1095#if defined(VRPN_USE_LIBUSB_1_0)
1096
1098 vrpn_uint16 vendor, vrpn_uint16 product,
1099 long baud)
1100 : vrpn_Tracker(name, c)
1101 , _device_handle(NULL)
1102 , _vendor(vendor)
1103 , _product(product)
1104 , _baudrate(baud)
1105{
1106 // Register handlers
1108
1109 // Initialize libusb
1110 if (libusb_init(&_context) != 0) {
1111 fprintf(stderr, "vrpn_Tracker_USB: can't init LibUSB\n");
1113 return;
1114 }
1115 // libusb_set_debug (_context, 3);
1116
1117 // Open and claim an usb device with the expected vendor and product ID.
1118 if ((_device_handle = libusb_open_device_with_vid_pid(_context, _vendor,
1119 _product)) == NULL) {
1120 fprintf(stderr, "vrpn_Tracker_USB: can't find any Polhemus High Speed "
1121 "Liberty Latus devices\n");
1122 fprintf(stderr,
1123 " (Did you remember to run as root?)\n");
1125 return;
1126 }
1127
1128 if (libusb_claim_interface(_device_handle, 0) != 0) {
1129 fprintf(stderr,
1130 "vrpn_Tracker_USB: can't claim interface for this device\n");
1131 fprintf(stderr,
1132 " (Did you remember to run as root?)\n");
1133 libusb_close(_device_handle);
1134 _device_handle = NULL;
1135 libusb_exit(_context);
1136 _context = NULL;
1138 return;
1139 }
1140
1141 // Reset the tracker and find out what time it is
1144}
1145
1147{
1148 if (_device_handle) {
1149 libusb_close(_device_handle);
1150 _device_handle = NULL;
1151 }
1152 if (_context) {
1153 libusb_exit(_context);
1154 _context = NULL;
1155 }
1156}
1157
1159{
1160 // Send the message on the connection
1161 if (d_connection) {
1162 char msgbuf[1000];
1163 int len = encode_to(msgbuf);
1165 d_sender_id, msgbuf,
1167 fprintf(stderr, "Tracker: cannot write message: tossing\n");
1168 }
1169 }
1170 else {
1171 fprintf(stderr, "Tracker: No valid connection\n");
1172 }
1173}
1174
1181{
1183
1184 switch (status) {
1186 case vrpn_TRACKER_PARTIAL: {
1187 // It turns out to be important to get the report before checking
1188 // to see if it has been too long since the last report. This is
1189 // because there is the possibility that some other device running
1190 // in the same server may have taken a long time on its last pass
1191 // through mainloop(). Trackers that are resetting do this. When
1192 // this happens, you can get an infinite loop -- where one tracker
1193 // resets and causes the other to timeout, and then it returns the
1194 // favor. By checking for the report here, we reset the timestamp
1195 // if there is a report ready (ie, if THIS device is still operating).
1196
1197 get_report();
1198
1199 // Ready for another report
1201
1202 // Save reception time
1203 struct timeval current_time;
1204 vrpn_gettimeofday(&current_time, NULL);
1205 int time_lapsed; // The time since the last report
1206
1207 // Watchdog timestamp is implemented by Polhemus Liberty driver.
1208 // XXX All trackers should be modified to use this, or it to not.
1209 // If the watchdog timestamp is zero, use the last timestamp to check.
1210 if (watchdog_timestamp.tv_sec == 0) {
1211 time_lapsed = vrpn_TimevalDuration(current_time, timestamp);
1212 }
1213 else { // The watchdog_timestamp is being used
1214 time_lapsed =
1216 }
1217
1218 if (time_lapsed > vrpn_ser_tkr_MAX_TIME_INTERVAL) {
1219 char errmsg[1024];
1220 sprintf(errmsg, "Tracker failed to read... current_time=%ld:%ld, "
1221 "timestamp=%ld:%ld\n",
1222 current_time.tv_sec,
1223 static_cast<long>(current_time.tv_usec), timestamp.tv_sec,
1224 static_cast<long>(timestamp.tv_usec));
1225 send_text_message(errmsg, current_time, vrpn_TEXT_ERROR);
1227 }
1228
1229 } break;
1230
1232 reset();
1233 break;
1234
1235 case vrpn_TRACKER_FAIL:
1236 send_text_message("Tracker failed, trying to reset (Try power cycle if "
1237 "more than 4 attempts made)",
1239 // Reset the device handle and then attempt to connect to a device.
1240 if (_device_handle) {
1241 libusb_close(_device_handle);
1242 _device_handle = NULL;
1243 }
1244 if ((_device_handle = libusb_open_device_with_vid_pid(
1245 _context, _vendor, _product)) == NULL) {
1246 fprintf(stderr, "vrpn_Tracker_USB::mainloop(): can't find any "
1247 "Polhemus High Speed Liberty Latus devices\n");
1249 break;
1250 }
1251
1252 if (libusb_claim_interface(_device_handle, 0) != 0) {
1253 fprintf(stderr, "vrpn_Tracker_USB::mainloop(): can't claim "
1254 "interface for this device\n");
1255 libusb_close(_device_handle);
1256 _device_handle = NULL;
1258 break;
1259 }
1260
1262 break;
1263 }
1264}
1265
1266// End of LIBUSB
1267#endif
1268
1269#endif // VRPN_CLIENT_ONLY
1270
1272 : vrpn_Tracker(name, cn)
1273 , sensor_callbacks(NULL)
1274 , num_sensor_callbacks(0)
1275{
1276 // Make sure that we have a valid connection
1277 if (d_connection == NULL) {
1278 fprintf(stderr, "vrpn_Tracker_Remote: No connection\n");
1279 return;
1280 }
1281
1282 // Register a handler for the position change callback from this device.
1284 d_sender_id)) {
1285 fprintf(stderr,
1286 "vrpn_Tracker_Remote: can't register position handler\n");
1287 d_connection = NULL;
1288 }
1289
1290 // Register a handler for the velocity change callback from this device.
1292 this, d_sender_id)) {
1293 fprintf(stderr,
1294 "vrpn_Tracker_Remote: can't register velocity handler\n");
1295 d_connection = NULL;
1296 }
1297
1298 // Register a handler for the acceleration change callback.
1300 this, d_sender_id)) {
1301 fprintf(stderr,
1302 "vrpn_Tracker_Remote: can't register acceleration handler\n");
1303 d_connection = NULL;
1304 }
1305
1306 // Register a handler for the room to tracker xform change callback
1309 d_sender_id)) {
1310 fprintf(stderr,
1311 "vrpn_Tracker_Remote: can't register tracker2room handler\n");
1312 d_connection = NULL;
1313 }
1314
1315 // Register a handler for the sensor to unit xform change callback
1318 d_sender_id)) {
1319 fprintf(stderr,
1320 "vrpn_Tracker_Remote: can't register unit2sensor handler\n");
1321 d_connection = NULL;
1322 }
1323
1324 // Register a handler for the workspace change callback
1327 d_sender_id)) {
1328 fprintf(stderr,
1329 "vrpn_Tracker_Remote: can't register workspace handler\n");
1330 d_connection = NULL;
1331 }
1332
1333 // Find out what time it is and put this into the timestamp
1335}
1336
1337// The remote tracker has to un-register its handlers when it
1338// is destroyed to avoid seg faults (this is taken care of by
1339// using autodeleted handlers above). It should also remove all
1340// remaining user-registered callbacks to free up memory.
1341
1343{
1344 if (sensor_callbacks != NULL) {
1345 try {
1346 delete[] sensor_callbacks;
1347 } catch (...) {
1348 fprintf(stderr, "vrpn_Tracker_Remote::~vrpn_Tracker_Remote(): delete failed\n");
1349 return;
1350 }
1351 }
1353}
1354
1355// Make sure we have enough sensor_callback elements in the array.
1356// Returns false if we run out of memory, true otherwise.
1358{
1359 unsigned i;
1360 ++num; // Just to make sure we don't fall prey to off-by-one indexing
1361 // errors.
1362 if (num > num_sensor_callbacks) {
1363 // Make sure we allocate in large chunks, rather than one at a time.
1364 if (num < 2 * num_sensor_callbacks) {
1365 num = 2 * num_sensor_callbacks;
1366 }
1367
1368 // Allocate new space for the list.
1370 try { newlist = new vrpn_Tracker_Sensor_Callbacks[num]; }
1371 catch (...) {
1372 return false;
1373 }
1374
1375 // Copy all of the existing elements.
1376 for (i = 0; i < num_sensor_callbacks; i++) {
1377 newlist[i] = sensor_callbacks[i];
1378 }
1379
1380 // The new elements will be empty by default, nothing to do here.
1381
1382 // Switch the new list in for the old, and delete the old.
1383 if (sensor_callbacks != NULL) {
1384 try {
1385 delete[] sensor_callbacks;
1386 } catch (...) {
1387 fprintf(stderr, "vrpn_Tracker_Remote::ensure_enough_sensor_callbacks(): delete failed\n");
1388 return false;
1389 }
1390 }
1391 sensor_callbacks = newlist;
1393 }
1394 return true;
1395}
1396
1398{
1399 char *msgbuf = NULL;
1400 vrpn_int32 len = 0; // no payload
1401 struct timeval current_time;
1402
1403 vrpn_gettimeofday(&current_time, NULL);
1404 timestamp.tv_sec = current_time.tv_sec;
1405 timestamp.tv_usec = current_time.tv_usec;
1406
1407 if (d_connection) {
1409 d_sender_id, msgbuf,
1411 fprintf(stderr, "vrpn_Tracker_Remote: cannot request t2r xform\n");
1412 return -1;
1413 }
1414 }
1415 return 0;
1416}
1417
1419{
1420 char *msgbuf = NULL;
1421 vrpn_int32 len = 0; // no payload
1422 struct timeval current_time;
1423
1424 vrpn_gettimeofday(&current_time, NULL);
1425 timestamp.tv_sec = current_time.tv_sec;
1426 timestamp.tv_usec = current_time.tv_usec;
1427
1428 if (d_connection) {
1430 d_sender_id, msgbuf,
1432 fprintf(stderr, "vrpn_Tracker_Remote: cannot request u2s xform\n");
1433 return -1;
1434 }
1435 }
1436 return 0;
1437}
1438
1440{
1441 char *msgbuf = NULL;
1442 vrpn_int32 len = 0; // no payload
1443 struct timeval current_time;
1444
1445 vrpn_gettimeofday(&current_time, NULL);
1446 timestamp.tv_sec = current_time.tv_sec;
1447 timestamp.tv_usec = current_time.tv_usec;
1448
1449 if (d_connection) {
1451 d_sender_id, msgbuf,
1453 fprintf(stderr, "vrpn_Tracker_Remote: cannot request workspace\n");
1454 return -1;
1455 }
1456 }
1457
1458 return 0;
1459}
1460
1461int vrpn_Tracker_Remote::set_update_rate(vrpn_float64 samplesPerSecond)
1462{
1463 char msgbuf[sizeof(vrpn_float64)];
1464 char *bufptr = msgbuf;
1465 vrpn_int32 len = sizeof(vrpn_float64);
1466 struct timeval now;
1467
1468 vrpn_int32 buflen = len;
1469 vrpn_buffer(&bufptr, &buflen, samplesPerSecond);
1470
1471 vrpn_gettimeofday(&now, NULL);
1472 timestamp.tv_sec = now.tv_sec;
1473 timestamp.tv_usec = now.tv_usec;
1474
1475 if (d_connection) {
1477 d_sender_id, msgbuf,
1479 fprintf(stderr, "vrpn_Tracker_Remote::set_update_rate: "
1480 "Cannot send message.\n");
1481 return -1;
1482 }
1483 }
1484 return 0;
1485}
1486
1488{
1489 struct timeval current_time;
1490 vrpn_gettimeofday(&current_time, NULL);
1491 timestamp.tv_sec = current_time.tv_sec;
1492 timestamp.tv_usec = current_time.tv_usec;
1493
1494 if (d_connection) {
1496 d_sender_id, NULL,
1498 fprintf(stderr,
1499 "vrpn_Tracker_Remote: cannot write message: tossing\n");
1500 }
1501 }
1502 return 0;
1503}
1504
1506{
1507 if (d_connection) {
1509 }
1511}
1512
1514 void *userdata, vrpn_TRACKERCHANGEHANDLER handler, vrpn_int32 whichSensor)
1515{
1516 if (whichSensor < vrpn_ALL_SENSORS) {
1517 fprintf(
1518 stderr,
1519 "vrpn_Tracker_Remote::register_change_handler: bad sensor index\n");
1520 return -1;
1521 }
1522 // Ensure that the handler is non-NULL
1523 if (handler == NULL) {
1524 fprintf(stderr,
1525 "vrpn_Tracker_Remote::register_change_handler: NULL handler\n");
1526 return -1;
1527 }
1528
1529 // If this is the ALL_SENSORS value, put it on the all list; otherwise,
1530 // put it into the normal list.
1531 if (whichSensor == vrpn_ALL_SENSORS) {
1533 handler);
1534 }
1535 else if (ensure_enough_sensor_callbacks(whichSensor)) {
1537 handler);
1538 }
1539 else {
1540 fprintf(
1541 stderr,
1542 "vrpn_Tracker_Remote::register_change_handler: Out of memory\n");
1543 return -1;
1544 }
1545}
1546
1548 void *userdata, vrpn_TRACKERVELCHANGEHANDLER handler,
1549 vrpn_int32 whichSensor)
1550{
1551 if (whichSensor < vrpn_ALL_SENSORS) {
1552 fprintf(
1553 stderr,
1554 "vrpn_Tracker_Remote::register_change_handler: bad sensor index\n");
1555 return -1;
1556 }
1557 // Ensure that the handler is non-NULL
1558 if (handler == NULL) {
1559 fprintf(stderr,
1560 "vrpn_Tracker_Remote::register_change_handler: NULL handler\n");
1561 return -1;
1562 }
1563
1564 // If this is the ALL_SENSORS value, put it on the all list; otherwise,
1565 // put it into the normal list.
1566 if (whichSensor == vrpn_ALL_SENSORS) {
1568 handler);
1569 }
1570 else if (ensure_enough_sensor_callbacks(whichSensor)) {
1571 return sensor_callbacks[whichSensor].d_velchange.register_handler(
1572 userdata, handler);
1573 }
1574 else {
1575 fprintf(
1576 stderr,
1577 "vrpn_Tracker_Remote::register_change_handler: Out of memory\n");
1578 return -1;
1579 }
1580}
1581
1583 void *userdata, vrpn_TRACKERACCCHANGEHANDLER handler,
1584 vrpn_int32 whichSensor)
1585{
1586 if (whichSensor < vrpn_ALL_SENSORS) {
1587 fprintf(
1588 stderr,
1589 "vrpn_Tracker_Remote::register_change_handler: bad sensor index\n");
1590 return -1;
1591 }
1592
1593 // Ensure that the handler is non-NULL
1594 if (handler == NULL) {
1595 fprintf(stderr,
1596 "vrpn_Tracker_Remote::register_change_handler: NULL handler\n");
1597 return -1;
1598 }
1599
1600 // If this is the ALL_SENSORS value, put it on the all list; otherwise,
1601 // put it into the normal list.
1602 if (whichSensor == vrpn_ALL_SENSORS) {
1604 handler);
1605 }
1606 else if (ensure_enough_sensor_callbacks(whichSensor)) {
1607 return sensor_callbacks[whichSensor].d_accchange.register_handler(
1608 userdata, handler);
1609 }
1610 else {
1611 fprintf(
1612 stderr,
1613 "vrpn_Tracker_Remote::register_change_handler: Out of memory\n");
1614 return -1;
1615 }
1616}
1617
1619 void *userdata, vrpn_TRACKERUNIT2SENSORCHANGEHANDLER handler,
1620 vrpn_int32 whichSensor)
1621{
1622 if (whichSensor < vrpn_ALL_SENSORS) {
1623 fprintf(
1624 stderr,
1625 "vrpn_Tracker_Remote::register_change_handler: bad sensor index\n");
1626 return -1;
1627 }
1628
1629 // Ensure that the handler is non-NULL
1630 if (handler == NULL) {
1631 fprintf(stderr, "%s%s", "vrpn_Tracker_Remote:",
1632 ":register_change_handler: NULL handler\n");
1633 return -1;
1634 }
1635
1636 // If this is the ALL_SENSORS value, put it on the all list; otherwise,
1637 // put it into the normal list.
1638 if (whichSensor == vrpn_ALL_SENSORS) {
1640 userdata, handler);
1641 }
1642 else if (ensure_enough_sensor_callbacks(whichSensor)) {
1643 return sensor_callbacks[whichSensor]
1645 }
1646 else {
1647 fprintf(
1648 stderr,
1649 "vrpn_Tracker_Remote::register_change_handler: Out of memory\n");
1650 return -1;
1651 }
1652}
1653
1655 void *userdata, vrpn_TRACKERCHANGEHANDLER handler, vrpn_int32 whichSensor)
1656{
1657 if (whichSensor < vrpn_ALL_SENSORS) {
1658 fprintf(stderr, "vrpn_Tracker_Remote::unregister_change_handler: bad "
1659 "sensor index\n");
1660 return -1;
1661 }
1662
1663 if (whichSensor == vrpn_ALL_SENSORS) {
1665 handler);
1666 }
1667 else if (ensure_enough_sensor_callbacks(whichSensor)) {
1668 return sensor_callbacks[whichSensor].d_change.unregister_handler(
1669 userdata, handler);
1670 }
1671 else {
1672 fprintf(
1673 stderr,
1674 "vrpn_Tracker_Remote::unregister_change_handler: Out of memory\n");
1675 return -1;
1676 }
1677}
1678
1680 void *userdata, vrpn_TRACKERVELCHANGEHANDLER handler,
1681 vrpn_int32 whichSensor)
1682{
1683 if (whichSensor < vrpn_ALL_SENSORS) {
1684 fprintf(stderr, "vrpn_Tracker_Remote::unregister_change_handler: bad "
1685 "sensor index\n");
1686 return -1;
1687 }
1688
1689 if (whichSensor == vrpn_ALL_SENSORS) {
1691 handler);
1692 }
1693 else if (ensure_enough_sensor_callbacks(whichSensor)) {
1695 userdata, handler);
1696 }
1697 else {
1698 fprintf(
1699 stderr,
1700 "vrpn_Tracker_Remote::unregister_change_handler: Out of memory\n");
1701 return -1;
1702 }
1703}
1704
1706 void *userdata, vrpn_TRACKERACCCHANGEHANDLER handler,
1707 vrpn_int32 whichSensor)
1708{
1709 if (whichSensor < vrpn_ALL_SENSORS) {
1710 fprintf(stderr, "vrpn_Tracker_Remote::unregister_change_handler: bad "
1711 "sensor index\n");
1712 return -1;
1713 }
1714
1715 if (whichSensor == vrpn_ALL_SENSORS) {
1717 handler);
1718 }
1719 else if (ensure_enough_sensor_callbacks(whichSensor)) {
1721 userdata, handler);
1722 }
1723 else {
1724 fprintf(
1725 stderr,
1726 "vrpn_Tracker_Remote::unregister_change_handler: Out of memory\n");
1727 return -1;
1728 }
1729}
1730
1732 void *userdata, vrpn_TRACKERUNIT2SENSORCHANGEHANDLER handler,
1733 vrpn_int32 whichSensor)
1734{
1735 if (whichSensor < vrpn_ALL_SENSORS) {
1736 fprintf(stderr, "vrpn_Tracker_Remote::unregister_change_handler: bad "
1737 "sensor index\n");
1738 return -1;
1739 }
1740
1741 if (whichSensor == vrpn_ALL_SENSORS) {
1743 userdata, handler);
1744 }
1745 else if (ensure_enough_sensor_callbacks(whichSensor)) {
1746 return sensor_callbacks[whichSensor]
1748 }
1749 else {
1750 fprintf(
1751 stderr,
1752 "vrpn_Tracker_Remote::unregister_change_handler: Out of memory\n");
1753 return -1;
1754 }
1755}
1756
1759{
1761 const char *params = (p.buffer);
1762 vrpn_int32 padding;
1763 vrpn_TRACKERCB tp;
1764 int i;
1765
1766 // Fill in the parameters to the tracker from the message
1767 if (p.payload_len != (8 * sizeof(vrpn_float64))) {
1768 fprintf(stderr, "vrpn_Tracker: change message payload error\n");
1769 fprintf(stderr, " (got %d, expected %lud)\n", p.payload_len,
1770 static_cast<unsigned long>(8 * sizeof(vrpn_float64)));
1771 return -1;
1772 }
1773 tp.msg_time = p.msg_time;
1774 vrpn_unbuffer(&params, &tp.sensor);
1775 vrpn_unbuffer(&params, &padding);
1776
1777 for (i = 0; i < 3; i++) {
1778 vrpn_unbuffer(&params, &tp.pos[i]);
1779 }
1780 for (i = 0; i < 4; i++) {
1781 vrpn_unbuffer(&params, &tp.quat[i]);
1782 }
1783
1784 // Go down the list of callbacks that have been registered.
1785 // Fill in the parameter and call each.
1787
1788 // Go down the list of callbacks that have been registered for this
1789 // particular sensor
1790 if (tp.sensor < 0) {
1791 fprintf(stderr, "vrpn_Tracker_Rem:pos sensor index is negative!\n");
1792 return -1;
1793 }
1794 else if (me->ensure_enough_sensor_callbacks(tp.sensor)) {
1796 }
1797 else {
1798 fprintf(stderr, "vrpn_Tracker_Rem:pos sensor index too large\n");
1799 return -1;
1800 }
1801 return 0;
1802}
1803
1806{
1808 const char *params = p.buffer;
1809 vrpn_int32 padding;
1811 int i;
1812
1813 // Fill in the parameters to the tracker from the message
1814 if (p.payload_len != (9 * sizeof(vrpn_float64))) {
1815 fprintf(stderr, "vrpn_Tracker: vel message payload error\n");
1816 fprintf(stderr, " (got %d, expected %lud)\n", p.payload_len,
1817 static_cast<unsigned long>(9 * sizeof(vrpn_float64)));
1818 return -1;
1819 }
1820 tp.msg_time = p.msg_time;
1821 vrpn_unbuffer(&params, &tp.sensor);
1822 vrpn_unbuffer(&params, &padding);
1823
1824 for (i = 0; i < 3; i++) {
1825 vrpn_unbuffer(&params, &tp.vel[i]);
1826 }
1827 for (i = 0; i < 4; i++) {
1828 vrpn_unbuffer(&params, &tp.vel_quat[i]);
1829 }
1830
1831 vrpn_unbuffer(&params, &tp.vel_quat_dt);
1832
1833 // Go down the list of callbacks that have been registered.
1834 // Fill in the parameter and call each.
1836
1837 // Go down the list of callbacks that have been registered for this
1838 // particular sensor
1841 }
1842 else {
1843 fprintf(stderr, "vrpn_Tracker_Rem:vel sensor index too large\n");
1844 return -1;
1845 }
1846 return 0;
1847}
1848
1851{
1853 const char *params = p.buffer;
1854 vrpn_int32 padding;
1856 int i;
1857
1858 // Fill in the parameters to the tracker from the message
1859 if (p.payload_len != (9 * sizeof(vrpn_float64))) {
1860 fprintf(stderr, "vrpn_Tracker: acc message payload error\n");
1861 fprintf(stderr, "(got %d, expected %lud)\n", p.payload_len,
1862 static_cast<unsigned long>(9 * sizeof(vrpn_float64)));
1863 return -1;
1864 }
1865 tp.msg_time = p.msg_time;
1866 vrpn_unbuffer(&params, &tp.sensor);
1867 vrpn_unbuffer(&params, &padding);
1868
1869 for (i = 0; i < 3; i++) {
1870 vrpn_unbuffer(&params, &tp.acc[i]);
1871 }
1872 for (i = 0; i < 4; i++) {
1873 vrpn_unbuffer(&params, &tp.acc_quat[i]);
1874 }
1875
1876 vrpn_unbuffer(&params, &tp.acc_quat_dt);
1877
1878 // Go down the list of callbacks that have been registered.
1879 // Fill in the parameter and call each.
1881
1882 // Go down the list of callbacks that have been registered for this
1883 // particular sensor
1886 }
1887 else {
1888 fprintf(stderr, "vrpn_Tracker_Rem:acc sensor index too large\n");
1889 return -1;
1890 }
1891 return 0;
1892}
1893
1896{
1898 const char *params = p.buffer;
1899 vrpn_int32 padding;
1901 int i;
1902
1903 // Fill in the parameters to the tracker from the message
1904 if (p.payload_len != (8 * sizeof(vrpn_float64))) {
1905 fprintf(stderr, "vrpn_Tracker: unit2sensor message payload");
1906 fprintf(stderr, " error\n(got %d, expected %lud)\n", p.payload_len,
1907 static_cast<unsigned long>(8 * sizeof(vrpn_float64)));
1908 return -1;
1909 }
1910 tp.msg_time = p.msg_time;
1911 vrpn_unbuffer(&params, &tp.sensor);
1912 vrpn_unbuffer(&params, &padding);
1913
1914 // Typecasting used to get the byte order correct on the vrpn_float64
1915 // that are coming from the other side.
1916 for (i = 0; i < 3; i++) {
1917 vrpn_unbuffer(&params, &tp.unit2sensor[i]);
1918 }
1919 for (i = 0; i < 4; i++) {
1920 vrpn_unbuffer(&params, &tp.unit2sensor_quat[i]);
1921 }
1922
1923 // Go down the list of callbacks that have been registered.
1924 // Fill in the parameter and call each.
1926
1927 // Go down the list of callbacks that have been registered for this
1928 // particular sensor
1931 }
1932 else {
1933 fprintf(stderr, "vrpn_Tracker_Rem:u2s sensor index too large\n");
1934 return -1;
1935 }
1936
1937 return 0;
1938}
1939
1942{
1944 const char *params = p.buffer;
1946 int i;
1947
1948 // Fill in the parameters to the tracker from the message
1949 if (p.payload_len != (7 * sizeof(vrpn_float64))) {
1950 fprintf(stderr, "vrpn_Tracker: tracker2room message payload");
1951 fprintf(stderr, " error\n(got %d, expected %lud)\n", p.payload_len,
1952 static_cast<unsigned long>(7 * sizeof(vrpn_float64)));
1953 return -1;
1954 }
1955 tp.msg_time = p.msg_time;
1956
1957 for (i = 0; i < 3; i++) {
1958 vrpn_unbuffer(&params, &tp.tracker2room[i]);
1959 }
1960 for (i = 0; i < 4; i++) {
1961 vrpn_unbuffer(&params, &tp.tracker2room_quat[i]);
1962 }
1963
1964 // Go down the list of callbacks that have been registered.
1965 // Fill in the parameter and call each.
1967
1968 return 0;
1969}
1970
1973{
1975 const char *params = p.buffer;
1977 int i;
1978
1979 // Fill in the parameters to the tracker from the message
1980 if (p.payload_len != (6 * sizeof(vrpn_float64))) {
1981 fprintf(stderr, "vrpn_Tracker: tracker2room message payload");
1982 fprintf(stderr, " error\n(got %d, expected %lud)\n", p.payload_len,
1983 static_cast<unsigned long>(6 * sizeof(vrpn_float64)));
1984 return -1;
1985 }
1986 tp.msg_time = p.msg_time;
1987
1988 for (i = 0; i < 3; i++) {
1989 vrpn_unbuffer(&params, &tp.workspace_min[i]);
1990 }
1991 for (i = 0; i < 3; i++) {
1992 vrpn_unbuffer(&params, &tp.workspace_max[i]);
1993 }
1994
1995 // Go down the list of callbacks that have been registered.
1996 // Fill in the parameter and call each.
1998
1999 return 0;
2000}
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.
vrpn_Connection * d_connection
Connection that this object talks to.
void client_mainloop(void)
Handles functions that all clients should provide in their mainloop() (warning of no server,...
vrpn_MESSAGEHANDLER handler
vrpn_int32 d_sender_id
Sender ID registered with the connection.
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
int send_text_message(const char *msg, struct timeval timestamp, vrpn_TEXT_SEVERITY type=vrpn_TEXT_NORMAL, vrpn_uint32 level=0)
Sends a NULL-terminated text message from the device d_sender_id.
Class from which all user-level (and other) classes that communicate with vrpn_Connections should der...
virtual int init(void)
Initialize things that the constructor can't. Returns 0 on success, -1 on failure.
int register_handler(void *userdata, HANDLER_TYPE handler)
Call this to add a handler to the list.
int unregister_handler(void *userdata, HANDLER_TYPE handler)
Call this to remove a handler from the list (if it exists)
void call_handlers(const CALLBACK_STRUCT &info)
This will pass the referenced parameter as a const to all the callbacks.
Generic connection class not specific to the transport mechanism.
virtual vrpn_int32 register_message_type(const char *name)
virtual int pack_message(vrpn_uint32 len, struct timeval time, vrpn_int32 type, vrpn_int32 sender, const char *buffer, vrpn_uint32 class_of_service)
Pack a message that will be sent the next time mainloop() is called. Turn off the RELIABLE flag if yo...
virtual int mainloop(const struct timeval *timeout=NULL)=0
Call each time through program main loop to handle receiving any incoming messages and sending any pa...
Helper class for vrpn_Connection that automates redundant transmission for unreliable (low-latency) m...
virtual int pack_message(vrpn_uint32 len, timeval time, vrpn_uint32 type, vrpn_uint32 sender, const char *buffer, vrpn_uint32 class_of_service, vrpn_int32 numRetransmissions=-1, timeval *transmissionInterval=NULL)
If !isEnabled(), does a normal pack_message(), but if isEnabled() ignores class_of_service and sends ...
vrpn_float64 update_rate
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
vrpn_RedundantTransmission * d_redundancy
vrpn_Tracker_NULL(const char *name, vrpn_Connection *c, vrpn_int32 sensors=1, vrpn_float64 Hz=1.0)
void setRedundantTransmission(vrpn_RedundantTransmission *)
vrpn_Tracker_Sensor_Callbacks * sensor_callbacks
unsigned num_sensor_callbacks
virtual int unregister_change_handler(void *userdata, vrpn_TRACKERCHANGEHANDLER handler, vrpn_int32 sensor=vrpn_ALL_SENSORS)
vrpn_Tracker_Sensor_Callbacks all_sensor_callbacks
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
int request_workspace(void)
bool ensure_enough_sensor_callbacks(unsigned num)
static int VRPN_CALLBACK handle_workspace_change_message(void *userdata, vrpn_HANDLERPARAM p)
static int VRPN_CALLBACK handle_vel_change_message(void *userdata, vrpn_HANDLERPARAM p)
static int VRPN_CALLBACK handle_change_message(void *userdata, vrpn_HANDLERPARAM p)
vrpn_Callback_List< vrpn_TRACKERWORKSPACECB > d_workspacechange_list
virtual int register_change_handler(void *userdata, vrpn_TRACKERCHANGEHANDLER handler, vrpn_int32 sensor=vrpn_ALL_SENSORS)
static int VRPN_CALLBACK handle_unit2sensor_change_message(void *userdata, vrpn_HANDLERPARAM p)
vrpn_Tracker_Remote(const char *name, vrpn_Connection *c=NULL)
virtual ~vrpn_Tracker_Remote(void)
static int VRPN_CALLBACK handle_tracker2room_change_message(void *userdata, vrpn_HANDLERPARAM p)
int request_u2s_xform(void)
vrpn_Callback_List< vrpn_TRACKERTRACKER2ROOMCB > d_tracker2roomchange_list
int request_t2r_xform(void)
static int VRPN_CALLBACK handle_acc_change_message(void *userdata, vrpn_HANDLERPARAM p)
int set_update_rate(vrpn_float64 samplesPerSecond)
vrpn_Callback_List< vrpn_TRACKERCB > d_change
vrpn_Callback_List< vrpn_TRACKERVELCB > d_velchange
vrpn_Callback_List< vrpn_TRACKERACCCB > d_accchange
vrpn_Callback_List< vrpn_TRACKERUNIT2SENSORCB > d_unit2sensorchange
char portname[VRPN_TRACKER_BUF_SIZE]
virtual void send_report(void)
virtual void reset(void)=0
Reset the tracker.
virtual void mainloop()
Uses the get_report, send_report, and reset routines to implement a server.
virtual ~vrpn_Tracker_Serial()
virtual int get_report(void)=0
Gets a report if one is available, returns 0 if not, 1 if complete report.
vrpn_Tracker_Serial(const char *name, vrpn_Connection *c, const char *port="/dev/ttyS1", long baud=38400)
virtual int report_pose_acceleration(const int sensor, const struct timeval t, const vrpn_float64 position[3], const vrpn_float64 quaternion[4], const vrpn_float64 interval, const vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY)
virtual void mainloop()
This function should be called each time through app mainloop.
vrpn_Tracker_Server(const char *name, vrpn_Connection *c, vrpn_int32 sensors=1)
virtual int report_pose(const int sensor, const struct timeval t, const vrpn_float64 position[3], const vrpn_float64 quaternion[4], const vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY)
These functions should be called to report changes in state, once per sensor.
virtual int report_pose_velocity(const int sensor, const struct timeval t, const vrpn_float64 position[3], const vrpn_float64 quaternion[4], const vrpn_float64 interval, const vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY)
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
vrpn_Tracker_Spin(const char *name, vrpn_Connection *c, vrpn_int32 sensors=1, vrpn_float64 reportRateHz=1.0, vrpn_float64 axisX=0, vrpn_float64 axisY=0, vrpn_float64 axisZ=1, vrpn_float64 spinRateHz=0.5)
vrpn_float64 update_rate
vrpn_float64 spin_rate_Hz
struct timeval start
vrpn_Tracker_USB(const char *name, vrpn_Connection *c, vrpn_uint16 vendor, vrpn_uint16 product, long baud=115200)
virtual ~vrpn_Tracker_USB()
virtual void reset(void)=0
Reset the tracker.
virtual void mainloop()
Uses the get_report, send_report, and reset routines to implement a server.
virtual void send_report(void)
struct libusb_device_handle * _device_handle
virtual int get_report(void)=0
Gets reports if some are available, returns 0 if not, 1 if complete report(s).
vrpn_uint16 _vendor
vrpn_uint16 _product
struct libusb_context * _context
vrpn_float64 acc_quat[4]
virtual int encode_to(char *buf)
int register_server_handlers(void)
vrpn_float64 workspace_max[3]
vrpn_float64 vel_quat[4]
vrpn_int32 request_t2r_m_id
vrpn_float64 d_quat[4]
vrpn_int32 reset_origin_m_id
static int VRPN_CALLBACK handle_t2r_request(void *userdata, vrpn_HANDLERPARAM p)
vrpn_int32 velocity_m_id
virtual int encode_acc_to(char *buf)
bool ensure_enough_unit2sensors(unsigned num)
static int VRPN_CALLBACK handle_u2s_request(void *userdata, vrpn_HANDLERPARAM p)
vrpn_float64 vel_quat_dt
vrpn_int32 request_workspace_m_id
vrpn_float64 vel[3]
vrpn_int32 update_rate_id
vrpn_Tracker(const char *name, vrpn_Connection *c=NULL, const char *tracker_cfg_file_name=NULL)
vrpn_float64 acc_quat_dt
vrpn_int32 accel_m_id
void get_local_u2s(vrpn_int32 sensor, vrpn_float64 *vec, vrpn_float64 *quat)
struct timeval watchdog_timestamp
vrpn_int32 workspace_m_id
void get_local_t2r(vrpn_float64 *vec, vrpn_float64 *quat)
virtual int encode_unit2sensor_to(char *buf)
Encodes the "Unit to Sensor" transformation into the buffer specified.
vrpn_int32 request_u2s_m_id
virtual int encode_workspace_to(char *buf)
virtual int encode_vel_to(char *buf)
vrpn_int32 d_sensor
virtual ~vrpn_Tracker(void)
virtual int encode_tracker2room_to(char *buf)
Encodes the "Tracker to Room" transformation into the buffer specified.
vrpn_float64 workspace_min[3]
vrpn_Tracker_Quat * unit2sensor_quat
vrpn_float64 pos[3]
vrpn_int32 num_sensors
void print_latest_report(void)
struct timeval timestamp
unsigned num_unit2sensors
int read_config_file(FILE *config_file, const char *tracker_name)
vrpn_int32 frame_count
vrpn_int32 unit2sensor_m_id
vrpn_Tracker_Pos * unit2sensor
vrpn_float64 tracker2room_quat[4]
vrpn_int32 tracker2room_m_id
virtual int register_types(void)
Register the types of messages this device sends/receives. Return 0 on success, -1 on fail.
vrpn_float64 acc[3]
vrpn_int32 position_m_id
static int VRPN_CALLBACK handle_workspace_request(void *userdata, vrpn_HANDLERPARAM p)
vrpn_float64 tracker2room[3]
This structure is what is passed to a vrpn_Connection message callback.
const char * buffer
struct timeval msg_time
vrpn_float64 acc[3]
vrpn_float64 acc_quat[4]
struct timeval msg_time
vrpn_float64 acc_quat_dt
struct timeval msg_time
vrpn_int32 sensor
vrpn_float64 quat[4]
vrpn_float64 pos[3]
vrpn_float64 tracker2room_quat[4]
vrpn_float64 tracker2room[3]
vrpn_float64 unit2sensor_quat[4]
vrpn_float64 unit2sensor[3]
vrpn_float64 vel[3]
vrpn_float64 vel_quat_dt
struct timeval msg_time
vrpn_float64 vel_quat[4]
vrpn_float64 workspace_min[3]
vrpn_float64 workspace_max[3]
struct timeval msg_time
@ vrpn_TEXT_ERROR
const vrpn_uint32 vrpn_CONNECTION_RELIABLE
Classes of service for messages, specify multiple by ORing them together Priority of satisfying these...
const vrpn_uint32 vrpn_CONNECTION_LOW_LATENCY
int vrpn_close_commport(int comm)
int vrpn_open_commport(const char *portname, long baud, int charsize, vrpn_SER_PARITY parity, bool rts_flow)
Open a serial port, given its name and baud rate.
Definition vrpn_Serial.C:54
vrpn_Serial: Pulls all the serial port routines into one file to make porting to new operating system...
VRPN_API int vrpn_unbuffer(const char **buffer, timeval *t)
Utility routine for taking a struct timeval from a buffer that was sent as a message.
unsigned long vrpn_TimevalDuration(struct timeval endT, struct timeval startT)
Return number of microseconds between startT and endT.
double vrpn_TimevalDurationSeconds(struct timeval endT, struct timeval startT)
Return the number of seconds between startT and endT as a floating-point value.
VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen, const timeval t)
Utility routine for placing a timeval struct into a buffer that is to be sent as a message.
void vrpn_strcpy(char(&to)[charCount], const char *pSrc)
Null-terminated-string copy function that both guarantees not to overrun the buffer and guarantees th...
#define vrpn_gettimeofday
Definition vrpn_Shared.h:99
#define vrpn_ser_tkr_MAX_TIME_INTERVAL
const int vrpn_TRACKER_FAIL
const int vrpn_ALL_SENSORS
const int vrpn_TRACKER_RESETTING
void(VRPN_CALLBACK * vrpn_TRACKERACCCHANGEHANDLER)(void *userdata, const vrpn_TRACKERACCCB info)
vrpn_float64 vrpn_Tracker_Quat[4]
const int vrpn_TRACKER_SYNCING
const int vrpn_TRACKER_PARTIAL
void(VRPN_CALLBACK * vrpn_TRACKERCHANGEHANDLER)(void *userdata, const vrpn_TRACKERCB info)
vrpn_float64 vrpn_Tracker_Pos[3]
void(VRPN_CALLBACK * vrpn_TRACKERVELCHANGEHANDLER)(void *userdata, const vrpn_TRACKERVELCB info)
const int vrpn_TRACKER_AWAITING_STATION
void(VRPN_CALLBACK * vrpn_TRACKERUNIT2SENSORCHANGEHANDLER)(void *userdata, const vrpn_TRACKERUNIT2SENSORCB info)