Skip to content

Commit 93f034b

Browse files
committed
Merge remote-tracking branch 'company/main' into support-batch-renderer
2 parents 45bf9ed + 511dd04 commit 93f034b

Some content is hidden

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

48 files changed

+19416
-15870
lines changed

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/keyboard_teleop.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,6 @@ def build_scene():
5454

5555
########################## create a scene ##########################
5656
scene = gs.Scene(
57-
viewer_options=gs.options.ViewerOptions(
58-
camera_pos=(1.5, 0.0, 0.7),
59-
camera_lookat=(0.2, 0.0, 0.1),
60-
camera_fov=50,
61-
max_FPS=60,
62-
),
6357
sim_options=gs.options.SimOptions(
6458
substeps=4,
6559
),
@@ -70,6 +64,12 @@ def build_scene():
7064
box_box_detection=True,
7165
constraint_timeconst=0.02,
7266
),
67+
viewer_options=gs.options.ViewerOptions(
68+
camera_pos=(1.5, 0.0, 0.7),
69+
camera_lookat=(0.2, 0.0, 0.1),
70+
camera_fov=50,
71+
max_FPS=60,
72+
),
7373
show_viewer=True,
7474
show_FPS=False,
7575
)

examples/rigid/convex_decomposition.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ def main():
1212
args = parser.parse_args()
1313

1414
########################## init ##########################
15-
gs.init(backend=gs.cpu if args.cpu else gs.gpu, precision="64" if args.cpu else "32", seed=0)
15+
gs.init(backend=gs.cpu if args.cpu else gs.gpu, precision="32", seed=0)
1616

1717
########################## create a scene ##########################
1818
scene = gs.Scene(
1919
rigid_options=gs.options.RigidOptions(
20-
dt=0.004,
20+
dt=0.01,
2121
),
2222
show_viewer=args.vis,
2323
show_FPS=False,
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import argparse
2+
3+
import genesis as gs
4+
import numpy as np
5+
import trimesh
6+
from genesis.sensors import NPZFileWriter, RigidContactForceGridSensor, SensorDataRecorder, VideoFileWriter
7+
from genesis.utils.misc import tensor_to_array
8+
from tqdm import tqdm
9+
10+
11+
def visualize_grid_sensor(scene: gs.Scene, sensor: RigidContactForceGridSensor, min_force=0.0, max_force=1.0):
12+
"""
13+
Draws debug objects on scene to visualize the contact grid sensor data.
14+
15+
Note: This method is very inefficient and purely for demo/debugging purposes.
16+
This processes the grid data from the sensor, which means the transformation from global-> local frame is undone to
17+
revert back to into global frame to draw the debug objects.
18+
"""
19+
grid_data = sensor.read()
20+
21+
link_pos = tensor_to_array(scene._sim.rigid_solver.get_links_pos(links_idx=sensor.link_idx).squeeze(axis=1))
22+
link_quat = tensor_to_array(scene._sim.rigid_solver.get_links_quat(links_idx=sensor.link_idx).squeeze(axis=1))
23+
24+
sensor_dims = sensor.max_bounds - sensor.min_bounds
25+
grid_cell_size = sensor_dims / np.array(sensor.grid_size)
26+
27+
debug_objs = []
28+
29+
for x in range(grid_data.shape[1]):
30+
for y in range(grid_data.shape[2]):
31+
for z in range(grid_data.shape[3]):
32+
force = grid_data[0, x, y, z]
33+
force_magnitude = np.linalg.norm(force)
34+
35+
color_intensity = np.clip(force_magnitude, min_force, max_force) / max_force
36+
color = np.array([color_intensity, 0.0, 1.0 - color_intensity, 0.4])
37+
38+
mesh = trimesh.creation.box(extents=grid_cell_size)
39+
mesh.visual = trimesh.visual.ColorVisuals(vertex_colors=np.tile(color, [len(mesh.vertices), 1]))
40+
41+
local_pos = sensor.min_bounds + (np.array([x, y, z]) + 0.5) * grid_cell_size
42+
43+
T = trimesh.transformations.quaternion_matrix(link_quat)
44+
T[:3, 3] = link_pos
45+
46+
local_T = np.eye(4)
47+
local_T[:3, 3] = local_pos
48+
final_T = T @ local_T
49+
50+
debug_objs.append(scene.draw_debug_mesh(mesh, T=final_T))
51+
52+
return debug_objs
53+
54+
55+
def main():
56+
parser = argparse.ArgumentParser()
57+
parser.add_argument("--seconds", "-t", type=float, default=1, help="Number of seconds to simulate")
58+
parser.add_argument("--dt", type=float, default=1e-2, help="Simulation time step")
59+
parser.add_argument(
60+
"--substeps",
61+
type=int,
62+
default=1,
63+
help="Number of substeps",
64+
)
65+
parser.add_argument("--n_envs", type=int, default=0, help="Number of environments (default: 0)")
66+
parser.add_argument("--cpu", action="store_true", help="Use CPU instead of GPU")
67+
parser.add_argument("--vis", "-v", action="store_true", help="Show visualization GUI")
68+
parser.add_argument(
69+
"--debug", "-d", action="store_true", default=True, help="Draw the contact grid sensor debug objects"
70+
)
71+
72+
args = parser.parse_args()
73+
74+
gs.init(backend=gs.gpu, logging_level=None)
75+
76+
scene = gs.Scene(
77+
sim_options=gs.options.SimOptions(
78+
dt=args.dt,
79+
substeps=args.substeps,
80+
gravity=(0, 0, -9.81),
81+
),
82+
rigid_options=gs.options.RigidOptions(
83+
use_gjk_collision=True,
84+
constraint_timeconst=max(0.01, 2 * args.dt / args.substeps),
85+
),
86+
profiling_options=gs.options.ProfilingOptions(
87+
show_FPS=False,
88+
),
89+
show_viewer=args.vis,
90+
)
91+
92+
scene.add_entity(gs.morphs.Plane())
93+
94+
block = scene.add_entity(
95+
morph=gs.morphs.Box(
96+
pos=(0.0, 0.0, 0.2),
97+
euler=(0, 10, 0),
98+
size=(2.0, 2.0, 0.05),
99+
visualization=not args.debug,
100+
),
101+
material=gs.materials.Rigid(
102+
gravity_compensation=1.0,
103+
),
104+
)
105+
106+
sphere1 = scene.add_entity(
107+
gs.morphs.Sphere(pos=(0.7, 0.4, 0.4), radius=0.1),
108+
surface=gs.surfaces.Default(
109+
color=(1.0, 0.0, 0.0, 1.0),
110+
),
111+
)
112+
sphere2 = scene.add_entity(
113+
gs.morphs.Sphere(pos=(-0.5, -0.3, 0.5), radius=0.1),
114+
surface=gs.surfaces.Default(
115+
color=(0.0, 1.0, 0.0, 1.0),
116+
),
117+
)
118+
sphere3 = scene.add_entity(
119+
gs.morphs.Sphere(pos=(-0.2, 0.7, 0.6), radius=0.1),
120+
surface=gs.surfaces.Default(
121+
color=(0.0, 0.0, 1.0, 1.0),
122+
),
123+
)
124+
125+
steps = int(args.seconds / args.dt)
126+
cam = scene.add_camera(res=(640, 480), pos=(-2, 3, 1.5), lookat=(0.0, 0.0, 0.1), fov=30, GUI=args.vis)
127+
grid_sensor = RigidContactForceGridSensor(block, grid_size=(4, 4, 2))
128+
129+
scene.build(n_envs=args.n_envs)
130+
131+
data_recorder = SensorDataRecorder()
132+
data_recorder.add_sensor(cam, VideoFileWriter(filename="grid_test.mp4"))
133+
data_recorder.add_sensor(grid_sensor, NPZFileWriter(filename="grid_test.npz"))
134+
data_recorder.start_recording()
135+
136+
try:
137+
for _ in tqdm(range(steps), total=steps):
138+
scene.step()
139+
140+
if args.debug:
141+
scene.clear_debug_objects()
142+
visualize_grid_sensor(scene, grid_sensor)
143+
144+
data_recorder.step()
145+
146+
except KeyboardInterrupt:
147+
gs.logger.info("Simulation interrupted, exiting.")
148+
finally:
149+
gs.logger.info("Simulation finished.")
150+
151+
data_recorder.stop_recording()
152+
153+
154+
if __name__ == "__main__":
155+
main()

0 commit comments

Comments
 (0)