Newer
Older
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
/* Author: Kris Burney
*
* BlueTooth socket program for passing vrpn data to quad.
*/
//system includes
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <pthread.h>
//user created includes
#include "communication.h"
#include "parse_packet.h"
#include "vrpn_tracker.hpp"
#include "type_def.h"
#include "commands.h"
#include "logger.h"
#define QUAD_BT_ADDR "00:06:66:64:61:D6"
#define QUAD_BT_CHANNEL 0x01
#define CMD_MAX_LENGTH 1024
// function prototypes
void killHandler(int);
void readAndPrint(void);
void sendVrpnPacket(struct ucart_vrpn_TrackerData *);
void sendStartPacket(void);
void getVRPNPacket(struct ucart_vrpn_TrackerData *);
void printVrpnData(struct ucart_vrpn_TrackerData *);
int connectToZybo();
void *handleQuadResponse();
void *handleCliInput();
static void cb(struct ucart_vrpn_TrackerData *);
// global variables
static volatile int keepRunning = 1;
const char *TRACKER_IP = "UAV@192.168.0.120:3883";
int quadlog_file;
int zyboSocket, status, bytes_read;
struct ucart_vrpn_tracker * tracker = NULL;
const char *logHeader = "";//"#\n#\tDefault log header\n#\tEverything after '#'`s will be printed as is in the processed logs.\n#\n\0";
pthread_mutex_t quadResponseMutex, cliInputMutex ;
unsigned char *respBuf, *commandBuf;
int newQuadResponse = 0, newCliInput = 0;
// Callback to be ran whenever the tracker receives data.
// Currently doing much more than it should. It will be slimmed down
// in the future.
static void cb(struct ucart_vrpn_TrackerData * td)
{
static int count = 0;
if(!(count % 10)) {
sendVrpnPacket(td);
updateLogFile(td);
}
count++;
// This will print the vrpn data to the terminal if necissary.
// Commented out because the callback will cover quad log data
// at the end of flight.
/**if(!(count % 100)) {
printVrpnData(td);
printf("[Info] Received %d tracker updates.\n", count);
}**/
}
void *handleQuadResponse() {
unsigned char buffer[255];
while(keepRunning) {
printf("in quad response thread\n"); fflush(0);
// Clear the buffer and read the message from the socket (from the server)
memset(buffer, 0, 255);
// If there was an error reading from the socket, throw an error
if(read(zyboSocket, buffer, 255) <= 0) {
fprintf(stderr, "CLI QUAD: ERROR reading from quad.\n");
fflush(stderr);
continue;
}
pthread_mutex_lock(&quadResponseMutex);
newQuadResponse = 1;
memcpy(respBuf, buffer, 255);
pthread_mutex_unlock(&quadResponseMutex);
//parse_packet(buffer, &respBuf, &metadata);
printf("CLI QUAD: %s\n", buffer);
}
pthread_exit(NULL);
}
void *handleCliInput() {
while(keepRunning)
{
printf("in cli input thread\n"); fflush(0);
char userCommand[CMD_MAX_LENGTH] = {};
fprintf(stderr, "$microcart> ");
while(fgets(userCommand, sizeof(userCommand), stdin) != NULL && keepRunning) {
// if the user simply hit enter then let them try again
if((userCommand[0] == '\n') || (userCommand[0] == '\r'))
{
fprintf(stderr, "$microcart> ");
memset(userCommand, 0, CMD_MAX_LENGTH);
continue;
}
pthread_mutex_lock(&cliInputMutex);
newCliInput = 1;
memcpy(commandBuf, &userCommand, CMD_MAX_LENGTH);
pthread_mutex_unlock(&cliInputMutex);
fprintf(stderr, "$microcart> ");
memset(userCommand, 0, CMD_MAX_LENGTH);
}
}
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
pthread_t quadResponse, cliInput;
respBuf = malloc(1024);
commandBuf = malloc(CMD_MAX_LENGTH);
signal(SIGINT, killHandler);
// if ((zyboSocket = connectToZybo()) < 0)
// {
// perror("Error connecting to Zybo...");
// exit(1);
// }
// create vrpnTracker instance
// tracker = ucart_vrpn_tracker_createInstance(TRACKER_IP);
// Retrieve VRPN data from the control loop
fprintf(stderr, "CLI: Starting quad receiving thread...\n");
pthread_create(&quadResponse, NULL, handleQuadResponse, NULL);
fprintf(stderr, "CLI: Thread quad receiving started.\n");
fprintf(stderr, "CLI: Starting cli input thread...\n");
pthread_create(&cliInput, NULL, handleCliInput, NULL);
fprintf(stderr, "CLI: Thread Cli input started.\n");
// open the log file
// if( (status = createLogFile(argc, argv[1])) < 0)
// {
// perror("Error creating log file...");
// exit(1);
// }
// writeLogHeader(logHeader);
//tell the quad we are ready to send it vrpn data
// printf("sending Start Packet...\n");
// sendStartPacket();
// this function will be called whenever tracker receives data
// ucart_vrpn_tracker_addCallback(tracker, cb);
while(1)
{
char tmpRespBuf[1024];
char tmpCommandBuf[CMD_MAX_LENGTH];
//check for user input via cli
if(newCliInput)
{
pthread_mutex_lock(&cliInputMutex);
newCliInput = 0;
memcpy(tmpCommandBuf, commandBuf, CMD_MAX_LENGTH);
pthread_mutex_unlock(&cliInputMutex);
// I can use printf becuase the command was gathered using fgets.
printf("\nINPUT FOUND via CLI: '%s'\n", tmpCommandBuf); fflush(0);
}
//check for update/response from quad
if(newQuadResponse)
{
pthread_mutex_lock(&quadResponseMutex);
newQuadResponse = 0;
memcpy(tmpRespBuf, respBuf, 1024);
pthread_mutex_unlock(&quadResponseMutex);
printf("\nINPUT FOUND via QUAD: '"); fflush(0);
fwrite(tmpRespBuf, 1024, 1, stdout);
printf("'\n"); fflush(0);
}
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
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
}
ucart_vrpn_tracker_freeInstance(tracker);
//free(vrpnData);
free(respBuf);
free(commandBuf);
pthread_mutex_destroy(&cliInputMutex);
pthread_mutex_destroy(&quadResponseMutex);
close(zyboSocket);
close(quadlog_file);
return 0;
}
// signal handler to exit while loop of main function
void killHandler(int dummy) {
keepRunning = 0;
printf("\nleaving Bluetooth module\n");
}
void readAndPrint() {
// read data from the server
// this is a blocking call.
//TODO: Implement a non blocking version of this.
bytes_read = read(zyboSocket, respBuf, sizeof(respBuf) -1);
if( bytes_read > 0)
{
respBuf[bytes_read] = '\0';
printf("%s", respBuf);
}
}
void sendStartPacket() {
unsigned char packet[8] = {0};
metadata_t metadata =
{
BEGIN_CHAR,
0x04,
0x01,
0x01,
0
};
packet[0] = metadata.begin_char; // BEGIN //PACKET_START_BYTE;
packet[1] = metadata.msg_type; // UPDATE //'U'; // U for vrpn camera update, C for command
packet[2] = metadata.msg_subtype; // BEGIN UPDATE
packet[3] = 1; // MSG ID(1)
packet[4] = 0; // MSG ID(2)
packet[5] = 0; // DATALEN(1)
packet[6] = 0; // DATALEN(2)
char checksum = 0;
int i;
for(i=0; i < metadata.data_len + 7; i++)
checksum ^= packet[i];
packet[metadata.data_len + 7] = checksum; //PACKET_END_BYTE;
status = write(zyboSocket, &packet, metadata.data_len + 8);
if (status != 8)
{
perror("Error sending start packet...\n");
keepRunning = 0;
}else
{
printf("Start packet successfuly sent...\n");
}
}
void sendVrpnPacket(struct ucart_vrpn_TrackerData *info) {
int pSize = sizeof(info) + 8;
int n;
char packet[pSize];
packet[0] = 0xBE; // BEGIN //PACKET_START_BYTE;
packet[1] = 0x04; // UPDATE //'U'; // U for vrpn camera update, C for command
packet[2] = 0x00; // N/A
//TODO Figure out Packet ID with this new ucar_vrpn_TrackerData struct
packet[3] = (0x00 & 0x000000ff); // MSG ID(1)
packet[4] = ((0x00 >> 8) & 0x000000ff); // MSG ID(2)
packet[5] = (sizeof(info) & 0x000000ff); // DATALEN(1)
packet[6] = ((sizeof(info) >> 8) & 0x00000ff); // DATALEN(2)
memcpy(&packet[7], &info, sizeof(info));
char checksum = 0;
int i;
for(i=0; i < pSize - 1; i++)
checksum ^= packet[i];
packet[pSize - 1] = checksum; //PACKET_END_BYTE;
n = write(zyboSocket, packet, pSize);
if(n < 0) {
perror("vrpnhandler: ERROR writing to socket");
keepRunning = 0;
}
}
void getVRPNPacket(struct ucart_vrpn_TrackerData *td) {
int status;
if((status = ucart_vrpn_tracker_getData(tracker, td)) < 0)
{
perror("Error receiving VRPN data from tracker...");
keepRunning = 0;
}
}
void printVrpnData(struct ucart_vrpn_TrackerData * td) {
printf("FPS: %lf Pos (xyz): (%lf %lf %lf) Att (pry): (%lf %lf %lf)\n",
td->fps, td->x, td->y, td->z, td->pitch, td->roll, td->yaw);
}
int connectToZybo() {
int sock;
struct sockaddr_rc addr = { -1 };
// allocate a socket
sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
//set the connection params ie. who to connect to
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = (uint8_t) QUAD_BT_CHANNEL;
str2ba( QUAD_BT_ADDR, &addr.rc_bdaddr );
printf("Attempting to connect to zybo. Please be patient...\n");
// blocking call to connect to socket sock ie. zybo board
status = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
// connection failed
if(status < 0)
{
close(sock);
printf("Connection failed!...\n");
return -1;
}
else
{
printf("connection successful!...\n");
return sock;
}
}