Skip to content

Commit 4ade718

Browse files
authored
Merge branch 'main' into feature/get-weld
2 parents ab2abfb + 40eac85 commit 4ade718

21 files changed

+3041
-1678
lines changed

genesis/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@ def init(
118118
np_int = np.int32
119119
tc_int = torch.int32
120120

121+
# Bool
122+
# Note that `ti.u1` is broken on Apple Metal and output garbage.
123+
global ti_bool
124+
global np_bool
125+
global tc_bool
126+
ti_bool = ti.u1 if backend != gs_backend.metal else ti.i32
127+
np_bool = np.bool_
128+
tc_bool = torch.bool
129+
121130
# let's use GLSL convention: https://learnwebgl.brown37.net/12_shader_language/glsl_data_types.html
122131
global ti_vec2
123132
ti_vec2 = ti.types.vector(2, ti_float)

genesis/engine/bvh.py

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def __init__(self, aabb: AABB, max_n_query_result_per_aabb: int = 8):
125125
self.aabb_min = ti.field(gs.ti_vec3, shape=(self.n_batches))
126126
self.aabb_max = ti.field(gs.ti_vec3, shape=(self.n_batches))
127127
self.scale = ti.field(gs.ti_vec3, shape=(self.n_batches))
128-
self.morton_codes = ti.field(ti.u64, shape=(self.n_batches, self.n_aabbs))
128+
self.morton_codes = ti.field(ti.types.vector(2, ti.u32), shape=(self.n_batches, self.n_aabbs))
129129

130130
# Histogram for radix sort
131131
self.hist = ti.field(ti.u32, shape=(self.n_batches, 256))
@@ -134,7 +134,7 @@ def __init__(self, aabb: AABB, max_n_query_result_per_aabb: int = 8):
134134
# Offset for radix sort
135135
self.offset = ti.field(ti.u32, shape=(self.n_batches, self.n_aabbs))
136136
# Temporary storage for radix sort
137-
self.tmp_morton_codes = ti.field(ti.u64, shape=(self.n_batches, self.n_aabbs))
137+
self.tmp_morton_codes = ti.field(ti.types.vector(2, ti.u32), shape=(self.n_batches, self.n_aabbs))
138138

139139
@ti.dataclass
140140
class Node:
@@ -158,8 +158,8 @@ class Node:
158158
# Nodes of the BVH, first n_aabbs - 1 are internal nodes, last n_aabbs are leaf nodes
159159
self.nodes = self.Node.field(shape=(self.n_batches, self.n_aabbs * 2 - 1))
160160
# Whether an internal node has been visited during traversal
161-
self.internal_node_active = ti.field(ti.u1, shape=(self.n_batches, self.n_aabbs - 1))
162-
self.internal_node_ready = ti.field(ti.u1, shape=(self.n_batches, self.n_aabbs - 1))
161+
self.internal_node_active = ti.field(gs.ti_bool, shape=(self.n_batches, self.n_aabbs - 1))
162+
self.internal_node_ready = ti.field(gs.ti_bool, shape=(self.n_batches, self.n_aabbs - 1))
163163

164164
# Query results, vec3 of batch id, self id, query id
165165
self.query_result = ti.field(gs.ti_ivec3, shape=(self.max_n_query_results))
@@ -213,7 +213,7 @@ def compute_morton_codes(self):
213213
morton_code_y = self.expand_bits(morton_code_y)
214214
morton_code_z = self.expand_bits(morton_code_z)
215215
morton_code = (morton_code_x << 2) | (morton_code_y << 1) | (morton_code_z)
216-
self.morton_codes[i_b, i_a] = (ti.u64(morton_code) << 32) | ti.u64(i_a)
216+
self.morton_codes[i_b, i_a] = ti.Vector([morton_code, i_a], dt=ti.u32)
217217

218218
@ti.func
219219
def expand_bits(self, v):
@@ -243,7 +243,7 @@ def _kernel_radix_sort_morton_codes_one_round(self, i: int):
243243
# This is now sequential
244244
# TODO Parallelize, need to use groups to handle data to remain stable, could be not worth it
245245
for i_a in range(self.n_aabbs):
246-
code = (self.morton_codes[i_b, i_a] >> (i * 8)) & 0xFF
246+
code = (self.morton_codes[i_b, i_a][1 - (i // 4)] >> ((i % 4) * 8)) & 0xFF
247247
self.offset[i_b, i_a] = ti.atomic_add(self.hist[i_b, ti.i32(code)], 1)
248248

249249
# Compute prefix sum
@@ -254,7 +254,7 @@ def _kernel_radix_sort_morton_codes_one_round(self, i: int):
254254

255255
# Reorder morton codes
256256
for i_b, i_a in ti.ndrange(self.n_batches, self.n_aabbs):
257-
code = (self.morton_codes[i_b, i_a] >> (i * 8)) & 0xFF
257+
code = (self.morton_codes[i_b, i_a][1 - (i // 4)] >> ((i % 4) * 8)) & 0xFF
258258
idx = ti.i32(self.offset[i_b, i_a] + self.prefix_sum[i_b, ti.i32(code)])
259259
self.tmp_morton_codes[i_b, idx] = self.morton_codes[i_b, i_a]
260260

@@ -318,10 +318,13 @@ def delta(self, i, j, i_b):
318318
result = -1
319319
if j >= 0 and j < self.n_aabbs:
320320
result = 64
321-
x = self.morton_codes[i_b, ti.i32(i)] ^ self.morton_codes[i_b, ti.i32(j)]
322-
for b in range(64):
323-
if x & (ti.u64(1) << (63 - b)):
324-
result = b
321+
for i_bit in range(2):
322+
x = self.morton_codes[i_b, ti.i32(i)][i_bit] ^ self.morton_codes[i_b, ti.i32(j)][i_bit]
323+
for b in range(32):
324+
if x & (1 << (31 - b)):
325+
result = b + 32 * i_bit
326+
break
327+
if result != 64:
325328
break
326329
return result
327330

@@ -342,15 +345,15 @@ def _kernel_compute_bounds_init(self):
342345
self.internal_node_ready.fill(False)
343346

344347
for i_b, i in ti.ndrange(self.n_batches, self.n_aabbs):
345-
idx = ti.i32(self.morton_codes[i_b, i])
348+
idx = ti.i32(self.morton_codes[i_b, i][1])
346349
self.nodes[i_b, i + self.n_aabbs - 1].bound.min = self.aabbs[i_b, idx].min
347350
self.nodes[i_b, i + self.n_aabbs - 1].bound.max = self.aabbs[i_b, idx].max
348351
parent_idx = self.nodes[i_b, i + self.n_aabbs - 1].parent
349352
if parent_idx != -1:
350353
self.internal_node_active[i_b, parent_idx] = True
351354

352355
@ti.kernel
353-
def _kernel_compute_bounds_one_layer(self) -> ti.u1:
356+
def _kernel_compute_bounds_one_layer(self) -> ti.i32:
354357
for i_b, i in ti.ndrange(self.n_batches, self.n_aabbs - 1):
355358
if self.internal_node_active[i_b, i]:
356359
left_bound = self.nodes[i_b, self.nodes[i_b, i].left].bound
@@ -395,10 +398,8 @@ def query(self, aabbs: ti.template()):
395398
if node.left == -1 and node.right == -1:
396399
idx = ti.atomic_add(self.query_result_count[None], 1)
397400
if idx < self.max_n_query_results:
398-
code = self.morton_codes[i_b, node_idx - (self.n_aabbs - 1)]
399-
self.query_result[idx] = gs.ti_ivec3(
400-
i_b, ti.i32(code & ti.u64(0xFFFFFFFF)), i_q
401-
) # Store the AABB index
401+
code = self.morton_codes[i_b, node_idx - (self.n_aabbs - 1)][1]
402+
self.query_result[idx] = gs.ti_ivec3(i_b, ti.i32(code), i_q) # Store the AABB index
402403
else:
403404
# Push children onto the stack
404405
if node.right != -1:

genesis/engine/coupler.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ def init_fem_fields(self):
694694
self.fem_pressure.from_numpy(fem_pressure_np)
695695
self.fem_pressure_gradient = ti.field(gs.ti_vec3, shape=(fem_solver._B, fem_solver.n_elements))
696696
self.fem_floor_contact_pair_type = ti.types.struct(
697-
active=ti.u1, # whether the contact pair is active
697+
active=gs.ti_bool, # whether the contact pair is active
698698
batch_idx=gs.ti_int, # batch index
699699
geom_idx=gs.ti_int, # index of the FEM element
700700
intersection_code=gs.ti_int, # intersection code for the element
@@ -747,7 +747,7 @@ def init_fem_fields(self):
747747

748748
def init_sap_fields(self):
749749
self.batch_active = ti.field(
750-
dtype=ti.u1,
750+
dtype=gs.ti_bool,
751751
shape=self.sim._B,
752752
needs_grad=False,
753753
)
@@ -757,7 +757,7 @@ def init_sap_fields(self):
757757

758758
def init_pcg_fields(self):
759759
self.batch_pcg_active = ti.field(
760-
dtype=ti.u1,
760+
dtype=gs.ti_bool,
761761
shape=self.sim._B,
762762
needs_grad=False,
763763
)
@@ -796,7 +796,7 @@ def init_pcg_fields(self):
796796

797797
def init_linesearch_fields(self):
798798
self.batch_linesearch_active = ti.field(
799-
dtype=ti.u1,
799+
dtype=gs.ti_bool,
800800
shape=self.sim._B,
801801
needs_grad=False,
802802
)

genesis/engine/entities/pbd_entity.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def _kernel_add_particles_edges_to_solver(
9595
edges: ti.types.ndarray(),
9696
edges_len_rest: ti.types.ndarray(),
9797
mat_type: ti.i32,
98-
active: ti.u1,
98+
active: ti.i32,
9999
):
100100
for i_p_ in range(self.n_particles):
101101
i_p = i_p_ + self._particle_start
@@ -587,7 +587,7 @@ def _kernel_add_particles_to_solver(
587587
particles: ti.types.ndarray(),
588588
rho: ti.float32,
589589
mat_type: ti.i32,
590-
active: ti.u1,
590+
active: ti.i32,
591591
):
592592
for i_p_ in range(self._n_particles):
593593
i_p = i_p_ + self._particle_start

genesis/engine/entities/rigid_entity/rigid_entity.py

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,9 @@ def _load_scene(self, morph, surface):
407407
j_info["dofs_stiffness"] = np.zeros(6)
408408
j_info["dofs_invweight"] = np.zeros(6)
409409
j_info["dofs_damping"] = np.zeros(6)
410+
if isinstance(morph, gs.morphs.Drone):
411+
mass_tot = sum(l_info["inertial_mass"] for l_info in l_infos)
412+
j_info["dofs_damping"][3:] = mass_tot * morph.default_base_ang_damping_scale
410413
j_info["dofs_armature"] = np.zeros(6)
411414
j_info["dofs_kp"] = np.zeros((6,), dtype=gs.np_float)
412415
j_info["dofs_kv"] = np.zeros((6,), dtype=gs.np_float)
@@ -1113,13 +1116,13 @@ def inverse_kinematics_multilink(
11131116
gs.raise_exception("Target link not provided.")
11141117

11151118
if len(poss) == 0:
1116-
poss = [None] * n_links
1119+
poss = [None for _ in range(n_links)]
11171120
pos_mask = [False, False, False]
11181121
elif len(poss) != n_links:
11191122
gs.raise_exception("Accepting only `poss` with length equal to `links` or empty list.")
11201123

11211124
if len(quats) == 0:
1122-
quats = [None] * n_links
1125+
quats = [None for _ in range(n_links)]
11231126
rot_mask = [False, False, False]
11241127
elif len(quats) != n_links:
11251128
gs.raise_exception("Accepting only `quats` with length equal to `links` or empty list.")
@@ -1300,8 +1303,19 @@ def _kernel_inverse_kinematics(
13001303
for i_sample in range(max_samples):
13011304
for _ in range(max_solver_iters):
13021305
# run FK to update link states using current q
1303-
self._solver._func_forward_kinematics_entity(self._idx_in_solver, i_b)
1304-
1306+
self._solver._func_forward_kinematics_entity(
1307+
self._idx_in_solver,
1308+
i_b,
1309+
self._solver.links_state,
1310+
self._solver.links_info,
1311+
self._solver.joints_state,
1312+
self._solver.joints_info,
1313+
self._solver.dofs_state,
1314+
self._solver.dofs_info,
1315+
self._solver.entities_info,
1316+
self._solver._rigid_global_info,
1317+
self._solver._static_rigid_sim_config,
1318+
)
13051319
# compute error
13061320
solved = True
13071321
for i_ee in range(n_links):
@@ -1386,7 +1400,19 @@ def _kernel_inverse_kinematics(
13861400

13871401
if not solved:
13881402
# re-compute final error if exited not due to solved
1389-
self._solver._func_forward_kinematics_entity(self._idx_in_solver, i_b)
1403+
self._solver._func_forward_kinematics_entity(
1404+
self._idx_in_solver,
1405+
i_b,
1406+
self._solver.links_state,
1407+
self._solver.links_info,
1408+
self._solver.joints_state,
1409+
self._solver.joints_info,
1410+
self._solver.dofs_state,
1411+
self._solver.dofs_info,
1412+
self._solver.entities_info,
1413+
self._solver._rigid_global_info,
1414+
self._solver._static_rigid_sim_config,
1415+
)
13901416
solved = True
13911417
for i_ee in range(n_links):
13921418
i_l_ee = links_idx[i_ee]
@@ -1480,7 +1506,19 @@ def _kernel_inverse_kinematics(
14801506
# restore original qpos and link state
14811507
for i_q in range(self.n_qs):
14821508
self._solver.qpos[i_q + self._q_start, i_b] = self._IK_qpos_orig[i_q, i_b]
1483-
self._solver._func_forward_kinematics_entity(self._idx_in_solver, i_b)
1509+
self._solver._func_forward_kinematics_entity(
1510+
self._idx_in_solver,
1511+
i_b,
1512+
self._solver.links_state,
1513+
self._solver.links_info,
1514+
self._solver.joints_state,
1515+
self._solver.joints_info,
1516+
self._solver.dofs_state,
1517+
self._solver.dofs_info,
1518+
self._solver.entities_info,
1519+
self._solver._rigid_global_info,
1520+
self._solver._static_rigid_sim_config,
1521+
)
14841522

14851523
@gs.assert_built
14861524
def forward_kinematics(self, qpos, qs_idx_local=None, links_idx_local=None, envs_idx=None):
@@ -1549,7 +1587,19 @@ def _kernel_forward_kinematics(
15491587
# set new qpos
15501588
self._solver.qpos[qs_idx[i_q_], envs_idx[i_b_]] = qpos[i_b_, i_q_]
15511589
# run FK
1552-
self._solver._func_forward_kinematics_entity(self._idx_in_solver, envs_idx[i_b_])
1590+
self._solver._func_forward_kinematics_entity(
1591+
self._idx_in_solver,
1592+
envs_idx[i_b_],
1593+
self._solver.links_state,
1594+
self._solver.links_info,
1595+
self._solver.joints_state,
1596+
self._solver.joints_info,
1597+
self._solver.dofs_state,
1598+
self._solver.dofs_info,
1599+
self._solver.entities_info,
1600+
self._solver._rigid_global_info,
1601+
self._solver._static_rigid_sim_config,
1602+
)
15531603

15541604
ti.loop_config(serialize=self._solver._para_level < gs.PARA_LEVEL.PARTIAL)
15551605
for i_l_, i_b_ in ti.ndrange(links_idx.shape[0], envs_idx.shape[0]):
@@ -1563,7 +1613,19 @@ def _kernel_forward_kinematics(
15631613
# restore original qpos
15641614
self._solver.qpos[qs_idx[i_q_], envs_idx[i_b_]] = self._IK_qpos_orig[qs_idx[i_q_], envs_idx[i_b_]]
15651615
# run FK
1566-
self._solver._func_forward_kinematics_entity(self._idx_in_solver, envs_idx[i_b_])
1616+
self._solver._func_forward_kinematics_entity(
1617+
self._idx_in_solver,
1618+
envs_idx[i_b_],
1619+
self._solver.links_state,
1620+
self._solver.links_info,
1621+
self._solver.joints_state,
1622+
self._solver.joints_info,
1623+
self._solver.dofs_state,
1624+
self._solver.dofs_info,
1625+
self._solver.entities_info,
1626+
self._solver._rigid_global_info,
1627+
self._solver._static_rigid_sim_config,
1628+
)
15671629

15681630
# ------------------------------------------------------------------------------------
15691631
# --------------------------------- motion planing -----------------------------------

genesis/engine/entities/rigid_entity/rigid_joint.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,6 @@ def __init__(
6767
self._dofs_kv = dofs_kv
6868
self._dofs_force_range = dofs_force_range
6969

70-
# NOTE: temp hack to use 0 damping/armature for drone
71-
if isinstance(self._entity, gs.engine.entities.DroneEntity) and self._type == gs.JOINT_TYPE.FREE:
72-
import numpy as np
73-
74-
self._dofs_damping = np.zeros_like(self._dofs_damping)
75-
self._dofs_armature = np.zeros_like(self._dofs_armature)
76-
7770
# ------------------------------------------------------------------------------------
7871
# -------------------------------- real-time state -----------------------------------
7972
# ------------------------------------------------------------------------------------

genesis/engine/force_fields.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class ForceField(RBC):
1616
"""
1717

1818
def __init__(self):
19-
self._active = ti.field(ti.u1, shape=())
19+
self._active = ti.field(gs.ti_bool, shape=())
2020
self._active[None] = False
2121

2222
def activate(self):

genesis/engine/solvers/avatar_solver.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,30 @@ def _kernel_step(self):
5858
@ti.kernel
5959
def _kernel_forward_kinematics_links_geoms(self, envs_idx: ti.types.ndarray()):
6060
for i_b in envs_idx:
61-
self._func_forward_kinematics(i_b)
62-
self._func_update_geoms(i_b)
61+
self._func_forward_kinematics(
62+
i_b,
63+
self.links_state,
64+
self.links_info,
65+
self.joints_state,
66+
self.joints_info,
67+
self.dofs_state,
68+
self.dofs_info,
69+
self.entities_info,
70+
self._rigid_global_info,
71+
self._static_rigid_sim_config,
72+
)
73+
self._func_update_geoms(
74+
i_b,
75+
self.links_state,
76+
self.links_info,
77+
self.joints_state,
78+
self.joints_info,
79+
self.dofs_state,
80+
self.dofs_info,
81+
self.entities_info,
82+
self._rigid_global_info,
83+
self._static_rigid_sim_config,
84+
)
6385

6486
@ti.func
6587
def _func_detect_collision(self):

0 commit comments

Comments
 (0)