tiffank1802 commited on
Commit ·
d0e4d91
1
Parent(s): 1f654d9
SOLUTION: Replace Gradio with Streamlit
Browse files- Gradio had persistent dependency conflicts with huggingface_hub
- Streamlit is much simpler and more reliable for deployment
- Same interactive functionality with faster startup
- Clean interface with sidebar controls
- Only 3 dependencies: streamlit, numpy, matplotlib
- Dockerfile +1 -1
- app.py +34 -35
- app_gradio.py +104 -0
- requirements.txt +1 -1
Dockerfile
CHANGED
|
@@ -8,4 +8,4 @@ RUN pip install --no-cache-dir --upgrade pip && \
|
|
| 8 |
|
| 9 |
COPY . .
|
| 10 |
|
| 11 |
-
CMD ["
|
|
|
|
| 8 |
|
| 9 |
COPY . .
|
| 10 |
|
| 11 |
+
CMD ["streamlit", "run", "app.py", "--server.port=7860"]
|
app.py
CHANGED
|
@@ -1,8 +1,6 @@
|
|
| 1 |
-
import
|
| 2 |
import numpy as np
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
-
from io import BytesIO
|
| 5 |
-
import base64
|
| 6 |
import time
|
| 7 |
|
| 8 |
def simple_simulation(mode, nx, delta, with_perturbation):
|
|
@@ -62,43 +60,44 @@ def simple_simulation(mode, nx, delta, with_perturbation):
|
|
| 62 |
|
| 63 |
plt.tight_layout()
|
| 64 |
|
| 65 |
-
# Convertir en image
|
| 66 |
-
buf = BytesIO()
|
| 67 |
-
fig.savefig(buf, format='png', dpi=100)
|
| 68 |
-
buf.seek(0)
|
| 69 |
-
img_b64 = base64.b64encode(buf.read()).decode('utf-8')
|
| 70 |
-
plt.close(fig)
|
| 71 |
-
|
| 72 |
-
plot_html = f'<img src="data:image/png;base64,{img_b64}" style="max-width:100%;">'
|
| 73 |
elapsed = f"Temps de calcul: {time.time() - start_time:.2f}s"
|
| 74 |
|
| 75 |
-
return
|
| 76 |
|
| 77 |
except Exception as e:
|
| 78 |
-
return f"Erreur: {str(e)}"
|
| 79 |
|
| 80 |
-
# Interface
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
with gr.Row():
|
| 93 |
-
run_btn = gr.Button("Lancer Simulation", variant="primary")
|
| 94 |
|
| 95 |
-
|
| 96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
|
|
|
|
|
|
| 103 |
|
| 104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
import numpy as np
|
| 3 |
import matplotlib.pyplot as plt
|
|
|
|
|
|
|
| 4 |
import time
|
| 5 |
|
| 6 |
def simple_simulation(mode, nx, delta, with_perturbation):
|
|
|
|
| 60 |
|
| 61 |
plt.tight_layout()
|
| 62 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
elapsed = f"Temps de calcul: {time.time() - start_time:.2f}s"
|
| 64 |
|
| 65 |
+
return fig, elapsed
|
| 66 |
|
| 67 |
except Exception as e:
|
| 68 |
+
return None, f"Erreur: {str(e)}"
|
| 69 |
|
| 70 |
+
# Interface Streamlit
|
| 71 |
+
st.title("🤖 Simulation Robot Souple")
|
| 72 |
+
st.markdown("Interface simple et rapide pour simuler un robot flexible")
|
| 73 |
+
|
| 74 |
+
# Contrôles dans la sidebar
|
| 75 |
+
with st.sidebar:
|
| 76 |
+
st.header("Paramètres")
|
| 77 |
+
mode = st.selectbox("Mode de simulation", ["Boucle ouverte", "PID"])
|
| 78 |
+
nx = st.slider("Nombre d'éléments (nx)", 5, 15, 10)
|
| 79 |
+
delta = st.slider("Pas de temps (δt)", 0.01, 0.1, 0.02)
|
| 80 |
+
with_perturbation = st.checkbox("Avec perturbation", False)
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
+
run_button = st.button("🚀 Lancer Simulation", type="primary")
|
| 83 |
+
|
| 84 |
+
# Zone de résultat
|
| 85 |
+
if run_button:
|
| 86 |
+
with st.spinner("Calcul en cours..."):
|
| 87 |
+
fig, elapsed = simple_simulation(mode, nx, delta, with_perturbation)
|
| 88 |
|
| 89 |
+
if fig is not None:
|
| 90 |
+
st.success(elapsed)
|
| 91 |
+
st.pyplot(fig, use_container_width=True)
|
| 92 |
+
else:
|
| 93 |
+
st.error(elapsed)
|
| 94 |
+
else:
|
| 95 |
+
st.info("👈 Configurez les paramètres et cliquez sur 'Lancer Simulation'")
|
| 96 |
|
| 97 |
+
# Instructions
|
| 98 |
+
st.markdown("---")
|
| 99 |
+
st.markdown("### 💡 Instructions")
|
| 100 |
+
st.markdown("1. Choisissez le mode de simulation dans le menu de gauche")
|
| 101 |
+
st.markdown("2. Ajustez les paramètres avec les curseurs")
|
| 102 |
+
st.markdown("3. Cliquez sur 'Lancer Simulation' pour voir les résultats")
|
| 103 |
+
st.markdown("4. Les calculs sont ultra-rapides : < 1 seconde !")
|
app_gradio.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import numpy as np
|
| 3 |
+
import matplotlib.pyplot as plt
|
| 4 |
+
from io import BytesIO
|
| 5 |
+
import base64
|
| 6 |
+
import time
|
| 7 |
+
|
| 8 |
+
def simple_simulation(mode, nx, delta, with_perturbation):
|
| 9 |
+
start_time = time.time()
|
| 10 |
+
|
| 11 |
+
try:
|
| 12 |
+
# Paramètres très simplifiés
|
| 13 |
+
L = 500
|
| 14 |
+
nstep = min(50, int(1 / delta)) # Très court
|
| 15 |
+
time0 = np.linspace(0, delta * nstep, nstep + 1)
|
| 16 |
+
ixe = np.linspace(delta, L, nx)
|
| 17 |
+
|
| 18 |
+
# Simulation ultra-simplifiée
|
| 19 |
+
if mode == "Boucle ouverte":
|
| 20 |
+
# Signal simple
|
| 21 |
+
u = np.zeros((nx, len(time0)))
|
| 22 |
+
for i, t in enumerate(time0):
|
| 23 |
+
if t > 0.1:
|
| 24 |
+
u[:, i] = 0.01 * np.sin(2 * np.pi * 0.5 * t) * np.sin(np.pi * ixe / L)
|
| 25 |
+
else:
|
| 26 |
+
u[:, i] = 0
|
| 27 |
+
|
| 28 |
+
title = "Simulation Boucle Ouverte"
|
| 29 |
+
|
| 30 |
+
else: # PID
|
| 31 |
+
# Simulation PID ultra-simple
|
| 32 |
+
u = np.zeros((nx, len(time0)))
|
| 33 |
+
for i, t in enumerate(time0):
|
| 34 |
+
if t > 0.1:
|
| 35 |
+
u[:, i] = 0.005 * (1 - np.exp(-2 * t)) * np.sin(np.pi * ixe / L)
|
| 36 |
+
else:
|
| 37 |
+
u[:, i] = 0
|
| 38 |
+
|
| 39 |
+
title = "Simulation PID"
|
| 40 |
+
|
| 41 |
+
# Ajouter bruit si demandé
|
| 42 |
+
if with_perturbation:
|
| 43 |
+
noise = 0.001 * np.random.randn(nx, len(time0))
|
| 44 |
+
u += noise
|
| 45 |
+
|
| 46 |
+
# Créer un simple plot
|
| 47 |
+
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
|
| 48 |
+
|
| 49 |
+
# Plot 1: Déformation finale
|
| 50 |
+
ax1.plot(ixe, u[:, -1], 'b-', linewidth=2)
|
| 51 |
+
ax1.set_title(f'{title} - Déformation finale')
|
| 52 |
+
ax1.set_xlabel('Position x (m)')
|
| 53 |
+
ax1.set_ylabel('Déplacement u (m)')
|
| 54 |
+
ax1.grid(True)
|
| 55 |
+
|
| 56 |
+
# Plot 2: Évolution au temps
|
| 57 |
+
ax2.plot(time0, u[-1, :], 'r-', linewidth=2)
|
| 58 |
+
ax2.set_title(f'{title} - Évolution du tip')
|
| 59 |
+
ax2.set_xlabel('Temps (s)')
|
| 60 |
+
ax2.set_ylabel('Déplacement u_B (m)')
|
| 61 |
+
ax2.grid(True)
|
| 62 |
+
|
| 63 |
+
plt.tight_layout()
|
| 64 |
+
|
| 65 |
+
# Convertir en image
|
| 66 |
+
buf = BytesIO()
|
| 67 |
+
fig.savefig(buf, format='png', dpi=100)
|
| 68 |
+
buf.seek(0)
|
| 69 |
+
img_b64 = base64.b64encode(buf.read()).decode('utf-8')
|
| 70 |
+
plt.close(fig)
|
| 71 |
+
|
| 72 |
+
plot_html = f'<img src="data:image/png;base64,{img_b64}" style="max-width:100%;">'
|
| 73 |
+
elapsed = f"Temps de calcul: {time.time() - start_time:.2f}s"
|
| 74 |
+
|
| 75 |
+
return plot_html, elapsed
|
| 76 |
+
|
| 77 |
+
except Exception as e:
|
| 78 |
+
return f"Erreur: {str(e)}", f"Temps: {time.time() - start_time:.2f}s"
|
| 79 |
+
|
| 80 |
+
# Interface Gradio simplifiée
|
| 81 |
+
with gr.Blocks() as demo:
|
| 82 |
+
gr.Markdown("# Simulation Robot Souple - Interface Simplifiée")
|
| 83 |
+
|
| 84 |
+
with gr.Row():
|
| 85 |
+
mode_dropdown = gr.Dropdown(["Boucle ouverte", "PID"], value="Boucle ouverte", label="Mode de simulation")
|
| 86 |
+
|
| 87 |
+
with gr.Row():
|
| 88 |
+
nx_slider = gr.Slider(5, 15, 10, label="Nombre d'éléments (nx)")
|
| 89 |
+
delta_slider = gr.Slider(0.01, 0.1, 0.02, label="Pas de temps (δt)")
|
| 90 |
+
pert_checkbox = gr.Checkbox(False, label="Avec perturbation")
|
| 91 |
+
|
| 92 |
+
with gr.Row():
|
| 93 |
+
run_btn = gr.Button("Lancer Simulation", variant="primary")
|
| 94 |
+
|
| 95 |
+
plot_output = gr.HTML()
|
| 96 |
+
time_output = gr.Textbox(label="Performance")
|
| 97 |
+
|
| 98 |
+
run_btn.click(
|
| 99 |
+
simple_simulation,
|
| 100 |
+
inputs=[mode_dropdown, nx_slider, delta_slider, pert_checkbox],
|
| 101 |
+
outputs=[plot_output, time_output]
|
| 102 |
+
)
|
| 103 |
+
|
| 104 |
+
demo.launch()
|
requirements.txt
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
-
|
| 2 |
numpy==1.24.3
|
| 3 |
matplotlib==3.7.2
|
|
|
|
| 1 |
+
streamlit==1.28.1
|
| 2 |
numpy==1.24.3
|
| 3 |
matplotlib==3.7.2
|