Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / traffic_navigation / collision_avoid.c @ 1962

History | View | Annotate | Download (6.86 KB)

1
/* TODO:
2
 *  - Document how to call functions.
3
 *  - Actually Test this stuff. Especially the intersection rotating thing. and the parts marked sketchy.
4
 *  - Integrate into main.c
5
 *  - In the intersection queue in main.c, allow bots to skip each other (since this code allows it).
6
 *    (because some bot at another intersection entrance may be able to go before another bot at another
7
 *    intersection entrance, but their order in the queue may not allow this.).
8
*/
9
#include "collision_avoid.h"
10
#include "traffic_navigation.h"
11
static unsigned int my_path = 0;
12
static unsigned int first_hop = 0;
13
static char intersection = 0;
14

    
15
/*           Dir0
16
 *         [0 ][4 ]
17
 *Dir1  [5][8 ][9 ][3]   Dir3
18
 *      [1][11][10][7]
19
 *         [6 ][2 ]
20
 *           Dir2  
21
 *
22
 *            Dir0
23
 *          [D0E][D0X]
24
 *Dir1  [D1X][I0][I1][D3E]   Dir3
25
 *      [D1E][12][13][D3X]
26
 *          [D2X][D2E]
27
 *            Dir2  
28
 */
29

    
30
/* Upon entering an intersection, this function should be called. To achieve
31
 * nonstop motion when possible, it is preferable to call this right after
32
 * reading the barcode.
33
 *
34
 * This function sets up the "my_path" variable with the proper bits representing
35
 * the path that the bot will travel in the intersection.
36
 *
37
 * char intersectionNum: The # of the intersection
38
 * char fromDir: The direction the bot is entering the intersection
39
 * char nextDir: The direction the bot is exiting the intersection
40
 */
41
void ca_EnterIntersection(char intersectionNum, char fromDir, char nextDir){
42
        /* Generic turn model condenses all turns into either:
43
         * - a right turn from dir0 to dir1
44
         * - a straight from dir0 to dir2
45
         * - a left turn dir0 to dir3
46
         * - maybe a U-turn from dir0 to dir0 **UNIMPLEMENTED*
47
         */
48
        /* Fill in dir0 */
49
        my_path = 0;
50
        my_path = my_path | D0E;
51
        my_path = my_path | I0;
52
        char genericNext = nextDir-fromDir;
53
        if(genericNext < 0){
54
                genericNext += 4;
55
        }
56
        if(genericNext == 1){ //right turn
57
#ifdef DEBUG_CA
58
                usb_puts("CA: Setting up Generic Right Turn\n");
59
#endif
60
                my_path = my_path | D1X;
61
        }
62
        else if(genericNext == 2){ //straight turn
63
#ifdef DEBUG_CA
64
                usb_puts("CA: Setting up Generic Straight Turn\n");
65
#endif
66
                my_path = my_path | D2X;
67
                my_path = my_path | I2;
68
        }
69
        else{ //left turn
70
#ifdef DEBUG_CA
71
                if(genericNext != 3)
72
                        usb_puts("CA ERROR: Error in generic turn generator (CA_E0)\n");
73
                usb_puts("CA: Setting up Generic Left Turn\n");
74
#endif
75
                my_path = my_path | D3X;
76
                my_path = my_path | I2;
77
                my_path = my_path | I3;
78

    
79
        }
80
        //now rotate turn to match what it's really supposed to be
81
        for(int i = 0; i < fromDir; i++){
82
                int new_path = 0;
83
                char temp = my_path & DAE;
84
                char shiftoff = temp & 0x8;
85
                temp = temp << 1;
86
                temp = temp | (shiftoff >> 3);
87
                new_path = new_path | temp;
88

    
89
                temp = (my_path & DAX) >> DAXS;
90
                shiftoff = temp & 0x1;
91
                temp = temp << 1;
92
                temp = temp | (shiftoff >> 3);
93
                new_path = new_path | (temp << DAXS);
94

    
95
                temp = (my_path & DAX) >> IAS;
96
                shiftoff = temp & 0x1;
97
                temp = temp << 1;
98
                temp = temp | (shiftoff >> 3);
99
                new_path = new_path | (temp << IAS);
100
                my_path = new_path;
101

    
102
        }
103
        first_hop = fromDir;
104
        intersection = intersectionNum;
105
}
106

    
107
/* Call this function when the bot has left the intersection.
108
 *
109
 * All this function does is clear some variables. I guess
110
 * this is optional but it is nice for debugging. */
111
void ca_ExitIntersection(){
112
        my_path = 0;
113
        first_hop = -1; 
114
        intersection = -1;
115
}
116

    
117
/* Don't call this function. This is strictly an internal function to this library.
118
 *
119
 * int path: Takes the path to be sent in the packet.
120
 *
121
 * This will send a collision avoidance packet with the bot id, the intersection # and path */
122
void ca_sendPacket(char id, int path){
123
        if(path & D0E && path & D1E && path & D2E && path & D3E){
124
#ifdef DEBUG_CA
125
                usb_puts("CA: No open entry ways to intersection, so not sending CA packet.");
126
#endif
127
                return;
128
        }
129
        char sendBuffer[PACKET_LENGTH];
130
        sendBuffer[0] = WCOLLISIONAVOID;
131
        sendBuffer[1] = id;
132
        sendBuffer[2] = intersection;
133
        sendBuffer[3] = path; /* sketchy because path is an int. so will it take both sendBuffer[3] and sendBuffer[4]? */
134
        wl_basic_send_global_packet(42, sendBuffer, PACKET_LENGTH);
135
}
136

    
137
/* Call this if the bot is the first in the queue for the intersection and wishes
138
 * to attempt collision avoidance.
139
 *
140
 * char id: the bot's id.
141
 *
142
 * What this does is send a collision avoidance packet with this bot's path.
143
 */
144
void ca_Initiator(char id){ //args: (This bot's ID)
145
#ifdef DEBUG_CA
146
        if(mypath == 0)
147
                usb_puts("CA ERROR: Someone Forgot to call ca_EnterIntersection. mypath == 0 (CA_E1)\n");
148
#endif
149
        ca_sendPacket(id, my_path);
150
}
151

    
152
/* Call this when the bot gets a collision avoidance packet that *MATCHES*
153
 * the intersection it is in and the id identifying the sender in the packet
154
 * matches the bot id that is in line in front. (so the collision avoidance
155
 * packet sent by the bot last in the queue gets no listener. This is expected.)
156
 * This function will return whether it is okay for
157
 * the bot to proceed into the intersection with a true or false.
158
 *
159
 * char id: the bot's id
160
 * char recieve[]: the wireless packet recieved.
161
 *
162
 * What this does is check if the path that the bot needs to travel is clear by
163
 * comparing my_path and the path in the packet.
164
 * If it is clear, the bot will add my_path to the path it got in the wireless
165
 * packet and then send it. Then the function will return true.
166
 * Otherwise, the bot will only fill in the entrance bit in the function it
167
 * recieved in the wireless packet to indicate it is sitting at the entrance
168
 * to the intersection so that bots behind it won't try to enter the intersection
169
 * and crash into the bot at the front of the line for that intersection.
170
 */
171
bool ca_Process(char id, char recieve[]){ //args: (This bot's ID, a pointer to the packet recieved)
172
        bool result = false;
173
#ifdef DEBUG_CA
174
        if(recieve[0] != WCOLLISIONAVOID)
175
                usb_puts("CA ERROR: You didn't call ca_Process with a WCOLLISIONAVOID type packet (CA_E2)\n");
176
        if(recieve[1] < 0)
177
                usb_puts("CA ERROR: Recieved Packet indicates sending bot has a negative ID. (CA_E3)\n");
178
        if(recieve[2] != intersection)
179
                usb_puts("CA ERROR: Recieved Packet's intersection doesn't match the intersection CA is operating on in this Bot.. (CA_E4)\n");
180
#endif
181
        if((*(recieve+3) & my_path) != 0){ /* Sketchy Code because recieve is made of chars and my_path is an int */
182
#ifdef DEBUG_CA
183
                usb_puts("CA: My Path is occupied through intersection ");
184
                usb_puti(intersection);
185
                usb_putc('\n');
186
#endif
187
                result = false;
188
                ca_sendPacket(id, 1 << first_hop | *(recieve+3)); /* Sketchy Code because recieve is made of chars and ca_send_packet expects an int. we need the whole int to make it through*/
189
        }
190
        else{
191
#ifdef DEBUG_CA
192
                usb_puts("CA: My Path is clear through intersection ");
193
                usb_puti(intersection);
194
                usb_putc('\n');
195
#endif
196
                result = true;
197
                ca_sendPacket(id, my_path | *(recieve+3)); /* Sketchy Code because recieve is made of chars and ca_send_packet expects an int.  we need the whole int to make it through. Also, my_path is an int.*/
198
        }
199
        return result;
200
}