vrpn 07.35
Virtual Reality Peripheral Network
Loading...
Searching...
No Matches
vrpn_YEI_3Space.C
Go to the documentation of this file.
1// This is a driver for the YEI 3Space serial-port devices.
2
3#include <stdio.h> // for sprintf, printf
4
5#include "vrpn_YEI_3Space.h"
6#include "vrpn_MessageMacros.h" // for VRPN_MSG_INFO, VRPN_MSG_WARNING, VRPN_MSG_ERROR
7#include "quat.h"
8
9//#define VERBOSE
10
11// Defines the modes in which the device can find itself.
12#define STATUS_NOT_INITIALIZED (-2) // Not yet initialized
13#define STATUS_RESETTING (-1) // Resetting the device
14#define STATUS_READING (0) // Looking for the a report
15
16// The wired USB connection can stream up to 256 bytes, but the wireless
17// can stream a maximum of 96 bytes per sensor.
18static const int REPORT_LENGTH = 16 + 16 + 12 + 36 + 4 + 4 + 1;
19#define MAX_TIME_INTERVAL (2000000) // max time between reports (usec)
20
21
22/******************************************************************************
23 * NAME : vrpn_YEI_3Space::vrpn_YEI_3Space
24 * ROLE : This creates a vrpn_YEI_3Space and sets it to reset mode.
25 * ARGUMENTS :
26 * RETURN :
27 ******************************************************************************/
29 , vrpn_Connection * p_c
30 , double frames_per_second
31 , const char *reset_commands[])
32 : vrpn_Tracker_Server (p_name, p_c, 2)
33 , vrpn_Analog (p_name, p_c)
34 , vrpn_Button_Filter(p_name, p_c)
35 , d_frames_per_second(frames_per_second)
36{
37 // Count the reset commands and allocate an array to store them in.
38 const char **ptr = reset_commands;
39 d_reset_commands = NULL;
41 if (ptr != NULL) while ((*ptr) != NULL) {
43 ptr++;
44 }
45 if (d_reset_command_count > 0) {
47 }
48
49 // Copy any reset commands.
50 ptr = reset_commands;
51 for (int i = 0; i < d_reset_command_count; i++) {
52 d_reset_commands[i] = new char[strlen(reset_commands[i]) + 1];
53 strcpy(d_reset_commands[i], reset_commands[i]);
54 }
55
56 // Set the parameters in the parent classes
58
59 // Initialize the state of all the buttons
61 memset(buttons, 0, sizeof(buttons));
62 memset(lastbuttons, 0, sizeof(lastbuttons));
63
65
66 // We're constructed, but not yet initialized.
68}
69
70/******************************************************************************
71 * NAME : vrpn_YEI_3Space::~vrpn_YEI_3Space
72 * ROLE : This destroys a vrpn_YEI_3Space and frees its memory.
73 * ARGUMENTS :
74 * RETURN :
75 ******************************************************************************/
77{
78 // Free the space used to store the additional reset commands,
79 // then free the array used to store the pointers.
80 try {
81 for (int i = 0; i < d_reset_command_count; i++) {
82 delete[] d_reset_commands[i];
83 }
84 if (d_reset_commands != NULL) {
85 delete[] d_reset_commands;
86 d_reset_commands = NULL;
87 }
88 } catch (...) {
89 fprintf(stderr, "vrpn_YEI_3Space::~vrpn_YEI_3Space(): delete failed\n");
90 return;
91 }
92}
93
94/******************************************************************************
95 * NAME : vrpn_YEI_3Space::vrpn_YEI_3Space
96 * ROLE : This creates a vrpn_YEI_3Space and sets it to reset mode.
97 * ARGUMENTS :
98 * RETURN :
99 ******************************************************************************/
100void vrpn_YEI_3Space::init (bool calibrate_gyros_on_setup
101 , bool tare_on_setup
102 , double red_LED_color
103 , double green_LED_color
104 , double blue_LED_color
105 , int LED_mode)
106{
107 // Configure LED mode.
108 unsigned char set_LED_mode[2] = { 0xC4, 0 };
109 set_LED_mode[1] = static_cast<unsigned char>(LED_mode);
110 if (!send_binary_command(set_LED_mode, sizeof(set_LED_mode))) {
111 VRPN_MSG_ERROR ("vrpn_YEI_3Space::init: Unable to send set-LED-mode command\n");
112 }
113#ifdef VERBOSE
114 printf("LED mode set\n");
115#endif
116
117 // Configure LED color.
118 unsigned char set_LED_color[13] = { 0xEE, 0,0,0,0,0,0,0,0,0,0,0,0 };
119 unsigned char *bufptr = &set_LED_color[1];
120 vrpn_int32 buflen = 12;
121 vrpn_float32 LEDs[3];
122 LEDs[0] = static_cast<vrpn_float32>(red_LED_color);
123 LEDs[1] = static_cast<vrpn_float32>(green_LED_color);
124 LEDs[2] = static_cast<vrpn_float32>(blue_LED_color);
125 vrpn_buffer(&bufptr, &buflen, LEDs[0]);
126 vrpn_buffer(&bufptr, &buflen, LEDs[1]);
127 vrpn_buffer(&bufptr, &buflen, LEDs[2]);
128 if (!send_binary_command (set_LED_color, sizeof(set_LED_color))) {
129 VRPN_MSG_ERROR ("vrpn_YEI_3Space::init: Unable to send set-LED-color command\n");
130 }
131
132 // If we're supposed to calibrate the gyros on startup, do so now.
133 if (calibrate_gyros_on_setup) {
134 unsigned char begin_gyroscope_calibration[1] = { 0xA5 };
135 if (!send_binary_command (begin_gyroscope_calibration, sizeof(begin_gyroscope_calibration))) {
136 VRPN_MSG_ERROR ("vrpn_YEI_3Space::init: Unable to send set-gyroscope-calibration command\n");
137 }
138 }
139
140 // If we're supposed to tare on startup, do so now.
141 if (tare_on_setup) {
142 unsigned char tare[1] = { 0x60 };
143 if (!send_binary_command (tare, sizeof(tare))) {
144 VRPN_MSG_ERROR ("vrpn_YEI_3Space::init: Unable to send tare command\n");
145 }
146 }
147
148 // Set the mode to reset
151#ifdef VERBOSE
152 printf("init() complete\n");
153#endif
154}
155
156/******************************************************************************
157 * NAME : vrpn_YEI_3Space::reset
158 * ROLE : This routine will reset the YEI_3Space
159 * ARGUMENTS :
160 * RETURN : 0 else -1 in case of error
161 ******************************************************************************/
163{
164 struct timeval l_timeout;
165
166 // Ask the device to stop streaming and then wait a little and flush the
167 // input buffer and then ask it for the LED mode and make sure we get a response.
168 unsigned char stop_streaming[1] = { 0x56 };
169 if (!send_binary_command (stop_streaming, sizeof(stop_streaming))) {
170 VRPN_MSG_ERROR ("vrpn_YEI_3Space::reset: Unable to send stop-streaming command\n");
171 return -1;
172 }
173 vrpn_SleepMsecs(50);
174 flush_input();
175 unsigned char get_led_mode[1] = { 0xC8 };
176 if (!send_binary_command (get_led_mode, sizeof(get_led_mode))) {
177 VRPN_MSG_ERROR ("vrpn_YEI_3Space::reset: Unable to send get-led-mode command\n");
178 return -1;
179 }
180 l_timeout.tv_sec = 2;
181 l_timeout.tv_usec = 0;
182 if (!receive_LED_mode_response(&l_timeout)) {
183 VRPN_MSG_ERROR ("vrpn_YEI_3Space::reset: Unable to read get-led-mode response\n");
184 return -1;
185 }
186
187 // Request the 3 LED colors and set our internal values to match them.
188 unsigned char get_led_values[1] = { 0xEF };
189 if (!send_binary_command (get_led_values, sizeof(get_led_values))) {
190 VRPN_MSG_ERROR ("vrpn_YEI_3Space::reset: Unable to send get-led-values command\n");
191 return -1;
192 }
193 if (!receive_LED_values_response(&l_timeout)) {
194 VRPN_MSG_ERROR ("vrpn_YEI_3Space::reset: Unable to read get-led-mode response\n");
195 return -1;
196 }
197
198 // Change into the x-right, z-up right handed CS we want
199 unsigned char set_rh_system[] = { 0x74, 0x01 };
200 if (!send_binary_command(set_rh_system, sizeof(set_rh_system))) {
201 VRPN_MSG_ERROR("vrpn_YEI_3Space::reset: Unable to send coordinate system selection command\n");
202 return -1;
203 }
204
205 // Configure streaming speed based on the requested frames/second value.
206 unsigned char set_streaming_timing[13] = { 0x52, 0,0,0,0,0,0,0,0,0,0,0,0 };
207 vrpn_uint32 interval;
208 if (d_frames_per_second <= 0) {
209 VRPN_MSG_ERROR ("vrpn_YEI_3Space::reset: Bad frames/second value, setting to maximum\n");
210 interval = 0;
211 } else {
212 interval = static_cast<vrpn_uint32>(1e6 * 1 / d_frames_per_second);
213 }
214 vrpn_uint32 duration = 0xFFFFFFFF;
215 vrpn_uint32 delay = 0;
216 unsigned char *bufptr = &set_streaming_timing[1];
217 vrpn_int32 buflen = 12;
218 vrpn_buffer(&bufptr, &buflen, interval);
219 vrpn_buffer(&bufptr, &buflen, duration);
220 vrpn_buffer(&bufptr, &buflen, delay);
221 if (!send_binary_command (set_streaming_timing, sizeof(set_streaming_timing))) {
222 VRPN_MSG_ERROR ("vrpn_YEI_3Space::reset: Unable to send set-streaming-timing command\n");
223 return -1;
224 }
225
226 // Configure the set of values we want to have streamed.
227 // The value 0xFF means "nothing." We want to stream the untared
228 // orientiation as a quaternion, the tared orientation as a quaternion,
229 // all corrected sensor data, the temperature in Celsius, and the
230 // confidence factor.
231 unsigned char set_streaming_slots[9] = { 0x50,
232 0x06, // untared quat
233 0x00, // tared quat
234 0x29, // tared corrected linear acceleration with gravity removed
235 0x25, // all corrected sensor data (3D vectors: rate gyro in rad/s, accel in g, and compass in gauss)
236 0x2B, // temperature C
237 0x2D, // confidence factor
238 0xFA, // button state
239 0xFF }; // followed by empty streaming spots.
240 if (!send_binary_command (set_streaming_slots, sizeof(set_streaming_slots))) {
241 VRPN_MSG_ERROR ("vrpn_YEI_3Space::reset: Unable to send set-streaming-slots command\n");
242 return -1;
243 }
244
245 // Send any additional ACII reset commands that were passed into the
246 // constructor.
247 for (int i = 0; i < d_reset_command_count; i++) {
249 VRPN_MSG_ERROR ("vrpn_YEI_3Space::reset: Unable to send additional reset command\n");
250 return -1;
251 }
252 }
253
254 // Start streaming mode.
255 unsigned char start_streaming[1] = { 0x55 };
256 if (!send_binary_command (start_streaming, sizeof(start_streaming))) {
257 VRPN_MSG_ERROR ("vrpn_YEI_3Space::reset: Unable to send start-streaming command\n");
258 return -1;
259 }
260
261 // We're now entering the reading mode with no characters.
262 d_expected_characters = REPORT_LENGTH;
265
266 vrpn_gettimeofday (&timestamp, NULL); // Set watchdog now
267 return 0;
268}
269
270/******************************************************************************
271 * NAME : vrpn_YEI_3Space::handle_report
272 * ROLE : This function will parse a full report, then
273 * put that report into analog fields and call the report methods on these.
274 * ARGUMENTS : void
275 * RETURN : void
276 ******************************************************************************/
277void vrpn_YEI_3Space::handle_report(unsigned char *report)
278{
279 vrpn_float32 value;
280 unsigned char *bufptr = report;
281
282 // Read the two orientations and report them
283 q_vec_type pos;
284 pos[Q_X] = pos[Q_Y] = pos[Q_Z] = 0;
285 q_type quat;
286
287 for (int i = 0; i < 2; i++) {
288 vrpn_unbuffer(&bufptr, &value);
289 quat[Q_X] = value;
290 vrpn_unbuffer(&bufptr, &value);
291 quat[Q_Y] = value;
292 vrpn_unbuffer(&bufptr, &value);
293 quat[Q_Z] = value;
294 vrpn_unbuffer(&bufptr, &value);
295 quat[Q_W] = value;
296 if (0 != report_pose(i, timestamp, pos, quat)) {
297 VRPN_MSG_ERROR ("vrpn_YEI_3Space::handle_report(): Error sending sensor report");
299 }
300 }
301
302 // XXX Linear rate gyros into orientation change?
303
304 // Read the three values for linear acceleration in tared
305 // space with gravity removed. Convert it into units of
306 // meters/second/second. Put it into the tared sensor.
307 q_vec_type acc;
308 q_type acc_quat;
309 acc_quat[Q_X] = acc_quat[Q_Y] = acc_quat[Q_Z] = 0; acc_quat[Q_W] = 1;
310 vrpn_unbuffer(&bufptr, &value);
311 static const double GRAVITY = 9.80665; // Meters/second/second
312 acc[Q_X] = value * GRAVITY;
313 vrpn_unbuffer(&bufptr, &value);
314 acc[Q_Y] = value * GRAVITY;
315 vrpn_unbuffer(&bufptr, &value);
316 acc[Q_Z] = value * GRAVITY;
317 int sensor = 1;
318 double interval = 1;
319 if (0 != report_pose_acceleration(sensor, timestamp, acc, acc_quat, interval)) {
320 VRPN_MSG_ERROR ("vrpn_YEI_3Space::handle_report(): Error sending acceleration report");
322 }
323
324 // Read the analog values and put them into the channels.
325 for (int i = 0; i < vrpn_Analog::getNumChannels(); i++) {
326 vrpn_unbuffer(&bufptr, &value);
327 channel[i] = value;
328 }
329
330 // Check the confidence factor to make sure it is between 0 and 1.
331 // If not, there is trouble parsing the report. Sometimes the wired
332 // unit gets the wrong number of bytes in the report, causing things
333 // to wrap around. This catches that case.
334 if ((channel[10] < 0) || (channel[10] > 1)) {
335 VRPN_MSG_ERROR("vrpn_YEI_3Space::handle_report(): Invalid confidence, resetting");
337 }
338
339 // Read the button values and put them into the buttons.
340 vrpn_uint8 b;
341 vrpn_unbuffer(&bufptr, &b);
342 for (int i = 0; i < 8; i++) {
343 buttons[i] = (b & (1 << i)) != 0;
344 }
345
346 //--------------------------------------------------------------------
347 // Done with the decoding, send the analog and button reports.
348 //--------------------------------------------------------------------
349
351}
352
353/******************************************************************************
354 * NAME : vrpn_YEI_3Space::report_changes
355 * ROLE :
356 * ARGUMENTS :
357 * RETURN : void
358 ******************************************************************************/
366
367
368/******************************************************************************
369 * NAME : vrpn_YEI_3Space::report
370 * ROLE :
371 * ARGUMENTS :
372 * RETURN : void
373 ******************************************************************************/
374void vrpn_YEI_3Space::report (vrpn_uint32 class_of_service)
375{
377 vrpn_Analog::report(class_of_service);
378}
379
380/******************************************************************************
381 * NAME : vrpn_YEI_3Space::mainloop
382 * ROLE : This routine is called each time through the server's main loop. It will
383 * take a course of action depending on the current status of the device,
384 * either trying to reset it or trying to get a reading from it. It will
385 * try to reset the device if no data has come from it for a couple of
386 * seconds
387 * ARGUMENTS :
388 * RETURN : void
389 ******************************************************************************/
391{
392 char l_errmsg[256];
393
395
396 switch (d_status)
397 {
399 break;
400
401 case STATUS_RESETTING:
402 if (reset()== -1) {
403 VRPN_MSG_ERROR ("vrpn_YEI_3Space: Cannot reset!");
404 }
405 break;
406
407 case STATUS_READING:
408 {
409 // It turns out to be important to get the report before checking
410 // to see if it has been too long since the last report. This is
411 // because there is the possibility that some other device running
412 // in the same server may have taken a long time on its last pass
413 // through mainloop(). Trackers that are resetting do this. When
414 // this happens, you can get an infinite loop -- where one tracker
415 // resets and causes the other to timeout, and then it returns the
416 // favor. By checking for the report here, we reset the timestamp
417 // if there is a report ready (ie, if THIS device is still operating).
418 while (get_report()) {}
419 struct timeval current_time;
420 vrpn_gettimeofday (&current_time, NULL);
421 if (vrpn_TimevalDuration (current_time, timestamp) > MAX_TIME_INTERVAL) {
422 sprintf (l_errmsg, "vrpn_YEI_3Space::mainloop: Timeout... current_time=%ld:%ld, timestamp=%ld:%ld",
423 current_time.tv_sec,
424 static_cast<long> (current_time.tv_usec),
425 timestamp.tv_sec,
426 static_cast<long> (timestamp.tv_usec));
427 VRPN_MSG_ERROR (l_errmsg);
429 }
430 }
431 break;
432
433 default:
434 VRPN_MSG_ERROR ("vrpn_YEI_3Space::mainloop: Unknown mode (internal error)");
435 break;
436 }
437}
438
439
440/******************************************************************************
441 * NAME : vrpn_YEI_3Space_Sensor::vrpn_YEI_3Space_Sensor
442 * ROLE : This creates a vrpn_YEI_3Space_Sensor and sets it to reset mode. It opens
443 * the serial port to use to communicate to it.
444 * ARGUMENTS :
445 * RETURN :
446 ******************************************************************************/
448 , vrpn_Connection * p_c
449 , const char * p_port
450 , int p_baud
451 , bool calibrate_gyros_on_setup
452 , bool tare_on_setup
453 , double frames_per_second
454 , double red_LED_color
455 , double green_LED_color
456 , double blue_LED_color
457 , int LED_mode
458 , const char *reset_commands[])
459 : vrpn_YEI_3Space (p_name, p_c, frames_per_second, reset_commands)
460{
461 // Open the serial port we're going to use to talk with the device.
462 if ((d_serial_fd = vrpn_open_commport(p_port, p_baud,
463 8, vrpn_SER_PARITY_NONE)) == -1) {
464 perror("vrpn_YEI_3Space_Sensor::vrpn_YEI_3Space_Sensor: Cannot open serial port");
465 fprintf(stderr," (port %s)\n", p_port);
466 }
467
468 // Initialize the state of the device, now that we've established a
469 // way to talk with it.
470 init(calibrate_gyros_on_setup
471 , tare_on_setup, red_LED_color
472 , green_LED_color, blue_LED_color, LED_mode);
473}
474
475/******************************************************************************
476 * NAME : vrpn_YEI_3Space_Sensor::~vrpn_YEI_3Space_Sensor
477 * ROLE : This destroys a vrpn_YEI_3Space_Sensor and closes its ports.
478 * ARGUMENTS :
479 * RETURN :
480 ******************************************************************************/
482{
483 // Ask the device to stop streaming.
484 unsigned char stop_streaming[1] = { 0x56 };
485 if (!send_binary_command(stop_streaming, sizeof(stop_streaming))) {
486 VRPN_MSG_ERROR ("vrpn_YEI_3Space_Sensor_Wireless::~vrpn_YEI_3Space_Sensor_Wireless: Unable to send stop-streaming command\n");
487 }
488
489 // Close com port when destroyed.
490 if (d_serial_fd != -1) {
492 }
493}
494
495/******************************************************************************
496 * NAME : vrpn_YEI_3Space_Sensor::send_binary_command
497 * ROLE :
498 * ARGUMENTS : char *cmd : the command to be sent
499 * int len : Length of the command to be sent
500 * RETURN : true on success, false on failure.
501 ******************************************************************************/
502
503// Info from YEI 3-Space Sensor User's Manual Wireless 2.0 R21 26 March2014
504// http://www.yeitechnology.com/sites/default/files/YEI_3-Space_Sensor_Users_Manual_Wireless_2.0_r21_26Mar2014.pdf
505// Binary-mode command packet format:
506// 0xF7 (start of packet)
507// Command byte (command value)
508// Command data (0 or more bytes of parameters, in big-endian format)
509// Checksum (sum of all bytes in the packet % 256)
510bool vrpn_YEI_3Space_Sensor::send_binary_command (const unsigned char *p_cmd, int p_len)
511{
512 const unsigned char START_OF_PACKET = 0xF7;
513
514 // Compute the checksum. The description of the checksum implies that it should
515 // include the START_OF_PACKET data, but the example provided in page 28 does not
516 // include that data in the checksum, so we only include the packet data here.
517 int checksum = 0;
518 for (int i = 0; i < p_len; i++) {
519 checksum += p_cmd[i];
520 }
521 checksum %= 256;
522
523 // Pack the command into the buffer with the start-of-packet and checksum.
524 unsigned char buffer[256]; // Large enough buffer to hold all possible commands.
525 buffer[0] = START_OF_PACKET;
526 memcpy(&(buffer[1]), p_cmd, p_len);
527 buffer[p_len + 1] = static_cast<unsigned char>(checksum);
528
529 // Send the command and return whether it worked.
530 int l_ret;
531 l_ret = vrpn_write_characters (d_serial_fd, buffer, p_len+2);
532 // Tell if this all worked.
533 if (l_ret == p_len+2) {
534 return true;
535 } else {
536 return false;
537 }
538}
539
540/******************************************************************************
541 * NAME : vrpn_YEI_3Space_Sensor::send_ascii_command
542 * ROLE :
543 * ARGUMENTS : char *cmd : the command to be sent
544 * RETURN : true on success, false on failure.
545 ******************************************************************************/
546
547// Info from YEI 3-Space Sensor User's Manual Wireless 2.0 R21 26 March2014
548// http://www.yeitechnology.com/sites/default/files/YEI_3-Space_Sensor_Users_Manual_Wireless_2.0_r21_26Mar2014.pdf
549// Ascii-mode command packet format:
550// ':' (start of packet)
551// Command value (decimal)
552// ',' Command data (0 or more bytes of parameters
553// '\n'
555{
556 // Check to make sure we have a non-empty command
557 if (strlen(p_cmd) == 0) {
558 return false;
559 }
560
561 // Allocate space for the command plus padding and zero terminator
562 int buflen = static_cast<int>(strlen(p_cmd) + 3);
563 unsigned char *buffer;
564 try { buffer = new unsigned char[buflen]; }
565 catch (...) {
566 return false;
567 }
568
569 // Fill in the command
570 buffer[0] = ':';
571 memcpy(&buffer[1], p_cmd, strlen(p_cmd));
572 buffer[buflen-2] = '\n';
573 buffer[buflen-1] = 0;
574
575 // Send the command and see if it worked.
576 int l_ret = vrpn_write_characters (d_serial_fd, buffer, buflen);
577
578 // Free the buffer.
579 try {
580 delete[] buffer;
581 } catch (...) {
582 fprintf(stderr, "vrpn_YEI_3Space_Sensor::send_ascii_command(): delete failed\n");
583 return false;
584 }
585
586 // Tell if sending worked.
587 if (l_ret == buflen) {
588 return true;
589 } else {
590 return false;
591 }
592}
593
594/******************************************************************************
595 * NAME : vrpn_YEI_3Space_Sensor::receive_LED_mode_response
596 * ROLE :
597 * ARGUMENTS : struct timeval *timeout; how long to wait, NULL for forever
598 * RETURN : true on success, false on failure.
599 ******************************************************************************/
600
601// Info from YEI 3-Space Sensor User's Manual Wireless 2.0 R21 26 March2014
602// http://www.yeitechnology.com/sites/default/files/YEI_3-Space_Sensor_Users_Manual_Wireless_2.0_r21_26Mar2014.pdf
603// Binary-mode command packet format:
604// Single byte: value 0 or 1.
606{
607 unsigned char value;
608 int ret = vrpn_read_available_characters (d_serial_fd, &value, sizeof(value), timeout);
609 if (ret != sizeof(value)) {
610 return false;
611 }
612 d_LED_mode = value;
613 return true;
614}
615
616/******************************************************************************
617 * NAME : vrpn_YEI_3Space_Sensor::receive_LED_values_response
618 * ROLE :
619 * ARGUMENTS : struct timeval *timeout; how long to wait, NULL for forever
620 * RETURN : true on success, false on failure.
621 ******************************************************************************/
622
623// Info from YEI 3-Space Sensor User's Manual Wireless 2.0 R21 26 March2014
624// http://www.yeitechnology.com/sites/default/files/YEI_3-Space_Sensor_Users_Manual_Wireless_2.0_r21_26Mar2014.pdf
625// Binary-mode command packet format:
626// Three four-byte float responses, each big-endian.
628{
629 unsigned char buffer[3*sizeof(vrpn_float32)];
630 int ret = vrpn_read_available_characters (d_serial_fd, buffer, sizeof(buffer), timeout);
631 if (ret != sizeof(buffer)) {
632 return false;
633 }
634 vrpn_float32 value;
635 unsigned char *bufptr = buffer;
636 vrpn_unbuffer(&bufptr, &value);
637 d_LED_color[0] = value;
638 vrpn_unbuffer(&bufptr, &value);
639 d_LED_color[1] = value;
640 vrpn_unbuffer(&bufptr, &value);
641 d_LED_color[2] = value;
642 return true;
643}
644
645/******************************************************************************
646 * NAME : vrpn_YEI_3Space_Sensor::get_report
647 * ROLE : This function will read characters until it has a full report, then
648 * call handle_report() with the report and clear the counts.
649 * ARGUMENTS : void
650 * RETURN : bool: Did I get a complete report?
651 ******************************************************************************/
653{
654 int l_ret; // Return value from function call to be checked
655
656 //--------------------------------------------------------------------
657 // Read as many bytes of this report as we can, storing them
658 // in the buffer. We keep track of how many have been read so far
659 // and only try to read the rest.
660 //--------------------------------------------------------------------
661
664 if (l_ret == -1) {
665 VRPN_MSG_ERROR ("vrpn_YEI_3Space_Sensor::get_report(): Error reading the sensor, resetting");
667 return false;
668 }
669#ifdef VERBOSE
670 if (l_ret != 0) printf("... got %d characters (%d total)\n",l_ret, d_characters_read);
671#endif
672
673 //--------------------------------------------------------------------
674 // The time of the report is the time at which the first character for
675 // the report is read.
676 //--------------------------------------------------------------------
677
678 if ( (l_ret > 0) && (d_characters_read == 0) ) {
680 }
681
682 //--------------------------------------------------------------------
683 // We keep track of how many characters we have received and keep
684 // going back until we get as many as we expect.
685 //--------------------------------------------------------------------
686
687 d_characters_read += l_ret;
688 if (d_characters_read < d_expected_characters) { // Not done -- go back for more
689 return false;
690 }
691
692 //--------------------------------------------------------------------
693 // We now have enough characters to make a full report. Parse each
694 // input in order and check to make sure they work, then send the results.
695 //--------------------------------------------------------------------
697
698 //--------------------------------------------------------------------
699 // Clear our counts to be ready for the next report
700 //--------------------------------------------------------------------
701 d_expected_characters = REPORT_LENGTH;
703 return true;
704}
705
710
711
712/******************************************************************************
713 * NAME : vrpn_YEI_3Space_Sensor_Wireless::vrpn_YEI_3Space_Sensor_Wireless
714 * ROLE : This creates a vrpn_YEI_3Space_Sensor_Wireless and sets it to
715 * reset mode. This constructor is for the first sensor on a
716 * given dongle, so it opens the serial port and configures the
717 * dongle.
718 * ARGUMENTS :
719 * RETURN :
720 ******************************************************************************/
722 , vrpn_Connection * p_c
723 , int logical_id
724 , const char * p_port
725 , int p_baud
726 , bool calibrate_gyros_on_setup
727 , bool tare_on_setup
728 , double frames_per_second
729 , double red_LED_color
730 , double green_LED_color
731 , double blue_LED_color
732 , int LED_mode
733 , const char *reset_commands[])
734 : vrpn_YEI_3Space (p_name, p_c, frames_per_second, reset_commands)
735 , d_i_am_first(true)
736 , d_logical_id(-1)
737{
738 // Open the serial port we're going to use to talk with the device.
739 if ((d_serial_fd = vrpn_open_commport(p_port, p_baud,
740 8, vrpn_SER_PARITY_NONE)) == -1) {
741 perror("vrpn_YEI_3Space_Sensor_Wireless::vrpn_YEI_3Space_Sensor_Wireless: Cannot open serial port");
742 fprintf(stderr," (port %s)\n", p_port);
743 }
744#ifdef VERBOSE
745 printf("Serial port opened\n");
746#endif
747
748 // Initialize the dongle state, since we are the first device to connect
749 // to it.
750 if (!configure_dongle()){
751 fprintf(stderr,"vrpn_YEI_3Space_Sensor_Wireless::vrpn_YEI_3Space_Sensor_Wireless: Could not configure dongle\n");
753 d_serial_fd = -1;
754 return;
755 }
756#ifdef VERBOSE
757 printf("Dongle configured\n");
758#endif
759
760 d_logical_id = logical_id;
761
762#ifdef VERBOSE
763 printf("Logical ID set\n");
764#endif
765 // Initialize the state of the device, now that we've established a
766 // way to talk with it.
767 init(calibrate_gyros_on_setup
768 , tare_on_setup, red_LED_color
769 , green_LED_color, blue_LED_color, LED_mode);
770#ifdef VERBOSE
771 printf("Constructor done\n");
772#endif
773}
774
775/******************************************************************************
776 * NAME : vrpn_YEI_3Space_Sensor_Wireless::vrpn_YEI_3Space_Sensor_Wireless
777 * ROLE : This creates a vrpn_YEI_3Space_Sensor_Wireless and sets it to
778 * reset mode. This constructor is for not the first sensor on a
779 * given dongle.
780 * ARGUMENTS :
781 * RETURN :
782 ******************************************************************************/
784 , vrpn_Connection * p_c
785 , int logical_id
786 , int serial_file_descriptor
787 , bool calibrate_gyros_on_setup
788 , bool tare_on_setup
789 , double frames_per_second
790 , double red_LED_color
791 , double green_LED_color
792 , double blue_LED_color
793 , int LED_mode
794 , const char *reset_commands[])
795 : vrpn_YEI_3Space (p_name, p_c, frames_per_second, reset_commands)
796 , d_i_am_first(false)
797 , d_serial_fd(serial_file_descriptor)
798 , d_logical_id(-1)
799{
800 d_logical_id = logical_id;
801
802 // Initialize the state of the device, now that we've established a
803 // way to talk with it.
804 init(calibrate_gyros_on_setup
805 , tare_on_setup, red_LED_color
806 , green_LED_color, blue_LED_color, LED_mode);
807}
808
809/******************************************************************************
810 * NAME : vrpn_YEI_3Space_Sensor_Wireless::~vrpn_YEI_3Space_Sensor_Wireless
811 * ROLE : This destroys a vrpn_YEI_3Space_Sensor_Wireless and closes its ports.
812 * ARGUMENTS :
813 * RETURN :
814 ******************************************************************************/
816{
817 // Ask the device to stop streaming.
818 unsigned char stop_streaming[1] = { 0x56 };
819 if (!send_binary_command(stop_streaming, sizeof(stop_streaming))) {
820 VRPN_MSG_ERROR ("vrpn_YEI_3Space_Sensor_Wireless::~vrpn_YEI_3Space_Sensor_Wireless: Unable to send stop-streaming command\n");
821 }
822
823 // Close com port when destroyed, if I am the first device on the dongle.
824 if (d_i_am_first) if (d_serial_fd != -1) {
826 }
827}
828
829/******************************************************************************
830 * NAME : vrpn_YEI_3Space_Sensor_Wireless::configure_dongle
831 * ROLE : * ARGUMENTS :
832 * RETURN : true on success, false on failure.
833 ******************************************************************************/
834
836{
837 // Configure the wireless streaming mode to manual flush.
838 unsigned char set_mode[2] = { 0xb0, 0 };
839 if (!send_binary_command_to_dongle(set_mode, sizeof(set_mode))) {
840 VRPN_MSG_ERROR ("vrpn_YEI_3Space_Sensor_Wireless::configure_dongle: Unable to send set-streaming-mode command\n");
841 return false;
842 }
843
844 return true;
845}
846
847/******************************************************************************
848 * NAME : vrpn_YEI_3Space_Sensor_Wireless::configure_dongle
849 * ROLE :
850 * ARGUMENTS :
851 * RETURN : true on success, false on failure.
852 ******************************************************************************/
853
854bool vrpn_YEI_3Space_Sensor_Wireless::set_logical_id(vrpn_uint8 logical_id, int serial_number)
855{
856 // Configure logical ID.
857 unsigned char set_id[6] = { 0xd1, 0, 0,0,0,0 };
858 unsigned char *bufptr = &set_id[1];
859 vrpn_int32 buflen = 5;
860 vrpn_buffer(&bufptr, &buflen, logical_id);
861 vrpn_buffer(&bufptr, &buflen, serial_number);
862 if (!send_binary_command_to_dongle(set_id, sizeof(set_id))) {
863 VRPN_MSG_ERROR ("vrpn_YEI_3Space_Sensor_Wireless::set_logical_id: Unable to send set-logical-id command\n");
864 return false;
865 }
866#ifdef VERBOSE
867 printf("... Logical id %d set to serial_number %x\n", logical_id, serial_number);
868#endif
869
870 return true;
871}
872
873/******************************************************************************
874 * NAME : vrpn_YEI_3Space_Sensor_Wireless::send_binary_command_to_dongle
875 * ROLE :
876 * ARGUMENTS : char *cmd : the command to be sent
877 * int len : Length of the command to be sent
878 * RETURN : true on success, false on failure.
879 ******************************************************************************/
880
881// This is the same as the send_binary_command() from the wired interface.
882bool vrpn_YEI_3Space_Sensor_Wireless::send_binary_command_to_dongle (const unsigned char *p_cmd, int p_len)
883{
884 const unsigned char START_OF_PACKET = 0xF7;
885
886 // Compute the checksum. The description of the checksum implies that it should
887 // include the START_OF_PACKET data, but the example provided in page 28 does not
888 // include that data in the checksum, so we only include the packet data here.
889 int checksum = 0;
890 for (int i = 0; i < p_len; i++) {
891 checksum += p_cmd[i];
892 }
893 checksum %= 256;
894
895 // Pack the command into the buffer with the start-of-packet and checksum.
896 unsigned char buffer[256]; // Large enough buffer to hold all possible commands.
897 buffer[0] = START_OF_PACKET;
898 memcpy(&(buffer[1]), p_cmd, p_len);
899 buffer[p_len + 1] = static_cast<unsigned char>(checksum);
900
901 // Send the command and return whether it worked.
902 int l_ret;
903 l_ret = vrpn_write_characters (d_serial_fd, buffer, p_len+2);
904 // Tell if this all worked.
905 if (l_ret == p_len+2) {
906 return true;
907 } else {
908 return false;
909 }
910}
911
912/******************************************************************************
913 * NAME : vrpn_YEI_3Space_Sensor_Wireless::send_binary_command
914 * ROLE :
915 * ARGUMENTS : char *cmd : the command to be sent
916 * int len : Length of the command to be sent
917 * RETURN : true on success, false on failure.
918 ******************************************************************************/
919
920// Info from YEI 3-Space Sensor User's Manual Wireless 2.0 R21 26 March2014
921// http://www.yeitechnology.com/sites/default/files/YEI_3-Space_Sensor_Users_Manual_Wireless_2.0_r21_26Mar2014.pdf
922// Binary-mode wireless command packet format:
923// 0xF8 (start of packet)
924// Logical address
925// Command byte (command value)
926// Command data (0 or more bytes of parameters, in big-endian format)
927// Checksum (sum of all bytes in the packet including the address) % 256
928// NOTE: In the wireless protocol, all commands are acknowledged, so we
929// wait for the response to make sure the command was properly received.
930bool vrpn_YEI_3Space_Sensor_Wireless::send_binary_command (const unsigned char *p_cmd, int p_len)
931{
932 const unsigned char START_OF_PACKET = 0xF8;
933
934 // Pack the command into the buffer with the start-of-packet and checksum.
935 unsigned char buffer[256]; // Large enough buffer to hold all possible commands.
936 buffer[0] = START_OF_PACKET;
937 buffer[1] = d_logical_id;
938 memcpy(&(buffer[2]), p_cmd, p_len);
939
940 // Compute the checksum. The description of the checksum implies that it should
941 // include the START_OF_PACKET data, but the example provided in page 25 does not
942 // include that data in the checksum, so we only include the address and
943 // packet data here.
944 int checksum = 0;
945 for (int i = 0; i < p_len+1; i++) {
946 checksum += buffer[1 + i];
947 }
948 checksum %= 256;
949 buffer[p_len + 2] = static_cast<unsigned char>(checksum);
950
951 // Send the command.
952 int l_ret;
953 l_ret = vrpn_write_characters (d_serial_fd, buffer, p_len+3);
954 if (l_ret != p_len+3) {
955 fprintf(stderr, "vrpn_YEI_3Space_Sensor_Wireless::send_binary_command: Could not send command\n");
956 return false;
957 }
958#ifdef VERBOSE
959 printf("... packet of length %d sent\n", l_ret);
960#endif
961
962 // Listen for a response telling whether the command was received.
963 // We do not listen for the data returned by the command, but only
964 // check the header on the return to make sure the command was a
965 // success. The caller should separately look for any requested
966 // data.
967 struct timeval timeout;
968 timeout.tv_sec = 0;
969 timeout.tv_usec = 500000;
970 int ret = vrpn_read_available_characters(d_serial_fd, buffer, 3, &timeout);
971 if (ret == 2) {
972 fprintf(stderr, "vrpn_YEI_3Space_Sensor_Wireless::send_binary_command: Error (%d) from ID %d\n", buffer[0], buffer[1]);
973 return false;
974 } else if (ret != 3) {
975 fprintf(stderr, "vrpn_YEI_3Space_Sensor_Wireless::send_binary_command: Timeout waiting for command status (got %d chars)\n", ret);
976 return false;
977 }
978 if (buffer[0] != 0) {
979 fprintf(stderr, "vrpn_YEI_3Space_Sensor_Wireless::send_binary_command: Command failed\n");
980 return false;
981 }
982 if (buffer[1] != d_logical_id) {
983 fprintf(stderr, "vrpn_YEI_3Space_Sensor_Wireless::send_binary_command: Got response for incorrect logical ID\n");
984 return false;
985 }
986#ifdef VERBOSE
987 printf("..... send succeded\n");
988#endif
989
990 return true;
991}
992
993/******************************************************************************
994 * NAME : vrpn_YEI_3Space_Sensor_Wireless::send_ascii_command
995 * ROLE :
996 * ARGUMENTS : char *cmd : the command to be sent
997 * RETURN : true on success, false on failure.
998 ******************************************************************************/
999
1000// Info from YEI 3-Space Sensor User's Manual Wireless 2.0 R21 26 March2014
1001// http://www.yeitechnology.com/sites/default/files/YEI_3-Space_Sensor_Users_Manual_Wireless_2.0_r21_26Mar2014.pdf
1002// Ascii-mode command packet format:
1003// '>' (start of packet)
1004// ',' and then logical ID (decimal)
1005// ',' and then data Command value (decimal)
1006// ',' Command data (0 or more bytes of parameters
1007// '\n'
1008// NOTE: In the wireless protocol, all commands are acknowledged, so we
1009// wait for the response to make sure the command was properly received.
1011{
1012 // Check to make sure we have a non-empty command
1013 if (strlen(p_cmd) == 0) {
1014 return false;
1015 }
1016
1017 // Allocate space for the longest command plus padding and zero terminator
1018 char buffer[256];
1019
1020 // Fill in the command
1021 sprintf(buffer, ">%d,%s\n", d_logical_id, p_cmd);
1022
1023 // Send the command and see if it worked.
1024 int buflen = static_cast<int>(strlen(buffer) + 1);
1025 unsigned char *bufptr = static_cast<unsigned char *>(
1026 static_cast<void*>(buffer));
1027 int l_ret = vrpn_write_characters(d_serial_fd, bufptr, buflen);
1028
1029 // Tell if sending worked.
1030 if (l_ret != buflen) {
1031 fprintf(stderr, "vrpn_YEI_3Space_Sensor_Wireless::send_ascii_command: Error sending command\n");
1032 return false;
1033 }
1034
1035 // Listen for a response telling whether the command was received.
1036 // We parse the entire ASCII command response, including the \n at
1037 // the end, since we aren't programmatically handling any of these
1038 // in the driver but only letting the user specify them in the
1039 // reset routine.
1040 struct timeval timeout;
1041 timeout.tv_sec = 0;
1042 timeout.tv_usec = 500000;
1043 int ret;
1044 if ((ret = vrpn_read_available_characters(d_serial_fd, bufptr, sizeof(buffer)-1, &timeout)) <= 0) {
1045 fprintf(stderr, "vrpn_YEI_3Space_Sensor_Wireless::send_ascii_command: Timeout waiting for command status\n");
1046 return false;
1047 }
1048 buffer[ret] = '\0';
1049 if (buffer[0] != '0') {
1050 fprintf(stderr, "vrpn_YEI_3Space_Sensor_Wireless::send_ascii_command: Command failed: response (%s)\n", buffer);
1051 return false;
1052 }
1053 if (buffer[strlen(buffer)-1] != '\n') {
1054 fprintf(stderr, "vrpn_YEI_3Space_Sensor_Wireless::send_ascii_command: Got ill-formatted response: (%s).\n", buffer);
1055 return false;
1056 }
1057
1058 return true;
1059}
1060
1061/******************************************************************************
1062 * NAME : vrpn_YEI_3Space_Sensor_Wireless::receive_LED_mode_response
1063 * ROLE :
1064 * ARGUMENTS : struct timeval *timeout; how long to wait, NULL for forever
1065 * RETURN : true on success, false on failure.
1066 ******************************************************************************/
1067
1068// Info from YEI 3-Space Sensor User's Manual Wireless 2.0 R21 26 March2014
1069// http://www.yeitechnology.com/sites/default/files/YEI_3-Space_Sensor_Users_Manual_Wireless_2.0_r21_26Mar2014.pdf
1070// Binary-mode command packet format:
1071// Single byte: value 0 or 1.
1073{
1074 unsigned char value;
1075 int ret = vrpn_read_available_characters (d_serial_fd, &value, sizeof(value), timeout);
1076 if (ret != sizeof(value)) {
1077 return false;
1078 }
1079 d_LED_mode = value;
1080 return true;
1081}
1082
1083/******************************************************************************
1084 * NAME : vrpn_YEI_3Space_Sensor_Wireless::receive_LED_values_response
1085 * ROLE :
1086 * ARGUMENTS : struct timeval *timeout; how long to wait, NULL for forever
1087 * RETURN : true on success, false on failure.
1088 ******************************************************************************/
1089
1090// Info from YEI 3-Space Sensor User's Manual Wireless 2.0 R21 26 March2014
1091// http://www.yeitechnology.com/sites/default/files/YEI_3-Space_Sensor_Users_Manual_Wireless_2.0_r21_26Mar2014.pdf
1092// Binary-mode command packet format:
1093// Three four-byte float responses, each big-endian.
1095{
1096 unsigned char buffer[3*sizeof(vrpn_float32)];
1097 int ret = vrpn_read_available_characters (d_serial_fd, buffer, sizeof(buffer), timeout);
1098 if (ret != sizeof(buffer)) {
1099 return false;
1100 }
1101 vrpn_float32 value;
1102 unsigned char *bufptr = buffer;
1103 vrpn_unbuffer(&bufptr, &value);
1104 d_LED_color[0] = value;
1105 vrpn_unbuffer(&bufptr, &value);
1106 d_LED_color[1] = value;
1107 vrpn_unbuffer(&bufptr, &value);
1108 d_LED_color[2] = value;
1109 return true;
1110}
1111
1112/******************************************************************************
1113 * NAME : vrpn_YEI_3Space_Sensor_Wireless::get_report
1114 * ROLE : This function will read characters until it has a full report, then
1115 * call handle_report() with the report and clear the counts. For the
1116 * wireless protocol, we need to manually request release of streaming
1117 * characters from our logical ID before checking to see if there are
1118 * any.
1119 * ARGUMENTS : void
1120 * RETURN : bool: Did we get a complete report?
1121 ******************************************************************************/
1123{
1124 int l_ret; // Return value from function call to be checked
1125
1126 //--------------------------------------------------------------------
1127 // Request release of pending reports from our ID.
1128 unsigned char release_report[2] = { 0xB4, 0 };
1129 release_report[1] = d_logical_id;
1130 if (!send_binary_command_to_dongle(release_report, sizeof(release_report))) {
1131 VRPN_MSG_ERROR ("vrpn_YEI_3Space::get_report: Unable to send release-report command\n");
1132 return false;
1133 }
1134
1135 //--------------------------------------------------------------------
1136 // Read a report if it is available.
1137 struct timeval timeout;
1138 timeout.tv_sec = 0;
1139 timeout.tv_usec = 1000;
1141 REPORT_LENGTH + 3,
1142 &timeout);
1143 if (l_ret == -1) {
1144 VRPN_MSG_ERROR ("vrpn_YEI_3Space_Sensor_Wireless::get_report(): Error reading the sensor, resetting");
1146 return false;
1147 }
1148#ifdef VERBOSE
1149 if (l_ret != 0) printf("... got %d characters\n",l_ret);
1150#endif
1151 // If we didn't get any reports, we're done and will look again next time.
1152 if (l_ret == 0) {
1153 return false;
1154 }
1155
1156 // Check to be sure that the length was what we expect, we got no errors
1157 // (first header byte 0) and the response is from the correct device.
1158 if (l_ret != REPORT_LENGTH + 3) {
1159 VRPN_MSG_ERROR ("vrpn_YEI_3Space_Sensor_Wireless::get_report(): Truncated report, resetting");
1161 return false;
1162 }
1163 if (d_buffer[0] != 0) {
1164 VRPN_MSG_ERROR ("vrpn_YEI_3Space_Sensor_Wireless::get_report(): Error reported, resetting");
1166 return false;
1167 }
1168 if (d_buffer[1] != d_logical_id) {
1169 VRPN_MSG_ERROR ("vrpn_YEI_3Space_Sensor_Wireless::get_report(): Report from wrong sensor received, resetting");
1171 return false;
1172 }
1173
1174 //--------------------------------------------------------------------
1175 // Parse and handle the report.
1178 return true;
1179}
1180
vrpn_int32 getNumChannels(void) const
Definition vrpn_Analog.C:52
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition vrpn_Analog.h:38
struct timeval timestamp
Definition vrpn_Analog.h:41
vrpn_int32 num_channel
Definition vrpn_Analog.h:40
virtual void report(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY, const struct timeval time=vrpn_ANALOG_NOW)
Send a report whether something has changed or not (for servers) Optionally, tell what time to stamp ...
Definition vrpn_Analog.C:94
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
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
virtual int init(void)
Initialize things that the constructor can't. Returns 0 on success, -1 on failure.
All button servers should derive from this class, which provides the ability to turn any of the butto...
Definition vrpn_Button.h:66
virtual void report_changes(void)
vrpn_int32 num_buttons
Definition vrpn_Button.h:48
struct timeval timestamp
Definition vrpn_Button.h:49
virtual void report_changes(void)
unsigned char lastbuttons[vrpn_BUTTON_MAX_BUTTONS]
Definition vrpn_Button.h:46
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition vrpn_Button.h:45
Generic connection class not specific to the transport mechanism.
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 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.
vrpn_float64 acc_quat[4]
vrpn_float64 pos[3]
vrpn_float64 acc[3]
virtual bool set_logical_id(vrpn_uint8 logical_id, vrpn_int32 serial_number)
Insert our serial number into the specified slot.
bool receive_LED_values_response(struct timeval *timeout=NULL)
Read and parse the response to an LED-values request command. NULL timeout pointer means wait forever...
bool send_ascii_command(const char *cmd)
Put a ':' character at the front and ' ' at the end and then send the resulting command as an ASCII c...
virtual bool configure_dongle(void)
Configure the dongle (called if we are the first one)
bool receive_LED_mode_response(struct timeval *timeout=NULL)
Read and parse the response to an LED-state request command. NULL timeout pointer means wait forever....
virtual ~vrpn_YEI_3Space_Sensor_Wireless()
Destructor.
vrpn_YEI_3Space_Sensor_Wireless(const char *name, vrpn_Connection *c, int logical_id, const char *port, int baud=115200, bool calibrate_gyros_on_setup=false, bool tare_on_setup=false, double frames_per_second=50, double red_LED_color=0, double green_LED_color=0, double blue_LED_color=0, int LED_mode=1, const char *reset_commands[]=NULL)
Constructor for the first device, which will open the serial port and configure the dongle.
virtual void flush_input(void)
Flush any incoming characters in the communications channel.
virtual bool get_report(void)
Get and handle a report from the device if one is available. Return true if one was available,...
bool send_binary_command(const unsigned char *cmd, int len)
Compute the CRC for the message, append it, and send message. Returns true on success,...
bool send_binary_command_to_dongle(const unsigned char *cmd, int len)
Compute the CRC for the message, append it, and send message to the dongle directly (not a wireless c...
bool receive_LED_values_response(struct timeval *timeout=NULL)
Read and parse the response to an LED-values request command. NULL timeout pointer means wait forever...
virtual bool get_report(void)
virtual void flush_input(void)
Flush any incoming characters in the communications channel.
bool receive_LED_mode_response(struct timeval *timeout=NULL)
Read and parse the response to an LED-state request command. NULL timeout pointer means wait forever....
bool send_ascii_command(const char *cmd)
Put a ':' character at the front and ' ' at the end and then send the resulting command as an ASCII c...
virtual ~vrpn_YEI_3Space_Sensor()
Destructor.
bool send_binary_command(const unsigned char *cmd, int len)
Compute the CRC for the message, append it, and send message. Returns true on success,...
vrpn_YEI_3Space_Sensor(const char *name, vrpn_Connection *c, const char *port, int baud=115200, bool calibrate_gyros_on_setup=false, bool tare_on_setup=false, double frames_per_second=50, double red_LED_color=0, double green_LED_color=0, double blue_LED_color=0, int LED_mode=1, const char *reset_commands[]=NULL)
Constructor.
Base class with routines for YEI 3Space units.
virtual bool receive_LED_values_response(struct timeval *timeout=NULL)=0
Read and parse the response to an LED-values request command. NULL timeout pointer means wait forever...
virtual void handle_report(unsigned char *report)
vrpn_float32 d_LED_color[3]
virtual void report(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY)
send report whether or not changed
struct timeval timestamp
virtual void mainloop()
Called once through each main loop iteration to handle updates.
vrpn_YEI_3Space(const char *name, vrpn_Connection *c, double frames_per_second=50, const char *reset_commands[]=NULL)
Constructor.
virtual bool receive_LED_mode_response(struct timeval *timeout=NULL)=0
Read and parse the response to an LED-state request command. NULL timeout pointer means wait forever....
virtual bool get_report(void)=0
virtual bool send_ascii_command(const char *cmd)=0
Put a ':' character at the front and ' ' at the end and then send the resulting command as an ASCII c...
unsigned d_expected_characters
virtual int reset(void)
unsigned d_characters_read
virtual void flush_input(void)=0
Flush any incoming characters in the communications channel.
virtual ~vrpn_YEI_3Space()
Destructor.
virtual bool send_binary_command(const unsigned char *cmd, int len)=0
Compute the CRC for the message, append it, and send message. Returns true on success,...
unsigned char d_buffer[128]
#define MAX_TIME_INTERVAL
#define STATUS_READING
#define STATUS_RESETTING
Header containing macros formerly duplicated in a lot of implementation files.
#define VRPN_MSG_ERROR(msg)
int vrpn_write_characters(int comm, const unsigned char *buffer, size_t bytes)
Write the buffer to the serial port.
int vrpn_close_commport(int comm)
int vrpn_flush_input_buffer(int comm)
Throw out any characters within the input buffer.
int vrpn_read_available_characters(int comm, unsigned char *buffer, size_t bytes)
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_SER_PARITY_NONE
Definition vrpn_Serial.h:16
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.
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_SleepMsecs(double dMilliSecs)
#define vrpn_gettimeofday
Definition vrpn_Shared.h:99
#define STATUS_NOT_INITIALIZED