IncreasingLoss commited on
Commit
bc024e3
·
verified ·
1 Parent(s): 590c947

Delete app copy 2.py

Browse files
Files changed (1) hide show
  1. app copy 2.py +0 -400
app copy 2.py DELETED
@@ -1,400 +0,0 @@
1
- import gradio as gr
2
- import numpy as np
3
- import pygame
4
- import threading
5
- import queue
6
- from PIL import Image
7
- from car_game_classes_gradio import Car, RayCasting, MapGenerator
8
- from ppo_agent_gradio import PPOAgent
9
- from collections import deque
10
-
11
- # Initialize Pygame
12
- pygame.init()
13
- SCREEN_WIDTH, SCREEN_HEIGHT = 1600, 900
14
- screen = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
15
- clock = pygame.time.Clock()
16
-
17
- # Define constants
18
- ACTION_SPACE = 8
19
- state_size = 22
20
- LOADED_MODEL = "model/18.6_car_model_epoch_270_lvl3_final.pth"
21
- SIMULATION_FPS = 120 # Fixed simulation FPS, matching training
22
- DT = 1.0 / SIMULATION_FPS # Fixed time step
23
-
24
- # Frame queue for Gradio
25
- frame_queue = queue.Queue(maxsize=1)
26
-
27
- def point_to_line_distance(point, line_p0, line_p1):
28
- p = pygame.math.Vector2(point)
29
- a = pygame.math.Vector2(line_p0)
30
- b = pygame.math.Vector2(line_p1)
31
- ap = p - a
32
- ab = b - a
33
- magnitude_ab = ab.length_squared()
34
- if magnitude_ab == 0:
35
- return ap.length()
36
- projection = ap.dot(ab) / magnitude_ab
37
- projection = max(0, min(1, projection))
38
- closest = a + projection * ab
39
- return p.distance_to(closest)
40
-
41
- class TrainingEnvironment:
42
- def __init__(self, action_space=8):
43
- self.action_space = action_space
44
- self.map_generator = MapGenerator(SCREEN_WIDTH, SCREEN_HEIGHT, 2, 18) # Difficulty 2 = lvl 3 in training
45
- car_surf = pygame.image.load("assets/car_transparent.png").convert_alpha()
46
- w, h = car_surf.get_size()
47
- self.car_image = pygame.transform.scale(car_surf, (w//18, h//18))
48
- self.start_pos = None
49
- self.start_dir = None
50
- self.previous_speed = 0.0
51
- self.speed_history = deque(maxlen=5)
52
- self.steering_history = deque(maxlen=10)
53
- self.steering_persistence = {'direction': 0, 'count': 0}
54
- self.last_steering_reward = 0.0
55
- self.prev_pos = None
56
- self.passed_goals = []
57
- self.last_action = 0
58
- self.reset()
59
-
60
- def generate_new_map(self):
61
- start_pos, start_dir = self.map_generator.update()
62
- self.start_pos = pygame.math.Vector2(start_pos)
63
- self.start_dir = pygame.math.Vector2(start_dir).normalize()
64
-
65
- def reset_car(self):
66
- if self.start_pos is None or self.start_dir is None:
67
- raise ValueError("Map not generated yet")
68
- self.car = Car(self.car_image, self.start_pos)
69
- self.car.direction = self.start_dir
70
- self.rays = RayCasting(
71
- self.car.pos, self.car.direction, self.map_generator.surface,
72
- [-60, -30, -15, 0, 15, 30, 60],
73
- [14, 22, 27, 26, 27, 22, 14],
74
- draw_rays=False)
75
- self.current_goal_index = 0
76
- self.passed_goals = []
77
- self.prev_pos = self.car.pos.copy()
78
- self.previous_speed = 0.0
79
- self.speed_history.clear()
80
- self.steering_history.clear()
81
- self.steering_persistence = {'direction': 0, 'count': 0}
82
- self.last_steering_reward = 0.0
83
- self.last_action = 0
84
-
85
- def reset(self):
86
- self.map_generator.difficulty = 2 # Ensure difficulty matches training
87
- self.generate_new_map()
88
- self.reset_car()
89
-
90
- def detect_steering_need(self, ray_distances):
91
- norm_distances = [min(d / self.rays.max_distance, 1.0) for d in ray_distances]
92
- left_rays = norm_distances[0:3]
93
- center_ray = norm_distances[3]
94
- right_rays = norm_distances[4:7]
95
- left_avg = sum(left_rays) / len(left_rays)
96
- right_avg = sum(right_rays) / len(right_rays)
97
- space_difference = right_avg - left_avg
98
- steering_needed = False
99
- preferred_direction = 0
100
- urgency = 0.0
101
- min_side_distance = min(min(left_rays), min(right_rays))
102
- if min_side_distance < 0.3:
103
- steering_needed = True
104
- urgency = 1.0 - min_side_distance
105
- preferred_direction = 1 if left_avg < right_avg else -1
106
- elif abs(space_difference) > 0.15:
107
- steering_needed = True
108
- urgency = min(abs(space_difference), 1.0)
109
- preferred_direction = 1 if space_difference > 0 else -1
110
- elif center_ray < 0.4:
111
- steering_needed = True
112
- urgency = 1.0 - center_ray
113
- preferred_direction = 1 if left_avg < right_avg else -1
114
- return {
115
- 'needed': steering_needed,
116
- 'direction': preferred_direction,
117
- 'urgency': urgency,
118
- 'space_diff': space_difference,
119
- 'left_space': left_avg,
120
- 'right_space': right_avg,
121
- 'center_distance': center_ray
122
- }
123
-
124
- def get_state(self):
125
- self.rays.update(self.car.pos, self.car.direction)
126
- ray_distances = self.rays.get_ray_distances()
127
- normalized_ray_distances = [min(distance / self.rays.max_distance, 1.0) for distance in ray_distances]
128
- steering_info = self.detect_steering_need(ray_distances)
129
- state = [
130
- self.car.velocity / self.car.max_velocity,
131
- self.car.direction.x,
132
- self.car.direction.y,
133
- int(self.car.is_braking),
134
- ]
135
- state.extend(normalized_ray_distances)
136
- state.extend([
137
- float(steering_info['needed']),
138
- steering_info['direction'],
139
- steering_info['urgency'],
140
- steering_info['space_diff'],
141
- steering_info['left_space'],
142
- steering_info['right_space'],
143
- steering_info['center_distance']
144
- ])
145
- total_goals = len(self.map_generator.goals)
146
- progress = self.current_goal_index / max(total_goals, 1)
147
- state.append(progress)
148
- state.append(self.last_action / 4.0)
149
- speed_change = self.car.velocity - self.previous_speed
150
- self.speed_history.append(speed_change)
151
- avg_speed_change = sum(self.speed_history) / max(len(self.speed_history), 1)
152
- state.extend([speed_change / 100.0, avg_speed_change / 100.0])
153
- self.previous_speed = self.car.velocity
154
- return np.array(state, dtype=np.float32)
155
-
156
- def execute_action_dispatch(self, action, dt):
157
- action_int = int(action)
158
- self.last_action = action_int
159
- keys = {'w': False, 'a': False, 'd': False, 's': False}
160
- steer_factor = 1.0
161
- if action_int == 0:
162
- keys['w'] = True
163
- elif action_int == 1:
164
- keys['a'] = True
165
- steer_factor = 1.0
166
- elif action_int == 2:
167
- keys['d'] = True
168
- steer_factor = 1.0
169
- elif action_int == 3:
170
- keys['w'] = True
171
- keys['a'] = True
172
- steer_factor = 0.8
173
- elif action_int == 4:
174
- keys['w'] = True
175
- keys['d'] = True
176
- steer_factor = 0.8
177
- elif action_int == 5:
178
- keys['s'] = True
179
- original_brake = self.car.brake_deceleration
180
- self.car.brake_deceleration *= 0.6
181
- self.car.update(dt, keys, steer_factor)
182
- self.car.brake_deceleration = original_brake
183
- return
184
- elif action_int == 6:
185
- keys['s'] = True
186
- keys['a'] = True
187
- steer_factor = 1.2
188
- elif action_int == 7:
189
- keys['s'] = True
190
- keys['d'] = True
191
- steer_factor = 1.2
192
- self.car.update(dt, keys, steer_factor)
193
-
194
- def detect_curve_severity(self, ray_distances, steering_info):
195
- normalized_ray_distances = [min(distance / self.rays.max_distance, 1.0) for distance in ray_distances]
196
- longest_distance = max(normalized_ray_distances)
197
- longest_index = normalized_ray_distances.index(longest_distance)
198
- main_ray_index = 3
199
- if longest_index == main_ray_index:
200
- return 0.0
201
- left_adjacent_index = max(0, longest_index - 1)
202
- right_adjacent_index = min(len(normalized_ray_distances) - 1, longest_index + 1)
203
- left_adjacent_distance = normalized_ray_distances[left_adjacent_index]
204
- right_adjacent_distance = normalized_ray_distances[right_adjacent_index]
205
- if left_adjacent_distance > right_adjacent_distance:
206
- longer_adjacent_index = left_adjacent_index
207
- longer_adjacent_distance = left_adjacent_distance
208
- else:
209
- longer_adjacent_index = right_adjacent_index
210
- longer_adjacent_distance = right_adjacent_distance
211
- weight = longer_adjacent_distance / longest_distance
212
- ray_angles = [-60, -30, -15, 0, 15, 30, 60]
213
- longest_ray_angle = ray_angles[longest_index]
214
- longer_adjacent_angle = ray_angles[longer_adjacent_index]
215
- longest_pos_angle = longest_ray_angle + weight * (longer_adjacent_angle - longest_ray_angle)
216
- front_ray_angle = ray_angles[main_ray_index]
217
- angle_difference = abs(longest_pos_angle - front_ray_angle)
218
- if angle_difference >= 50:
219
- curve_severity = 1.0
220
- else:
221
- curve_severity = angle_difference / 40.0
222
- return curve_severity
223
-
224
- def calculate_reward(self):
225
- self.rays.update(self.car.pos, self.car.direction)
226
- ray_distances = self.rays.get_ray_distances()
227
- collision = self.rays.has_zero_length_ray()
228
- if collision:
229
- return -100.0, collision, False
230
- steering_info = self.detect_steering_need(ray_distances)
231
- reward = 0.0
232
- curve_severity = self.detect_curve_severity(ray_distances, steering_info)
233
- center_distance = ray_distances[3] / self.rays.max_distance
234
- if center_distance > 0.25:
235
- reward += 0.25 * self.car.velocity - 6
236
- if curve_severity > 0.1:
237
- if curve_severity > 0.5:
238
- if 0.125 < self.car.velocity < 0.25:
239
- reward += self.car.velocity / 10
240
- else:
241
- reward += -2
242
- elif curve_severity > 0.25:
243
- if 0.15 < self.car.velocity < 0.35:
244
- reward += self.car.velocity / 12
245
- else:
246
- reward += -2
247
- else:
248
- if 0.35 < self.car.velocity < 0.7:
249
- reward += self.car.velocity / 10
250
- else:
251
- reward += -2
252
- else:
253
- if self.car.velocity > 40:
254
- reward += self.car.velocity / 20
255
- elif self.car.velocity < 25:
256
- reward += -0.5
257
- if hasattr(self, 'speed_consistency_tracker'):
258
- self.speed_consistency_tracker = {'appropriate': False, 'count': 0}
259
- if steering_info['needed']:
260
- steering_urgency = steering_info['urgency']
261
- base_steering_reward = 5.0 + (steering_urgency * 4.0)
262
- correct_action = False
263
- if steering_info['direction'] == -1:
264
- if self.last_action in [1, 3, 6]:
265
- correct_action = True
266
- if self.steering_persistence['direction'] == -1:
267
- self.steering_persistence['count'] += 2
268
- persistence_bonus = min(3.0, self.steering_persistence['count'] * 0.5)
269
- base_steering_reward += persistence_bonus
270
- else:
271
- self.steering_persistence = {'direction': -1, 'count': 1}
272
- if curve_severity > 0.4 and self.last_action == 6:
273
- base_steering_reward += 5.0
274
- elif steering_info['direction'] == 1:
275
- if self.last_action in [2, 4, 7]:
276
- correct_action = True
277
- if self.steering_persistence['direction'] == 1:
278
- self.steering_persistence['count'] += 2
279
- persistence_bonus = min(3.0, self.steering_persistence['count'] * 0.0)
280
- base_steering_reward += persistence_bonus
281
- else:
282
- self.steering_persistence = {'direction': 1, 'count': 1}
283
- if curve_severity > 0.4 and self.last_action == 7:
284
- base_steering_reward += 5.0
285
- if correct_action:
286
- reward += base_steering_reward
287
- else:
288
- self.steering_persistence = {'direction': 0, 'count': 0}
289
- if steering_urgency > 0.6:
290
- penalty = -4.0 * steering_urgency
291
- reward += penalty
292
- else:
293
- self.steering_persistence = {'direction': 0, 'count': 0}
294
- speed_factor = self.car.velocity / self.car.max_velocity
295
- min_side_distance = min([ray_distances[i] for i in [0, 1, 2, 4, 5, 6]]) / self.rays.max_distance
296
- center_distance = ray_distances[3] / self.rays.max_distance
297
- if min_side_distance < 0.01:
298
- danger_penalty = -5.0 * (1.0 - min_side_distance * 12.5) * (0.5 + speed_factor * 0.5)
299
- reward += danger_penalty
300
- elif min_side_distance < 0.0166:
301
- if speed_factor > 0.7:
302
- minor_penalty = -2 * (1.0 - min_side_distance * 6.67)
303
- reward += minor_penalty
304
- if 0.01666 <= min_side_distance and center_distance > 0.2:
305
- safety_efficiency_bonus = 0.3
306
- if 0.3 <= speed_factor <= 0.8:
307
- safety_efficiency_bonus += 0.2
308
- reward += safety_efficiency_bonus
309
- total_goals = len(self.map_generator.goals)
310
- if self.current_goal_index < total_goals:
311
- goal = self.map_generator.goals[self.current_goal_index]
312
- dist = point_to_line_distance(self.car.pos, goal[0], goal[1])
313
- if dist < 8:
314
- reward += 7.5
315
- self.passed_goals.append(self.current_goal_index)
316
- self.current_goal_index += 1
317
- all_goals_completed = self.current_goal_index >= total_goals
318
- if all_goals_completed:
319
- reward += 20.0
320
- reward = max(-15.0, min(reward, 12.0))
321
- self.prev_pos = pygame.math.Vector2(self.car.pos)
322
- self.last_steering_reward = reward
323
- return reward, collision, all_goals_completed
324
-
325
- def game_loop():
326
- try:
327
- pygame.init()
328
- pygame.display.set_mode((1, 1), pygame.NOFRAME)
329
- screen = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
330
- env = TrainingEnvironment(ACTION_SPACE)
331
- env.reset()
332
- agent = PPOAgent(state_size, ACTION_SPACE)
333
- agent.load(LOADED_MODEL)
334
- steps = 0
335
- action_counts = [0] * ACTION_SPACE
336
- while True:
337
- for event in pygame.event.get():
338
- if event.type == pygame.QUIT:
339
- pygame.quit()
340
- return
341
- state = env.get_state()
342
- action, _ = agent.select_action(state)
343
- action_int = int(action)
344
- action_counts[action_int] += 1
345
- env.execute_action_dispatch(action_int, DT)
346
- reward, collision, all_goals_completed = env.calculate_reward()
347
- env.rays.update(env.car.pos, env.car.direction)
348
- if collision or all_goals_completed:
349
- env.reset()
350
- steps += 1
351
- screen.fill((255, 255,255))
352
- env.map_generator.draw(screen)
353
- env.car.draw(screen)
354
- for i, (angle, offset) in enumerate(zip([-60, -30, -15, 0, 15, 30, 60], [14, 22, 27, 26, 27, 22, 14])):
355
- if i < len(env.rays.last_collisions):
356
- ray_dir = env.car.direction.rotate(angle).normalize()
357
- origin = env.car.pos + ray_dir * offset
358
- end_point = env.rays.last_collisions[i]
359
- pygame.draw.line(screen, (255, 255, 0),
360
- (int(origin.x), int(origin.y)),
361
- (int(end_point.x), int(end_point.y)),
362
- width=2)
363
- frame_array = pygame.surfarray.array3d(screen)
364
- frame_array = np.transpose(frame_array, (1, 0, 2))
365
- pil_image = Image.fromarray(frame_array)
366
- pil_image = pil_image.resize((SCREEN_WIDTH, SCREEN_HEIGHT))
367
- try:
368
- frame_queue.put(pil_image, block=False)
369
- except queue.Full:
370
- pass
371
- clock.tick(SIMULATION_FPS)
372
- except Exception as e:
373
- print(f"Error in game loop: {e}")
374
-
375
- def get_frame():
376
- try:
377
- return frame_queue.get_nowait()
378
- except queue.Empty:
379
- return Image.new('RGB', (SCREEN_WIDTH, SCREEN_HEIGHT), (0, 0, 0))
380
-
381
- css = """#game-image {
382
- height: calc(100vw * 9 / 16) !important;
383
- object-fit: contain;
384
- margin: 0 auto;
385
- display: block;
386
- }"""
387
-
388
- def execute_interference():
389
- game_thread = threading.Thread(target=game_loop)
390
- game_thread.daemon = True
391
- game_thread.start()
392
- with gr.Blocks(css=css) as demo:
393
- with gr.Column():
394
- img = gr.Image(type="pil", label="Game Stream", elem_id="game-image", scale=1, min_width=0)
395
- timer = gr.Timer(value=0.00833)
396
- timer.tick(fn=get_frame, inputs=None, outputs=img)
397
- demo.launch()
398
-
399
- if __name__ == "__main__":
400
- execute_interference()