Skip to content

Commit ee6e6e8

Browse files
authored
Merge branch 'main' into yiling/250728_frictionloss
2 parents af015a5 + d88faa9 commit ee6e6e8

File tree

226 files changed

+2004
-4287
lines changed

Some content is hidden

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

226 files changed

+2004
-4287
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

MANIFEST.in

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@ include LICENSE
33
recursive-include genesis/assets *
44
recursive-include genesis/ext/pyrender/fonts *
55
recursive-include genesis/ext/pyrender/shaders *
6-
include genesis/ext/VolumeSampling
7-
include genesis/ext/fast_simplification/*.h
6+
include genesis/ext/VolumeSampling

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: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ def main():
3737
pos=(0.025, 0, 0.5),
3838
quat=(0, 0, 0, 1),
3939
size=(0.1, 0.1, 0.1),
40-
contype=1,
41-
conaffinity=1,
40+
contype=0b001,
41+
conaffinity=0b001,
4242
),
4343
surface=gs.surfaces.Default(
4444
color=(1.0, 0.0, 0.0, 1.0),
@@ -49,8 +49,8 @@ def main():
4949
pos=(-0.025, 0, 1.0),
5050
quat=(0, 0, 0, 1),
5151
size=(0.1, 0.1, 0.1),
52-
contype=2,
53-
conaffinity=2,
52+
contype=0b010,
53+
conaffinity=0b010,
5454
),
5555
surface=gs.surfaces.Default(
5656
color=(0.0, 1.0, 0.0, 1.0),
@@ -61,8 +61,8 @@ def main():
6161
pos=(0.0, 0, 1.5),
6262
quat=(0, 0, 0, 1),
6363
size=(0.1, 0.1, 0.1),
64-
contype=3,
65-
conaffinity=3,
64+
contype=0b011,
65+
conaffinity=0b011,
6666
),
6767
surface=gs.surfaces.Default(
6868
color=(0.0, 0.0, 1.0, 1.0),
@@ -74,8 +74,8 @@ def main():
7474
scale=0.004,
7575
euler=(0, 0, 90),
7676
pos=(-0.1, 0.0, 1.0),
77-
contype=4,
78-
conaffinity=4,
77+
contype=0b100,
78+
conaffinity=0b100,
7979
),
8080
)
8181

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

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import argparse
2+
import numpy as np
3+
4+
import genesis as gs
5+
from genesis.utils.geom import trans_to_T
6+
from genesis.utils.image_exporter import FrameImageExporter
7+
8+
9+
def main():
10+
parser = argparse.ArgumentParser()
11+
parser.add_argument("-v", "--vis", action="store_true", default=False)
12+
parser.add_argument("-c", "--cpu", action="store_true", default=False)
13+
parser.add_argument("-b", "--n_envs", type=int, default=3)
14+
parser.add_argument("-s", "--n_steps", type=int, default=2)
15+
parser.add_argument("-r", "--render_all_cameras", action="store_true", default=False)
16+
parser.add_argument("-o", "--output_dir", type=str, default="img_output/test")
17+
parser.add_argument("-u", "--use_rasterizer", action="store_true", default=False)
18+
args = parser.parse_args()
19+
20+
########################## init ##########################
21+
gs.init(backend=gs.cpu if args.cpu else gs.gpu)
22+
23+
########################## create a scene ##########################
24+
scene = gs.Scene(
25+
renderer=gs.options.renderers.BatchRenderer(
26+
use_rasterizer=args.use_rasterizer,
27+
),
28+
)
29+
30+
########################## entities ##########################
31+
plane = scene.add_entity(
32+
gs.morphs.Plane(),
33+
)
34+
franka = scene.add_entity(
35+
gs.morphs.MJCF(file="xml/franka_emika_panda/panda.xml"),
36+
visualize_contact=True,
37+
)
38+
39+
########################## cameras ##########################
40+
cam_0 = scene.add_camera(
41+
res=(512, 512),
42+
pos=(1.5, 0.5, 1.5),
43+
lookat=(0.0, 0.0, 0.5),
44+
fov=45,
45+
GUI=args.vis,
46+
)
47+
cam_0.attach(franka.links[6], trans_to_T(np.array([0.0, 0.5, 0.0])))
48+
cam_1 = scene.add_camera(
49+
res=(512, 512),
50+
pos=(1.5, -0.5, 1.5),
51+
lookat=(0.0, 0.0, 0.5),
52+
fov=45,
53+
GUI=args.vis,
54+
)
55+
scene.add_light(
56+
pos=[0.0, 0.0, 1.5],
57+
dir=[1.0, 1.0, -2.0],
58+
directional=1,
59+
castshadow=1,
60+
cutoff=45.0,
61+
intensity=0.5,
62+
)
63+
scene.add_light(
64+
pos=[4, -4, 4],
65+
dir=[-1, 1, -1],
66+
directional=0,
67+
castshadow=1,
68+
cutoff=45.0,
69+
intensity=0.5,
70+
)
71+
72+
########################## build ##########################
73+
scene.build(n_envs=args.n_envs)
74+
75+
# Create an image exporter
76+
exporter = FrameImageExporter(args.output_dir)
77+
78+
for i in range(args.n_steps):
79+
scene.step()
80+
if args.render_all_cameras:
81+
rgba, depth, _, _ = scene.render_all_cameras(rgb=True, depth=True)
82+
exporter.export_frame_all_cameras(i, rgb=rgba, depth=depth)
83+
else:
84+
rgba, depth, _, _ = cam_1.render(rgb=True, depth=True)
85+
exporter.export_frame_single_camera(i, cam_1.idx, rgb=rgba, depth=depth)
86+
87+
88+
if __name__ == "__main__":
89+
main()

0 commit comments

Comments
 (0)