-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPathPlanningAndCommunication.py
More file actions
380 lines (341 loc) · 13.9 KB
/
PathPlanningAndCommunication.py
File metadata and controls
380 lines (341 loc) · 13.9 KB
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
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
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
'''
Team Id: GG_3096
Author List: Om Mandhane
Filename: PathPlanningAndCommunication
Theme: GG_3096
Functions: find_nearest, Bot, node_to_event, execute_commands
Global Variables: G, layout, node_to_remove, file, first_column, second_column, third_column, fourth_column, fifth_column,
closest_node, first_nodes, second_nodes, third_nodes, fourth_nodes, fifth_nodes, my_bot, ip
'''
import time
import networkx as nx
import pandas as pd
import socket
# Create a graph representing a 2D grid of the map with coordinates at nodes
G = nx.grid_2d_graph(3, 4)
layout = {node: (node[0], node[1]) for node in G.nodes}
node_to_remove = (2, 0)
G.remove_node(node_to_remove)
# Visualize the modified graph
nx.draw(G, pos=layout, with_labels=True, font_weight='bold')
#the events to visit in the priority order is saved in the csv "event_to_visit"
file = pd.read_csv("event_to_visit.csv")
first_event = file.columns[0]
second_event = file.columns[1]
third_event = file.columns[2]
fourth_event = file.columns[3]
fifth_event = file.columns[4]
#closest_nodes: dictionary with event as keys and the nodes closest to the event as value
closest_nodes = {"A": [(0, 0), (1, 0)],
"B": [(1, 1), (2, 1)],
"C": [(1, 2), (2, 2)],
"D": [(0, 2), (1, 2)],
"E": [(0, 3), (2, 3)]}
# contains the coordinates of the closest node to the respective event
first_nodes = closest_nodes[first_event]
second_nodes = closest_nodes[second_event ]
third_nodes = closest_nodes[third_event]
fourth_nodes = closest_nodes[fourth_event]
fifth_nodes = closest_nodes[fifth_event]
def find_nearest(A, B):
'''
* Function Name: find_nearest
* Input: A - List of two nodes that can used to got to the particular event, B - Current location/node of the bot
* Output: The nearest node from A to the target node B
* Logic: Calculates the Euclidean distance from both nodes in A to the target node B and returns the closest one.
* Example Call: find_nearest([(0, 0), (1, 0)], [0, 0])
'''
x1, y1 = A[0]
x2, y2 = A[1]
x, y = B
first = (x1 - x) ** 2 + (y1 - y) ** 2
second = (x2 - x) ** 2 + (y2 - y) ** 2
if first <= second:
return A[0]
else:
return A[1]
class Bot:
def __init__(self, start_position):
'''
* Function Name: __init__
* Input: start_position - Tuple representing the initial position of the bot (x, y)
* Output: None
* Logic: Initializes the Bot object with the given start position and default orientation ('up')
* Example Call: my_bot = Bot((0, 0))
'''
self.position = start_position
self.orientation = 'up' # Initial orientation (up, down, left, right)
self.commands = [] #the path commands to reach all the events keep getting appended to this attribute
def move_forward(self):
'''
* Function Name: move_forward
* Input: None
* Output: None
* Logic: Moves the bot one step forward based on its current orientation and updates the position along with
along appending the esp32 function name that moves the bot forward to the commands attribute.
* Example Call: my_bot.move_forward()
'''
x, y = self.position
self.commands.append("ForwardTN")
if self.orientation == 'up':
self.position = (x, y + 1)
elif self.orientation == 'down':
self.position = (x, y - 1)
elif self.orientation == 'left':
self.position = (x - 1, y)
elif self.orientation == 'right':
self.position = (x + 1, y)
def turn_left(self):
'''
* Function Name: turn_left
* Input: None
* Output: None
* Logic: Adds the esp32 function name that turns the bot 90 degrees to the left to the commands
list and updates its orientation
* Example Call: my_bot.turn_left()
'''
self.commands.append("Left90")
orientations = ['up', 'left', 'down', 'right']
current_index = orientations.index(self.orientation)
self.orientation = orientations[(current_index + 1) % 4]
def turn_right(self):
'''
* Function Name: turn_right
* Input: None
* Output: None
* Logic: Adds the esp32 function name that turns the bot 90 degrees to the right to the commands
list and updates its orientation
* Example Call: my_bot.turn_right()
'''
self.commands.append("Right90")
orientations = ['up', 'left', 'down', 'right']
current_index = orientations.index(self.orientation)
self.orientation = orientations[(current_index - 1) % 4]
def forward_right_ad(self):
'''
* Function Name: forward_right_ad
* Input: None
* Output: None
* Logic: Adds the esp32 function name that moves the bot from left of event A/D to the right
while stopping at A/D, to the command list. This function updates the position accordingly
* Example Call: my_bot.forward_right_ad()
'''
x, y = self.position
self.position = (x + 1, y)
self.commands.append("FRAD")
def forward_left_ad(self):
'''
* Function Name: forward_left_ad
* Input: None
* Output: None
* Logic: Adds the esp32 function name that moves the bot from right of event A/D to the left
while stopping at A/D, to the command list. This function updates the position accordingly
* Example Call: my_bot.forward_left_ad()
'''
x, y = self.position
self.position = (x - 1, y)
self.commands.append("FLAD")
def forward_right_b(self):
'''
* Function Name: forward_right_b
* Input: None
* Output: None
* Logic: Adds the esp32 function name that moves the bot from left of event B to the right
while stopping at B, to the command list. This function updates the position accordingly
* Example Call: my_bot.forward_right_b()
'''
x, y = self.position
self.position = (x + 1, y)
self.commands.append("FRB")
def forward_left_b(self):
'''
* Function Name: forward_left_b
* Input: None
* Output: None
* Logic: Adds the esp32 function name that moves the bot from right of event B to the left
while stopping at B, to the command list. This function updates the position accordingly
* Example Call: my_bot.forward_left_b()
'''
x, y = self.position
self.position = (x - 1, y)
self.commands.append("FLB")
def forward_right_c(self):
'''
* Function Name: forward_right_c
* Input: None
* Output: None
* Logic: Does the same as the above functions, but for event C
* Example Call: my_bot.forward_right_c()
'''
x, y = self.position
self.position = (x + 1, y)
self.commands.append("FRC")
def forward_left_c(self):
'''
* Function Name: forward_left_c
* Input: None
* Output: None
* Logic: Does the same as the above functions, but for event C
* Example Call: my_bot.forward_left_c()
'''
x, y = self.position
self.position = (x - 1, y)
self.commands.append("FLC")
def forward_right_e(self):
'''
* Function Name: forward_right_e
* Input: None
* Output: None
* Logic: Does the same as the above functions, but for event C
* Example Call: my_bot.forward_right_e()
'''
self.position = (2, 3)
self.orientation = 'down'
self.commands.append("FRE")
def forward_left_e(self):
'''
* Function Name: forward_left_e
* Input: None
* Output: None
* Logic: Moves the bot to the target position and changes its orientation for event 'E'.
* Example Call: my_bot.forward_left_e()
'''
self.position = (0, 3)
self.orientation = 'down'
self.commands.append("FLE")
def node_to_event(event, node, bot):
'''
* Function Name: node_to_event
* Input: event - The event to be executed (A, B, C, D, E), node - Current node, bot - Bot object
* Output: None
* Logic: Determines which function to execute from Bot class to move the bot from current node
to the given event and then till the next node. Adjusts the orientation of the bot till
it is facing in the right directiom
* Example Call: node_to_event('A', (1, 0), my_bot)
'''
if event == 'A' and node == (0, 0):
while bot.orientation != "right":
bot.turn_right()
bot.forward_right_ad()
elif event == 'A' and node == (1, 0):
while bot.orientation != "left":
bot.turn_left()
bot.forward_left_ad()
elif event == 'B' and node == (1, 1):
while bot.orientation != "right":
bot.turn_right()
bot.forward_right_b()
elif event == 'B' and node == (2, 1):
while bot.orientation != "left":
bot.turn_left()
bot.forward_left_b()
elif event == 'C' and node == (1, 2):
while bot.orientation != "right":
bot.turn_right()
bot.forward_right_c()
elif event == 'C' and node == (2, 2):
while bot.orientation != "left":
bot.turn_left()
bot.forward_left_c()
elif event == 'D' and node == (0, 2):
while bot.orientation != "right":
bot.turn_right()
bot.forward_right_ad()
elif event == 'D' and node == (1, 2):
while bot.orientation != "left":
bot.turn_left()
bot.forward_left_ad()
elif event == 'E' and node == (0, 3):
while bot.orientation != "up":
bot.turn_right()
bot.forward_right_e()
elif event == 'E' and node == (2, 3):
while bot.orientation != "up":
bot.turn_left()
bot.forward_left_e()
my_bot = Bot((0, 0)) #initialising bot object at node (0,0)
def execute_commands(path):
'''
* Function Name: execute_commands
* Input: path - List of nodes representing the path the bot needs to traverse
* Output: List of commands to be executed by the bot
* Logic: Takes a path as input and generates the commands for the bot to traverse that path.
* Example Call: execute_commands([(0, 0), (1, 0), (1, 1)])
'''
for node in path:
if node[0] > my_bot.position[0]:
while my_bot.orientation != 'right':
my_bot.turn_right()
my_bot.move_forward()
elif node[0] < my_bot.position[0]:
while my_bot.orientation != 'left':
my_bot.turn_left()
my_bot.move_forward()
elif node[1] > my_bot.position[1]:
while my_bot.orientation != 'up':
my_bot.turn_left()
my_bot.move_forward()
elif node[1] < my_bot.position[1]:
while my_bot.orientation != 'down':
my_bot.turn_left()
my_bot.move_forward()
return my_bot.commands
#finding the nearest node to the first event
first_to_visit = find_nearest(first_nodes, [0, 0])
#using the dijkstras algorithm to find shortest path
path1 = nx.shortest_path(G, source=(0, 0), target=first_to_visit)
#commands to be executed to reach first event nearest node
command1 = execute_commands(path1)
#function to go from the node to the event
node_to_event(first_event, path1[-1], my_bot)
#path/commands to go from first event to second is appended in the commands attribute
second_to_visit = find_nearest(second_nodes, my_bot.position)
path2 = nx.shortest_path(G, source=my_bot.position, target=second_to_visit)
command2 = execute_commands(path2)
node_to_event(second_event, path2[-1], my_bot)
#path/commands to go from second event to third is appended in the commands attribute
third_to_visit = find_nearest(third_nodes, my_bot.position)
path3 = nx.shortest_path(G, source=my_bot.position, target=third_to_visit)
command3 = execute_commands(path3)
node_to_event(third_event, path3[-1], my_bot)
#path/commands to go from third event to fourth is appended in the commands attribute
fourth_to_visit = find_nearest(fourth_nodes, my_bot.position)
path4 = nx.shortest_path(G, source=my_bot.position, target=fourth_to_visit)
command4 = execute_commands(path4)
node_to_event(fourth_event, path4[-1], my_bot)
#path/commands to go from fourth event to fifth is appended in the commands attribute
fifth_to_visit = find_nearest(fifth_nodes, my_bot.position)
path5 = nx.shortest_path(G, source=my_bot.position, target=fifth_to_visit)
command5 = execute_commands(path5)
node_to_event(fifth_event, path5[-1], my_bot)
##path to go from last event to (0,0)
path6 = nx.shortest_path(G, source=my_bot.position, target=(0, 0))
command6 = execute_commands(path6)
#turning the bot left till it is facing downward at node (0,0)
while my_bot.orientation != "down":
my_bot.turn_left()
#converting the command list to a string
string = str(my_bot.commands)
print(string)
message = string[1:-1] #removing inverted commas from the string and storing the commands in message variable
ip = "192.168.155.229" # IP address of the laptop after connecting it to the WIFI hotspot
#using socket library to establish connection and sending the message string to the esp32 on the bot
while True:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((ip, 8002))
s.listen()
conn, addr = s.accept()
print("done")
with conn:
print(f"Connected by {addr}")
data = conn.recv(1024)
print(data)
conn.sendall(message.encode('utf-8'))
print("done2")
break
except Exception as e:
print(f"An error occurred: {e}")
# Wait for some time before attempting to reconnect
time.sleep(5)