jandan138 commited on
Commit
a5eb7ce
·
verified ·
1 Parent(s): 82836da

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -328
app.py CHANGED
@@ -1,343 +1,98 @@
1
  import gradio as gr
2
  import requests
3
- # import json
4
- import os
5
- from typing import Optional
6
- import numpy as np
7
- import cv2
8
- from PIL import Image
9
 
10
- # 后端API配置(可配置化)
11
- BACKEND_URL = os.getenv("BACKEND_URL", "http://your-backend-server:5000")
12
- API_ENDPOINTS = {
13
- "submit_task": f"{BACKEND_URL}/api/v1/submit",
14
- "query_status": f"{BACKEND_URL}/api/v1/status",
15
- "get_result": f"{BACKEND_URL}/api/v1/result"
16
- }
17
-
18
- # 全局缓存原始图像
19
- #ORIGINAL_IMAGE = cv2.imread("scene.png")
20
- ORIGINAL_IMAGE = np.array(Image.open("scene.png").convert("RGB"))
21
- if ORIGINAL_IMAGE is None:
22
- raise RuntimeError("❌ 无法加载 scene.png,请确保图片文件与 app.py 同目录,并命名正确。")
23
-
24
-
25
- # 模拟场景配置
26
- SCENE_CONFIGS = {
27
- "default_desk": {
28
- "description": "标准实验桌",
29
- "objects": ["番茄酱", "盐瓶", "餐刀", "杯子"]
30
- },
31
- "cluttered_desk": {
32
- "description": "杂乱桌面场景",
33
- "objects": ["书本", "笔", "手机", "水杯", "零食袋"]
34
- },
35
- "industrial_table": {
36
- "description": "工业工作台",
37
- "objects": ["扳手", "螺丝", "电路板", "润滑剂"]
38
- }
39
- }
40
-
41
- # 可用模型列表
42
- MODEL_CHOICES = [
43
- "GRManipulation-v1.0",
44
- "GR00T-N1",
45
- "GR00T-1.5",
46
- "Pi0",
47
- "DP+CLIP",
48
- "AcT+CLIP"
49
- ]
50
-
51
- def image_to_position(image: np.ndarray, evt: gr.SelectData) -> tuple[np.ndarray, str]:
52
- h, w = image.shape[:2]
53
- px, py = evt.index # 点击位置 (x, y)
54
-
55
- # 坐标转换
56
- x = (px / w) * 2 - 1
57
- y = -((py / h) * 2 - 1)
58
- z = 0.1
59
- coord_str = f"{x:.2f}, {y:.2f}, {z:.2f}"
60
-
61
- # 使用原始图像绘制新图(保证每次只有一个点)
62
- marked = ORIGINAL_IMAGE.copy()
63
- cv2.circle(marked, center=(px, py), radius=8, color=(255, 0, 0), thickness=-1)
64
-
65
- return marked, coord_str
66
-
67
-
68
- def submit_to_backend(
69
- scene: str,
70
- prompt: str,
71
- start_position: str,
72
- max_steps: int = 100,
73
- visualize: bool = True
74
- ) -> dict:
75
- """
76
- 提交任务到后端API
77
- """
78
- payload = {
79
- "scene_config": scene,
80
- "prompt": prompt,
81
- "start_position": start_position,
82
- "params": {
83
- "max_steps": max_steps,
84
- "visualize": visualize
85
- },
86
- "metadata": {
87
- "submit_from": "gradio_ui"
88
- }
89
- }
90
-
91
-
92
  try:
93
- response = requests.post(
94
- API_ENDPOINTS["submit_task"],
95
- json=payload,
96
- timeout=10
97
- )
98
- return response.json()
99
  except Exception as e:
100
- return {"status": "error", "message": str(e)}
101
-
102
- def get_task_status(task_id: str) -> dict:
103
- """
104
- 查询任务状态
105
- """
106
- try:
107
- response = requests.get(
108
- f"{API_ENDPOINTS['query_status']}/{task_id}",
109
- timeout=5
110
- )
111
- return response.json()
112
- except Exception as e:
113
- return {"status": "error", "message": str(e)}
114
-
115
- def get_task_result(task_id: str) -> Optional[dict]:
116
- """
117
- 获取任务结果
118
- """
119
- try:
120
- response = requests.get(
121
- f"{API_ENDPOINTS['get_result']}/{task_id}",
122
- timeout=5
123
- )
124
- return response.json()
125
- except Exception as e:
126
- print(f"Error fetching result: {e}")
127
- return None
128
-
129
- def run_simulation(
130
- scene: str,
131
- prompt: str,
132
- model: str,
133
- progress=gr.Progress()
134
- ) -> dict:
135
- """
136
- 运行仿真的主函数
137
- """
138
- # 提交任务到后端
139
- progress(0.1, desc="提交任务到后端...")
140
- submission = submit_to_backend(scene, prompt, model)
141
-
142
- if submission.get("status") != "success":
143
- raise gr.Error(f"提交失败: {submission.get('message', '未知错误')}")
144
-
145
- task_id = submission["task_id"]
146
- progress(0.3, desc="任务已提交,等待执行...")
147
 
148
- # 轮询任务状态
149
- max_checks = 20
150
- for i in range(max_checks):
151
- status = get_task_status(task_id)
152
 
153
- if status.get("status") == "completed":
154
- progress(0.9, desc="获取结果...")
155
- result = get_task_result(task_id)
156
- if result:
157
- return {
158
- "video": result.get("video_path"),
159
- "metrics": result.get("metrics"),
160
- "log": result.get("log")
161
- }
162
- else:
163
- raise gr.Error("获取结果失败")
164
 
165
- elif status.get("status") == "failed":
166
- raise gr.Error(f"任务执行失败: {status.get('message')}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
- progress(0.3 + 0.6 * (i/max_checks), desc=f"任务执行中...({status.get('progress', 0)}%)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
 
170
- raise gr.Error("任务执行超时")
171
-
172
- # 自定义CSS样式
173
- custom_css = """
174
- #simulation-panel {
175
- border-radius: 8px;
176
- padding: 20px;
177
- background: #f9f9f9;
178
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
179
- }
180
- #result-panel {
181
- border-radius: 8px;
182
- padding: 20px;
183
- background: #f0f8ff;
184
- }
185
- .dark #simulation-panel { background: #2a2a2a; }
186
- .dark #result-panel { background: #1a2a3a; }
187
-
188
- /* 强力隐藏图像组件底部工具栏 */
189
- .gr-image .absolute.bottom-0,
190
- .gr-image .flex.justify-between.items-center.px-2.pb-2 {
191
- display: none !important;
192
- }
193
-
194
- """
195
-
196
- with gr.Blocks(title="机器人导航仿真系统", css=custom_css) as demo:
197
- # 标题和描述
198
- gr.Markdown("""
199
- # 🧭 GRNavigation 机器人导航仿真平台
200
- ### 基于 GRNavigation 框架的多场景路径规划与自主导航训练
201
- """)
202
 
203
- with gr.Row():
204
- # 左侧控制面板
205
- with gr.Column(elem_id="simulation-panel"):
206
- gr.Markdown("### 仿真任务配置")
207
-
208
- # 场景选择
209
- scene_dropdown = gr.Dropdown(
210
- label="选择导航环境",
211
- choices=list(SCENE_CONFIGS.keys()),
212
- value="default_desk",
213
- interactive=True
214
- )
215
-
216
- def update_scene_desc(scene):
217
- config = SCENE_CONFIGS.get(scene, {})
218
- desc = config.get("description", "无描述")
219
- objects = "、".join(config.get("objects", []))
220
- return f"**{desc}** \n包含物体: {objects}"
221
-
222
-
223
- # 场景描述预览
224
- scene_description = gr.Markdown("")
225
-
226
- # 动态更新场景描述(函数不变)
227
-
228
- # 操作指令输入
229
- prompt_input = gr.Textbox(
230
- label="导航指令(自然语言)",
231
- placeholder="例如:'从桌角出发,穿过障碍物,前往水杯位置'",
232
- lines=2,
233
- max_lines=4
234
- )
235
-
236
- # 起始坐标输入
237
- start_pos_input = gr.Textbox(
238
- label="起始位置坐标 (x, y, z)",
239
- placeholder="例如:0.0, 0.0, 0.2",
240
- lines=1
241
- )
242
-
243
-
244
- # 高级参数
245
- with gr.Accordion("高级设置", open=False):
246
- max_steps = gr.Slider(
247
- minimum=50,
248
- maximum=500,
249
- value=100,
250
- step=10,
251
- label="最大导航步数"
252
- )
253
- visualize = gr.Checkbox(
254
- value=True,
255
- label="显示可视化界面(Isaac Sim)"
256
- )
257
-
258
- # 提交按钮
259
- submit_btn = gr.Button("开始导航仿真", variant="primary")
260
-
261
- # 右侧结果面板
262
- with gr.Column(elem_id="result-panel"):
263
- gr.Markdown("### 仿真结果预览")
264
-
265
- # 视频输出
266
- video_output = gr.Video(
267
- label="导航过程回放",
268
- interactive=False,
269
- format="mp4"
270
- )
271
-
272
- # 场景俯视图图像(点击获取起点)
273
- scene_image = gr.Image(
274
- value="/scene.png", # 占位图路径
275
- label="点击选择起点位置(场景俯视图)",
276
- type="numpy", # 获取坐标
277
- interactive=True,
278
- height=300,
279
- show_share_button=False # ✅ 关闭底部按钮(上传、拍照、复制)
280
- )
281
-
282
- # ✅ 添加“刷新场景图像”按钮
283
- def reload_scene_image():
284
- new_image = np.array(Image.open("scene.png").convert("RGB"))
285
- global ORIGINAL_IMAGE
286
- ORIGINAL_IMAGE = new_image
287
- return new_image
288
-
289
- refresh_btn = gr.Button("🔁 刷新场景图像")
290
- refresh_btn.click(fn=reload_scene_image, outputs=scene_image)
291
-
292
-
293
- # 指标展示
294
- metrics_output = gr.JSON(
295
- label="导航性能指标",
296
- visible=False
297
- )
298
-
299
- # 日志输出
300
- log_output = gr.Textbox(
301
- label="任务执行日志",
302
- visible=False,
303
- lines=10,
304
- max_lines=20
305
- )
306
-
307
- # 示例任务
308
- gr.Examples(
309
- examples=[
310
- ["default_desk", "从桌角出发,前往番茄酱附近", "0.0, 0.0, 0.1"],
311
- ["cluttered_desk", "从水杯出发,移动到手机旁", "1.0, -0.5, 0.0"],
312
- ["industrial_table", "避开扳手,从台边移动到润滑剂", "0.5, 0.2, 0.0"]
313
- ],
314
- inputs=[scene_dropdown, prompt_input, start_pos_input],
315
- label="导航任务示例"
316
- )
317
-
318
-
319
- # 提交处理逻辑
320
- submit_btn.click(
321
- fn=run_simulation,
322
- inputs=[scene_dropdown, prompt_input, start_pos_input],
323
- outputs=[video_output, metrics_output, log_output],
324
- api_name="run_simulation"
325
- )
326
 
327
- # 初始场景文字描述
328
- demo.load(
329
- fn=lambda: (update_scene_desc("default_desk"), reload_scene_image()),
330
- outputs=[scene_description, scene_image]
331
- )
332
-
333
- # ✅ 添加点击图片 → 自动设置起始位置
334
- scene_image.select(
335
- fn=image_to_position,
336
- inputs=[scene_image],
337
- outputs=[scene_image, start_pos_input]
338
- )
339
-
 
 
 
 
340
 
341
  # 启动应用
342
  if __name__ == "__main__":
343
- demo.launch(server_name="0.0.0.0", server_port=7860, share=True, debug=True)
 
 
 
 
 
1
  import gradio as gr
2
  import requests
3
+ import time
 
 
 
 
 
4
 
5
+ def check_url_status():
6
+ """检查目标URL的状态"""
7
+ target_url = "http://123.57.187.96:55005/"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  try:
9
+ response = requests.get(target_url, timeout=10)
10
+ return f"✅ URL状态: {response.status_code} - 可访问"
 
 
 
 
11
  except Exception as e:
12
+ return f" URL错误: {str(e)}"
13
+
14
+ def create_webpage_display():
15
+ """创建显示指定网页的HTML内容"""
16
+ # 添加调试信息
17
+ debug_info = f"调试时间: {time.strftime('%Y-%m-%d %H:%M:%S')}<br>"
18
+ debug_info += f"目标URL: http://123.57.187.96:55005/<br>"
19
+ debug_info += f"{check_url_status()}<br><br>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
+ iframe_html = f'''
22
+ <div style="border: 2px solid #ccc; padding: 10px; margin: 10px 0;">
23
+ <h3>调试信息:</h3>
24
+ <p>{debug_info}</p>
25
 
26
+ <h3>方式1: 直接链接</h3>
27
+ <p><a href="http://123.57.187.96:55005/" target="_blank" style="font-size: 18px; color: blue;">🔗 点击这里直接访问网站</a></p>
 
 
 
 
 
 
 
 
 
28
 
29
+ <h3>方式2: iframe嵌入</h3>
30
+ <div style="width: 100%; height: 600px; border: 1px solid #999;">
31
+ <iframe src="http://123.57.187.96:55005/"
32
+ width="100%"
33
+ height="100%"
34
+ frameborder="1"
35
+ allowfullscreen
36
+ sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
37
+ onerror="console.log('iframe加载失败')"
38
+ onload="console.log('iframe加载成功')">
39
+ <p style="color: red; font-size: 16px;">
40
+ ⚠️ iframe无法显示内容。可能原因:<br>
41
+ 1. 目标网站不允许被嵌入<br>
42
+ 2. 跨域安全策略限制<br>
43
+ 3. HTTPS/HTTP混合内容问题<br>
44
+ <a href="http://123.57.187.96:55005/" target="_blank">请点击这里直接访问</a>
45
+ </p>
46
+ </iframe>
47
+ </div>
48
 
49
+ <h3>方式3: 网站预览信息</h3>
50
+ <div style="background: #f5f5f5; padding: 10px; border-radius: 5px;">
51
+ <p>如果iframe无法显示,这通常是因为:</p>
52
+ <ul>
53
+ <li>目标网站设置了 X-Frame-Options 禁止被嵌入</li>
54
+ <li>CSP (Content Security Policy) 限制</li>
55
+ <li>HTTPS页面无法嵌入HTTP内容</li>
56
+ </ul>
57
+ </div>
58
+ </div>
59
+ '''
60
+ return iframe_html
61
+
62
+ # 创建 Gradio 界面
63
+ with gr.Blocks(title="网页显示器", css=".gradio-container {padding: 0px !important}") as demo:
64
+ gr.Markdown("# 网页内容显示")
65
+ gr.Markdown("以下是来自 http://123.57.187.96:55005/ 的网页内容:")
66
 
67
+ # 显示网页内容
68
+ webpage_html = gr.HTML(value=create_webpage_display())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
+ # 添加刷新按钮
71
+ refresh_btn = gr.Button("🔄 刷新页面", variant="primary")
72
+ refresh_btn.click(fn=create_webpage_display, outputs=webpage_html)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
+ # 添加获取网页源码的功能
75
+ def get_webpage_content():
76
+ try:
77
+ response = requests.get("http://123.57.187.96:55005/", timeout=10)
78
+ content = response.text
79
+ # 简单处理HTML内容,移除可能的脚本
80
+ import re
81
+ content = re.sub(r'<script.*?</script>', '', content, flags=re.DOTALL)
82
+ return f"<div style='border: 1px solid #ccc; padding: 10px; max-height: 500px; overflow-y: auto;'><h3>网页源码内容:</h3><pre>{content[:2000]}{'...' if len(content) > 2000 else ''}</pre></div>"
83
+ except Exception as e:
84
+ return f"<p style='color: red;'>获取网页内容失败: {str(e)}</p>"
85
+
86
+ gr.Markdown("---")
87
+ gr.Markdown("### 备用方案:直接获取网页内容")
88
+ content_btn = gr.Button("📄 获取网页源码", variant="secondary")
89
+ content_output = gr.HTML()
90
+ content_btn.click(fn=get_webpage_content, outputs=content_output)
91
 
92
  # 启动应用
93
  if __name__ == "__main__":
94
+ demo.launch(
95
+ server_name="0.0.0.0", # 允许外部访问
96
+ server_port=7860, # Hugging Face Spaces 默认端口
97
+ share=False # 在 HF Spaces 上不需要 share
98
+ )