.env.example DELETED
File without changes
.gitattributes CHANGED
@@ -38,7 +38,3 @@ assets/scene_2.png filter=lfs diff=lfs merge=lfs -text
38
  assets/scene_3.png filter=lfs diff=lfs merge=lfs -text
39
  assets/scene_4.png filter=lfs diff=lfs merge=lfs -text
40
  assets/scene_5.png filter=lfs diff=lfs merge=lfs -text
41
- scene_assets/scene1_no_ceiling.glb filter=lfs diff=lfs merge=lfs -text
42
- scene_assets/scene2_no_ceiling.glb filter=lfs diff=lfs merge=lfs -text
43
- scene_assets/scene3_no_ceiling.glb filter=lfs diff=lfs merge=lfs -text
44
- scene_assets/scene4_no_ceiling.glb filter=lfs diff=lfs merge=lfs -text
 
38
  assets/scene_3.png filter=lfs diff=lfs merge=lfs -text
39
  assets/scene_4.png filter=lfs diff=lfs merge=lfs -text
40
  assets/scene_5.png filter=lfs diff=lfs merge=lfs -text
 
 
 
 
.gradio/certificate.pem DELETED
@@ -1,31 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
3
- TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
4
- cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
5
- WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
6
- ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
7
- MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
8
- h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
9
- 0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
10
- A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
11
- T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
12
- B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
13
- B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
14
- KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
15
- OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
16
- jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
17
- qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
18
- rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
19
- HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
20
- hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
21
- ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
22
- 3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
23
- NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
24
- ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
25
- TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
26
- jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
27
- oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
28
- 4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
29
- mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
30
- emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
31
- -----END CERTIFICATE-----
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.py CHANGED
@@ -1,52 +1,17 @@
1
  # main.py
2
  # 主入口文件,负责启动 Gradio UI
3
  import gradio as gr
4
- from config import SCENE_CONFIGS, MODEL_CHOICES, MODE_CHOICES, EPISODE_CONFIGS
5
  from backend_api import submit_to_backend, get_task_status, get_task_result
6
  from logging_utils import log_access, log_submission, is_request_allowed
7
  from simulation import stream_simulation_results, convert_to_h264, create_final_video_from_oss_images
8
- from ui_components import update_history_display, update_scene_display, update_episode_display, update_log_display, get_scene_instruction
9
  from oss_utils import download_oss_file, get_user_tmp_dir, cleanup_user_tmp_dir, oss_file_exists, clean_oss_result_path
10
  import os
11
  from datetime import datetime
12
 
13
  SESSION_TASKS = {}
14
 
15
- # 添加版本检查函数
16
- def get_gradio_versions():
17
- """获取Gradio相关包的版本信息"""
18
- try:
19
- import gradio
20
- gradio_version = gradio.__version__
21
- except:
22
- gradio_version = "Unknown"
23
-
24
- try:
25
- import gradio_client
26
- gradio_client_version = gradio_client.__version__
27
- except:
28
- gradio_client_version = "Not installed"
29
-
30
- return gradio_version, gradio_client_version
31
-
32
- def display_version_info():
33
- """显示版本信息"""
34
- gradio_version, gradio_client_version = get_gradio_versions()
35
-
36
- # 在控制台输出版本信息
37
- print("=" * 50)
38
- print("📦 Package Versions:")
39
- print(f" Gradio: {gradio_version}")
40
- print(f" Gradio Client: {gradio_client_version}")
41
- print("=" * 50)
42
-
43
- # 返回格式化的版本信息字符串
44
- version_info = f"""**📦 Package Versions:**
45
- - **Gradio**: `{gradio_version}`
46
- - **Gradio Client**: `{gradio_client_version}`"""
47
- return version_info
48
-
49
-
50
  def run_simulation(scene, model, mode, prompt, history, request: gr.Request):
51
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
52
  scene_desc = SCENE_CONFIGS.get(scene, {}).get("description", scene)
@@ -171,25 +136,6 @@ custom_css = """
171
  .history-accordion {
172
  margin-bottom: 10px;
173
  }
174
- .scene-preview {
175
- height: 400px;
176
- border: 1px solid #ddd;
177
- border-radius: 8px;
178
- overflow: hidden;
179
- }
180
- .version-info {
181
- background: #e8f4fd;
182
- border: 1px solid #bee5eb;
183
- border-radius: 6px;
184
- padding: 10px;
185
- margin: 10px 0;
186
- font-size: 0.9em;
187
- }
188
- .dark .version-info {
189
- background: #1a2a3a;
190
- border-color: #3a5a7a;
191
- color: #e0e0e0;
192
- }
193
  """
194
 
195
  header_html = """
@@ -224,40 +170,22 @@ header_html = """
224
  with gr.Blocks(title="InternNav Model Inference Demo", css=custom_css) as demo:
225
  gr.HTML(header_html)
226
 
227
- # 添加版本信息显示
228
- version_display = gr.Markdown(
229
- value="",
230
- elem_classes=["version-info"],
231
- visible=True
232
- )
233
-
234
  history_state = gr.State([])
235
  with gr.Row():
236
  with gr.Column(elem_id="simulation-panel"):
237
  gr.Markdown("### Simulation Settings")
238
- with gr.Row():
239
- scene_dropdown = gr.Dropdown(
240
- label="Choose a scene",
241
- choices=list(SCENE_CONFIGS.keys()),
242
- value="demo1",
243
- interactive=True
244
- )
245
- episode_dropdown = gr.Dropdown(
246
- label="Select Start Position",
247
- choices=list(EPISODE_CONFIGS.keys()),
248
- value="episode_1",
249
- interactive=True
250
- )
251
-
252
- with gr.Row():
253
- scene_preview = gr.Model3D(
254
- elem_classes=["scene-preview"],
255
- camera_position=(90.0, 120, 20000.0)
256
- )
257
- fps_preview = gr.Image(label="FPS Preview")
258
-
259
- scene_description = gr.Markdown("### Scene preview")
260
-
261
  prompt_input = gr.Textbox(
262
  label="Navigation Prompt",
263
  value="Walk past the left side of the bed and stop in the doorway.",
@@ -281,16 +209,6 @@ with gr.Blocks(title="InternNav Model Inference Demo", css=custom_css) as demo:
281
  fn=lambda scene: [update_scene_display(scene)[0], update_scene_display(scene)[1], get_scene_instruction(scene)],
282
  inputs=scene_dropdown,
283
  outputs=[scene_description, scene_preview, prompt_input]
284
- ).then(
285
- update_episode_display,
286
- inputs=[scene_dropdown, episode_dropdown],
287
- outputs=[fps_preview]
288
- )
289
-
290
- episode_dropdown.change(
291
- update_episode_display,
292
- inputs=[scene_dropdown, episode_dropdown],
293
- outputs=[fps_preview]
294
  )
295
 
296
  submit_btn = gr.Button("Start Navigation Simulation", variant="primary")
@@ -337,11 +255,8 @@ with gr.Blocks(title="InternNav Model Inference Demo", css=custom_css) as demo:
337
  queue=True
338
  )
339
  demo.load(
340
- fn=lambda: [display_version_info(), update_scene_display("demo1")[0], update_scene_display("demo1")[1]],
341
- outputs=[version_display, scene_description, scene_preview]
342
- ).then(
343
- fn=lambda: update_episode_display("demo1", "episode_1"),
344
- outputs=[fps_preview]
345
  )
346
  demo.load(
347
  fn=record_access,
@@ -353,9 +268,6 @@ with gr.Blocks(title="InternNav Model Inference Demo", css=custom_css) as demo:
353
  demo.unload(fn=cleanup_session)
354
 
355
  if __name__ == "__main__":
356
- # 在启动时显示版本信息
357
- display_version_info()
358
-
359
  demo.launch(
360
  server_name="0.0.0.0",
361
  server_port=7860, # Hugging Face Space默认端口
 
1
  # main.py
2
  # 主入口文件,负责启动 Gradio UI
3
  import gradio as gr
4
+ from config import SCENE_CONFIGS, MODEL_CHOICES, MODE_CHOICES
5
  from backend_api import submit_to_backend, get_task_status, get_task_result
6
  from logging_utils import log_access, log_submission, is_request_allowed
7
  from simulation import stream_simulation_results, convert_to_h264, create_final_video_from_oss_images
8
+ from ui_components import update_history_display, update_scene_display, update_log_display, get_scene_instruction
9
  from oss_utils import download_oss_file, get_user_tmp_dir, cleanup_user_tmp_dir, oss_file_exists, clean_oss_result_path
10
  import os
11
  from datetime import datetime
12
 
13
  SESSION_TASKS = {}
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  def run_simulation(scene, model, mode, prompt, history, request: gr.Request):
16
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
17
  scene_desc = SCENE_CONFIGS.get(scene, {}).get("description", scene)
 
136
  .history-accordion {
137
  margin-bottom: 10px;
138
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  """
140
 
141
  header_html = """
 
170
  with gr.Blocks(title="InternNav Model Inference Demo", css=custom_css) as demo:
171
  gr.HTML(header_html)
172
 
 
 
 
 
 
 
 
173
  history_state = gr.State([])
174
  with gr.Row():
175
  with gr.Column(elem_id="simulation-panel"):
176
  gr.Markdown("### Simulation Settings")
177
+ scene_dropdown = gr.Dropdown(
178
+ label="Choose a scene",
179
+ choices=list(SCENE_CONFIGS.keys()),
180
+ value="demo1",
181
+ interactive=True
182
+ )
183
+ scene_description = gr.Markdown("")
184
+ scene_preview = gr.Image(
185
+ label="Scene Preview",
186
+ elem_classes=["scene-preview"],
187
+ interactive=False
188
+ )
 
 
 
 
 
 
 
 
 
 
 
189
  prompt_input = gr.Textbox(
190
  label="Navigation Prompt",
191
  value="Walk past the left side of the bed and stop in the doorway.",
 
209
  fn=lambda scene: [update_scene_display(scene)[0], update_scene_display(scene)[1], get_scene_instruction(scene)],
210
  inputs=scene_dropdown,
211
  outputs=[scene_description, scene_preview, prompt_input]
 
 
 
 
 
 
 
 
 
 
212
  )
213
 
214
  submit_btn = gr.Button("Start Navigation Simulation", variant="primary")
 
255
  queue=True
256
  )
257
  demo.load(
258
+ fn=lambda: update_scene_display("demo1"),
259
+ outputs=[scene_description, scene_preview]
 
 
 
260
  )
261
  demo.load(
262
  fn=record_access,
 
268
  demo.unload(fn=cleanup_session)
269
 
270
  if __name__ == "__main__":
 
 
 
271
  demo.launch(
272
  server_name="0.0.0.0",
273
  server_port=7860, # Hugging Face Space默认端口
app_old.py DELETED
@@ -1,277 +0,0 @@
1
- # main.py
2
- # 主入口文件,负责启动 Gradio UI
3
- import gradio as gr
4
- from config import SCENE_CONFIGS, MODEL_CHOICES, MODE_CHOICES
5
- from backend_api import submit_to_backend, get_task_status, get_task_result
6
- from logging_utils import log_access, log_submission, is_request_allowed
7
- from simulation import stream_simulation_results, convert_to_h264, create_final_video_from_oss_images
8
- from ui_components import update_history_display, update_scene_display, update_log_display, get_scene_instruction
9
- from oss_utils import download_oss_file, get_user_tmp_dir, cleanup_user_tmp_dir, oss_file_exists, clean_oss_result_path
10
- import os
11
- from datetime import datetime
12
-
13
- SESSION_TASKS = {}
14
-
15
- def run_simulation(scene, model, mode, prompt, history, request: gr.Request):
16
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
17
- scene_desc = SCENE_CONFIGS.get(scene, {}).get("description", scene)
18
- user_ip = request.client.host if request else "unknown"
19
- session_id = request.session_hash
20
-
21
- if not is_request_allowed(user_ip):
22
- log_submission(scene, prompt, model, user_ip, "IP blocked temporarily")
23
- raise gr.Error("Too many requests from this IP. Please wait and try again one minute later.")
24
-
25
- # 提交任务到后端
26
- submission_result = submit_to_backend(scene, prompt, mode, model, user_ip)
27
- if submission_result.get("status") != "pending":
28
- log_submission(scene, prompt, model, user_ip, "Submission failed")
29
- raise gr.Error(f"Submission failed: {submission_result.get('message', 'unknown issue')}")
30
-
31
- try:
32
- task_id = submission_result["task_id"]
33
- SESSION_TASKS[session_id] = task_id
34
- gr.Info(f"Simulation started, task_id: {task_id}")
35
-
36
- import time
37
- time.sleep(5)
38
- status = get_task_status(task_id)
39
- # OSS上的结果文件夹路径,不再检查本地路径是否存在
40
- result_folder = clean_oss_result_path(status.get("result", f"gradio_demo/tasks/{task_id}"), task_id)
41
-
42
- except Exception as e:
43
- log_submission(scene, prompt, model, user_ip, str(e))
44
- raise gr.Error(f"error occurred when parsing submission result from backend: {str(e)}")
45
-
46
- # 流式输出视频片段(从OSS读取)
47
- try:
48
- for video_path in stream_simulation_results(result_folder, task_id, request):
49
- if video_path:
50
- yield video_path, history
51
- except Exception as e:
52
- log_submission(scene, prompt, model, user_ip, str(e))
53
- raise gr.Error(f"流式输出过程中出错: {str(e)}")
54
-
55
- # 获取最终任务状态
56
- status = get_task_status(task_id)
57
- if status.get("status") == "completed":
58
- try:
59
- # 从OSS上的所有图片拼接成最终视频(6帧每秒)
60
- gr.Info("Creating final video from all OSS images...")
61
- video_path = create_final_video_from_oss_images(result_folder, task_id, request, fps=6)
62
- gr.Info(f"Final video created successfully with 6 fps!")
63
-
64
- except Exception as e:
65
- print(f"Error creating final video from OSS images: {e}")
66
- log_submission(scene, prompt, model, user_ip, f"Final video creation failed: {str(e)}")
67
- video_path = None
68
- new_entry = {
69
- "timestamp": timestamp,
70
- "scene": scene,
71
- "model": model,
72
- "mode": mode,
73
- "prompt": prompt,
74
- "video_path": video_path
75
- }
76
- updated_history = history + [new_entry]
77
- if len(updated_history) > 10:
78
- updated_history = updated_history[:10]
79
- log_submission(scene, prompt, model, user_ip, "success")
80
- gr.Info("Simulation completed successfully!")
81
- yield None, updated_history
82
- elif status.get("status") == "failed":
83
- log_submission(scene, prompt, model, user_ip, status.get('result', 'backend error'))
84
- raise gr.Error(f"任务执行失败: {status.get('result', 'backend 未知错误')}")
85
- yield None, history
86
- elif status.get("status") == "terminated":
87
- log_submission(scene, prompt, model, user_ip, "terminated")
88
- # 对于终止的任务,不再检查本地文件
89
- yield None, history
90
- else:
91
- log_submission(scene, prompt, model, user_ip, "missing task's status from backend")
92
- raise gr.Error("missing task's status from backend")
93
- yield None, history
94
-
95
- def cleanup_session(request: gr.Request):
96
- session_id = request.session_hash
97
- task_id = SESSION_TASKS.pop(session_id, None)
98
- from config import BACKEND_URL
99
- import requests
100
- if task_id:
101
- try:
102
- requests.post(f"{BACKEND_URL}/predict/terminate/{task_id}", timeout=3)
103
- except Exception:
104
- pass
105
-
106
- # 清理用户临时目录
107
- cleanup_user_tmp_dir(session_id)
108
-
109
- def record_access(request: gr.Request):
110
- user_ip = request.client.host if request else "unknown"
111
- user_agent = request.headers.get("user-agent", "unknown")
112
- log_access(user_ip, user_agent)
113
- return update_log_display()
114
-
115
-
116
-
117
- custom_css = """
118
- #simulation-panel {
119
- border-radius: 8px;
120
- padding: 20px;
121
- background: #f9f9f9;
122
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
123
- }
124
- #result-panel {
125
- border-radius: 8px;
126
- padding: 20px;
127
- background: #f0f8ff;
128
- }
129
- .dark #simulation-panel { background: #2a2a2a; }
130
- .dark #result-panel { background: #1a2a3a; }
131
- .history-container {
132
- max-height: 600px;
133
- overflow-y: auto;
134
- margin-top: 20px;
135
- }
136
- .history-accordion {
137
- margin-bottom: 10px;
138
- }
139
- """
140
-
141
- header_html = """
142
- <div style="display: flex; justify-content: space-between; align-items: center; width: 100%; margin-bottom: 20px; padding: 20px; background: linear-gradient(135deg, #e0e5ec 0%, #a7b5d0 100%); border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
143
- <div style="display: flex; align-items: center;">
144
- <img src="https://www.shlab.org.cn/static/img/index_14.685f6559.png" alt="Institution Logo" style="height: 60px; margin-right: 20px;">
145
- <div>
146
- <h1 style="margin: 0; color: #2c3e50; font-weight: 600;">🤖 InternNav Model Inference Demo</h1>
147
- <p style="margin: 4px 0 0 0; color: #5d6d7e; font-size: 0.9em;">Model trained on InternNav framework</p>
148
- </div>
149
- </div>
150
- <div style="display: flex; gap: 15px; align-items: center;">
151
- <a href="https://github.com/OpenRobotLab" target="_blank" style="text-decoration: none; transition: transform 0.2s;" onmouseover="this.style.transform='scale(1.1)'" onmouseout="this.style.transform='scale(1)'">
152
- <img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" alt="GitHub" style="height: 30px;">
153
- </a>
154
- <a href="https://huggingface.co/OpenRobotLab" target="_blank" style="text-decoration: none; transition: transform 0.2s;" onmouseover="this.style.transform='scale(1.1)'" onmouseout="this.style.transform='scale(1)'">
155
- <img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg" alt="HuggingFace" style="height: 30px;">
156
- </a>
157
- <a href="https://huggingface.co/spaces/OpenRobotLab/InternManip-eval-demo" target="_blank">
158
- <button style="padding: 8px 15px; background: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 500; transition: all 0.2s;"
159
- onmouseover="this.style.backgroundColor='#2980b9'; this.style.transform='scale(1.05)'"
160
- onmouseout="this.style.backgroundColor='#3498db'; this.style.transform='scale(1)'">
161
- Go to InternManip Demo
162
- </button>
163
- </a>
164
- </div>
165
- </div>
166
- """
167
-
168
-
169
-
170
- with gr.Blocks(title="InternNav Model Inference Demo", css=custom_css) as demo:
171
- gr.HTML(header_html)
172
-
173
- history_state = gr.State([])
174
- with gr.Row():
175
- with gr.Column(elem_id="simulation-panel"):
176
- gr.Markdown("### Simulation Settings")
177
- scene_dropdown = gr.Dropdown(
178
- label="Choose a scene",
179
- choices=list(SCENE_CONFIGS.keys()),
180
- value="demo1",
181
- interactive=True
182
- )
183
- scene_description = gr.Markdown("")
184
- scene_preview = gr.Image(
185
- label="Scene Preview",
186
- elem_classes=["scene-preview"],
187
- interactive=False
188
- )
189
- prompt_input = gr.Textbox(
190
- label="Navigation Prompt",
191
- value="Walk past the left side of the bed and stop in the doorway.",
192
- placeholder="e.g.: 'Walk past the left side of the bed and stop in the doorway.'",
193
- lines=2,
194
- max_lines=4
195
- )
196
- model_dropdown = gr.Dropdown(
197
- label="Chose a pretrained model",
198
- choices=MODEL_CHOICES,
199
- value=MODEL_CHOICES[0],
200
- interactive=True
201
- )
202
- mode_dropdown = gr.Dropdown(
203
- label="Select Mode",
204
- choices=MODE_CHOICES,
205
- value=MODE_CHOICES[0],
206
- interactive=True
207
- )
208
- scene_dropdown.change(
209
- fn=lambda scene: [update_scene_display(scene)[0], update_scene_display(scene)[1], get_scene_instruction(scene)],
210
- inputs=scene_dropdown,
211
- outputs=[scene_description, scene_preview, prompt_input]
212
- )
213
-
214
- submit_btn = gr.Button("Start Navigation Simulation", variant="primary")
215
- with gr.Column(elem_id="result-panel"):
216
- gr.Markdown("### Latest Simulation Result")
217
- video_output = gr.Video(
218
- label="Live",
219
- interactive=False,
220
- format="mp4",
221
- autoplay=True,
222
- streaming=True
223
- )
224
- with gr.Column() as history_container:
225
- gr.Markdown("### History")
226
- gr.Markdown("#### History will be reset after refresh")
227
- history_slots = []
228
- for i in range(10):
229
- with gr.Column(visible=False) as slot:
230
- with gr.Accordion(visible=False, open=False) as accordion:
231
- video = gr.Video(interactive=False)
232
- detail_md = gr.Markdown()
233
- history_slots.append((slot, accordion, video, detail_md))
234
- gr.Examples(
235
- examples=[
236
- ["demo1", "rdp", "vlnPE", "Walk past the left side of the bed and stop in the doorway."],
237
- ["demo2", "rdp", "vlnPE", "Walk through the bathroom, past the sink and toilet. Stop in front of the counter with the two suitcase."],
238
- ["demo3", "rdp", "vlnPE", "Do a U-turn. Walk forward through the kitchen, heading to the black door. Walk out of the door and take a right onto the deck. Walk out on to the deck and stop."],
239
- ["demo4", "rdp", "vlnPE", "Walk out of bathroom and stand on white bath mat."],
240
- ["demo5", "rdp", "vlnPE", "Walk straight through the double wood doors, follow the red carpet straight to the next doorway and stop where the carpet splits off."]
241
- ],
242
- inputs=[scene_dropdown, model_dropdown, mode_dropdown, prompt_input],
243
- label="Navigation Task Examples"
244
- )
245
- submit_btn.click(
246
- fn=run_simulation,
247
- inputs=[scene_dropdown, model_dropdown, mode_dropdown, prompt_input, history_state],
248
- outputs=[video_output, history_state],
249
- queue=True,
250
- api_name="run_simulation"
251
- ).then(
252
- fn=update_history_display,
253
- inputs=history_state,
254
- outputs=[comp for slot in history_slots for comp in slot],
255
- queue=True
256
- )
257
- demo.load(
258
- fn=lambda: update_scene_display("demo1"),
259
- outputs=[scene_description, scene_preview]
260
- )
261
- demo.load(
262
- fn=record_access,
263
- inputs=None,
264
- outputs=None,
265
- queue=False
266
- )
267
- demo.queue(default_concurrency_limit=8)
268
- demo.unload(fn=cleanup_session)
269
-
270
- if __name__ == "__main__":
271
- demo.launch(
272
- server_name="0.0.0.0",
273
- server_port=7860, # Hugging Face Space默认端口
274
- share=False,
275
- debug=False, # 生产环境建议关闭debug
276
- allowed_paths=["./assets", "./logs", "./tmp"] # 添加临时目录到允许路径
277
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
check_paths.py DELETED
@@ -1,17 +0,0 @@
1
- from config import SCENE_CONFIGS
2
- import os
3
-
4
- print('GLB文件路径检查:')
5
- for scene, config in SCENE_CONFIGS.items():
6
- glb_path = config.get('glb_path', '')
7
- exists = os.path.exists(glb_path)
8
- status = '存在' if exists else '不存在'
9
- print(f'{scene}: {glb_path} - {status}')
10
-
11
- print('\nEpisode图片路径检查 (以episode_1为例):')
12
- for scene, config in SCENE_CONFIGS.items():
13
- scene_name = config.get('scene_name', scene)
14
- image_path = os.path.join('scene_assets', f'{scene_name}_0.jpg')
15
- exists = os.path.exists(image_path)
16
- status = '存在' if exists else '不存在'
17
- print(f'{scene} -> {scene_name}: {image_path} - {status}')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
config.py CHANGED
@@ -14,58 +14,33 @@ SCENE_CONFIGS = {
14
  "description": "Demo 1",
15
  "objects": ["bedroom", "kitchen", "living room", ""],
16
  "preview_image": "./assets/scene_1.png",
17
- "glb_path": "scene_assets/scene1_no_ceiling.glb",
18
- "scene_name": "17DRP5sb8fy",
19
  "default_instruction": "Walk past the left side of the bed and stop in the doorway."
20
  },
21
  "demo2": {
22
- "description": "Demo 2",
23
  "objects": ["office", "meeting room", "corridor"],
24
  "preview_image": "./assets/scene_2.png",
25
- "glb_path": "scene_assets/scene2_no_ceiling.glb",
26
- "scene_name": "r1Q1Z4BcV1o",
27
  "default_instruction": "Walk through the bathroom, past the sink and toilet. Stop in front of the counter with the two suitcase."
28
  },
29
  "demo3": {
30
  "description": "Demo 3",
31
  "objects": ["garage", "workshop", "storage"],
32
  "preview_image": "./assets/scene_3.png",
33
- "glb_path": "scene_assets/scene3_no_ceiling.glb",
34
- "scene_name": "dhjEzFoUFzH",
35
  "default_instruction": "Do a U-turn. Walk forward through the kitchen, heading to the black door. Walk out of the door and take a right onto the deck. Walk out on to the deck and stop."
36
  },
37
  "demo4": {
38
  "description": "Demo 4",
39
  "objects": ["garden", "patio", "pool"],
40
  "preview_image": "./assets/scene_4.png",
41
- "glb_path": "scene_assets/scene4_no_ceiling.glb",
42
- "scene_name": "demo4", # 没有对应的图片文件,保持原名
43
  "default_instruction": "Walk out of bathroom and stand on white bath mat."
44
  },
45
  "demo5": {
46
  "description": "Demo 5",
47
  "objects": ["library", "hall", "lounge"],
48
  "preview_image": "./assets/scene_5.png",
49
- "glb_path": "scene_assets/scene4_no_ceiling.glb", # 只有scene1-4的GLB文件
50
- "scene_name": "demo5", # 没有对应的图片文件,保持原名
51
  "default_instruction": "Walk straight through the double wood doors, follow the red carpet straight to the next doorway and stop where the carpet splits off."
52
  },
53
  }
54
 
55
- EPISODE_CONFIGS = {
56
- "episode_1": {
57
- "description": "1",
58
- },
59
- "episode_2": {
60
- "description": "2",
61
- },
62
- "episode_3": {
63
- "description": "3",
64
- },
65
- "episode_4": {
66
- "description": "4",
67
- }
68
- }
69
-
70
  MODEL_CHOICES = ["rdp", "cma"]
71
  MODE_CHOICES = ["vlnPE", "vlnCE"]
 
14
  "description": "Demo 1",
15
  "objects": ["bedroom", "kitchen", "living room", ""],
16
  "preview_image": "./assets/scene_1.png",
 
 
17
  "default_instruction": "Walk past the left side of the bed and stop in the doorway."
18
  },
19
  "demo2": {
20
+ "description": "Demo 2",
21
  "objects": ["office", "meeting room", "corridor"],
22
  "preview_image": "./assets/scene_2.png",
 
 
23
  "default_instruction": "Walk through the bathroom, past the sink and toilet. Stop in front of the counter with the two suitcase."
24
  },
25
  "demo3": {
26
  "description": "Demo 3",
27
  "objects": ["garage", "workshop", "storage"],
28
  "preview_image": "./assets/scene_3.png",
 
 
29
  "default_instruction": "Do a U-turn. Walk forward through the kitchen, heading to the black door. Walk out of the door and take a right onto the deck. Walk out on to the deck and stop."
30
  },
31
  "demo4": {
32
  "description": "Demo 4",
33
  "objects": ["garden", "patio", "pool"],
34
  "preview_image": "./assets/scene_4.png",
 
 
35
  "default_instruction": "Walk out of bathroom and stand on white bath mat."
36
  },
37
  "demo5": {
38
  "description": "Demo 5",
39
  "objects": ["library", "hall", "lounge"],
40
  "preview_image": "./assets/scene_5.png",
 
 
41
  "default_instruction": "Walk straight through the double wood doors, follow the red carpet straight to the next doorway and stop where the carpet splits off."
42
  },
43
  }
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  MODEL_CHOICES = ["rdp", "cma"]
46
  MODE_CHOICES = ["vlnPE", "vlnCE"]
navigation_ui.py DELETED
@@ -1,575 +0,0 @@
1
- import base64
2
- import json
3
- import logging
4
- import os
5
- import subprocess
6
- import sys
7
- import threading
8
- import time
9
- import uuid
10
- from datetime import datetime, timedelta
11
- from typing import Dict, List, Optional
12
-
13
- import gradio as gr
14
- import numpy as np
15
- import open3d as o3d
16
- import plotly.graph_objects as go
17
- import requests
18
- from fastapi import APIRouter, FastAPI, HTTPException, status, BackgroundTasks, Response
19
- from pydantic import BaseModel
20
-
21
- import asyncio
22
- import uvicorn
23
- from collections import defaultdict
24
-
25
- BACKEND_URL = os.getenv("BACKEND_URL", "http://localhost:8001") # fastapi server
26
- API_ENDPOINTS = {
27
- "submit_task": f"{BACKEND_URL}/predict/video",
28
- "query_status": f"{BACKEND_URL}/predict/task",
29
- "get_result": f"{BACKEND_URL}/predict"
30
- }
31
-
32
-
33
- SCENE_CONFIGS = {
34
- "scene_1": {
35
- "description": "Modern Apartment",
36
- "name": "17DRP5sb8fy",
37
- "glb_path": "scene_assets/scene1_no_ceiling.glb" # PLY file path
38
- },
39
- "scene_2": {
40
- "description": "Office Building",
41
- "name": "r1Q1Z4BcV1o",
42
- "glb_path": "scene_assets/scene2_no_ceiling.glb"
43
- },
44
- "scene_3": {
45
- "description": "University Campus",
46
- "name": "dhjEzFoUFzH",
47
- "glb_path": "scene_assets/scene3_no_ceiling.glb"
48
- },
49
- }
50
-
51
- EPISODE_CONFIGS = {
52
- "episode_1": {
53
- "description": "1",
54
- },
55
- "episode_2": {
56
- "description": "2",
57
- },
58
- "episode_3": {
59
- "description": "3",
60
- },
61
- "episode_4": {
62
- "description": "4",
63
- }
64
- }
65
-
66
- MODEL_CHOICES = []
67
-
68
-
69
- ###############################################################################
70
-
71
- SESSION_TASKS = {}
72
- IP_REQUEST_RECORDS = defaultdict(list)
73
- IP_LIMIT = 5
74
-
75
- def is_request_allowed(ip: str) -> bool:
76
- now = datetime.now()
77
- IP_REQUEST_RECORDS[ip] = [t for t in IP_REQUEST_RECORDS[ip] if now - t < timedelta(minutes=1)]
78
- if len(IP_REQUEST_RECORDS[ip]) < IP_LIMIT:
79
- IP_REQUEST_RECORDS[ip].append(now)
80
- return True
81
- return False
82
-
83
- ###############################################################################
84
-
85
-
86
- # Log directory path
87
- LOG_DIR = "~/logs"
88
- os.makedirs(LOG_DIR, exist_ok=True)
89
- ACCESS_LOG = os.path.join(LOG_DIR, "access.log")
90
- SUBMISSION_LOG = os.path.join(LOG_DIR, "submissions.log")
91
-
92
- def log_access(user_ip: str = None, user_agent: str = None):
93
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
94
- log_entry = {
95
- "timestamp": timestamp,
96
- "type": "access",
97
- "user_ip": user_ip or "unknown",
98
- "user_agent": user_agent or "unknown"
99
- }
100
-
101
- with open(ACCESS_LOG, "a") as f:
102
- f.write(json.dumps(log_entry) + "\n")
103
-
104
- def log_submission(scene: str, prompt: str, model: str, user: str = "anonymous", res: str = "unknown"):
105
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
106
- log_entry = {
107
- "timestamp": timestamp,
108
- "type": "submission",
109
- "user": user,
110
- "scene": scene,
111
- "prompt": prompt,
112
- "model": model,
113
- #"max_step": str(max_step),
114
- "res": res
115
- }
116
-
117
- with open(SUBMISSION_LOG, "a") as f:
118
- f.write(json.dumps(log_entry) + "\n")
119
-
120
- def read_logs(log_type: str = "all", max_entries: int = 50) -> list:
121
- logs = []
122
-
123
- if log_type in ["all", "access"]:
124
- try:
125
- with open(ACCESS_LOG, "r") as f:
126
- for line in f:
127
- logs.append(json.loads(line.strip()))
128
- except FileNotFoundError:
129
- pass
130
-
131
- if log_type in ["all", "submission"]:
132
- try:
133
- with open(SUBMISSION_LOG, "r") as f:
134
- for line in f:
135
- logs.append(json.loads(line.strip()))
136
- except FileNotFoundError:
137
- pass
138
-
139
- # Sorted by timestemp
140
- logs.sort(key=lambda x: x["timestamp"], reverse=True)
141
- return logs[:max_entries]
142
-
143
- def format_logs_for_display(logs: list) -> str:
144
- if not logs:
145
- return "No log record"
146
-
147
- markdown = "### System Access Log\n\n"
148
- markdown += "| Time | Type | User/IP | Details |\n"
149
- markdown += "|------|------|---------|----------|\n"
150
-
151
- for log in logs:
152
- timestamp = log.get("timestamp", "unknown")
153
- log_type = "Access" if log.get("type") == "access" else "Submission"
154
-
155
- if log_type == "Access":
156
- user = log.get("user_ip", "unknown")
157
- details = f"User-Agent: {log.get('user_agent', 'unknown')}"
158
- else:
159
- user = log.get("user", "anonymous")
160
- result = log.get('res', 'unknown')
161
- if result != "success":
162
- if len(result) > 40: # Adjust this threshold as needed
163
- result = f"{result[:20]}...{result[-20:]}"
164
- details = f"Scene: {log.get('scene', 'unknown')}, Prompt: {log.get('prompt', '')}, Model: {log.get('model', 'unknown')}, result: {result}"
165
-
166
- markdown += f"| {timestamp} | {log_type} | {user} | {details} |\n"
167
-
168
- return markdown
169
-
170
-
171
- def submit_to_backend(
172
- scene: str,
173
- prompt: str,
174
- episode: str,
175
- user: str = "Gradio-user",
176
- ) -> dict:
177
- job_id = str(uuid.uuid4())
178
-
179
- scene_index = scene.split("_")[-1]
180
- episode_index = episode.split("_")[-1]
181
-
182
- data = {
183
- "task_type": "vln_eval", # Identify task type
184
- "instruction": prompt,
185
- "scene_index": scene_index,
186
- "episode_index": episode_index,
187
- }
188
-
189
- payload = {
190
- "user": user,
191
- "task": "robot_navigation",
192
- "job_id": job_id,
193
- "data": json.dumps(data)
194
- }
195
-
196
- try:
197
- headers = {"Content-Type": "application/json"}
198
- response = requests.post(
199
- API_ENDPOINTS["submit_task"],
200
- json=payload,
201
- headers=headers,
202
- timeout=600
203
- )
204
- return response.json()
205
- except Exception as e:
206
- return {"status": "error", "message": str(e)}
207
-
208
- def get_task_status(task_id: str) -> dict:
209
- try:
210
- response = requests.get(f"{API_ENDPOINTS['query_status']}/{task_id}", timeout=600)
211
- try:
212
- return response.json()
213
- except json.JSONDecodeError:
214
- return {"status": "error", "message": response.text}
215
- except Exception as e:
216
- return {"status": "error", "message": str(e)}
217
-
218
-
219
- def get_task_result(task_id: str) -> Optional[dict]:
220
- try:
221
- response = requests.get(
222
- f"{API_ENDPOINTS['get_result']}/{task_id}",
223
- timeout=5
224
- )
225
- return response.json()
226
- except Exception as e:
227
- print(f"Error fetching result: {e}")
228
- return None
229
-
230
- def run_simulation(
231
- scene: str,
232
- prompt: str,
233
- episode: str,
234
- history: list,
235
- request: gr.Request
236
- ) -> dict:
237
- model = "InternNav-VLA"
238
-
239
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
240
- scene_desc = SCENE_CONFIGS.get(scene, {}).get("description", scene)
241
-
242
- user_ip = request.client.host if request else "unknown"
243
- session_id = request.session_hash
244
-
245
- if not is_request_allowed(user_ip):
246
- log_submission(scene, prompt, model, user_ip, "IP blocked temporarily")
247
- raise gr.Error("Too many requests from this IP. Please wait and try again one minute later.")
248
-
249
- submission_result = submit_to_backend(scene, prompt, episode)
250
- print("submission_result: ", submission_result)
251
-
252
- if submission_result.get("status") != "pending":
253
- log_submission(scene, prompt, model, user_ip, "Submission failed")
254
- raise gr.Error(f"Submission failed: {submission_result.get('message', 'unknown issue')}")
255
-
256
- try:
257
- task_id = submission_result["task_id"]
258
- SESSION_TASKS[session_id] = task_id
259
-
260
- gr.Info(f"Simulation started, task_id: {task_id}")
261
- time.sleep(5)
262
- # Get Task Status
263
- status = get_task_status(task_id)
264
- print("first status: ", status)
265
- result_folder = status.get("result", "")
266
- except Exception as e:
267
- log_submission(scene, prompt, model, user_ip, str(e))
268
- raise gr.Error(f"error occurred when parsing submission result from backend: {str(e)}")
269
-
270
- while True:
271
- status = get_task_status(task_id)
272
- if status.get("status") == "completed":
273
- break
274
- elif status.get("status") == "failed":
275
- break
276
- time.sleep(1)
277
- if status.get("status") == "completed":
278
- import base64
279
- video_bytes = base64.b64decode(status.get("video"))
280
- receive_time = time.time()
281
- with open(f"received_video_{receive_time}.mp4", "wb") as f:
282
- f.write(video_bytes)
283
- video_path = f"received_video_{receive_time}.mp4"
284
- new_entry = {
285
- "timestamp": timestamp,
286
- "scene": scene,
287
- "model": model,
288
- "prompt": prompt,
289
- "video_path": video_path
290
- }
291
-
292
- updated_history = history + [new_entry]
293
-
294
- if len(updated_history) > 10:
295
- updated_history = updated_history[:10]
296
-
297
- print("updated_history:", updated_history)
298
- log_submission(scene, prompt, model, user_ip, "success")
299
- gr.Info("Simulation completed successfully!")
300
- yield video_path, updated_history
301
-
302
- elif status.get("status") == "failed":
303
- log_submission(scene, prompt, model, user_ip, status.get('result', 'backend error'))
304
- raise gr.Error(f"task execution fails: {status.get('result', 'backend error')}")
305
- yield None, history
306
-
307
- elif status.get("status") == "terminated":
308
- log_submission(scene, prompt, model, user_ip, "terminated")
309
- video_path = os.path.join(result_folder, "output.mp4")
310
- if os.path.exists(video_path):
311
- return f" task {task_id} terminated with some results", video_path, history
312
- else:
313
- return f" task {task_id} terminated without any results", None, history
314
-
315
- else:
316
- log_submission(scene, prompt, model, user_ip, "missing task's status from backend")
317
- yield None, history
318
-
319
- ###################################################################################################################
320
- def update_history_display(history: list) -> list:
321
- print("update_history_display")
322
- updates = []
323
-
324
- for i in range(10):
325
- if i < len(history):
326
- entry = history[i]
327
- updates.extend([
328
- gr.update(visible=True),
329
- gr.update(visible=True, label=f"Simulation {i+1} scene: {entry['scene']}, prompt: {entry['prompt']}", open=False),
330
- gr.update(value=entry['video_path'], visible=True),
331
- gr.update(value=f"{entry['timestamp']}")
332
- ])
333
- print(f'update video')
334
- print(entry['video_path'])
335
- else:
336
- updates.extend([
337
- gr.update(visible=False),
338
- gr.update(visible=False),
339
- gr.update(value=None, visible=False),
340
- gr.update(value="")
341
- ])
342
- print("update_history_display end!!")
343
- return updates
344
-
345
- def update_scene_display(scene: str):
346
- print(f"update_scene_display {scene}")
347
- config = SCENE_CONFIGS.get(scene, {})
348
- glb_path = config.get("glb_path", "")
349
-
350
- # Validate if file path exists
351
- if not os.path.exists(glb_path):
352
- return None, None
353
-
354
- return None, glb_path
355
-
356
- def update_episode_display(scene: str, episode: str):
357
- print(f"update_episode_display {scene} {episode}")
358
- config = SCENE_CONFIGS.get(scene, {})
359
- scene_name = config.get("name", "")
360
- episode_id = int(episode[-1])
361
- image_path = os.path.join("scene_assets", f"{scene_name}_{episode_id-1}.jpg")
362
- print(f"image_path {image_path}")
363
- # vaild if file path exists
364
- if not os.path.exists(image_path):
365
- return None
366
-
367
- return image_path
368
- def update_log_display():
369
- logs = read_logs()
370
- return format_logs_for_display(logs)
371
- ##############################################################################
372
-
373
-
374
- def cleanup_session(request: gr.Request):
375
- session_id = request.session_hash
376
- task_id = SESSION_TASKS.pop(session_id, None)
377
- if task_id:
378
- try:
379
- requests.post(f"{BACKEND_URL}/predict/terminate/{task_id}", timeout=3)
380
- print(f"Task Terminated: {task_id}")
381
- except Exception as e:
382
- print(f"Task Termination Failed: {task_id}: {e}")
383
-
384
-
385
-
386
- ###############################################################################
387
-
388
- custom_css = """
389
- #simulation-panel {
390
- border-radius: 8px;
391
- padding: 20px;
392
- background: #f9f9f9;
393
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
394
- }
395
- #result-panel {
396
- border-radius: 8px;
397
- padding: 20px;
398
- background: #f0f8ff;
399
- }
400
- .dark #simulation-panel { background: #2a2a2a; }
401
- .dark #result-panel { background: #1a2a3a; }
402
-
403
- .history-container {
404
- max-height: 600px;
405
- overflow-y: auto;
406
- margin-top: 20px;
407
- }
408
-
409
- .history-accordion {
410
- margin-bottom: 10px;
411
- }
412
-
413
- .scene-preview {
414
- height: 400px;
415
- border: 1px solid #ddd;
416
- border-radius: 8px;
417
- overflow: hidden;
418
- }
419
- """
420
-
421
- with gr.Blocks(title="Robot Navigation Inference", css=custom_css) as demo:
422
- gr.Markdown("""
423
- # 🧭 Habitat Robot Navigation Demo
424
- ### Simulation Test Based on Habitat Framework
425
- """)
426
-
427
- history_state = gr.State([])
428
-
429
- with gr.Row():
430
- with gr.Column(elem_id="simulation-panel"):
431
- gr.Markdown("### Simulation Task Configuration")
432
- with gr.Row():
433
- scene_dropdown = gr.Dropdown(
434
- label="Select Scene",
435
- choices=list(SCENE_CONFIGS.keys()),
436
- value="scene_1",
437
- interactive=True,
438
- )
439
- episode_dropdown = gr.Dropdown(
440
- label="Select Start Position",
441
- choices=list(EPISODE_CONFIGS.keys()),
442
- value="episode_1",
443
- interactive=True,
444
- )
445
-
446
- with gr.Row():
447
- scene_preview = gr.Model3D(elem_classes=["scene-preview"],
448
- camera_position=(90.0, 120, 20000.0),
449
- #display_mode="solid"
450
- )
451
- fps_preview = gr.Image(label="FPS Preview")
452
-
453
- scene_description = gr.Markdown("### Scene preview")
454
-
455
- prompt_input = gr.Textbox(
456
- label="Navigation Instruction",
457
- value="Exit the bedroom and turn left. Walk straight passing the gray couch and stop near the rug.",
458
- placeholder="e.g.: 'Exit the bedroom and turn left. Walk straight passing the gray couch and stop near the rug.'",
459
- lines=2,
460
- max_lines=4
461
- )
462
-
463
- scene_dropdown.change(
464
- update_scene_display,
465
- inputs=scene_dropdown,
466
- outputs=[scene_description, scene_preview]
467
- ).then(
468
- update_episode_display,
469
- inputs=[scene_dropdown, episode_dropdown],
470
- outputs=[fps_preview]
471
- )
472
-
473
- episode_dropdown.change(
474
- update_episode_display,
475
- inputs=[scene_dropdown, episode_dropdown],
476
- outputs=[fps_preview]
477
- )
478
-
479
- submit_btn = gr.Button("Start Navigation Simulation", variant="primary")
480
-
481
-
482
- with gr.Column(elem_id="result-panel"):
483
- gr.Markdown("### Latest Simulation Result")
484
-
485
- # Video Output
486
- video_output = gr.Video(
487
- label="Live",
488
- interactive=False,
489
- format="mp4",
490
- autoplay=True,
491
- # streaming=True
492
- )
493
-
494
- with gr.Column() as history_container:
495
- gr.Markdown("### History")
496
- gr.Markdown("#### History will be reset after refresh")
497
-
498
- history_slots = []
499
- for i in range(10):
500
- with gr.Column(visible=False) as slot:
501
- with gr.Accordion(visible=False, open=False) as accordion:
502
- video = gr.Video(interactive=False)
503
- detail_md = gr.Markdown()
504
- history_slots.append((slot, accordion, video, detail_md))
505
-
506
- with gr.Accordion("View System Log (DEV ONLY)", open=False):
507
- logs_display = gr.Markdown()
508
- refresh_logs_btn = gr.Button("Refresh Log", variant="secondary")
509
-
510
- refresh_logs_btn.click(
511
- update_log_display,
512
- outputs=logs_display
513
- )
514
-
515
- gr.Examples(
516
- examples=[
517
- ["scene_1", "Exit the bedroom and turn left. Walk straight passing the gray couch and stop near the rug.", "episode_0"],
518
- ["scene_2", "Go from reception to conference room passing the water cooler.", "episode_1"],
519
- ["scene_3", "From the classroom, go to the library via the main hall.", "episode_2"],
520
- ["scene_4", "From emergency room to pharmacy passing nurse station.", "episode_3"]
521
- ],
522
- inputs=[scene_dropdown, prompt_input, episode_dropdown],
523
- label="Navigation Task Example"
524
- )
525
-
526
- submit_btn.click(
527
- fn=run_simulation,
528
- inputs=[scene_dropdown, prompt_input, episode_dropdown, history_state],
529
- outputs=[video_output, history_state],
530
- queue=True,
531
- api_name="run_simulation"
532
- ).then(
533
- fn=update_history_display,
534
- inputs=history_state,
535
- outputs=[comp for slot in history_slots for comp in slot],
536
- queue=True
537
- ).then(
538
- fn=update_log_display,
539
- outputs=logs_display,
540
- )
541
-
542
-
543
- demo.load(
544
- fn=lambda: update_scene_display("scene_1"),
545
- outputs=[scene_description, scene_preview]
546
- ).then(
547
- fn=update_log_display,
548
- outputs=logs_display
549
- )
550
- demo.load(
551
- fn=lambda: update_episode_display("scene_1", "episode_1"),
552
- outputs=[fps_preview]
553
- )
554
-
555
- def record_access(request: gr.Request):
556
- user_ip = request.client.host if request else "unknown"
557
- user_agent = request.headers.get("user-agent", "unknown")
558
- log_access(user_ip, user_agent)
559
- return update_log_display()
560
-
561
- demo.load(
562
- fn=record_access,
563
- inputs=None,
564
- outputs=logs_display,
565
- queue=False
566
- )
567
-
568
- demo.queue(default_concurrency_limit=8)
569
-
570
- demo.unload(fn=cleanup_session)
571
-
572
- if __name__ == "__main__":
573
- demo.launch(server_name="0.0.0.0", server_port=5750, debug=True, share = True, allowed_paths=["/mnt"])
574
-
575
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
scene_assets/17DRP5sb8fy_0.jpg DELETED
Binary file (43 kB)
 
scene_assets/17DRP5sb8fy_1.jpg DELETED
Binary file (38.6 kB)
 
scene_assets/17DRP5sb8fy_2.jpg DELETED
Binary file (64.6 kB)
 
scene_assets/17DRP5sb8fy_3.jpg DELETED
Binary file (21.6 kB)
 
scene_assets/dhjEzFoUFzH_0.jpg DELETED
Binary file (63.9 kB)
 
scene_assets/dhjEzFoUFzH_1.jpg DELETED
Binary file (73.2 kB)
 
scene_assets/dhjEzFoUFzH_2.jpg DELETED
Binary file (72 kB)
 
scene_assets/dhjEzFoUFzH_3.jpg DELETED
Binary file (59.8 kB)
 
scene_assets/r1Q1Z4BcV1o_0.jpg DELETED
Binary file (63.1 kB)
 
scene_assets/r1Q1Z4BcV1o_1.jpg DELETED
Binary file (50 kB)
 
scene_assets/r1Q1Z4BcV1o_2.jpg DELETED
Binary file (53.9 kB)
 
scene_assets/r1Q1Z4BcV1o_3.jpg DELETED
Binary file (47.9 kB)
 
scene_assets/scene1_no_ceiling.glb DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:1c4f3c57d4a316bae5e8574602f0809f516fed743064b1f867b13ad4c5eafd6c
3
- size 43925372
 
 
 
 
scene_assets/scene2_no_ceiling.glb DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:d02e41f07558ee1b085edd08d8473fd38f65c3496d23365bdc171dae1178db5d
3
- size 47916736
 
 
 
 
scene_assets/scene3_no_ceiling.glb DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:aba480ff78c3d08416caea5b603cb775590aeb83b1e09af8606aafbefde141e7
3
- size 139535840
 
 
 
 
scene_assets/scene4_no_ceiling.glb DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:de5f487e0085d2bea34445392656324dcb10e53b0c87c0ad48c1e1b8eec6f14b
3
- size 51743004
 
 
 
 
ui_components.py CHANGED
@@ -1,8 +1,7 @@
1
  # ui_components.py
2
  # Gradio界面相关和辅助函数
3
  import gradio as gr
4
- import os
5
- from config import SCENE_CONFIGS, EPISODE_CONFIGS
6
  from logging_utils import read_logs, format_logs_for_display
7
 
8
  def update_history_display(history: list) -> list:
@@ -30,28 +29,9 @@ def update_scene_display(scene: str):
30
  config = SCENE_CONFIGS.get(scene, {})
31
  desc = config.get("description", "No Description")
32
  objects = "、".join(config.get("objects", []))
33
- glb_path = config.get("glb_path", "")
34
  markdown = f"**{desc}** \nPlaces Included: {objects}"
35
-
36
- # Validate if file path exists
37
- if not os.path.exists(glb_path):
38
- return markdown, None
39
-
40
- return markdown, glb_path
41
-
42
- def update_episode_display(scene: str, episode: str):
43
- config = SCENE_CONFIGS.get(scene, {})
44
- scene_name = config.get("scene_name", scene) # 使用配置中的scene_name
45
- episode_id = int(episode[-1])
46
- image_path = os.path.join("scene_assets", f"{scene_name}_{episode_id-1}.jpg")
47
-
48
- # Validate if file path exists
49
- if os.path.exists(image_path):
50
- return image_path
51
- else:
52
- # Fallback to preview_image if episode image doesn't exist
53
- fallback_path = config.get("preview_image", None)
54
- return fallback_path
55
 
56
  def get_scene_instruction(scene: str):
57
  """根据场景获取默认指令"""
 
1
  # ui_components.py
2
  # Gradio界面相关和辅助函数
3
  import gradio as gr
4
+ from config import SCENE_CONFIGS
 
5
  from logging_utils import read_logs, format_logs_for_display
6
 
7
  def update_history_display(history: list) -> list:
 
29
  config = SCENE_CONFIGS.get(scene, {})
30
  desc = config.get("description", "No Description")
31
  objects = "、".join(config.get("objects", []))
32
+ image = config.get("preview_image", None)
33
  markdown = f"**{desc}** \nPlaces Included: {objects}"
34
+ return markdown, image
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  def get_scene_instruction(scene: str):
37
  """根据场景获取默认指令"""