Skip to content

Commit 6234c25

Browse files
Fix ContactSensor flat-buffer indexing to match ovphysx pattern-major layout
ovphysx ContactBinding returns sensors in pattern-major order: the flat index for (env, sensor) is sensor*num_envs + env, NOT the PhysX env-major env*num_sensors + sensor that update_net_forces_kernel inherited from the PhysX port. Symptom on AnymalD locomotion: body indices were scrambled, so foot contacts were attributed to the wrong body (often the base), tripping Episode_Termination/base_contact and resetting episodes after ~4 steps. Verified by inspecting cb.sensor_paths for a 3-env, 2-body scene: ['/World/envs/env_0/A', '/World/envs/env_1/A', '/World/envs/env_2/A', '/World/envs/env_0/B', '/World/envs/env_1/B', '/World/envs/env_2/B'] i.e. each per-body sensor pattern is fully expanded across envs before the next pattern starts. Pass num_envs through update_net_forces_kernel and switch its src_idx to the pattern-major formula.
1 parent 25e8f3c commit 6234c25

2 files changed

Lines changed: 12 additions & 3 deletions

File tree

source/isaaclab_ovphysx/isaaclab_ovphysx/sensors/contact_sensor/contact_sensor.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ def _update_buffers_impl(self, env_mask: wp.array | None = None) -> None:
336336
net_forces_flat,
337337
force_matrix_flat,
338338
env_mask,
339+
self._num_envs,
339340
self._num_sensors,
340341
self._num_filter_shapes,
341342
self._history_length,

source/isaaclab_ovphysx/isaaclab_ovphysx/sensors/contact_sensor/kernels.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ def update_net_forces_kernel(
192192
net_forces_flat: wp.array(dtype=wp.vec3f),
193193
net_forces_matrix_flat: wp.array2d(dtype=wp.vec3f),
194194
mask: wp.array(dtype=wp.bool),
195+
num_envs: int,
195196
num_sensors: int,
196197
num_filter_shapes: int,
197198
history_length: int,
@@ -212,10 +213,17 @@ def update_net_forces_kernel(
212213
213214
Launch with dim=(num_envs, num_sensors).
214215
216+
The OVPhysX :class:`ContactBinding` returns sensors in **pattern-major**
217+
order — the flat buffer index for ``(env, sensor)`` is
218+
``sensor * num_envs + env``, not the PhysX env-major
219+
``env * num_sensors + sensor``. We pass ``num_envs`` so the kernel can
220+
compute the right index.
221+
215222
Args:
216-
net_forces_flat: Flat net forces. Shape is (num_envs*num_sensors,).
217-
net_forces_matrix_flat: Flat force matrix. Shape is (num_envs*num_sensors, num_filter_shapes).
223+
net_forces_flat: Flat net forces. Shape is (num_sensors*num_envs,) in pattern-major order.
224+
net_forces_matrix_flat: Flat force matrix. Shape is (num_sensors*num_envs, num_filter_shapes).
218225
mask: Mask array. Shape is (num_envs,).
226+
num_envs: Number of environments.
219227
num_sensors: Number of sensors per environment.
220228
num_filter_shapes: Number of filter shapes.
221229
history_length: Length of history.
@@ -238,7 +246,7 @@ def update_net_forces_kernel(
238246
if not mask[env]:
239247
return
240248

241-
src_idx = env * num_sensors + sensor
249+
src_idx = sensor * num_envs + env
242250

243251
# Update net forces
244252
net_forces_w[env, sensor] = net_forces_flat[src_idx]

0 commit comments

Comments
 (0)