43#define MM_TO_METERS (0.001)
44#define MSGBUFSIZE 1024
46#ifdef VRPN_INCLUDE_PHASESPACE
65 search_hint = std::numeric_limits<uint32_t>::max();
75bool operator<(
const SensorInfo& a,
const SensorInfo& b)
77 if(a.type < b.type)
return true;
78 if(a.type > b.type)
return false;
83class vrpn_Tracker_PhaseSpace::SensorManager
89 void add(
const SensorInfo& s)
92 std::sort(_v.begin(), _v.end());
95 const SensorInfo* get_by_sensor(
int sensor_id)
97 for(
size_t i = 0; i < _v.size(); i++)
98 if(_v[i].sensor_id == sensor_id)
return &_v[i];
127 smgr =
new SensorManager();
132 fprintf(stderr,
"vrpn_Tracker: Can't register workspace handler\n");
148 printf(
"connecting to OWL server at %s...\n",
device.c_str());
150 std::string init_options =
"event.markers=1 event.rigids=1";
158 fprintf(stderr,
"owl connect error: %s\n",
context.lastError().c_str());
164 std::string coreversion =
context.property<std::string>(
"coreversion");
165 printf(
"[debug] server version: %s\n", coreversion.length() ? coreversion.c_str() :
"unknown");
167 std::string apiversion =
context.property<std::string>(
"apiversion");
169 printf(
"[debug] API version: %s\n", apiversion.length() ? apiversion.c_str() :
"unknown");
172 if(
debug) printf(
"[debug] initialization parameters: %s\n", init_options.c_str());
173 if(
context.initialize(init_options) <= 0)
175 fprintf(stderr,
"owl init error: %s\n",
context.lastError().c_str());
179 if(
options.find(
"timebase=") == std::string::npos)
context.timeBase(1, 1000000);
182 if(
context.lastError().length())
184 fprintf(stderr,
"owl error: %s\n",
context.lastError().c_str());
188 int slave =
context.property<
int>(
"slave");
190 if(slave) printf(
"slave mode enabled.\n");
193 printf(
"owl initialized\n");
201 if(
debug) printf(
"[debug] creating trackers...\n");
211 if(s->type != OWL::Type::RIGID)
continue;
213 if(std::find(ti.
begin(), ti.
end(), s->tracker) != ti.
end())
215 fprintf(stderr,
"rigid tracker %d already defined\n", s->tracker);
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());
224 if(!
context.createTracker(s->tracker,
type, name.str(), s->opt))
226 fprintf(stderr,
"tracker creation error: %s\n",
context.lastError().c_str());
235 if(s->type != OWL::Type::MARKER)
continue;
237 if(std::find(ti.
begin(), ti.
end(), s->tracker) == ti.
end())
239 printf(
"creating point tracker %d\n", s->tracker);
240 std::string
type =
"point";
241 std::stringstream name; name <<
type << nm;
243 context.createTracker(s->tracker,
type, name.str());
245 if(!
context.assignMarker(s->tracker, s->id,
"", s->opt))
247 fprintf(stderr,
"marker assignment error: %s\n",
context.lastError().c_str());
250 if(
debug) printf(
"[debug] id=%d tracker=%d options=\'%s\'\n", s->id, s->tracker, s->opt.c_str());
253 if(
context.lastError().length())
255 fprintf(stderr,
"tracker creation error: %s\n",
context.lastError().c_str());
275std::string
trim(
char* line,
int len)
279 for(s = 0; isspace(line[s]) && s < len; s++);
282 for(
int i = s; line[i] && i < len; i++)
284 if(line[i] ==
'#')
break;
285 if(!isspace(line[i])) e = i+1;
287 return std::string(line+s, e-s);
294 if(!str)
return false;
297 i = strtol(str, &endptr, 10);
298 if(*endptr || errno) {
299 fprintf(stderr,
"Error, expected an integer but got token: \"%s\"\n", str);
309 if(!str)
return false;
312 i = strtoul(str, &endptr, 10);
313 if(*endptr || errno) {
314 fprintf(stderr,
"Error, expected an unsigned integer but got token: \"%s\"\n", str);
324 if(!str)
return false;
329 }
else if(s ==
"false") {
335 b = i ? true :
false;
343 if(!str)
return false;
346 f = (float) strtod(str, &endptr);
347 if(*endptr || errno) {
348 fprintf(stderr,
"Error, expected a float but got token: \"%s\"\n", str);
366 std::map <std::string, std::string> keyvals;
367 std::stringstream _error;
376 bool contains(
const std::string &key)
378 return keyvals.find(key) != keyvals.end();
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;
390 bool parse(SensorInfo &si)
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();
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 }
408 Spec spec_rigid[] = {
409 {
"tracker",
"uint32_t", &si.tracker,
true },
410 {
"",
"", NULL,
false }
413 if(pop_int(
"sensor", si.sensor_id))
415 _error <<
"required key 'sensor' not found";
419 if(pop(
"type", spec_type))
421 _error <<
"required key 'type' not found";
426 if(spec_type ==
"rigid" || spec_type ==
"rigid_body")
428 si.type = OWL::Type::RIGID;
431 else if(spec_type ==
"point")
433 si.type = OWL::Type::MARKER;
437 _error <<
"unknown sensor type: " << spec_type;
441 for(
int i = 0; spec[i].dest; i++)
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));
452 _error <<
"unknown spec type: " << spec[i].type;
459 _error <<
"required key not found: " << spec[i].key;
465 _error <<
"error reading value for key \'" << spec[i].key <<
"'";
470 if(si.type == OWL::Type::RIGID)
474 if(!isnan(x) || !isnan(y) || !isnan(z))
476 if(isnan(x) || isnan(y) || isnan(z))
478 _error <<
"x,y,z keys must all be specified if any are specified.";
483 _error <<
"pos and x,y,z keys are mutually exclusive.";
486 std::stringstream pos; pos << x <<
',' << y <<
',' << z;
487 keyvals[
"pos"] = pos.str();
495 int pop(std::string key, std::string &val)
497 if(keyvals.find(key) == keyvals.end())
505 int pop_int(std::string key,
int &n)
508 if(pop(key, v))
return 1;
509 return read_int(v.c_str(), n) ? 0 : 2;
513 int pop_uint(std::string key, uint32_t &n)
516 if(pop(key, v))
return 1;
521 int pop_float(std::string key,
float &n)
524 if(pop(key, v))
return 1;
529 int pop_bool(std::string key,
bool &n)
532 if(pop(key, v))
return 1;
537 int parse_kv(std::string str)
542 vrpn_vector<char> current_key;
543 vrpn_vector<char> current_val;
550 while(isspace(str[i])) i++;
553 _error <<
"key names are not allowed to contain quotes or be contained in quotes.";
555 }
else if(isspace(str[i])) {
556 _error <<
"unexpected whitespace.";
558 }
else if(str[i] ==
'=') {
563 if(!current_key.
size()) {
564 _error <<
"empty key name.";
579 _error <<
"misplaced quotes.";
582 }
else if(str[i] ==
'=') {
583 _error <<
"unexpected '=' char in value token.";
585 }
else if(!quoted && isspace(str[i]))
break;
589 _error <<
"unterminated quotes.";
592 if(str[i] && !isspace(str[i])) {
593 _error <<
"expected whitespace after value token.";
596 if(!current_val.
size()) {
597 _error <<
"empty value string.";
600 std::string key = std::string(current_key.
data(), current_key.
size());
601 std::string val = std::string(current_val.
data(), current_val.
size());
603 if(keyvals.find(key) != keyvals.end())
605 _error <<
"duplicate key encountered: '" << key <<
"'";
619 const int BUFSIZE = 1024;
626 while(!(eof = (fgets(line, BUFSIZE, file) == NULL)))
629 ln =
trim(line, BUFSIZE);
632 if(!ln.length())
continue;
637 fprintf (stderr,
"Error, nested <owl> tag encountered. Aborting...\n");
643 }
else if (ln ==
"</owl>") {
647 printf(
"[debug] parsed config file:\n");
648 printf(
"[debug] %s\n",
options.c_str());
650 fprintf(stdout,
"[debug] sensor=%d type=%d tracker=%d options=\'%s\'\n", s->sensor_id, s->type, s->tracker, s->opt.c_str());
655 fprintf (stderr,
"Error, </owl> tag without <owl> tag. Aborting...\n");
662 int e = parser.parse_kv(ln);
664 fprintf(stderr,
"Error at character %d.\n", e);
669 if(parser.contains(
"sensor")) {
672 if(parser.parse(info))
675 if(
smgr->get_by_sensor(info.sensor_id))
677 fprintf(stderr,
"duplicate sensor defined: %d\n", info.sensor_id);
684 fprintf(stderr,
"%s\n", parser.error().c_str());
689 if(parser.pop(
"device",
device) == 2)
691 fprintf(stderr,
"error reading value for key 'device'\n");
694 if(parser.pop_bool(
"drop_frames",
drop_frames) == 2)
696 fprintf(stderr,
"error reading value for key 'drop_frames'\n");
699 if(parser.pop_bool(
"debug",
debug) == 2)
701 fprintf(stderr,
"error reading value for key 'debug'\n");
706 std::string new_options = parser.join();
707 if(new_options.length())
options += (
options.length()?
" ":
"") + parser.join();
711 if(eof) fprintf(stderr,
"Unexpected end of file.\n");
712 else fprintf(stderr,
"Unable to parse line: \"%s\"\n", ln.c_str());
720 if(!
context.isOpen())
return false;
722 context.streaming(enable ? 1 : 0);
723 printf(
"streaming: %d\n", enable);
725 if(
context.lastError().length())
727 fprintf(stderr,
"owl error: %s\n",
context.lastError().c_str());
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);
762 if(m.cond <= 0)
return;
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);
788 if(r.cond <= 0)
return;
805 fprintf(stderr,
"PhaseSpace: cannot write message: tossing\n");
816 fprintf(stderr,
"error: sensor %d exceeds max button count\n", sensor);
825 printf(
"[debug] button %d 0x%x\n",
d_sensor, value);
838 printf(
"[debug] analog button %d 0x%x\n",
d_sensor, value);
847 if(hint >= data.
size() ||
id != data[hint].id)
849 for(
size_t i = 0; i < data.
size(); i++)
851 const A &d = data[i];
866 if(!
context.isOpen())
return 0;
874 const OWL::Event *
event = NULL;
877 const OWL::Event *e = NULL;
881 if(e->type_id() == OWL::Type::FRAME)
event = e;
882 else if(e->type_id() == OWL::Type::ERROR)
886 fprintf(stderr,
"owl error event: %s\n", err.c_str());
887 if(e->name() ==
"fatal")
889 fprintf(stderr,
"stopping...\n");
895 else if(e->type_id() == OWL::Type::BYTE)
897 std::string s; e->get(s);
898 printf(
"%s: %s\n", e->name(), s.c_str());
900 if(strcmp(e->name(),
"done") == 0)
903 if(maxiter && ++count >= maxiter)
break;
914 lldiv_t divresult = lldiv(event->time(), 1000000);
924 OWL::Markers markers;
927 for(
const OWL::Event *e = event->begin(); e != event->end(); e++)
929 if(e->type_id() == OWL::Type::MARKER)
931 else if(e->type_id() == OWL::Type::RIGID)
935 int slave =
context.property<
int>(
"slave");
944 case OWL::Type::MARKER:
949 if(slave) reported_markers.push_back(m);
953 case OWL::Type::RIGID:
968 if(s->sensor_id > sensor) sensor = s->sensor_id;
975 if(sensor < 1000) sensor = 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())
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())
988 if(
context.lastError().length())
990 printf(
"owl error: %s\n",
context.lastError().c_str());
994 if(!
context.property<
int>(
"initialized"))
997 return (markers.size() || rigids.size()) ? 1 : 0;
1005 if(thistracker->
debug) {
1006 printf(
"[debug] vrpn_Tracker_PhaseSpace::handle_update_rate_request\n");
1008 vrpn_float64 update_rate = 0;
1010 thistracker->
context.frequency((
float) update_rate);
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...
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...
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)
virtual int get_report(void)
void report_marker(vrpn_int32 sensor, const OWL::Marker &m)
void report_rigid(vrpn_int32 sensor, const OWL::Rigid &r, bool is_stylus=false)
~vrpn_Tracker_PhaseSpace()
bool enableStreaming(bool enable)
virtual void send_report(void)
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_int32 update_rate_id
vrpn_Tracker(const char *name, vrpn_Connection *c=NULL, const char *tracker_cfg_file_name=NULL)
const SensorInfo * const_iterator
void push_back(const T &val)
This structure is what is passed to a vrpn_Connection message callback.
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)
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)