vrpn 07.35
Virtual Reality Peripheral Network
Loading...
Searching...
No Matches
vrpn_5DT16.C
Go to the documentation of this file.
1// This is a driver for the 5dt Data Glove 16 sensors
2// Look at www.5dt.com for more informations about this product
3// Manuals are avalaible freely from this site
4// The original code for 5dt was written by Philippe DAVID with the help of Yves GAUVIN
5// This version for the 16 sensor version was written by Tom De Weyer
6// naming convention used in this file:
7// l_ is the prefixe for local variables
8// g_ is the prefixe for global variables
9// p_ is the prefixe for parameters
10
11#include <stdio.h> // for sprintf, fprintf, stderr
12
13#include "vrpn_5DT16.h"
14#include "vrpn_BaseClass.h" // for ::vrpn_TEXT_ERROR, etc
15#include "vrpn_Serial.h"
16#include "vrpn_Shared.h" // for timeval, vrpn_SleepMsecs, etc
17#include "vrpn_MessageMacros.h" // for VRPN_MSG_INFO, VRPN_MSG_WARNING, VRPN_MSG_ERROR
18
19#undef VERBOSE
20
21// Defines the modes in which the device can find itself.
22#define STATUS_RESETTING (-1) // Resetting the device
23#define STATUS_SYNCING (0) // Looking for the first character of report
24#define STATUS_READING (1) // Looking for the rest of the report
25
26#define MAX_TIME_INTERVAL (2000000) // max time between reports (usec)
27
28
29/******************************************************************************
30 * NAME : vrpn_5dt16::vrpn_5dt16
31 * ROLE : This creates a vrpn_5dt16 and sets it to reset mode. It opens
32 * the serial device using the code in the vrpn_Serial_Analog constructor.
33 * ARGUMENTS :
34 * RETURN :
35 ******************************************************************************/
36vrpn_5dt16::vrpn_5dt16 (const char * p_name, vrpn_Connection * p_c, const char * p_port, int p_baud):
37 vrpn_Serial_Analog (p_name, p_c, p_port, p_baud, 8, vrpn_SER_PARITY_NONE),
38 _numchannels (17) // This is an estimate; will change when reports come
39{
40 // Set the parameters in the parent classes
42
43 vrpn_gettimeofday(&timestamp, NULL); // Set watchdog now
44
45 // Set the status of the buttons and analogs to 0 to start
47
48 // Set the mode to reset
50}
51
52
53/******************************************************************************
54 * NAME : vrpn_5dt16::clear_values
55 * ROLE :
56 * ARGUMENTS :
57 * RETURN :
58 ******************************************************************************/
60{
61 int i;
62
63 for (i = 0; i < _numchannels; i++) {
65 }
66}
67
68
69/******************************************************************************
70 * NAME : vrpn_5dt16::reset
71 * ROLE : This routine will reset the 5DT
72 * ARGUMENTS :
73 * RETURN : 0 else -1 in case of error
74 ******************************************************************************/
76{
77 unsigned char l_inbuf [45];
78 int l_ret;
79 bool found=false;
80 struct timeval start, now;
81
82 vrpn_gettimeofday(&start, NULL);
83 while(!found) // read the begin sequence of an info packet "<I"
84 {
85 l_ret = vrpn_read_available_characters (serial_fd, l_inbuf, 1);
86 if(l_ret!=1) {
87 vrpn_SleepMsecs (100); //Give it time to send data
88 } else if(l_inbuf[0] == '<' ) {
89 while(!vrpn_read_available_characters (serial_fd, l_inbuf, 1)) {
90 vrpn_SleepMsecs (100); //Give it time to send data
91 }
92 if(l_inbuf[0]=='I') {
93 found=true;
94 }
95 }
96 // See if we've timed out on the reset
97 vrpn_gettimeofday(&now, NULL);
98 if (now.tv_sec > start.tv_sec + 2) {
99 fprintf(stderr,"vrpn_5dt16::reset(): Timeout during reset\n");
100 return -1;
101 }
102 }
103 vrpn_SleepMsecs (100); //Give it time to send data
104 l_ret=vrpn_read_available_characters (serial_fd, l_inbuf, 5); // read the rest of the data
105 char text[50];
106 sprintf(text,"Hardware Version %i.0%i",l_inbuf[0],l_inbuf[1]); // hardware version
107 VRPN_MSG_WARNING(text);
108 if (l_inbuf[2] & 1) //right or left glove
109 {
110 VRPN_MSG_WARNING ("A right glove is ready");
111 } else {
112 VRPN_MSG_WARNING ("A left glove is ready");
113 }
114 if (l_inbuf[3] & 1) //wireless glove or wired
115 {
116 VRPN_MSG_WARNING ("no wireless glove");
117 } else {
118 VRPN_MSG_WARNING ("wireless glove");
119 }
120
121 // We're now entering the syncing mode which send the read command to the glove
123 _bufcount = 0;
124
125 vrpn_gettimeofday (&timestamp, NULL); // Set watchdog now
126 return 0;
127}
128
129/******************************************************************************
130 * NAME : vrpn_5dt16::get_report
131 * ROLE : This function will read characters until it has a full report, then
132 * put that report into analog fields and call the report methods on these.
133 * ARGUMENTS : void
134 * RETURN : void
135 ******************************************************************************/
137{
138 int l_ret; // Return value from function call to be checked
139
140 // The official doc (http://www.5dt.com/downloads/5DTDataGlove5Manual.pdf)
141 // says we should get 36 bytes, but once in a while an info packet arrives and we should
142 // ignore that packet.
143 _expected_chars = 36;
144
145 //--------------------------------------------------------------------
146 // Read as many bytes of this report as we can, storing them
147 // in the buffer. We keep track of how many have been read so far
148 // and only try to read the rest.
149 //--------------------------------------------------------------------
150
153 if (l_ret == -1) {
154 VRPN_MSG_ERROR ("Error reading the glove");
156 return;
157 }
158#ifdef VERBOSE
159 if (l_ret != 0) printf("... got %d characters (%d total)\n",l_ret, _bufcount);
160#endif
161
162 //--------------------------------------------------------------------
163 // The time of the report is the time at which the first character for
164 // the report is read.
165 //--------------------------------------------------------------------
166
167 if ( (l_ret > 0) && (_bufcount == 0) ) {
169 }
170
171 //--------------------------------------------------------------------
172 // We keep track of how many characters we have received and keep
173 // going back until we get as many as we expect.
174 //--------------------------------------------------------------------
175
176 _bufcount += l_ret;
177 if (_bufcount < _expected_chars) { // Not done -- go back for more
178 return;
179 }
180
181 //--------------------------------------------------------------------
182 // We now have enough characters to make a full report. First check to
183 // make sure that the first one is what we expect.
184
185 if (!( (_buffer[0] == '<') && (_buffer[1] == 'D') ) ) //first characters need to be <D
186 {
187 VRPN_MSG_INFO ("Unexpected first character in report, probably info packet (recovering)");
188 for(int i=0;i<29;i++) {
189 _buffer[i]=_buffer[i+7];
190 }
191 _bufcount=29;
192 return;
193 }
194
195#ifdef VERBOSE
196 printf ("Got a complete report (%d of %d)!\n", _bufcount, _expected_chars);
197#endif
198
199 //--------------------------------------------------------------------
200 // Decode the report and store the values in it into the analog values
201 // if appropriate.
202 //--------------------------------------------------------------------
203
204 for(int i=0;i<16;i++) {
205 channel[i]=_buffer[i*2+2]*256+_buffer[i*2+3];
206 }
207 char text[512];
208
209 sprintf(text,"original %f|%f|%f|%f|%f|%f|%f|%f|%f|%f|%f|%f|%f|%f|%f|%f\n",channel[0],channel[1],channel[2],channel[3],channel[4],
210 channel[5],channel[6],channel[7],channel[8],channel[9],
211 channel[10],channel[11],channel[12],channel[13],channel[14],
212 channel[15]);
213 VRPN_MSG_ERROR(text);
214
215 //--------------------------------------------------------------------
216 // Done with the decoding, send the reports and go back to syncing
217 //--------------------------------------------------------------------
218
220 _bufcount =0;
221}
222
223
224/******************************************************************************
225 * NAME : vrpn_5dt16::report_changes
226 * ROLE :
227 * ARGUMENTS :
228 * RETURN : void
229 ******************************************************************************/
230void vrpn_5dt16::report_changes (vrpn_uint32 class_of_service)
231{
233 vrpn_Analog::report_changes(class_of_service);
234}
235
236
237/******************************************************************************
238 * NAME : vrpn_5dt16::report
239 * ROLE :
240 * ARGUMENTS :
241 * RETURN : void
242 ******************************************************************************/
243void vrpn_5dt16::report (vrpn_uint32 class_of_service)
244{
246 vrpn_Analog::report(class_of_service);
247}
248
249
250/******************************************************************************
251 * NAME : vrpn_5dt16::mainloop
252 * ROLE : This routine is called each time through the server's main loop. It will
253 * take a course of action depending on the current status of the device,
254 * either trying to reset it or trying to get a reading from it. It will
255 * try to reset the device if no data has come from it for a couple of
256 * seconds
257 * ARGUMENTS :
258 * RETURN : void
259 ******************************************************************************/
261{
262 char l_errmsg[256];
263
265
266 switch (_status) {
267 case STATUS_RESETTING:
268 if (reset()== -1)
269 {
270 VRPN_MSG_ERROR ("vrpn_Analog_5dt: Cannot reset the glove!");
271 }
272 break;
273
274 case STATUS_READING:
275 {
276 // It turns out to be important to get the report before checking
277 // to see if it has been too long since the last report. This is
278 // because there is the possibility that some other device running
279 // in the same server may have taken a long time on its last pass
280 // through mainloop(). Trackers that are resetting do this. When
281 // this happens, you can get an infinite loop -- where one tracker
282 // resets and causes the other to timeout, and then it returns the
283 // favor. By checking for the report here, we reset the timestamp
284 // if there is a report ready (ie, if THIS device is still operating).
285 get_report();
286 struct timeval current_time;
287 vrpn_gettimeofday(&current_time, NULL);
289 {
290 sprintf (l_errmsg, "vrpn_5dt16::mainloop: Timeout... current_time=%ld:%ld, timestamp=%ld:%ld",
291 current_time.tv_sec,
292 static_cast<long>(current_time.tv_usec),
293 timestamp.tv_sec,
294 static_cast<long>(timestamp.tv_usec));
295 VRPN_MSG_ERROR (l_errmsg);
297 }
298 }
299 break;
300
301 default:
302 VRPN_MSG_ERROR ("vrpn_5dt16::mainloop: Unknown mode (internal error)");
303 break;
304 }
305}
306
307vrpn_Button_5DT_Server::vrpn_Button_5DT_Server(const char *name, const char *deviceName,vrpn_Connection *c, double threshold[16]) : vrpn_Button_Filter(name, c)
308{
309 num_buttons = 16;
310 for(int i=0;i<num_buttons;i++) {
311 m_threshold[i]=threshold[i];
312 }
313 d_5dt_button = NULL;
315#ifdef VERBOSE
316 printf("vrpn_Button_5DT_Server: Adding local analog %s\n",name);
317#endif
318 // Set up the callback handler for the channel
320}
321
323{
324}
325
326// This routine handles updates of the analog values. The value coming in is
327// adjusted per the parameters in the full axis description, and then used to
328// update the value there. The value is used by the matrix-generation code in
329// mainloop() to update the transformations; that work is not done here.
330
332{
334 for(int i=0;i<16;i++) { // adjust with range and center value
335 if(info.channel[i]>full->m_threshold[i] ) {
336 full->buttons[i]=true;
337 } else {
338 full->buttons[i]=false;
339 }
340 }
341}
342
344{
345 struct timeval current_time;
346
347 // Call the generic server mainloop, since we are a server
349
351
352 vrpn_gettimeofday(&current_time, NULL);
353 // Send reports. Stays the same in a real server.
355}
356
vrpn_5dt16(const char *name, vrpn_Connection *c, const char *port, int baud=19200)
Definition: vrpn_5DT16.C:36
virtual void get_report(void)
Definition: vrpn_5DT16.C:136
virtual int reset(void)
Definition: vrpn_5DT16.C:75
unsigned _expected_chars
Definition: vrpn_5DT16.h:31
int _status
Definition: vrpn_5DT16.h:28
virtual void mainloop()
Called once through each main loop iteration to handle updates.
Definition: vrpn_5DT16.C:260
virtual void report_changes(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY)
send report iff changed
Definition: vrpn_5DT16.C:230
unsigned _bufcount
Definition: vrpn_5DT16.h:33
unsigned char _buffer[512]
Definition: vrpn_5DT16.h:32
struct timeval timestamp
Definition: vrpn_5DT16.h:35
int _numchannels
Definition: vrpn_5DT16.h:29
virtual void report(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY)
send report whether or not changed
Definition: vrpn_5DT16.C:243
virtual void clear_values(void)
Definition: vrpn_5DT16.C:59
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_Analog.C:327
virtual int register_change_handler(void *userdata, vrpn_ANALOGCHANGEHANDLER handler)
Definition: vrpn_Analog.h:192
vrpn_float64 last[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog.h:39
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
vrpn_Connection * d_connection
Connection that this object talks to.
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
vrpn_Button_5DT_Server(const char *name, const char *deviceName, vrpn_Connection *c, double threshold[16])
Definition: vrpn_5DT16.C:307
vrpn_Analog_Remote * d_5dt_button
Definition: vrpn_5DT16.h:70
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_5DT16.C:343
static void VRPN_CALLBACK handle_analog_update(void *userdata, const vrpn_ANALOGCB info)
Definition: vrpn_5DT16.C:331
double m_threshold[16]
Definition: vrpn_5DT16.h:71
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)
Definition: vrpn_Button.C:383
vrpn_int32 num_buttons
Definition: vrpn_Button.h:48
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:45
Generic connection class not specific to the transport mechanism.
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog.h:171
#define MAX_TIME_INTERVAL
#define STATUS_READING
#define STATUS_RESETTING
All types of client/server/peer objects in VRPN should be derived from the vrpn_BaseClass type descri...
Header containing macros formerly duplicated in a lot of implementation files.
#define VRPN_MSG_INFO(msg)
#define VRPN_MSG_ERROR(msg)
#define VRPN_MSG_WARNING(msg)
int vrpn_read_available_characters(int comm, unsigned char *buffer, size_t bytes)
Definition: vrpn_Serial.C:515
vrpn_Serial: Pulls all the serial port routines into one file to make porting to new operating system...
@ vrpn_SER_PARITY_NONE
Definition: vrpn_Serial.h:16
unsigned long vrpn_TimevalDuration(struct timeval endT, struct timeval startT)
Return number of microseconds between startT and endT.
Definition: vrpn_Shared.C:138
void vrpn_SleepMsecs(double dMilliSecs)
Definition: vrpn_Shared.C:166
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:99