Import google-deepmind/mujoco_warp from GitHub.
PiperOrigin-RevId: 885715192 Change-Id: I13fcb8312c1515bb1bd2d6cdfd0d256e37cb74de
This commit is contained in:
committed by
Copybara-Service
parent
eec6e43a73
commit
57bdf89d07
@@ -205,6 +205,9 @@ def _wp_to_np_type(wp_field: Any, name: str = '') -> Any:
|
||||
)
|
||||
if isinstance(wp_field, mjwp_types.BlockDim):
|
||||
return mjxw.types.BlockDim(**wp_field.__dict__)
|
||||
if isinstance(wp_field, mjwp_types.Callback):
|
||||
return wp_field
|
||||
|
||||
if isinstance(wp_field, tuple) and is_static(wp_field[0]):
|
||||
return wp_field
|
||||
|
||||
|
||||
@@ -848,9 +848,9 @@ class Model(PyTreeNode):
|
||||
actuator_forcerange: jax.Array
|
||||
actuator_actrange: jax.Array
|
||||
actuator_gear: jax.Array
|
||||
actuator_cranklength: np.ndarray
|
||||
actuator_cranklength: jax.Array
|
||||
actuator_acc0: jax.Array
|
||||
actuator_lengthrange: np.ndarray
|
||||
actuator_lengthrange: jax.Array
|
||||
sensor_type: np.ndarray
|
||||
sensor_datatype: np.ndarray
|
||||
sensor_needstage: np.ndarray
|
||||
|
||||
@@ -56,6 +56,8 @@ from mujoco.mjx.third_party.mujoco_warp._src.io import reset_data as reset_data
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.io import set_const as set_const
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.io import set_const_0 as set_const_0
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.io import set_const_fixed as set_const_fixed
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.io import set_length_range as set_length_range
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.island import island as island
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.passive import passive as passive
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.ray import ray as ray
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.ray import rays as rays
|
||||
|
||||
@@ -57,12 +57,12 @@ def ctrl_noise(
|
||||
worldid, actid = wp.tid()
|
||||
|
||||
# convert rate and scale to discrete time (Ornstein-Uhlenbeck)
|
||||
rate = wp.exp(-opt_timestep[0] / ctrlnoiserate)
|
||||
rate = wp.exp(-opt_timestep[worldid % opt_timestep.shape[0]] / ctrlnoiserate)
|
||||
scale = ctrlnoisestd * wp.sqrt(1.0 - rate * rate)
|
||||
|
||||
midpoint = 0.0
|
||||
halfrange = 1.0
|
||||
ctrlrange = actuator_ctrlrange[0, actid]
|
||||
ctrlrange = actuator_ctrlrange[worldid % actuator_ctrlrange.shape[0], actid]
|
||||
is_limited = actuator_ctrllimited[actid]
|
||||
if is_limited:
|
||||
midpoint = 0.5 * (ctrlrange[1] + ctrlrange[0])
|
||||
|
||||
+2
-1
@@ -215,7 +215,8 @@ def _compute_bvh_bounds(
|
||||
lower_bound, upper_bound = _compute_box_bounds(pos, rot, size)
|
||||
elif type == GeomType.HFIELD:
|
||||
size = hfield_bounds_size[geom_dataid[geom_id]]
|
||||
lower_bound, upper_bound = _compute_box_bounds(pos, rot, size)
|
||||
hfield_center = pos + rot[:, 2] * size[2]
|
||||
lower_bound, upper_bound = _compute_box_bounds(hfield_center, rot, size)
|
||||
|
||||
lower_out[world_id * bvh_ngeom + geom_local_id] = lower_bound
|
||||
upper_out[world_id * bvh_ngeom + geom_local_id] = upper_bound
|
||||
|
||||
+20
-14
@@ -15,32 +15,34 @@
|
||||
|
||||
from typing import Tuple
|
||||
|
||||
import warp as wp
|
||||
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import CollisionContext
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import contact_params
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import Geom
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import geom_collision_pair
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import write_contact
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_gjk import ccd
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_gjk import multicontact
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_gjk import support
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import Geom
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import contact_params
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import Geom
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import geom_collision_pair
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import write_contact
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.io import BLEEDING_EDGE_MUJOCO
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.math import make_frame
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.math import upper_trid_index
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Data
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import EnableBit
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import GeomType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import mat43
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import mat63
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAX_EPAFACES
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAX_EPAHORIZON
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAXCONPAIR
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAXVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import CollisionContext
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Data
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import EnableBit
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import GeomType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Model
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import mat43
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import mat63
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import vec5
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import cache_kernel
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import event_scope
|
||||
import warp as wp
|
||||
|
||||
# TODO(team): improve compile time to enable backward pass
|
||||
wp.set_module_options({"enable_backward": False})
|
||||
@@ -92,10 +94,7 @@ def _hfield_filter(
|
||||
r2 = geom_rbound[rbound_id, g2]
|
||||
|
||||
# TODO(team): margin?
|
||||
if BLEEDING_EDGE_MUJOCO:
|
||||
margin = geom_margin[margin_id, g1] + geom_margin[margin_id, g2]
|
||||
else:
|
||||
margin = wp.max(geom_margin[margin_id, g1], geom_margin[margin_id, g2])
|
||||
margin = geom_margin[margin_id, g1] + geom_margin[margin_id, g2]
|
||||
|
||||
# box-sphere test: horizontal plane
|
||||
for i in range(2):
|
||||
@@ -789,6 +788,13 @@ def ccd_kernel_builder(
|
||||
if dist >= 0.0 and pairid[1] == -1:
|
||||
return 0
|
||||
|
||||
# CCD operates on margin-inflated shapes (support() inflates each geom by
|
||||
# 0.5 * margin). The returned dist is therefore relative to the inflated
|
||||
# geometry. Correct back to the true surface-to-surface distance so that
|
||||
# the constraint pipeline (pos = dist - includemargin) works consistently
|
||||
# with the primitive narrowphase, which reports un-inflated distances.
|
||||
dist += margin
|
||||
|
||||
witness1[0] = w1
|
||||
witness2[0] = w2
|
||||
|
||||
|
||||
@@ -0,0 +1,372 @@
|
||||
# Copyright 2026 The Newton Developers
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
|
||||
"""Core collision types and utilities shared across collision modules."""
|
||||
|
||||
import dataclasses
|
||||
from typing import Tuple
|
||||
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.math import safe_div
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import ContactType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import GeomType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import mat63
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MINMU
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MINVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import vec5
|
||||
import warp as wp
|
||||
|
||||
wp.set_module_options({"enable_backward": False})
|
||||
|
||||
|
||||
@wp.struct
|
||||
class Geom:
|
||||
"""Geom properties for pairwise collision detection.
|
||||
|
||||
Bundles a geometry's pose, size, surface normal, and mesh topology data into
|
||||
a single struct that can be passed to Warp collision kernels.
|
||||
"""
|
||||
|
||||
pos: wp.vec3
|
||||
rot: wp.mat33
|
||||
normal: wp.vec3
|
||||
size: wp.vec3
|
||||
margin: float
|
||||
hfprism: mat63
|
||||
vertadr: int
|
||||
vertnum: int
|
||||
vert: wp.array(dtype=wp.vec3)
|
||||
graphadr: int
|
||||
graph: wp.array(dtype=int)
|
||||
mesh_polynum: int
|
||||
mesh_polyadr: int
|
||||
mesh_polynormal: wp.array(dtype=wp.vec3)
|
||||
mesh_polyvertadr: wp.array(dtype=int)
|
||||
mesh_polyvertnum: wp.array(dtype=int)
|
||||
mesh_polyvert: wp.array(dtype=int)
|
||||
mesh_polymapadr: wp.array(dtype=int)
|
||||
mesh_polymapnum: wp.array(dtype=int)
|
||||
mesh_polymap: wp.array(dtype=int)
|
||||
index: int
|
||||
|
||||
|
||||
@wp.func
|
||||
def geom_collision_pair(
|
||||
# Model:
|
||||
geom_type: wp.array(dtype=int),
|
||||
geom_dataid: wp.array(dtype=int),
|
||||
geom_size: wp.array2d(dtype=wp.vec3),
|
||||
mesh_vertadr: wp.array(dtype=int),
|
||||
mesh_vertnum: wp.array(dtype=int),
|
||||
mesh_graphadr: wp.array(dtype=int),
|
||||
mesh_vert: wp.array(dtype=wp.vec3),
|
||||
mesh_graph: wp.array(dtype=int),
|
||||
mesh_polynum: wp.array(dtype=int),
|
||||
mesh_polyadr: wp.array(dtype=int),
|
||||
mesh_polynormal: wp.array(dtype=wp.vec3),
|
||||
mesh_polyvertadr: wp.array(dtype=int),
|
||||
mesh_polyvertnum: wp.array(dtype=int),
|
||||
mesh_polyvert: wp.array(dtype=int),
|
||||
mesh_polymapadr: wp.array(dtype=int),
|
||||
mesh_polymapnum: wp.array(dtype=int),
|
||||
mesh_polymap: wp.array(dtype=int),
|
||||
# Data in:
|
||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
||||
# In:
|
||||
geoms: wp.vec2i,
|
||||
worldid: int,
|
||||
) -> Tuple[Geom, Geom]:
|
||||
geom1 = Geom()
|
||||
geom2 = Geom()
|
||||
|
||||
g1 = geoms[0]
|
||||
g2 = geoms[1]
|
||||
geom_type1 = geom_type[g1]
|
||||
geom_type2 = geom_type[g2]
|
||||
|
||||
geom1.pos = geom_xpos_in[worldid, g1]
|
||||
geom1.rot = geom_xmat_in[worldid, g1]
|
||||
geom1.size = geom_size[worldid % geom_size.shape[0], g1]
|
||||
# z-axis of the rotation matrix, used as the surface normal for plane collisions
|
||||
geom1.normal = wp.vec3(geom1.rot[0, 2], geom1.rot[1, 2], geom1.rot[2, 2])
|
||||
|
||||
geom2.pos = geom_xpos_in[worldid, g2]
|
||||
geom2.rot = geom_xmat_in[worldid, g2]
|
||||
geom2.size = geom_size[worldid % geom_size.shape[0], g2]
|
||||
# z-axis of the rotation matrix, used as the surface normal for plane collisions
|
||||
geom2.normal = wp.vec3(geom2.rot[0, 2], geom2.rot[1, 2], geom2.rot[2, 2])
|
||||
|
||||
if geom_type1 == GeomType.MESH:
|
||||
dataid = geom_dataid[g1]
|
||||
geom1.vertadr = wp.where(dataid >= 0, mesh_vertadr[dataid], -1)
|
||||
geom1.vertnum = wp.where(dataid >= 0, mesh_vertnum[dataid], -1)
|
||||
geom1.graphadr = wp.where(dataid >= 0, mesh_graphadr[dataid], -1)
|
||||
geom1.mesh_polynum = wp.where(dataid >= 0, mesh_polynum[dataid], -1)
|
||||
geom1.mesh_polyadr = wp.where(dataid >= 0, mesh_polyadr[dataid], -1)
|
||||
|
||||
geom1.vert = mesh_vert
|
||||
geom1.graph = mesh_graph
|
||||
geom1.mesh_polynormal = mesh_polynormal
|
||||
geom1.mesh_polyvertadr = mesh_polyvertadr
|
||||
geom1.mesh_polyvertnum = mesh_polyvertnum
|
||||
geom1.mesh_polyvert = mesh_polyvert
|
||||
geom1.mesh_polymapadr = mesh_polymapadr
|
||||
geom1.mesh_polymapnum = mesh_polymapnum
|
||||
geom1.mesh_polymap = mesh_polymap
|
||||
|
||||
if geom_type2 == GeomType.MESH:
|
||||
dataid = geom_dataid[g2]
|
||||
geom2.vertadr = wp.where(dataid >= 0, mesh_vertadr[dataid], -1)
|
||||
geom2.vertnum = wp.where(dataid >= 0, mesh_vertnum[dataid], -1)
|
||||
geom2.graphadr = wp.where(dataid >= 0, mesh_graphadr[dataid], -1)
|
||||
geom2.mesh_polynum = wp.where(dataid >= 0, mesh_polynum[dataid], -1)
|
||||
geom2.mesh_polyadr = wp.where(dataid >= 0, mesh_polyadr[dataid], -1)
|
||||
|
||||
geom2.vert = mesh_vert
|
||||
geom2.graph = mesh_graph
|
||||
geom2.mesh_polynormal = mesh_polynormal
|
||||
geom2.mesh_polyvertadr = mesh_polyvertadr
|
||||
geom2.mesh_polyvertnum = mesh_polyvertnum
|
||||
geom2.mesh_polyvert = mesh_polyvert
|
||||
geom2.mesh_polymapadr = mesh_polymapadr
|
||||
geom2.mesh_polymapnum = mesh_polymapnum
|
||||
geom2.mesh_polymap = mesh_polymap
|
||||
|
||||
geom1.index = -1
|
||||
geom1.margin = 0.0
|
||||
|
||||
geom2.index = -1
|
||||
geom2.margin = 0.0
|
||||
|
||||
return geom1, geom2
|
||||
|
||||
|
||||
@wp.func
|
||||
def write_contact(
|
||||
# Data in:
|
||||
naconmax_in: int,
|
||||
# In:
|
||||
id_: int,
|
||||
dist_in: float,
|
||||
pos_in: wp.vec3,
|
||||
frame_in: wp.mat33,
|
||||
margin_in: float,
|
||||
gap_in: float,
|
||||
condim_in: int,
|
||||
friction_in: vec5,
|
||||
solref_in: wp.vec2,
|
||||
solreffriction_in: wp.vec2,
|
||||
solimp_in: vec5,
|
||||
geoms_in: wp.vec2i,
|
||||
pairid_in: wp.vec2i,
|
||||
worldid_in: int,
|
||||
# Data out:
|
||||
contact_dist_out: wp.array(dtype=float),
|
||||
contact_pos_out: wp.array(dtype=wp.vec3),
|
||||
contact_frame_out: wp.array(dtype=wp.mat33),
|
||||
contact_includemargin_out: wp.array(dtype=float),
|
||||
contact_friction_out: wp.array(dtype=vec5),
|
||||
contact_solref_out: wp.array(dtype=wp.vec2),
|
||||
contact_solreffriction_out: wp.array(dtype=wp.vec2),
|
||||
contact_solimp_out: wp.array(dtype=vec5),
|
||||
contact_dim_out: wp.array(dtype=int),
|
||||
contact_geom_out: wp.array(dtype=wp.vec2i),
|
||||
contact_worldid_out: wp.array(dtype=int),
|
||||
contact_type_out: wp.array(dtype=int),
|
||||
contact_geomcollisionid_out: wp.array(dtype=int),
|
||||
nacon_out: wp.array(dtype=int),
|
||||
) -> int:
|
||||
"""Atomically write a detected contact into the contact output arrays.
|
||||
|
||||
Returns 1 if the contact is active (dist < margin), 0 otherwise.
|
||||
"""
|
||||
active = dist_in < margin_in
|
||||
|
||||
# skip contact and no collision sensor
|
||||
if (pairid_in[0] == -2 or not active) and pairid_in[1] == -1:
|
||||
return 0
|
||||
|
||||
contact_type = 0
|
||||
|
||||
if pairid_in[0] >= -1 and active:
|
||||
contact_type |= ContactType.CONSTRAINT
|
||||
|
||||
if pairid_in[1] >= 0:
|
||||
contact_type |= ContactType.SENSOR
|
||||
|
||||
cid = wp.atomic_add(nacon_out, 0, 1)
|
||||
if cid < naconmax_in:
|
||||
contact_dist_out[cid] = dist_in
|
||||
contact_pos_out[cid] = pos_in
|
||||
contact_frame_out[cid] = frame_in
|
||||
contact_geom_out[cid] = geoms_in
|
||||
contact_worldid_out[cid] = worldid_in
|
||||
includemargin = margin_in - gap_in
|
||||
contact_includemargin_out[cid] = includemargin
|
||||
contact_dim_out[cid] = condim_in
|
||||
contact_friction_out[cid] = friction_in
|
||||
contact_solref_out[cid] = solref_in
|
||||
contact_solreffriction_out[cid] = solreffriction_in
|
||||
contact_solimp_out[cid] = solimp_in
|
||||
contact_type_out[cid] = contact_type
|
||||
contact_geomcollisionid_out[cid] = id_
|
||||
return int(active)
|
||||
return 0
|
||||
|
||||
|
||||
@wp.func
|
||||
def contact_params(
|
||||
# Model:
|
||||
geom_condim: wp.array(dtype=int),
|
||||
geom_priority: wp.array(dtype=int),
|
||||
geom_solmix: wp.array2d(dtype=float),
|
||||
geom_solref: wp.array2d(dtype=wp.vec2),
|
||||
geom_solimp: wp.array2d(dtype=vec5),
|
||||
geom_friction: wp.array2d(dtype=wp.vec3),
|
||||
geom_margin: wp.array2d(dtype=float),
|
||||
geom_gap: wp.array2d(dtype=float),
|
||||
pair_dim: wp.array(dtype=int),
|
||||
pair_solref: wp.array2d(dtype=wp.vec2),
|
||||
pair_solreffriction: wp.array2d(dtype=wp.vec2),
|
||||
pair_solimp: wp.array2d(dtype=vec5),
|
||||
pair_margin: wp.array2d(dtype=float),
|
||||
pair_gap: wp.array2d(dtype=float),
|
||||
pair_friction: wp.array2d(dtype=vec5),
|
||||
# In:
|
||||
collision_pair_in: wp.array(dtype=wp.vec2i),
|
||||
collision_pairid_in: wp.array(dtype=wp.vec2i),
|
||||
cid: int,
|
||||
worldid: int,
|
||||
):
|
||||
"""Resolve contact parameters for a collision pair.
|
||||
|
||||
Uses explicit pair overrides when available, otherwise mixes geom-level
|
||||
properties by priority and solmix weights.
|
||||
"""
|
||||
geoms = collision_pair_in[cid]
|
||||
pairid = collision_pairid_in[cid][0]
|
||||
|
||||
# TODO(team): early return if collision sensor but no contact
|
||||
# (ie, pairid[0] < -1 and pairid[1] < 0)
|
||||
|
||||
if pairid > -1:
|
||||
margin = pair_margin[worldid % pair_margin.shape[0], pairid]
|
||||
gap = pair_gap[worldid % pair_gap.shape[0], pairid]
|
||||
condim = pair_dim[pairid]
|
||||
friction = pair_friction[worldid % pair_friction.shape[0], pairid]
|
||||
solref = pair_solref[worldid % pair_solref.shape[0], pairid]
|
||||
solreffriction = pair_solreffriction[
|
||||
worldid % pair_solreffriction.shape[0], pairid
|
||||
]
|
||||
solimp = pair_solimp[worldid % pair_solimp.shape[0], pairid]
|
||||
else:
|
||||
g1 = geoms[0]
|
||||
g2 = geoms[1]
|
||||
solmix_id = worldid % geom_solmix.shape[0]
|
||||
friction_id = worldid % geom_friction.shape[0]
|
||||
solref_id = worldid % geom_solref.shape[0]
|
||||
solimp_id = worldid % geom_solimp.shape[0]
|
||||
margin_id = worldid % geom_margin.shape[0]
|
||||
gap_id = worldid % geom_gap.shape[0]
|
||||
|
||||
solmix1 = geom_solmix[solmix_id, g1]
|
||||
solmix2 = geom_solmix[solmix_id, g2]
|
||||
|
||||
condim1 = geom_condim[g1]
|
||||
condim2 = geom_condim[g2]
|
||||
|
||||
# priority
|
||||
p1 = geom_priority[g1]
|
||||
p2 = geom_priority[g2]
|
||||
|
||||
if p1 > p2:
|
||||
mix = 1.0
|
||||
condim = condim1
|
||||
max_geom_friction = geom_friction[friction_id, g1]
|
||||
elif p2 > p1:
|
||||
mix = 0.0
|
||||
condim = condim2
|
||||
max_geom_friction = geom_friction[friction_id, g2]
|
||||
else:
|
||||
mix = safe_div(solmix1, solmix1 + solmix2)
|
||||
mix = wp.where((solmix1 < MJ_MINVAL) and (solmix2 < MJ_MINVAL), 0.5, mix)
|
||||
mix = wp.where((solmix1 < MJ_MINVAL) and (solmix2 >= MJ_MINVAL), 0.0, mix)
|
||||
mix = wp.where((solmix1 >= MJ_MINVAL) and (solmix2 < MJ_MINVAL), 1.0, mix)
|
||||
condim = wp.max(condim1, condim2)
|
||||
max_geom_friction = wp.max(
|
||||
geom_friction[friction_id, g1], geom_friction[friction_id, g2]
|
||||
)
|
||||
|
||||
friction = vec5(
|
||||
max_geom_friction[0],
|
||||
max_geom_friction[0],
|
||||
max_geom_friction[1],
|
||||
max_geom_friction[2],
|
||||
max_geom_friction[2],
|
||||
)
|
||||
|
||||
if (
|
||||
geom_solref[solref_id, g1][0] > 0.0
|
||||
and geom_solref[solref_id, g2][0] > 0.0
|
||||
):
|
||||
solref = (
|
||||
mix * geom_solref[solref_id, g1]
|
||||
+ (1.0 - mix) * geom_solref[solref_id, g2]
|
||||
)
|
||||
else:
|
||||
solref = wp.min(geom_solref[solref_id, g1], geom_solref[solref_id, g2])
|
||||
|
||||
solreffriction = wp.vec2(0.0, 0.0)
|
||||
solimp = (
|
||||
mix * geom_solimp[solimp_id, g1]
|
||||
+ (1.0 - mix) * geom_solimp[solimp_id, g2]
|
||||
)
|
||||
# geom priority is ignored
|
||||
margin = geom_margin[margin_id, g1] + geom_margin[margin_id, g2]
|
||||
gap = geom_gap[gap_id, g1] + geom_gap[gap_id, g2]
|
||||
|
||||
friction = vec5(
|
||||
wp.max(MJ_MINMU, friction[0]),
|
||||
wp.max(MJ_MINMU, friction[1]),
|
||||
wp.max(MJ_MINMU, friction[2]),
|
||||
wp.max(MJ_MINMU, friction[3]),
|
||||
wp.max(MJ_MINMU, friction[4]),
|
||||
)
|
||||
|
||||
return geoms, margin, gap, condim, friction, solref, solreffriction, solimp
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class CollisionContext:
|
||||
"""Collision driver intermediate arrays.
|
||||
|
||||
Attributes:
|
||||
collision_pair: collision pairs from broadphase (naconmax, 2)
|
||||
collision_pairid: ids from broadphase (naconmax, 2)
|
||||
collision_worldid: collision world ids from broadphase (naconmax,)
|
||||
"""
|
||||
|
||||
collision_pair: wp.array
|
||||
collision_pairid: wp.array
|
||||
collision_worldid: wp.array
|
||||
|
||||
|
||||
def create_collision_context(naconmax: int) -> CollisionContext:
|
||||
"""Create a CollisionContext with allocated arrays."""
|
||||
return CollisionContext(
|
||||
collision_pair=wp.empty(naconmax, dtype=wp.vec2i),
|
||||
collision_pairid=wp.empty(naconmax, dtype=wp.vec2i),
|
||||
collision_worldid=wp.empty(naconmax, dtype=int),
|
||||
)
|
||||
+29
-39
@@ -15,26 +15,25 @@
|
||||
|
||||
from typing import Any
|
||||
|
||||
import warp as wp
|
||||
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_convex import convex_narrowphase
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import CollisionContext
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import create_collision_context
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import primitive_narrowphase
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_sdf import sdf_narrowphase
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.io import BLEEDING_EDGE_MUJOCO
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.math import upper_tri_index
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAXVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import BroadphaseFilter
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import BroadphaseType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import CollisionContext
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import CollisionType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Data
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import DisableBit
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import GeomType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Model
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import mat23
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import mat63
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAXVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Model
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import cache_kernel
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import event_scope
|
||||
import warp as wp
|
||||
|
||||
wp.set_module_options({"enable_backward": False})
|
||||
|
||||
@@ -76,15 +75,6 @@ MJ_COLLISION_TABLE = {
|
||||
}
|
||||
|
||||
|
||||
def create_collision_context(naconmax: int) -> CollisionContext:
|
||||
"""Create a CollisionContext with allocated arrays."""
|
||||
return CollisionContext(
|
||||
collision_pair=wp.empty(naconmax, dtype=wp.vec2i),
|
||||
collision_pairid=wp.empty(naconmax, dtype=wp.vec2i),
|
||||
collision_worldid=wp.empty(naconmax, dtype=int),
|
||||
)
|
||||
|
||||
|
||||
@wp.kernel
|
||||
def _zero_nacon_ncollision(
|
||||
# Data out:
|
||||
@@ -102,27 +92,18 @@ def _plane_filter(
|
||||
if size1 == 0.0:
|
||||
# geom1 is a plane
|
||||
dist = wp.dot(xpos2 - xpos1, wp.vec3(xmat1[0, 2], xmat1[1, 2], xmat1[2, 2]))
|
||||
if BLEEDING_EDGE_MUJOCO:
|
||||
return dist <= size2 + margin1 + margin2
|
||||
else:
|
||||
return dist <= size2 + wp.max(margin1, margin2)
|
||||
return dist <= size2 + margin1 + margin2
|
||||
elif size2 == 0.0:
|
||||
# geom2 is a plane
|
||||
dist = wp.dot(xpos1 - xpos2, wp.vec3(xmat2[0, 2], xmat2[1, 2], xmat2[2, 2]))
|
||||
if BLEEDING_EDGE_MUJOCO:
|
||||
return dist <= size1 + margin1 + margin2
|
||||
else:
|
||||
return dist <= size1 + wp.max(margin1, margin2)
|
||||
return dist <= size1 + margin1 + margin2
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@wp.func
|
||||
def _sphere_filter(size1: float, size2: float, margin1: float, margin2: float, xpos1: wp.vec3, xpos2: wp.vec3) -> bool:
|
||||
if BLEEDING_EDGE_MUJOCO:
|
||||
bound = size1 + size2 + margin1 + margin2
|
||||
else:
|
||||
bound = size1 + size2 + wp.max(margin1, margin2)
|
||||
bound = size1 + size2 + margin1 + margin2
|
||||
dif = xpos2 - xpos1
|
||||
dist_sq = wp.dot(dif, dif)
|
||||
return dist_sq <= bound * bound
|
||||
@@ -151,10 +132,7 @@ def _aabb_filter(
|
||||
center1 = xmat1 @ center1 + xpos1
|
||||
center2 = xmat2 @ center2 + xpos2
|
||||
|
||||
if BLEEDING_EDGE_MUJOCO:
|
||||
margin = margin1 + margin2
|
||||
else:
|
||||
margin = wp.max(margin1, margin2)
|
||||
margin = margin1 + margin2
|
||||
|
||||
max_x1 = -MJ_MAXVAL
|
||||
max_y1 = -MJ_MAXVAL
|
||||
@@ -249,10 +227,7 @@ def _obb_filter(
|
||||
xmat2: wp.mat33,
|
||||
) -> bool:
|
||||
"""Oriented bounding boxes collision (see Gottschalk et al.), see mj_collideOBB."""
|
||||
if BLEEDING_EDGE_MUJOCO:
|
||||
margin = margin1 + margin2
|
||||
else:
|
||||
margin = wp.max(margin1, margin2)
|
||||
margin = margin1 + margin2
|
||||
|
||||
xcenter = mat23()
|
||||
normal = mat63()
|
||||
@@ -315,13 +290,25 @@ def _broadphase_filter(opt_broadphase_filter: int, ngeom_aabb: int, ngeom_rbound
|
||||
# 8: obb
|
||||
|
||||
aabb_id = worldid % ngeom_aabb if wp.static(ngeom_aabb > 1) else 0
|
||||
center1, center2 = geom_aabb[aabb_id, geom1, 0], geom_aabb[aabb_id, geom2, 0]
|
||||
size1, size2 = geom_aabb[aabb_id, geom1, 1], geom_aabb[aabb_id, geom2, 1]
|
||||
center1, center2 = (
|
||||
geom_aabb[aabb_id, geom1, 0],
|
||||
geom_aabb[aabb_id, geom2, 0],
|
||||
) # kernel_analyzer: ignore
|
||||
size1, size2 = (
|
||||
geom_aabb[aabb_id, geom1, 1],
|
||||
geom_aabb[aabb_id, geom2, 1],
|
||||
) # kernel_analyzer: ignore
|
||||
|
||||
rbound_id = worldid % ngeom_rbound if wp.static(ngeom_rbound > 1) else 0
|
||||
rbound1, rbound2 = geom_rbound[rbound_id, geom1], geom_rbound[rbound_id, geom2]
|
||||
rbound1, rbound2 = (
|
||||
geom_rbound[rbound_id, geom1],
|
||||
geom_rbound[rbound_id, geom2],
|
||||
) # kernel_analyzer: ignore
|
||||
margin_id = worldid % ngeom_margin if wp.static(ngeom_margin > 1) else 0
|
||||
margin1, margin2 = geom_margin[margin_id, geom1], geom_margin[margin_id, geom2]
|
||||
margin1, margin2 = (
|
||||
geom_margin[margin_id, geom1],
|
||||
geom_margin[margin_id, geom2],
|
||||
) # kernel_analyzer: ignore
|
||||
xpos1, xpos2 = geom_xpos_in[worldid, geom1], geom_xpos_in[worldid, geom2]
|
||||
xmat1, xmat2 = geom_xmat_in[worldid, geom1], geom_xmat_in[worldid, geom2]
|
||||
|
||||
@@ -804,3 +791,6 @@ def collision(m: Model, d: Data):
|
||||
sap_broadphase(m, d, ctx)
|
||||
|
||||
_narrowphase(m, d, ctx)
|
||||
|
||||
if m.callback.contactfilter:
|
||||
m.callback.contactfilter(m, d)
|
||||
|
||||
+16
-14
@@ -16,12 +16,11 @@
|
||||
import math
|
||||
from typing import Tuple
|
||||
|
||||
import warp as wp
|
||||
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import Geom
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import Geom
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import GeomType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import mat43
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import mat63
|
||||
import warp as wp
|
||||
|
||||
# TODO(team): improve compile time to enable backward pass
|
||||
wp.set_module_options({"enable_backward": False})
|
||||
@@ -581,14 +580,13 @@ def gjk(
|
||||
simplex_index1 = wp.vec4i()
|
||||
simplex_index2 = wp.vec4i()
|
||||
n = int(0)
|
||||
cnt = int(1)
|
||||
coordinates = wp.vec4() # barycentric coordinates
|
||||
epsilon = wp.where(is_discrete, 0.0, 0.5 * tolerance * tolerance)
|
||||
|
||||
# set initial guess
|
||||
x_k = x1_0 - x2_0
|
||||
|
||||
for _ in range(gjk_iterations):
|
||||
for k in range(gjk_iterations):
|
||||
xnorm = wp.dot(x_k, x_k)
|
||||
# TODO(kbayes): determine new constant here
|
||||
if xnorm < 1e-12:
|
||||
@@ -665,10 +663,12 @@ def gjk(
|
||||
if n == 4:
|
||||
break
|
||||
|
||||
cnt += 1
|
||||
|
||||
if cnt == gjk_iterations:
|
||||
wp.printf("Warning: opt.ccd_iterations, currently set to %d, needs to be increased.\n", gjk_iterations)
|
||||
if k == gjk_iterations - 1:
|
||||
wp.printf(
|
||||
"Warning: opt.ccd_iterations, currently set to %d, needs to be"
|
||||
" increased.\n",
|
||||
gjk_iterations,
|
||||
)
|
||||
|
||||
result = GJKResult()
|
||||
|
||||
@@ -1220,14 +1220,13 @@ def _epa(
|
||||
idx = int(-1)
|
||||
pidx = int(-1)
|
||||
epsilon = wp.where(is_discrete, 1e-15, tolerance)
|
||||
cnt = int(1)
|
||||
nvalid = pt.nface # number of potential faces for expanding the polytope
|
||||
|
||||
# the face vertices are encoded in 10-bits that index the vertex array,
|
||||
# so iterations must be cap to limit the number of generated vertices
|
||||
# (one new vertex per iteration)
|
||||
epa_iterations = wp.min(epa_iterations, 1000)
|
||||
for _ in range(epa_iterations):
|
||||
for k in range(epa_iterations):
|
||||
pidx = idx
|
||||
idx = int(-1)
|
||||
lower2 = float(FLOAT_MAX)
|
||||
@@ -1325,10 +1324,13 @@ def _epa(
|
||||
|
||||
# clear horizon
|
||||
pt.nhorizon = 0
|
||||
cnt += 1
|
||||
|
||||
if cnt == epa_iterations:
|
||||
wp.printf("Warning: opt.ccd_iterations, currently set to %d, needs to be increased.\n", gjk_iterations)
|
||||
if k == epa_iterations - 1:
|
||||
wp.printf(
|
||||
"Warning: opt.ccd_iterations, currently set to %d, needs to be"
|
||||
" increased.\n",
|
||||
gjk_iterations,
|
||||
)
|
||||
|
||||
# return from valid face
|
||||
if idx > -1:
|
||||
|
||||
@@ -15,8 +15,11 @@
|
||||
|
||||
from typing import Tuple
|
||||
|
||||
import warp as wp
|
||||
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import CollisionContext
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import contact_params
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import Geom
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import geom_collision_pair
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import write_contact
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive_core import box_box
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive_core import capsule_box
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive_core import capsule_capsule
|
||||
@@ -29,142 +32,21 @@ from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive_core import sph
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive_core import sphere_capsule
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive_core import sphere_cylinder
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive_core import sphere_sphere
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.io import BLEEDING_EDGE_MUJOCO
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.math import make_frame
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.math import safe_div
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.math import upper_trid_index
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAXVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MINMU
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MINVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import CollisionContext
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import ContactType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Data
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import GeomType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Model
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import mat43
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import mat63
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAXVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Model
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import vec5
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import cache_kernel
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import event_scope
|
||||
import warp as wp
|
||||
|
||||
wp.set_module_options({"enable_backward": False})
|
||||
|
||||
|
||||
@wp.struct
|
||||
class Geom:
|
||||
pos: wp.vec3
|
||||
rot: wp.mat33
|
||||
normal: wp.vec3
|
||||
size: wp.vec3
|
||||
margin: float
|
||||
hfprism: mat63
|
||||
vertadr: int
|
||||
vertnum: int
|
||||
vert: wp.array(dtype=wp.vec3)
|
||||
graphadr: int
|
||||
graph: wp.array(dtype=int)
|
||||
mesh_polynum: int
|
||||
mesh_polyadr: int
|
||||
mesh_polynormal: wp.array(dtype=wp.vec3)
|
||||
mesh_polyvertadr: wp.array(dtype=int)
|
||||
mesh_polyvertnum: wp.array(dtype=int)
|
||||
mesh_polyvert: wp.array(dtype=int)
|
||||
mesh_polymapadr: wp.array(dtype=int)
|
||||
mesh_polymapnum: wp.array(dtype=int)
|
||||
mesh_polymap: wp.array(dtype=int)
|
||||
index: int
|
||||
|
||||
|
||||
@wp.func
|
||||
def geom_collision_pair(
|
||||
# Model:
|
||||
geom_type: wp.array(dtype=int),
|
||||
geom_dataid: wp.array(dtype=int),
|
||||
geom_size: wp.array2d(dtype=wp.vec3),
|
||||
mesh_vertadr: wp.array(dtype=int),
|
||||
mesh_vertnum: wp.array(dtype=int),
|
||||
mesh_graphadr: wp.array(dtype=int),
|
||||
mesh_vert: wp.array(dtype=wp.vec3),
|
||||
mesh_graph: wp.array(dtype=int),
|
||||
mesh_polynum: wp.array(dtype=int),
|
||||
mesh_polyadr: wp.array(dtype=int),
|
||||
mesh_polynormal: wp.array(dtype=wp.vec3),
|
||||
mesh_polyvertadr: wp.array(dtype=int),
|
||||
mesh_polyvertnum: wp.array(dtype=int),
|
||||
mesh_polyvert: wp.array(dtype=int),
|
||||
mesh_polymapadr: wp.array(dtype=int),
|
||||
mesh_polymapnum: wp.array(dtype=int),
|
||||
mesh_polymap: wp.array(dtype=int),
|
||||
# Data in:
|
||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
||||
# In:
|
||||
geoms: wp.vec2i,
|
||||
worldid: int,
|
||||
) -> Tuple[Geom, Geom]:
|
||||
geom1 = Geom()
|
||||
geom2 = Geom()
|
||||
|
||||
g1 = geoms[0]
|
||||
g2 = geoms[1]
|
||||
geom_type1 = geom_type[g1]
|
||||
geom_type2 = geom_type[g2]
|
||||
|
||||
geom1.pos = geom_xpos_in[worldid, g1]
|
||||
geom1.rot = geom_xmat_in[worldid, g1]
|
||||
geom1.size = geom_size[worldid % geom_size.shape[0], g1]
|
||||
geom1.normal = wp.vec3(geom1.rot[0, 2], geom1.rot[1, 2], geom1.rot[2, 2]) # plane
|
||||
|
||||
geom2.pos = geom_xpos_in[worldid, g2]
|
||||
geom2.rot = geom_xmat_in[worldid, g2]
|
||||
geom2.size = geom_size[worldid % geom_size.shape[0], g2]
|
||||
geom2.normal = wp.vec3(geom2.rot[0, 2], geom2.rot[1, 2], geom2.rot[2, 2]) # plane
|
||||
|
||||
if geom_type1 == GeomType.MESH:
|
||||
dataid = geom_dataid[g1]
|
||||
geom1.vertadr = wp.where(dataid >= 0, mesh_vertadr[dataid], -1)
|
||||
geom1.vertnum = wp.where(dataid >= 0, mesh_vertnum[dataid], -1)
|
||||
geom1.graphadr = wp.where(dataid >= 0, mesh_graphadr[dataid], -1)
|
||||
geom1.mesh_polynum = wp.where(dataid >= 0, mesh_polynum[dataid], -1)
|
||||
geom1.mesh_polyadr = wp.where(dataid >= 0, mesh_polyadr[dataid], -1)
|
||||
|
||||
geom1.vert = mesh_vert
|
||||
geom1.graph = mesh_graph
|
||||
geom1.mesh_polynormal = mesh_polynormal
|
||||
geom1.mesh_polyvertadr = mesh_polyvertadr
|
||||
geom1.mesh_polyvertnum = mesh_polyvertnum
|
||||
geom1.mesh_polyvert = mesh_polyvert
|
||||
geom1.mesh_polymapadr = mesh_polymapadr
|
||||
geom1.mesh_polymapnum = mesh_polymapnum
|
||||
geom1.mesh_polymap = mesh_polymap
|
||||
|
||||
if geom_type2 == GeomType.MESH:
|
||||
dataid = geom_dataid[g2]
|
||||
geom2.vertadr = wp.where(dataid >= 0, mesh_vertadr[dataid], -1)
|
||||
geom2.vertnum = wp.where(dataid >= 0, mesh_vertnum[dataid], -1)
|
||||
geom2.graphadr = wp.where(dataid >= 0, mesh_graphadr[dataid], -1)
|
||||
geom2.mesh_polynum = wp.where(dataid >= 0, mesh_polynum[dataid], -1)
|
||||
geom2.mesh_polyadr = wp.where(dataid >= 0, mesh_polyadr[dataid], -1)
|
||||
|
||||
geom2.vert = mesh_vert
|
||||
geom2.graph = mesh_graph
|
||||
geom2.mesh_polynormal = mesh_polynormal
|
||||
geom2.mesh_polyvertadr = mesh_polyvertadr
|
||||
geom2.mesh_polyvertnum = mesh_polyvertnum
|
||||
geom2.mesh_polyvert = mesh_polyvert
|
||||
geom2.mesh_polymapadr = mesh_polymapadr
|
||||
geom2.mesh_polymapnum = mesh_polymapnum
|
||||
geom2.mesh_polymap = mesh_polymap
|
||||
|
||||
geom1.index = -1
|
||||
geom1.margin = 0.0
|
||||
|
||||
geom2.index = -1
|
||||
geom2.margin = 0.0
|
||||
|
||||
return geom1, geom2
|
||||
|
||||
|
||||
@wp.func
|
||||
def plane_convex(plane_normal: wp.vec3, plane_pos: wp.vec3, convex: Geom) -> Tuple[wp.vec4, mat43, wp.vec3]:
|
||||
"""Core contact geometry calculation for plane-convex collision.
|
||||
@@ -394,183 +276,6 @@ def plane_convex(plane_normal: wp.vec3, plane_pos: wp.vec3, convex: Geom) -> Tup
|
||||
return contact_dist, contact_pos, plane_normal
|
||||
|
||||
|
||||
@wp.func
|
||||
def write_contact(
|
||||
# Data in:
|
||||
naconmax_in: int,
|
||||
# In:
|
||||
id_: int,
|
||||
dist_in: float,
|
||||
pos_in: wp.vec3,
|
||||
frame_in: wp.mat33,
|
||||
margin_in: float,
|
||||
gap_in: float,
|
||||
condim_in: int,
|
||||
friction_in: vec5,
|
||||
solref_in: wp.vec2,
|
||||
solreffriction_in: wp.vec2,
|
||||
solimp_in: vec5,
|
||||
geoms_in: wp.vec2i,
|
||||
pairid_in: wp.vec2i,
|
||||
worldid_in: int,
|
||||
# Data out:
|
||||
contact_dist_out: wp.array(dtype=float),
|
||||
contact_pos_out: wp.array(dtype=wp.vec3),
|
||||
contact_frame_out: wp.array(dtype=wp.mat33),
|
||||
contact_includemargin_out: wp.array(dtype=float),
|
||||
contact_friction_out: wp.array(dtype=vec5),
|
||||
contact_solref_out: wp.array(dtype=wp.vec2),
|
||||
contact_solreffriction_out: wp.array(dtype=wp.vec2),
|
||||
contact_solimp_out: wp.array(dtype=vec5),
|
||||
contact_dim_out: wp.array(dtype=int),
|
||||
contact_geom_out: wp.array(dtype=wp.vec2i),
|
||||
contact_worldid_out: wp.array(dtype=int),
|
||||
contact_type_out: wp.array(dtype=int),
|
||||
contact_geomcollisionid_out: wp.array(dtype=int),
|
||||
nacon_out: wp.array(dtype=int),
|
||||
) -> int:
|
||||
active = dist_in < margin_in
|
||||
|
||||
# skip contact and no collision sensor
|
||||
if (pairid_in[0] == -2 or not active) and pairid_in[1] == -1:
|
||||
return 0
|
||||
|
||||
contact_type = 0
|
||||
|
||||
if pairid_in[0] >= -1 and active:
|
||||
contact_type |= ContactType.CONSTRAINT
|
||||
|
||||
if pairid_in[1] >= 0:
|
||||
contact_type |= ContactType.SENSOR
|
||||
|
||||
cid = wp.atomic_add(nacon_out, 0, 1)
|
||||
if cid < naconmax_in:
|
||||
contact_dist_out[cid] = dist_in
|
||||
contact_pos_out[cid] = pos_in
|
||||
contact_frame_out[cid] = frame_in
|
||||
contact_geom_out[cid] = geoms_in
|
||||
contact_worldid_out[cid] = worldid_in
|
||||
includemargin = margin_in - gap_in
|
||||
contact_includemargin_out[cid] = includemargin
|
||||
contact_dim_out[cid] = condim_in
|
||||
contact_friction_out[cid] = friction_in
|
||||
contact_solref_out[cid] = solref_in
|
||||
contact_solreffriction_out[cid] = solreffriction_in
|
||||
contact_solimp_out[cid] = solimp_in
|
||||
contact_type_out[cid] = contact_type
|
||||
contact_geomcollisionid_out[cid] = id_
|
||||
return int(active)
|
||||
return 0
|
||||
|
||||
|
||||
@wp.func
|
||||
def contact_params(
|
||||
# Model:
|
||||
geom_condim: wp.array(dtype=int),
|
||||
geom_priority: wp.array(dtype=int),
|
||||
geom_solmix: wp.array2d(dtype=float),
|
||||
geom_solref: wp.array2d(dtype=wp.vec2),
|
||||
geom_solimp: wp.array2d(dtype=vec5),
|
||||
geom_friction: wp.array2d(dtype=wp.vec3),
|
||||
geom_margin: wp.array2d(dtype=float),
|
||||
geom_gap: wp.array2d(dtype=float),
|
||||
pair_dim: wp.array(dtype=int),
|
||||
pair_solref: wp.array2d(dtype=wp.vec2),
|
||||
pair_solreffriction: wp.array2d(dtype=wp.vec2),
|
||||
pair_solimp: wp.array2d(dtype=vec5),
|
||||
pair_margin: wp.array2d(dtype=float),
|
||||
pair_gap: wp.array2d(dtype=float),
|
||||
pair_friction: wp.array2d(dtype=vec5),
|
||||
# In:
|
||||
collision_pair_in: wp.array(dtype=wp.vec2i),
|
||||
collision_pairid_in: wp.array(dtype=wp.vec2i),
|
||||
cid: int,
|
||||
worldid: int,
|
||||
):
|
||||
geoms = collision_pair_in[cid]
|
||||
pairid = collision_pairid_in[cid][0]
|
||||
|
||||
# TODO(team): early return if collision sensor but no contact
|
||||
# (ie, pairid[0] < -1 and pairid[1] < 0)
|
||||
|
||||
if pairid > -1:
|
||||
margin = pair_margin[worldid, pairid]
|
||||
gap = pair_gap[worldid, pairid]
|
||||
condim = pair_dim[pairid]
|
||||
friction = pair_friction[worldid, pairid]
|
||||
solref = pair_solref[worldid, pairid]
|
||||
solreffriction = pair_solreffriction[worldid, pairid]
|
||||
solimp = pair_solimp[worldid, pairid]
|
||||
else:
|
||||
g1 = geoms[0]
|
||||
g2 = geoms[1]
|
||||
solmix_id = worldid % geom_solmix.shape[0]
|
||||
friction_id = worldid % geom_friction.shape[0]
|
||||
solref_id = worldid % geom_solref.shape[0]
|
||||
solimp_id = worldid % geom_solimp.shape[0]
|
||||
margin_id = worldid % geom_margin.shape[0]
|
||||
gap_id = worldid % geom_gap.shape[0]
|
||||
|
||||
solmix1 = geom_solmix[solmix_id, g1]
|
||||
solmix2 = geom_solmix[solmix_id, g2]
|
||||
|
||||
condim1 = geom_condim[g1]
|
||||
condim2 = geom_condim[g2]
|
||||
|
||||
# priority
|
||||
p1 = geom_priority[g1]
|
||||
p2 = geom_priority[g2]
|
||||
|
||||
if p1 > p2:
|
||||
mix = 1.0
|
||||
condim = condim1
|
||||
max_geom_friction = geom_friction[friction_id, g1]
|
||||
elif p2 > p1:
|
||||
mix = 0.0
|
||||
condim = condim2
|
||||
max_geom_friction = geom_friction[friction_id, g2]
|
||||
else:
|
||||
mix = safe_div(solmix1, solmix1 + solmix2)
|
||||
mix = wp.where((solmix1 < MJ_MINVAL) and (solmix2 < MJ_MINVAL), 0.5, mix)
|
||||
mix = wp.where((solmix1 < MJ_MINVAL) and (solmix2 >= MJ_MINVAL), 0.0, mix)
|
||||
mix = wp.where((solmix1 >= MJ_MINVAL) and (solmix2 < MJ_MINVAL), 1.0, mix)
|
||||
condim = wp.max(condim1, condim2)
|
||||
max_geom_friction = wp.max(geom_friction[friction_id, g1], geom_friction[friction_id, g2])
|
||||
|
||||
friction = vec5(
|
||||
max_geom_friction[0],
|
||||
max_geom_friction[0],
|
||||
max_geom_friction[1],
|
||||
max_geom_friction[2],
|
||||
max_geom_friction[2],
|
||||
)
|
||||
|
||||
if geom_solref[solref_id, g1][0] > 0.0 and geom_solref[solref_id, g2][0] > 0.0:
|
||||
solref = mix * geom_solref[solref_id, g1] + (1.0 - mix) * geom_solref[solref_id, g2]
|
||||
else:
|
||||
solref = wp.min(geom_solref[solref_id, g1], geom_solref[solref_id, g2])
|
||||
|
||||
solreffriction = wp.vec2(0.0, 0.0)
|
||||
solimp = mix * geom_solimp[solimp_id, g1] + (1.0 - mix) * geom_solimp[solimp_id, g2]
|
||||
# geom priority is ignored
|
||||
if BLEEDING_EDGE_MUJOCO:
|
||||
margin = geom_margin[margin_id, g1] + geom_margin[margin_id, g2]
|
||||
gap = geom_gap[gap_id, g1] + geom_gap[gap_id, g2]
|
||||
else:
|
||||
margin = wp.max(geom_margin[margin_id, g1], geom_margin[margin_id, g2])
|
||||
gap = wp.max(geom_gap[gap_id, g1], geom_gap[gap_id, g2])
|
||||
|
||||
friction = vec5(
|
||||
wp.max(MJ_MINMU, friction[0]),
|
||||
wp.max(MJ_MINMU, friction[1]),
|
||||
wp.max(MJ_MINMU, friction[2]),
|
||||
wp.max(MJ_MINMU, friction[3]),
|
||||
wp.max(MJ_MINMU, friction[4]),
|
||||
)
|
||||
|
||||
return geoms, margin, gap, condim, friction, solref, solreffriction, solimp
|
||||
|
||||
|
||||
@wp.func
|
||||
def plane_sphere_wrapper(
|
||||
# Data in:
|
||||
|
||||
+217
-174
@@ -15,14 +15,12 @@
|
||||
|
||||
from typing import Tuple
|
||||
|
||||
import warp as wp
|
||||
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import contact_params
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import geom_collision_pair
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import write_contact
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import CollisionContext
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import contact_params
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import geom_collision_pair
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_core import write_contact
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.math import make_frame
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.ray import ray_mesh
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import CollisionContext
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Data
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import GeomType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Model
|
||||
@@ -31,6 +29,7 @@ from mujoco.mjx.third_party.mujoco_warp._src.types import vec8
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import vec8i
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.util_misc import halton
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import event_scope
|
||||
import warp as wp
|
||||
|
||||
wp.set_module_options({"enable_backward": False})
|
||||
|
||||
@@ -56,6 +55,7 @@ class VolumeData:
|
||||
oct_aabb: wp.array2d(dtype=wp.vec3)
|
||||
oct_child: wp.array(dtype=vec8i)
|
||||
oct_coeff: wp.array(dtype=vec8)
|
||||
root: int = 0
|
||||
valid: bool = False
|
||||
|
||||
|
||||
@@ -77,17 +77,18 @@ class MeshData:
|
||||
|
||||
@wp.func
|
||||
def get_sdf_params(
|
||||
# Model:
|
||||
oct_child: wp.array(dtype=vec8i),
|
||||
oct_aabb: wp.array2d(dtype=wp.vec3),
|
||||
oct_coeff: wp.array(dtype=vec8),
|
||||
plugin: wp.array(dtype=int),
|
||||
plugin_attr: wp.array(dtype=wp.vec3f),
|
||||
# In:
|
||||
g_type: int,
|
||||
g_size: wp.vec3,
|
||||
plugin_id: int,
|
||||
mesh_id: int,
|
||||
# Model:
|
||||
oct_child: wp.array(dtype=vec8i),
|
||||
oct_aabb: wp.array2d(dtype=wp.vec3),
|
||||
oct_coeff: wp.array(dtype=vec8),
|
||||
mesh_octadr: wp.array(dtype=int),
|
||||
plugin: wp.array(dtype=int),
|
||||
plugin_attr: wp.array(dtype=wp.vec3f),
|
||||
# In:
|
||||
g_type: int,
|
||||
g_size: wp.vec3,
|
||||
plugin_id: int,
|
||||
mesh_id: int,
|
||||
) -> Tuple[wp.vec3, int, VolumeData, MeshData]:
|
||||
attributes = g_size
|
||||
plugin_index = -1
|
||||
@@ -98,8 +99,10 @@ def get_sdf_params(
|
||||
plugin_index = plugin[plugin_id]
|
||||
|
||||
elif g_type == GeomType.SDF and mesh_id != -1:
|
||||
volume_data.center = oct_aabb[mesh_id, 0]
|
||||
volume_data.half_size = oct_aabb[mesh_id, 1]
|
||||
octadr = mesh_octadr[mesh_id]
|
||||
volume_data.center = oct_aabb[octadr, 0]
|
||||
volume_data.half_size = oct_aabb[octadr, 1]
|
||||
volume_data.root = octadr
|
||||
volume_data.oct_aabb = oct_aabb
|
||||
volume_data.oct_child = oct_child
|
||||
volume_data.oct_coeff = oct_coeff
|
||||
@@ -225,9 +228,13 @@ def user_sdf_grad(p: wp.vec3, attr: wp.vec3, sdf_type: int) -> wp.vec3:
|
||||
|
||||
@wp.func
|
||||
def find_oct(
|
||||
oct_child: wp.array(dtype=vec8i), oct_aabb: wp.array2d(dtype=wp.vec3), p: wp.vec3, grad: bool
|
||||
oct_child: wp.array(dtype=vec8i),
|
||||
oct_aabb: wp.array2d(dtype=wp.vec3),
|
||||
p: wp.vec3,
|
||||
grad: bool,
|
||||
root: int,
|
||||
) -> Tuple[int, Tuple[vec8, vec8, vec8]]:
|
||||
stack = int(0)
|
||||
stack = root
|
||||
niter = int(100)
|
||||
rx = vec8(0.0)
|
||||
ry = vec8(0.0)
|
||||
@@ -258,15 +265,17 @@ def find_oct(
|
||||
coord = wp.cw_div(p - vmin, vmax - vmin)
|
||||
|
||||
# check if the node is a leaf
|
||||
# child indices are relative to root (mesh_octadr offset)
|
||||
child0 = oct_child[node][0]
|
||||
if (
|
||||
oct_child[node][0] == -1
|
||||
and oct_child[node][1] == -1
|
||||
and oct_child[node][2] == -1
|
||||
and oct_child[node][3] == -1
|
||||
and oct_child[node][4] == -1
|
||||
and oct_child[node][5] == -1
|
||||
and oct_child[node][6] == -1
|
||||
and oct_child[node][7] == -1
|
||||
child0 == -1
|
||||
and oct_child[node][1] == -1
|
||||
and oct_child[node][2] == -1
|
||||
and oct_child[node][3] == -1
|
||||
and oct_child[node][4] == -1
|
||||
and oct_child[node][5] == -1
|
||||
and oct_child[node][6] == -1
|
||||
and oct_child[node][7] == -1
|
||||
):
|
||||
for j in range(8):
|
||||
if not grad:
|
||||
@@ -282,10 +291,12 @@ def find_oct(
|
||||
return node, (rx, ry, rz)
|
||||
|
||||
# compute which of 8 children to visit next
|
||||
# child indices are stored relative to mesh_octadr, add root offset
|
||||
x = 0 if coord[0] < 0.5 else 1
|
||||
y = 0 if coord[1] < 0.5 else 1
|
||||
z = 0 if coord[2] < 0.5 else 1
|
||||
stack = oct_child[node][4 * z + 2 * y + x]
|
||||
child = oct_child[node][4 * z + 2 * y + x]
|
||||
stack = child + root if child != -1 else -1
|
||||
|
||||
wp.print("ERROR: Node not found\n")
|
||||
return -1, (rx, ry, rz)
|
||||
@@ -331,7 +342,13 @@ def box_project(center: wp.vec3, half_size: wp.vec3, xyz: wp.vec3) -> Tuple[floa
|
||||
@wp.func
|
||||
def sample_volume_sdf(xyz: wp.vec3, volume_data: VolumeData) -> float:
|
||||
dist0, point = box_project(volume_data.center, volume_data.half_size, xyz)
|
||||
node, weights = find_oct(volume_data.oct_child, volume_data.oct_aabb, point, grad=False)
|
||||
node, weights = find_oct(
|
||||
volume_data.oct_child,
|
||||
volume_data.oct_aabb,
|
||||
point,
|
||||
grad=False,
|
||||
root=volume_data.root,
|
||||
)
|
||||
return dist0 + wp.dot(weights[0], volume_data.oct_coeff[node])
|
||||
|
||||
|
||||
@@ -348,7 +365,13 @@ def sample_volume_grad(xyz: wp.vec3, volume_data: VolumeData) -> wp.vec3:
|
||||
grad_y = (sample_volume_sdf(xyz + dy, volume_data) - f) / h
|
||||
grad_z = (sample_volume_sdf(xyz + dz, volume_data) - f) / h
|
||||
return wp.vec3(grad_x, grad_y, grad_z)
|
||||
node, weights = find_oct(volume_data.oct_child, volume_data.oct_aabb, point, grad=True)
|
||||
node, weights = find_oct(
|
||||
volume_data.oct_child,
|
||||
volume_data.oct_aabb,
|
||||
point,
|
||||
grad=True,
|
||||
root=volume_data.root,
|
||||
)
|
||||
grad_x = wp.dot(weights[0], volume_data.oct_coeff[node])
|
||||
grad_y = wp.dot(weights[1], volume_data.oct_coeff[node])
|
||||
grad_z = wp.dot(weights[2], volume_data.oct_coeff[node])
|
||||
@@ -622,75 +645,76 @@ def gradient_descent(
|
||||
|
||||
@wp.kernel
|
||||
def _sdf_narrowphase(
|
||||
# Model:
|
||||
nmeshface: int,
|
||||
oct_child: wp.array(dtype=vec8i),
|
||||
oct_aabb: wp.array2d(dtype=wp.vec3),
|
||||
oct_coeff: wp.array(dtype=vec8),
|
||||
geom_type: wp.array(dtype=int),
|
||||
geom_condim: wp.array(dtype=int),
|
||||
geom_dataid: wp.array(dtype=int),
|
||||
geom_priority: wp.array(dtype=int),
|
||||
geom_solmix: wp.array2d(dtype=float),
|
||||
geom_solref: wp.array2d(dtype=wp.vec2),
|
||||
geom_solimp: wp.array2d(dtype=vec5),
|
||||
geom_size: wp.array2d(dtype=wp.vec3),
|
||||
geom_aabb: wp.array3d(dtype=wp.vec3),
|
||||
geom_friction: wp.array2d(dtype=wp.vec3),
|
||||
geom_margin: wp.array2d(dtype=float),
|
||||
geom_gap: wp.array2d(dtype=float),
|
||||
mesh_vertadr: wp.array(dtype=int),
|
||||
mesh_vertnum: wp.array(dtype=int),
|
||||
mesh_faceadr: wp.array(dtype=int),
|
||||
mesh_graphadr: wp.array(dtype=int),
|
||||
mesh_vert: wp.array(dtype=wp.vec3),
|
||||
mesh_face: wp.array(dtype=wp.vec3i),
|
||||
mesh_graph: wp.array(dtype=int),
|
||||
mesh_polynum: wp.array(dtype=int),
|
||||
mesh_polyadr: wp.array(dtype=int),
|
||||
mesh_polynormal: wp.array(dtype=wp.vec3),
|
||||
mesh_polyvertadr: wp.array(dtype=int),
|
||||
mesh_polyvertnum: wp.array(dtype=int),
|
||||
mesh_polyvert: wp.array(dtype=int),
|
||||
mesh_polymapadr: wp.array(dtype=int),
|
||||
mesh_polymapnum: wp.array(dtype=int),
|
||||
mesh_polymap: wp.array(dtype=int),
|
||||
pair_dim: wp.array(dtype=int),
|
||||
pair_solref: wp.array2d(dtype=wp.vec2),
|
||||
pair_solreffriction: wp.array2d(dtype=wp.vec2),
|
||||
pair_solimp: wp.array2d(dtype=vec5),
|
||||
pair_margin: wp.array2d(dtype=float),
|
||||
pair_gap: wp.array2d(dtype=float),
|
||||
pair_friction: wp.array2d(dtype=vec5),
|
||||
plugin: wp.array(dtype=int),
|
||||
plugin_attr: wp.array(dtype=wp.vec3f),
|
||||
geom_plugin_index: wp.array(dtype=int),
|
||||
# Data in:
|
||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
||||
naconmax_in: int,
|
||||
ncollision_in: wp.array(dtype=int),
|
||||
# In:
|
||||
collision_pair_in: wp.array(dtype=wp.vec2i),
|
||||
collision_pairid_in: wp.array(dtype=wp.vec2i),
|
||||
collision_worldid_in: wp.array(dtype=int),
|
||||
sdf_initpoints: int,
|
||||
sdf_iterations: int,
|
||||
# Data out:
|
||||
contact_dist_out: wp.array(dtype=float),
|
||||
contact_pos_out: wp.array(dtype=wp.vec3),
|
||||
contact_frame_out: wp.array(dtype=wp.mat33),
|
||||
contact_includemargin_out: wp.array(dtype=float),
|
||||
contact_friction_out: wp.array(dtype=vec5),
|
||||
contact_solref_out: wp.array(dtype=wp.vec2),
|
||||
contact_solreffriction_out: wp.array(dtype=wp.vec2),
|
||||
contact_solimp_out: wp.array(dtype=vec5),
|
||||
contact_dim_out: wp.array(dtype=int),
|
||||
contact_geom_out: wp.array(dtype=wp.vec2i),
|
||||
contact_worldid_out: wp.array(dtype=int),
|
||||
contact_type_out: wp.array(dtype=int),
|
||||
contact_geomcollisionid_out: wp.array(dtype=int),
|
||||
nacon_out: wp.array(dtype=int),
|
||||
# Model:
|
||||
nmeshface: int,
|
||||
oct_child: wp.array(dtype=vec8i),
|
||||
oct_aabb: wp.array2d(dtype=wp.vec3),
|
||||
oct_coeff: wp.array(dtype=vec8),
|
||||
geom_type: wp.array(dtype=int),
|
||||
geom_condim: wp.array(dtype=int),
|
||||
geom_dataid: wp.array(dtype=int),
|
||||
geom_priority: wp.array(dtype=int),
|
||||
geom_solmix: wp.array2d(dtype=float),
|
||||
geom_solref: wp.array2d(dtype=wp.vec2),
|
||||
geom_solimp: wp.array2d(dtype=vec5),
|
||||
geom_size: wp.array2d(dtype=wp.vec3),
|
||||
geom_aabb: wp.array3d(dtype=wp.vec3),
|
||||
geom_friction: wp.array2d(dtype=wp.vec3),
|
||||
geom_margin: wp.array2d(dtype=float),
|
||||
geom_gap: wp.array2d(dtype=float),
|
||||
mesh_vertadr: wp.array(dtype=int),
|
||||
mesh_vertnum: wp.array(dtype=int),
|
||||
mesh_faceadr: wp.array(dtype=int),
|
||||
mesh_octadr: wp.array(dtype=int),
|
||||
mesh_graphadr: wp.array(dtype=int),
|
||||
mesh_vert: wp.array(dtype=wp.vec3),
|
||||
mesh_face: wp.array(dtype=wp.vec3i),
|
||||
mesh_graph: wp.array(dtype=int),
|
||||
mesh_polynum: wp.array(dtype=int),
|
||||
mesh_polyadr: wp.array(dtype=int),
|
||||
mesh_polynormal: wp.array(dtype=wp.vec3),
|
||||
mesh_polyvertadr: wp.array(dtype=int),
|
||||
mesh_polyvertnum: wp.array(dtype=int),
|
||||
mesh_polyvert: wp.array(dtype=int),
|
||||
mesh_polymapadr: wp.array(dtype=int),
|
||||
mesh_polymapnum: wp.array(dtype=int),
|
||||
mesh_polymap: wp.array(dtype=int),
|
||||
pair_dim: wp.array(dtype=int),
|
||||
pair_solref: wp.array2d(dtype=wp.vec2),
|
||||
pair_solreffriction: wp.array2d(dtype=wp.vec2),
|
||||
pair_solimp: wp.array2d(dtype=vec5),
|
||||
pair_margin: wp.array2d(dtype=float),
|
||||
pair_gap: wp.array2d(dtype=float),
|
||||
pair_friction: wp.array2d(dtype=vec5),
|
||||
plugin: wp.array(dtype=int),
|
||||
plugin_attr: wp.array(dtype=wp.vec3f),
|
||||
geom_plugin_index: wp.array(dtype=int),
|
||||
# Data in:
|
||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
||||
naconmax_in: int,
|
||||
ncollision_in: wp.array(dtype=int),
|
||||
# In:
|
||||
collision_pair_in: wp.array(dtype=wp.vec2i),
|
||||
collision_pairid_in: wp.array(dtype=wp.vec2i),
|
||||
collision_worldid_in: wp.array(dtype=int),
|
||||
sdf_initpoints: int,
|
||||
sdf_iterations: int,
|
||||
# Data out:
|
||||
contact_dist_out: wp.array(dtype=float),
|
||||
contact_pos_out: wp.array(dtype=wp.vec3),
|
||||
contact_frame_out: wp.array(dtype=wp.mat33),
|
||||
contact_includemargin_out: wp.array(dtype=float),
|
||||
contact_friction_out: wp.array(dtype=vec5),
|
||||
contact_solref_out: wp.array(dtype=wp.vec2),
|
||||
contact_solreffriction_out: wp.array(dtype=wp.vec2),
|
||||
contact_solimp_out: wp.array(dtype=vec5),
|
||||
contact_dim_out: wp.array(dtype=int),
|
||||
contact_geom_out: wp.array(dtype=wp.vec2i),
|
||||
contact_worldid_out: wp.array(dtype=int),
|
||||
contact_type_out: wp.array(dtype=int),
|
||||
contact_geomcollisionid_out: wp.array(dtype=int),
|
||||
nacon_out: wp.array(dtype=int),
|
||||
):
|
||||
i, contact_tid = wp.tid()
|
||||
if i >= sdf_initpoints:
|
||||
@@ -775,11 +799,29 @@ def _sdf_narrowphase(
|
||||
rot1 = geom1.rot
|
||||
|
||||
attr1, g1_plugin_id, volume_data1, mesh_data1 = get_sdf_params(
|
||||
oct_child, oct_aabb, oct_coeff, plugin, plugin_attr, type1, geom1.size, g1_plugin, geom_dataid[g1]
|
||||
oct_child,
|
||||
oct_aabb,
|
||||
oct_coeff,
|
||||
mesh_octadr,
|
||||
plugin,
|
||||
plugin_attr,
|
||||
type1,
|
||||
geom1.size,
|
||||
g1_plugin,
|
||||
geom_dataid[g1],
|
||||
)
|
||||
|
||||
attr2, g2_plugin_id, volume_data2, mesh_data2 = get_sdf_params(
|
||||
oct_child, oct_aabb, oct_coeff, plugin, plugin_attr, type2, geom2.size, g2_plugin, geom_dataid[g2]
|
||||
oct_child,
|
||||
oct_aabb,
|
||||
oct_coeff,
|
||||
mesh_octadr,
|
||||
plugin,
|
||||
plugin_attr,
|
||||
type2,
|
||||
geom2.size,
|
||||
g2_plugin,
|
||||
geom_dataid[g2],
|
||||
)
|
||||
|
||||
mesh_data1.nmeshface = nmeshface
|
||||
@@ -868,75 +910,76 @@ def _sdf_narrowphase(
|
||||
@event_scope
|
||||
def sdf_narrowphase(m: Model, d: Data, ctx: CollisionContext):
|
||||
wp.launch(
|
||||
_sdf_narrowphase,
|
||||
dim=(m.opt.sdf_initpoints, d.naconmax),
|
||||
inputs=[
|
||||
m.nmeshface,
|
||||
m.oct_child,
|
||||
m.oct_aabb,
|
||||
m.oct_coeff,
|
||||
m.geom_type,
|
||||
m.geom_condim,
|
||||
m.geom_dataid,
|
||||
m.geom_priority,
|
||||
m.geom_solmix,
|
||||
m.geom_solref,
|
||||
m.geom_solimp,
|
||||
m.geom_size,
|
||||
m.geom_aabb,
|
||||
m.geom_friction,
|
||||
m.geom_margin,
|
||||
m.geom_gap,
|
||||
m.mesh_vertadr,
|
||||
m.mesh_vertnum,
|
||||
m.mesh_faceadr,
|
||||
m.mesh_graphadr,
|
||||
m.mesh_vert,
|
||||
m.mesh_face,
|
||||
m.mesh_graph,
|
||||
m.mesh_polynum,
|
||||
m.mesh_polyadr,
|
||||
m.mesh_polynormal,
|
||||
m.mesh_polyvertadr,
|
||||
m.mesh_polyvertnum,
|
||||
m.mesh_polyvert,
|
||||
m.mesh_polymapadr,
|
||||
m.mesh_polymapnum,
|
||||
m.mesh_polymap,
|
||||
m.pair_dim,
|
||||
m.pair_solref,
|
||||
m.pair_solreffriction,
|
||||
m.pair_solimp,
|
||||
m.pair_margin,
|
||||
m.pair_gap,
|
||||
m.pair_friction,
|
||||
m.plugin,
|
||||
m.plugin_attr,
|
||||
m.geom_plugin_index,
|
||||
d.geom_xpos,
|
||||
d.geom_xmat,
|
||||
d.naconmax,
|
||||
d.ncollision,
|
||||
ctx.collision_pair,
|
||||
ctx.collision_pairid,
|
||||
ctx.collision_worldid,
|
||||
m.opt.sdf_initpoints,
|
||||
m.opt.sdf_iterations,
|
||||
],
|
||||
outputs=[
|
||||
d.contact.dist,
|
||||
d.contact.pos,
|
||||
d.contact.frame,
|
||||
d.contact.includemargin,
|
||||
d.contact.friction,
|
||||
d.contact.solref,
|
||||
d.contact.solreffriction,
|
||||
d.contact.solimp,
|
||||
d.contact.dim,
|
||||
d.contact.geom,
|
||||
d.contact.worldid,
|
||||
d.contact.type,
|
||||
d.contact.geomcollisionid,
|
||||
d.nacon,
|
||||
],
|
||||
_sdf_narrowphase,
|
||||
dim=(m.opt.sdf_initpoints, d.naconmax),
|
||||
inputs=[
|
||||
m.nmeshface,
|
||||
m.oct_child,
|
||||
m.oct_aabb,
|
||||
m.oct_coeff,
|
||||
m.geom_type,
|
||||
m.geom_condim,
|
||||
m.geom_dataid,
|
||||
m.geom_priority,
|
||||
m.geom_solmix,
|
||||
m.geom_solref,
|
||||
m.geom_solimp,
|
||||
m.geom_size,
|
||||
m.geom_aabb,
|
||||
m.geom_friction,
|
||||
m.geom_margin,
|
||||
m.geom_gap,
|
||||
m.mesh_vertadr,
|
||||
m.mesh_vertnum,
|
||||
m.mesh_faceadr,
|
||||
m.mesh_octadr,
|
||||
m.mesh_graphadr,
|
||||
m.mesh_vert,
|
||||
m.mesh_face,
|
||||
m.mesh_graph,
|
||||
m.mesh_polynum,
|
||||
m.mesh_polyadr,
|
||||
m.mesh_polynormal,
|
||||
m.mesh_polyvertadr,
|
||||
m.mesh_polyvertnum,
|
||||
m.mesh_polyvert,
|
||||
m.mesh_polymapadr,
|
||||
m.mesh_polymapnum,
|
||||
m.mesh_polymap,
|
||||
m.pair_dim,
|
||||
m.pair_solref,
|
||||
m.pair_solreffriction,
|
||||
m.pair_solimp,
|
||||
m.pair_margin,
|
||||
m.pair_gap,
|
||||
m.pair_friction,
|
||||
m.plugin,
|
||||
m.plugin_attr,
|
||||
m.geom_plugin_index,
|
||||
d.geom_xpos,
|
||||
d.geom_xmat,
|
||||
d.naconmax,
|
||||
d.ncollision,
|
||||
ctx.collision_pair,
|
||||
ctx.collision_pairid,
|
||||
ctx.collision_worldid,
|
||||
m.opt.sdf_initpoints,
|
||||
m.opt.sdf_iterations,
|
||||
],
|
||||
outputs=[
|
||||
d.contact.dist,
|
||||
d.contact.pos,
|
||||
d.contact.frame,
|
||||
d.contact.includemargin,
|
||||
d.contact.friction,
|
||||
d.contact.solref,
|
||||
d.contact.solreffriction,
|
||||
d.contact.solimp,
|
||||
d.contact.dim,
|
||||
d.contact.geom,
|
||||
d.contact.worldid,
|
||||
d.contact.type,
|
||||
d.contact.geomcollisionid,
|
||||
d.nacon,
|
||||
],
|
||||
)
|
||||
|
||||
+1891
-1401
File diff suppressed because it is too large
Load Diff
+51
-66
@@ -21,9 +21,7 @@ from mujoco.mjx.third_party.mujoco_warp._src.types import DisableBit
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import DynType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import GainType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Model
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import TileSet
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import vec10f
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import cache_kernel
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import event_scope
|
||||
|
||||
wp.set_module_options({"enable_backward": False})
|
||||
@@ -96,55 +94,22 @@ def _nonzero_mask(x: float) -> float:
|
||||
return 0.0
|
||||
|
||||
|
||||
@cache_kernel
|
||||
def _qderiv_actuator_passive_actuation_dense(tile: TileSet, nu: int):
|
||||
@wp.kernel(module="unique", enable_backward=False)
|
||||
def kernel(
|
||||
# Data in:
|
||||
actuator_moment_in: wp.array3d(dtype=float),
|
||||
qM_in: wp.array3d(dtype=float),
|
||||
# In:
|
||||
vel_in: wp.array3d(dtype=float),
|
||||
adr: wp.array(dtype=int),
|
||||
# Out:
|
||||
qDeriv_out: wp.array3d(dtype=float),
|
||||
):
|
||||
worldid, nodeid = wp.tid()
|
||||
TILE_SIZE = wp.static(tile.size)
|
||||
NU = wp.static(nu)
|
||||
|
||||
dofid = adr[nodeid]
|
||||
vel_tile = wp.tile_load(vel_in[worldid], shape=(NU, 1), bounds_check=False)
|
||||
moment_tile = wp.tile_load(actuator_moment_in[worldid], shape=(NU, TILE_SIZE), offset=(0, dofid), bounds_check=False)
|
||||
moment_weighted = wp.tile_map(wp.mul, wp.tile_broadcast(vel_tile, shape=(NU, TILE_SIZE)), moment_tile)
|
||||
qderiv_tile = wp.tile_matmul(wp.tile_transpose(moment_tile), moment_weighted)
|
||||
|
||||
# Mask out cross-terms for DOF pairs that are structurally zero in M
|
||||
# (e.g., sibling DOFs coupled only through tendons). Without this,
|
||||
# stale actuation values at sibling positions make A = M - dt*qDeriv
|
||||
# non-positive-definite, causing the tiled Cholesky to produce NaN.
|
||||
# Dropping these terms matches MuJoCo CPU's implicitfast approximation.
|
||||
qM_tile = wp.tile_load(qM_in[worldid], shape=(TILE_SIZE, TILE_SIZE), offset=(dofid, dofid), bounds_check=False)
|
||||
mask_tile = wp.tile_map(_nonzero_mask, qM_tile)
|
||||
qderiv_tile = wp.tile_map(wp.mul, qderiv_tile, mask_tile)
|
||||
|
||||
wp.tile_store(qDeriv_out[worldid], qderiv_tile, offset=(dofid, dofid), bounds_check=False)
|
||||
|
||||
return kernel
|
||||
|
||||
|
||||
@wp.kernel
|
||||
def _qderiv_actuator_passive_actuation_sparse(
|
||||
# Model:
|
||||
nu: int,
|
||||
# Data in:
|
||||
actuator_moment_in: wp.array3d(dtype=float),
|
||||
# In:
|
||||
vel_in: wp.array2d(dtype=float),
|
||||
qMi: wp.array(dtype=int),
|
||||
qMj: wp.array(dtype=int),
|
||||
# Out:
|
||||
qDeriv_out: wp.array3d(dtype=float),
|
||||
# Model:
|
||||
nu: int,
|
||||
is_sparse: bool,
|
||||
# Data in:
|
||||
moment_rownnz_in: wp.array2d(dtype=int),
|
||||
moment_rowadr_in: wp.array2d(dtype=int),
|
||||
moment_colind_in: wp.array2d(dtype=int),
|
||||
actuator_moment_in: wp.array2d(dtype=float),
|
||||
# In:
|
||||
vel_in: wp.array2d(dtype=float),
|
||||
qMi: wp.array(dtype=int),
|
||||
qMj: wp.array(dtype=int),
|
||||
# Out:
|
||||
qDeriv_out: wp.array3d(dtype=float),
|
||||
):
|
||||
worldid, elemid = wp.tid()
|
||||
|
||||
@@ -156,12 +121,33 @@ def _qderiv_actuator_passive_actuation_sparse(
|
||||
if vel == 0.0:
|
||||
continue
|
||||
|
||||
moment_i = actuator_moment_in[worldid, actid, dofiid]
|
||||
moment_j = actuator_moment_in[worldid, actid, dofjid]
|
||||
# TODO(team): restructure sparse version for better parallelism?
|
||||
moment_i = float(0.0)
|
||||
moment_j = float(0.0)
|
||||
|
||||
rownnz = moment_rownnz_in[worldid, actid]
|
||||
rowadr = moment_rowadr_in[worldid, actid]
|
||||
for i in range(rownnz):
|
||||
sparseid = rowadr + i
|
||||
colind = moment_colind_in[worldid, sparseid]
|
||||
if colind == dofiid:
|
||||
moment_i = actuator_moment_in[worldid, sparseid]
|
||||
if colind == dofjid:
|
||||
moment_j = actuator_moment_in[worldid, sparseid]
|
||||
if moment_i != 0.0 and moment_j != 0.0:
|
||||
break
|
||||
|
||||
if moment_i == 0 and moment_j == 0:
|
||||
continue
|
||||
|
||||
qderiv_contrib += moment_i * moment_j * vel
|
||||
|
||||
qDeriv_out[worldid, 0, elemid] = qderiv_contrib
|
||||
if is_sparse:
|
||||
qDeriv_out[worldid, 0, elemid] = qderiv_contrib
|
||||
else:
|
||||
qDeriv_out[worldid, dofiid, dofjid] = qderiv_contrib
|
||||
if dofiid != dofjid:
|
||||
qDeriv_out[worldid, dofjid, dofiid] = qderiv_contrib
|
||||
|
||||
|
||||
@wp.kernel
|
||||
@@ -277,23 +263,22 @@ def deriv_smooth_vel(m: Model, d: Data, out: wp.array2d(dtype=float)):
|
||||
],
|
||||
outputs=[vel],
|
||||
)
|
||||
if m.is_sparse:
|
||||
wp.launch(
|
||||
wp.launch(
|
||||
_qderiv_actuator_passive_actuation_sparse,
|
||||
dim=(d.nworld, qMi.size),
|
||||
inputs=[m.nu, d.actuator_moment, vel, qMi, qMj],
|
||||
inputs=[
|
||||
m.nu,
|
||||
m.is_sparse,
|
||||
d.moment_rownnz,
|
||||
d.moment_rowadr,
|
||||
d.moment_colind,
|
||||
d.actuator_moment,
|
||||
vel,
|
||||
qMi,
|
||||
qMj,
|
||||
],
|
||||
outputs=[out],
|
||||
)
|
||||
else:
|
||||
vel_3d = vel.reshape(vel.shape + (1,))
|
||||
for tile in m.qM_tiles:
|
||||
wp.launch_tiled(
|
||||
_qderiv_actuator_passive_actuation_dense(tile, m.nu),
|
||||
dim=(d.nworld, tile.adr.size),
|
||||
inputs=[d.actuator_moment, d.qM, vel_3d, tile.adr],
|
||||
outputs=[out],
|
||||
block_dim=m.block_dim.qderiv_actuator_dense,
|
||||
)
|
||||
)
|
||||
wp.launch(
|
||||
_qderiv_actuator_passive,
|
||||
dim=(d.nworld, qMi.size),
|
||||
|
||||
+226
-135
@@ -15,11 +15,10 @@
|
||||
|
||||
from typing import Optional
|
||||
|
||||
import warp as wp
|
||||
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import collision_driver
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import constraint
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import derivative
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import island
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import math
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import passive
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import sensor
|
||||
@@ -27,7 +26,6 @@ from mujoco.mjx.third_party.mujoco_warp._src import smooth
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import solver
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import util_misc
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.support import xfrc_accumulate
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MINVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import BiasType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Data
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import DisableBit
|
||||
@@ -36,12 +34,14 @@ from mujoco.mjx.third_party.mujoco_warp._src.types import EnableBit
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import GainType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import IntegratorType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import JointType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MINVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Model
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import TileSet
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import TrnType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import vec10f
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import cache_kernel
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import event_scope
|
||||
import warp as wp
|
||||
|
||||
wp.set_module_options({"enable_backward": False})
|
||||
|
||||
@@ -146,6 +146,8 @@ def _next_act(
|
||||
if actuator_dyntype == DynType.FILTEREXACT:
|
||||
tau = wp.max(MJ_MINVAL, actuator_dynprm[0])
|
||||
act = act_in + act_dot_scale * act_dot_in * tau * (1.0 - wp.exp(-opt_timestep / tau))
|
||||
elif actuator_dyntype == DynType.USER:
|
||||
return act_in
|
||||
else:
|
||||
act = act_in + act_dot_scale * act_dot_in * opt_timestep
|
||||
|
||||
@@ -158,36 +160,41 @@ def _next_act(
|
||||
|
||||
@wp.kernel
|
||||
def _next_activation(
|
||||
# Model:
|
||||
opt_timestep: wp.array(dtype=float),
|
||||
actuator_dyntype: wp.array(dtype=int),
|
||||
actuator_actlimited: wp.array(dtype=bool),
|
||||
actuator_dynprm: wp.array2d(dtype=vec10f),
|
||||
actuator_actrange: wp.array2d(dtype=wp.vec2),
|
||||
# Data in:
|
||||
act_in: wp.array2d(dtype=float),
|
||||
act_dot_in: wp.array2d(dtype=float),
|
||||
# In:
|
||||
act_dot_scale: float,
|
||||
limit: bool,
|
||||
# Data out:
|
||||
act_out: wp.array2d(dtype=float),
|
||||
# Model:
|
||||
opt_timestep: wp.array(dtype=float),
|
||||
actuator_dyntype: wp.array(dtype=int),
|
||||
actuator_actadr: wp.array(dtype=int),
|
||||
actuator_actnum: wp.array(dtype=int),
|
||||
actuator_actlimited: wp.array(dtype=bool),
|
||||
actuator_dynprm: wp.array2d(dtype=vec10f),
|
||||
actuator_actrange: wp.array2d(dtype=wp.vec2),
|
||||
# Data in:
|
||||
act_in: wp.array2d(dtype=float),
|
||||
act_dot_in: wp.array2d(dtype=float),
|
||||
# In:
|
||||
act_dot_scale: float,
|
||||
limit: bool,
|
||||
# Data out:
|
||||
act_out: wp.array2d(dtype=float),
|
||||
):
|
||||
worldid, actid = wp.tid()
|
||||
worldid, uid = wp.tid()
|
||||
opt_timestep_id = worldid % opt_timestep.shape[0]
|
||||
actuator_dynprm_id = worldid % actuator_dynprm.shape[0]
|
||||
actuator_actrange_id = worldid % actuator_actrange.shape[0]
|
||||
act = _next_act(
|
||||
opt_timestep[opt_timestep_id],
|
||||
actuator_dyntype[actid],
|
||||
actuator_dynprm[actuator_dynprm_id, actid],
|
||||
actuator_actrange[actuator_actrange_id, actid],
|
||||
act_in[worldid, actid],
|
||||
act_dot_in[worldid, actid],
|
||||
act_dot_scale,
|
||||
limit and actuator_actlimited[actid],
|
||||
)
|
||||
act_out[worldid, actid] = act
|
||||
actadr = actuator_actadr[uid]
|
||||
actnum = actuator_actnum[uid]
|
||||
for j in range(actadr, actadr + actnum):
|
||||
act = _next_act(
|
||||
opt_timestep[opt_timestep_id],
|
||||
actuator_dyntype[uid],
|
||||
actuator_dynprm[actuator_dynprm_id, uid],
|
||||
actuator_actrange[actuator_actrange_id, uid],
|
||||
act_in[worldid, j],
|
||||
act_dot_in[worldid, j],
|
||||
act_dot_scale,
|
||||
limit and actuator_actlimited[uid],
|
||||
)
|
||||
act_out[worldid, j] = act
|
||||
|
||||
|
||||
@wp.kernel
|
||||
@@ -229,20 +236,22 @@ def _advance(m: Model, d: Data, qacc: wp.array, qvel: Optional[wp.array] = None)
|
||||
|
||||
# advance activations
|
||||
wp.launch(
|
||||
_next_activation,
|
||||
dim=(d.nworld, m.na),
|
||||
inputs=[
|
||||
m.opt.timestep,
|
||||
m.actuator_dyntype,
|
||||
m.actuator_actlimited,
|
||||
m.actuator_dynprm,
|
||||
m.actuator_actrange,
|
||||
d.act,
|
||||
d.act_dot,
|
||||
1.0,
|
||||
True,
|
||||
],
|
||||
outputs=[d.act],
|
||||
_next_activation,
|
||||
dim=(d.nworld, m.nu),
|
||||
inputs=[
|
||||
m.opt.timestep,
|
||||
m.actuator_dyntype,
|
||||
m.actuator_actadr,
|
||||
m.actuator_actnum,
|
||||
m.actuator_actlimited,
|
||||
m.actuator_dynprm,
|
||||
m.actuator_actrange,
|
||||
d.act,
|
||||
d.act_dot,
|
||||
1.0,
|
||||
True,
|
||||
],
|
||||
outputs=[d.act],
|
||||
)
|
||||
|
||||
wp.launch(
|
||||
@@ -285,7 +294,9 @@ def _euler_damp_qfrc_sparse(
|
||||
timestep = opt_timestep[worldid % opt_timestep.shape[0]]
|
||||
|
||||
adr = dof_Madr[tid]
|
||||
qM_integration_out[worldid, 0, adr] += timestep * dof_damping[worldid, tid]
|
||||
qM_integration_out[worldid, 0, adr] += (
|
||||
timestep * dof_damping[worldid % dof_damping.shape[0], tid]
|
||||
)
|
||||
|
||||
|
||||
@cache_kernel
|
||||
@@ -379,10 +390,22 @@ def _rk_perturb_state(
|
||||
# activation
|
||||
if m.na and act_t0 is not None:
|
||||
wp.launch(
|
||||
_next_activation,
|
||||
dim=(d.nworld, m.na),
|
||||
inputs=[m.opt.timestep, act_t0, d.act_dot, scale, False],
|
||||
outputs=[d.act],
|
||||
_next_activation,
|
||||
dim=(d.nworld, m.nu),
|
||||
inputs=[
|
||||
m.opt.timestep,
|
||||
m.actuator_dyntype,
|
||||
m.actuator_actadr,
|
||||
m.actuator_actnum,
|
||||
m.actuator_actlimited,
|
||||
m.actuator_dynprm,
|
||||
m.actuator_actrange,
|
||||
act_t0,
|
||||
d.act_dot,
|
||||
scale,
|
||||
False,
|
||||
],
|
||||
outputs=[d.act],
|
||||
)
|
||||
|
||||
|
||||
@@ -517,28 +540,35 @@ def fwd_position(m: Model, d: Data, factorize: bool = True):
|
||||
if m.opt.run_collision_detection:
|
||||
collision_driver.collision(m, d)
|
||||
constraint.make_constraint(m, d)
|
||||
# TODO(team): remove False after island features are more complete
|
||||
if False and not (m.opt.disableflags & DisableBit.ISLAND):
|
||||
island.island(m, d)
|
||||
smooth.transmission(m, d)
|
||||
|
||||
|
||||
# TODO(team): sparse actuator_moment version
|
||||
@cache_kernel
|
||||
def _actuator_velocity(nv: int):
|
||||
@wp.kernel(module="unique", enable_backward=False)
|
||||
def actuator_velocity(
|
||||
@wp.kernel
|
||||
def _actuator_velocity(
|
||||
# Data in:
|
||||
qvel_in: wp.array2d(dtype=float),
|
||||
actuator_moment_in: wp.array3d(dtype=float),
|
||||
moment_rownnz_in: wp.array2d(dtype=int),
|
||||
moment_rowadr_in: wp.array2d(dtype=int),
|
||||
moment_colind_in: wp.array2d(dtype=int),
|
||||
actuator_moment_in: wp.array2d(dtype=float),
|
||||
# Data out:
|
||||
actuator_velocity_out: wp.array2d(dtype=float),
|
||||
):
|
||||
worldid, actid = wp.tid()
|
||||
moment_tile = wp.tile_load(actuator_moment_in[worldid, actid], shape=wp.static(nv))
|
||||
qvel_tile = wp.tile_load(qvel_in[worldid], shape=wp.static(nv))
|
||||
moment_qvel_tile = wp.tile_map(wp.mul, moment_tile, qvel_tile)
|
||||
actuator_velocity_tile = wp.tile_reduce(wp.add, moment_qvel_tile)
|
||||
actuator_velocity_out[worldid, actid] = actuator_velocity_tile[0]
|
||||
):
|
||||
worldid, actid = wp.tid()
|
||||
|
||||
return actuator_velocity
|
||||
rownnz = moment_rownnz_in[worldid, actid]
|
||||
rowadr = moment_rowadr_in[worldid, actid]
|
||||
|
||||
vel = float(0.0)
|
||||
for i in range(rownnz):
|
||||
sparseid = rowadr + i
|
||||
colind = moment_colind_in[worldid, sparseid]
|
||||
vel += actuator_moment_in[worldid, sparseid] * qvel_in[worldid, colind]
|
||||
|
||||
actuator_velocity_out[worldid, actid] = vel
|
||||
|
||||
|
||||
@cache_kernel
|
||||
@@ -565,11 +595,17 @@ def _tendon_velocity(nv: int):
|
||||
def fwd_velocity(m: Model, d: Data):
|
||||
"""Velocity-dependent computations."""
|
||||
wp.launch_tiled(
|
||||
_actuator_velocity(m.nv),
|
||||
dim=(d.nworld, m.nu),
|
||||
inputs=[d.qvel, d.actuator_moment],
|
||||
outputs=[d.actuator_velocity],
|
||||
block_dim=m.block_dim.actuator_velocity,
|
||||
_actuator_velocity,
|
||||
dim=(d.nworld, m.nu),
|
||||
inputs=[
|
||||
d.qvel,
|
||||
d.moment_rownnz,
|
||||
d.moment_rowadr,
|
||||
d.moment_colind,
|
||||
d.actuator_moment,
|
||||
],
|
||||
outputs=[d.actuator_velocity],
|
||||
block_dim=m.block_dim.actuator_velocity,
|
||||
)
|
||||
|
||||
# TODO(team): sparse version
|
||||
@@ -589,36 +625,36 @@ def fwd_velocity(m: Model, d: Data):
|
||||
|
||||
@wp.kernel
|
||||
def _actuator_force(
|
||||
# Model:
|
||||
na: int,
|
||||
opt_timestep: wp.array(dtype=float),
|
||||
actuator_dyntype: wp.array(dtype=int),
|
||||
actuator_gaintype: wp.array(dtype=int),
|
||||
actuator_biastype: wp.array(dtype=int),
|
||||
actuator_actadr: wp.array(dtype=int),
|
||||
actuator_actnum: wp.array(dtype=int),
|
||||
actuator_ctrllimited: wp.array(dtype=bool),
|
||||
actuator_forcelimited: wp.array(dtype=bool),
|
||||
actuator_actlimited: wp.array(dtype=bool),
|
||||
actuator_dynprm: wp.array2d(dtype=vec10f),
|
||||
actuator_gainprm: wp.array2d(dtype=vec10f),
|
||||
actuator_biasprm: wp.array2d(dtype=vec10f),
|
||||
actuator_actearly: wp.array(dtype=bool),
|
||||
actuator_ctrlrange: wp.array2d(dtype=wp.vec2),
|
||||
actuator_forcerange: wp.array2d(dtype=wp.vec2),
|
||||
actuator_actrange: wp.array2d(dtype=wp.vec2),
|
||||
actuator_acc0: wp.array(dtype=float),
|
||||
actuator_lengthrange: wp.array(dtype=wp.vec2),
|
||||
# Data in:
|
||||
act_in: wp.array2d(dtype=float),
|
||||
ctrl_in: wp.array2d(dtype=float),
|
||||
actuator_length_in: wp.array2d(dtype=float),
|
||||
actuator_velocity_in: wp.array2d(dtype=float),
|
||||
# In:
|
||||
dsbl_clampctrl: int,
|
||||
# Data out:
|
||||
act_dot_out: wp.array2d(dtype=float),
|
||||
actuator_force_out: wp.array2d(dtype=float),
|
||||
# Model:
|
||||
na: int,
|
||||
opt_timestep: wp.array(dtype=float),
|
||||
actuator_dyntype: wp.array(dtype=int),
|
||||
actuator_gaintype: wp.array(dtype=int),
|
||||
actuator_biastype: wp.array(dtype=int),
|
||||
actuator_actadr: wp.array(dtype=int),
|
||||
actuator_actnum: wp.array(dtype=int),
|
||||
actuator_ctrllimited: wp.array(dtype=bool),
|
||||
actuator_forcelimited: wp.array(dtype=bool),
|
||||
actuator_actlimited: wp.array(dtype=bool),
|
||||
actuator_dynprm: wp.array2d(dtype=vec10f),
|
||||
actuator_gainprm: wp.array2d(dtype=vec10f),
|
||||
actuator_biasprm: wp.array2d(dtype=vec10f),
|
||||
actuator_actearly: wp.array(dtype=bool),
|
||||
actuator_ctrlrange: wp.array2d(dtype=wp.vec2),
|
||||
actuator_forcerange: wp.array2d(dtype=wp.vec2),
|
||||
actuator_actrange: wp.array2d(dtype=wp.vec2),
|
||||
actuator_acc0: wp.array2d(dtype=float),
|
||||
actuator_lengthrange: wp.array2d(dtype=wp.vec2),
|
||||
# Data in:
|
||||
act_in: wp.array2d(dtype=float),
|
||||
ctrl_in: wp.array2d(dtype=float),
|
||||
actuator_length_in: wp.array2d(dtype=float),
|
||||
actuator_velocity_in: wp.array2d(dtype=float),
|
||||
# In:
|
||||
dsbl_clampctrl: int,
|
||||
# Data out:
|
||||
act_dot_out: wp.array2d(dtype=float),
|
||||
actuator_force_out: wp.array2d(dtype=float),
|
||||
):
|
||||
worldid, uid = wp.tid()
|
||||
|
||||
@@ -643,9 +679,11 @@ def _actuator_force(
|
||||
act = act_in[worldid, act_last]
|
||||
act_dot = (ctrl - act) / wp.max(dynprm[0], MJ_MINVAL)
|
||||
elif dyntype == DynType.MUSCLE:
|
||||
dynprm = actuator_dynprm[worldid, uid]
|
||||
dynprm = actuator_dynprm[worldid % actuator_dynprm.shape[0], uid]
|
||||
act = act_in[worldid, act_last]
|
||||
act_dot = util_misc.muscle_dynamics(ctrl, act, dynprm)
|
||||
elif dyntype == DynType.USER:
|
||||
act_dot = 0.0 # set by act_dyn_callback
|
||||
else: # DynType.NONE
|
||||
act_dot = 0.0
|
||||
|
||||
@@ -681,20 +719,25 @@ def _actuator_force(
|
||||
elif gaintype == GainType.AFFINE:
|
||||
gain = gainprm[0] + gainprm[1] * length + gainprm[2] * velocity
|
||||
elif gaintype == GainType.MUSCLE:
|
||||
acc0 = actuator_acc0[uid]
|
||||
lengthrange = actuator_lengthrange[uid]
|
||||
acc0 = actuator_acc0[worldid % actuator_acc0.shape[0], uid]
|
||||
lengthrange = actuator_lengthrange[
|
||||
worldid % actuator_lengthrange.shape[0], uid
|
||||
]
|
||||
gain = util_misc.muscle_gain(length, velocity, lengthrange, acc0, gainprm)
|
||||
# GainType.USER: gain stays 0, modified by act_gain_callback
|
||||
|
||||
# bias
|
||||
biastype = actuator_biastype[uid]
|
||||
biasprm = actuator_biasprm[worldid % actuator_biasprm.shape[0], uid]
|
||||
|
||||
bias = 0.0 # BiasType.NONE
|
||||
bias = 0.0 # BiasType.NONE or BiasType.USER (modified by act_bias_callback)
|
||||
if biastype == BiasType.AFFINE:
|
||||
bias = biasprm[0] + biasprm[1] * length + biasprm[2] * velocity
|
||||
elif biastype == BiasType.MUSCLE:
|
||||
acc0 = actuator_acc0[uid]
|
||||
lengthrange = actuator_lengthrange[uid]
|
||||
acc0 = actuator_acc0[worldid % actuator_acc0.shape[0], uid]
|
||||
lengthrange = actuator_lengthrange[
|
||||
worldid % actuator_lengthrange.shape[0], uid
|
||||
]
|
||||
bias = util_misc.muscle_bias(length, lengthrange, acc0, biasprm)
|
||||
|
||||
force = gain * ctrl_act + bias
|
||||
@@ -752,32 +795,54 @@ def _tendon_actuator_force_clamp(
|
||||
|
||||
@wp.kernel
|
||||
def _qfrc_actuator(
|
||||
# Model:
|
||||
nu: int,
|
||||
ngravcomp: int,
|
||||
jnt_actfrclimited: wp.array(dtype=bool),
|
||||
jnt_actgravcomp: wp.array(dtype=int),
|
||||
jnt_actfrcrange: wp.array2d(dtype=wp.vec2),
|
||||
dof_jntid: wp.array(dtype=int),
|
||||
# Data in:
|
||||
actuator_moment_in: wp.array3d(dtype=float),
|
||||
qfrc_gravcomp_in: wp.array2d(dtype=float),
|
||||
actuator_force_in: wp.array2d(dtype=float),
|
||||
# Data out:
|
||||
qfrc_actuator_out: wp.array2d(dtype=float),
|
||||
# Data in:
|
||||
moment_rownnz_in: wp.array2d(dtype=int),
|
||||
moment_rowadr_in: wp.array2d(dtype=int),
|
||||
moment_colind_in: wp.array2d(dtype=int),
|
||||
actuator_moment_in: wp.array2d(dtype=float),
|
||||
actuator_force_in: wp.array2d(dtype=float),
|
||||
# Data out:
|
||||
qfrc_actuator_out: wp.array2d(dtype=float),
|
||||
):
|
||||
worldid, actid = wp.tid()
|
||||
|
||||
rownnz = moment_rownnz_in[worldid, actid]
|
||||
rowadr = moment_rowadr_in[worldid, actid]
|
||||
|
||||
for i in range(rownnz):
|
||||
sparseid = rowadr + i
|
||||
colind = moment_colind_in[worldid, sparseid]
|
||||
qfrc = (
|
||||
actuator_moment_in[worldid, sparseid]
|
||||
* actuator_force_in[worldid, actid]
|
||||
)
|
||||
wp.atomic_add(qfrc_actuator_out[worldid], colind, qfrc)
|
||||
|
||||
|
||||
@wp.kernel
|
||||
def _qfrc_actuator_gravcomp_limits(
|
||||
# Model:
|
||||
ngravcomp: int,
|
||||
jnt_actfrclimited: wp.array(dtype=bool),
|
||||
jnt_actgravcomp: wp.array(dtype=int),
|
||||
jnt_actfrcrange: wp.array2d(dtype=wp.vec2),
|
||||
dof_jntid: wp.array(dtype=int),
|
||||
# Data in:
|
||||
qfrc_gravcomp_in: wp.array2d(dtype=float),
|
||||
qfrc_actuator_in: wp.array2d(dtype=float),
|
||||
# Data out:
|
||||
qfrc_actuator_out: wp.array2d(dtype=float),
|
||||
):
|
||||
worldid, dofid = wp.tid()
|
||||
|
||||
qfrc = float(0.0)
|
||||
for uid in range(nu):
|
||||
qfrc += actuator_moment_in[worldid, uid, dofid] * actuator_force_in[worldid, uid]
|
||||
|
||||
jntid = dof_jntid[dofid]
|
||||
|
||||
qfrc = qfrc_actuator_in[worldid, dofid]
|
||||
|
||||
# actuator-level gravity compensation, skip if added as passive force
|
||||
if ngravcomp and jnt_actgravcomp[jntid]:
|
||||
qfrc += qfrc_gravcomp_in[worldid, dofid]
|
||||
|
||||
# limits
|
||||
if jnt_actfrclimited[jntid]:
|
||||
frcrange = jnt_actfrcrange[worldid % jnt_actfrcrange.shape[0], jntid]
|
||||
qfrc = wp.clamp(qfrc, frcrange[0], frcrange[1])
|
||||
@@ -825,6 +890,13 @@ def fwd_actuation(m: Model, d: Data):
|
||||
outputs=[d.act_dot, d.actuator_force],
|
||||
)
|
||||
|
||||
if m.callback.act_dyn:
|
||||
m.callback.act_dyn(m, d)
|
||||
if m.callback.act_gain:
|
||||
m.callback.act_gain(m, d)
|
||||
if m.callback.act_bias:
|
||||
m.callback.act_bias(m, d)
|
||||
|
||||
if m.ntendon:
|
||||
# total actuator force at tendon
|
||||
ten_actfrc = wp.zeros((d.nworld, m.ntendon), dtype=float)
|
||||
@@ -842,21 +914,33 @@ def fwd_actuation(m: Model, d: Data):
|
||||
outputs=[d.actuator_force],
|
||||
)
|
||||
|
||||
# TODO(team): optimize performance
|
||||
d.qfrc_actuator.zero_()
|
||||
wp.launch(
|
||||
_qfrc_actuator,
|
||||
dim=(d.nworld, m.nv),
|
||||
inputs=[
|
||||
m.nu,
|
||||
m.ngravcomp,
|
||||
m.jnt_actfrclimited,
|
||||
m.jnt_actgravcomp,
|
||||
m.jnt_actfrcrange,
|
||||
m.dof_jntid,
|
||||
d.actuator_moment,
|
||||
d.qfrc_gravcomp,
|
||||
d.actuator_force,
|
||||
],
|
||||
outputs=[d.qfrc_actuator],
|
||||
_qfrc_actuator,
|
||||
dim=(d.nworld, m.nu),
|
||||
inputs=[
|
||||
d.moment_rownnz,
|
||||
d.moment_rowadr,
|
||||
d.moment_colind,
|
||||
d.actuator_moment,
|
||||
d.actuator_force,
|
||||
],
|
||||
outputs=[d.qfrc_actuator],
|
||||
)
|
||||
wp.launch(
|
||||
_qfrc_actuator_gravcomp_limits,
|
||||
dim=(d.nworld, m.nv),
|
||||
inputs=[
|
||||
m.ngravcomp,
|
||||
m.jnt_actfrclimited,
|
||||
m.jnt_actgravcomp,
|
||||
m.jnt_actfrcrange,
|
||||
m.dof_jntid,
|
||||
d.qfrc_gravcomp,
|
||||
d.qfrc_actuator,
|
||||
],
|
||||
outputs=[d.qfrc_actuator],
|
||||
)
|
||||
|
||||
|
||||
@@ -923,6 +1007,9 @@ def forward(m: Model, d: Data):
|
||||
if m.sensor_e_kinetic == 0: # not computed by sensor
|
||||
sensor.energy_vel(m, d)
|
||||
|
||||
if not (m.opt.disableflags & DisableBit.ACTUATION):
|
||||
if m.callback.control:
|
||||
m.callback.control(m, d)
|
||||
fwd_actuation(m, d)
|
||||
fwd_acceleration(m, d, factorize=True)
|
||||
|
||||
@@ -971,6 +1058,10 @@ def step1(m: Model, d: Data):
|
||||
if m.sensor_e_kinetic == 0: # not computed by sensor
|
||||
sensor.energy_vel(m, d)
|
||||
|
||||
if not (m.opt.disableflags & DisableBit.ACTUATION):
|
||||
if m.callback.control:
|
||||
m.callback.control(m, d)
|
||||
|
||||
|
||||
@event_scope
|
||||
def step2(m: Model, d: Data):
|
||||
|
||||
+502
-186
@@ -14,32 +14,24 @@
|
||||
# ==============================================================================
|
||||
|
||||
import dataclasses
|
||||
import importlib.metadata
|
||||
import warnings
|
||||
from typing import Any, Optional, Sequence
|
||||
import warnings
|
||||
|
||||
import mujoco
|
||||
import numpy as np
|
||||
import packaging.version
|
||||
import warp as wp
|
||||
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import bvh
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import math as mjmath
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import render_util
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import smooth
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import types
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import warp_util
|
||||
|
||||
|
||||
def _is_mujoco_dev() -> bool:
|
||||
"""Checks if mujoco version is > 3.4.0."""
|
||||
version_str = getattr(mujoco, "__version__", None)
|
||||
if not version_str:
|
||||
version_str = importlib.metadata.version("mujoco")
|
||||
version_str = version_str.split("-")[0].split(".dev")[0]
|
||||
return packaging.version.parse(version_str) > packaging.version.parse("3.4.0")
|
||||
|
||||
|
||||
BLEEDING_EDGE_MUJOCO = _is_mujoco_dev()
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import BiasType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MINVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import SPARSE_CONSTRAINT_JACOBIAN
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import TrnType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import vec10
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.util_pkg import check_version
|
||||
import numpy as np
|
||||
import warp as wp
|
||||
|
||||
|
||||
def _create_array(data: Any, spec: wp.array, sizes: dict[str, int]) -> wp.array | None:
|
||||
@@ -218,6 +210,7 @@ def put_model(mjm: mujoco.MjModel) -> types.Model:
|
||||
|
||||
m.opt = opt
|
||||
m.stat = stat
|
||||
m.callback = types.Callback()
|
||||
|
||||
m.nv_pad = _get_padded_sizes(
|
||||
mjm.nv, 0, is_sparse(mjm), types.TILE_SIZE_JTDAJ_SPARSE if is_sparse(mjm) else types.TILE_SIZE_JTDAJ_DENSE
|
||||
@@ -585,17 +578,9 @@ def put_model(mjm: mujoco.MjModel) -> types.Model:
|
||||
m.qM_mulm_madr.append(madr)
|
||||
m.qM_mulm_rowadr.append(len(m.qM_mulm_col))
|
||||
|
||||
# TODO(team): remove after mjwarp depends on mujoco > 3.4.0 in pyproject.toml
|
||||
if BLEEDING_EDGE_MUJOCO:
|
||||
m.flexedge_J_rownnz = mjm.flexedge_J_rownnz
|
||||
m.flexedge_J_rowadr = mjm.flexedge_J_rowadr
|
||||
m.flexedge_J_colind = mjm.flexedge_J_colind.reshape(-1)
|
||||
else:
|
||||
mjd = mujoco.MjData(mjm)
|
||||
mujoco.mj_forward(mjm, mjd)
|
||||
m.flexedge_J_rownnz = mjd.flexedge_J_rownnz
|
||||
m.flexedge_J_rowadr = mjd.flexedge_J_rowadr
|
||||
m.flexedge_J_colind = mjd.flexedge_J_colind.reshape(-1)
|
||||
m.flexedge_J_rownnz = mjm.flexedge_J_rownnz
|
||||
m.flexedge_J_rowadr = mjm.flexedge_J_rowadr
|
||||
m.flexedge_J_colind = mjm.flexedge_J_colind.reshape(-1)
|
||||
|
||||
# place m on device
|
||||
sizes = dict({"*": 1}, **{f.name: getattr(m, f.name) for f in dataclasses.fields(types.Model) if f.type is int})
|
||||
@@ -646,6 +631,16 @@ def _default_njmax(mjm: mujoco.MjModel, mjd: Optional[mujoco.MjData] = None) ->
|
||||
return int(valid_sizes[np.searchsorted(valid_sizes, njmax)])
|
||||
|
||||
|
||||
def _resolve_batch_size(
|
||||
na: int | None, n: int | None, nworld: int, default: int
|
||||
) -> int:
|
||||
if na is not None:
|
||||
return na
|
||||
if n is not None:
|
||||
return n * nworld
|
||||
return default
|
||||
|
||||
|
||||
def make_data(
|
||||
mjm: mujoco.MjModel,
|
||||
nworld: int = 1,
|
||||
@@ -675,37 +670,36 @@ def make_data(
|
||||
if nconmax is None:
|
||||
nconmax = _default_nconmax(mjm)
|
||||
|
||||
if nconmax < 0:
|
||||
raise ValueError("nconmax must be >= 0")
|
||||
|
||||
if nccdmax is None:
|
||||
nccdmax = nconmax
|
||||
elif nccdmax < 0:
|
||||
raise ValueError("nccdmax must be >= 0")
|
||||
elif nccdmax > nconmax:
|
||||
raise ValueError(f"nccdmax ({nccdmax}) must be <= nconmax ({nconmax})")
|
||||
|
||||
if njmax is None:
|
||||
njmax = _default_njmax(mjm)
|
||||
|
||||
if nconmax < 0:
|
||||
raise ValueError("nconmax must be >= 0")
|
||||
|
||||
if njmax < 0:
|
||||
raise ValueError("njmax must be >= 0")
|
||||
|
||||
if nworld < 1:
|
||||
raise ValueError(f"nworld must be >= 1")
|
||||
|
||||
if naconmax is None:
|
||||
naconmax = nworld * nconmax
|
||||
elif naconmax < 0:
|
||||
naconmax = _resolve_batch_size(naconmax, nconmax, nworld, 0)
|
||||
if naconmax < 0:
|
||||
raise ValueError("naconmax must be >= 0")
|
||||
|
||||
if naccdmax is None:
|
||||
naccdmax = nworld * nccdmax
|
||||
elif naccdmax < 0:
|
||||
naccdmax = _resolve_batch_size(naccdmax, nccdmax, nworld, naconmax)
|
||||
if naccdmax < 0:
|
||||
raise ValueError("naccdmax must be >= 0")
|
||||
elif naccdmax > naconmax:
|
||||
raise ValueError(f"naccdmax ({naccdmax}) must be <= naconmax ({naconmax})")
|
||||
|
||||
if nccdmax is None:
|
||||
nccdmax = nconmax
|
||||
else:
|
||||
if nccdmax < 0:
|
||||
raise ValueError("nccdmax must be >= 0")
|
||||
elif nccdmax > nconmax:
|
||||
raise ValueError(f"nccdmax ({nccdmax}) must be <= nconmax ({nconmax})")
|
||||
|
||||
sizes = dict({"*": 1}, **{f.name: getattr(mjm, f.name, None) for f in dataclasses.fields(types.Model) if f.type is int})
|
||||
sizes["nmaxcondim"] = np.concatenate(([0], mjm.geom_condim, mjm.pair_dim)).max()
|
||||
sizes["nmaxpyramid"] = np.maximum(1, 2 * (sizes["nmaxcondim"] - 1))
|
||||
@@ -718,6 +712,17 @@ def make_data(
|
||||
contact = types.Contact(**{f.name: _create_array(None, f.type, sizes) for f in dataclasses.fields(types.Contact)})
|
||||
efc = types.Constraint(**{f.name: _create_array(None, f.type, sizes) for f in dataclasses.fields(types.Constraint)})
|
||||
|
||||
if SPARSE_CONSTRAINT_JACOBIAN:
|
||||
efc.J_rownnz = wp.zeros((nworld, njmax), dtype=int)
|
||||
efc.J_rowadr = wp.zeros((nworld, njmax), dtype=int)
|
||||
efc.J_colind = wp.zeros((nworld, 1, njmax * mjm.nv), dtype=int)
|
||||
efc.J = wp.zeros((nworld, 1, njmax * mjm.nv), dtype=float)
|
||||
else:
|
||||
efc.J_rownnz = wp.zeros((nworld, 0), dtype=int)
|
||||
efc.J_rowadr = wp.zeros((nworld, 0), dtype=int)
|
||||
efc.J_colind = wp.zeros((nworld, 0, 0), dtype=int)
|
||||
efc.J = wp.zeros((nworld, sizes["njmax_pad"], sizes["nv_pad"]), dtype=float)
|
||||
|
||||
# world body and static geom (attached to the world) poses are precomputed
|
||||
# this speeds up scenes with many static geoms (e.g. terrains)
|
||||
# TODO(team): remove this when we introduce dof islands + sleeping
|
||||
@@ -729,31 +734,65 @@ def make_data(
|
||||
mocap_id = mjm.body_mocapid[mocap_body]
|
||||
|
||||
d_kwargs = {
|
||||
"qpos": wp.array(np.tile(mjm.qpos0, nworld), shape=(nworld, mjm.nq), dtype=float),
|
||||
"contact": contact,
|
||||
"efc": efc,
|
||||
"nworld": nworld,
|
||||
"naconmax": naconmax,
|
||||
"naccdmax": naccdmax,
|
||||
"njmax": njmax,
|
||||
"qM": None,
|
||||
"qLD": None,
|
||||
# world body
|
||||
"xquat": wp.array(np.tile(mjd.xquat, (nworld, 1)), shape=(nworld, mjm.nbody), dtype=wp.quat),
|
||||
"xmat": wp.array(np.tile(mjd.xmat, (nworld, 1)), shape=(nworld, mjm.nbody), dtype=wp.mat33),
|
||||
"ximat": wp.array(np.tile(mjd.ximat, (nworld, 1)), shape=(nworld, mjm.nbody), dtype=wp.mat33),
|
||||
# static geoms
|
||||
"geom_xpos": wp.array(np.tile(mjd.geom_xpos, (nworld, 1)), shape=(nworld, mjm.ngeom), dtype=wp.vec3),
|
||||
"geom_xmat": wp.array(np.tile(mjd.geom_xmat, (nworld, 1)), shape=(nworld, mjm.ngeom), dtype=wp.mat33),
|
||||
# mocap
|
||||
"mocap_pos": wp.array(np.tile(mjm.body_pos[mocap_body[mocap_id]], (nworld, 1)), shape=(nworld, mjm.nmocap), dtype=wp.vec3),
|
||||
"mocap_quat": wp.array(
|
||||
np.tile(mjm.body_quat[mocap_body[mocap_id]], (nworld, 1)), shape=(nworld, mjm.nmocap), dtype=wp.quat
|
||||
),
|
||||
# equality constraints
|
||||
"eq_active": wp.array(np.tile(mjm.eq_active0.astype(bool), (nworld, 1)), shape=(nworld, mjm.neq), dtype=bool),
|
||||
# flexedge
|
||||
"flexedge_J": None,
|
||||
"qpos": wp.array(
|
||||
np.tile(mjm.qpos0, nworld), shape=(nworld, mjm.nq), dtype=float
|
||||
),
|
||||
"contact": contact,
|
||||
"efc": efc,
|
||||
"nworld": nworld,
|
||||
"naconmax": naconmax,
|
||||
"naccdmax": naccdmax,
|
||||
"njmax": njmax,
|
||||
"njmax_pad": sizes["njmax_pad"],
|
||||
"qM": None,
|
||||
"qLD": None,
|
||||
# world body
|
||||
"xquat": wp.array(
|
||||
np.tile(mjd.xquat, (nworld, 1)),
|
||||
shape=(nworld, mjm.nbody),
|
||||
dtype=wp.quat,
|
||||
),
|
||||
"xmat": wp.array(
|
||||
np.tile(mjd.xmat, (nworld, 1)),
|
||||
shape=(nworld, mjm.nbody),
|
||||
dtype=wp.mat33,
|
||||
),
|
||||
"ximat": wp.array(
|
||||
np.tile(mjd.ximat, (nworld, 1)),
|
||||
shape=(nworld, mjm.nbody),
|
||||
dtype=wp.mat33,
|
||||
),
|
||||
# static geoms
|
||||
"geom_xpos": wp.array(
|
||||
np.tile(mjd.geom_xpos, (nworld, 1)),
|
||||
shape=(nworld, mjm.ngeom),
|
||||
dtype=wp.vec3,
|
||||
),
|
||||
"geom_xmat": wp.array(
|
||||
np.tile(mjd.geom_xmat, (nworld, 1)),
|
||||
shape=(nworld, mjm.ngeom),
|
||||
dtype=wp.mat33,
|
||||
),
|
||||
# mocap
|
||||
"mocap_pos": wp.array(
|
||||
np.tile(mjm.body_pos[mocap_body[mocap_id]], (nworld, 1)),
|
||||
shape=(nworld, mjm.nmocap),
|
||||
dtype=wp.vec3,
|
||||
),
|
||||
"mocap_quat": wp.array(
|
||||
np.tile(mjm.body_quat[mocap_body[mocap_id]], (nworld, 1)),
|
||||
shape=(nworld, mjm.nmocap),
|
||||
dtype=wp.quat,
|
||||
),
|
||||
# equality constraints
|
||||
"eq_active": wp.array(
|
||||
np.tile(mjm.eq_active0.astype(bool), (nworld, 1)),
|
||||
shape=(nworld, mjm.neq),
|
||||
dtype=bool,
|
||||
),
|
||||
# island arrays
|
||||
"nisland": None,
|
||||
"tree_island": None,
|
||||
}
|
||||
for f in dataclasses.fields(types.Data):
|
||||
if f.name in d_kwargs:
|
||||
@@ -769,7 +808,9 @@ def make_data(
|
||||
d.qM = wp.zeros((nworld, sizes["nv_pad"], sizes["nv_pad"]), dtype=float)
|
||||
d.qLD = wp.zeros((nworld, mjm.nv, mjm.nv), dtype=float)
|
||||
|
||||
d.flexedge_J = wp.zeros((nworld, 1, mjd.flexedge_J.size), dtype=float)
|
||||
# island discovery arrays
|
||||
d.nisland = wp.zeros((nworld,), dtype=int)
|
||||
d.tree_island = wp.zeros((nworld, mjm.ntree), dtype=int)
|
||||
|
||||
return d
|
||||
|
||||
@@ -808,39 +849,43 @@ def put_data(
|
||||
if nconmax is None:
|
||||
nconmax = _default_nconmax(mjm, mjd)
|
||||
|
||||
if nconmax < 0:
|
||||
raise ValueError("nconmax must be >= 0")
|
||||
|
||||
if nccdmax is None:
|
||||
nccdmax = nconmax
|
||||
elif nccdmax < 0:
|
||||
raise ValueError("nccdmax must be >= 0")
|
||||
elif nccdmax > nconmax:
|
||||
raise ValueError(f"nccdmax ({nccdmax}) must be <= nconmax ({nconmax})")
|
||||
|
||||
if njmax is None:
|
||||
njmax = _default_njmax(mjm, mjd)
|
||||
|
||||
if nconmax < 0:
|
||||
raise ValueError("nconmax must be >= 0")
|
||||
|
||||
if njmax < 0:
|
||||
raise ValueError("njmax must be >= 0")
|
||||
|
||||
if nworld < 1:
|
||||
raise ValueError(f"nworld must be >= 1")
|
||||
|
||||
if naconmax is None:
|
||||
if mjd.ncon > nconmax:
|
||||
raise ValueError(f"nconmax overflow (nconmax must be >= {mjd.ncon})")
|
||||
naconmax = nworld * nconmax
|
||||
naconmax_is_input = naconmax is not None
|
||||
naconmax = _resolve_batch_size(naconmax, nconmax, nworld, 0)
|
||||
if naconmax < 0:
|
||||
raise ValueError("naconmax must be >= 0")
|
||||
|
||||
if not naconmax_is_input and mjd.ncon > nconmax:
|
||||
raise ValueError(f"nconmax overflow (nconmax must be >= {mjd.ncon})")
|
||||
elif naconmax < mjd.ncon * nworld:
|
||||
raise ValueError(f"naconmax overflow (naconmax must be >= {mjd.ncon * nworld})")
|
||||
|
||||
if naccdmax is None:
|
||||
naccdmax = nworld * nccdmax
|
||||
elif naccdmax < 0:
|
||||
naccdmax = _resolve_batch_size(naccdmax, nccdmax, nworld, naconmax)
|
||||
|
||||
if naccdmax < 0:
|
||||
raise ValueError("naccdmax must be >= 0")
|
||||
elif naccdmax > naconmax:
|
||||
raise ValueError(f"naccdmax ({naccdmax}) must be <= naconmax ({naconmax})")
|
||||
|
||||
if nccdmax is None:
|
||||
nccdmax = nconmax
|
||||
else:
|
||||
if nccdmax < 0:
|
||||
raise ValueError("nccdmax must be >= 0")
|
||||
elif nccdmax > nconmax:
|
||||
raise ValueError(f"nccdmax ({nccdmax}) must be <= nconmax ({nconmax})")
|
||||
|
||||
if mjd.nefc > njmax:
|
||||
raise ValueError(f"njmax overflow (njmax must be >= {mjd.nefc})")
|
||||
|
||||
@@ -887,7 +932,7 @@ def put_data(
|
||||
contact.geomcollisionid = wp.empty((naconmax,), dtype=int) # TODO(team): set values
|
||||
|
||||
# create efc
|
||||
efc_kwargs = {"J": None}
|
||||
efc_kwargs = {"J_rownnz": None, "J_rowadr": None, "J_colind": None, "J": None}
|
||||
|
||||
for f in dataclasses.fields(types.Constraint):
|
||||
if f.name in efc_kwargs:
|
||||
@@ -900,31 +945,82 @@ def put_data(
|
||||
|
||||
efc = types.Constraint(**efc_kwargs)
|
||||
|
||||
if mujoco.mj_isSparse(mjm):
|
||||
efc_j = np.zeros((mjd.nefc, mjm.nv))
|
||||
mujoco.mju_sparse2dense(efc_j, mjd.efc_J, mjd.efc_J_rownnz, mjd.efc_J_rowadr, mjd.efc_J_colind)
|
||||
if SPARSE_CONSTRAINT_JACOBIAN:
|
||||
# TODO(team): process efc_J sparsity structure for nv row shift
|
||||
efc.J_rownnz = wp.array(
|
||||
np.full((nworld, njmax), mjm.nv, dtype=int), dtype=int
|
||||
)
|
||||
efc.J_rowadr = wp.array(
|
||||
np.tile(
|
||||
np.arange(0, njmax * mjm.nv, mjm.nv)
|
||||
if mjm.nv
|
||||
else np.zeros(njmax, dtype=int),
|
||||
(nworld, 1),
|
||||
),
|
||||
dtype=int,
|
||||
)
|
||||
efc.J_colind = wp.array(
|
||||
np.tile(np.arange(mjm.nv), (nworld, njmax)).reshape((nworld, 1, -1)),
|
||||
dtype=int,
|
||||
)
|
||||
|
||||
mj_efc_J = np.zeros((mjd.nefc, mjm.nv))
|
||||
if mjd.nefc:
|
||||
if mujoco.mj_isSparse(mjm):
|
||||
mujoco.mju_sparse2dense(
|
||||
mj_efc_J,
|
||||
mjd.efc_J,
|
||||
mjd.efc_J_rownnz,
|
||||
mjd.efc_J_rowadr,
|
||||
mjd.efc_J_colind,
|
||||
)
|
||||
else:
|
||||
mj_efc_J = mjd.efc_J.reshape((mjd.nefc, mjm.nv))
|
||||
efc_J = np.zeros((njmax, mjm.nv), dtype=float)
|
||||
efc_J[: mjd.nefc, : mjm.nv] = mj_efc_J
|
||||
efc.J = wp.array(
|
||||
np.tile(efc_J.reshape(-1), (nworld, 1, 1)).reshape((nworld, 1, -1)),
|
||||
dtype=float,
|
||||
)
|
||||
else:
|
||||
efc_j = mjd.efc_J.reshape((mjd.nefc, mjm.nv))
|
||||
efc.J = np.zeros((nworld, sizes["njmax_pad"], sizes["nv_pad"]), dtype=f.type.dtype)
|
||||
efc.J[:, : mjd.nefc, : mjm.nv] = np.tile(efc_j, (nworld, 1, 1))
|
||||
efc.J = wp.array(efc.J, dtype=float)
|
||||
efc.J_rownnz = wp.zeros((nworld, 0), dtype=int)
|
||||
efc.J_rowadr = wp.zeros((nworld, 0), dtype=int)
|
||||
efc.J_colind = wp.zeros((nworld, 0, 0), dtype=int)
|
||||
|
||||
mj_efc_J = np.zeros((mjd.nefc, mjm.nv))
|
||||
if mjd.nefc:
|
||||
if mujoco.mj_isSparse(mjm):
|
||||
mujoco.mju_sparse2dense(
|
||||
mj_efc_J,
|
||||
mjd.efc_J,
|
||||
mjd.efc_J_rownnz,
|
||||
mjd.efc_J_rowadr,
|
||||
mjd.efc_J_colind,
|
||||
)
|
||||
else:
|
||||
mj_efc_J = mjd.efc_J.reshape((mjd.nefc, mjm.nv))
|
||||
efc_J = np.zeros((nworld, sizes["njmax_pad"], sizes["nv_pad"]), dtype=float)
|
||||
efc_J[:, : mjd.nefc, : mjm.nv] = np.tile(mj_efc_J, (nworld, 1, 1))
|
||||
efc.J = wp.array(efc_J, dtype=float)
|
||||
|
||||
# create data
|
||||
d_kwargs = {
|
||||
"contact": contact,
|
||||
"efc": efc,
|
||||
"nworld": nworld,
|
||||
"naconmax": naconmax,
|
||||
"naccdmax": naccdmax,
|
||||
"njmax": njmax,
|
||||
# fields set after initialization:
|
||||
"solver_niter": None,
|
||||
"qM": None,
|
||||
"qLD": None,
|
||||
"ten_J": None,
|
||||
"actuator_moment": None,
|
||||
"flexedge_J": None,
|
||||
"nacon": None,
|
||||
"contact": contact,
|
||||
"efc": efc,
|
||||
"nworld": nworld,
|
||||
"naconmax": naconmax,
|
||||
"naccdmax": naccdmax,
|
||||
"njmax": njmax,
|
||||
"njmax_pad": sizes["njmax_pad"],
|
||||
# fields set after initialization:
|
||||
"solver_niter": None,
|
||||
"qM": None,
|
||||
"qLD": None,
|
||||
"ten_J": None,
|
||||
"nacon": None,
|
||||
# island arrays
|
||||
"nisland": None,
|
||||
"tree_island": None,
|
||||
}
|
||||
for f in dataclasses.fields(types.Data):
|
||||
if f.name in d_kwargs:
|
||||
@@ -950,19 +1046,32 @@ def put_data(
|
||||
d.qM = wp.array(np.full((nworld, sizes["nv_pad"], sizes["nv_pad"]), qM_padded), dtype=float)
|
||||
d.qLD = wp.array(np.full((nworld, mjm.nv, mjm.nv), qLD), dtype=float)
|
||||
|
||||
d.flexedge_J = wp.array(np.tile(mjd.flexedge_J.reshape(-1), (nworld, 1)).reshape((nworld, 1, -1)), dtype=float)
|
||||
# island arrays
|
||||
d.nisland = wp.array(np.full(nworld, mjd.nisland), dtype=int)
|
||||
d.tree_island = wp.array(np.tile(mjd.tree_island, (nworld, 1)), dtype=int)
|
||||
|
||||
if mjm.ntendon:
|
||||
ten_J = np.zeros((mjm.ntendon, mjm.nv))
|
||||
mujoco.mju_sparse2dense(ten_J, mjd.ten_J.reshape(-1), mjm.ten_J_rownnz, mjm.ten_J_rowadr, mjm.ten_J_colind.reshape(-1))
|
||||
d.ten_J = wp.array(np.full((nworld, mjm.ntendon, mjm.nv), ten_J), dtype=float)
|
||||
ten_J = np.zeros((mjm.ntendon, mjm.nv))
|
||||
if mujoco.mj_isSparse(mjm) or check_version("mujoco>=3.5.1.dev872479828"):
|
||||
if mjm.ntendon:
|
||||
if check_version("mujoco>=3.5.1.dev875093374"):
|
||||
mujoco.mju_sparse2dense(
|
||||
ten_J,
|
||||
mjd.ten_J.reshape(-1),
|
||||
mjm.ten_J_rownnz,
|
||||
mjm.ten_J_rowadr,
|
||||
mjm.ten_J_colind.reshape(-1),
|
||||
)
|
||||
else:
|
||||
mujoco.mju_sparse2dense(
|
||||
ten_J,
|
||||
mjd.ten_J.reshape(-1),
|
||||
mjd.ten_J_rownnz,
|
||||
mjd.ten_J_rowadr,
|
||||
mjd.ten_J_colind.reshape(-1),
|
||||
)
|
||||
else:
|
||||
d.ten_J = wp.array(np.full((nworld, mjm.ntendon, mjm.nv), 0.0), dtype=float)
|
||||
|
||||
# TODO(taylorhowell): sparse actuator_moment
|
||||
actuator_moment = np.zeros((mjm.nu, mjm.nv))
|
||||
mujoco.mju_sparse2dense(actuator_moment, mjd.actuator_moment, mjd.moment_rownnz, mjd.moment_rowadr, mjd.moment_colind)
|
||||
d.actuator_moment = wp.array(np.full((nworld, mjm.nu, mjm.nv), actuator_moment), dtype=float)
|
||||
ten_J = mjd.ten_J.reshape((mjm.ntendon, mjm.nv))
|
||||
d.ten_J = wp.array(np.full((nworld, mjm.ntendon, mjm.nv), ten_J), dtype=float)
|
||||
|
||||
d.nacon = wp.array([mjd.ncon * nworld], dtype=int)
|
||||
|
||||
@@ -1066,28 +1175,15 @@ def get_data_into(
|
||||
result.cinert[:] = d.cinert.numpy()[world_id]
|
||||
result.flexvert_xpos[:] = d.flexvert_xpos.numpy()[world_id]
|
||||
if mjm.nflexedge > 0:
|
||||
# TODO(team): remove after mjwarp depends on mujoco > 3.4.0 in pyproject.toml
|
||||
if not BLEEDING_EDGE_MUJOCO:
|
||||
m = put_model(mjm)
|
||||
result.flexedge_J_rownnz[:] = m.flexedge_J_rownnz.numpy()
|
||||
result.flexedge_J_rowadr[:] = m.flexedge_J_rowadr.numpy()
|
||||
result.flexedge_J_colind[:, :] = m.flexedge_J_colind.numpy().reshape((mjm.nflexedge, mjm.nv))
|
||||
mujoco.mju_sparse2dense(
|
||||
result.flexedge_J,
|
||||
d.flexedge_J.numpy()[world_id].reshape(-1),
|
||||
m.flexedge_J_rownnz.numpy(),
|
||||
m.flexedge_J_rowadr.numpy(),
|
||||
m.flexedge_J_colind.numpy(),
|
||||
)
|
||||
else:
|
||||
result.flexedge_J[:] = d.flexedge_J.numpy()[world_id].reshape(-1)
|
||||
result.flexedge_J[:] = d.flexedge_J.numpy()[world_id].reshape(-1)
|
||||
result.flexedge_length[:] = d.flexedge_length.numpy()[world_id]
|
||||
result.flexedge_velocity[:] = d.flexedge_velocity.numpy()[world_id]
|
||||
result.actuator_length[:] = d.actuator_length.numpy()[world_id]
|
||||
actuator_moment = d.actuator_moment.numpy()[world_id]
|
||||
mujoco.mju_dense2sparse(
|
||||
result.actuator_moment, actuator_moment, result.moment_rownnz, result.moment_rowadr, result.moment_colind
|
||||
)
|
||||
result.moment_rownnz[:] = d.moment_rownnz.numpy()[world_id]
|
||||
result.moment_rowadr[:] = d.moment_rowadr.numpy()[world_id]
|
||||
if mjm.nu:
|
||||
result.moment_colind[:] = d.moment_colind.numpy()[world_id]
|
||||
result.actuator_moment[:] = d.actuator_moment.numpy()[world_id]
|
||||
result.crb[:] = d.crb.numpy()[world_id]
|
||||
result.qLDiagInv[:] = d.qLDiagInv.numpy()[world_id]
|
||||
result.ten_velocity[:] = d.ten_velocity.numpy()[world_id]
|
||||
@@ -1137,11 +1233,29 @@ def get_data_into(
|
||||
mujoco.mj_factorM(mjm, result)
|
||||
|
||||
if nefc > 0:
|
||||
if mujoco.mj_isSparse(mjm):
|
||||
efc_J = d.efc.J.numpy()[world_id, efc_idx, : mjm.nv]
|
||||
mujoco.mju_dense2sparse(result.efc_J, efc_J, result.efc_J_rownnz, result.efc_J_rowadr, result.efc_J_colind)
|
||||
if SPARSE_CONSTRAINT_JACOBIAN:
|
||||
efc_J = np.zeros((nefc, mjm.nv))
|
||||
mujoco.mju_sparse2dense(
|
||||
efc_J,
|
||||
d.efc.J.numpy()[world_id, 0],
|
||||
d.efc.J_rownnz.numpy()[world_id, :nefc],
|
||||
d.efc.J_rowadr.numpy()[world_id, :nefc],
|
||||
d.efc.J_colind.numpy()[world_id, 0],
|
||||
)
|
||||
else:
|
||||
result.efc_J[: nefc * mjm.nv] = d.efc.J.numpy()[world_id, :nefc, : mjm.nv].flatten()
|
||||
efc_J = d.efc.J.numpy()[world_id, :nefc, : mjm.nv]
|
||||
|
||||
# write to mujoco result (format depends on mj_isSparse)
|
||||
if mujoco.mj_isSparse(mjm):
|
||||
mujoco.mju_dense2sparse(
|
||||
result.efc_J,
|
||||
efc_J[efc_idx],
|
||||
result.efc_J_rownnz,
|
||||
result.efc_J_rowadr,
|
||||
result.efc_J_colind,
|
||||
)
|
||||
else:
|
||||
result.efc_J[: nefc * mjm.nv] = efc_J[efc_idx].flatten()
|
||||
|
||||
# efc
|
||||
result.efc_type[:] = d.efc.type.numpy()[world_id, efc_idx]
|
||||
@@ -1162,15 +1276,22 @@ def get_data_into(
|
||||
|
||||
# tendon
|
||||
result.ten_length[:] = d.ten_length.numpy()[world_id]
|
||||
# TODO(team): remove after mjwarp depends on mujoco > 3.4.0 in pyproject.toml
|
||||
if BLEEDING_EDGE_MUJOCO:
|
||||
if check_version("mujoco>=3.5.1.dev869712136"):
|
||||
ten_J = d.ten_J.numpy()[world_id]
|
||||
if check_version("mujoco>=3.5.1.dev875093374"):
|
||||
ten_J_rownnz = mjm.ten_J_rownnz
|
||||
ten_J_rowadr = mjm.ten_J_rowadr
|
||||
ten_J_colind = mjm.ten_J_colind.reshape(-1)
|
||||
else:
|
||||
ten_J_rownnz = result.ten_J_rownnz
|
||||
ten_J_rowadr = result.ten_J_rowadr
|
||||
ten_J_colind = result.ten_J_colind.reshape(-1)
|
||||
mujoco.mju_dense2sparse(
|
||||
result.ten_J,
|
||||
ten_J,
|
||||
mjm.ten_J_rownnz,
|
||||
mjm.ten_J_rowadr,
|
||||
mjm.ten_J_colind,
|
||||
ten_J_rownnz,
|
||||
ten_J_rowadr,
|
||||
ten_J_colind,
|
||||
)
|
||||
else:
|
||||
result.ten_J[:] = d.ten_J.numpy()[world_id]
|
||||
@@ -1182,6 +1303,12 @@ def get_data_into(
|
||||
# sensors
|
||||
result.sensordata[:] = d.sensordata.numpy()[world_id]
|
||||
|
||||
# islands
|
||||
nisland = d.nisland.numpy()[world_id]
|
||||
result.nisland = nisland
|
||||
if nisland:
|
||||
result.tree_island[:] = d.tree_island.numpy()[world_id]
|
||||
|
||||
|
||||
def reset_data(m: types.Model, d: types.Data, reset: Optional[wp.array] = None):
|
||||
"""Clear data, set defaults; optionally by world.
|
||||
@@ -1301,8 +1428,12 @@ def reset_data(m: types.Model, d: types.Data, reset: Optional[wp.array] = None):
|
||||
mocapid = body_mocapid[bodyid]
|
||||
|
||||
if mocapid >= 0:
|
||||
mocap_pos_out[worldid, mocapid] = body_pos[worldid, bodyid]
|
||||
mocap_quat_out[worldid, mocapid] = body_quat[worldid, bodyid]
|
||||
mocap_pos_out[worldid, mocapid] = body_pos[
|
||||
worldid % body_pos.shape[0], bodyid
|
||||
]
|
||||
mocap_quat_out[worldid, mocapid] = body_quat[
|
||||
worldid % body_quat.shape[0], bodyid
|
||||
]
|
||||
|
||||
@wp.kernel(module="unique", enable_backward=False)
|
||||
def reset_contact(
|
||||
@@ -1760,28 +1891,140 @@ def _compute_light_pos0(
|
||||
|
||||
@wp.kernel
|
||||
def _copy_actuator_moment(
|
||||
actid_target: int,
|
||||
actuator_moment_in: wp.array3d(dtype=float),
|
||||
act_moment_vec_out: wp.array2d(dtype=float),
|
||||
actid_target: int,
|
||||
moment_rownnz_in: wp.array2d(dtype=int),
|
||||
moment_rowadr_in: wp.array2d(dtype=int),
|
||||
moment_colind_in: wp.array2d(dtype=int),
|
||||
actuator_moment_in: wp.array2d(dtype=float),
|
||||
act_moment_vec_out: wp.array2d(dtype=float),
|
||||
):
|
||||
worldid = wp.tid()
|
||||
nv = actuator_moment_in.shape[2]
|
||||
nv = act_moment_vec_out.shape[1]
|
||||
for i in range(nv):
|
||||
act_moment_vec_out[worldid, i] = actuator_moment_in[worldid, actid_target, i]
|
||||
act_moment_vec_out[worldid, i] = 0.0
|
||||
rownnz = moment_rownnz_in[worldid, actid_target]
|
||||
rowadr = moment_rowadr_in[worldid, actid_target]
|
||||
for i in range(rownnz):
|
||||
sparseid = rowadr + i
|
||||
col = moment_colind_in[worldid, sparseid]
|
||||
act_moment_vec_out[worldid, col] = actuator_moment_in[worldid, sparseid]
|
||||
|
||||
|
||||
@wp.kernel
|
||||
def _compute_actuator_acc0(
|
||||
actid_target: int,
|
||||
nv: int,
|
||||
result_vec_in: wp.array2d(dtype=float),
|
||||
actuator_acc0_out: wp.array(dtype=float),
|
||||
actid_target: int,
|
||||
nv: int,
|
||||
result_vec_in: wp.array2d(dtype=float),
|
||||
actuator_acc0_out: wp.array2d(dtype=float),
|
||||
):
|
||||
worldid = wp.tid()
|
||||
norm_sq = float(0.0)
|
||||
for i in range(nv):
|
||||
norm_sq += result_vec_in[worldid, i] * result_vec_in[worldid, i]
|
||||
actuator_acc0_out[actid_target] = wp.sqrt(norm_sq)
|
||||
actuator_acc0_out[worldid, actid_target] = wp.sqrt(norm_sq)
|
||||
|
||||
|
||||
@wp.kernel
|
||||
def _compute_dof_M0(
|
||||
dof_bodyid: wp.array(dtype=int),
|
||||
dof_armature: wp.array2d(dtype=float),
|
||||
cdof_in: wp.array2d(dtype=wp.spatial_vector),
|
||||
crb_in: wp.array2d(dtype=vec10),
|
||||
dof_M0_out: wp.array2d(dtype=float),
|
||||
):
|
||||
worldid, dofid = wp.tid()
|
||||
bodyid = dof_bodyid[dofid]
|
||||
armature = dof_armature[worldid % dof_armature.shape[0], dofid]
|
||||
buf = mjmath.inert_vec(crb_in[worldid, bodyid], cdof_in[worldid, dofid])
|
||||
dof_M0_out[worldid, dofid] = armature + wp.dot(cdof_in[worldid, dofid], buf)
|
||||
|
||||
|
||||
@wp.kernel
|
||||
def _resolve_dampratio(
|
||||
actuator_biastype: wp.array(dtype=int),
|
||||
actuator_gainprm: wp.array2d(dtype=types.vec10f),
|
||||
moment_rownnz_in: wp.array2d(dtype=int),
|
||||
moment_rowadr_in: wp.array2d(dtype=int),
|
||||
moment_colind_in: wp.array2d(dtype=int),
|
||||
actuator_moment_in: wp.array2d(dtype=float),
|
||||
dof_M0_in: wp.array2d(dtype=float),
|
||||
nv: int,
|
||||
actuator_biasprm: wp.array2d(dtype=types.vec10f),
|
||||
):
|
||||
worldid, actid = wp.tid()
|
||||
biastype = actuator_biastype[actid]
|
||||
|
||||
# only affine bias (position actuators)
|
||||
if biastype != BiasType.AFFINE:
|
||||
return
|
||||
|
||||
gainprm_id = worldid % actuator_gainprm.shape[0]
|
||||
biasprm_id = worldid % actuator_biasprm.shape[0]
|
||||
kp = actuator_gainprm[gainprm_id, actid][0]
|
||||
|
||||
biasprm = actuator_biasprm[biasprm_id, actid]
|
||||
# dampratio condition: gainprm[0] == -biasprm[1] and biasprm[2] > 0
|
||||
if wp.abs(kp + biasprm[1]) > MJ_MINVAL:
|
||||
return
|
||||
if biasprm[2] <= 0.0:
|
||||
return
|
||||
|
||||
dampratio = biasprm[2]
|
||||
|
||||
# compute reflected mass: sum(dof_M0[j] / moment[i,j]^2) for active DOFs
|
||||
mass = float(0.0)
|
||||
rownnz = moment_rownnz_in[worldid, actid]
|
||||
rowadr = moment_rowadr_in[worldid, actid]
|
||||
for k in range(rownnz):
|
||||
sparseid = rowadr + k
|
||||
j = moment_colind_in[worldid, sparseid]
|
||||
moment = actuator_moment_in[worldid, sparseid]
|
||||
if wp.abs(moment) > MJ_MINVAL:
|
||||
mass += dof_M0_in[worldid, j] / (moment * moment)
|
||||
|
||||
damping = dampratio * 2.0 * wp.sqrt(kp * mass)
|
||||
|
||||
# write -damping to biasprm[2]
|
||||
new_biasprm = biasprm
|
||||
new_biasprm[2] = -damping
|
||||
actuator_biasprm[biasprm_id, actid] = new_biasprm
|
||||
|
||||
|
||||
@wp.kernel
|
||||
def _set_length_range(
|
||||
actuator_trntype: wp.array(dtype=int),
|
||||
actuator_trnid: wp.array(dtype=wp.vec2i),
|
||||
actuator_gear: wp.array2d(dtype=wp.spatial_vector),
|
||||
jnt_limited: wp.array(dtype=int),
|
||||
jnt_range: wp.array2d(dtype=wp.vec2),
|
||||
tendon_limited: wp.array(dtype=int),
|
||||
tendon_range: wp.array2d(dtype=wp.vec2),
|
||||
ntendon: int,
|
||||
actuator_lengthrange_out: wp.array2d(dtype=wp.vec2),
|
||||
):
|
||||
worldid, actid = wp.tid()
|
||||
trntype = actuator_trntype[actid]
|
||||
id0 = actuator_trnid[actid][0]
|
||||
gear0 = actuator_gear[worldid % actuator_gear.shape[0], actid][0]
|
||||
|
||||
lr = wp.vec2(0.0, 0.0)
|
||||
|
||||
if trntype == TrnType.JOINT or trntype == TrnType.JOINTINPARENT:
|
||||
if jnt_limited[id0]:
|
||||
rng = jnt_range[worldid % jnt_range.shape[0], id0]
|
||||
if gear0 > 0.0:
|
||||
lr = wp.vec2(rng[0] * gear0, rng[1] * gear0)
|
||||
else:
|
||||
lr = wp.vec2(rng[1] * gear0, rng[0] * gear0)
|
||||
elif trntype == TrnType.TENDON:
|
||||
if ntendon > 0 and tendon_limited[id0]:
|
||||
rng = tendon_range[worldid % tendon_range.shape[0], id0]
|
||||
if gear0 > 0.0:
|
||||
lr = wp.vec2(rng[0] * gear0, rng[1] * gear0)
|
||||
else:
|
||||
lr = wp.vec2(rng[1] * gear0, rng[0] * gear0)
|
||||
|
||||
actuator_lengthrange_out[worldid, actid] = lr
|
||||
|
||||
|
||||
# kernel_analyzer: on
|
||||
@@ -1823,6 +2066,9 @@ def set_const_0(m: types.Model, d: types.Data):
|
||||
- cam_pos0, cam_poscom0, cam_mat0: camera references
|
||||
- light_pos0, light_poscom0, light_dir0: light references
|
||||
- actuator_acc0: acceleration from unit actuator force
|
||||
- actuator_biasprm[2] (dampratio resolution): for position actuators where
|
||||
gainprm[0] == -biasprm[1] and biasprm[2] > 0, converts dampratio to
|
||||
damping via biasprm[2] = -dampratio * 2 * sqrt(kp * reflected_mass)
|
||||
|
||||
Args:
|
||||
m: The model containing kinematic and dynamic information (device).
|
||||
@@ -1954,10 +2200,46 @@ def set_const_0(m: types.Model, d: types.Data):
|
||||
act_result_vec = wp.zeros((d.nworld, m.nv), dtype=float)
|
||||
|
||||
for actid in range(m.nu):
|
||||
wp.launch(_copy_actuator_moment, dim=d.nworld, inputs=[actid, d.actuator_moment], outputs=[act_moment_vec])
|
||||
wp.launch(
|
||||
_copy_actuator_moment,
|
||||
dim=d.nworld,
|
||||
inputs=[
|
||||
actid,
|
||||
d.moment_rownnz,
|
||||
d.moment_rowadr,
|
||||
d.moment_colind,
|
||||
d.actuator_moment,
|
||||
],
|
||||
outputs=[act_moment_vec],
|
||||
)
|
||||
smooth.solve_m(m, d, act_result_vec, act_moment_vec)
|
||||
wp.launch(_compute_actuator_acc0, dim=d.nworld, inputs=[actid, m.nv, act_result_vec], outputs=[m.actuator_acc0])
|
||||
|
||||
# resolve dampratio: compute dof_M0, then convert dampratio to damping
|
||||
if m.nu > 0 and m.nv > 0:
|
||||
dof_M0 = wp.zeros((d.nworld, m.nv), dtype=float)
|
||||
wp.launch(
|
||||
_compute_dof_M0,
|
||||
dim=(d.nworld, m.nv),
|
||||
inputs=[m.dof_bodyid, m.dof_armature, d.cdof, d.crb],
|
||||
outputs=[dof_M0],
|
||||
)
|
||||
wp.launch(
|
||||
_resolve_dampratio,
|
||||
dim=(d.nworld, m.nu),
|
||||
inputs=[
|
||||
m.actuator_biastype,
|
||||
m.actuator_gainprm,
|
||||
d.moment_rownnz,
|
||||
d.moment_rowadr,
|
||||
d.moment_colind,
|
||||
d.actuator_moment,
|
||||
dof_M0,
|
||||
m.nv,
|
||||
],
|
||||
outputs=[m.actuator_biasprm],
|
||||
)
|
||||
|
||||
wp.copy(d.qpos, qpos_saved)
|
||||
|
||||
|
||||
@@ -1973,12 +2255,16 @@ def set_const(m: types.Model, d: types.Data):
|
||||
Field | Notes
|
||||
---------------------------------|----------------------------------------------
|
||||
qpos0, qpos_spring |
|
||||
body_mass, body_inertia, | Mass and inertia are usually scaled together
|
||||
body_mass, body_inertia, | Mass and inertia are usually scaled
|
||||
together
|
||||
body_ipos, body_iquat | since inertia is sum(m * r^2).
|
||||
body_pos, body_quat | Unsafe for static bodies (invalidates BVH).
|
||||
body_gravcomp | If changing from 0 to >0 bodies, required.
|
||||
body_pos, body_quat | Unsafe for static bodies (invalidates
|
||||
BVH).
|
||||
body_gravcomp | If changing from 0 to >0 bodies,
|
||||
required.
|
||||
dof_armature |
|
||||
eq_data | For connect/weld, offsets computed if not set.
|
||||
eq_data | For connect/weld, offsets computed if not
|
||||
set.
|
||||
hfield_size |
|
||||
tendon_stiffness, tendon_damping | Only if changing from/to zero.
|
||||
actuator_gainprm, actuator_biasprm | For position actuators with dampratio.
|
||||
@@ -2004,8 +2290,9 @@ def set_const(m: types.Model, d: types.Data):
|
||||
- cam_pos0, cam_poscom0, cam_mat0: camera references
|
||||
- light_pos0, light_poscom0, light_dir0: light references
|
||||
- actuator_acc0: acceleration from unit actuator force
|
||||
- actuator_biasprm[2] (dampratio resolution)
|
||||
|
||||
Skips: dof_M0, actuator_length0 (not in mjwarp).
|
||||
Skips: actuator_length0 (not in mjwarp).
|
||||
|
||||
Args:
|
||||
m: The model containing kinematic and dynamic information (device).
|
||||
@@ -2015,6 +2302,39 @@ def set_const(m: types.Model, d: types.Data):
|
||||
set_const_0(m, d)
|
||||
|
||||
|
||||
def set_length_range(m: types.Model, d: types.Data, index: int = -1):
|
||||
"""Compute feasible actuator length ranges from joint/tendon limits.
|
||||
|
||||
For joint and tendon transmissions with limits, copies the range directly
|
||||
from jnt_range or tendon_range scaled by gear. Actuators without limits
|
||||
keep (0, 0). This covers the common robotics use case; simulation-based
|
||||
computation for general transmissions is not yet implemented.
|
||||
|
||||
Args:
|
||||
m: The model containing kinematic and dynamic information (device).
|
||||
d: The data object (unused, kept for API compatibility with MuJoCo C).
|
||||
index: Actuator index to compute for, or -1 for all actuators.
|
||||
"""
|
||||
if m.nu == 0:
|
||||
return
|
||||
|
||||
wp.launch(
|
||||
_set_length_range,
|
||||
dim=(d.nworld, m.nu),
|
||||
inputs=[
|
||||
m.actuator_trntype,
|
||||
m.actuator_trnid,
|
||||
m.actuator_gear,
|
||||
m.jnt_limited,
|
||||
m.jnt_range,
|
||||
m.tendon_limited,
|
||||
m.tendon_range,
|
||||
m.ntendon,
|
||||
],
|
||||
outputs=[m.actuator_lengthrange],
|
||||
)
|
||||
|
||||
|
||||
def override_model(model: types.Model | mujoco.MjModel, overrides: dict[str, Any] | Sequence[str]):
|
||||
"""Overrides model parameters.
|
||||
|
||||
@@ -2321,26 +2641,25 @@ def create_render_context(
|
||||
|
||||
cam_res_arr = wp.array(active_cam_res, dtype=wp.vec2i)
|
||||
|
||||
if render_rgb and isinstance(render_rgb, bool):
|
||||
if render_rgb is None:
|
||||
render_rgb = [
|
||||
mjm.cam_output[i] & mujoco.mjtCamOutBit.mjCAMOUT_RGB
|
||||
for i in active_cam_indices
|
||||
]
|
||||
elif isinstance(render_rgb, bool):
|
||||
render_rgb = [render_rgb] * ncam
|
||||
elif render_rgb is None:
|
||||
# TODO: remove after mjwarp depends on mujoco >= 3.4.1 in pyproject.toml
|
||||
if BLEEDING_EDGE_MUJOCO:
|
||||
render_rgb = [mjm.cam_output[i] & mujoco.mjtCamOutBit.mjCAMOUT_RGB for i in active_cam_indices]
|
||||
else:
|
||||
render_rgb = [True] * ncam
|
||||
|
||||
if render_depth and isinstance(render_depth, bool):
|
||||
if render_depth is None:
|
||||
render_depth = [
|
||||
mjm.cam_output[i] & mujoco.mjtCamOutBit.mjCAMOUT_DEPTH
|
||||
for i in active_cam_indices
|
||||
]
|
||||
if isinstance(render_depth, bool):
|
||||
render_depth = [render_depth] * ncam
|
||||
elif render_depth is None:
|
||||
# TODO: remove after mjwarp depends on mujoco >= 3.4.1 in pyproject.toml
|
||||
if BLEEDING_EDGE_MUJOCO:
|
||||
render_depth = [mjm.cam_output[i] & mujoco.mjtCamOutBit.mjCAMOUT_DEPTH for i in active_cam_indices]
|
||||
else:
|
||||
render_depth = [True] * ncam
|
||||
|
||||
assert len(render_rgb) == ncam and len(render_depth) == ncam, (
|
||||
f"Render RGB and depth must be provided for all active cameras (got {len(render_rgb)}, {len(render_depth)}, expected {ncam})"
|
||||
"render_rgb and render_depth must be a bool or a list of bools with"
|
||||
f" length {ncam}"
|
||||
)
|
||||
|
||||
rgb_adr = -1 * np.ones(ncam, dtype=int)
|
||||
@@ -2364,10 +2683,7 @@ def create_render_context(
|
||||
|
||||
ray = wp.zeros(int(total), dtype=wp.vec3)
|
||||
|
||||
# TODO: remove after mjwarp depends on mujoco >= 3.4.1 in pyproject.toml
|
||||
cam_projection = np.zeros(mjm.ncam, dtype=int)
|
||||
if BLEEDING_EDGE_MUJOCO:
|
||||
cam_projection = mjm.cam_projection
|
||||
cam_projection = mjm.cam_projection
|
||||
|
||||
offset = 0
|
||||
for idx, cam_id in enumerate(active_cam_indices):
|
||||
|
||||
+89
-3
@@ -13,12 +13,12 @@
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
|
||||
import warp as wp
|
||||
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import types
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import ConstraintType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import EqType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import ObjType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import event_scope
|
||||
import warp as wp
|
||||
|
||||
|
||||
@wp.kernel
|
||||
@@ -44,7 +44,7 @@ def _tree_edges(
|
||||
# Out:
|
||||
tree_tree: wp.array3d(dtype=int), # kernel_analyzer: off
|
||||
):
|
||||
"""Find tree edges. Launch: (nworld, njmax)."""
|
||||
"""Find tree edges."""
|
||||
worldid, efcid = wp.tid()
|
||||
|
||||
# skip if beyond active constraints
|
||||
@@ -176,3 +176,89 @@ def tree_edges(m: types.Model, d: types.Data, tree_tree: wp.array3d(dtype=int)):
|
||||
],
|
||||
outputs=[tree_tree],
|
||||
)
|
||||
|
||||
|
||||
@wp.kernel
|
||||
def _flood_fill(
|
||||
# Model:
|
||||
ntree: int,
|
||||
# In:
|
||||
tree_tree_in: wp.array3d(dtype=int),
|
||||
labels_in: wp.array2d(dtype=int),
|
||||
stack_in: wp.array2d(dtype=int),
|
||||
# Data out:
|
||||
nisland_out: wp.array(dtype=int),
|
||||
tree_island_out: wp.array2d(dtype=int),
|
||||
# Out:
|
||||
stack_out: wp.array2d(dtype=int),
|
||||
):
|
||||
"""DFS flood fill to discover islands using tree_tree matrix."""
|
||||
worldid = wp.tid()
|
||||
nisland = int(0)
|
||||
|
||||
# iterate over trees
|
||||
for i in range(ntree):
|
||||
# already assigned
|
||||
if labels_in[worldid, i] != -1:
|
||||
continue
|
||||
|
||||
# check if tree has any edges
|
||||
has_edge = int(0)
|
||||
for j in range(ntree):
|
||||
if tree_tree_in[worldid, i, j] != 0:
|
||||
has_edge = 1
|
||||
break
|
||||
if has_edge == 0:
|
||||
continue
|
||||
|
||||
# DFS: push i onto stack
|
||||
nstack = int(0)
|
||||
stack_out[worldid, nstack] = i
|
||||
nstack = nstack + 1
|
||||
|
||||
while nstack > 0:
|
||||
# pop v from stack
|
||||
nstack = nstack - 1
|
||||
v = stack_in[worldid, nstack]
|
||||
|
||||
# already assigned
|
||||
if labels_in[worldid, v] != -1:
|
||||
continue
|
||||
|
||||
# assign to current island
|
||||
tree_island_out[worldid, v] = nisland
|
||||
|
||||
# push neighbors
|
||||
for neighbor in range(ntree):
|
||||
if tree_tree_in[worldid, v, neighbor] != 0:
|
||||
if labels_in[worldid, neighbor] == -1:
|
||||
stack_out[worldid, nstack] = neighbor
|
||||
nstack = nstack + 1
|
||||
|
||||
# island filled
|
||||
nisland = nisland + 1
|
||||
|
||||
nisland_out[worldid] = nisland
|
||||
|
||||
|
||||
@event_scope
|
||||
def island(m: types.Model, d: types.Data):
|
||||
"""Discover constraint islands."""
|
||||
if m.ntree == 0:
|
||||
d.nisland.zero_()
|
||||
return
|
||||
|
||||
# Step 1: Find tree edges
|
||||
tree_tree = wp.zeros((d.nworld, m.ntree, m.ntree), dtype=int)
|
||||
tree_edges(m, d, tree_tree)
|
||||
|
||||
# Step 2: DFS flood fill
|
||||
d.tree_island.fill_(-1)
|
||||
stack_scratch = wp.empty((d.nworld, m.ntree * m.ntree), dtype=int)
|
||||
|
||||
wp.launch(
|
||||
_flood_fill,
|
||||
dim=d.nworld,
|
||||
inputs=[m.ntree, tree_tree, d.tree_island, stack_scratch],
|
||||
outputs=[d.nisland, d.tree_island, stack_scratch],
|
||||
)
|
||||
|
||||
+48
-45
@@ -265,28 +265,28 @@ def _gravity_force(
|
||||
|
||||
@wp.kernel
|
||||
def _fluid_force(
|
||||
# Model:
|
||||
opt_density: wp.array(dtype=float),
|
||||
opt_viscosity: wp.array(dtype=float),
|
||||
opt_wind: wp.array(dtype=wp.vec3),
|
||||
body_rootid: wp.array(dtype=int),
|
||||
body_geomnum: wp.array(dtype=int),
|
||||
body_geomadr: wp.array(dtype=int),
|
||||
body_mass: wp.array2d(dtype=float),
|
||||
body_inertia: wp.array2d(dtype=wp.vec3),
|
||||
geom_type: wp.array(dtype=int),
|
||||
geom_size: wp.array2d(dtype=wp.vec3),
|
||||
geom_fluid: wp.array2d(dtype=float),
|
||||
body_fluid_ellipsoid: wp.array(dtype=bool),
|
||||
# Data in:
|
||||
xipos_in: wp.array2d(dtype=wp.vec3),
|
||||
ximat_in: wp.array2d(dtype=wp.mat33),
|
||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
||||
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
||||
cvel_in: wp.array2d(dtype=wp.spatial_vector),
|
||||
# Out:
|
||||
fluid_applied_out: wp.array2d(dtype=wp.spatial_vector),
|
||||
# Model:
|
||||
opt_wind: wp.array(dtype=wp.vec3),
|
||||
opt_density: wp.array(dtype=float),
|
||||
opt_viscosity: wp.array(dtype=float),
|
||||
body_rootid: wp.array(dtype=int),
|
||||
body_geomnum: wp.array(dtype=int),
|
||||
body_geomadr: wp.array(dtype=int),
|
||||
body_mass: wp.array2d(dtype=float),
|
||||
body_inertia: wp.array2d(dtype=wp.vec3),
|
||||
geom_type: wp.array(dtype=int),
|
||||
geom_size: wp.array2d(dtype=wp.vec3),
|
||||
geom_fluid: wp.array2d(dtype=float),
|
||||
body_fluid_ellipsoid: wp.array(dtype=bool),
|
||||
# Data in:
|
||||
xipos_in: wp.array2d(dtype=wp.vec3),
|
||||
ximat_in: wp.array2d(dtype=wp.mat33),
|
||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
||||
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
||||
cvel_in: wp.array2d(dtype=wp.spatial_vector),
|
||||
# Out:
|
||||
fluid_applied_out: wp.array2d(dtype=wp.spatial_vector),
|
||||
):
|
||||
"""Computes body-space fluid forces for both inertia-box and ellipsoid models."""
|
||||
worldid, bodyid = wp.tid()
|
||||
@@ -495,29 +495,29 @@ def _fluid(m: Model, d: Data):
|
||||
fluid_applied = wp.empty((d.nworld, m.nbody), dtype=wp.spatial_vector)
|
||||
|
||||
wp.launch(
|
||||
_fluid_force,
|
||||
dim=(d.nworld, m.nbody),
|
||||
inputs=[
|
||||
m.opt.density,
|
||||
m.opt.viscosity,
|
||||
m.opt.wind,
|
||||
m.body_rootid,
|
||||
m.body_geomnum,
|
||||
m.body_geomadr,
|
||||
m.body_mass,
|
||||
m.body_inertia,
|
||||
m.geom_type,
|
||||
m.geom_size,
|
||||
m.geom_fluid,
|
||||
m.body_fluid_ellipsoid,
|
||||
d.xipos,
|
||||
d.ximat,
|
||||
d.geom_xpos,
|
||||
d.geom_xmat,
|
||||
d.subtree_com,
|
||||
d.cvel,
|
||||
],
|
||||
outputs=[fluid_applied],
|
||||
_fluid_force,
|
||||
dim=(d.nworld, m.nbody),
|
||||
inputs=[
|
||||
m.opt.wind,
|
||||
m.opt.density,
|
||||
m.opt.viscosity,
|
||||
m.body_rootid,
|
||||
m.body_geomnum,
|
||||
m.body_geomadr,
|
||||
m.body_mass,
|
||||
m.body_inertia,
|
||||
m.geom_type,
|
||||
m.geom_size,
|
||||
m.geom_fluid,
|
||||
m.body_fluid_ellipsoid,
|
||||
d.xipos,
|
||||
d.ximat,
|
||||
d.geom_xpos,
|
||||
d.geom_xmat,
|
||||
d.subtree_com,
|
||||
d.cvel,
|
||||
],
|
||||
outputs=[fluid_applied],
|
||||
)
|
||||
|
||||
support.apply_ft(m, d, fluid_applied, d.qfrc_fluid, False)
|
||||
@@ -846,3 +846,6 @@ def passive(m: Model, d: Data):
|
||||
d.qfrc_passive,
|
||||
],
|
||||
)
|
||||
|
||||
if m.callback.passive:
|
||||
m.callback.passive(m, d)
|
||||
|
||||
+3
-3
@@ -66,19 +66,19 @@ def _ray_eliminate(
|
||||
) -> bool:
|
||||
"""Eliminate ray."""
|
||||
bodyid = geom_bodyid[geomid]
|
||||
matid = geom_matid[geomid]
|
||||
matid = geom_matid[geomid] # kernel_analyzer: ignore
|
||||
|
||||
# body exclusion
|
||||
if bodyid == bodyexclude:
|
||||
return True
|
||||
|
||||
# invisible geom exclusion
|
||||
if matid < 0 and geom_rgba[geomid][3] == 0.0:
|
||||
if matid < 0 and geom_rgba[geomid][3] == 0.0: # kernel_analyzer: ignore
|
||||
return True
|
||||
|
||||
# invisible material exclusion
|
||||
if matid >= 0:
|
||||
if mat_rgba[matid][3] == 0.0:
|
||||
if mat_rgba[matid][3] == 0.0: # kernel_analyzer: ignore
|
||||
return True
|
||||
|
||||
# static exclusion
|
||||
|
||||
+7
-1
@@ -552,7 +552,13 @@ def render(m: Model, d: Data, rc: RenderContext):
|
||||
return
|
||||
|
||||
if render_depth[cam_idx]:
|
||||
depth_out[world_idx, depth_adr[cam_idx] + ray_idx_local] = dist
|
||||
# Planar depth: project Euclidean distance onto the camera's optical axis.
|
||||
# In camera-local coordinates, the optical axis is -Z. The Z-component of the
|
||||
# normalized ray direction is negative, so -ray_dir_local_cam[2] gives cos(θ)
|
||||
# between the ray and the optical axis.
|
||||
depth_out[world_idx, depth_adr[cam_idx] + ray_idx_local] = dist * (
|
||||
-ray_dir_local_cam[2]
|
||||
)
|
||||
|
||||
if not render_rgb[cam_idx]:
|
||||
return
|
||||
|
||||
+239
-133
@@ -15,16 +15,12 @@
|
||||
|
||||
from typing import Any, Tuple
|
||||
|
||||
import warp as wp
|
||||
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import math
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import ray
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import smooth
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import support
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_sdf import get_sdf_params
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_sdf import sdf
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAXVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MINVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import ConeType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import ConstraintType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import ContactType
|
||||
@@ -32,9 +28,13 @@ from mujoco.mjx.third_party.mujoco_warp._src.types import Data
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import DataType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import DisableBit
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import JointType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAXCONPAIR
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAXVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MINVAL
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Model
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import ObjType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import SensorType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Stage
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import TrnType
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import vec5
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.types import vec6
|
||||
@@ -43,6 +43,7 @@ from mujoco.mjx.third_party.mujoco_warp._src.types import vec8i
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.util_misc import inside_geom
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import cache_kernel
|
||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import event_scope
|
||||
import warp as wp
|
||||
|
||||
wp.set_module_options({"enable_backward": False})
|
||||
|
||||
@@ -898,6 +899,9 @@ def sensor_pos(m: Model, d: Data):
|
||||
],
|
||||
)
|
||||
|
||||
if m.callback.sensor:
|
||||
m.callback.sensor(m, d, Stage.POS)
|
||||
|
||||
|
||||
@wp.func
|
||||
def _velocimeter(
|
||||
@@ -1437,6 +1441,9 @@ def sensor_vel(m: Model, d: Data):
|
||||
],
|
||||
)
|
||||
|
||||
if m.callback.sensor:
|
||||
m.callback.sensor(m, d, Stage.VEL)
|
||||
|
||||
|
||||
@wp.func
|
||||
def _accelerometer(
|
||||
@@ -2073,67 +2080,92 @@ def _transform_spatial(vec: wp.spatial_vector, dif: wp.vec3) -> wp.vec3:
|
||||
|
||||
|
||||
@wp.kernel
|
||||
def _sensor_tactile(
|
||||
# Model:
|
||||
body_rootid: wp.array(dtype=int),
|
||||
body_weldid: wp.array(dtype=int),
|
||||
oct_child: wp.array(dtype=vec8i),
|
||||
oct_aabb: wp.array2d(dtype=wp.vec3),
|
||||
oct_coeff: wp.array(dtype=vec8),
|
||||
geom_type: wp.array(dtype=int),
|
||||
geom_bodyid: wp.array(dtype=int),
|
||||
geom_size: wp.array2d(dtype=wp.vec3),
|
||||
mesh_vertadr: wp.array(dtype=int),
|
||||
mesh_normaladr: wp.array(dtype=int),
|
||||
mesh_vert: wp.array(dtype=wp.vec3),
|
||||
mesh_normal: wp.array(dtype=wp.vec3),
|
||||
mesh_quat: wp.array(dtype=wp.quat),
|
||||
sensor_objid: wp.array(dtype=int),
|
||||
sensor_refid: wp.array(dtype=int),
|
||||
sensor_dim: wp.array(dtype=int),
|
||||
sensor_adr: wp.array(dtype=int),
|
||||
plugin: wp.array(dtype=int),
|
||||
plugin_attr: wp.array(dtype=wp.vec3f),
|
||||
geom_plugin_index: wp.array(dtype=int),
|
||||
taxel_vertadr: wp.array(dtype=int),
|
||||
taxel_sensorid: wp.array(dtype=int),
|
||||
# Data in:
|
||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
||||
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
||||
cvel_in: wp.array2d(dtype=wp.spatial_vector),
|
||||
contact_geom_in: wp.array(dtype=wp.vec2i),
|
||||
contact_worldid_in: wp.array(dtype=int),
|
||||
nacon_in: wp.array(dtype=int),
|
||||
# Data out:
|
||||
sensordata_out: wp.array2d(dtype=float),
|
||||
def _preprocess_tactile_contacts(
|
||||
# Model:
|
||||
body_weldid: wp.array(dtype=int),
|
||||
geom_bodyid: wp.array(dtype=int),
|
||||
# Data in:
|
||||
contact_geom_in: wp.array(dtype=wp.vec2i),
|
||||
contact_worldid_in: wp.array(dtype=int),
|
||||
nacon_in: wp.array(dtype=int),
|
||||
# Out:
|
||||
weld_geom_count_out: wp.array2d(dtype=int),
|
||||
weld_geom_list_out: wp.array3d(dtype=int),
|
||||
):
|
||||
conid, taxelid = wp.tid()
|
||||
|
||||
if conid >= nacon_in[0]:
|
||||
conid = wp.tid()
|
||||
ncon = nacon_in[0]
|
||||
if conid >= ncon:
|
||||
return
|
||||
|
||||
worldid = contact_worldid_in[conid]
|
||||
contact_geom = contact_geom_in[conid]
|
||||
weld1 = body_weldid[geom_bodyid[contact_geom[0]]]
|
||||
weld2 = body_weldid[geom_bodyid[contact_geom[1]]]
|
||||
geom1 = contact_geom[0]
|
||||
geom2 = contact_geom[1]
|
||||
|
||||
for side in range(2):
|
||||
if side == 0:
|
||||
weld = weld1
|
||||
geom = geom2
|
||||
else:
|
||||
weld = weld2
|
||||
geom = geom1
|
||||
|
||||
idx = wp.atomic_add(weld_geom_count_out[worldid], weld, 1)
|
||||
if idx < MJ_MAXCONPAIR:
|
||||
weld_geom_list_out[worldid, weld, idx] = geom
|
||||
|
||||
|
||||
@wp.kernel
|
||||
def _sensor_tactile(
|
||||
# Model:
|
||||
body_rootid: wp.array(dtype=int),
|
||||
body_weldid: wp.array(dtype=int),
|
||||
oct_child: wp.array(dtype=vec8i),
|
||||
oct_aabb: wp.array2d(dtype=wp.vec3),
|
||||
oct_coeff: wp.array(dtype=vec8),
|
||||
geom_type: wp.array(dtype=int),
|
||||
geom_bodyid: wp.array(dtype=int),
|
||||
geom_size: wp.array2d(dtype=wp.vec3),
|
||||
mesh_vertadr: wp.array(dtype=int),
|
||||
mesh_vertnum: wp.array(dtype=int),
|
||||
mesh_octadr: wp.array(dtype=int),
|
||||
mesh_normaladr: wp.array(dtype=int),
|
||||
mesh_normalnum: wp.array(dtype=int),
|
||||
mesh_vert: wp.array(dtype=wp.vec3),
|
||||
mesh_normal: wp.array(dtype=wp.vec3),
|
||||
mesh_quat: wp.array(dtype=wp.quat),
|
||||
sensor_objid: wp.array(dtype=int),
|
||||
sensor_refid: wp.array(dtype=int),
|
||||
sensor_dim: wp.array(dtype=int),
|
||||
sensor_adr: wp.array(dtype=int),
|
||||
plugin: wp.array(dtype=int),
|
||||
plugin_attr: wp.array(dtype=wp.vec3f),
|
||||
geom_plugin_index: wp.array(dtype=int),
|
||||
taxel_vertadr: wp.array(dtype=int),
|
||||
taxel_sensorid: wp.array(dtype=int),
|
||||
# Data in:
|
||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
||||
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
||||
cvel_in: wp.array2d(dtype=wp.spatial_vector),
|
||||
# In:
|
||||
weld_geom_count_in: wp.array2d(dtype=int),
|
||||
weld_geom_list_in: wp.array3d(dtype=int),
|
||||
# Data out:
|
||||
sensordata_out: wp.array2d(dtype=float),
|
||||
):
|
||||
worldid, taxelid = wp.tid()
|
||||
|
||||
# get sensor_id
|
||||
sensor_id = taxel_sensorid[taxelid]
|
||||
|
||||
# get parent weld id
|
||||
mesh_id = sensor_objid[sensor_id]
|
||||
geom_id = sensor_refid[sensor_id]
|
||||
parent_body = geom_bodyid[geom_id]
|
||||
parent_weld = body_weldid[parent_body]
|
||||
|
||||
# contact geom
|
||||
body1 = body_weldid[geom_bodyid[contact_geom_in[conid][0]]]
|
||||
body2 = body_weldid[geom_bodyid[contact_geom_in[conid][1]]]
|
||||
if body1 == parent_weld:
|
||||
geom = contact_geom_in[conid][1]
|
||||
elif body2 == parent_weld:
|
||||
geom = contact_geom_in[conid][0]
|
||||
else:
|
||||
geom_count = weld_geom_count_in[worldid, parent_weld]
|
||||
if geom_count == 0:
|
||||
return
|
||||
body = geom_bodyid[geom]
|
||||
|
||||
# vertex local position
|
||||
vertid = taxel_vertadr[taxelid] - mesh_vertadr[mesh_id]
|
||||
@@ -2143,57 +2175,108 @@ def _sensor_tactile(
|
||||
xpos = geom_xmat_in[worldid, geom_id] @ pos
|
||||
xpos += geom_xpos_in[worldid, geom_id]
|
||||
|
||||
# position in other geom frame
|
||||
tmp = xpos - geom_xpos_in[worldid, geom]
|
||||
lpos = wp.transpose(geom_xmat_in[worldid, geom]) @ tmp
|
||||
has_frame = mesh_normalnum[mesh_id] == 3 * mesh_vertnum[mesh_id]
|
||||
normal_stride = 3 if has_frame else 1
|
||||
offset = mesh_normaladr[mesh_id] + normal_stride * vertid
|
||||
quat = mesh_quat[mesh_id]
|
||||
normal = math.rot_vec_quat(mesh_normal[offset], quat)
|
||||
tang1 = wp.vec3(0.0, 0.0, 0.0)
|
||||
tang2 = wp.vec3(0.0, 0.0, 0.0)
|
||||
if has_frame:
|
||||
tang1 = math.rot_vec_quat(mesh_normal[offset + 1], quat)
|
||||
tang2 = math.rot_vec_quat(mesh_normal[offset + 2], quat)
|
||||
|
||||
plugin_id = geom_plugin_index[geom]
|
||||
for g in range(MJ_MAXCONPAIR):
|
||||
if g >= geom_count:
|
||||
break
|
||||
|
||||
contact_type = geom_type[geom]
|
||||
geom = weld_geom_list_in[worldid, parent_weld, g]
|
||||
if geom < 0:
|
||||
continue
|
||||
|
||||
plugin_attributes, plugin_index, volume_data, mesh_data = get_sdf_params(
|
||||
oct_child,
|
||||
oct_aabb,
|
||||
oct_coeff,
|
||||
plugin,
|
||||
plugin_attr,
|
||||
contact_type,
|
||||
geom_size[worldid % geom_size.shape[0], geom],
|
||||
plugin_id,
|
||||
mesh_id,
|
||||
)
|
||||
is_dup = int(0)
|
||||
for j in range(g):
|
||||
if weld_geom_list_in[worldid, parent_weld, j] == geom:
|
||||
is_dup = int(1)
|
||||
break
|
||||
if is_dup == int(1):
|
||||
continue
|
||||
|
||||
depth = wp.min(sdf(contact_type, lpos, plugin_attributes, plugin_index, volume_data, mesh_data), 0.0)
|
||||
if depth >= 0.0:
|
||||
return
|
||||
body = geom_bodyid[geom]
|
||||
|
||||
# get velocity in global
|
||||
vel_sensor = _transform_spatial(cvel_in[worldid, parent_weld], xpos - subtree_com_in[worldid, body_rootid[parent_weld]])
|
||||
vel_other = _transform_spatial(
|
||||
cvel_in[worldid, body], geom_xpos_in[worldid, geom] - subtree_com_in[worldid, body_rootid[body]]
|
||||
)
|
||||
vel_rel = vel_sensor - vel_other
|
||||
tmp = xpos - geom_xpos_in[worldid, geom]
|
||||
lpos = wp.transpose(geom_xmat_in[worldid, geom]) @ tmp
|
||||
|
||||
# get contact force/torque, rotate into node frame
|
||||
offset = mesh_normaladr[mesh_id] + 3 * vertid
|
||||
normal = math.rot_vec_quat(mesh_normal[offset], mesh_quat[mesh_id])
|
||||
tang1 = math.rot_vec_quat(mesh_normal[offset + 1], mesh_quat[mesh_id])
|
||||
tang2 = math.rot_vec_quat(mesh_normal[offset + 2], mesh_quat[mesh_id])
|
||||
kMaxDepth = 0.05
|
||||
pressure = depth / wp.max(kMaxDepth - depth, MJ_MINVAL)
|
||||
force = wp.mul(normal, pressure)
|
||||
plugin_id = geom_plugin_index[geom]
|
||||
contact_type = geom_type[geom]
|
||||
|
||||
# one row of mat^T * force
|
||||
forceT = wp.vec3()
|
||||
forceT[0] = wp.dot(force, normal)
|
||||
forceT[1] = wp.abs(wp.dot(vel_rel, tang1))
|
||||
forceT[2] = wp.abs(wp.dot(vel_rel, tang2))
|
||||
plugin_attributes, plugin_index, volume_data, mesh_data = get_sdf_params(
|
||||
oct_child,
|
||||
oct_aabb,
|
||||
oct_coeff,
|
||||
mesh_octadr,
|
||||
plugin,
|
||||
plugin_attr,
|
||||
contact_type,
|
||||
geom_size[worldid % geom_size.shape[0], geom],
|
||||
plugin_id,
|
||||
mesh_id,
|
||||
)
|
||||
|
||||
# add to sensor output
|
||||
dim = sensor_dim[sensor_id] / 3
|
||||
wp.atomic_add(sensordata_out[worldid], sensor_adr[sensor_id] + 0 * dim + vertid, forceT[0])
|
||||
wp.atomic_add(sensordata_out[worldid], sensor_adr[sensor_id] + 1 * dim + vertid, forceT[1])
|
||||
wp.atomic_add(sensordata_out[worldid], sensor_adr[sensor_id] + 2 * dim + vertid, forceT[2])
|
||||
depth = wp.min(
|
||||
sdf(
|
||||
contact_type,
|
||||
lpos,
|
||||
plugin_attributes,
|
||||
plugin_index,
|
||||
volume_data,
|
||||
mesh_data,
|
||||
),
|
||||
0.0,
|
||||
)
|
||||
if depth >= 0.0:
|
||||
continue
|
||||
|
||||
vel_sensor = _transform_spatial(
|
||||
cvel_in[worldid, parent_weld],
|
||||
xpos - subtree_com_in[worldid, body_rootid[parent_weld]],
|
||||
)
|
||||
vel_other = _transform_spatial(
|
||||
cvel_in[worldid, body],
|
||||
geom_xpos_in[worldid, geom]
|
||||
- subtree_com_in[worldid, body_rootid[body]],
|
||||
)
|
||||
vel_rel = vel_sensor - vel_other
|
||||
|
||||
kMaxDepth = 0.05
|
||||
pressure = depth / wp.max(kMaxDepth - depth, MJ_MINVAL)
|
||||
force = wp.mul(normal, pressure)
|
||||
|
||||
forceT = wp.vec3(0.0, 0.0, 0.0)
|
||||
forceT[0] = wp.dot(force, normal)
|
||||
if has_frame:
|
||||
forceT[1] = wp.abs(wp.dot(vel_rel, tang1))
|
||||
forceT[2] = wp.abs(wp.dot(vel_rel, tang2))
|
||||
|
||||
dim = sensor_dim[sensor_id] // 3
|
||||
wp.atomic_add(
|
||||
sensordata_out,
|
||||
worldid,
|
||||
sensor_adr[sensor_id] + 0 * dim + vertid,
|
||||
forceT[0],
|
||||
)
|
||||
wp.atomic_add(
|
||||
sensordata_out,
|
||||
worldid,
|
||||
sensor_adr[sensor_id] + 1 * dim + vertid,
|
||||
forceT[1],
|
||||
)
|
||||
wp.atomic_add(
|
||||
sensordata_out,
|
||||
worldid,
|
||||
sensor_adr[sensor_id] + 2 * dim + vertid,
|
||||
forceT[2],
|
||||
)
|
||||
|
||||
|
||||
@wp.func
|
||||
@@ -2421,43 +2504,63 @@ def sensor_acc(m: Model, d: Data):
|
||||
],
|
||||
)
|
||||
|
||||
weld_geom_count = wp.zeros((d.nworld, m.nbody), dtype=int)
|
||||
weld_geom_list = wp.full((d.nworld, m.nbody, MJ_MAXCONPAIR), -1, dtype=int)
|
||||
wp.launch(
|
||||
_sensor_tactile,
|
||||
dim=(d.naconmax, m.nsensortaxel),
|
||||
inputs=[
|
||||
m.body_rootid,
|
||||
m.body_weldid,
|
||||
m.oct_child,
|
||||
m.oct_aabb,
|
||||
m.oct_coeff,
|
||||
m.geom_type,
|
||||
m.geom_bodyid,
|
||||
m.geom_size,
|
||||
m.mesh_vertadr,
|
||||
m.mesh_normaladr,
|
||||
m.mesh_vert,
|
||||
m.mesh_normal,
|
||||
m.mesh_quat,
|
||||
m.sensor_objid,
|
||||
m.sensor_refid,
|
||||
m.sensor_dim,
|
||||
m.sensor_adr,
|
||||
m.plugin,
|
||||
m.plugin_attr,
|
||||
m.geom_plugin_index,
|
||||
m.taxel_vertadr,
|
||||
m.taxel_sensorid,
|
||||
d.geom_xpos,
|
||||
d.geom_xmat,
|
||||
d.subtree_com,
|
||||
d.cvel,
|
||||
d.contact.geom,
|
||||
d.contact.worldid,
|
||||
d.nacon,
|
||||
],
|
||||
outputs=[
|
||||
d.sensordata,
|
||||
],
|
||||
_preprocess_tactile_contacts,
|
||||
dim=d.naconmax,
|
||||
inputs=[
|
||||
m.body_weldid,
|
||||
m.geom_bodyid,
|
||||
d.contact.geom,
|
||||
d.contact.worldid,
|
||||
d.nacon,
|
||||
],
|
||||
outputs=[
|
||||
weld_geom_count,
|
||||
weld_geom_list,
|
||||
],
|
||||
)
|
||||
|
||||
wp.launch(
|
||||
_sensor_tactile,
|
||||
dim=(d.nworld, m.nsensortaxel),
|
||||
inputs=[
|
||||
m.body_rootid,
|
||||
m.body_weldid,
|
||||
m.oct_child,
|
||||
m.oct_aabb,
|
||||
m.oct_coeff,
|
||||
m.geom_type,
|
||||
m.geom_bodyid,
|
||||
m.geom_size,
|
||||
m.mesh_vertadr,
|
||||
m.mesh_vertnum,
|
||||
m.mesh_octadr,
|
||||
m.mesh_normaladr,
|
||||
m.mesh_normalnum,
|
||||
m.mesh_vert,
|
||||
m.mesh_normal,
|
||||
m.mesh_quat,
|
||||
m.sensor_objid,
|
||||
m.sensor_refid,
|
||||
m.sensor_dim,
|
||||
m.sensor_adr,
|
||||
m.plugin,
|
||||
m.plugin_attr,
|
||||
m.geom_plugin_index,
|
||||
m.taxel_vertadr,
|
||||
m.taxel_sensorid,
|
||||
d.geom_xpos,
|
||||
d.geom_xmat,
|
||||
d.subtree_com,
|
||||
d.cvel,
|
||||
weld_geom_count,
|
||||
weld_geom_list,
|
||||
],
|
||||
outputs=[
|
||||
d.sensordata,
|
||||
],
|
||||
)
|
||||
|
||||
sensor_contact_nmatch = wp.empty((d.nworld, m.nsensorcontact), dtype=int)
|
||||
@@ -2616,6 +2719,9 @@ def sensor_acc(m: Model, d: Data):
|
||||
],
|
||||
)
|
||||
|
||||
if m.callback.sensor:
|
||||
m.callback.sensor(m, d, Stage.ACC)
|
||||
|
||||
|
||||
@wp.kernel
|
||||
def _energy_pos_zero(
|
||||
|
||||
+533
-287
File diff suppressed because it is too large
Load Diff
+1081
-398
File diff suppressed because it is too large
Load Diff
+194
-84
@@ -14,6 +14,7 @@
|
||||
# ==============================================================================
|
||||
import dataclasses
|
||||
import enum
|
||||
from typing import Callable
|
||||
|
||||
import mujoco
|
||||
import warp as wp
|
||||
@@ -32,6 +33,9 @@ MJ_MAX_EPAFACES = 5
|
||||
TILE_SIZE_JTDAJ_SPARSE = 16
|
||||
TILE_SIZE_JTDAJ_DENSE = 16
|
||||
|
||||
# TODO(team): remove after improving performance for sparse constraint jacobian
|
||||
SPARSE_CONSTRAINT_JACOBIAN = False
|
||||
|
||||
# TODO(team): remove after mjwarp depends on warp-lang >= 1.12 in pyproject.toml
|
||||
TEXTURE_DTYPE = wp.Texture2D if hasattr(wp, "Texture2D") else int
|
||||
|
||||
@@ -134,6 +138,20 @@ class ProjectionType(enum.IntEnum):
|
||||
ORTHOGRAPHIC = 1
|
||||
|
||||
|
||||
class Stage(enum.IntEnum):
|
||||
"""Computation stage.
|
||||
|
||||
Attributes:
|
||||
POS: position-dependent
|
||||
VEL: velocity-dependent
|
||||
ACC: acceleration/force-dependent
|
||||
"""
|
||||
|
||||
POS = mujoco.mjtStage.mjSTAGE_POS
|
||||
VEL = mujoco.mjtStage.mjSTAGE_VEL
|
||||
ACC = mujoco.mjtStage.mjSTAGE_ACC
|
||||
|
||||
|
||||
class DataType(enum.IntFlag):
|
||||
"""Sensor data types.
|
||||
|
||||
@@ -167,6 +185,7 @@ class DisableBit(enum.IntFlag):
|
||||
SENSOR: sensors
|
||||
EULERDAMP: implicit damping for Euler integration
|
||||
NATIVECCD: native convex collision detection (ignored in MJWarp)
|
||||
ISLAND: constraint islands
|
||||
"""
|
||||
|
||||
CONSTRAINT = mujoco.mjtDisableBit.mjDSBL_CONSTRAINT
|
||||
@@ -185,7 +204,8 @@ class DisableBit(enum.IntFlag):
|
||||
SENSOR = mujoco.mjtDisableBit.mjDSBL_SENSOR
|
||||
EULERDAMP = mujoco.mjtDisableBit.mjDSBL_EULERDAMP
|
||||
NATIVECCD = mujoco.mjtDisableBit.mjDSBL_NATIVECCD
|
||||
# unsupported: MIDPHASE, AUTORESET, ISLAND
|
||||
ISLAND = mujoco.mjtDisableBit.mjDSBL_ISLAND
|
||||
# unsupported: MIDPHASE, AUTORESET
|
||||
|
||||
|
||||
class EnableBit(enum.IntFlag):
|
||||
@@ -232,6 +252,7 @@ class DynType(enum.IntEnum):
|
||||
FILTER: linear filter: da/dt = (u-a) / tau
|
||||
FILTEREXACT: linear filter: da/dt = (u-a) / tau, with exact integration
|
||||
MUSCLE: piece-wise linear filter with two time constants
|
||||
USER: user-defined dynamics via act_dyn_callback
|
||||
"""
|
||||
|
||||
NONE = mujoco.mjtDyn.mjDYN_NONE
|
||||
@@ -239,7 +260,7 @@ class DynType(enum.IntEnum):
|
||||
FILTER = mujoco.mjtDyn.mjDYN_FILTER
|
||||
FILTEREXACT = mujoco.mjtDyn.mjDYN_FILTEREXACT
|
||||
MUSCLE = mujoco.mjtDyn.mjDYN_MUSCLE
|
||||
# unsupported: USER
|
||||
USER = mujoco.mjtDyn.mjDYN_USER
|
||||
|
||||
|
||||
class GainType(enum.IntEnum):
|
||||
@@ -249,12 +270,13 @@ class GainType(enum.IntEnum):
|
||||
FIXED: fixed gain
|
||||
AFFINE: const + kp*length + kv*velocity
|
||||
MUSCLE: muscle FLV curve computed by muscle_gain
|
||||
USER: user-defined gain via act_gain_callback
|
||||
"""
|
||||
|
||||
FIXED = mujoco.mjtGain.mjGAIN_FIXED
|
||||
AFFINE = mujoco.mjtGain.mjGAIN_AFFINE
|
||||
MUSCLE = mujoco.mjtGain.mjGAIN_MUSCLE
|
||||
# unsupported: USER
|
||||
USER = mujoco.mjtGain.mjGAIN_USER
|
||||
|
||||
|
||||
class BiasType(enum.IntEnum):
|
||||
@@ -264,12 +286,13 @@ class BiasType(enum.IntEnum):
|
||||
NONE: no bias
|
||||
AFFINE: const + kp*length + kv*velocity
|
||||
MUSCLE: muscle passive force computed by muscle_bias
|
||||
USER: user-defined bias via act_bias_callback
|
||||
"""
|
||||
|
||||
NONE = mujoco.mjtBias.mjBIAS_NONE
|
||||
AFFINE = mujoco.mjtBias.mjBIAS_AFFINE
|
||||
MUSCLE = mujoco.mjtBias.mjBIAS_MUSCLE
|
||||
# unsupported: USER
|
||||
USER = mujoco.mjtBias.mjBIAS_USER
|
||||
|
||||
|
||||
class JointType(enum.IntEnum):
|
||||
@@ -462,6 +485,7 @@ class SensorType(enum.IntEnum):
|
||||
FRAMELINACC: 3D linear acceleration
|
||||
FRAMEANGACC: 3D angular acceleration
|
||||
TACTILE: tactile sensor
|
||||
USER: user-defined sensor via sensor_callback
|
||||
"""
|
||||
|
||||
MAGNETOMETER = mujoco.mjtSensor.mjSENS_MAGNETOMETER
|
||||
@@ -511,6 +535,7 @@ class SensorType(enum.IntEnum):
|
||||
FRAMELINACC = mujoco.mjtSensor.mjSENS_FRAMELINACC
|
||||
FRAMEANGACC = mujoco.mjtSensor.mjSENS_FRAMEANGACC
|
||||
TACTILE = mujoco.mjtSensor.mjSENS_TACTILE
|
||||
USER = mujoco.mjtSensor.mjSENS_USER
|
||||
|
||||
|
||||
class ObjType(enum.IntEnum):
|
||||
@@ -768,6 +793,29 @@ class TileSet:
|
||||
size: int
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Callback:
|
||||
"""Callbacks for custom physics behavior.
|
||||
|
||||
Attributes:
|
||||
passive: custom passive forces, writes to ``Data.qfrc_passive``
|
||||
control: custom control laws, writes to ``Data.ctrl``
|
||||
act_dyn: custom actuator dynamics, writes to ``Data.act_dot``
|
||||
act_gain: custom actuator gains, writes to ``Data.actuator_force``
|
||||
act_bias: custom actuator biases, writes to ``Data.actuator_force``
|
||||
sensor: custom sensors, writes to ``Data.sensordata``
|
||||
contactfilter: custom contact filtering, writes to ``Data.contact``
|
||||
"""
|
||||
|
||||
passive: Callable | None = None
|
||||
control: Callable | None = None
|
||||
act_dyn: Callable | None = None
|
||||
act_gain: Callable | None = None
|
||||
act_bias: Callable | None = None
|
||||
sensor: Callable | None = None
|
||||
contactfilter: Callable | None = None
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Model:
|
||||
"""Model definition and parameters.
|
||||
@@ -793,6 +841,7 @@ class Model:
|
||||
nflexelem: number of elements in all flexes
|
||||
nflexelemdata: number of element vertex ids in all flexes
|
||||
nflexelemedge: number of element edge ids in all flexes
|
||||
nJfe: number of non-zeros in sparse flexedge Jacobian
|
||||
nmesh: number of meshes
|
||||
nmeshvert: number of vertices for all meshes
|
||||
nmeshnormal: number of normals in all meshes
|
||||
@@ -812,6 +861,7 @@ class Model:
|
||||
nsensor: number of sensors
|
||||
nmocap: number of mocap bodies
|
||||
nplugin: number of plugin instances
|
||||
nJmom: number of non-zeros in actuator_moment
|
||||
ngravcomp: number of bodies with nonzero gravcomp
|
||||
nsensordata: number of elements in sensor data vector
|
||||
opt: physics options
|
||||
@@ -947,7 +997,9 @@ class Model:
|
||||
mesh_vertadr: first vertex address (nmesh,)
|
||||
mesh_vertnum: number of vertices (nmesh,)
|
||||
mesh_faceadr: first face address (nmesh,)
|
||||
mesh_octadr: octree address for each mesh (nmesh,)
|
||||
mesh_normaladr: first normal address (nmesh,)
|
||||
mesh_normalnum: number of normals (nmesh,)
|
||||
mesh_graphadr: graph data address; -1: no graph (nmesh,)
|
||||
mesh_vert: vertex positions for all meshes (nmeshvert, 3)
|
||||
mesh_normal: normals for all meshes (nmeshnormal, 3)
|
||||
@@ -968,7 +1020,8 @@ class Model:
|
||||
hfield_ncol: number of columns in grid (nhfield,)
|
||||
hfield_adr: start address in hfield_data (nhfield,)
|
||||
hfield_data: elevation data (nhfielddata,)
|
||||
mat_texid: texture id for rendering (*, nmat, mjNTEXROLE)
|
||||
mat_texid: texture id for rendering (*, nmat,
|
||||
mjNTEXROLE)
|
||||
mat_texrepeat: texture repeat for rendering (*, nmat, 2)
|
||||
mat_rgba: rgba (*, nmat, 4)
|
||||
pair_dim: contact dimensionality (npair,)
|
||||
@@ -993,10 +1046,14 @@ class Model:
|
||||
tendon_num: number of objects in tendon's path (ntendon,)
|
||||
tendon_limited: does tendon have length limits (ntendon,)
|
||||
tendon_actfrclimited: does ten have actuator force limit (ntendon,)
|
||||
tendon_solref_lim: constraint solver reference: limit (*, ntendon, mjNREF)
|
||||
tendon_solimp_lim: constraint solver impedance: limit (*, ntendon, mjNIMP)
|
||||
tendon_solref_fri: constraint solver reference: friction (*, ntendon, mjNREF)
|
||||
tendon_solimp_fri: constraint solver impedance: friction (*, ntendon, mjNIMP)
|
||||
tendon_solref_lim: constraint solver reference: limit (*, ntendon,
|
||||
mjNREF)
|
||||
tendon_solimp_lim: constraint solver impedance: limit (*, ntendon,
|
||||
mjNIMP)
|
||||
tendon_solref_fri: constraint solver reference: friction (*, ntendon,
|
||||
mjNREF)
|
||||
tendon_solimp_fri: constraint solver impedance: friction (*, ntendon,
|
||||
mjNIMP)
|
||||
tendon_range: tendon length limits (*, ntendon, 2)
|
||||
tendon_actfrcrange: range of total actuator force (*, ntendon, 2)
|
||||
tendon_margin: min distance for limit detection (*, ntendon)
|
||||
@@ -1028,9 +1085,9 @@ class Model:
|
||||
actuator_forcerange: range of forces (*, nu, 2)
|
||||
actuator_actrange: range of activations (*, nu, 2)
|
||||
actuator_gear: scale length and transmitted force (*, nu, 6)
|
||||
actuator_cranklength: crank length for slider-crank (nu,)
|
||||
actuator_acc0: acceleration from unit force in qpos0 (nu,)
|
||||
actuator_lengthrange: feasible actuator length range (nu, 2)
|
||||
actuator_cranklength: crank length for slider-crank (*, nu)
|
||||
actuator_acc0: acceleration from unit force in qpos0 (*, nu)
|
||||
actuator_lengthrange: feasible actuator length range (*, nu, 2)
|
||||
sensor_type: sensor type (SensorType) (nsensor,)
|
||||
sensor_datatype: numeric data type (DataType) (nsensor,)
|
||||
sensor_objtype: type of sensorized object (ObjType) (nsensor,)
|
||||
@@ -1049,6 +1106,7 @@ class Model:
|
||||
mapM2M: index mapping from M (legacy) to M (CSR) (nC)
|
||||
|
||||
warp only fields:
|
||||
callback: custom physics callbacks
|
||||
nbranch: number of branches (leaf-to-root paths)
|
||||
nv_pad: number of degrees of freedom + padding
|
||||
nacttrnbody: number of actuators with body transmission
|
||||
@@ -1062,12 +1120,14 @@ class Model:
|
||||
nmaxpolygon: maximum number of verts per polygon
|
||||
nmaxmeshdeg: maximum number of polygons per vert
|
||||
is_sparse: whether to use sparse representations
|
||||
has_fluid: True if wind, density, or viscosity are non-zero at put_model time
|
||||
has_fluid: True if wind, density, or viscosity are non-zero at put_model
|
||||
time
|
||||
has_sdf_geom: whether the model contains SDF geoms
|
||||
block_dim: block dim options
|
||||
body_tree: list of body ids by tree level
|
||||
body_branches: flattened body ids for all branches
|
||||
body_branch_start: start index in body_branches for each branch (nbranch + 1,)
|
||||
body_branch_start: start index in body_branches for each branch (nbranch +
|
||||
1,)
|
||||
mocap_bodyid: id of body for mocap (nmocap,)
|
||||
body_fluid_ellipsoid: does body use ellipsoid fluid (nbody,)
|
||||
jnt_limited_slide_hinge_adr: limited/slide/hinge jntadr
|
||||
@@ -1156,6 +1216,7 @@ class Model:
|
||||
nflexelem: int
|
||||
nflexelemdata: int
|
||||
nflexelemedge: int
|
||||
nJfe: int
|
||||
nmesh: int
|
||||
nmeshvert: int
|
||||
nmeshnormal: int
|
||||
@@ -1175,6 +1236,7 @@ class Model:
|
||||
nsensor: int
|
||||
nmocap: int
|
||||
nplugin: int
|
||||
nJmom: int
|
||||
ngravcomp: int
|
||||
nsensordata: int
|
||||
opt: Option
|
||||
@@ -1306,11 +1368,13 @@ class Model:
|
||||
flex_damping: array("nflex", float)
|
||||
flexedge_J_rownnz: array("nflexedge", int)
|
||||
flexedge_J_rowadr: array("nflexedge", int)
|
||||
flexedge_J_colind: wp.array(dtype=int)
|
||||
flexedge_J_colind: array("nJfe", int)
|
||||
mesh_vertadr: array("nmesh", int)
|
||||
mesh_vertnum: array("nmesh", int)
|
||||
mesh_faceadr: array("nmesh", int)
|
||||
mesh_octadr: array("nmesh", int)
|
||||
mesh_normaladr: array("nmesh", int)
|
||||
mesh_normalnum: array("nmesh", int)
|
||||
mesh_graphadr: array("nmesh", int)
|
||||
mesh_vert: array("nmeshvert", wp.vec3)
|
||||
mesh_normal: array("nmeshnormal", wp.vec3)
|
||||
@@ -1391,9 +1455,9 @@ class Model:
|
||||
actuator_forcerange: array("*", "nu", wp.vec2)
|
||||
actuator_actrange: array("*", "nu", wp.vec2)
|
||||
actuator_gear: array("*", "nu", wp.spatial_vector)
|
||||
actuator_cranklength: array("nu", float)
|
||||
actuator_acc0: array("nu", float)
|
||||
actuator_lengthrange: array("nu", wp.vec2)
|
||||
actuator_cranklength: array("*", "nu", float)
|
||||
actuator_acc0: array("*", "nu", float)
|
||||
actuator_lengthrange: array("*", "nu", wp.vec2)
|
||||
sensor_type: array("nsensor", int)
|
||||
sensor_datatype: array("nsensor", int)
|
||||
sensor_objtype: array("nsensor", int)
|
||||
@@ -1411,6 +1475,7 @@ class Model:
|
||||
M_colind: array("nC", int)
|
||||
mapM2M: array("nC", int)
|
||||
# warp only fields:
|
||||
callback: Callback
|
||||
nbranch: int
|
||||
nv_pad: int
|
||||
nacttrnbody: int
|
||||
@@ -1546,7 +1611,14 @@ class Constraint:
|
||||
Attributes:
|
||||
type: constraint type (ConstraintType) (nworld, njmax)
|
||||
id: id of object of specific type (nworld, njmax)
|
||||
J: constraint Jacobian (nworld, njmax_pad, nv_pad)
|
||||
J_rownnz: number of non-zeros in J row (nworld, 0) dense (nworld,
|
||||
njmax) sparse
|
||||
J_rowadr: row start address in colind array (nworld, 0) dense (nworld,
|
||||
njmax) sparse
|
||||
J_colind: column indices in J (nworld, 0, 0) dense
|
||||
(nworld, 1, njmax * nv) sparse
|
||||
J: constraint Jacobian (nworld, njmax_pad,
|
||||
nv_pad) dense (nworld, 1, njmax * nv) sparse
|
||||
pos: constraint position (equality, contact) (nworld, njmax)
|
||||
margin: inclusion margin (contact) (nworld, njmax)
|
||||
D: constraint mass (nworld, njmax_pad)
|
||||
@@ -1555,13 +1627,17 @@ class Constraint:
|
||||
frictionloss: frictionloss (friction) (nworld, njmax)
|
||||
force: constraint force in constraint space (nworld, njmax)
|
||||
state: constraint state (nworld, njmax_pad)
|
||||
|
||||
warp only fields:
|
||||
Ma: M*qacc (nworld, nv)
|
||||
"""
|
||||
|
||||
type: array("nworld", "njmax", int)
|
||||
id: array("nworld", "njmax", int)
|
||||
J: array("nworld", "njmax_pad", "nv_pad", float)
|
||||
J_rownnz: wp.array2d(dtype=int)
|
||||
J_rowadr: wp.array2d(dtype=int)
|
||||
J_colind: wp.array3d(dtype=int)
|
||||
J: wp.array3d(dtype=float)
|
||||
pos: array("nworld", "njmax", float)
|
||||
margin: array("nworld", "njmax", float)
|
||||
D: array("nworld", "njmax_pad", float)
|
||||
@@ -1583,6 +1659,7 @@ class Data:
|
||||
nf: number of friction constraints (nworld,)
|
||||
nl: number of limit constraints (nworld,)
|
||||
nefc: number of constraints (nworld,)
|
||||
nisland: number of constraint islands (nworld,)
|
||||
time: simulation time (nworld,)
|
||||
energy: potential, kinetic energy (nworld, 2)
|
||||
qpos: position (nworld, nq)
|
||||
@@ -1591,52 +1668,88 @@ class Data:
|
||||
qacc_warmstart: acceleration used for warmstart (nworld, nv)
|
||||
ctrl: control (nworld, nu)
|
||||
qfrc_applied: applied generalized force (nworld, nv)
|
||||
xfrc_applied: applied Cartesian force/torque (nworld, nbody, 6)
|
||||
xfrc_applied: applied Cartesian force/torque (nworld, nbody,
|
||||
6)
|
||||
eq_active: enable/disable constraints (nworld, neq)
|
||||
mocap_pos: position of mocap bodies (nworld, nmocap, 3)
|
||||
mocap_quat: orientation of mocap bodies (nworld, nmocap, 4)
|
||||
mocap_pos: position of mocap bodies (nworld, nmocap,
|
||||
3)
|
||||
mocap_quat: orientation of mocap bodies (nworld, nmocap,
|
||||
4)
|
||||
qacc: acceleration (nworld, nv)
|
||||
act_dot: time-derivative of actuator activation (nworld, na)
|
||||
sensordata: sensor data array (nworld, nsensordata,)
|
||||
xpos: Cartesian position of body frame (nworld, nbody, 3)
|
||||
xquat: Cartesian orientation of body frame (nworld, nbody, 4)
|
||||
xmat: Cartesian orientation of body frame (nworld, nbody, 3, 3)
|
||||
xipos: Cartesian position of body com (nworld, nbody, 3)
|
||||
ximat: Cartesian orientation of body inertia (nworld, nbody, 3, 3)
|
||||
xanchor: Cartesian position of joint anchor (nworld, njnt, 3)
|
||||
xaxis: Cartesian joint axis (nworld, njnt, 3)
|
||||
geom_xpos: Cartesian geom position (nworld, ngeom, 3)
|
||||
geom_xmat: Cartesian geom orientation (nworld, ngeom, 3, 3)
|
||||
site_xpos: Cartesian site position (nworld, nsite, 3)
|
||||
site_xmat: Cartesian site orientation (nworld, nsite, 3, 3)
|
||||
cam_xpos: Cartesian camera position (nworld, ncam, 3)
|
||||
cam_xmat: Cartesian camera orientation (nworld, ncam, 3, 3)
|
||||
light_xpos: Cartesian light position (nworld, nlight, 3)
|
||||
light_xdir: Cartesian light direction (nworld, nlight, 3)
|
||||
subtree_com: center of mass of each subtree (nworld, nbody, 3)
|
||||
sensordata: sensor data array (nworld,
|
||||
nsensordata,)
|
||||
xpos: Cartesian position of body frame (nworld, nbody,
|
||||
3)
|
||||
xquat: Cartesian orientation of body frame (nworld, nbody,
|
||||
4)
|
||||
xmat: Cartesian orientation of body frame (nworld, nbody,
|
||||
3, 3)
|
||||
xipos: Cartesian position of body com (nworld, nbody,
|
||||
3)
|
||||
ximat: Cartesian orientation of body inertia (nworld, nbody,
|
||||
3, 3)
|
||||
xanchor: Cartesian position of joint anchor (nworld, njnt,
|
||||
3)
|
||||
xaxis: Cartesian joint axis (nworld, njnt,
|
||||
3)
|
||||
geom_xpos: Cartesian geom position (nworld, ngeom,
|
||||
3)
|
||||
geom_xmat: Cartesian geom orientation (nworld, ngeom,
|
||||
3, 3)
|
||||
site_xpos: Cartesian site position (nworld, nsite,
|
||||
3)
|
||||
site_xmat: Cartesian site orientation (nworld, nsite,
|
||||
3, 3)
|
||||
cam_xpos: Cartesian camera position (nworld, ncam,
|
||||
3)
|
||||
cam_xmat: Cartesian camera orientation (nworld, ncam,
|
||||
3, 3)
|
||||
light_xpos: Cartesian light position (nworld, nlight,
|
||||
3)
|
||||
light_xdir: Cartesian light direction (nworld, nlight,
|
||||
3)
|
||||
subtree_com: center of mass of each subtree (nworld, nbody,
|
||||
3)
|
||||
cdof: com-based motion axis of each dof (rot:lin) (nworld, nv, 6)
|
||||
cinert: com-based body inertia and mass (nworld, nbody, 10)
|
||||
flexvert_xpos: cartesian flex vertex positions (nworld, nflexvert, 3)
|
||||
flexedge_J: edge length Jacobian (nworld, 1, nflexedge*6)
|
||||
flexedge_length: flex edge lengths (nworld, nflexedge, 1)
|
||||
ten_wrapadr: start address of tendon's path (nworld, ntendon)
|
||||
ten_wrapnum: number of wrap points in path (nworld, ntendon)
|
||||
ten_J: tendon Jacobian (nworld, ntendon, nv)
|
||||
ten_length: tendon lengths (nworld, ntendon)
|
||||
wrap_obj: geomid; -1: site; -2: pulley (nworld, nwrap, 2)
|
||||
wrap_xpos: Cartesian 3D points in all paths (nworld, nwrap, 6)
|
||||
cinert: com-based body inertia and mass (nworld, nbody,
|
||||
10)
|
||||
flexvert_xpos: cartesian flex vertex positions (nworld,
|
||||
nflexvert, 3)
|
||||
flexedge_J: edge length Jacobian (nworld, nJfe)
|
||||
flexedge_length: flex edge lengths (nworld,
|
||||
nflexedge, 1)
|
||||
ten_wrapadr: start address of tendon's path (nworld,
|
||||
ntendon)
|
||||
ten_wrapnum: number of wrap points in path (nworld,
|
||||
ntendon)
|
||||
ten_J: tendon Jacobian (nworld,
|
||||
ntendon, nv)
|
||||
ten_length: tendon lengths (nworld,
|
||||
ntendon)
|
||||
wrap_obj: geomid; -1: site; -2: pulley (nworld, nwrap,
|
||||
2)
|
||||
wrap_xpos: Cartesian 3D points in all paths (nworld, nwrap,
|
||||
6)
|
||||
actuator_length: actuator lengths (nworld, nu)
|
||||
actuator_moment: actuator moments (nworld, nu, nv)
|
||||
crb: com-based composite inertia and mass (nworld, nbody, 10)
|
||||
qM: total inertia (nworld, nv, nv) if dense
|
||||
(nworld, 1, nM) if sparse
|
||||
qLD: L'*D*L factorization of M (nworld, nv, nv) if dense
|
||||
(nworld, 1, nC) if sparse
|
||||
moment_rownnz: number of non-zeros in actuator_moment row (nworld, nu)
|
||||
moment_rowadr: row start address in actuator_moment (nworld, nu)
|
||||
moment_colind: column indices in sparse actuator_moment (nworld, nJmom)
|
||||
actuator_moment: actuator moments (nworld, nJmom)
|
||||
crb: com-based composite inertia and mass (nworld, nbody,
|
||||
10)
|
||||
qM: total inertia (nworld, nv, nv)
|
||||
if dense (nworld, 1, nM) if sparse
|
||||
qLD: L'*D*L factorization of M (nworld, nv, nv)
|
||||
if dense (nworld, 1, nC) if sparse
|
||||
qLDiagInv: 1/diag(D) (nworld, nv)
|
||||
flexedge_velocity: flex edge velocities (nworld, nflexedge)
|
||||
ten_velocity: tendon velocities (nworld, ntendon)
|
||||
flexedge_velocity: flex edge velocities (nworld,
|
||||
nflexedge)
|
||||
ten_velocity: tendon velocities (nworld,
|
||||
ntendon)
|
||||
actuator_velocity: actuator velocities (nworld, nu)
|
||||
cvel: com-based velocity (rot:lin) (nworld, nbody, 6)
|
||||
cvel: com-based velocity (rot:lin) (nworld, nbody,
|
||||
6)
|
||||
cdof_dot: time-derivative of cdof (rot:lin) (nworld, nv, 6)
|
||||
qfrc_bias: C(qpos,qvel) (nworld, nv)
|
||||
qfrc_spring: passive spring force (nworld, nv)
|
||||
@@ -1644,27 +1757,33 @@ class Data:
|
||||
qfrc_gravcomp: passive gravity compensation force (nworld, nv)
|
||||
qfrc_fluid: passive fluid force (nworld, nv)
|
||||
qfrc_passive: total passive force (nworld, nv)
|
||||
subtree_linvel: linear velocity of subtree com (nworld, nbody, 3)
|
||||
subtree_angmom: angular momentum about subtree com (nworld, nbody, 3)
|
||||
subtree_linvel: linear velocity of subtree com (nworld, nbody,
|
||||
3)
|
||||
subtree_angmom: angular momentum about subtree com (nworld, nbody,
|
||||
3)
|
||||
actuator_force: actuator force in actuation space (nworld, nu)
|
||||
qfrc_actuator: actuator force (nworld, nv)
|
||||
qfrc_smooth: net unconstrained force (nworld, nv)
|
||||
qacc_smooth: unconstrained acceleration (nworld, nv)
|
||||
qfrc_constraint: constraint force (nworld, nv)
|
||||
qfrc_inverse: net external force; should equal: (nworld, nv)
|
||||
qfrc_applied + J.T @ xfrc_applied
|
||||
+ qfrc_actuator
|
||||
cacc: com-based acceleration (nworld, nbody, 6)
|
||||
cfrc_int: com-based interaction force with parent (nworld, nbody, 6)
|
||||
cfrc_ext: com-based external force on body (nworld, nbody, 6)
|
||||
qfrc_applied + J.T @ xfrc_applied + qfrc_actuator
|
||||
cacc: com-based acceleration (nworld, nbody,
|
||||
6)
|
||||
cfrc_int: com-based interaction force with parent (nworld, nbody,
|
||||
6)
|
||||
cfrc_ext: com-based external force on body (nworld, nbody,
|
||||
6)
|
||||
contact: contact data
|
||||
efc: constraint data
|
||||
tree_island: island ID per tree (-1 if unconstrained) (nworld, ntree)
|
||||
|
||||
warp only fields:
|
||||
nworld: number of worlds
|
||||
naconmax: maximum number of contacts (shared across all worlds)
|
||||
naccdmax: maximum number of contacts for CCD (all worlds)
|
||||
njmax: maximum number of constraints per world
|
||||
njmax_pad: njmax rounded up to the nearest multiple of TILE_SIZE_JTDAJ
|
||||
nacon: number of detected contacts (across all worlds) (1,)
|
||||
ncollision: collision count from broadphase (1,)
|
||||
"""
|
||||
@@ -1674,6 +1793,7 @@ class Data:
|
||||
nf: array("nworld", int)
|
||||
nl: array("nworld", int)
|
||||
nefc: array("nworld", int)
|
||||
nisland: array("nworld", int)
|
||||
time: array("nworld", float)
|
||||
energy: array("nworld", wp.vec2)
|
||||
qpos: array("nworld", "nq", float)
|
||||
@@ -1708,7 +1828,7 @@ class Data:
|
||||
cdof: array("nworld", "nv", wp.spatial_vector)
|
||||
cinert: array("nworld", "nbody", vec10)
|
||||
flexvert_xpos: array("nworld", "nflexvert", wp.vec3)
|
||||
flexedge_J: wp.array3d(dtype=float)
|
||||
flexedge_J: array("nworld", "nJfe", float)
|
||||
flexedge_length: array("nworld", "nflexedge", float)
|
||||
ten_wrapadr: array("nworld", "ntendon", int)
|
||||
ten_wrapnum: array("nworld", "ntendon", int)
|
||||
@@ -1717,7 +1837,10 @@ class Data:
|
||||
wrap_obj: array("nworld", "nwrap", wp.vec2i)
|
||||
wrap_xpos: array("nworld", "nwrap", wp.spatial_vector)
|
||||
actuator_length: array("nworld", "nu", float)
|
||||
actuator_moment: array("nworld", "nu", "nv", float)
|
||||
moment_rownnz: array("nworld", "nu", int)
|
||||
moment_rowadr: array("nworld", "nu", int)
|
||||
moment_colind: array("nworld", "nJmom", int)
|
||||
actuator_moment: array("nworld", "nJmom", float)
|
||||
crb: array("nworld", "nbody", vec10)
|
||||
qM: wp.array3d(dtype=float)
|
||||
qLD: wp.array3d(dtype=float)
|
||||
@@ -1746,31 +1869,18 @@ class Data:
|
||||
cfrc_ext: array("nworld", "nbody", wp.spatial_vector)
|
||||
contact: Contact
|
||||
efc: Constraint
|
||||
tree_island: array("nworld", "ntree", int)
|
||||
|
||||
# warp only fields:
|
||||
nworld: int
|
||||
naconmax: int
|
||||
naccdmax: int
|
||||
njmax: int
|
||||
njmax_pad: int
|
||||
nacon: array(1, int)
|
||||
ncollision: array(1, int)
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class CollisionContext:
|
||||
"""Collision driver intermediate arrays.
|
||||
|
||||
Attributes:
|
||||
collision_pair: collision pairs from broadphase (naconmax, 2)
|
||||
collision_pairid: ids from broadphase (naconmax, 2)
|
||||
collision_worldid: collision world ids from broadphase (naconmax,)
|
||||
"""
|
||||
|
||||
collision_pair: wp.array
|
||||
collision_pairid: wp.array
|
||||
collision_worldid: wp.array
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class RenderContext:
|
||||
"""Context for rendering.
|
||||
@@ -1794,7 +1904,7 @@ class RenderContext:
|
||||
textures_registry: texture registry
|
||||
hfield_registry: hfield BVH id to warp mesh mapping
|
||||
hfield_bvh_id: hfield BVH ids
|
||||
hfield_bounds_size: hfield bounds size
|
||||
hfield_bounds_size: hfield bounds half-extents
|
||||
flex_mesh: flex mesh
|
||||
flex_rgba: flex rgba
|
||||
flex_bvh_id: flex BVH id
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
# Copyright 2026 The Newton Developers
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
"""Package version checking utilities."""
|
||||
|
||||
import importlib.metadata
|
||||
import operator
|
||||
import re
|
||||
|
||||
|
||||
def _parse_version(version_str: str) -> tuple[tuple[int, int | str], ...]:
|
||||
"""Parse a version string into comparable components.
|
||||
|
||||
Both '.' and '-' are treated as separators. Each component is wrapped in a
|
||||
tuple: (0, int) for numeric parts, (-1, str) for non-numeric. A (0, 0)
|
||||
sentinel is appended so that stable releases sort above pre-release suffixes
|
||||
during Python tuple comparison (e.g., 1.2.3 >= 1.2.3.dev). Non-numeric
|
||||
components are compared lexicographically (e.g., b >= a).
|
||||
|
||||
Args:
|
||||
version_str: Version string like "3.5.0" or "3.5.0.dev869102767".
|
||||
|
||||
Returns:
|
||||
Tuple of (type_order, value) pairs for comparison, where type_order is 0
|
||||
for integers and -1 for strings, followed by a (0, 0) sentinel.
|
||||
"""
|
||||
# Split on both '.' and '-'
|
||||
parts = re.split(r"[.\-]", version_str)
|
||||
return tuple(
|
||||
[(0, int(p)) if p.isdigit() else (-1, p) for p in parts] + [(0, 0)]
|
||||
)
|
||||
|
||||
|
||||
def check_version(spec: str) -> bool:
|
||||
"""Check if an installed package satisfies a version requirement.
|
||||
|
||||
Supports operators: >=, <=, >, <, ==, !=
|
||||
|
||||
Version comparison rules:
|
||||
- Both '.' and '-' are treated as separators
|
||||
- Numeric components are compared numerically
|
||||
- Non-numeric components are compared lexicographically
|
||||
- Stable releases are greater than pre-releases (e.g., 1.2.3 >= 1.2.3.dev)
|
||||
|
||||
Args:
|
||||
spec: Version specification like "numpy>=1.20.0".
|
||||
|
||||
Returns:
|
||||
True if the installed version satisfies the requirement.
|
||||
|
||||
Raises:
|
||||
ValueError: If the spec cannot be parsed.
|
||||
importlib.metadata.PackageNotFoundError: If the package is not installed.
|
||||
"""
|
||||
match = re.match(r"^([a-zA-Z0-9_\-]+)(>=|<=|>|<|==|!=)(.+)$", spec)
|
||||
if not match:
|
||||
raise ValueError(
|
||||
f"Invalid version spec '{spec}'. Expected format: 'package>=version'"
|
||||
)
|
||||
package_name, op, version_str = match.groups()
|
||||
|
||||
required_version = _parse_version(version_str)
|
||||
|
||||
try:
|
||||
installed_str = importlib.metadata.version(package_name)
|
||||
except importlib.metadata.PackageNotFoundError as e:
|
||||
# Fallback: import the package and read __version__
|
||||
try:
|
||||
import importlib as _importlib # noqa: F811
|
||||
|
||||
mod = _importlib.import_module(package_name)
|
||||
installed_str = mod.__version__
|
||||
except (ImportError, AttributeError):
|
||||
raise e
|
||||
|
||||
installed_version = _parse_version(installed_str)
|
||||
|
||||
ops = {
|
||||
">=": operator.ge,
|
||||
"<=": operator.le,
|
||||
">": operator.gt,
|
||||
"<": operator.lt,
|
||||
"==": operator.eq,
|
||||
"!=": operator.ne,
|
||||
}
|
||||
return ops[op](installed_version, required_version)
|
||||
+35
-1
@@ -15,6 +15,7 @@
|
||||
|
||||
import functools
|
||||
import inspect
|
||||
import warnings
|
||||
|
||||
import warp as wp
|
||||
|
||||
@@ -144,4 +145,37 @@ def check_toolkit_driver():
|
||||
wp.init()
|
||||
if wp.get_device().is_cuda:
|
||||
if not wp.is_conditional_graph_supported():
|
||||
raise RuntimeError("Minimum supported CUDA version: 12.4.")
|
||||
warnings.warn(
|
||||
"""
|
||||
CUDA version < 12.4 detected
|
||||
- graph capture may be unreliable for < 12.3
|
||||
- conditional graph nodes are not available for < 12.4
|
||||
Model.opt.graph_conditional should be set to False
|
||||
""",
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
|
||||
class scoped_mathdx_gemm_disabled:
|
||||
"""Temporarily disable Warp MathDx GEMM kernels within this scope."""
|
||||
|
||||
def __init__(self, disable: bool = True):
|
||||
self._disable = disable
|
||||
self._config = None
|
||||
self._prev = None
|
||||
|
||||
def __enter__(self):
|
||||
if not self._disable:
|
||||
return self
|
||||
config = getattr(wp, "config", None)
|
||||
if config is None or not hasattr(config, "enable_mathdx_gemm"):
|
||||
return self
|
||||
self._config = config
|
||||
self._prev = config.enable_mathdx_gemm
|
||||
self._config.enable_mathdx_gemm = False
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc, tb):
|
||||
if self._config is not None:
|
||||
self._config.enable_mathdx_gemm = self._prev
|
||||
return False
|
||||
|
||||
+5
-4
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name="mujoco-warp"
|
||||
version = "3.5.0"
|
||||
version = "3.6.0"
|
||||
# TODO(team): create a distribution list
|
||||
authors = [
|
||||
{name = "Newton Developers", email = "mujoco@deepmind.com"},
|
||||
@@ -21,15 +21,16 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Topic :: Scientific/Engineering",
|
||||
]
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
"absl-py",
|
||||
"etils[epath]",
|
||||
"mujoco>=3.4.0",
|
||||
"mujoco>=3.5.0",
|
||||
"numpy",
|
||||
"warp-lang>=1.11.0",
|
||||
"warp-lang>=1.12",
|
||||
]
|
||||
|
||||
[[tool.uv.index]]
|
||||
@@ -54,7 +55,7 @@ dev = [
|
||||
"ruff",
|
||||
"pygls>=1.0.0,<2.0.0",
|
||||
"lsprotocol>=2023.0.1,<2024.0.0",
|
||||
"mujoco>=3.4.1.dev0",
|
||||
"mujoco>=3.5.0.dev0",
|
||||
"warp-lang>=1.11.0.dev0",
|
||||
]
|
||||
# TODO(team): cpu and cuda JAX optional dependencies are temporary, remove after we land MJX:Warp
|
||||
|
||||
@@ -44,6 +44,9 @@ _c = mjwarp.Contact(
|
||||
_e = mjwarp.Constraint(
|
||||
**{f.name: None for f in dataclasses.fields(mjwarp.Constraint) if f.init}
|
||||
)
|
||||
_cb = mjwp_types.Callback(
|
||||
**{f.name: None for f in dataclasses.fields(mjwp_types.Callback) if f.init}
|
||||
)
|
||||
|
||||
@ffi.format_args_for_warp
|
||||
def _refit_bvh_shim(
|
||||
@@ -70,6 +73,7 @@ def _refit_bvh_shim(
|
||||
):
|
||||
_m.stat = _s
|
||||
_m.opt = _o
|
||||
_m.callback = _cb
|
||||
_d.efc = _e
|
||||
_d.contact = _c
|
||||
_m.flex_dim = flex_dim
|
||||
|
||||
@@ -42,6 +42,10 @@ _c = mjwarp.Contact(
|
||||
_e = mjwarp.Constraint(
|
||||
**{f.name: None for f in dataclasses.fields(mjwarp.Constraint) if f.init}
|
||||
)
|
||||
_cb = mjwp_types.Callback(
|
||||
**{f.name: None for f in dataclasses.fields(mjwp_types.Callback) if f.init}
|
||||
)
|
||||
|
||||
|
||||
@ffi.format_args_for_warp
|
||||
def _collision_shim(
|
||||
@@ -73,6 +77,7 @@ def _collision_shim(
|
||||
mesh_faceadr: wp.array(dtype=int),
|
||||
mesh_graph: wp.array(dtype=int),
|
||||
mesh_graphadr: wp.array(dtype=int),
|
||||
mesh_octadr: wp.array(dtype=int),
|
||||
mesh_polyadr: wp.array(dtype=int),
|
||||
mesh_polymap: wp.array(dtype=int),
|
||||
mesh_polymapadr: wp.array(dtype=int),
|
||||
@@ -135,6 +140,7 @@ def _collision_shim(
|
||||
):
|
||||
_m.stat = _s
|
||||
_m.opt = _o
|
||||
_m.callback = _cb
|
||||
_d.efc = _e
|
||||
_d.contact = _c
|
||||
_m.block_dim = block_dim
|
||||
@@ -163,6 +169,7 @@ def _collision_shim(
|
||||
_m.mesh_faceadr = mesh_faceadr
|
||||
_m.mesh_graph = mesh_graph
|
||||
_m.mesh_graphadr = mesh_graphadr
|
||||
_m.mesh_octadr = mesh_octadr
|
||||
_m.mesh_polyadr = mesh_polyadr
|
||||
_m.mesh_polymap = mesh_polymap
|
||||
_m.mesh_polymapadr = mesh_polymapadr
|
||||
@@ -317,6 +324,7 @@ def _collision_jax_impl(m: types.Model, d: types.Data):
|
||||
m.mesh_faceadr,
|
||||
m.mesh_graph,
|
||||
m.mesh_graphadr,
|
||||
m.mesh_octadr,
|
||||
m._impl.mesh_polyadr,
|
||||
m._impl.mesh_polymap,
|
||||
m._impl.mesh_polymapadr,
|
||||
|
||||
+281
-151
@@ -42,6 +42,10 @@ _c = mjwarp.Contact(
|
||||
_e = mjwarp.Constraint(
|
||||
**{f.name: None for f in dataclasses.fields(mjwarp.Constraint) if f.init}
|
||||
)
|
||||
_cb = mjwp_types.Callback(
|
||||
**{f.name: None for f in dataclasses.fields(mjwp_types.Callback) if f.init}
|
||||
)
|
||||
|
||||
|
||||
@ffi.format_args_for_warp
|
||||
def _forward_shim(
|
||||
@@ -49,7 +53,7 @@ def _forward_shim(
|
||||
nworld: int,
|
||||
M_rowadr: wp.array(dtype=int),
|
||||
M_rownnz: wp.array(dtype=int),
|
||||
actuator_acc0: wp.array(dtype=float),
|
||||
actuator_acc0: wp.array2d(dtype=float),
|
||||
actuator_actadr: wp.array(dtype=int),
|
||||
actuator_actearly: wp.array(dtype=bool),
|
||||
actuator_actlimited: wp.array(dtype=bool),
|
||||
@@ -57,7 +61,7 @@ def _forward_shim(
|
||||
actuator_actrange: wp.array2d(dtype=wp.vec2),
|
||||
actuator_biasprm: wp.array2d(dtype=mjwp_types.vec10f),
|
||||
actuator_biastype: wp.array(dtype=int),
|
||||
actuator_cranklength: wp.array(dtype=float),
|
||||
actuator_cranklength: wp.array2d(dtype=float),
|
||||
actuator_ctrllimited: wp.array(dtype=bool),
|
||||
actuator_ctrlrange: wp.array2d(dtype=wp.vec2),
|
||||
actuator_dynprm: wp.array2d(dtype=mjwp_types.vec10f),
|
||||
@@ -67,7 +71,7 @@ def _forward_shim(
|
||||
actuator_gainprm: wp.array2d(dtype=mjwp_types.vec10f),
|
||||
actuator_gaintype: wp.array(dtype=int),
|
||||
actuator_gear: wp.array2d(dtype=wp.spatial_vector),
|
||||
actuator_lengthrange: wp.array(dtype=wp.vec2),
|
||||
actuator_lengthrange: wp.array2d(dtype=wp.vec2),
|
||||
actuator_trnid: wp.array(dtype=wp.vec2i),
|
||||
actuator_trntype: wp.array(dtype=int),
|
||||
actuator_trntype_body_adr: wp.array(dtype=int),
|
||||
@@ -94,6 +98,7 @@ def _forward_shim(
|
||||
body_rootid: wp.array(dtype=int),
|
||||
body_subtreemass: wp.array2d(dtype=float),
|
||||
body_tree: tuple[wp.array(dtype=int), ...],
|
||||
body_treeid: wp.array(dtype=int),
|
||||
body_weldid: wp.array(dtype=int),
|
||||
cam_bodyid: wp.array(dtype=int),
|
||||
cam_fovy: wp.array2d(dtype=float),
|
||||
@@ -117,6 +122,7 @@ def _forward_shim(
|
||||
dof_parentid: wp.array(dtype=int),
|
||||
dof_solimp: wp.array2d(dtype=mjwp_types.vec5),
|
||||
dof_solref: wp.array2d(dtype=wp.vec2),
|
||||
dof_treeid: wp.array(dtype=int),
|
||||
dof_tri_col: wp.array(dtype=int),
|
||||
dof_tri_row: wp.array(dtype=int),
|
||||
eq_connect_adr: wp.array(dtype=int),
|
||||
@@ -214,6 +220,7 @@ def _forward_shim(
|
||||
mesh_normal: wp.array(dtype=wp.vec3),
|
||||
mesh_normaladr: wp.array(dtype=int),
|
||||
mesh_normalnum: wp.array(dtype=int),
|
||||
mesh_octadr: wp.array(dtype=int),
|
||||
mesh_polyadr: wp.array(dtype=int),
|
||||
mesh_polymap: wp.array(dtype=int),
|
||||
mesh_polymapadr: wp.array(dtype=int),
|
||||
@@ -253,6 +260,7 @@ def _forward_shim(
|
||||
nsensortaxel: int,
|
||||
nsite: int,
|
||||
ntendon: int,
|
||||
ntree: int,
|
||||
nu: int,
|
||||
nv: int,
|
||||
nv_pad: int,
|
||||
@@ -378,7 +386,7 @@ def _forward_shim(
|
||||
act_dot: wp.array2d(dtype=float),
|
||||
actuator_force: wp.array2d(dtype=float),
|
||||
actuator_length: wp.array2d(dtype=float),
|
||||
actuator_moment: wp.array3d(dtype=float),
|
||||
actuator_moment: wp.array2d(dtype=float),
|
||||
actuator_velocity: wp.array2d(dtype=float),
|
||||
cacc: wp.array2d(dtype=wp.spatial_vector),
|
||||
cam_xmat: wp.array2d(dtype=wp.mat33),
|
||||
@@ -393,7 +401,7 @@ def _forward_shim(
|
||||
cvel: wp.array2d(dtype=wp.spatial_vector),
|
||||
energy: wp.array(dtype=wp.vec2),
|
||||
eq_active: wp.array2d(dtype=bool),
|
||||
flexedge_J: wp.array3d(dtype=float),
|
||||
flexedge_J: wp.array2d(dtype=float),
|
||||
flexedge_length: wp.array2d(dtype=float),
|
||||
flexedge_velocity: wp.array2d(dtype=float),
|
||||
flexvert_xpos: wp.array2d(dtype=wp.vec3),
|
||||
@@ -403,11 +411,15 @@ def _forward_shim(
|
||||
light_xpos: wp.array2d(dtype=wp.vec3),
|
||||
mocap_pos: wp.array2d(dtype=wp.vec3),
|
||||
mocap_quat: wp.array2d(dtype=wp.quat),
|
||||
moment_colind: wp.array2d(dtype=int),
|
||||
moment_rowadr: wp.array2d(dtype=int),
|
||||
moment_rownnz: wp.array2d(dtype=int),
|
||||
nacon: wp.array(dtype=int),
|
||||
ncollision: wp.array(dtype=int),
|
||||
ne: wp.array(dtype=int),
|
||||
nefc: wp.array(dtype=int),
|
||||
nf: wp.array(dtype=int),
|
||||
nisland: wp.array(dtype=int),
|
||||
nl: wp.array(dtype=int),
|
||||
qLD: wp.array3d(dtype=float),
|
||||
qLDiagInv: wp.array2d(dtype=float),
|
||||
@@ -440,6 +452,7 @@ def _forward_shim(
|
||||
ten_wrapadr: wp.array2d(dtype=int),
|
||||
ten_wrapnum: wp.array2d(dtype=int),
|
||||
time: wp.array(dtype=float),
|
||||
tree_island: wp.array2d(dtype=int),
|
||||
wrap_obj: wp.array2d(dtype=wp.vec2i),
|
||||
wrap_xpos: wp.array2d(dtype=wp.spatial_vector),
|
||||
xanchor: wp.array2d(dtype=wp.vec3),
|
||||
@@ -466,6 +479,9 @@ def _forward_shim(
|
||||
contact__worldid: wp.array(dtype=int),
|
||||
efc__D: wp.array2d(dtype=float),
|
||||
efc__J: wp.array3d(dtype=float),
|
||||
efc__J_colind: wp.array3d(dtype=int),
|
||||
efc__J_rowadr: wp.array2d(dtype=int),
|
||||
efc__J_rownnz: wp.array2d(dtype=int),
|
||||
efc__Ma: wp.array2d(dtype=float),
|
||||
efc__aref: wp.array2d(dtype=float),
|
||||
efc__force: wp.array2d(dtype=float),
|
||||
@@ -479,6 +495,7 @@ def _forward_shim(
|
||||
):
|
||||
_m.stat = _s
|
||||
_m.opt = _o
|
||||
_m.callback = _cb
|
||||
_d.efc = _e
|
||||
_d.contact = _c
|
||||
_m.M_rowadr = M_rowadr
|
||||
@@ -528,6 +545,7 @@ def _forward_shim(
|
||||
_m.body_rootid = body_rootid
|
||||
_m.body_subtreemass = body_subtreemass
|
||||
_m.body_tree = body_tree
|
||||
_m.body_treeid = body_treeid
|
||||
_m.body_weldid = body_weldid
|
||||
_m.cam_bodyid = cam_bodyid
|
||||
_m.cam_fovy = cam_fovy
|
||||
@@ -551,6 +569,7 @@ def _forward_shim(
|
||||
_m.dof_parentid = dof_parentid
|
||||
_m.dof_solimp = dof_solimp
|
||||
_m.dof_solref = dof_solref
|
||||
_m.dof_treeid = dof_treeid
|
||||
_m.dof_tri_col = dof_tri_col
|
||||
_m.dof_tri_row = dof_tri_row
|
||||
_m.eq_connect_adr = eq_connect_adr
|
||||
@@ -648,6 +667,7 @@ def _forward_shim(
|
||||
_m.mesh_normal = mesh_normal
|
||||
_m.mesh_normaladr = mesh_normaladr
|
||||
_m.mesh_normalnum = mesh_normalnum
|
||||
_m.mesh_octadr = mesh_octadr
|
||||
_m.mesh_polyadr = mesh_polyadr
|
||||
_m.mesh_polymap = mesh_polymap
|
||||
_m.mesh_polymapadr = mesh_polymapadr
|
||||
@@ -687,6 +707,7 @@ def _forward_shim(
|
||||
_m.nsensortaxel = nsensortaxel
|
||||
_m.nsite = nsite
|
||||
_m.ntendon = ntendon
|
||||
_m.ntree = ntree
|
||||
_m.nu = nu
|
||||
_m.nv = nv
|
||||
_m.nv_pad = nv_pad
|
||||
@@ -837,6 +858,9 @@ def _forward_shim(
|
||||
_d.cvel = cvel
|
||||
_d.efc.D = efc__D
|
||||
_d.efc.J = efc__J
|
||||
_d.efc.J_colind = efc__J_colind
|
||||
_d.efc.J_rowadr = efc__J_rowadr
|
||||
_d.efc.J_rownnz = efc__J_rownnz
|
||||
_d.efc.Ma = efc__Ma
|
||||
_d.efc.aref = efc__aref
|
||||
_d.efc.force = efc__force
|
||||
@@ -859,6 +883,9 @@ def _forward_shim(
|
||||
_d.light_xpos = light_xpos
|
||||
_d.mocap_pos = mocap_pos
|
||||
_d.mocap_quat = mocap_quat
|
||||
_d.moment_colind = moment_colind
|
||||
_d.moment_rowadr = moment_rowadr
|
||||
_d.moment_rownnz = moment_rownnz
|
||||
_d.naccdmax = naccdmax
|
||||
_d.nacon = nacon
|
||||
_d.naconmax = naconmax
|
||||
@@ -866,6 +893,7 @@ def _forward_shim(
|
||||
_d.ne = ne
|
||||
_d.nefc = nefc
|
||||
_d.nf = nf
|
||||
_d.nisland = nisland
|
||||
_d.njmax = njmax
|
||||
_d.nl = nl
|
||||
_d.qLD = qLD
|
||||
@@ -899,6 +927,7 @@ def _forward_shim(
|
||||
_d.ten_wrapadr = ten_wrapadr
|
||||
_d.ten_wrapnum = ten_wrapnum
|
||||
_d.time = time
|
||||
_d.tree_island = tree_island
|
||||
_d.wrap_obj = wrap_obj
|
||||
_d.wrap_xpos = wrap_xpos
|
||||
_d.xanchor = xanchor
|
||||
@@ -939,11 +968,15 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
'geom_xpos': d.geom_xpos.shape,
|
||||
'light_xdir': d._impl.light_xdir.shape,
|
||||
'light_xpos': d._impl.light_xpos.shape,
|
||||
'moment_colind': d._impl.moment_colind.shape,
|
||||
'moment_rowadr': d._impl.moment_rowadr.shape,
|
||||
'moment_rownnz': d._impl.moment_rownnz.shape,
|
||||
'nacon': d._impl.nacon.shape,
|
||||
'ncollision': d._impl.ncollision.shape,
|
||||
'ne': d._impl.ne.shape,
|
||||
'nefc': d._impl.nefc.shape,
|
||||
'nf': d._impl.nf.shape,
|
||||
'nisland': d._impl.nisland.shape,
|
||||
'nl': d._impl.nl.shape,
|
||||
'qLD': d._impl.qLD.shape,
|
||||
'qLDiagInv': d._impl.qLDiagInv.shape,
|
||||
@@ -972,6 +1005,7 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
'ten_velocity': d._impl.ten_velocity.shape,
|
||||
'ten_wrapadr': d._impl.ten_wrapadr.shape,
|
||||
'ten_wrapnum': d._impl.ten_wrapnum.shape,
|
||||
'tree_island': d._impl.tree_island.shape,
|
||||
'wrap_obj': d._impl.wrap_obj.shape,
|
||||
'wrap_xpos': d._impl.wrap_xpos.shape,
|
||||
'xanchor': d.xanchor.shape,
|
||||
@@ -997,6 +1031,9 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
'contact__worldid': d._impl.contact__worldid.shape,
|
||||
'efc__D': d._impl.efc__D.shape,
|
||||
'efc__J': d._impl.efc__J.shape,
|
||||
'efc__J_colind': d._impl.efc__J_colind.shape,
|
||||
'efc__J_rowadr': d._impl.efc__J_rowadr.shape,
|
||||
'efc__J_rownnz': d._impl.efc__J_rownnz.shape,
|
||||
'efc__Ma': d._impl.efc__Ma.shape,
|
||||
'efc__aref': d._impl.efc__aref.shape,
|
||||
'efc__force': d._impl.efc__force.shape,
|
||||
@@ -1010,7 +1047,7 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
}
|
||||
jf = ffi.jax_callable_variadic_tuple(
|
||||
_forward_shim,
|
||||
num_outputs=92,
|
||||
num_outputs=100,
|
||||
output_dims=output_dims,
|
||||
vmap_method=None,
|
||||
in_out_argnames=set([
|
||||
@@ -1038,11 +1075,15 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
'geom_xpos',
|
||||
'light_xdir',
|
||||
'light_xpos',
|
||||
'moment_colind',
|
||||
'moment_rowadr',
|
||||
'moment_rownnz',
|
||||
'nacon',
|
||||
'ncollision',
|
||||
'ne',
|
||||
'nefc',
|
||||
'nf',
|
||||
'nisland',
|
||||
'nl',
|
||||
'qLD',
|
||||
'qLDiagInv',
|
||||
@@ -1071,6 +1112,7 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
'ten_velocity',
|
||||
'ten_wrapadr',
|
||||
'ten_wrapnum',
|
||||
'tree_island',
|
||||
'wrap_obj',
|
||||
'wrap_xpos',
|
||||
'xanchor',
|
||||
@@ -1096,6 +1138,9 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
'contact__worldid',
|
||||
'efc__D',
|
||||
'efc__J',
|
||||
'efc__J_colind',
|
||||
'efc__J_rowadr',
|
||||
'efc__J_rownnz',
|
||||
'efc__Ma',
|
||||
'efc__aref',
|
||||
'efc__force',
|
||||
@@ -1113,6 +1158,7 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
'actuator_acc0',
|
||||
'actuator_actrange',
|
||||
'actuator_biasprm',
|
||||
'actuator_cranklength',
|
||||
'actuator_ctrlrange',
|
||||
'actuator_dynprm',
|
||||
'actuator_force',
|
||||
@@ -1120,6 +1166,7 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
'actuator_gainprm',
|
||||
'actuator_gear',
|
||||
'actuator_length',
|
||||
'actuator_lengthrange',
|
||||
'body_gravcomp',
|
||||
'body_inertia',
|
||||
'body_invweight0',
|
||||
@@ -1330,6 +1377,7 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
m.body_rootid,
|
||||
m.body_subtreemass,
|
||||
m._impl.body_tree,
|
||||
m.body_treeid,
|
||||
m.body_weldid,
|
||||
m.cam_bodyid,
|
||||
m.cam_fovy,
|
||||
@@ -1353,6 +1401,7 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
m.dof_parentid,
|
||||
m.dof_solimp,
|
||||
m.dof_solref,
|
||||
m.dof_treeid,
|
||||
m._impl.dof_tri_col,
|
||||
m._impl.dof_tri_row,
|
||||
m._impl.eq_connect_adr,
|
||||
@@ -1450,6 +1499,7 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
m.mesh_normal,
|
||||
m.mesh_normaladr,
|
||||
m.mesh_normalnum,
|
||||
m.mesh_octadr,
|
||||
m._impl.mesh_polyadr,
|
||||
m._impl.mesh_polymap,
|
||||
m._impl.mesh_polymapadr,
|
||||
@@ -1489,6 +1539,7 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
m._impl.nsensortaxel,
|
||||
m.nsite,
|
||||
m.ntendon,
|
||||
m._impl.ntree,
|
||||
m.nu,
|
||||
m.nv,
|
||||
m._impl.nv_pad,
|
||||
@@ -1638,11 +1689,15 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
d._impl.light_xpos,
|
||||
d.mocap_pos,
|
||||
d.mocap_quat,
|
||||
d._impl.moment_colind,
|
||||
d._impl.moment_rowadr,
|
||||
d._impl.moment_rownnz,
|
||||
d._impl.nacon,
|
||||
d._impl.ncollision,
|
||||
d._impl.ne,
|
||||
d._impl.nefc,
|
||||
d._impl.nf,
|
||||
d._impl.nisland,
|
||||
d._impl.nl,
|
||||
d._impl.qLD,
|
||||
d._impl.qLDiagInv,
|
||||
@@ -1675,6 +1730,7 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
d._impl.ten_wrapadr,
|
||||
d._impl.ten_wrapnum,
|
||||
d.time,
|
||||
d._impl.tree_island,
|
||||
d._impl.wrap_obj,
|
||||
d._impl.wrap_xpos,
|
||||
d.xanchor,
|
||||
@@ -1701,6 +1757,9 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
d._impl.contact__worldid,
|
||||
d._impl.efc__D,
|
||||
d._impl.efc__J,
|
||||
d._impl.efc__J_colind,
|
||||
d._impl.efc__J_rowadr,
|
||||
d._impl.efc__J_rownnz,
|
||||
d._impl.efc__Ma,
|
||||
d._impl.efc__aref,
|
||||
d._impl.efc__force,
|
||||
@@ -1737,74 +1796,82 @@ def _forward_jax_impl(m: types.Model, d: types.Data):
|
||||
'geom_xpos': out[21],
|
||||
'_impl.light_xdir': out[22],
|
||||
'_impl.light_xpos': out[23],
|
||||
'_impl.nacon': out[24],
|
||||
'_impl.ncollision': out[25],
|
||||
'_impl.ne': out[26],
|
||||
'_impl.nefc': out[27],
|
||||
'_impl.nf': out[28],
|
||||
'_impl.nl': out[29],
|
||||
'_impl.qLD': out[30],
|
||||
'_impl.qLDiagInv': out[31],
|
||||
'_impl.qM': out[32],
|
||||
'qacc': out[33],
|
||||
'qacc_smooth': out[34],
|
||||
'qfrc_actuator': out[35],
|
||||
'qfrc_bias': out[36],
|
||||
'qfrc_constraint': out[37],
|
||||
'_impl.qfrc_damper': out[38],
|
||||
'qfrc_fluid': out[39],
|
||||
'qfrc_gravcomp': out[40],
|
||||
'qfrc_passive': out[41],
|
||||
'qfrc_smooth': out[42],
|
||||
'_impl.qfrc_spring': out[43],
|
||||
'qvel': out[44],
|
||||
'sensordata': out[45],
|
||||
'site_xmat': out[46],
|
||||
'site_xpos': out[47],
|
||||
'_impl.solver_niter': out[48],
|
||||
'_impl.subtree_angmom': out[49],
|
||||
'subtree_com': out[50],
|
||||
'_impl.subtree_linvel': out[51],
|
||||
'_impl.ten_J': out[52],
|
||||
'ten_length': out[53],
|
||||
'_impl.ten_velocity': out[54],
|
||||
'_impl.ten_wrapadr': out[55],
|
||||
'_impl.ten_wrapnum': out[56],
|
||||
'_impl.wrap_obj': out[57],
|
||||
'_impl.wrap_xpos': out[58],
|
||||
'xanchor': out[59],
|
||||
'xaxis': out[60],
|
||||
'ximat': out[61],
|
||||
'xipos': out[62],
|
||||
'xmat': out[63],
|
||||
'xpos': out[64],
|
||||
'xquat': out[65],
|
||||
'_impl.contact__dim': out[66],
|
||||
'_impl.contact__dist': out[67],
|
||||
'_impl.contact__efc_address': out[68],
|
||||
'_impl.contact__frame': out[69],
|
||||
'_impl.contact__friction': out[70],
|
||||
'_impl.contact__geom': out[71],
|
||||
'_impl.contact__geomcollisionid': out[72],
|
||||
'_impl.contact__includemargin': out[73],
|
||||
'_impl.contact__pos': out[74],
|
||||
'_impl.contact__solimp': out[75],
|
||||
'_impl.contact__solref': out[76],
|
||||
'_impl.contact__solreffriction': out[77],
|
||||
'_impl.contact__type': out[78],
|
||||
'_impl.contact__worldid': out[79],
|
||||
'_impl.efc__D': out[80],
|
||||
'_impl.efc__J': out[81],
|
||||
'_impl.efc__Ma': out[82],
|
||||
'_impl.efc__aref': out[83],
|
||||
'_impl.efc__force': out[84],
|
||||
'_impl.efc__frictionloss': out[85],
|
||||
'_impl.efc__id': out[86],
|
||||
'_impl.efc__margin': out[87],
|
||||
'_impl.efc__pos': out[88],
|
||||
'_impl.efc__state': out[89],
|
||||
'_impl.efc__type': out[90],
|
||||
'_impl.efc__vel': out[91],
|
||||
'_impl.moment_colind': out[24],
|
||||
'_impl.moment_rowadr': out[25],
|
||||
'_impl.moment_rownnz': out[26],
|
||||
'_impl.nacon': out[27],
|
||||
'_impl.ncollision': out[28],
|
||||
'_impl.ne': out[29],
|
||||
'_impl.nefc': out[30],
|
||||
'_impl.nf': out[31],
|
||||
'_impl.nisland': out[32],
|
||||
'_impl.nl': out[33],
|
||||
'_impl.qLD': out[34],
|
||||
'_impl.qLDiagInv': out[35],
|
||||
'_impl.qM': out[36],
|
||||
'qacc': out[37],
|
||||
'qacc_smooth': out[38],
|
||||
'qfrc_actuator': out[39],
|
||||
'qfrc_bias': out[40],
|
||||
'qfrc_constraint': out[41],
|
||||
'_impl.qfrc_damper': out[42],
|
||||
'qfrc_fluid': out[43],
|
||||
'qfrc_gravcomp': out[44],
|
||||
'qfrc_passive': out[45],
|
||||
'qfrc_smooth': out[46],
|
||||
'_impl.qfrc_spring': out[47],
|
||||
'qvel': out[48],
|
||||
'sensordata': out[49],
|
||||
'site_xmat': out[50],
|
||||
'site_xpos': out[51],
|
||||
'_impl.solver_niter': out[52],
|
||||
'_impl.subtree_angmom': out[53],
|
||||
'subtree_com': out[54],
|
||||
'_impl.subtree_linvel': out[55],
|
||||
'_impl.ten_J': out[56],
|
||||
'ten_length': out[57],
|
||||
'_impl.ten_velocity': out[58],
|
||||
'_impl.ten_wrapadr': out[59],
|
||||
'_impl.ten_wrapnum': out[60],
|
||||
'_impl.tree_island': out[61],
|
||||
'_impl.wrap_obj': out[62],
|
||||
'_impl.wrap_xpos': out[63],
|
||||
'xanchor': out[64],
|
||||
'xaxis': out[65],
|
||||
'ximat': out[66],
|
||||
'xipos': out[67],
|
||||
'xmat': out[68],
|
||||
'xpos': out[69],
|
||||
'xquat': out[70],
|
||||
'_impl.contact__dim': out[71],
|
||||
'_impl.contact__dist': out[72],
|
||||
'_impl.contact__efc_address': out[73],
|
||||
'_impl.contact__frame': out[74],
|
||||
'_impl.contact__friction': out[75],
|
||||
'_impl.contact__geom': out[76],
|
||||
'_impl.contact__geomcollisionid': out[77],
|
||||
'_impl.contact__includemargin': out[78],
|
||||
'_impl.contact__pos': out[79],
|
||||
'_impl.contact__solimp': out[80],
|
||||
'_impl.contact__solref': out[81],
|
||||
'_impl.contact__solreffriction': out[82],
|
||||
'_impl.contact__type': out[83],
|
||||
'_impl.contact__worldid': out[84],
|
||||
'_impl.efc__D': out[85],
|
||||
'_impl.efc__J': out[86],
|
||||
'_impl.efc__J_colind': out[87],
|
||||
'_impl.efc__J_rowadr': out[88],
|
||||
'_impl.efc__J_rownnz': out[89],
|
||||
'_impl.efc__Ma': out[90],
|
||||
'_impl.efc__aref': out[91],
|
||||
'_impl.efc__force': out[92],
|
||||
'_impl.efc__frictionloss': out[93],
|
||||
'_impl.efc__id': out[94],
|
||||
'_impl.efc__margin': out[95],
|
||||
'_impl.efc__pos': out[96],
|
||||
'_impl.efc__state': out[97],
|
||||
'_impl.efc__type': out[98],
|
||||
'_impl.efc__vel': out[99],
|
||||
})
|
||||
return d
|
||||
|
||||
@@ -1828,7 +1895,7 @@ def _step_shim(
|
||||
nworld: int,
|
||||
M_rowadr: wp.array(dtype=int),
|
||||
M_rownnz: wp.array(dtype=int),
|
||||
actuator_acc0: wp.array(dtype=float),
|
||||
actuator_acc0: wp.array2d(dtype=float),
|
||||
actuator_actadr: wp.array(dtype=int),
|
||||
actuator_actearly: wp.array(dtype=bool),
|
||||
actuator_actlimited: wp.array(dtype=bool),
|
||||
@@ -1836,7 +1903,7 @@ def _step_shim(
|
||||
actuator_actrange: wp.array2d(dtype=wp.vec2),
|
||||
actuator_biasprm: wp.array2d(dtype=mjwp_types.vec10f),
|
||||
actuator_biastype: wp.array(dtype=int),
|
||||
actuator_cranklength: wp.array(dtype=float),
|
||||
actuator_cranklength: wp.array2d(dtype=float),
|
||||
actuator_ctrllimited: wp.array(dtype=bool),
|
||||
actuator_ctrlrange: wp.array2d(dtype=wp.vec2),
|
||||
actuator_dynprm: wp.array2d(dtype=mjwp_types.vec10f),
|
||||
@@ -1846,7 +1913,7 @@ def _step_shim(
|
||||
actuator_gainprm: wp.array2d(dtype=mjwp_types.vec10f),
|
||||
actuator_gaintype: wp.array(dtype=int),
|
||||
actuator_gear: wp.array2d(dtype=wp.spatial_vector),
|
||||
actuator_lengthrange: wp.array(dtype=wp.vec2),
|
||||
actuator_lengthrange: wp.array2d(dtype=wp.vec2),
|
||||
actuator_trnid: wp.array(dtype=wp.vec2i),
|
||||
actuator_trntype: wp.array(dtype=int),
|
||||
actuator_trntype_body_adr: wp.array(dtype=int),
|
||||
@@ -1873,6 +1940,7 @@ def _step_shim(
|
||||
body_rootid: wp.array(dtype=int),
|
||||
body_subtreemass: wp.array2d(dtype=float),
|
||||
body_tree: tuple[wp.array(dtype=int), ...],
|
||||
body_treeid: wp.array(dtype=int),
|
||||
body_weldid: wp.array(dtype=int),
|
||||
cam_bodyid: wp.array(dtype=int),
|
||||
cam_fovy: wp.array2d(dtype=float),
|
||||
@@ -1896,6 +1964,7 @@ def _step_shim(
|
||||
dof_parentid: wp.array(dtype=int),
|
||||
dof_solimp: wp.array2d(dtype=mjwp_types.vec5),
|
||||
dof_solref: wp.array2d(dtype=wp.vec2),
|
||||
dof_treeid: wp.array(dtype=int),
|
||||
dof_tri_col: wp.array(dtype=int),
|
||||
dof_tri_row: wp.array(dtype=int),
|
||||
eq_connect_adr: wp.array(dtype=int),
|
||||
@@ -1993,6 +2062,7 @@ def _step_shim(
|
||||
mesh_normal: wp.array(dtype=wp.vec3),
|
||||
mesh_normaladr: wp.array(dtype=int),
|
||||
mesh_normalnum: wp.array(dtype=int),
|
||||
mesh_octadr: wp.array(dtype=int),
|
||||
mesh_polyadr: wp.array(dtype=int),
|
||||
mesh_polymap: wp.array(dtype=int),
|
||||
mesh_polymapadr: wp.array(dtype=int),
|
||||
@@ -2033,6 +2103,7 @@ def _step_shim(
|
||||
nsensortaxel: int,
|
||||
nsite: int,
|
||||
ntendon: int,
|
||||
ntree: int,
|
||||
nu: int,
|
||||
nv: int,
|
||||
nv_pad: int,
|
||||
@@ -2159,7 +2230,7 @@ def _step_shim(
|
||||
act_dot: wp.array2d(dtype=float),
|
||||
actuator_force: wp.array2d(dtype=float),
|
||||
actuator_length: wp.array2d(dtype=float),
|
||||
actuator_moment: wp.array3d(dtype=float),
|
||||
actuator_moment: wp.array2d(dtype=float),
|
||||
actuator_velocity: wp.array2d(dtype=float),
|
||||
cacc: wp.array2d(dtype=wp.spatial_vector),
|
||||
cam_xmat: wp.array2d(dtype=wp.mat33),
|
||||
@@ -2174,7 +2245,7 @@ def _step_shim(
|
||||
cvel: wp.array2d(dtype=wp.spatial_vector),
|
||||
energy: wp.array(dtype=wp.vec2),
|
||||
eq_active: wp.array2d(dtype=bool),
|
||||
flexedge_J: wp.array3d(dtype=float),
|
||||
flexedge_J: wp.array2d(dtype=float),
|
||||
flexedge_length: wp.array2d(dtype=float),
|
||||
flexedge_velocity: wp.array2d(dtype=float),
|
||||
flexvert_xpos: wp.array2d(dtype=wp.vec3),
|
||||
@@ -2184,11 +2255,15 @@ def _step_shim(
|
||||
light_xpos: wp.array2d(dtype=wp.vec3),
|
||||
mocap_pos: wp.array2d(dtype=wp.vec3),
|
||||
mocap_quat: wp.array2d(dtype=wp.quat),
|
||||
moment_colind: wp.array2d(dtype=int),
|
||||
moment_rowadr: wp.array2d(dtype=int),
|
||||
moment_rownnz: wp.array2d(dtype=int),
|
||||
nacon: wp.array(dtype=int),
|
||||
ncollision: wp.array(dtype=int),
|
||||
ne: wp.array(dtype=int),
|
||||
nefc: wp.array(dtype=int),
|
||||
nf: wp.array(dtype=int),
|
||||
nisland: wp.array(dtype=int),
|
||||
nl: wp.array(dtype=int),
|
||||
qLD: wp.array3d(dtype=float),
|
||||
qLDiagInv: wp.array2d(dtype=float),
|
||||
@@ -2221,6 +2296,7 @@ def _step_shim(
|
||||
ten_wrapadr: wp.array2d(dtype=int),
|
||||
ten_wrapnum: wp.array2d(dtype=int),
|
||||
time: wp.array(dtype=float),
|
||||
tree_island: wp.array2d(dtype=int),
|
||||
wrap_obj: wp.array2d(dtype=wp.vec2i),
|
||||
wrap_xpos: wp.array2d(dtype=wp.spatial_vector),
|
||||
xanchor: wp.array2d(dtype=wp.vec3),
|
||||
@@ -2247,6 +2323,9 @@ def _step_shim(
|
||||
contact__worldid: wp.array(dtype=int),
|
||||
efc__D: wp.array2d(dtype=float),
|
||||
efc__J: wp.array3d(dtype=float),
|
||||
efc__J_colind: wp.array3d(dtype=int),
|
||||
efc__J_rowadr: wp.array2d(dtype=int),
|
||||
efc__J_rownnz: wp.array2d(dtype=int),
|
||||
efc__Ma: wp.array2d(dtype=float),
|
||||
efc__aref: wp.array2d(dtype=float),
|
||||
efc__force: wp.array2d(dtype=float),
|
||||
@@ -2260,6 +2339,7 @@ def _step_shim(
|
||||
):
|
||||
_m.stat = _s
|
||||
_m.opt = _o
|
||||
_m.callback = _cb
|
||||
_d.efc = _e
|
||||
_d.contact = _c
|
||||
_m.M_rowadr = M_rowadr
|
||||
@@ -2309,6 +2389,7 @@ def _step_shim(
|
||||
_m.body_rootid = body_rootid
|
||||
_m.body_subtreemass = body_subtreemass
|
||||
_m.body_tree = body_tree
|
||||
_m.body_treeid = body_treeid
|
||||
_m.body_weldid = body_weldid
|
||||
_m.cam_bodyid = cam_bodyid
|
||||
_m.cam_fovy = cam_fovy
|
||||
@@ -2332,6 +2413,7 @@ def _step_shim(
|
||||
_m.dof_parentid = dof_parentid
|
||||
_m.dof_solimp = dof_solimp
|
||||
_m.dof_solref = dof_solref
|
||||
_m.dof_treeid = dof_treeid
|
||||
_m.dof_tri_col = dof_tri_col
|
||||
_m.dof_tri_row = dof_tri_row
|
||||
_m.eq_connect_adr = eq_connect_adr
|
||||
@@ -2429,6 +2511,7 @@ def _step_shim(
|
||||
_m.mesh_normal = mesh_normal
|
||||
_m.mesh_normaladr = mesh_normaladr
|
||||
_m.mesh_normalnum = mesh_normalnum
|
||||
_m.mesh_octadr = mesh_octadr
|
||||
_m.mesh_polyadr = mesh_polyadr
|
||||
_m.mesh_polymap = mesh_polymap
|
||||
_m.mesh_polymapadr = mesh_polymapadr
|
||||
@@ -2469,6 +2552,7 @@ def _step_shim(
|
||||
_m.nsensortaxel = nsensortaxel
|
||||
_m.nsite = nsite
|
||||
_m.ntendon = ntendon
|
||||
_m.ntree = ntree
|
||||
_m.nu = nu
|
||||
_m.nv = nv
|
||||
_m.nv_pad = nv_pad
|
||||
@@ -2620,6 +2704,9 @@ def _step_shim(
|
||||
_d.cvel = cvel
|
||||
_d.efc.D = efc__D
|
||||
_d.efc.J = efc__J
|
||||
_d.efc.J_colind = efc__J_colind
|
||||
_d.efc.J_rowadr = efc__J_rowadr
|
||||
_d.efc.J_rownnz = efc__J_rownnz
|
||||
_d.efc.Ma = efc__Ma
|
||||
_d.efc.aref = efc__aref
|
||||
_d.efc.force = efc__force
|
||||
@@ -2642,6 +2729,9 @@ def _step_shim(
|
||||
_d.light_xpos = light_xpos
|
||||
_d.mocap_pos = mocap_pos
|
||||
_d.mocap_quat = mocap_quat
|
||||
_d.moment_colind = moment_colind
|
||||
_d.moment_rowadr = moment_rowadr
|
||||
_d.moment_rownnz = moment_rownnz
|
||||
_d.naccdmax = naccdmax
|
||||
_d.nacon = nacon
|
||||
_d.naconmax = naconmax
|
||||
@@ -2649,6 +2739,7 @@ def _step_shim(
|
||||
_d.ne = ne
|
||||
_d.nefc = nefc
|
||||
_d.nf = nf
|
||||
_d.nisland = nisland
|
||||
_d.njmax = njmax
|
||||
_d.nl = nl
|
||||
_d.qLD = qLD
|
||||
@@ -2682,6 +2773,7 @@ def _step_shim(
|
||||
_d.ten_wrapadr = ten_wrapadr
|
||||
_d.ten_wrapnum = ten_wrapnum
|
||||
_d.time = time
|
||||
_d.tree_island = tree_island
|
||||
_d.wrap_obj = wrap_obj
|
||||
_d.wrap_xpos = wrap_xpos
|
||||
_d.xanchor = xanchor
|
||||
@@ -2723,11 +2815,15 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
'geom_xpos': d.geom_xpos.shape,
|
||||
'light_xdir': d._impl.light_xdir.shape,
|
||||
'light_xpos': d._impl.light_xpos.shape,
|
||||
'moment_colind': d._impl.moment_colind.shape,
|
||||
'moment_rowadr': d._impl.moment_rowadr.shape,
|
||||
'moment_rownnz': d._impl.moment_rownnz.shape,
|
||||
'nacon': d._impl.nacon.shape,
|
||||
'ncollision': d._impl.ncollision.shape,
|
||||
'ne': d._impl.ne.shape,
|
||||
'nefc': d._impl.nefc.shape,
|
||||
'nf': d._impl.nf.shape,
|
||||
'nisland': d._impl.nisland.shape,
|
||||
'nl': d._impl.nl.shape,
|
||||
'qLD': d._impl.qLD.shape,
|
||||
'qLDiagInv': d._impl.qLDiagInv.shape,
|
||||
@@ -2759,6 +2855,7 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
'ten_wrapadr': d._impl.ten_wrapadr.shape,
|
||||
'ten_wrapnum': d._impl.ten_wrapnum.shape,
|
||||
'time': d.time.shape,
|
||||
'tree_island': d._impl.tree_island.shape,
|
||||
'wrap_obj': d._impl.wrap_obj.shape,
|
||||
'wrap_xpos': d._impl.wrap_xpos.shape,
|
||||
'xanchor': d.xanchor.shape,
|
||||
@@ -2784,6 +2881,9 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
'contact__worldid': d._impl.contact__worldid.shape,
|
||||
'efc__D': d._impl.efc__D.shape,
|
||||
'efc__J': d._impl.efc__J.shape,
|
||||
'efc__J_colind': d._impl.efc__J_colind.shape,
|
||||
'efc__J_rowadr': d._impl.efc__J_rowadr.shape,
|
||||
'efc__J_rownnz': d._impl.efc__J_rownnz.shape,
|
||||
'efc__Ma': d._impl.efc__Ma.shape,
|
||||
'efc__aref': d._impl.efc__aref.shape,
|
||||
'efc__force': d._impl.efc__force.shape,
|
||||
@@ -2797,7 +2897,7 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
}
|
||||
jf = ffi.jax_callable_variadic_tuple(
|
||||
_step_shim,
|
||||
num_outputs=96,
|
||||
num_outputs=104,
|
||||
output_dims=output_dims,
|
||||
vmap_method=None,
|
||||
in_out_argnames=set([
|
||||
@@ -2826,11 +2926,15 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
'geom_xpos',
|
||||
'light_xdir',
|
||||
'light_xpos',
|
||||
'moment_colind',
|
||||
'moment_rowadr',
|
||||
'moment_rownnz',
|
||||
'nacon',
|
||||
'ncollision',
|
||||
'ne',
|
||||
'nefc',
|
||||
'nf',
|
||||
'nisland',
|
||||
'nl',
|
||||
'qLD',
|
||||
'qLDiagInv',
|
||||
@@ -2862,6 +2966,7 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
'ten_wrapadr',
|
||||
'ten_wrapnum',
|
||||
'time',
|
||||
'tree_island',
|
||||
'wrap_obj',
|
||||
'wrap_xpos',
|
||||
'xanchor',
|
||||
@@ -2887,6 +2992,9 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
'contact__worldid',
|
||||
'efc__D',
|
||||
'efc__J',
|
||||
'efc__J_colind',
|
||||
'efc__J_rowadr',
|
||||
'efc__J_rownnz',
|
||||
'efc__Ma',
|
||||
'efc__aref',
|
||||
'efc__force',
|
||||
@@ -2904,6 +3012,7 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
'actuator_acc0',
|
||||
'actuator_actrange',
|
||||
'actuator_biasprm',
|
||||
'actuator_cranklength',
|
||||
'actuator_ctrlrange',
|
||||
'actuator_dynprm',
|
||||
'actuator_force',
|
||||
@@ -2911,6 +3020,7 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
'actuator_gainprm',
|
||||
'actuator_gear',
|
||||
'actuator_length',
|
||||
'actuator_lengthrange',
|
||||
'body_gravcomp',
|
||||
'body_inertia',
|
||||
'body_invweight0',
|
||||
@@ -3125,6 +3235,7 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
m.body_rootid,
|
||||
m.body_subtreemass,
|
||||
m._impl.body_tree,
|
||||
m.body_treeid,
|
||||
m.body_weldid,
|
||||
m.cam_bodyid,
|
||||
m.cam_fovy,
|
||||
@@ -3148,6 +3259,7 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
m.dof_parentid,
|
||||
m.dof_solimp,
|
||||
m.dof_solref,
|
||||
m.dof_treeid,
|
||||
m._impl.dof_tri_col,
|
||||
m._impl.dof_tri_row,
|
||||
m._impl.eq_connect_adr,
|
||||
@@ -3245,6 +3357,7 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
m.mesh_normal,
|
||||
m.mesh_normaladr,
|
||||
m.mesh_normalnum,
|
||||
m.mesh_octadr,
|
||||
m._impl.mesh_polyadr,
|
||||
m._impl.mesh_polymap,
|
||||
m._impl.mesh_polymapadr,
|
||||
@@ -3285,6 +3398,7 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
m._impl.nsensortaxel,
|
||||
m.nsite,
|
||||
m.ntendon,
|
||||
m._impl.ntree,
|
||||
m.nu,
|
||||
m.nv,
|
||||
m._impl.nv_pad,
|
||||
@@ -3435,11 +3549,15 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
d._impl.light_xpos,
|
||||
d.mocap_pos,
|
||||
d.mocap_quat,
|
||||
d._impl.moment_colind,
|
||||
d._impl.moment_rowadr,
|
||||
d._impl.moment_rownnz,
|
||||
d._impl.nacon,
|
||||
d._impl.ncollision,
|
||||
d._impl.ne,
|
||||
d._impl.nefc,
|
||||
d._impl.nf,
|
||||
d._impl.nisland,
|
||||
d._impl.nl,
|
||||
d._impl.qLD,
|
||||
d._impl.qLDiagInv,
|
||||
@@ -3472,6 +3590,7 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
d._impl.ten_wrapadr,
|
||||
d._impl.ten_wrapnum,
|
||||
d.time,
|
||||
d._impl.tree_island,
|
||||
d._impl.wrap_obj,
|
||||
d._impl.wrap_xpos,
|
||||
d.xanchor,
|
||||
@@ -3498,6 +3617,9 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
d._impl.contact__worldid,
|
||||
d._impl.efc__D,
|
||||
d._impl.efc__J,
|
||||
d._impl.efc__J_colind,
|
||||
d._impl.efc__J_rowadr,
|
||||
d._impl.efc__J_rownnz,
|
||||
d._impl.efc__Ma,
|
||||
d._impl.efc__aref,
|
||||
d._impl.efc__force,
|
||||
@@ -3535,77 +3657,85 @@ def _step_jax_impl(m: types.Model, d: types.Data):
|
||||
'geom_xpos': out[22],
|
||||
'_impl.light_xdir': out[23],
|
||||
'_impl.light_xpos': out[24],
|
||||
'_impl.nacon': out[25],
|
||||
'_impl.ncollision': out[26],
|
||||
'_impl.ne': out[27],
|
||||
'_impl.nefc': out[28],
|
||||
'_impl.nf': out[29],
|
||||
'_impl.nl': out[30],
|
||||
'_impl.qLD': out[31],
|
||||
'_impl.qLDiagInv': out[32],
|
||||
'_impl.qM': out[33],
|
||||
'qacc': out[34],
|
||||
'qacc_smooth': out[35],
|
||||
'qacc_warmstart': out[36],
|
||||
'qfrc_actuator': out[37],
|
||||
'qfrc_bias': out[38],
|
||||
'qfrc_constraint': out[39],
|
||||
'_impl.qfrc_damper': out[40],
|
||||
'qfrc_fluid': out[41],
|
||||
'qfrc_gravcomp': out[42],
|
||||
'qfrc_passive': out[43],
|
||||
'qfrc_smooth': out[44],
|
||||
'_impl.qfrc_spring': out[45],
|
||||
'qpos': out[46],
|
||||
'qvel': out[47],
|
||||
'sensordata': out[48],
|
||||
'site_xmat': out[49],
|
||||
'site_xpos': out[50],
|
||||
'_impl.solver_niter': out[51],
|
||||
'_impl.subtree_angmom': out[52],
|
||||
'subtree_com': out[53],
|
||||
'_impl.subtree_linvel': out[54],
|
||||
'_impl.ten_J': out[55],
|
||||
'ten_length': out[56],
|
||||
'_impl.ten_velocity': out[57],
|
||||
'_impl.ten_wrapadr': out[58],
|
||||
'_impl.ten_wrapnum': out[59],
|
||||
'time': out[60],
|
||||
'_impl.wrap_obj': out[61],
|
||||
'_impl.wrap_xpos': out[62],
|
||||
'xanchor': out[63],
|
||||
'xaxis': out[64],
|
||||
'ximat': out[65],
|
||||
'xipos': out[66],
|
||||
'xmat': out[67],
|
||||
'xpos': out[68],
|
||||
'xquat': out[69],
|
||||
'_impl.contact__dim': out[70],
|
||||
'_impl.contact__dist': out[71],
|
||||
'_impl.contact__efc_address': out[72],
|
||||
'_impl.contact__frame': out[73],
|
||||
'_impl.contact__friction': out[74],
|
||||
'_impl.contact__geom': out[75],
|
||||
'_impl.contact__geomcollisionid': out[76],
|
||||
'_impl.contact__includemargin': out[77],
|
||||
'_impl.contact__pos': out[78],
|
||||
'_impl.contact__solimp': out[79],
|
||||
'_impl.contact__solref': out[80],
|
||||
'_impl.contact__solreffriction': out[81],
|
||||
'_impl.contact__type': out[82],
|
||||
'_impl.contact__worldid': out[83],
|
||||
'_impl.efc__D': out[84],
|
||||
'_impl.efc__J': out[85],
|
||||
'_impl.efc__Ma': out[86],
|
||||
'_impl.efc__aref': out[87],
|
||||
'_impl.efc__force': out[88],
|
||||
'_impl.efc__frictionloss': out[89],
|
||||
'_impl.efc__id': out[90],
|
||||
'_impl.efc__margin': out[91],
|
||||
'_impl.efc__pos': out[92],
|
||||
'_impl.efc__state': out[93],
|
||||
'_impl.efc__type': out[94],
|
||||
'_impl.efc__vel': out[95],
|
||||
'_impl.moment_colind': out[25],
|
||||
'_impl.moment_rowadr': out[26],
|
||||
'_impl.moment_rownnz': out[27],
|
||||
'_impl.nacon': out[28],
|
||||
'_impl.ncollision': out[29],
|
||||
'_impl.ne': out[30],
|
||||
'_impl.nefc': out[31],
|
||||
'_impl.nf': out[32],
|
||||
'_impl.nisland': out[33],
|
||||
'_impl.nl': out[34],
|
||||
'_impl.qLD': out[35],
|
||||
'_impl.qLDiagInv': out[36],
|
||||
'_impl.qM': out[37],
|
||||
'qacc': out[38],
|
||||
'qacc_smooth': out[39],
|
||||
'qacc_warmstart': out[40],
|
||||
'qfrc_actuator': out[41],
|
||||
'qfrc_bias': out[42],
|
||||
'qfrc_constraint': out[43],
|
||||
'_impl.qfrc_damper': out[44],
|
||||
'qfrc_fluid': out[45],
|
||||
'qfrc_gravcomp': out[46],
|
||||
'qfrc_passive': out[47],
|
||||
'qfrc_smooth': out[48],
|
||||
'_impl.qfrc_spring': out[49],
|
||||
'qpos': out[50],
|
||||
'qvel': out[51],
|
||||
'sensordata': out[52],
|
||||
'site_xmat': out[53],
|
||||
'site_xpos': out[54],
|
||||
'_impl.solver_niter': out[55],
|
||||
'_impl.subtree_angmom': out[56],
|
||||
'subtree_com': out[57],
|
||||
'_impl.subtree_linvel': out[58],
|
||||
'_impl.ten_J': out[59],
|
||||
'ten_length': out[60],
|
||||
'_impl.ten_velocity': out[61],
|
||||
'_impl.ten_wrapadr': out[62],
|
||||
'_impl.ten_wrapnum': out[63],
|
||||
'time': out[64],
|
||||
'_impl.tree_island': out[65],
|
||||
'_impl.wrap_obj': out[66],
|
||||
'_impl.wrap_xpos': out[67],
|
||||
'xanchor': out[68],
|
||||
'xaxis': out[69],
|
||||
'ximat': out[70],
|
||||
'xipos': out[71],
|
||||
'xmat': out[72],
|
||||
'xpos': out[73],
|
||||
'xquat': out[74],
|
||||
'_impl.contact__dim': out[75],
|
||||
'_impl.contact__dist': out[76],
|
||||
'_impl.contact__efc_address': out[77],
|
||||
'_impl.contact__frame': out[78],
|
||||
'_impl.contact__friction': out[79],
|
||||
'_impl.contact__geom': out[80],
|
||||
'_impl.contact__geomcollisionid': out[81],
|
||||
'_impl.contact__includemargin': out[82],
|
||||
'_impl.contact__pos': out[83],
|
||||
'_impl.contact__solimp': out[84],
|
||||
'_impl.contact__solref': out[85],
|
||||
'_impl.contact__solreffriction': out[86],
|
||||
'_impl.contact__type': out[87],
|
||||
'_impl.contact__worldid': out[88],
|
||||
'_impl.efc__D': out[89],
|
||||
'_impl.efc__J': out[90],
|
||||
'_impl.efc__J_colind': out[91],
|
||||
'_impl.efc__J_rowadr': out[92],
|
||||
'_impl.efc__J_rownnz': out[93],
|
||||
'_impl.efc__Ma': out[94],
|
||||
'_impl.efc__aref': out[95],
|
||||
'_impl.efc__force': out[96],
|
||||
'_impl.efc__frictionloss': out[97],
|
||||
'_impl.efc__id': out[98],
|
||||
'_impl.efc__margin': out[99],
|
||||
'_impl.efc__pos': out[100],
|
||||
'_impl.efc__state': out[101],
|
||||
'_impl.efc__type': out[102],
|
||||
'_impl.efc__vel': out[103],
|
||||
})
|
||||
return d
|
||||
|
||||
|
||||
@@ -181,7 +181,15 @@ class ForwardTest(parameterized.TestCase):
|
||||
d.moment_rowadr,
|
||||
d.moment_colind,
|
||||
)
|
||||
tu.assert_eq(dx._impl.actuator_moment, actuator_moment, 'actuator_moment')
|
||||
warp_actuator_moment = np.zeros((m.nu, m.nv))
|
||||
mujoco.mju_sparse2dense(
|
||||
warp_actuator_moment,
|
||||
np.asarray(dx._impl.actuator_moment),
|
||||
np.asarray(dx._impl.moment_rownnz),
|
||||
np.asarray(dx._impl.moment_rowadr),
|
||||
np.asarray(dx._impl.moment_colind),
|
||||
)
|
||||
tu.assert_eq(warp_actuator_moment, actuator_moment, 'actuator_moment')
|
||||
|
||||
# fwd_velocity
|
||||
tu.assert_attr_eq(dx._impl, d, 'actuator_velocity')
|
||||
|
||||
@@ -44,6 +44,9 @@ _c = mjwarp.Contact(
|
||||
_e = mjwarp.Constraint(
|
||||
**{f.name: None for f in dataclasses.fields(mjwarp.Constraint) if f.init}
|
||||
)
|
||||
_cb = mjwp_types.Callback(
|
||||
**{f.name: None for f in dataclasses.fields(mjwp_types.Callback) if f.init}
|
||||
)
|
||||
|
||||
@ffi.format_args_for_warp
|
||||
def _render_shim(
|
||||
@@ -81,6 +84,7 @@ def _render_shim(
|
||||
):
|
||||
_m.stat = _s
|
||||
_m.opt = _o
|
||||
_m.callback = _cb
|
||||
_d.efc = _e
|
||||
_d.contact = _c
|
||||
_m.cam_fovy = cam_fovy
|
||||
|
||||
@@ -42,6 +42,9 @@ _c = mjwarp.Contact(
|
||||
_e = mjwarp.Constraint(
|
||||
**{f.name: None for f in dataclasses.fields(mjwarp.Constraint) if f.init}
|
||||
)
|
||||
_cb = mjwp_types.Callback(
|
||||
**{f.name: None for f in dataclasses.fields(mjwp_types.Callback) if f.init}
|
||||
)
|
||||
|
||||
@ffi.format_args_for_warp
|
||||
def _kinematics_shim(
|
||||
@@ -92,6 +95,7 @@ def _kinematics_shim(
|
||||
):
|
||||
_m.stat = _s
|
||||
_m.opt = _o
|
||||
_m.callback = _cb
|
||||
_d.efc = _e
|
||||
_d.contact = _c
|
||||
_m.body_branch_start = body_branch_start
|
||||
@@ -332,6 +336,7 @@ def _tendon_shim(
|
||||
):
|
||||
_m.stat = _s
|
||||
_m.opt = _o
|
||||
_m.callback = _cb
|
||||
_d.efc = _e
|
||||
_d.contact = _c
|
||||
_m.body_parentid = body_parentid
|
||||
|
||||
@@ -25,11 +25,20 @@ from mujoco.mjx._src import dataclasses as mjx_dataclasses
|
||||
import numpy as np
|
||||
if typing.TYPE_CHECKING:
|
||||
GraphMode = int
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Callback:
|
||||
pass
|
||||
|
||||
else:
|
||||
try:
|
||||
from warp._src.jax_experimental.ffi import GraphMode
|
||||
from mujoco.mjx.third_party.mujoco_warp._src import types as mjwp_types
|
||||
|
||||
Callback = mjwp_types.Callback
|
||||
except ImportError:
|
||||
GraphMode = int
|
||||
Callback = None
|
||||
PyTreeNode = mjx_dataclasses.PyTreeNode
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
@@ -43,7 +52,6 @@ class TileSet:
|
||||
adr: address of each tile in the set
|
||||
size: size of all the tiles in this set
|
||||
"""
|
||||
|
||||
adr: np.ndarray
|
||||
size: int
|
||||
|
||||
@@ -122,6 +130,7 @@ class ModelWarp(PyTreeNode):
|
||||
body_branches: np.ndarray
|
||||
body_fluid_ellipsoid: np.ndarray
|
||||
body_tree: Tuple[np.ndarray, ...]
|
||||
callback: Callback
|
||||
cam_projection: np.ndarray
|
||||
collision_sensor_adr: np.ndarray
|
||||
dof_tri_col: np.ndarray
|
||||
@@ -174,6 +183,7 @@ class ModelWarp(PyTreeNode):
|
||||
mesh_polyvertadr: np.ndarray
|
||||
mesh_polyvertnum: np.ndarray
|
||||
mocap_bodyid: np.ndarray
|
||||
nJfe: int
|
||||
nacttrnbody: int
|
||||
nbranch: int
|
||||
nflex: int
|
||||
@@ -270,6 +280,9 @@ class DataWarp(PyTreeNode):
|
||||
crb: jax.Array
|
||||
efc__D: jax.Array
|
||||
efc__J: jax.Array
|
||||
efc__J_colind: jax.Array
|
||||
efc__J_rowadr: jax.Array
|
||||
efc__J_rownnz: jax.Array
|
||||
efc__Ma: jax.Array
|
||||
efc__aref: jax.Array
|
||||
efc__force: jax.Array
|
||||
@@ -287,6 +300,9 @@ class DataWarp(PyTreeNode):
|
||||
flexvert_xpos: jax.Array
|
||||
light_xdir: jax.Array
|
||||
light_xpos: jax.Array
|
||||
moment_colind: jax.Array
|
||||
moment_rowadr: jax.Array
|
||||
moment_rownnz: jax.Array
|
||||
naccdmax: int
|
||||
nacon: jax.Array
|
||||
naconmax: int
|
||||
@@ -294,7 +310,9 @@ class DataWarp(PyTreeNode):
|
||||
ne: jax.Array
|
||||
nefc: jax.Array
|
||||
nf: jax.Array
|
||||
nisland: jax.Array
|
||||
njmax: int
|
||||
njmax_pad: int
|
||||
nl: jax.Array
|
||||
nworld: int
|
||||
qLD: jax.Array
|
||||
@@ -309,6 +327,7 @@ class DataWarp(PyTreeNode):
|
||||
ten_velocity: jax.Array
|
||||
ten_wrapadr: jax.Array
|
||||
ten_wrapnum: jax.Array
|
||||
tree_island: jax.Array
|
||||
wrap_obj: jax.Array
|
||||
wrap_xpos: jax.Array
|
||||
shape = property(lambda self: self.cacc.shape)
|
||||
@@ -332,6 +351,7 @@ DATA_NON_VMAP = {
|
||||
'naconmax',
|
||||
'ncollision',
|
||||
'njmax',
|
||||
'njmax_pad',
|
||||
'nworld',
|
||||
}
|
||||
|
||||
@@ -365,7 +385,7 @@ _NDIM = {
|
||||
'act_dot': 2,
|
||||
'actuator_force': 2,
|
||||
'actuator_length': 2,
|
||||
'actuator_moment': 3,
|
||||
'actuator_moment': 2,
|
||||
'actuator_velocity': 2,
|
||||
'cacc': 3,
|
||||
'cam_xmat': 4,
|
||||
@@ -394,6 +414,9 @@ _NDIM = {
|
||||
'cvel': 3,
|
||||
'efc__D': 2,
|
||||
'efc__J': 3,
|
||||
'efc__J_colind': 3,
|
||||
'efc__J_rowadr': 2,
|
||||
'efc__J_rownnz': 2,
|
||||
'efc__Ma': 2,
|
||||
'efc__aref': 2,
|
||||
'efc__force': 2,
|
||||
@@ -406,7 +429,7 @@ _NDIM = {
|
||||
'efc__vel': 2,
|
||||
'energy': 2,
|
||||
'eq_active': 2,
|
||||
'flexedge_J': 3,
|
||||
'flexedge_J': 2,
|
||||
'flexedge_length': 2,
|
||||
'flexedge_velocity': 2,
|
||||
'flexvert_xpos': 3,
|
||||
@@ -416,6 +439,9 @@ _NDIM = {
|
||||
'light_xpos': 3,
|
||||
'mocap_pos': 3,
|
||||
'mocap_quat': 3,
|
||||
'moment_colind': 2,
|
||||
'moment_rowadr': 2,
|
||||
'moment_rownnz': 2,
|
||||
'naccdmax': 0,
|
||||
'nacon': 1,
|
||||
'naconmax': 0,
|
||||
@@ -423,7 +449,9 @@ _NDIM = {
|
||||
'ne': 1,
|
||||
'nefc': 1,
|
||||
'nf': 1,
|
||||
'nisland': 1,
|
||||
'njmax': 0,
|
||||
'njmax_pad': 0,
|
||||
'nl': 1,
|
||||
'nworld': 0,
|
||||
'qLD': 3,
|
||||
@@ -458,6 +486,7 @@ _NDIM = {
|
||||
'ten_wrapadr': 2,
|
||||
'ten_wrapnum': 2,
|
||||
'time': 1,
|
||||
'tree_island': 2,
|
||||
'wrap_obj': 3,
|
||||
'wrap_xpos': 3,
|
||||
'xanchor': 3,
|
||||
@@ -473,7 +502,7 @@ _NDIM = {
|
||||
'M_colind': 1,
|
||||
'M_rowadr': 1,
|
||||
'M_rownnz': 1,
|
||||
'actuator_acc0': 1,
|
||||
'actuator_acc0': 2,
|
||||
'actuator_actadr': 1,
|
||||
'actuator_actearly': 1,
|
||||
'actuator_actlimited': 1,
|
||||
@@ -481,7 +510,7 @@ _NDIM = {
|
||||
'actuator_actrange': 3,
|
||||
'actuator_biasprm': 3,
|
||||
'actuator_biastype': 1,
|
||||
'actuator_cranklength': 1,
|
||||
'actuator_cranklength': 2,
|
||||
'actuator_ctrllimited': 1,
|
||||
'actuator_ctrlrange': 3,
|
||||
'actuator_dynprm': 3,
|
||||
@@ -491,7 +520,7 @@ _NDIM = {
|
||||
'actuator_gainprm': 3,
|
||||
'actuator_gaintype': 1,
|
||||
'actuator_gear': 3,
|
||||
'actuator_lengthrange': 2,
|
||||
'actuator_lengthrange': 3,
|
||||
'actuator_trnid': 2,
|
||||
'actuator_trntype': 1,
|
||||
'actuator_trntype_body_adr': 1,
|
||||
@@ -670,6 +699,7 @@ _NDIM = {
|
||||
'mesh_normal': 2,
|
||||
'mesh_normaladr': 1,
|
||||
'mesh_normalnum': 1,
|
||||
'mesh_octadr': 1,
|
||||
'mesh_polyadr': 1,
|
||||
'mesh_polymap': 1,
|
||||
'mesh_polymapadr': 1,
|
||||
@@ -685,6 +715,8 @@ _NDIM = {
|
||||
'mesh_vertnum': 1,
|
||||
'mocap_bodyid': 1,
|
||||
'nC': 0,
|
||||
'nJfe': 0,
|
||||
'nJmom': 0,
|
||||
'nM': 0,
|
||||
'na': 0,
|
||||
'nacttrnbody': 0,
|
||||
@@ -924,6 +956,9 @@ _BATCH_DIM = {
|
||||
'cvel': True,
|
||||
'efc__D': True,
|
||||
'efc__J': True,
|
||||
'efc__J_colind': True,
|
||||
'efc__J_rowadr': True,
|
||||
'efc__J_rownnz': True,
|
||||
'efc__Ma': True,
|
||||
'efc__aref': True,
|
||||
'efc__force': True,
|
||||
@@ -946,6 +981,9 @@ _BATCH_DIM = {
|
||||
'light_xpos': True,
|
||||
'mocap_pos': True,
|
||||
'mocap_quat': True,
|
||||
'moment_colind': True,
|
||||
'moment_rowadr': True,
|
||||
'moment_rownnz': True,
|
||||
'naccdmax': False,
|
||||
'nacon': False,
|
||||
'naconmax': False,
|
||||
@@ -953,7 +991,9 @@ _BATCH_DIM = {
|
||||
'ne': True,
|
||||
'nefc': True,
|
||||
'nf': True,
|
||||
'nisland': True,
|
||||
'njmax': False,
|
||||
'njmax_pad': False,
|
||||
'nl': True,
|
||||
'nworld': False,
|
||||
'qLD': True,
|
||||
@@ -988,6 +1028,7 @@ _BATCH_DIM = {
|
||||
'ten_wrapadr': True,
|
||||
'ten_wrapnum': True,
|
||||
'time': True,
|
||||
'tree_island': True,
|
||||
'wrap_obj': True,
|
||||
'wrap_xpos': True,
|
||||
'xanchor': True,
|
||||
@@ -1003,7 +1044,7 @@ _BATCH_DIM = {
|
||||
'M_colind': False,
|
||||
'M_rowadr': False,
|
||||
'M_rownnz': False,
|
||||
'actuator_acc0': False,
|
||||
'actuator_acc0': True,
|
||||
'actuator_actadr': False,
|
||||
'actuator_actearly': False,
|
||||
'actuator_actlimited': False,
|
||||
@@ -1011,7 +1052,7 @@ _BATCH_DIM = {
|
||||
'actuator_actrange': True,
|
||||
'actuator_biasprm': True,
|
||||
'actuator_biastype': False,
|
||||
'actuator_cranklength': False,
|
||||
'actuator_cranklength': True,
|
||||
'actuator_ctrllimited': False,
|
||||
'actuator_ctrlrange': True,
|
||||
'actuator_dynprm': True,
|
||||
@@ -1021,7 +1062,7 @@ _BATCH_DIM = {
|
||||
'actuator_gainprm': True,
|
||||
'actuator_gaintype': False,
|
||||
'actuator_gear': True,
|
||||
'actuator_lengthrange': False,
|
||||
'actuator_lengthrange': True,
|
||||
'actuator_trnid': False,
|
||||
'actuator_trntype': False,
|
||||
'actuator_trntype_body_adr': False,
|
||||
@@ -1200,6 +1241,7 @@ _BATCH_DIM = {
|
||||
'mesh_normal': False,
|
||||
'mesh_normaladr': False,
|
||||
'mesh_normalnum': False,
|
||||
'mesh_octadr': False,
|
||||
'mesh_polyadr': False,
|
||||
'mesh_polymap': False,
|
||||
'mesh_polymapadr': False,
|
||||
@@ -1215,6 +1257,8 @@ _BATCH_DIM = {
|
||||
'mesh_vertnum': False,
|
||||
'mocap_bodyid': False,
|
||||
'nC': False,
|
||||
'nJfe': False,
|
||||
'nJmom': False,
|
||||
'nM': False,
|
||||
'na': False,
|
||||
'nacttrnbody': False,
|
||||
|
||||
Reference in New Issue
Block a user