vrpn 07.36
Virtual Reality Peripheral Network
Loading...
Searching...
No Matches
vrpn_Tracker_PhaseSpace.C
Go to the documentation of this file.
1/*
2 PhaseSpace, Inc 2017
3 vrpn_Tracker_PhaseSpace.C
4
5 ChangeLog
6 =================
7 20170802
8 * fixed a bug where timestamp's microsecond field was same as seconds in Windows.
9
10 20170629
11 * added support non-fatal errors (i.e. license warnings)
12 * added server version query for newer cores that support it.
13 * changed indentation of some debugging output.
14
15 20170201
16 * removed some extraneous comments
17
18 20151008
19 * slave mode now uses cfg specs to assign sensors to markers and rigids.
20 Unassigned devices will still be assigned arbitrarily.
21
22 20150818
23 * Update to libowl2 API for X2e device support, removed support for Impulse
24 * removed stylus and button support
25 * removed maximum rigid and marker limitations
26 * vrpn.cfg: x,y, and z parameters for point sensors changed to single pos
27 parameter
28 * vrpn.cfg: k1,k2,k3,k4 parameters for rigid sensors changed to single init
29 parameter
30
31 */
33
34#include <errno.h>
35#include <math.h>
36
37#include <limits>
38#include <string>
39#include <sstream>
40#include <algorithm>
41#include <map>
42
43#define MM_TO_METERS (0.001)
44#define MSGBUFSIZE 1024
45
46#ifdef VRPN_INCLUDE_PHASESPACE
47
48//
49struct SensorInfo {
50 vrpn_int32 sensor_id; // vrpn sensor
51
52 int type; // owl tracker type
53 uint32_t tracker; // tracker_id
54 uint32_t id; // marker_id
55 std::string opt;
56
57 size_t search_hint;
58
59 SensorInfo()
60 {
61 type = -1;
62 tracker = 0;
63 id = 0;
64 opt = "";
65 search_hint = std::numeric_limits<uint32_t>::max();
66 }
67};
68
69
70//
72
73
74//
75bool operator<(const SensorInfo& a, const SensorInfo& b)
76{
77 if(a.type < b.type) return true;
78 if(a.type > b.type) return false;
79 return a.id < b.id;
80}
81
82//
83class vrpn_Tracker_PhaseSpace::SensorManager
84{
85protected:
86 Sensors _v;
87
88public:
89 void add(const SensorInfo& s)
90 {
91 _v.push_back(s);
92 std::sort(_v.begin(), _v.end());
93 }
94
95 const SensorInfo* get_by_sensor(int sensor_id)
96 {
97 for(size_t i = 0; i < _v.size(); i++)
98 if(_v[i].sensor_id == sensor_id) return &_v[i];
99 return NULL;
100 }
101
102 Sensors::iterator begin()
103 {
104 return _v.begin();
105 }
106
108 {
109 return _v.end();
110 }
111};
112
113
114// ctor
116 : vrpn_Tracker(name ,c),
117 vrpn_Button_Filter(name, c),
119 debug(false),
120 drop_frames(false),
121 smgr(NULL)
122{
123 // TODO fix
124 //num_buttons = vrpn_BUTTON_MAX_BUTTONS;
125 num_buttons = 0;
126
127 smgr = new SensorManager();
128
129 if(d_connection) {
130 // Register a handler for the update change callback
132 fprintf(stderr,"vrpn_Tracker: Can't register workspace handler\n");
133 }
134}
135
136
137// dtor
143
144
145//
147{
148 printf("connecting to OWL server at %s...\n", device.c_str());
149
150 std::string init_options = "event.markers=1 event.rigids=1";
151 if(options.length()) init_options += " " + options;
152
153 if(drop_frames) printf("drop_frames enabled\n");
154
155 // connect to Impulse server
156 if(context.open(device) <= 0)
157 {
158 fprintf(stderr, "owl connect error: %s\n", context.lastError().c_str());
159 return false;
160 }
161
162 if(debug)
163 {
164 std::string coreversion = context.property<std::string>("coreversion");
165 printf("[debug] server version: %s\n", coreversion.length() ? coreversion.c_str() : "unknown");
166
167 std::string apiversion = context.property<std::string>("apiversion");
168
169 printf("[debug] API version: %s\n", apiversion.length() ? apiversion.c_str() : "unknown");
170 }
171
172 if(debug) printf("[debug] initialization parameters: %s\n", init_options.c_str());
173 if(context.initialize(init_options) <= 0)
174 {
175 fprintf(stderr, "owl init error: %s\n", context.lastError().c_str());
176 return false;
177 }
178
179 if(options.find("timebase=") == std::string::npos) context.timeBase(1, 1000000);
180 if(options.find("scale=") == std::string::npos) context.scale(MM_TO_METERS);
181
182 if(context.lastError().length())
183 {
184 fprintf(stderr, "owl error: %s\n", context.lastError().c_str());
185 return false;
186 }
187
188 int slave = context.property<int>("slave");
189
190 if(slave) printf("slave mode enabled.\n");
191 else if(!create_trackers()) return false;
192
193 printf("owl initialized\n");
194 return true;
195}
196
197
198//
200{
201 if(debug) printf("[debug] creating trackers...\n");
202
203 // create trackers
204 int nr = 0;
205 int nm = 0;
207
208 // create rigid trackers
209 for(Sensors::iterator s = smgr->begin(); s != smgr->end(); s++)
210 {
211 if(s->type != OWL::Type::RIGID) continue;
212 nr++;
213 if(std::find(ti.begin(), ti.end(), s->tracker) != ti.end())
214 {
215 fprintf(stderr, "rigid tracker %d already defined\n", s->tracker);
216 continue;
217 }
218
219 printf("creating rigid tracker %d\n", s->tracker);
220 std::string type = "rigid";
221 std::stringstream name; name << type << nr;
222 if(debug) printf("[debug] type=%s id=%d name=%s options=\'%s\'\n", type.c_str(), s->tracker, name.str().c_str(), s->opt.c_str());
223
224 if(!context.createTracker(s->tracker, type, name.str(), s->opt))
225 {
226 fprintf(stderr, "tracker creation error: %s\n", context.lastError().c_str());
227 return false;
228 }
229 ti.push_back(s->tracker);
230 }
231
232 // create point trackers
233 for(Sensors::iterator s = smgr->begin(); s != smgr->end(); s++)
234 {
235 if(s->type != OWL::Type::MARKER) continue;
236 nm++;
237 if(std::find(ti.begin(), ti.end(), s->tracker) == ti.end())
238 {
239 printf("creating point tracker %d\n", s->tracker);
240 std::string type = "point";
241 std::stringstream name; name << type << nm;
242 ti.push_back(s->tracker);
243 context.createTracker(s->tracker, type, name.str());
244 }
245 if(!context.assignMarker(s->tracker, s->id, "", s->opt))
246 {
247 fprintf(stderr, "marker assignment error: %s\n", context.lastError().c_str());
248 return false;
249 }
250 if(debug) printf("[debug] id=%d tracker=%d options=\'%s\'\n", s->id, s->tracker, s->opt.c_str());
251 }
252
253 if(context.lastError().length())
254 {
255 fprintf(stderr, "tracker creation error: %s\n", context.lastError().c_str());
256 return false;
257 }
258
259 return true;
260}
261
262
263// This function should be called each time through the main loop
264// of the server code. It polls for data from the OWL server and
265// sends them if available.
267{
268 get_report();
270 return;
271}
272
273
274//
275std::string trim(char* line, int len)
276{
277 // cut off leading whitespace
278 int s, e;
279 for(s = 0; isspace(line[s]) && s < len; s++);
280 // cut off comments and trailing whitespace
281 e = s;
282 for(int i = s; line[i] && i < len; i++)
283 {
284 if(line[i] == '#') break;
285 if(!isspace(line[i])) e = i+1;
286 }
287 return std::string(line+s, e-s);
288}
289
290
291//
292bool read_int(const char* str, int &i)
293{
294 if(!str) return false;
295 errno = 0;
296 char* endptr = NULL;
297 i = strtol(str, &endptr, 10);
298 if(*endptr || errno) {
299 fprintf(stderr, "Error, expected an integer but got token: \"%s\"\n", str);
300 return false;
301 }
302 return true;
303}
304
305
306//
307bool read_uint(const char* str, uint32_t &i)
308{
309 if(!str) return false;
310 errno = 0;
311 char* endptr = NULL;
312 i = strtoul(str, &endptr, 10);
313 if(*endptr || errno) {
314 fprintf(stderr, "Error, expected an unsigned integer but got token: \"%s\"\n", str);
315 return false;
316 }
317 return true;
318}
319
320
321//
322bool read_bool(const char* str, bool &b)
323{
324 if(!str) return false;
325 std::string s(str);
326 if(s == "true") {
327 b = true;
328 return true;
329 } else if(s == "false") {
330 b = false;
331 return true;
332 }
333 int i = 0;
334 bool ret = read_int(str, i);
335 b = i ? true : false;
336 return ret;
337}
338
339
340//
341bool read_float(const char* str, float &f)
342{
343 if(!str) return false;
344 errno = 0;
345 char* endptr = NULL;
346 f = (float) strtod(str, &endptr);
347 if(*endptr || errno) {
348 fprintf(stderr, "Error, expected a float but got token: \"%s\"\n", str);
349 return false;
350 }
351 return true;
352}
353
354
355// TODO: Replace all of this junk with <regex> once it is standard in gcc
356class ConfigParser
357{
358protected:
359 struct Spec {
360 std::string key;
361 std::string type;
362 void* dest;
363 bool required;
364 };
365
366 std::map <std::string, std::string> keyvals;
367 std::stringstream _error;
368
369public:
370
371 std::string error()
372 {
373 return _error.str();
374 }
375
376 bool contains(const std::string &key)
377 {
378 return keyvals.find(key) != keyvals.end();
379 }
380
381 std::string join()
382 {
383 std::stringstream s;
384 for(std::map<std::string, std::string>::iterator i = keyvals.begin(); i != keyvals.end(); i++)
385 s << (i==keyvals.begin()?"":" ") << i->first << "=" << i->second;
386 return s.str();
387 }
388
389 //
390 bool parse(SensorInfo &si)
391 {
392 _error.str("");
393
394 std::string spec_type;
395 float x=std::numeric_limits<float>::quiet_NaN();
396 float y=std::numeric_limits<float>::quiet_NaN();
397 float z=std::numeric_limits<float>::quiet_NaN();
398
399 Spec spec_marker[] = {
400 { "led", "uint32_t", &si.id, true },
401 { "tracker", "uint32_t", &si.tracker, false },
402 { "x", "float", &x, false },
403 { "y", "float", &y, false },
404 { "z", "float", &z, false },
405 { "", "", NULL, false } // sentinel
406 };
407
408 Spec spec_rigid[] = {
409 { "tracker", "uint32_t", &si.tracker, true },
410 { "", "", NULL, false } // sentinel
411 };
412
413 if(pop_int("sensor", si.sensor_id))
414 {
415 _error << "required key 'sensor' not found";
416 return false;
417 }
418
419 if(pop("type", spec_type))
420 {
421 _error << "required key 'type' not found";
422 return false;
423 }
424
425 Spec* spec = NULL;
426 if(spec_type == "rigid" || spec_type == "rigid_body")
427 {
428 si.type = OWL::Type::RIGID;
429 spec = spec_rigid;
430 }
431 else if(spec_type == "point")
432 {
433 si.type = OWL::Type::MARKER;
434 spec = spec_marker;
435 }
436 else {
437 _error << "unknown sensor type: " << spec_type;
438 return false;
439 }
440
441 for(int i = 0; spec[i].dest; i++)
442 {
443 int ret = 0;
444 if(spec[i].type == "string")
445 ret = pop(spec[i].key, *((std::string*) spec[i].dest));
446 else if(spec[i].type == "uint32_t")
447 ret = pop_uint(spec[i].key, *((uint32_t*) spec[i].dest));
448 else if(spec[i].type == "float")
449 ret = pop_float(spec[i].key, *((float*) spec[i].dest));
450 else
451 {
452 _error << "unknown spec type: " << spec[i].type;
453 return false;
454 }
455 if(ret == 1)
456 {
457 if(spec[i].required)
458 {
459 _error << "required key not found: " << spec[i].key;
460 return false;
461 }
462 }
463 else if(ret)
464 {
465 _error << "error reading value for key \'" << spec[i].key << "'";
466 return false;
467 }
468 }
469
470 if(si.type == OWL::Type::RIGID)
471 si.id = si.tracker;
472
473 //special case (legacy)
474 if(!isnan(x) || !isnan(y) || !isnan(z))
475 {
476 if(isnan(x) || isnan(y) || isnan(z))
477 {
478 _error << "x,y,z keys must all be specified if any are specified.";
479 return false;
480 }
481 if(contains("pos"))
482 {
483 _error << "pos and x,y,z keys are mutually exclusive.";
484 return false;
485 }
486 std::stringstream pos; pos << x << ',' << y << ',' << z;
487 keyvals["pos"] = pos.str();
488 }
489
490 si.opt = join();
491 return true;
492 }
493
494 // returns: 0 on success, 1 on key error
495 int pop(std::string key, std::string &val)
496 {
497 if(keyvals.find(key) == keyvals.end())
498 return 1;
499 val = keyvals[key];
500 keyvals.erase(key);
501 return 0;
502 }
503
504 // returns: 0 on success, 1 on key error, 2 on parse error
505 int pop_int(std::string key, int &n)
506 {
507 std::string v;
508 if(pop(key, v)) return 1;
509 return read_int(v.c_str(), n) ? 0 : 2;
510 }
511
512 // returns: 0 on success, 1 on key error, 2 on parse error
513 int pop_uint(std::string key, uint32_t &n)
514 {
515 std::string v;
516 if(pop(key, v)) return 1;
517 return read_uint(v.c_str(), n) ? 0 : 2;
518 }
519
520 // returns: 0 on success, 1 on key error, 2 on parse error
521 int pop_float(std::string key, float &n)
522 {
523 std::string v;
524 if(pop(key, v)) return 1;
525 return read_float(v.c_str(), n) ? 0 : 2;
526 }
527
528 // returns: 0 on success, 1 on key error, 2 on parse error
529 int pop_bool(std::string key, bool &n)
530 {
531 std::string v;
532 if(pop(key, v)) return 1;
533 return read_bool(v.c_str(), n) ? 0 : 2;
534 }
535
536 // return index of error, or -1 on success
537 int parse_kv(std::string str)
538 {
539 keyvals.clear();
540 _error.str("");
541
542 vrpn_vector<char> current_key;
543 vrpn_vector<char> current_val;
544
545 int i = 0;
546 while(str[i])
547 {
548 current_key.clear();
549 current_val.clear();
550 while(isspace(str[i])) i++;
551 while(str[i]) {
552 if(str[i] == '"') {
553 _error << "key names are not allowed to contain quotes or be contained in quotes.";
554 return i;
555 } else if(isspace(str[i])) {
556 _error << "unexpected whitespace.";
557 return i;
558 } else if(str[i] == '=') {
559 i++;
560 break;
561 } else current_key.push_back(str[i++]);
562 }
563 if(!current_key.size()) {
564 _error << "empty key name.";
565 return i;
566 }
567 bool quoted = false;
568 if(str[i] == '"') {
569 quoted = true;
570 i++;
571 }
572 while(str[i]) {
573 if(str[i] == '"') {
574 if(quoted) {
575 quoted = false;
576 i++;
577 break;
578 } else {
579 _error << "misplaced quotes.";
580 return i;
581 }
582 } else if(str[i] == '=') {
583 _error << "unexpected '=' char in value token.";
584 return i;
585 } else if(!quoted && isspace(str[i])) break;
586 else current_val.push_back(str[i++]);
587 }
588 if(quoted) {
589 _error << "unterminated quotes.";
590 return i;
591 }
592 if(str[i] && !isspace(str[i])) {
593 _error << "expected whitespace after value token.";
594 return i;
595 }
596 if(!current_val.size()) {
597 _error << "empty value string.";
598 return i;
599 }
600 std::string key = std::string(current_key.data(), current_key.size());
601 std::string val = std::string(current_val.data(), current_val.size());
602
603 if(keyvals.find(key) != keyvals.end())
604 {
605 _error << "duplicate key encountered: '" << key << "'";
606 return i;
607 }
608 keyvals[key] = val;
609 }
610
611 return -1;
612 }
613};
614
615
616//
618{
619 const int BUFSIZE = 1024;
620 char line[BUFSIZE];
621 bool inTag = false;
622
623 std::string ln;
624 bool eof = false;
625
626 while(!(eof = (fgets(line, BUFSIZE, file) == NULL)))
627 {
628 ConfigParser parser;
629 ln = trim(line, BUFSIZE);
630
631 // skip contentless lines
632 if(!ln.length()) continue;
633
634 // skip lines unless we're nested in <owl> tags
635 if(ln == "<owl>") {
636 if (inTag) {
637 fprintf (stderr, "Error, nested <owl> tag encountered. Aborting...\n");
638 return false;
639 } else {
640 inTag = true;
641 continue;
642 }
643 } else if (ln == "</owl>") {
644 if (inTag) {
645 if(debug)
646 {
647 printf("[debug] parsed config file:\n");
648 printf("[debug] %s\n", options.c_str());
649 for(Sensors::const_iterator s = smgr->begin(); s != smgr->end(); s++)
650 fprintf(stdout, "[debug] sensor=%d type=%d tracker=%d options=\'%s\'\n", s->sensor_id, s->type, s->tracker, s->opt.c_str());
651 }
652 // closing tag encountered, exit.
653 return true;
654 } else {
655 fprintf (stderr, "Error, </owl> tag without <owl> tag. Aborting...\n");
656 return false;
657 }
658 }
659
660 // parse line for key-value pairs
661 if(inTag) {
662 int e = parser.parse_kv(ln);
663 if(e >= 0) {
664 fprintf(stderr, "Error at character %d.\n", e);
665 break;
666 }
667 }
668
669 if(parser.contains("sensor")) {
670 // line is a sensor specification
671 SensorInfo info;
672 if(parser.parse(info))
673 {
674 // check duplicates
675 if(smgr->get_by_sensor(info.sensor_id))
676 {
677 fprintf(stderr, "duplicate sensor defined: %d\n", info.sensor_id);
678 break;
679 }
680 smgr->add(info);
681 }
682 else
683 {
684 fprintf(stderr, "%s\n", parser.error().c_str());
685 break;
686 }
687 } else {
688 // line is an option specification
689 if(parser.pop("device", device) == 2)
690 {
691 fprintf(stderr, "error reading value for key 'device'\n");
692 break;
693 }
694 if(parser.pop_bool("drop_frames", drop_frames) == 2)
695 {
696 fprintf(stderr, "error reading value for key 'drop_frames'\n");
697 break;
698 }
699 if(parser.pop_bool("debug", debug) == 2)
700 {
701 fprintf(stderr, "error reading value for key 'debug'\n");
702 break;
703 }
704
705
706 std::string new_options = parser.join();
707 if(new_options.length()) options += (options.length()?" ":"") + parser.join();
708 }
709 }
710
711 if(eof) fprintf(stderr, "Unexpected end of file.\n");
712 else fprintf(stderr, "Unable to parse line: \"%s\"\n", ln.c_str());
713 return false;
714}
715
716
717//
719{
720 if(!context.isOpen()) return false;
721
722 context.streaming(enable ? 1 : 0);
723 printf("streaming: %d\n", enable);
724
725 if(context.lastError().length())
726 {
727 fprintf(stderr, "owl error: %s\n", context.lastError().c_str());
728 return false;
729 }
730
731 return true;
732}
733
734
735//
736void vrpn_Tracker_PhaseSpace::set_pose(const OWL::Rigid &r)
737{
738 //set the position
739 pos[0] = r.pose[0];
740 pos[1] = r.pose[1];
741 pos[2] = r.pose[2];
742
743 //set the orientation quaternion
744 //OWL has the scale factor first, whereas VRPN has it last.
745 d_quat[0] = r.pose[4];
746 d_quat[1] = r.pose[5];
747 d_quat[2] = r.pose[6];
748 d_quat[3] = r.pose[3];
749}
750
751//
752void vrpn_Tracker_PhaseSpace::report_marker(vrpn_int32 sensor, const OWL::Marker &m)
753{
754 d_sensor = sensor;
755
756 if(debug)
757 {
758 int tr = context.markerInfo(m.id).tracker_id;
759 printf("[debug] sensor=%d type=point tracker=%d led=%d x=%f y=%f z=%f cond=%f\n", d_sensor, tr, m.id, m.x, m.y, m.z, m.cond);
760 }
761
762 if(m.cond <= 0) return;
763
764 pos[0] = m.x;
765 pos[1] = m.y;
766 pos[2] = m.z;
767
768 //raw positions have no rotation
769 d_quat[0] = 0;
770 d_quat[1] = 0;
771 d_quat[2] = 0;
772 d_quat[3] = 1;
773
774 send_report();
775}
776
777
778//
779void vrpn_Tracker_PhaseSpace::report_rigid(vrpn_int32 sensor, const OWL::Rigid& r, bool is_stylus)
780{
781 d_sensor = sensor;
782
783 if(debug)
784 {
785 printf("[debug] sensor=%d type=rigid tracker=%d x=%f y=%f z=%f w=%f a=%f b=%f c=%f cond=%f\n", d_sensor, r.id, r.pose[0], r.pose[1], r.pose[2], r.pose[3], r.pose[4], r.pose[5], r.pose[6], r.cond);
786 }
787
788 if(r.cond <= 0) return;
789
790 // set the position/orientation
791 set_pose(r);
792 send_report();
793}
794
795
796//
798{
799 if(d_connection)
800 {
801 char msgbuf[MSGBUFSIZE];
802 int len = vrpn_Tracker::encode_to(msgbuf);
803 if(d_connection->pack_message(len, vrpn_Tracker::timestamp, position_m_id, d_sender_id, msgbuf,
805 fprintf(stderr,"PhaseSpace: cannot write message: tossing\n");
806 }
807 }
808}
809
810
811//
812void vrpn_Tracker_PhaseSpace::report_button(vrpn_int32 sensor, int value)
813{
815 {
816 fprintf(stderr, "error: sensor %d exceeds max button count\n", sensor);
817 return;
818 }
819
820 d_sensor = sensor;
821 buttons[d_sensor] = value;
822
823 if(debug)
824 {
825 printf("[debug] button %d 0x%x\n", d_sensor, value);
826 }
827}
828
829
830//
831void vrpn_Tracker_PhaseSpace::report_button_analog(vrpn_int32 sensor, int value)
832{
833 d_sensor = sensor;
835
836 if(debug)
837 {
838 printf("[debug] analog button %d 0x%x\n", d_sensor, value);
839 }
840}
841
842
843//
844template<class A>
845const A* find(int id, size_t& hint, vrpn_vector<A> &data)
846{
847 if(hint >= data.size() || id != data[hint].id)
848 {
849 for(size_t i = 0; i < data.size(); i++)
850 {
851 const A &d = data[i];
852 if(d.id == id)
853 {
854 hint = i;
855 return &d;
856 }
857 }
858 return NULL;
859 }
860 return &data[hint];
861}
862
863//
865{
866 if(!context.isOpen()) return 0;
867
868 int maxiter = 1;
869
870 // set limit on looping
871 if(drop_frames) maxiter = 10000;
872
873 // read new data
874 const OWL::Event *event = NULL;
875
876 {
877 const OWL::Event *e = NULL;
878 int count = 0;
879 while(context.isOpen() && context.property<int>("initialized") && (e = context.nextEvent()))
880 {
881 if(e->type_id() == OWL::Type::FRAME) event = e;
882 else if(e->type_id() == OWL::Type::ERROR)
883 {
884 std::string err;
885 e->get(err);
886 fprintf(stderr, "owl error event: %s\n", err.c_str());
887 if(e->name() == "fatal")
888 {
889 fprintf(stderr, "stopping...\n");
890 context.done();
891 context.close();
892 return -1;
893 }
894 }
895 else if(e->type_id() == OWL::Type::BYTE)
896 {
897 std::string s; e->get(s);
898 printf("%s: %s\n", e->name(), s.c_str());
899
900 if(strcmp(e->name(), "done") == 0)
901 return 0;
902 }
903 if(maxiter && ++count >= maxiter) break;
904 }
905 }
906
907 if(!event) return 0;
908
909 // set timestamp
910#if WIN32 // msvc 2008
911 vrpn_Tracker::timestamp.tv_sec = (long) event->time() / 1000000;
912 vrpn_Tracker::timestamp.tv_usec = (long) event->time() % 1000000;
913#else
914 lldiv_t divresult = lldiv(event->time(), 1000000);
915 vrpn_Tracker::timestamp.tv_sec = divresult.quot;
916 vrpn_Tracker::timestamp.tv_usec = divresult.rem;
917#endif
918
919 if(debug)
920 {
921 printf("[debug] time=%ld.%06ld\n", vrpn_Tracker::timestamp.tv_sec, vrpn_Tracker::timestamp.tv_usec);
922 }
923
924 OWL::Markers markers;
925 OWL::Rigids rigids;
926
927 for(const OWL::Event *e = event->begin(); e != event->end(); e++)
928 {
929 if(e->type_id() == OWL::Type::MARKER)
930 e->get(markers);
931 else if(e->type_id() == OWL::Type::RIGID)
932 e->get(rigids);
933 }
934
935 int slave = context.property<int>("slave");
936 vrpn_vector<const OWL::Marker*> reported_markers;
937 vrpn_vector<const OWL::Rigid*> reported_rigids;
938 int sensor = 0;
939
940 for(Sensors::iterator s = smgr->begin(); s != smgr->end(); s++)
941 {
942 switch(s->type)
943 {
944 case OWL::Type::MARKER:
945 {
946 const OWL::Marker *m = find<OWL::Marker>(s->id, s->search_hint, markers);
947 if(m) {
948 report_marker(s->sensor_id, *m);
949 if(slave) reported_markers.push_back(m);
950 }
951 }
952 break;
953 case OWL::Type::RIGID:
954 {
955 const OWL::Rigid *r = find<OWL::Rigid>(s->id, s->search_hint, rigids);
956 if(r) {
957 report_rigid(s->sensor_id, *r);
958 if(slave) reported_rigids.push_back(r);
959 }
960 }
961 break;
962 default:
963 break;
964 }
965
966 // TODO implement styluses
967
968 if(s->sensor_id > sensor) sensor = s->sensor_id;
969 }
970
971 if(slave)
972 {
973 // in slave mode, client doesn't necessarily know what the incoming data will be.
974 // Report the ones not specified in the cfg file
975 if(sensor < 1000) sensor = 1000; // start arbitrarily at 1000
976 for(OWL::Markers::iterator m = markers.begin(); m != markers.end(); m++)
977 if(std::find(reported_markers.begin(), reported_markers.end(), &*m) == reported_markers.end())
978 report_marker(sensor++, *m);
979 for(OWL::Rigids::iterator r = rigids.begin(); r != rigids.end(); r++)
980 if(std::find(reported_rigids.begin(), reported_rigids.end(), &*r) == reported_rigids.end())
981 report_rigid(sensor++, *r);
982 }
983
984 // finalize button and analog reports
987
988 if(context.lastError().length())
989 {
990 printf("owl error: %s\n", context.lastError().c_str());
991 return -1;
992 }
993
994 if(!context.property<int>("initialized"))
995 return -1;
996
997 return (markers.size() || rigids.size()) ? 1 : 0;
998}
999
1000
1001//
1003{
1005 if(thistracker->debug) {
1006 printf("[debug] vrpn_Tracker_PhaseSpace::handle_update_rate_request\n");
1007 }
1008 vrpn_float64 update_rate = 0;
1009 vrpn_unbuffer(&p.buffer,&update_rate);
1010 thistracker->context.frequency((float) update_rate);
1011 return 0;
1012}
1013
1014#endif // VRPN_INCLUDE_PHASESPACE
virtual void report_changes(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY, const struct timeval time=vrpn_ANALOG_NOW)
Send a report only if something has changed (for servers) Optionally, tell what time to stamp the val...
Definition vrpn_Analog.C:71
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.
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...
virtual void report_changes(void)
vrpn_Button_Filter(const char *, vrpn_Connection *c=NULL)
vrpn_int32 num_buttons
Definition vrpn_Button.h:48
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition vrpn_Button.h:45
int setChannelValue(int channel, double value)
This method should be used to set the value of a channel. It will be scaled and clipped as described ...
vrpn_Clipping_Analog_Server(const char *name, vrpn_Connection *c, vrpn_int32 numChannels=vrpn_CHANNEL_MAX)
Generic connection class not specific to the transport mechanism.
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
void set_pose(const OWL::Rigid &r)
vrpn_Tracker_PhaseSpace(const char *name, vrpn_Connection *c)
void report_marker(vrpn_int32 sensor, const OWL::Marker &m)
void report_rigid(vrpn_int32 sensor, const OWL::Rigid &r, bool is_stylus=false)
void report_button(vrpn_int32 sensor, int value)
void report_button_analog(vrpn_int32 sensor, int value)
static int VRPN_CALLBACK handle_update_rate_request(void *userdata, vrpn_HANDLERPARAM p)
virtual int encode_to(char *buf)
vrpn_float64 d_quat[4]
vrpn_int32 update_rate_id
vrpn_Tracker(const char *name, vrpn_Connection *c=NULL, const char *tracker_cfg_file_name=NULL)
vrpn_int32 d_sensor
vrpn_float64 pos[3]
struct timeval timestamp
vrpn_int32 position_m_id
const SensorInfo * const_iterator
iterator end()
void push_back(const T &val)
size_type size() const
iterator begin()
This structure is what is passed to a vrpn_Connection message callback.
const char * buffer
#define MM_TO_METERS
const int vrpn_BUTTON_MAX_BUTTONS
Definition vrpn_Button.h:13
const vrpn_uint32 vrpn_CONNECTION_LOW_LATENCY
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.
bool read_int(const char *str, int &i)
const A * find(int id, size_t &hint, vrpn_vector< A > &data)
bool read_float(const char *str, float &f)
#define MSGBUFSIZE
bool read_uint(const char *str, uint32_t &i)
bool read_bool(const char *str, bool &b)
std::string trim(char *line, int len)
vrpn_vector< SensorInfo > Sensors
bool operator<(const SensorInfo &a, const SensorInfo &b)