@@ -174,9 +174,6 @@ def f(leaf):
174174
175175def _wp_to_np_type (wp_field : Any , name : str = '' ) -> Any :
176176 """Converts a warp type to an MJX compatible numpy type."""
177- if hasattr (wp_field , '_is_batched' ):
178- wp_field .strides = wp_field .strides [1 :]
179- wp_field .shape = wp_field .shape [1 :]
180177 # warp scalars
181178 wp_dtype = type (wp_field )
182179 if wp_dtype in wp ._src .types .warp_type_to_np_dtype :
@@ -202,7 +199,13 @@ def _wp_to_np_type(wp_field: Any, name: str = '') -> Any:
202199 wp_field [0 ], mjwp_types .TileSet
203200 ):
204201 return tuple (
205- mjxw .types .TileSet (wp_field [i ].adr .numpy (), wp_field [i ].size )
202+ mjxw .types .TileSet (
203+ wp_field [i ].adr .numpy (),
204+ wp_field [i ].size ,
205+ wp_field [i ].elemid .numpy ()
206+ if wp_field [i ].elemid is not None
207+ else np .zeros (0 , dtype = np .int32 ),
208+ )
206209 for i in range (len (wp_field ))
207210 )
208211 if isinstance (wp_field , mjwp_types .BlockDim ):
@@ -272,11 +275,15 @@ def _put_option(
272275
273276
274277 if impl == types .Impl .WARP :
275- if not mjxw .mjwp_io .ENABLE_ISLANDS :
276- fields ['disableflags' ] = types .DisableBit (
277- fields ['disableflags' ] | mjwp_types .DisableBit .ISLAND
278- )
279- impl_fields = {k : _wp_to_np_type (v ) for k , v in impl_fields .items ()}
278+ impl_fields = {
279+ k : (
280+ v_np .reshape (v_np .shape [1 :])
281+ if isinstance (v_np := _wp_to_np_type (v , k ), np .ndarray )
282+ and mjxw .types ._BATCH_DIM ['Option' ].get (k , False ) # pylint: disable=protected-access
283+ else v_np
284+ )
285+ for k , v in impl_fields .items ()
286+ }
280287 return types .Option (** fields , _impl = mjxw .types .OptionWarp (** impl_fields ))
281288
282289 raise NotImplementedError (f'Unsupported implementation: { impl } ' )
@@ -460,6 +467,8 @@ def _put_model_warp(
460467 if not hasattr (mw , k ) or k in ('stat' , 'opt' ):
461468 continue
462469 field = _wp_to_np_type (getattr (mw , k ), k )
470+ if mjxw .types ._BATCH_DIM ['Model' ].get (k , False ): # pylint: disable=protected-access
471+ field = field .reshape (field .shape [1 :])
463472 if k == 'geom_dataid' and field .ndim > 1 :
464473 # Batched geom_dataid is not supported in MJX.
465474 field = field [0 ]
@@ -468,6 +477,8 @@ def _put_model_warp(
468477 impl_fields = {}
469478 for k in mjxw .types .ModelWarp .__annotations__ .keys ():
470479 field = _wp_to_np_type (getattr (mw , k ), k )
480+ if mjxw .types ._BATCH_DIM ['Model' ].get (k , False ): # pylint: disable=protected-access
481+ field = field .reshape (field .shape [1 :])
471482 impl_fields [k ] = field
472483
473484 model = types .Model (
@@ -1298,18 +1309,19 @@ def _get_data_into_warp(
12981309 'ten_J' ,
12991310 'flexedge_J' ,
13001311 'M' ,
1312+ 'map_efc2iefc' , 'map_iefc2efc'
13011313 ):
13021314 continue
13031315 if field .name .startswith ('efc_' ):
13041316 continue
13051317
1318+ # Skip island fields; host MjData arena memory cannot be reallocated from Python if not stepped.
1319+ if field .name .startswith ('island_' ):
1320+ continue
1321+
13061322 if isinstance (value , np .ndarray ) and value .shape :
13071323 result_field = getattr (result_i , field .name )
13081324 if result_field .shape != value .shape :
1309- # When ENABLE_ISLANDS is False, mujoco_warp allocates island fields with width 0,
1310- # while the host MjData sizes to nv/ntree. Skip to prevent mismatch.
1311- if value .size == 0 and not mjxw .mjwp_io .ENABLE_ISLANDS :
1312- continue
13131325 raise ValueError (
13141326 f'Input field { field .name } has shape { value .shape } , but output'
13151327 f' has shape { result_field .shape } '
0 commit comments