YashsharmaPhD commited on
Commit
e71fd51
·
verified ·
1 Parent(s): b8f4f42

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -36
app.py CHANGED
@@ -4,9 +4,10 @@ import matplotlib.patches as patches
4
  import matplotlib.image as mpimg
5
  import numpy as np
6
  import random
 
7
  import threading
8
  import time
9
- import os
10
 
11
  # Global state
12
  pose = {"x": 0, "z": 0, "angle": 0}
@@ -15,10 +16,10 @@ obstacle_hits = []
15
  color_index = 0
16
  rgb_colors = ['red', 'green', 'blue']
17
  noise_enabled = True
18
- auto_mode = False
19
- auto_thread = None
20
  obstacles = []
 
21
 
 
22
  def generate_obstacles(count=10):
23
  return [{
24
  "x": random.uniform(-8, 8),
@@ -26,51 +27,61 @@ def generate_obstacles(count=10):
26
  "radius": random.uniform(0.5, 1.2)
27
  } for _ in range(count)]
28
 
 
 
 
 
 
 
 
 
 
29
  def reset_sim(count):
30
  global pose, trajectory, obstacles, obstacle_hits, color_index
31
  pose = {"x": 0, "z": 0, "angle": 0}
32
  trajectory = [(0, 0)]
33
  obstacle_hits = []
34
  color_index = 0
35
- obstacles.clear()
36
- obstacles.extend(generate_obstacles(count))
37
  return render_env(), render_slam_map(), None, f"Simulation Reset with {count} obstacles"
38
 
39
- def toggle_noise():
40
- global noise_enabled
41
- noise_enabled = not noise_enabled
42
- return "Noise: ON" if noise_enabled else "Noise: OFF"
43
-
44
  def check_collision(x, z):
45
  for obs in obstacles:
46
- dist = np.sqrt((obs["x"] - x) ** 2 + (obs["z"] - z) ** 2)
47
  if dist <= obs["radius"] + 0.2:
48
  return True
49
  return False
50
 
 
51
  def move_robot(direction):
52
  global pose, trajectory
53
  step = 1
54
  direction = direction.upper()
55
 
56
- new_x, new_z = pose["x"], pose["z"]
57
  if direction == "W":
58
- new_z += step
59
  pose["angle"] = 90
60
  elif direction == "S":
61
- new_z -= step
62
  pose["angle"] = -90
63
  elif direction == "A":
64
- new_x -= step
65
  pose["angle"] = 180
66
  elif direction == "D":
67
- new_x += step
68
  pose["angle"] = 0
69
  else:
70
  return render_env(), render_slam_map(), None, "❌ Invalid Key"
71
 
72
  if check_collision(new_x, new_z):
73
- return render_env(), render_slam_map(), "collision1.mp3", "🚫 Collision Detected!"
 
 
 
 
 
 
74
 
75
  pose["x"], pose["z"] = new_x, new_z
76
  if noise_enabled:
@@ -82,11 +93,13 @@ def move_robot(direction):
82
 
83
  return render_env(), render_slam_map(), None, "Moved " + direction
84
 
 
85
  def render_env():
 
86
  fig, ax = plt.subplots()
87
  ax.set_xlim(-10, 10)
88
  ax.set_ylim(-10, 10)
89
- ax.set_title("SLAM Environment")
90
 
91
  try:
92
  bg = mpimg.imread("map.png")
@@ -113,6 +126,7 @@ def render_env():
113
  plt.close(fig)
114
  return fig
115
 
 
116
  def render_slam_map():
117
  global color_index
118
  fig, ax = plt.subplots()
@@ -131,49 +145,49 @@ def render_slam_map():
131
  plt.close(fig)
132
  return fig
133
 
 
134
  def handle_text_input(direction):
135
  return move_robot(direction.strip().upper())
136
 
137
- # --------- Automatic Mode Logic ---------
138
- def auto_move_loop(update_callback):
139
  global auto_mode
140
  directions = ['W', 'A', 'S', 'D']
141
  while auto_mode:
142
  direction = random.choice(directions)
143
- env, slam, audio, msg = move_robot(direction)
144
- update_callback(env, slam, audio, f"[AUTO] {msg}")
145
- time.sleep(1.0)
146
 
147
  def toggle_auto_mode(env_plot, slam_plot, collision_audio, status_text):
148
- global auto_mode, auto_thread
149
-
150
  auto_mode = not auto_mode
 
151
  if auto_mode:
152
- def update_ui(e, s, a, t):
153
  env_plot.update(value=e)
154
  slam_plot.update(value=s)
155
- collision_audio.update(value=a)
156
  status_text.update(value=t)
157
 
158
- auto_thread = threading.Thread(target=auto_move_loop, args=(update_ui,))
159
- auto_thread.daemon = True
160
- auto_thread.start()
161
  return "🟢 Auto Mode: ON"
162
  else:
163
  return "⚪ Auto Mode: OFF"
164
 
165
- # --------- Gradio UI ---------
166
  with gr.Blocks() as demo:
167
- gr.Markdown("## 🤖 SLAM Simulation: Manual + Auto Navigation")
168
 
169
  obstacle_slider = gr.Slider(1, 20, value=10, step=1, label="Number of Obstacles")
170
- direction_input = gr.Textbox(label="Type W / A / S / D", placeholder="e.g., W")
171
  status_text = gr.Textbox(label="Status")
172
- collision_audio = gr.Audio(label="Collision Sound", interactive=False)
173
 
174
  with gr.Row():
175
  with gr.Column():
176
- env_plot = gr.Plot(label="Environment")
177
  with gr.Column():
178
  slam_plot = gr.Plot(label="SLAM Map")
179
 
@@ -192,7 +206,7 @@ with gr.Blocks() as demo:
192
  d.click(fn=move_robot, inputs=gr.State("D"), outputs=[env_plot, slam_plot, collision_audio, status_text])
193
  reset.click(fn=reset_sim, inputs=[obstacle_slider], outputs=[env_plot, slam_plot, collision_audio, status_text])
194
  toggle.click(fn=lambda: (None, None, None, toggle_noise()), outputs=[env_plot, slam_plot, collision_audio, status_text])
195
- direction_input.submit(fn=handle_text_input, inputs=direction_input, outputs=[env_plot, slam_plot, collision_audio, status_text])
196
  auto.click(fn=toggle_auto_mode, inputs=[env_plot, slam_plot, collision_audio, status_text], outputs=auto)
 
197
 
198
  demo.launch()
 
4
  import matplotlib.image as mpimg
5
  import numpy as np
6
  import random
7
+ import os
8
  import threading
9
  import time
10
+ from IPython.display import Audio, display
11
 
12
  # Global state
13
  pose = {"x": 0, "z": 0, "angle": 0}
 
16
  color_index = 0
17
  rgb_colors = ['red', 'green', 'blue']
18
  noise_enabled = True
 
 
19
  obstacles = []
20
+ auto_mode = False
21
 
22
+ # Generate obstacles
23
  def generate_obstacles(count=10):
24
  return [{
25
  "x": random.uniform(-8, 8),
 
27
  "radius": random.uniform(0.5, 1.2)
28
  } for _ in range(count)]
29
 
30
+ obstacles = generate_obstacles(10)
31
+
32
+ # Toggle noise
33
+ def toggle_noise():
34
+ global noise_enabled
35
+ noise_enabled = not noise_enabled
36
+ return "Noise: ON" if noise_enabled else "Noise: OFF"
37
+
38
+ # Reset simulation
39
  def reset_sim(count):
40
  global pose, trajectory, obstacles, obstacle_hits, color_index
41
  pose = {"x": 0, "z": 0, "angle": 0}
42
  trajectory = [(0, 0)]
43
  obstacle_hits = []
44
  color_index = 0
45
+ obstacles = generate_obstacles(int(count))
 
46
  return render_env(), render_slam_map(), None, f"Simulation Reset with {count} obstacles"
47
 
48
+ # Check collision
 
 
 
 
49
  def check_collision(x, z):
50
  for obs in obstacles:
51
+ dist = np.sqrt((obs["x"] - x)**2 + (obs["z"] - z)**2)
52
  if dist <= obs["radius"] + 0.2:
53
  return True
54
  return False
55
 
56
+ # Movement logic
57
  def move_robot(direction):
58
  global pose, trajectory
59
  step = 1
60
  direction = direction.upper()
61
 
 
62
  if direction == "W":
63
+ new_x, new_z = pose["x"], pose["z"] + step
64
  pose["angle"] = 90
65
  elif direction == "S":
66
+ new_x, new_z = pose["x"], pose["z"] - step
67
  pose["angle"] = -90
68
  elif direction == "A":
69
+ new_x, new_z = pose["x"] - step, pose["z"]
70
  pose["angle"] = 180
71
  elif direction == "D":
72
+ new_x, new_z = pose["x"] + step, pose["z"]
73
  pose["angle"] = 0
74
  else:
75
  return render_env(), render_slam_map(), None, "❌ Invalid Key"
76
 
77
  if check_collision(new_x, new_z):
78
+ # Play collision1.mp3 directly if in Jupyter/Colab
79
+ if os.path.exists("collision1.mp3"):
80
+ try:
81
+ display(Audio("collision1.mp3", autoplay=True))
82
+ except:
83
+ pass
84
+ return render_env(), render_slam_map(), None, "🚫 Collision detected!"
85
 
86
  pose["x"], pose["z"] = new_x, new_z
87
  if noise_enabled:
 
93
 
94
  return render_env(), render_slam_map(), None, "Moved " + direction
95
 
96
+ # Environment view
97
  def render_env():
98
+ global obstacle_hits
99
  fig, ax = plt.subplots()
100
  ax.set_xlim(-10, 10)
101
  ax.set_ylim(-10, 10)
102
+ ax.set_title("SLAM Environment View")
103
 
104
  try:
105
  bg = mpimg.imread("map.png")
 
126
  plt.close(fig)
127
  return fig
128
 
129
+ # SLAM map
130
  def render_slam_map():
131
  global color_index
132
  fig, ax = plt.subplots()
 
145
  plt.close(fig)
146
  return fig
147
 
148
+ # Text command
149
  def handle_text_input(direction):
150
  return move_robot(direction.strip().upper())
151
 
152
+ # Auto movement thread
153
+ def auto_movement(update_callback):
154
  global auto_mode
155
  directions = ['W', 'A', 'S', 'D']
156
  while auto_mode:
157
  direction = random.choice(directions)
158
+ env, slam, _, msg = move_robot(direction)
159
+ update_callback(env, slam, None, f"[AUTO] {msg}")
160
+ time.sleep(1)
161
 
162
  def toggle_auto_mode(env_plot, slam_plot, collision_audio, status_text):
163
+ global auto_mode
 
164
  auto_mode = not auto_mode
165
+
166
  if auto_mode:
167
+ def update_ui(e, s, _, t):
168
  env_plot.update(value=e)
169
  slam_plot.update(value=s)
 
170
  status_text.update(value=t)
171
 
172
+ thread = threading.Thread(target=auto_movement, args=(update_ui,))
173
+ thread.daemon = True
174
+ thread.start()
175
  return "🟢 Auto Mode: ON"
176
  else:
177
  return "⚪ Auto Mode: OFF"
178
 
179
+ # UI
180
  with gr.Blocks() as demo:
181
+ gr.Markdown("## 🤖 SLAM Simulation with Auto Mode + Collision Sound (No Play Button)")
182
 
183
  obstacle_slider = gr.Slider(1, 20, value=10, step=1, label="Number of Obstacles")
184
+ direction_input = gr.Textbox(label="Type W / A / S / D and press Enter", placeholder="e.g., W")
185
  status_text = gr.Textbox(label="Status")
186
+ collision_audio = gr.Audio(label="(Hidden) Collision Sound", interactive=False, visible=False)
187
 
188
  with gr.Row():
189
  with gr.Column():
190
+ env_plot = gr.Plot(label="Robot View")
191
  with gr.Column():
192
  slam_plot = gr.Plot(label="SLAM Map")
193
 
 
206
  d.click(fn=move_robot, inputs=gr.State("D"), outputs=[env_plot, slam_plot, collision_audio, status_text])
207
  reset.click(fn=reset_sim, inputs=[obstacle_slider], outputs=[env_plot, slam_plot, collision_audio, status_text])
208
  toggle.click(fn=lambda: (None, None, None, toggle_noise()), outputs=[env_plot, slam_plot, collision_audio, status_text])
 
209
  auto.click(fn=toggle_auto_mode, inputs=[env_plot, slam_plot, collision_audio, status_text], outputs=auto)
210
+ direction_input.submit(fn=handle_text_input, inputs=direction_input, outputs=[env_plot, slam_plot, collision_audio, status_text])
211
 
212
  demo.launch()