Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / mapping / matlab / receive.c @ 966

History | View | Annotate | Download (6.52 KB)

1
/* This version of receive initializes
2
 * the token ring and then requests and
3
 * receives data in a different packet group
4
 * unsynchronized with the token ring.
5
 */
6

    
7
#include <stdio.h>
8
#include <stdlib.h>
9
#include <mex.h>
10
#include <pthread.h>
11
#include <unistd.h>
12
#include "../../libwireless/lib/wireless.h"
13
#include "../../libwireless/lib/wl_token_ring.h"
14

    
15
#define WL_COM_PORT "/dev/ttyUSB1" 
16
#define WL_CHANNEL 0xE
17

    
18
#define MAP_REQUEST_GROUP 23
19

    
20
#define DATA_POINT 2 /* packet type for map data points w/ odometry data*/
21
#define DATA_REQUEST 3
22

    
23
#define BUFFER_SIZE 1000
24
#define BUFFER_EMPTY -1
25

    
26
pthread_rwlock_t buffer_lock;
27
pthread_t receive_thread;
28

    
29
int packets_received; /*Used to block overlapping packet requests.*/
30

    
31
void packet_receive(char type, int source, unsigned char* packet, int length);
32

    
33
PacketGroupHandler requestHandler = {MAP_REQUEST_GROUP, NULL, NULL, &packet_receive, NULL};
34

    
35
/*Buffers*/
36
short robot_buffer[BUFFER_SIZE];                        /*by #*/
37
short range_buffer[BUFFER_SIZE][5];                 /*IR1, IR2 ... */
38
short coordinate_buffer[BUFFER_SIZE][2];        /*X Y*/
39
float orientation_buffer[BUFFER_SIZE];
40

    
41
int tail_index; /*Points to the newest data in the buffers.*/
42
int head_index; /*Points to the oldest data in the buffers.*/
43

    
44
void* buffer_data(void* arg);
45
void init_wireless(void);
46

    
47
void mexFunction(int nlhs, mxArray* ret[], int nrhs, const mxArray* args[]){
48
        
49
        if(nrhs == 1){        
50
                
51
                /*Initialization*/
52
                head_index = BUFFER_EMPTY;
53
                tail_index = BUFFER_EMPTY;        
54
                 
55
                pthread_rwlock_init(&buffer_lock, NULL);
56

    
57
                pthread_create(&receive_thread, NULL, buffer_data, NULL);
58
                return;
59
        }
60
        
61
        /*Return stuff to matlab*/
62
        /*deliberately ignore nrhs.        */
63

    
64
        if(nlhs != 4){
65
                mexErrMsgTxt("Error: Expect output arguments [P IR T R]\n  \
66
                                          where P = [X Y], IR = [IR1, IR2 ...],\n \
67
                                          T = angle, and R = Robot number."); 
68
        }
69
        
70
        int index,i,j;
71
        
72
        pthread_rwlock_rdlock(&buffer_lock);
73
        {
74

    
75
                if(tail_index == BUFFER_EMPTY || head_index == BUFFER_EMPTY){
76
                        double* point, *ranges, *theta, *robot;
77
                        /*Appropriately return with nothing.*/
78
                        ret[0] = mxCreateDoubleMatrix(1, 2, mxREAL);
79
                        ret[1] = mxCreateDoubleMatrix(1, 5, mxREAL);
80
                        ret[2] = mxCreateDoubleMatrix(1, 1, mxREAL);
81
                        ret[3] = mxCreateDoubleMatrix(1, 1, mxREAL);
82
                        
83
                        point  = mxGetPr(ret[0]);
84
                        ranges = mxGetPr(ret[1]);
85
                        theta = mxGetPr(ret[2]);
86
                        robot = mxGetPr(ret[3]);
87

    
88
                        point[0] = point[1] = 0.0;
89
                        
90
                        ranges[0] = ranges[1] = ranges[2] = 0.0;
91
                        ranges[3] = ranges[4] = 0.0;
92

    
93
                        theta[0] = 0.0;
94
                        robot[0] = 0.0;
95

    
96
                        return;
97
                }
98
                else{
99
                        double** point, **ranges, *theta, *robot;
100
                        
101
                        int num_buffer_elements = tail_index - head_index;
102
                        if(num_buffer_elements < 0) num_buffer_elements += BUFFER_SIZE;        
103

    
104
                        ret[0] = mxCreateDoubleMatrix(num_buffer_elements, 2, mxREAL);
105
                        ret[1] = mxCreateDoubleMatrix(num_buffer_elements, 5, mxREAL);
106
                        ret[2] = mxCreateDoubleMatrix(num_buffer_elements, 1, mxREAL);
107
                        ret[3] = mxCreateDoubleMatrix(num_buffer_elements, 1, mxREAL);
108
                
109
                        /*This may not work on some computers.*/
110
                        point  = (double**)mxGetPr(ret[0]);
111
                        ranges = (double**)mxGetPr(ret[1]);
112
                        theta = mxGetPr(ret[2]);
113
                        robot = mxGetPr(ret[3]);
114

    
115
                        for(index = head_index; index <= tail_index; index = (index + 1)%1024){
116
                                point[i][0] = (double)coordinate_buffer[index][0];        
117
                                point[i][1] = (double)coordinate_buffer[index][1];        
118
                                
119
                                for(j=0;j<5;j++)
120
                                        ranges[i][j] = (double)range_buffer[index][j];
121

    
122
                                theta[i] = (double)(orientation_buffer[index]);        
123
                                robot[i] = (double)(robot_buffer[index]);
124
                        }
125
                        head_index = BUFFER_EMPTY;
126
                        tail_index = BUFFER_EMPTY;
127
                }
128
        }        
129
        pthread_rwlock_unlock(&buffer_lock);
130
}
131

    
132
void init_wireless(void){
133
        /*General communication initialization.        */
134
        wl_set_com_port(WL_COM_PORT);        
135
        wl_init();
136
        wl_set_channel(WL_CHANNEL);
137
        wl_register_packet_group(&requestHandler);
138

    
139
        /*Token ring / sensor network initialization.*/
140
        wl_token_ring_register();        
141
}
142

    
143
/*
144
 * buffer_data continuously runs through the robots and
145
 * waits for them to respond.
146
 */
147
void* buffer_data(void* arg){
148
        int robot_num, num_robots,time_out, i;        
149

    
150
        pthread_detach(pthread_self());
151
        
152
        init_wireless();
153
        
154
        /*Continuously iterate over all the robots - buffering data.*/
155
        
156
        while(1){
157
                wl_do();
158

    
159
                printf("sending new round of packets\n");        
160
                wl_token_iterator_begin();
161
                
162
                num_robots = wl_token_get_num_robots();
163
                
164
                /*Initialize the 'packets received' number. */
165
                packets_received = 0;
166
        
167
                /*Send a data request to all robots.*/
168
                while(wl_token_iterator_has_next()){
169
                        wl_do();
170
                        
171
                        robot_num = wl_token_iterator_next();
172
                    
173
                        printf("sending a packet to robot %d\n",robot_num);
174
                        wl_send_robot_to_robot_global_packet(MAP_REQUEST_GROUP, 
175
                                DATA_REQUEST, NULL, 0, robot_num, 0);
176
                    
177
                        for(i=0;i<50;i++){
178
                                wl_do();        
179
                                usleep(10000); /*500ms*/
180
                        }
181
                }
182
                
183
                time_out = 50; /*50 * 10ms = 1s*/
184

    
185
                /*Wait for all packets to be received 
186
                 * before sending more requests.
187
                 * ring etc.) For example, if a robot drops
188
                 * a packet (highly likely) it is not dealt with
189
                 * */
190
                while(packets_received < num_robots 
191
                   && packets_received < wl_token_get_num_robots() && time_out){
192
                        
193
                        wl_do();
194
                        time_out--;        
195
                        usleep(10000); /*10ms*/
196
                }
197

    
198
                for(i=0;i<50;i++){
199
                        wl_do();        
200
                        usleep(10000); /*500ms*/
201
                }
202
        }
203
}
204

    
205
void packet_receive (char type, int source, unsigned char* packet, int length) {
206
        printf("A packet came in!\n");        
207
        if(type==DATA_POINT){        
208

    
209
                if(length!=18) printf("Packet came without the standard length!\n");
210

    
211
                /* expected input: x y theta(double) IR1 IR2 IR3 IR4 IR5*/
212
                /* Pull in data:*/
213
                
214
                short x,y,i;
215
                short ranges[5];        
216
                
217
                x = ((short)packet[1] << 8)  | (short)packet[0];
218
                y = ((short)packet[3] << 8)  | (short)packet[2];
219

    
220
                for(i=0; i<5; i++){
221
                        ranges[i] 
222
                           = ((short)packet[8+2*i+1] << 8) | (short)packet[8 + 2*i];
223
                }
224

    
225
                float theta = *((float*)(packet + 4));
226
        
227
                /*Write new data to buffers. (Lock down!)*/
228
                pthread_rwlock_wrlock(&buffer_lock);
229
                {        
230
                        /*Note that you write no matter what.        */
231
                        tail_index = (tail_index + 1) % BUFFER_SIZE; 
232
                        
233
                        /*Write the robots number.*/
234
                        robot_buffer[tail_index] = source;
235
                        
236
                        /*Write in range data.*/
237
                        for(i=0; i<5; i++) range_buffer[tail_index][i] = ranges[i];
238
                        
239
                        coordinate_buffer[tail_index][0] = x;
240
                        coordinate_buffer[tail_index][1] = y;
241
                        
242
                        orientation_buffer[tail_index] = theta;
243
                        
244
                        /*If the oldest member didn't exist, buffer was empty.*/
245
                        if(head_index == BUFFER_EMPTY) head_index = 0;
246
                
247
                        /*Otherwise check for overwritten data.        */
248
                        else if(tail_index == head_index) 
249
                                head_index = (head_index +1) % BUFFER_SIZE;  
250
                        
251
                }
252
                pthread_rwlock_unlock(&buffer_lock);
253
                
254
                /*Increment for the transmit thread.*/
255
                packets_received++;
256
        }
257
}
258