-
Notifications
You must be signed in to change notification settings - Fork 1
/
vrpn_Dyna.C
297 lines (243 loc) · 8.82 KB
/
vrpn_Dyna.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
/* Modification to make it work with the SeerReal D4D Headtracker,
needs to send "0" instead of "V" to set it to continuous mode.
Untested if this still works with the Dynasight Tracker.*/
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#include <stdio.h>
#include <string.h>
#include "vrpn_Dyna.h"
#include "vrpn_Serial.h"
#define T_ERROR (-1)
#define T_OK (0)
/* return codes for status check */
#define T_PDYN_SPEW_MODE (-50)
#define T_PDYN_NO_DATA (-51)
#define lOOO_OOOO (0x80)
#define llll_OOOO (0xf0)
#define OOOO_OOll (0x03)
#define OOOO_llOO (0x0c)
vrpn_Tracker_Dyna::vrpn_Tracker_Dyna(
char *name, vrpn_Connection *c, int cSensors,
const char *port, long baud ) :
vrpn_Tracker_Serial(name,c,port,baud), cSensors(cSensors), cResets(0)
{
if (cSensors>MAX_SENSORS) {
fprintf(stderr, "\nvrpn_Tracker_Dyna: too many sensors requested ... only %d allowed (%d specified)", MAX_SENSORS, cSensors );
cSensors = MAX_SENSORS;
}
fprintf(stderr, "\nvrpn_Tracker_Dyna: starting up ...");
d_sensor = 0 ; // sensor id is always 0 (first sensor is 0);
}
vrpn_Tracker_Dyna::~vrpn_Tracker_Dyna() {
fprintf(stderr, "vrpn_Tracker_Dyna:Shutting down...\n");
}
int vrpn_Tracker_Dyna::get_status()
{
int bytesRead;
unsigned char statusBuffer[256];
my_flush();
/* send request for status record */
vrpn_write_characters(serial_fd,(const unsigned char *) "\021", 1);
vrpn_drain_output_buffer(serial_fd);
vrpn_SleepMsecs(1000.0*2);
/* do non-blocking read of status record */
bytesRead = vrpn_read_available_characters(serial_fd, statusBuffer, 8);
// T_PDYN_STATUS_RECORD_LENGTH =8;
if ( bytesRead == 8 )
{
/* we have correct length- check a few chars to make sure this is a valid
* record
*/
if ( ((statusBuffer[0] & lOOO_OOOO) != lOOO_OOOO) ||
((statusBuffer[1] & lOOO_OOOO) != lOOO_OOOO) )
return(T_ERROR);
/* otherwise, all is well */
return(T_OK);
}
/* if we get here, we either got too much data or not enough */
/* no data means it's probably disconnected or not turned on */
if ( bytesRead == 0 )
{
// fprintf(stderr, "No data\n");
return(T_PDYN_NO_DATA);
}
/* if we got too much data, chances are that it's in continuous mode */
if ( bytesRead > 8)
{
fprintf(stderr, "3\n");
return(T_PDYN_SPEW_MODE);
}
/* if we get here, i have no idea what's going on- could be garbage on the
* serial line, wrong baud rate, or that the Dynasight is flaking out.
*/
return(T_ERROR);
} /* t_pdyn_get_status */
#define MAX_TRIAL 10
void vrpn_Tracker_Dyna::reset() {
//static int numResets = 0; // How many resets have we tried?;
static char T_PDYN_C_CTL_C[4] ="\003\003\003";
static int T_PDYN_RECORD_LENGTH = 8;
vrpn_write_characters(serial_fd, (unsigned char*)T_PDYN_C_CTL_C, strlen(T_PDYN_C_CTL_C));
vrpn_write_characters(serial_fd,(const unsigned char *) "4", 1); // set to polling mode;
/* pause 1 second to allow the Dynasight buffer to stabilize */
vrpn_SleepMsecs(1000.0*1);
status = get_status();
if ( status != T_OK ) {
/* if no data, tracker probably not connected. just bag it. */
if ( status == T_PDYN_NO_DATA )
{
fprintf(stderr, "vrpn_Tracker_Dyna::reset(): no data (is tracker turned on?)\n");
status = vrpn_TRACKER_RESETTING;
return;
}
}else {
fprintf(stderr, "vrpn_Tracker_Dyna: return valid status report\n");
reportLength = T_PDYN_RECORD_LENGTH;
// set it to continues mode;
/* clear any leftover data */
my_flush();
/* set the Dynasight to continuous mode */
vrpn_write_characters(serial_fd, (unsigned char*)T_PDYN_C_CTL_C, strlen(T_PDYN_C_CTL_C));
//vrpn_write_characters(serial_fd, (const unsigned char *)"V", 1);
vrpn_write_characters(serial_fd, (const unsigned char *)"0", 1);
//T_PDYN_C_CONTINUOUS = "V"
vrpn_SleepMsecs(1000.0*1);
//vrpn_gettimeofday(×tamp, NULL); // Set watchdog now;
timestamp.tv_sec = -1;
status = vrpn_TRACKER_SYNCING; // We are trying for a new reading;
return;
}
}
int vrpn_Tracker_Dyna::get_report(void) {
int ret;
if (status == vrpn_TRACKER_SYNCING) {
if ((ret=vrpn_read_available_characters(serial_fd, buffer, 1)) != 1 ||
(buffer[0] & llll_OOOO) != lOOO_OOOO) {
return 0;
}
vrpn_gettimeofday(×tamp, NULL);
status = vrpn_TRACKER_PARTIAL;
bufcount= ret;
}
if (status == vrpn_TRACKER_PARTIAL) {
ret=vrpn_read_available_characters(serial_fd, &(buffer[bufcount]),
reportLength-bufcount);
if (ret < 0) {
fprintf(stderr,"%s@%d: Error reading\n", __FILE__, __LINE__);
status = vrpn_TRACKER_FAIL;
return 0;
}
bufcount += ret;
if (bufcount < reportLength) { // Not done -- go back for more
return 0;
}
}
if (!valid_report()) {
//fprintf(stderr,"no valid report");
bufcount = 0;
status = vrpn_TRACKER_SYNCING;
return 0;
}
//else fprintf(stderr,"got valid report");
decode_record();
status = vrpn_TRACKER_SYNCING;
bufcount=0;
return 1;
}
int vrpn_Tracker_Dyna::valid_report() {
/* Check to see that the first four bits of the *
* first two bytes correspond to 1000. */
if ( ( (buffer[0] & llll_OOOO) != lOOO_OOOO) ||
( (buffer[1] & llll_OOOO) != lOOO_OOOO) )
return (0);
/* Make sure no other consecutive bytes have 1000 in the high nibble */
for (unsigned i = 2; i <reportLength-1; i += 2)
{
if ( ( (buffer[i] & llll_OOOO) == lOOO_OOOO) &&
( (buffer[i+1] & llll_OOOO) == lOOO_OOOO))
{
fprintf(stderr,
"vrpn_Tracker_Dyna: found two more status bytes in the Dynasight's output list\n");
return (0);
}
}
/* Next, check that the Dynasight is tracking or in caution mode. If *
* it is not, then we can't be sure of what data is being sent back, *
* copy the most recent tracked data into the buffer. */
if ( ( (buffer[1] & OOOO_OOll) == 0 ) ||
( (buffer[1] & OOOO_OOll) == 1 ) )
{
return (1);
}
/* Also, for this passive Dynasight mode, we want to make sure that we *
* only getting records from the single (00) sensor, not any active *
* sensors. */
if ( (buffer[0] & OOOO_llOO) != 0)
{
fprintf(stderr, "trackerlib: Invalid target number for passive Dynasight\n");
return (0);
}
/* If we've made it this far, we have a target that is being tracked, *
* and it is the correct target. So, copy this into the *
* lastTrackedData array.
for (i = 0; i < trackerPtr->reportLength; i++)
lastTrackedData[i] = buffer[bufIndex + i];
*/
return (1);
}
/*****************************************************************************
*
decode_record - decodes a continuous binary encoded record
for one station.
output:
decodedMatrix- represents the row_matrix to transform the receiver
coordinates to tracker coordinates
- T_ERROR is returned if the record is munged, T_OK otherwise
*
*****************************************************************************/
int vrpn_Tracker_Dyna::decode_record()
// q_vec_type decoded_pos;
{
unsigned i;
unsigned char exp;
char x_high, y_high, z_high;
unsigned char x_low, y_low, z_low;
long x, y, z;
if ( (buffer[0] & lOOO_OOOO) == 0 )
{
fprintf(stderr, "bogus data to vrpn_Tracker_Dyna_decode_record:\n");
for ( i = 0; i < reportLength; i++ )
fprintf(stderr, "%x ", buffer[i]);
fprintf(stderr, "\n");
return(T_ERROR);
}
/* Pull out the exponent to shift by */
//exp = ( (buffer[0] & OOOO_OOlO)<<1 ) | (buffer[0] & OOOO_OOOl);
exp = (unsigned char)( ( (buffer[0] & 0x2)<<1 ) | (buffer[0] & 0x1) );
x_high = (char)buffer[2];
x_low = (char)buffer[3];
y_high = (char)buffer[4];
y_low = (char)buffer[5];
z_high = (char)buffer[6];
z_low = (char)buffer[7];
/* Shift high order byte, combine with low order, and then *
* shift by the exponent. */
x = (long)( ((short)x_high<<8) | ((short)x_low) ) << exp;
y = (long)( ((short)y_high<<8) | ((short)y_low) ) << exp;
z = (long)( ((short)z_high<<8) | ((short)z_low) ) << exp;
//fprintf(stderr,"x,y,z: %i,%i,%i\n",x,y,z);
/* Convert to meters -- 1 unit = 0.05mm = 0.00005m */
pos[0] = (double)x * 0.00005;
pos[1] = (double)y * 0.00005;
pos[2] = (double)z * 0.00005;
/* For the single-target Dynasight, we assume that the orientation *
* the target is that same as that of the Dynasight. */
d_quat[0] = 0.0;
d_quat[1] = 0.0;
d_quat[2] = 0.0;
d_quat[3] = 1.0;
return(T_OK);
} /* t_pdyn_decode_record */