Skip to content

Commit 8bd9fce

Browse files
authored
Merge branch 'main' into feature/get-weld
2 parents 0ea2e96 + 51d296e commit 8bd9fce

File tree

241 files changed

+20395
-16380
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

241 files changed

+20395
-16380
lines changed

.github/workflows/generic.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
matrix:
1717
# See official Github documentation for details: https://shorturl.at/NJgsj
1818
OS: ["ubuntu-22.04", "ubuntu-24.04", "macos-15", "windows-cpu-4-core"]
19-
PYTHON_VERSION: ["3.10", "3.11", "3.12"]
19+
PYTHON_VERSION: ["3.10", "3.11", "3.12", "3.13"]
2020

2121
env:
2222
HF_HUB_DOWNLOAD_TIMEOUT: 60
@@ -103,7 +103,7 @@ jobs:
103103
104104
- name: Install Genesis
105105
run: |
106-
pip install -e '.[dev,render]'
106+
pip install -e '.[dev]'
107107
108108
- name: Run unit tests
109109
run: |

.github/workflows/production.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ jobs:
2222
WANDB_API_KEY: ${{ secrets.WANDB_API_KEY }}
2323
HF_TOKEN: ${{ secrets.HF_TOKEN }}
2424
HF_HUB_DOWNLOAD_TIMEOUT: 60
25-
GENESIS_IMAGE_VER: "1_0"
25+
GENESIS_IMAGE_VER: "1_1"
2626
TIMEOUT_MINUTES: 180
27+
MADRONA_DISABLE_CUDA_HEAP_SIZE: "1"
2728

2829
steps:
2930
- name: Checkout code

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ Install **PyTorch** first following the [official instructions](https://pytorch.
7777

7878
Then, install Genesis via PyPI:
7979
```bash
80-
pip install genesis-world # Requires Python>=3.10,<3.13;
80+
pip install genesis-world # Requires Python>=3.10,<3.14;
8181
```
8282

8383
For the latest version to date, make sure that `pip` is up-to-date via `pip install --upgrade pip`, then run command:
@@ -172,6 +172,7 @@ Genesis's development has been made possible thanks to these open-source project
172172
- [libccd](https://github.com/danfis/libccd): Reference for collision detection.
173173
- [PyRender](https://github.com/mmatl/pyrender): Rasterization-based renderer.
174174
- [LuisaCompute](https://github.com/LuisaGroup/LuisaCompute) and [LuisaRender](https://github.com/LuisaGroup/LuisaRender): Ray-tracing DSL.
175+
- [Madrona](https://github.com/shacklettbp/madrona) and [Madrona-mjx](https://github.com/shacklettbp/madrona_mjx): Batch renderer backend
175176

176177
## Associated Papers
177178

README_FR.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Page du projet : <https://genesis-embodied-ai.github.io/>
6969
Genesis est disponible via PyPI :
7070

7171
```bash
72-
pip install genesis-world # Nécessite Python>=3.10,<3.13;
72+
pip install genesis-world # Nécessite Python>=3.10,<3.14;
7373
```
7474

7575
Vous devez également installer **PyTorch** en suivant [les instructions officielles](https://pytorch.org/get-started/locally/).

README_JA.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Genesisの目指すところ:
6969
GenesisはPyPIで利用可能です:
7070

7171
```bash
72-
pip install genesis-world # Python>=3.10,<3.13 が必要です;
72+
pip install genesis-world # Python>=3.10,<3.14 が必要です;
7373
```
7474

7575
また、**PyTorch**[公式手順](https://pytorch.org/get-started/locally/)に従ってインストールする必要があります。

README_KR.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Genesis의 목표:
6969
Genesis는 PyPI를 통해 설치할 수 있습니다:
7070

7171
```bash
72-
pip install genesis-world # Python>=3.10,<3.13 필요
72+
pip install genesis-world # Python>=3.10,<3.14 필요
7373
```
7474

7575
또한, [공식 설명서](https://pytorch.org/get-started/locally/)에 따라 **PyTorch**를 설치해야 합니다.

examples/collision/contype.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
"""
2+
NOTE: contype and conaffinity are 32-bit integer bitmasks used for contact filtering of contact pairs.
3+
When the contype of one geom and the conaffinity of the other geom share a common bit set to 1, two geoms can collide.
4+
Plane: contype=0xFFFF, conaffinity=0xFFFF (1111 1111 1111 1111)
5+
Red Cube: contype=1, conaffinity=1 (0001) -> collide with Plane and Blue Cube
6+
Green Cube: contype=2, conaffinity=2 (0010) -> collide with Plane and Blue Cube
7+
Blue Cube: contype=3, conaffinity=3 (0011) -> collide with Plane, Red Cube, and Green Cube
8+
Dragon: contype=4, conaffinity=4 (0100) -> collide with Plane only
9+
"""
10+
11+
import argparse
12+
13+
import genesis as gs
14+
15+
16+
def main():
17+
parser = argparse.ArgumentParser()
18+
parser.add_argument("-v", "--vis", action="store_true", default=False)
19+
args = parser.parse_args()
20+
21+
gs.init()
22+
23+
scene = gs.Scene(
24+
viewer_options=gs.options.ViewerOptions(
25+
camera_pos=(0.0, -2, 1.5),
26+
camera_lookat=(0.0, 0.0, 0.5),
27+
camera_fov=40,
28+
max_FPS=200,
29+
),
30+
show_viewer=args.vis,
31+
)
32+
33+
scene.add_entity(gs.morphs.Plane())
34+
35+
scene.add_entity(
36+
gs.morphs.Box(
37+
pos=(0.025, 0, 0.5),
38+
quat=(0, 0, 0, 1),
39+
size=(0.1, 0.1, 0.1),
40+
contype=1,
41+
conaffinity=1,
42+
),
43+
surface=gs.surfaces.Default(
44+
color=(1.0, 0.0, 0.0, 1.0),
45+
),
46+
)
47+
scene.add_entity(
48+
gs.morphs.Box(
49+
pos=(-0.025, 0, 1.0),
50+
quat=(0, 0, 0, 1),
51+
size=(0.1, 0.1, 0.1),
52+
contype=2,
53+
conaffinity=2,
54+
),
55+
surface=gs.surfaces.Default(
56+
color=(0.0, 1.0, 0.0, 1.0),
57+
),
58+
)
59+
scene.add_entity(
60+
gs.morphs.Box(
61+
pos=(0.0, 0, 1.5),
62+
quat=(0, 0, 0, 1),
63+
size=(0.1, 0.1, 0.1),
64+
contype=3,
65+
conaffinity=3,
66+
),
67+
surface=gs.surfaces.Default(
68+
color=(0.0, 0.0, 1.0, 1.0),
69+
),
70+
)
71+
scene.add_entity(
72+
morph=gs.morphs.Mesh(
73+
file="meshes/dragon/dragon.obj",
74+
scale=0.004,
75+
euler=(0, 0, 90),
76+
pos=(-0.1, 0.0, 1.0),
77+
contype=4,
78+
conaffinity=4,
79+
),
80+
)
81+
82+
scene.build()
83+
84+
for i in range(1000):
85+
scene.step()
86+
87+
88+
if __name__ == "__main__":
89+
main()

examples/coupling/fem_cube_linked_with_arm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def main():
130130
cam.render()
131131

132132
print("Now dropping the cube")
133-
cube.solver.remove_vertex_constraints()
133+
cube.remove_vertex_constraints()
134134
steps = int(1 / dt)
135135
for i in tqdm(range(steps), total=steps):
136136
arm.control_dofs_position(arm_path_waypoints[-1])

examples/drone/hover_env.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
import math
33
import copy
44
import genesis as gs
5-
from genesis.utils.geom import quat_to_xyz, transform_by_quat, inv_quat, transform_quat_by_quat
5+
from genesis.utils.geom import (
6+
quat_to_xyz,
7+
transform_by_quat,
8+
inv_quat,
9+
transform_quat_by_quat,
10+
)
611

712

813
def gs_rand_float(lower, upper, shape, device):
@@ -147,7 +152,10 @@ def step(self, actions):
147152
self.last_rel_pos = self.commands - self.last_base_pos
148153
self.base_quat[:] = self.drone.get_quat()
149154
self.base_euler = quat_to_xyz(
150-
transform_quat_by_quat(torch.ones_like(self.base_quat) * self.inv_base_init_quat, self.base_quat),
155+
transform_quat_by_quat(
156+
torch.ones_like(self.base_quat) * self.inv_base_init_quat,
157+
self.base_quat,
158+
),
151159
rpy=True,
152160
degrees=True,
153161
)

examples/drone/interactive_drone.py

Lines changed: 38 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
import argparse
2-
import numpy as np
3-
import genesis as gs
41
import time
52
import threading
3+
64
from pynput import keyboard
5+
import numpy as np
6+
7+
import genesis as gs
78

89

910
class DroneController:
1011
def __init__(self):
11-
self.thrust = 14468.429183500699 # Base hover RPM - constant hover
12-
self.rotation_delta = 200 # Differential RPM for rotation
13-
self.thrust_delta = 10 # Amount to change thrust by when accelerating/decelerating
12+
self.thrust = 14475.8 # Base hover RPM - constant hover
13+
self.rotation_delta = 200.0 # Differential RPM for rotation
14+
self.thrust_delta = 10.0 # Amount to change thrust by when accelerating/decelerating
1415
self.running = True
1516
self.rpms = [self.thrust] * 4
1617
self.pressed_keys = set()
@@ -93,46 +94,37 @@ def update_thrust(self):
9394

9495
def run_sim(scene, drone, controller):
9596
while controller.running:
96-
try:
97-
# Update drone with current RPMs
98-
rpms = controller.update_thrust()
99-
drone.set_propellels_rpm(rpms)
97+
# Update drone with current RPMs
98+
rpms = controller.update_thrust()
99+
drone.set_propellels_rpm(rpms)
100100

101-
# Update physics
102-
scene.step()
101+
# Update physics
102+
scene.step(refresh_visualizer=False)
103103

104-
time.sleep(1 / 60) # Limit simulation rate
105-
except Exception as e:
106-
print(f"Error in simulation loop: {e}")
107-
108-
if scene.viewer:
109-
scene.viewer.stop()
104+
# Limit simulation rate
105+
time.sleep(1.0 / scene.viewer.max_FPS)
110106

111107

112108
def main():
113-
parser = argparse.ArgumentParser()
114-
parser.add_argument("-v", "--vis", action="store_true", default=True, help="Enable visualization (default: True)")
115-
parser.add_argument("-m", "--mac", action="store_true", default=False, help="Running on MacOS (default: False)")
116-
args = parser.parse_args()
117-
118109
# Initialize Genesis
119110
gs.init(backend=gs.cpu)
120111

121-
# Create scene with initial camera view
122-
viewer_options = gs.options.ViewerOptions(
123-
camera_pos=(0.0, -4.0, 2.0), # Now behind the drone (negative Y)
124-
camera_lookat=(0.0, 0.0, 0.5),
125-
camera_fov=45,
126-
max_FPS=60,
127-
)
128-
112+
# Create scene
129113
scene = gs.Scene(
130114
sim_options=gs.options.SimOptions(
131115
dt=0.01,
132116
gravity=(0, 0, -9.81),
133117
),
134-
viewer_options=viewer_options,
135-
show_viewer=args.vis,
118+
viewer_options=gs.options.ViewerOptions(
119+
camera_pos=(0.0, -2.0, 1.0),
120+
camera_lookat=(0.0, 0.0, 0.3),
121+
camera_fov=45,
122+
max_FPS=60,
123+
),
124+
vis_options=gs.options.VisOptions(
125+
show_world_frame=False,
126+
),
127+
show_viewer=True,
136128
)
137129

138130
# Add entities
@@ -146,38 +138,32 @@ def main():
146138

147139
scene.viewer.follow_entity(drone)
148140

149-
# Build scene
150-
scene.build()
151-
152141
# Initialize controller
153142
controller = DroneController()
154143

144+
# Start keyboard listener.
145+
# Note that instantiating the listener after building the scene causes segfault on MacOS.
146+
listener = keyboard.Listener(on_press=controller.on_press, on_release=controller.on_release)
147+
listener.start()
148+
149+
# Build scene
150+
scene.build()
151+
155152
# Print control instructions
156153
print("\nDrone Controls:")
157154
print("↑ - Move Forward (North)")
158155
print("↓ - Move Backward (South)")
159156
print("← - Move Left (West)")
160157
print("→ - Move Right (East)")
158+
print("space - Increase RPM")
159+
print("shift - Decrease RPM")
161160
print("ESC - Quit\n")
162161
print("Initial hover RPM:", controller.thrust)
163162

164-
# Start keyboard listener
165-
listener = keyboard.Listener(on_press=controller.on_press, on_release=controller.on_release)
166-
listener.start()
167-
168-
if args.mac:
169-
# Run simulation in another thread
170-
sim_thread = threading.Thread(target=run_sim, args=(scene, drone, controller))
171-
sim_thread.start()
172-
173-
if args.vis:
174-
scene.viewer.start()
163+
# Run simulation in another thread
164+
threading.Thread(target=run_sim, args=(scene, drone, controller)).start()
165+
scene.viewer.run()
175166

176-
# Wait for threads to finish
177-
sim_thread.join()
178-
else:
179-
# Run simulation in main thread
180-
run_sim(scene, drone, controller)
181167
listener.stop()
182168

183169

0 commit comments

Comments
 (0)