Programma
L’anno scorso è stato rilasciato Genesis, un nuovo strumento entusiasmante per creare simulazioni fisiche realistiche, mondi 4D interattivi e altro ancora. Non vedevo l’ora di provarlo, ma farlo funzionare non è stato semplice. Devo ammettere che ho incontrato parecchie difficoltà durante la configurazione.
In questo tutorial, ti racconterò brevemente i problemi che ho incontrato e ti mostrerò come alla fine sono riuscita a farlo girare usando Google Colab e un paio di trucchi.
Se vuoi soltanto una panoramica di Genesis, dai un’occhiata al mio articolo precedente, Genesis Physics Engine: una guida con esempi.
La mia esperienza iniziale di setup con Genesis
Quando ho iniziato a lavorare con Genesis, ho seguito i passaggi d’installazione indicati nella documentazione. Subito ho riscontrato problemi con le dipendenze. Genesis richiede una versione specifica di un modulo chiamato Taichi (1.7.x), ma il mio macOS non la supportava. Per riferimento, il mio Mac ha 8 anni…
Dopo qualche ricerca, ho capito che altri utenti avevano gli stessi problemi, anche con computer migliori. Dopo ore di tentativi, e dopo aver scoperto che Genesis funziona solo con determinate versioni di Python, sono finalmente riuscita a installarlo.
Ma sono emersi nuovi problemi. Non rendeva nulla a schermo e avevo diversi problemi con OpenGL. Anche provando a eseguire i file di esempio dal loro GitHub, ho incontrato ulteriori errori e conflitti.
Poi, quando pensavo di aver sistemato tutto, ho iniziato a ricevere errori come "uniform not found", che indicavano che mancavano alcune impostazioni di rendering.
Durante tutto il processo, ho cercato online per vedere se qualcun altro avesse incontrato gli stessi problemi. Si è scoperto che non ero la sola: molte persone hanno affrontato le stesse difficoltà e in molti sembravano non riuscire a trovare una soluzione per far funzionare i loro script.
Come ho fatto funzionare Genesis: Google Colab in soccorso
Dopo la frustrazione iniziale, ho deciso di provare Google Colab con un account Pro, e si è rivelato esattamente ciò di cui avevo bisogno. Usando le risorse GPU di Colab, sono riuscita a:
- Installare tutte le dipendenze necessarie senza alcun problema.
- Usare il backend GPU per ottenere ottime prestazioni e un rendering realistico.
- Finalmente, eseguire esempi di base ed esplorare il potenziale di Genesis.
Ho selezionato la NVIDIA A100-SXM4-40GB, che si è dimostrata sufficientemente potente per gestire le simulazioni di Genesis in modo efficiente.
Una volta configurato l’ambiente Google Colab e installato Genesis, ho provato a eseguire l’esempio più semplice dalla documentazione:
import genesis as gs
gs.init(backend=gs.cpu)
scene = gs.Scene(show_viewer=True)
Questo esempio dovrebbe inizializzare Genesis con il backend CPU e mostrare una scena di base. Tuttavia, mi sono imbattuta subito nel seguente errore:
GenesisException: No display detected. Use show_viewer=False for headless mode.
Il messaggio indica che Genesis sta cercando di creare una finestra grafica per renderizzare la scena, ma Google Colab non supporta la visualizzazione in tempo reale. Colab gira in un ambiente remoto senza accesso a un display locale, quindi il parametro show_viewer=True nell’inizializzazione di gs.Scene() non funziona.
Come suggerito dal messaggio d’errore, ho modificato il codice per disattivare il viewer:
scene = gs.Scene(show_viewer=False)
Questo ha permesso allo script di eseguire senza andare in crash. Tuttavia, questo approccio significava che non c’era modo di visualizzare direttamente i risultati.
Cercando online, ho scoperto che altri avevano affrontato lo stesso problema. Molte soluzioni proposte prevedevano la configurazione di ambienti OpenGL remoti o l’uso di Xvfb per creare un display virtuale. Purtroppo, non sono riuscita a far funzionare in modo affidabile questi metodi su Colab, probabilmente a causa di conflitti di dipendenze e limitazioni dell’ambiente.
A quel punto, avevo bisogno di una soluzione più pratica!
Dato che il rendering in tempo reale non era un’opzione in Colab, ho deciso di salvare l’output renderizzato frame per frame come immagini. Con queste idee, sono riuscita a generare una sequenza di immagini che poi potevano essere combinate in un’animazione.
Implementazione e output
In questa sezione, ti guiderò nell’implementazione del codice e negli output che ho ottenuto.
Configurare l’ambiente GPU
Per prima cosa, ho installato Genesis:
pip install genesis-world
Poi ho inizializzato Genesis con il backend CUDA per l’accelerazione su GPU.
import genesis as gs
gs.init(backend=gs.cuda)
Questo è l’output che ho ottenuto:
[Genesis] [INFO] Running on [NVIDIA A100-SXM4-40GB] with backend gs.cuda. Device memory: 39.56 GB.
[Genesis] [INFO] 🚀 Genesis initialized. Version: 0.2.1, Seed: None, Precision: 32.
Creare e costruire la scena
Crea una directory per salvare i risultati
La prima cosa di cui avevo bisogno era una cartella in cui Genesis potesse salvare le immagini renderizzate.
import os
save_dir = "/content/simulation_frames"
os.makedirs(save_dir, exist_ok=True)
La funzione os.makedirs() crea una cartella chiamata simulation_frames nel percorso specificato, e l’argomento exist_ok=True assicura che, se la cartella esiste già, non venga generato alcun errore.
In questo modo, avevo un luogo dedicato in cui salvare tutti i frame e gli output della mia simulazione.
Inizializza la scena
Successivamente, dovevo creare una scena in cui poter aggiungere oggetti e interagire con loro.
scene = gs.Scene(show_viewer=False)
gs.Scene() inizializza un nuovo spazio di simulazione e show_viewer=False disattiva la visualizzazione in tempo reale. A questo punto, avevo una scena vuota pronta da costruire.
Aggiungi un piano e un box
Con la scena pronta, ho iniziato ad aggiungere oggetti. Prima ho aggiunto un piano, che funge da suolo.
plane = scene.add_entity(gs.morphs.Plane())
Il piano serve da base piatta per la simulazione. Per impostazione predefinita è infinito e giace lungo l’asse x-y.
Poi ho aggiunto un box alla scena:
box = scene.add_entity(
gs.morphs.Box(
pos=(0, 0, 0), # Position of the box
size=(0.5, 0.5, 0.5) # Size of the box
)
)
Ho posizionato il box in (0, 0, 0), proprio al centro della scena, e l’ho ridimensionato a 0.5 unità di larghezza, altezza e profondità, rendendolo più piccolo del default.
Ora avevo un setup semplice: un piano come suolo e un box appoggiato sopra.
Aggiungi una camera
Per catturare ciò che accadeva nella scena, ho aggiunto una camera.
cam = scene.add_camera(
res=(320, 240), # Resolution: 320x240 pixels
pos=(3.5, 2.0, 2.5), # Camera position
lookat=(0, 0, 0.5), # Point the camera is focused on
fov=30 # Field of view (in degrees)
)
Ho impostato la risoluzione dell’immagine a 320x240 pixel, una scelta pratica per i test, e posizionato la camera a (3.5, 2.0, 2.5), che le dava una vista chiara della scena da leggermente sopra e di lato. Per assicurarmi che il box rimanesse a fuoco, ho puntato la camera su (0, 0, 0.5), appena sopra il centro del box. Con un campo visivo (FOV) di 30 gradi, la camera catturava una prospettiva stretta e focalizzata della scena.
Costruisci la scena
Il passo successivo era costruire la scena per prepararla alla simulazione e al rendering.
scene.build()
Questo passaggio è cruciale perché Genesis utilizza la compilazione just-in-time (JIT) per ottimizzare la simulazione. Quando ho costruito la scena, Genesis:
- Ha allocato memoria per gli oggetti nella scena.
- Ha preparato i kernel GPU per il rendering e i calcoli fisici.
- Ha predisposto tutte le strutture dati necessarie per far girare la simulazione in modo fluido.
Ora era tutto pronto: piano, box e camera erano impostati e la scena era stata costruita.
Rendering e salvataggio degli output
Per visualizzare la simulazione, ho renderizzato e salvato gli output frame per frame. Ogni frame è stato memorizzato come immagine nella directory simulation_frames.
from PIL import Image
import numpy as np
# Render and save images
for i in range(30):
scene.step() # Advance simulation
if i % 5 == 0: # Save every 5th frame
print(f"Step {i}/30")
rgb_data = cam.render(rgb=True)
# Extract image data and save it
img_array = rgb_data[0]
img = Image.fromarray((img_array * 255).astype(np.uint8))
img.save(f"{save_dir}/frame_{i:03d}.png")
print(f"Frame {i} saved to {save_dir}")
Durante il rendering, ho osservato che i primi frame venivano generati rapidamente (fino a 2.297 FPS), ma le prestazioni diminuivano con l’avanzare della simulazione. Gli FPS sono scesi fino a circa 0,33 FPS al frame 25. Ciò potrebbe essere dovuto alla crescente complessità computazionale della simulazione o forse a vincoli delle risorse GPU per scene più grandi.
Questo è l’output che ho ottenuto:
[Genesis] [22:16:38] [INFO] Running at 2297.81 FPS.
INFO:genesis:Running at ~<2297.81>~ FPS.
Step 0/30
[Genesis] [22:16:56] [INFO] Running at 1.11 FPS.
INFO:genesis:Running at ~<1.11>~ FPS.
[Genesis] [22:16:56] [INFO] Running at 1.17 FPS.
INFO:genesis:Running at ~<1.17>~ FPS.
[Genesis] [22:16:56] [INFO] Running at 1.23 FPS.
INFO:genesis:Running at ~<1.23>~ FPS.
[Genesis] [22:16:56] [INFO] Running at 1.29 FPS.
INFO:genesis:Running at ~<1.29>~ FPS.
[Genesis] [22:16:56] [INFO] Running at 1.36 FPS.
INFO:genesis:Running at ~<1.36>~ FPS.
Frame 0 saved to /content/simulation_frames
Step 5/30
[Genesis] [22:17:14] [INFO] Running at 0.63 FPS.
INFO:genesis:Running at ~<0.63>~ FPS.
[Genesis] [22:17:14] [INFO] Running at 0.67 FPS.
INFO:genesis:Running at ~<0.67>~ FPS.
[Genesis] [22:17:14] [INFO] Running at 0.70 FPS.
INFO:genesis:Running at ~<0.70>~ FPS.
[Genesis] [22:17:14] [INFO] Running at 0.74 FPS.
INFO:genesis:Running at ~<0.74>~ FPS.
[Genesis] [22:17:14] [INFO] Running at 0.78 FPS.
INFO:genesis:Running at ~<0.78>~ FPS.
Frame 5 saved to /content/simulation_frames
Step 10/30
[Genesis] [22:17:32] [INFO] Running at 0.47 FPS.
INFO:genesis:Running at ~<0.47>~ FPS.
[Genesis] [22:17:32] [INFO] Running at 0.50 FPS.
INFO:genesis:Running at ~<0.50>~ FPS.
[Genesis] [22:17:32] [INFO] Running at 0.53 FPS.
INFO:genesis:Running at ~<0.53>~ FPS.
[Genesis] [22:17:32] [INFO] Running at 0.55 FPS.
INFO:genesis:Running at ~<0.55>~ FPS.
[Genesis] [22:17:32] [INFO] Running at 0.58 FPS.
INFO:genesis:Running at ~<0.58>~ FPS.
Frame 10 saved to /content/simulation_frames
Step 15/30
[Genesis] [22:17:49] [INFO] Running at 0.40 FPS.
INFO:genesis:Running at ~<0.40>~ FPS.
[Genesis] [22:17:49] [INFO] Running at 0.42 FPS.
INFO:genesis:Running at ~<0.42>~ FPS.
[Genesis] [22:17:49] [INFO] Running at 0.44 FPS.
INFO:genesis:Running at ~<0.44>~ FPS.
[Genesis] [22:17:49] [INFO] Running at 0.46 FPS.
INFO:genesis:Running at ~<0.46>~ FPS.
[Genesis] [22:17:49] [INFO] Running at 0.49 FPS.
INFO:genesis:Running at ~<0.49>~ FPS.
Frame 15 saved to /content/simulation_frames
Step 20/30
[Genesis] [22:18:07] [INFO] Running at 0.35 FPS.
INFO:genesis:Running at ~<0.35>~ FPS.
[Genesis] [22:18:07] [INFO] Running at 0.37 FPS.
INFO:genesis:Running at ~<0.37>~ FPS.
[Genesis] [22:18:07] [INFO] Running at 0.39 FPS.
INFO:genesis:Running at ~<0.39>~ FPS.
[Genesis] [22:18:07] [INFO] Running at 0.41 FPS.
INFO:genesis:Running at ~<0.41>~ FPS.
[Genesis] [22:18:07] [INFO] Running at 0.43 FPS.
INFO:genesis:Running at ~<0.43>~ FPS.
Frame 20 saved to /content/simulation_frames
Step 25/30
[Genesis] [22:18:24] [INFO] Running at 0.33 FPS.
INFO:genesis:Running at ~<0.33>~ FPS.
[Genesis] [22:18:24] [INFO] Running at 0.35 FPS.
INFO:genesis:Running at ~<0.35>~ FPS.
[Genesis] [22:18:24] [INFO] Running at 0.36 FPS.
INFO:genesis:Running at ~<0.36>~ FPS.
[Genesis] [22:18:24] [INFO] Running at 0.38 FPS.
INFO:genesis:Running at ~<0.38>~ FPS.
Frame 25 saved to /content/simulation_frames
Queste sono le immagini che ho ottenuto:





Ogni immagine mostra come il box si muove nel tempo in relazione al piano, visto attraverso la camera. La simulazione procede a step e, a ogni step, la posizione del box cambia, facendo sembrare che il box stia muovendosi.
Questo esempio mette in evidenza come Genesis possa simulare e mostrare semplici interazioni fisiche. Anche se questo setup è basilare, dà una buona idea di come gli oggetti si comportano nella scena. Ma con Genesis puoi assolutamente creare scenari più complessi e realistici! Esploreremo alcune di queste capacità nella prossima sezione.
Esplorare Genesis: capacità e funzionalità
Creazione di oggetti e scene
Genesis ti permette di creare scene complesse aggiungendo vari oggetti e morph. Gli oggetti possono andare da primitive semplici come piani, box e sfere a entità più complesse come robot e terreni.
Primitive di forma:
- gs.morphs.Plane
- gs.morphs.Box
- gs.morphs.Cylinder
- gs.morphs.Sphere
Supporto a file esterni:
- MJCF: gs.morphs.MJCF per le configurazioni robot in XML MuJoCo.
- URDF: gs.morphs.URDF per i file in Unified Robot Description Format.
- Mesh: gs.morphs.Mesh per asset 3D come .obj, .ply, .stl, .glb e .gltf.
Genesis utilizza un concetto unificato chiamato "morph", che incapsula geometria e informazioni di posa. Questo design orientato agli oggetti permette di interagire direttamente con le entità tramite i loro metodi.
Rendering e visualizzazione
Uno dei punti di forza di Genesis è la capacità di creare output visivi dettagliati usando funzionalità avanzate della camera. Le camere funzionano in "modalità headless", cioè possono generare immagini senza la necessità di uno schermo. Possono produrre diversi tipi di visuali, tra cui immagini a colori (RGB), mappe di profondità che mostrano la distanza degli oggetti, maschere di segmentazione che etichettano le diverse parti della scena e normal map che rappresentano i dettagli delle superfici.
Registrazione di video
Puoi creare video lasciando che le camere registrino automaticamente ogni frame della simulazione. Puoi persino muovere la camera durante la registrazione per rendere il video più dinamico e coinvolgente.
Per esempio, puoi configurare una camera affinché si muova su una traiettoria circolare attorno alla scena mentre cattura i frame. La funzione cam.start_recording() avvia la registrazione e, a ogni step della simulazione, la posizione della camera viene aggiornata. Una volta catturati tutti i frame, cam.stop_recording() salva il video come "video.mp4".
Il video finale offre una visuale fluida della simulazione, mostrando come gli oggetti interagiscono e si muovono nel tempo.
Generazione di terreni per compiti di locomozione
Puoi anche creare diversi tipi di terreni per la robotica e l’addestramento di IA. Puoi usare le opzioni di terreno integrate o progettarne di tuoi fornendo height map personalizzate con gs.morphs.Terrain. Questi terreni sono perfetti per testare e allenare la locomozione dei robot, rendendo Genesis un ottimo strumento per la ricerca in robotica.
Estensibilità
Puoi anche personalizzare le tue simulazioni in vari modi. Puoi aggiungere texture realistiche agli oggetti, rendendoli più verosimili. Supporta inoltre molti formati di file per l’importazione di modelli e, se un formato non è supportato, puoi richiederne l’aggiunta. Inoltre, puoi creare forme di oggetti personalizzate (chiamate morph) usando file e impostazioni proprie.
Conclusione
Questo tutorial ha fornito un esempio semplice per aiutarti a iniziare con Genesis. Abbiamo coperto le basi, come creare scene, aggiungere oggetti e renderizzare gli output, per mostrare come funziona questo potente motore fisico.
Tuttavia, questo è solo l’inizio di ciò che Genesis può fare. Con l’hardware giusto, come una GPU potente e memoria sufficiente, le possibilità sono tantissime. Puoi usarlo per simulazioni robotiche complesse o per creare dataset di alta qualità per l’addestramento di IA. Anche se la configurazione può essere complicata, è sicuramente uno strumento con un enorme potenziale!
Ana Rojo Echeburúa è una specialista di AI e dati con un dottorato in Matematica Applicata. Le piace trasformare i dati in insight azionabili e ha una vasta esperienza nella guida di team tecnici. Ana ama collaborare da vicino con i clienti per risolvere le loro sfide di business e creare soluzioni di AI innovative. Nota per le sue capacità di problem solving e la comunicazione chiara, è appassionata di AI, in particolare di AI generativa. Ana è dedita all’apprendimento continuo e allo sviluppo etico dell’AI, oltre a semplificare problemi complessi e spiegare la tecnologia in modo accessibile.


