Import google-deepmind/mujoco_warp from GitHub.
PiperOrigin-RevId: 829017789 Change-Id: I2756e349297cd0ae53a63a38fb203e2fd2d5cb99
This commit is contained in:
committed by
Copybara-Service
parent
7dfd92098f
commit
fa062768f4
@@ -434,9 +434,9 @@ class DataIOTest(parameterized.TestCase):
|
|||||||
if not mjx_io.has_cuda_gpu_device():
|
if not mjx_io.has_cuda_gpu_device():
|
||||||
self.skipTest('No CUDA GPU device.')
|
self.skipTest('No CUDA GPU device.')
|
||||||
m = mujoco.MjModel.from_xml_string(_MULTIPLE_CONVEX_OBJECTS)
|
m = mujoco.MjModel.from_xml_string(_MULTIPLE_CONVEX_OBJECTS)
|
||||||
d = mjx.make_data(m, impl='warp', nconmax=9, njmax=11)
|
d = mjx.make_data(m, impl='warp', nconmax=9, njmax=23)
|
||||||
self.assertEqual(d._impl.contact__dist.shape[0], 9)
|
self.assertEqual(d._impl.contact__dist.shape[0], 9)
|
||||||
self.assertEqual(d._impl.efc__J.shape[0], 11)
|
self.assertEqual(d._impl.efc__pos.shape[0], 23)
|
||||||
|
|
||||||
@parameterized.parameters('jax', 'c')
|
@parameterized.parameters('jax', 'c')
|
||||||
def test_put_data(self, impl: str):
|
def test_put_data(self, impl: str):
|
||||||
|
|||||||
@@ -754,7 +754,7 @@ class Model(PyTreeNode):
|
|||||||
geom_solref: jax.Array
|
geom_solref: jax.Array
|
||||||
geom_solimp: jax.Array
|
geom_solimp: jax.Array
|
||||||
geom_size: jax.Array
|
geom_size: jax.Array
|
||||||
geom_aabb: np.ndarray
|
geom_aabb: jax.Array
|
||||||
geom_rbound: jax.Array
|
geom_rbound: jax.Array
|
||||||
geom_pos: jax.Array
|
geom_pos: jax.Array
|
||||||
geom_quat: jax.Array
|
geom_quat: jax.Array
|
||||||
|
|||||||
@@ -65,7 +65,9 @@ from mujoco.mjx.third_party.mujoco_warp._src.smooth import tendon as tendon
|
|||||||
from mujoco.mjx.third_party.mujoco_warp._src.smooth import transmission as transmission
|
from mujoco.mjx.third_party.mujoco_warp._src.smooth import transmission as transmission
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.solver import solve as solve
|
from mujoco.mjx.third_party.mujoco_warp._src.solver import solve as solve
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.support import contact_force as contact_force
|
from mujoco.mjx.third_party.mujoco_warp._src.support import contact_force as contact_force
|
||||||
|
from mujoco.mjx.third_party.mujoco_warp._src.support import get_state as get_state
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.support import mul_m as mul_m
|
from mujoco.mjx.third_party.mujoco_warp._src.support import mul_m as mul_m
|
||||||
|
from mujoco.mjx.third_party.mujoco_warp._src.support import set_state as set_state
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.support import xfrc_accumulate as xfrc_accumulate
|
from mujoco.mjx.third_party.mujoco_warp._src.support import xfrc_accumulate as xfrc_accumulate
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import BiasType as BiasType
|
from mujoco.mjx.third_party.mujoco_warp._src.types import BiasType as BiasType
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import BroadphaseFilter as BroadphaseFilter
|
from mujoco.mjx.third_party.mujoco_warp._src.types import BroadphaseFilter as BroadphaseFilter
|
||||||
@@ -82,5 +84,6 @@ from mujoco.mjx.third_party.mujoco_warp._src.types import IntegratorType as Inte
|
|||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import JointType as JointType
|
from mujoco.mjx.third_party.mujoco_warp._src.types import JointType as JointType
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Option as Option
|
from mujoco.mjx.third_party.mujoco_warp._src.types import Option as Option
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import SolverType as SolverType
|
from mujoco.mjx.third_party.mujoco_warp._src.types import SolverType as SolverType
|
||||||
|
from mujoco.mjx.third_party.mujoco_warp._src.types import State as State
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Statistic as Statistic
|
from mujoco.mjx.third_party.mujoco_warp._src.types import Statistic as Statistic
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import TrnType as TrnType
|
from mujoco.mjx.third_party.mujoco_warp._src.types import TrnType as TrnType
|
||||||
|
|||||||
+46
-32
@@ -45,28 +45,46 @@ def _sum(stack1, stack2):
|
|||||||
@wp.kernel
|
@wp.kernel
|
||||||
def ctrl_noise(
|
def ctrl_noise(
|
||||||
# Model:
|
# Model:
|
||||||
|
opt_timestep: wp.array(dtype=float),
|
||||||
actuator_ctrllimited: wp.array(dtype=bool),
|
actuator_ctrllimited: wp.array(dtype=bool),
|
||||||
actuator_ctrlrange: wp.array2d(dtype=wp.vec2),
|
actuator_ctrlrange: wp.array2d(dtype=wp.vec2),
|
||||||
|
# Data in:
|
||||||
|
ctrl_in: wp.array2d(dtype=float),
|
||||||
# In:
|
# In:
|
||||||
ctrl_center: wp.array1d(dtype=float),
|
ctrl_center: wp.array1d(dtype=float),
|
||||||
step: int,
|
step: int,
|
||||||
ctrlnoise: float,
|
ctrlnoisestd: float,
|
||||||
|
ctrlnoiserate: float,
|
||||||
# Data out:
|
# Data out:
|
||||||
ctrl_out: wp.array2d(dtype=float),
|
ctrl_out: wp.array2d(dtype=float),
|
||||||
):
|
):
|
||||||
worldid, actid = wp.tid()
|
worldid, actid = wp.tid()
|
||||||
|
|
||||||
center = 0.0
|
# convert rate and scale to discrete time (Ornstein-Uhlenbeck)
|
||||||
radius = 1.0
|
rate = wp.exp(-opt_timestep[0] / ctrlnoiserate)
|
||||||
|
scale = ctrlnoisestd * wp.sqrt(1.0 - rate * rate)
|
||||||
|
|
||||||
|
midpoint = 0.0
|
||||||
|
halfrange = 1.0
|
||||||
ctrlrange = actuator_ctrlrange[0, actid]
|
ctrlrange = actuator_ctrlrange[0, actid]
|
||||||
|
is_limited = actuator_ctrllimited[actid]
|
||||||
|
if is_limited:
|
||||||
|
midpoint = 0.5 * (ctrlrange[1] + ctrlrange[0])
|
||||||
|
halfrange = 0.5 * (ctrlrange[1] - ctrlrange[0])
|
||||||
if ctrl_center.shape[0] > 0:
|
if ctrl_center.shape[0] > 0:
|
||||||
center = ctrl_center[actid]
|
midpoint = ctrl_center[actid]
|
||||||
elif actuator_ctrllimited[actid]:
|
|
||||||
center = (ctrlrange[1] + ctrlrange[0]) / 2.0
|
# exponential convergence to midpoint at ctrlnoiserate
|
||||||
radius = (ctrlrange[1] - ctrlrange[0]) / 2.0
|
ctrl = rate * ctrl_in[worldid, actid] + (1.0 - rate) * midpoint
|
||||||
radius *= ctrlnoise
|
|
||||||
noise = 2.0 * halton((step + 1) * (worldid + 1), actid + 2) - 1.0
|
# add noise
|
||||||
ctrl_out[worldid, actid] = center + radius * noise
|
ctrl += scale * halfrange * (2.0 * halton((step + 1) * (worldid + 1), actid + 2) - 1.0)
|
||||||
|
|
||||||
|
# clip to range if limited
|
||||||
|
if is_limited:
|
||||||
|
ctrl = wp.clamp(ctrl, ctrlrange[0], ctrlrange[1])
|
||||||
|
|
||||||
|
ctrl_out[worldid, actid] = ctrl
|
||||||
|
|
||||||
|
|
||||||
def benchmark(
|
def benchmark(
|
||||||
@@ -82,28 +100,24 @@ def benchmark(
|
|||||||
"""Benchmark a function of Model and Data.
|
"""Benchmark a function of Model and Data.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
fn (Callable[[Model, Data], None]): Function to benchmark.
|
fn: Function to benchmark.
|
||||||
m (Model): The model containing kinematic and dynamic information (device).
|
m: The model containing kinematic and dynamic information (device).
|
||||||
d (Data): The data object containing the current state and output information (device).
|
d: The data object containing the current state and output information (device).
|
||||||
nstep (int): Number of timesteps.
|
nstep: Number of timesteps.
|
||||||
ctrls (list, optional): control sequence to apply during benchmarking.
|
ctrls: Control sequence to apply during benchmarking.
|
||||||
Default is None.
|
event_trace: If True, time routines decorated with @event_scope.
|
||||||
event_trace (bool, optional): If True, time routines decorated with @event_scope.
|
measure_alloc: If True, record number of contacts and constraints.
|
||||||
Default is False.
|
measure_solver_niter: If True, record the number of solver iterations.
|
||||||
measure_alloc (bool, optional): If True, record number of contacts and constraints.
|
|
||||||
Default is False.
|
|
||||||
measure_solver_niter (bool, False): If True, record the number of solver iterations.
|
|
||||||
Default is False.
|
|
||||||
Returns:
|
|
||||||
float: Time to JIT fn.
|
|
||||||
float: Total time to run the benchmark.
|
|
||||||
dict: Trace.
|
|
||||||
list: Number of contacts.
|
|
||||||
list: Number of constraints.
|
|
||||||
list: Number of solver iterations.
|
|
||||||
int: Number of converged worlds.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- Time to JIT fn.
|
||||||
|
- Total time to run the benchmark.
|
||||||
|
- Trace.
|
||||||
|
- Number of contacts.
|
||||||
|
- Number of constraints.
|
||||||
|
- Number of solver iterations.
|
||||||
|
- Number of converged worlds.
|
||||||
|
"""
|
||||||
trace = {}
|
trace = {}
|
||||||
nacon, nefc, solver_niter = [], [], []
|
nacon, nefc, solver_niter = [], [], []
|
||||||
center = wp.array([], dtype=wp.float32)
|
center = wp.array([], dtype=wp.float32)
|
||||||
@@ -126,7 +140,7 @@ def benchmark(
|
|||||||
wp.launch(
|
wp.launch(
|
||||||
ctrl_noise,
|
ctrl_noise,
|
||||||
dim=(d.nworld, m.nu),
|
dim=(d.nworld, m.nu),
|
||||||
inputs=[m.actuator_ctrllimited, m.actuator_ctrlrange, center, i, 0.01],
|
inputs=[m.opt.timestep, m.actuator_ctrllimited, m.actuator_ctrlrange, d.ctrl, center, i, 0.01, 0.1],
|
||||||
outputs=[d.ctrl],
|
outputs=[d.ctrl],
|
||||||
)
|
)
|
||||||
wp.synchronize()
|
wp.synchronize()
|
||||||
|
|||||||
@@ -29,11 +29,10 @@ def create_blocked_cholesky_func(block_size: int):
|
|||||||
# Out:
|
# Out:
|
||||||
L: wp.array(dtype=float, ndim=2),
|
L: wp.array(dtype=float, ndim=2),
|
||||||
):
|
):
|
||||||
"""
|
"""Computes the Cholesky factorization of a symmetric positive definite matrix A in blocks.
|
||||||
Computes the Cholesky factorization of a symmetric positive definite matrix A in blocks.
|
|
||||||
It returns a lower-triangular matrix L such that A = L L^T.
|
It returns a lower-triangular matrix L such that A = L L^T.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
num_threads_per_block = wp.block_dim()
|
num_threads_per_block = wp.block_dim()
|
||||||
|
|
||||||
# Round up active_matrix_size to next multiple of block_size
|
# Round up active_matrix_size to next multiple of block_size
|
||||||
@@ -120,11 +119,11 @@ def create_blocked_cholesky_solve_func(block_size: int):
|
|||||||
# Out:
|
# Out:
|
||||||
x: wp.array(dtype=float, ndim=2),
|
x: wp.array(dtype=float, ndim=2),
|
||||||
):
|
):
|
||||||
"""
|
"""Block Cholesky factorization and solve.
|
||||||
Solves A x = b given the Cholesky factor L (A = L L^T) using
|
|
||||||
blocked forward and backward substitution.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
Solves A x = b given the Cholesky factor L (A = L L^T) using blocked forward and backward
|
||||||
|
substitution.
|
||||||
|
"""
|
||||||
num_threads_per_block = wp.block_dim()
|
num_threads_per_block = wp.block_dim()
|
||||||
|
|
||||||
# Round up active_matrix_size to next multiple of block_size
|
# Round up active_matrix_size to next multiple of block_size
|
||||||
|
|||||||
+169
-55
@@ -16,6 +16,7 @@
|
|||||||
import warp as wp
|
import warp as wp
|
||||||
|
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_gjk import ccd
|
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_legacy import epa_legacy
|
from mujoco.mjx.third_party.mujoco_warp._src.collision_gjk_legacy import epa_legacy
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_gjk_legacy import gjk_legacy
|
from mujoco.mjx.third_party.mujoco_warp._src.collision_gjk_legacy import gjk_legacy
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_gjk_legacy import multicontact_legacy
|
from mujoco.mjx.third_party.mujoco_warp._src.collision_gjk_legacy import multicontact_legacy
|
||||||
@@ -26,6 +27,8 @@ from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import geom
|
|||||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import write_contact
|
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import write_contact
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.math import make_frame
|
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.math import upper_trid_index
|
||||||
|
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_MAXCONPAIR
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Data
|
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 GeomType
|
||||||
@@ -88,6 +91,7 @@ def ccd_kernel_builder(
|
|||||||
epa_exact_neg_distance: bool,
|
epa_exact_neg_distance: bool,
|
||||||
depth_extension: float,
|
depth_extension: float,
|
||||||
is_hfield: bool,
|
is_hfield: bool,
|
||||||
|
use_multiccd: bool,
|
||||||
):
|
):
|
||||||
@wp.func
|
@wp.func
|
||||||
def eval_ccd_write_contact(
|
def eval_ccd_write_contact(
|
||||||
@@ -96,6 +100,7 @@ def ccd_kernel_builder(
|
|||||||
geom_type: wp.array(dtype=int),
|
geom_type: wp.array(dtype=int),
|
||||||
# Data in:
|
# Data in:
|
||||||
naconmax_in: int,
|
naconmax_in: int,
|
||||||
|
# In:
|
||||||
epa_vert_in: wp.array2d(dtype=wp.vec3),
|
epa_vert_in: wp.array2d(dtype=wp.vec3),
|
||||||
epa_vert1_in: wp.array2d(dtype=wp.vec3),
|
epa_vert1_in: wp.array2d(dtype=wp.vec3),
|
||||||
epa_vert2_in: wp.array2d(dtype=wp.vec3),
|
epa_vert2_in: wp.array2d(dtype=wp.vec3),
|
||||||
@@ -118,7 +123,6 @@ def ccd_kernel_builder(
|
|||||||
multiccd_endvert_in: wp.array2d(dtype=wp.vec3),
|
multiccd_endvert_in: wp.array2d(dtype=wp.vec3),
|
||||||
multiccd_face1_in: wp.array2d(dtype=wp.vec3),
|
multiccd_face1_in: wp.array2d(dtype=wp.vec3),
|
||||||
multiccd_face2_in: wp.array2d(dtype=wp.vec3),
|
multiccd_face2_in: wp.array2d(dtype=wp.vec3),
|
||||||
# In:
|
|
||||||
geom1: Geom,
|
geom1: Geom,
|
||||||
geom2: Geom,
|
geom2: Geom,
|
||||||
geoms: wp.vec2i,
|
geoms: wp.vec2i,
|
||||||
@@ -134,8 +138,8 @@ def ccd_kernel_builder(
|
|||||||
x1: wp.vec3,
|
x1: wp.vec3,
|
||||||
x2: wp.vec3,
|
x2: wp.vec3,
|
||||||
count: int,
|
count: int,
|
||||||
|
pairid: wp.vec2i,
|
||||||
# Data out:
|
# Data out:
|
||||||
nacon_out: wp.array(dtype=int),
|
|
||||||
contact_dist_out: wp.array(dtype=float),
|
contact_dist_out: wp.array(dtype=float),
|
||||||
contact_pos_out: wp.array(dtype=wp.vec3),
|
contact_pos_out: wp.array(dtype=wp.vec3),
|
||||||
contact_frame_out: wp.array(dtype=wp.mat33),
|
contact_frame_out: wp.array(dtype=wp.mat33),
|
||||||
@@ -147,6 +151,9 @@ def ccd_kernel_builder(
|
|||||||
contact_dim_out: wp.array(dtype=int),
|
contact_dim_out: wp.array(dtype=int),
|
||||||
contact_geom_out: wp.array(dtype=wp.vec2i),
|
contact_geom_out: wp.array(dtype=wp.vec2i),
|
||||||
contact_worldid_out: wp.array(dtype=int),
|
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:
|
) -> int:
|
||||||
# TODO(kbayes): remove legacy GJK once multicontact can be enabled
|
# TODO(kbayes): remove legacy GJK once multicontact can be enabled
|
||||||
if wp.static(legacy_gjk):
|
if wp.static(legacy_gjk):
|
||||||
@@ -176,12 +183,18 @@ def ccd_kernel_builder(
|
|||||||
frame = make_frame(normal)
|
frame = make_frame(normal)
|
||||||
else:
|
else:
|
||||||
points = mat3c()
|
points = mat3c()
|
||||||
|
witness1 = mat3c()
|
||||||
|
witness2 = mat3c()
|
||||||
geom1.margin = margin
|
geom1.margin = margin
|
||||||
geom2.margin = margin
|
geom2.margin = margin
|
||||||
dist, ncontact, witness1, witness2 = ccd(
|
if pairid[1] >= 0:
|
||||||
False, # ignored for box-box, multiccd always on
|
# if collision sensor, set large cutoff to work with various sensor cutoff values
|
||||||
opt_ccd_tolerance[worldid],
|
cutoff = 1.0e32
|
||||||
0.0,
|
else:
|
||||||
|
cutoff = 0.0
|
||||||
|
dist, ncontact, w1, w2, idx = ccd(
|
||||||
|
opt_ccd_tolerance[worldid % opt_ccd_tolerance.shape[0]],
|
||||||
|
cutoff,
|
||||||
ccd_iterations,
|
ccd_iterations,
|
||||||
geom1,
|
geom1,
|
||||||
geom2,
|
geom2,
|
||||||
@@ -200,29 +213,60 @@ def ccd_kernel_builder(
|
|||||||
epa_index_in[tid],
|
epa_index_in[tid],
|
||||||
epa_map_in[tid],
|
epa_map_in[tid],
|
||||||
epa_horizon_in[tid],
|
epa_horizon_in[tid],
|
||||||
multiccd_polygon_in[tid],
|
|
||||||
multiccd_clipped_in[tid],
|
|
||||||
multiccd_pnormal_in[tid],
|
|
||||||
multiccd_pdist_in[tid],
|
|
||||||
multiccd_idx1_in[tid],
|
|
||||||
multiccd_idx2_in[tid],
|
|
||||||
multiccd_n1_in[tid],
|
|
||||||
multiccd_n2_in[tid],
|
|
||||||
multiccd_endvert_in[tid],
|
|
||||||
multiccd_face1_in[tid],
|
|
||||||
multiccd_face2_in[tid],
|
|
||||||
)
|
)
|
||||||
if dist >= 0.0:
|
|
||||||
|
if dist >= 0.0 and pairid[1] == -1:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
witness1[0] = w1
|
||||||
|
witness2[0] = w2
|
||||||
|
|
||||||
|
if wp.static(use_multiccd):
|
||||||
|
if (
|
||||||
|
geom1.margin == 0.0
|
||||||
|
and geom2.margin == 0.0
|
||||||
|
and (geomtype1 == GeomType.BOX or (geomtype1 == GeomType.MESH and geom1.mesh_polyadr > -1))
|
||||||
|
and (geomtype2 == GeomType.BOX or (geomtype2 == GeomType.MESH and geom2.mesh_polyadr > -1))
|
||||||
|
):
|
||||||
|
ncontact, witness1, witness2 = multicontact(
|
||||||
|
multiccd_polygon_in[tid],
|
||||||
|
multiccd_clipped_in[tid],
|
||||||
|
multiccd_pnormal_in[tid],
|
||||||
|
multiccd_pdist_in[tid],
|
||||||
|
multiccd_idx1_in[tid],
|
||||||
|
multiccd_idx2_in[tid],
|
||||||
|
multiccd_n1_in[tid],
|
||||||
|
multiccd_n2_in[tid],
|
||||||
|
multiccd_endvert_in[tid],
|
||||||
|
multiccd_face1_in[tid],
|
||||||
|
multiccd_face2_in[tid],
|
||||||
|
epa_vert1_in[tid],
|
||||||
|
epa_vert2_in[tid],
|
||||||
|
epa_vert_index1_in[tid],
|
||||||
|
epa_vert_index2_in[tid],
|
||||||
|
epa_face_in[tid, idx],
|
||||||
|
w1,
|
||||||
|
w2,
|
||||||
|
geom1,
|
||||||
|
geom2,
|
||||||
|
geomtype1,
|
||||||
|
geomtype2,
|
||||||
|
)
|
||||||
|
|
||||||
for i in range(ncontact):
|
for i in range(ncontact):
|
||||||
points[i] = 0.5 * (witness1[i] + witness2[i])
|
points[i] = 0.5 * (witness1[i] + witness2[i])
|
||||||
normal = witness1[0] - witness2[0]
|
normal = witness1[0] - witness2[0]
|
||||||
frame = make_frame(normal)
|
frame = make_frame(normal)
|
||||||
|
|
||||||
|
# flip if collision sensor
|
||||||
|
if pairid[1] >= 0:
|
||||||
|
frame *= -1.0
|
||||||
|
geoms = wp.vec2i(geoms[1], geoms[0])
|
||||||
|
|
||||||
for i in range(ncontact):
|
for i in range(ncontact):
|
||||||
write_contact(
|
write_contact(
|
||||||
naconmax_in,
|
naconmax_in,
|
||||||
|
i,
|
||||||
dist,
|
dist,
|
||||||
points[i],
|
points[i],
|
||||||
frame,
|
frame,
|
||||||
@@ -234,8 +278,8 @@ def ccd_kernel_builder(
|
|||||||
solreffriction,
|
solreffriction,
|
||||||
solimp,
|
solimp,
|
||||||
geoms,
|
geoms,
|
||||||
|
pairid,
|
||||||
worldid,
|
worldid,
|
||||||
nacon_out,
|
|
||||||
contact_dist_out,
|
contact_dist_out,
|
||||||
contact_pos_out,
|
contact_pos_out,
|
||||||
contact_frame_out,
|
contact_frame_out,
|
||||||
@@ -247,6 +291,9 @@ def ccd_kernel_builder(
|
|||||||
contact_dim_out,
|
contact_dim_out,
|
||||||
contact_geom_out,
|
contact_geom_out,
|
||||||
contact_worldid_out,
|
contact_worldid_out,
|
||||||
|
contact_type_out,
|
||||||
|
contact_geomcollisionid_out,
|
||||||
|
nacon_out,
|
||||||
)
|
)
|
||||||
if count + (i + 1) >= MJ_MAXCONPAIR:
|
if count + (i + 1) >= MJ_MAXCONPAIR:
|
||||||
return i + 1
|
return i + 1
|
||||||
@@ -266,7 +313,7 @@ def ccd_kernel_builder(
|
|||||||
geom_solref: wp.array2d(dtype=wp.vec2),
|
geom_solref: wp.array2d(dtype=wp.vec2),
|
||||||
geom_solimp: wp.array2d(dtype=vec5),
|
geom_solimp: wp.array2d(dtype=vec5),
|
||||||
geom_size: wp.array2d(dtype=wp.vec3),
|
geom_size: wp.array2d(dtype=wp.vec3),
|
||||||
geom_aabb: wp.array2d(dtype=wp.vec3),
|
geom_aabb: wp.array3d(dtype=wp.vec3),
|
||||||
geom_rbound: wp.array2d(dtype=float),
|
geom_rbound: wp.array2d(dtype=float),
|
||||||
geom_friction: wp.array2d(dtype=wp.vec3),
|
geom_friction: wp.array2d(dtype=wp.vec3),
|
||||||
geom_margin: wp.array2d(dtype=float),
|
geom_margin: wp.array2d(dtype=float),
|
||||||
@@ -302,9 +349,10 @@ def ccd_kernel_builder(
|
|||||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||||
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
||||||
collision_pair_in: wp.array(dtype=wp.vec2i),
|
collision_pair_in: wp.array(dtype=wp.vec2i),
|
||||||
collision_pairid_in: wp.array(dtype=int),
|
collision_pairid_in: wp.array(dtype=wp.vec2i),
|
||||||
collision_worldid_in: wp.array(dtype=int),
|
collision_worldid_in: wp.array(dtype=int),
|
||||||
ncollision_in: wp.array(dtype=int),
|
ncollision_in: wp.array(dtype=int),
|
||||||
|
# In:
|
||||||
epa_vert_in: wp.array2d(dtype=wp.vec3),
|
epa_vert_in: wp.array2d(dtype=wp.vec3),
|
||||||
epa_vert1_in: wp.array2d(dtype=wp.vec3),
|
epa_vert1_in: wp.array2d(dtype=wp.vec3),
|
||||||
epa_vert2_in: wp.array2d(dtype=wp.vec3),
|
epa_vert2_in: wp.array2d(dtype=wp.vec3),
|
||||||
@@ -340,6 +388,8 @@ def ccd_kernel_builder(
|
|||||||
contact_dim_out: wp.array(dtype=int),
|
contact_dim_out: wp.array(dtype=int),
|
||||||
contact_geom_out: wp.array(dtype=wp.vec2i),
|
contact_geom_out: wp.array(dtype=wp.vec2i),
|
||||||
contact_worldid_out: wp.array(dtype=int),
|
contact_worldid_out: wp.array(dtype=int),
|
||||||
|
contact_type_out: wp.array(dtype=int),
|
||||||
|
contact_geomcollisionid_out: wp.array(dtype=int),
|
||||||
):
|
):
|
||||||
tid = wp.tid()
|
tid = wp.tid()
|
||||||
if tid >= ncollision_in[0]:
|
if tid >= ncollision_in[0]:
|
||||||
@@ -384,15 +434,17 @@ def ccd_kernel_builder(
|
|||||||
worldid,
|
worldid,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
geom_size_id = worldid % geom_size.shape[0]
|
||||||
|
|
||||||
geom1_dataid = geom_dataid[g1]
|
geom1_dataid = geom_dataid[g1]
|
||||||
geom1 = geom(
|
geom1 = geom(
|
||||||
geomtype1,
|
geomtype1,
|
||||||
geom1_dataid,
|
geom1_dataid,
|
||||||
geom_size[worldid, g1],
|
geom_size[geom_size_id, g1],
|
||||||
mesh_vertadr,
|
mesh_vertadr,
|
||||||
mesh_vertnum,
|
mesh_vertnum,
|
||||||
mesh_vert,
|
|
||||||
mesh_graphadr,
|
mesh_graphadr,
|
||||||
|
mesh_vert,
|
||||||
mesh_graph,
|
mesh_graph,
|
||||||
mesh_polynum,
|
mesh_polynum,
|
||||||
mesh_polyadr,
|
mesh_polyadr,
|
||||||
@@ -411,11 +463,11 @@ def ccd_kernel_builder(
|
|||||||
geom2 = geom(
|
geom2 = geom(
|
||||||
geomtype2,
|
geomtype2,
|
||||||
geom2_dataid,
|
geom2_dataid,
|
||||||
geom_size[worldid, g2],
|
geom_size[geom_size_id, g2],
|
||||||
mesh_vertadr,
|
mesh_vertadr,
|
||||||
mesh_vertnum,
|
mesh_vertnum,
|
||||||
mesh_vert,
|
|
||||||
mesh_graphadr,
|
mesh_graphadr,
|
||||||
|
mesh_vert,
|
||||||
mesh_graph,
|
mesh_graph,
|
||||||
mesh_polynum,
|
mesh_polynum,
|
||||||
mesh_polyadr,
|
mesh_polyadr,
|
||||||
@@ -433,9 +485,9 @@ def ccd_kernel_builder(
|
|||||||
# see MuJoCo mjc_ConvexHField
|
# see MuJoCo mjc_ConvexHField
|
||||||
if wp.static(is_hfield):
|
if wp.static(is_hfield):
|
||||||
# height field subgrid
|
# height field subgrid
|
||||||
nrow = hfield_nrow[g1]
|
nrow = hfield_nrow[geom1_dataid]
|
||||||
ncol = hfield_ncol[g1]
|
ncol = hfield_ncol[geom1_dataid]
|
||||||
size = hfield_size[g1]
|
size = hfield_size[geom1_dataid]
|
||||||
|
|
||||||
# subgrid
|
# subgrid
|
||||||
x_scale = 0.5 * float(ncol - 1) / size[0]
|
x_scale = 0.5 * float(ncol - 1) / size[0]
|
||||||
@@ -541,7 +593,7 @@ def ccd_kernel_builder(
|
|||||||
x1,
|
x1,
|
||||||
geom2.pos,
|
geom2.pos,
|
||||||
count,
|
count,
|
||||||
nacon_out,
|
collision_pairid_in[tid],
|
||||||
contact_dist_out,
|
contact_dist_out,
|
||||||
contact_pos_out,
|
contact_pos_out,
|
||||||
contact_frame_out,
|
contact_frame_out,
|
||||||
@@ -553,6 +605,9 @@ def ccd_kernel_builder(
|
|||||||
contact_dim_out,
|
contact_dim_out,
|
||||||
contact_geom_out,
|
contact_geom_out,
|
||||||
contact_worldid_out,
|
contact_worldid_out,
|
||||||
|
contact_type_out,
|
||||||
|
contact_geomcollisionid_out,
|
||||||
|
nacon_out,
|
||||||
)
|
)
|
||||||
count += ncontact
|
count += ncontact
|
||||||
if count >= MJ_MAXCONPAIR:
|
if count >= MJ_MAXCONPAIR:
|
||||||
@@ -599,7 +654,7 @@ def ccd_kernel_builder(
|
|||||||
geom1.pos,
|
geom1.pos,
|
||||||
geom2.pos,
|
geom2.pos,
|
||||||
0,
|
0,
|
||||||
nacon_out,
|
collision_pairid_in[tid],
|
||||||
contact_dist_out,
|
contact_dist_out,
|
||||||
contact_pos_out,
|
contact_pos_out,
|
||||||
contact_frame_out,
|
contact_frame_out,
|
||||||
@@ -611,6 +666,9 @@ def ccd_kernel_builder(
|
|||||||
contact_dim_out,
|
contact_dim_out,
|
||||||
contact_geom_out,
|
contact_geom_out,
|
||||||
contact_worldid_out,
|
contact_worldid_out,
|
||||||
|
contact_type_out,
|
||||||
|
contact_geomcollisionid_out,
|
||||||
|
nacon_out,
|
||||||
)
|
)
|
||||||
|
|
||||||
return ccd_kernel
|
return ccd_kernel
|
||||||
@@ -625,19 +683,73 @@ def convex_narrowphase(m: Model, d: Data):
|
|||||||
determine the distance between shapes and the Expanding Polytope Algorithm (EPA) to find
|
determine the distance between shapes and the Expanding Polytope Algorithm (EPA) to find
|
||||||
the penetration depth and contact normal for colliding pairs.
|
the penetration depth and contact normal for colliding pairs.
|
||||||
|
|
||||||
The convex geom types handled by this function are SPHERE, CAPSULE, ELLIPSOID, CYLINDER,
|
The convex geom types handled by this function are `SPHERE`, `CAPSULE`, `ELLIPSOID`, `CYLINDER`,
|
||||||
BOX, MESH, HFIELD.
|
`BOX`, `MESH`, `HFIELD`.
|
||||||
|
|
||||||
To optimize performance, this function dynamically builds and launches a specialized
|
To optimize performance, this function dynamically builds and launches a specialized
|
||||||
kernel for each type of convex collision pair present in the model, avoiding unnecessary
|
kernel for each type of convex collision pair present in the model, avoiding unnecessary
|
||||||
computations for non-existent pair types.
|
computations for non-existent pair types.
|
||||||
"""
|
"""
|
||||||
|
# TODO(team): fix early return?
|
||||||
|
if not any(m.geom_pair_type_count[upper_trid_index(len(GeomType), g[0].value, g[1].value)] for g in _CONVEX_COLLISION_PAIRS):
|
||||||
|
return
|
||||||
|
|
||||||
|
# set to true to enable multiccd
|
||||||
|
use_multiccd = False
|
||||||
|
nmaxpolygon = m.nmaxpolygon if use_multiccd else 0
|
||||||
|
nmaxmeshdeg = m.nmaxmeshdeg if use_multiccd else 0
|
||||||
|
|
||||||
|
# epa_vert: vertices in EPA polytope in Minkowski space
|
||||||
|
epa_vert = wp.empty(shape=(d.naconmax, 5 + m.opt.ccd_iterations), dtype=wp.vec3)
|
||||||
|
# epa_vert1: vertices in EPA polytope in geom 1 space
|
||||||
|
epa_vert1 = wp.empty(shape=(d.naconmax, 5 + m.opt.ccd_iterations), dtype=wp.vec3)
|
||||||
|
# epa_vert2: vertices in EPA polytope in geom 2 space
|
||||||
|
epa_vert2 = wp.empty(shape=(d.naconmax, 5 + m.opt.ccd_iterations), dtype=wp.vec3)
|
||||||
|
# epa_vert_index1: vertex indices in EPA polytope for geom 1
|
||||||
|
epa_vert_index1 = wp.empty(shape=(d.naconmax, 5 + m.opt.ccd_iterations), dtype=int)
|
||||||
|
# epa_vert_index2: vertex indices in EPA polytope for geom 2 (naconmax, 5 + CCDiter)
|
||||||
|
epa_vert_index2 = wp.empty(shape=(d.naconmax, 5 + m.opt.ccd_iterations), dtype=int)
|
||||||
|
# epa_face: faces of polytope represented by three indices
|
||||||
|
epa_face = wp.empty(shape=(d.naconmax, 6 + MJ_MAX_EPAFACES * m.opt.ccd_iterations), dtype=wp.vec3i)
|
||||||
|
# epa_pr: projection of origin on polytope faces
|
||||||
|
epa_pr = wp.empty(shape=(d.naconmax, 6 + MJ_MAX_EPAFACES * m.opt.ccd_iterations), dtype=wp.vec3)
|
||||||
|
# epa_norm2: epa_pr * epa_pr
|
||||||
|
epa_norm2 = wp.empty(shape=(d.naconmax, 6 + MJ_MAX_EPAFACES * m.opt.ccd_iterations), dtype=float)
|
||||||
|
# epa_index: index of face in polytope map
|
||||||
|
epa_index = wp.empty(shape=(d.naconmax, 6 + MJ_MAX_EPAFACES * m.opt.ccd_iterations), dtype=int)
|
||||||
|
# epa_map: status of faces in polytope
|
||||||
|
epa_map = wp.empty(shape=(d.naconmax, 6 + MJ_MAX_EPAFACES * m.opt.ccd_iterations), dtype=int)
|
||||||
|
# epa_horizon: index pair (i j) of edges on horizon
|
||||||
|
epa_horizon = wp.empty(shape=(d.naconmax, 2 * MJ_MAX_EPAHORIZON), dtype=int)
|
||||||
|
# multiccd_polygon: clipped contact surface
|
||||||
|
multiccd_polygon = wp.empty(shape=(d.naconmax, 2 * nmaxpolygon), dtype=wp.vec3)
|
||||||
|
# multiccd_clipped: clipped contact surface (intermediate)
|
||||||
|
multiccd_clipped = wp.empty(shape=(d.naconmax, 2 * nmaxpolygon), dtype=wp.vec3)
|
||||||
|
# multiccd_pnormal: plane normal of clipping polygon
|
||||||
|
multiccd_pnormal = wp.empty(shape=(d.naconmax, nmaxpolygon), dtype=wp.vec3)
|
||||||
|
# multiccd_pdist: plane distance of clipping polygon
|
||||||
|
multiccd_pdist = wp.empty(shape=(d.naconmax, nmaxpolygon), dtype=float)
|
||||||
|
# multiccd_idx1: list of normal index candidates for Geom 1
|
||||||
|
multiccd_idx1 = wp.empty(shape=(d.naconmax, nmaxmeshdeg), dtype=int)
|
||||||
|
# multiccd_idx2: list of normal index candidates for Geom 2
|
||||||
|
multiccd_idx2 = wp.empty(shape=(d.naconmax, nmaxmeshdeg), dtype=int)
|
||||||
|
# multiccd_n1: list of normal candidates for Geom 1
|
||||||
|
multiccd_n1 = wp.empty(shape=(d.naconmax, nmaxmeshdeg), dtype=wp.vec3)
|
||||||
|
# multiccd_n2: list of normal candidates for Geom 1
|
||||||
|
multiccd_n2 = wp.empty(shape=(d.naconmax, nmaxmeshdeg), dtype=wp.vec3)
|
||||||
|
# multiccd_endvert: list of edge vertices candidates
|
||||||
|
multiccd_endvert = wp.empty(shape=(d.naconmax, nmaxmeshdeg), dtype=wp.vec3)
|
||||||
|
# multiccd_face1: contact face
|
||||||
|
multiccd_face1 = wp.empty(shape=(d.naconmax, nmaxpolygon), dtype=wp.vec3)
|
||||||
|
# multiccd_face2: contact face
|
||||||
|
multiccd_face2 = wp.empty(shape=(d.naconmax, nmaxpolygon), dtype=wp.vec3)
|
||||||
|
|
||||||
for geom_pair in _CONVEX_COLLISION_PAIRS:
|
for geom_pair in _CONVEX_COLLISION_PAIRS:
|
||||||
g1 = geom_pair[0].value
|
g1 = geom_pair[0].value
|
||||||
g2 = geom_pair[1].value
|
g2 = geom_pair[1].value
|
||||||
if m.geom_pair_type_count[upper_trid_index(len(GeomType), g1, g2)]:
|
if m.geom_pair_type_count[upper_trid_index(len(GeomType), g1, g2)]:
|
||||||
wp.launch(
|
wp.launch(
|
||||||
ccd_kernel_builder(m.opt.legacy_gjk, g1, g2, m.opt.ccd_iterations, True, 1e9, g1 == GeomType.HFIELD),
|
ccd_kernel_builder(m.opt.legacy_gjk, g1, g2, m.opt.ccd_iterations, True, 1e9, g1 == GeomType.HFIELD, use_multiccd),
|
||||||
dim=d.naconmax,
|
dim=d.naconmax,
|
||||||
inputs=[
|
inputs=[
|
||||||
m.opt.ccd_tolerance,
|
m.opt.ccd_tolerance,
|
||||||
@@ -687,28 +799,28 @@ def convex_narrowphase(m: Model, d: Data):
|
|||||||
d.collision_pairid,
|
d.collision_pairid,
|
||||||
d.collision_worldid,
|
d.collision_worldid,
|
||||||
d.ncollision,
|
d.ncollision,
|
||||||
d.epa_vert,
|
epa_vert,
|
||||||
d.epa_vert1,
|
epa_vert1,
|
||||||
d.epa_vert2,
|
epa_vert2,
|
||||||
d.epa_vert_index1,
|
epa_vert_index1,
|
||||||
d.epa_vert_index2,
|
epa_vert_index2,
|
||||||
d.epa_face,
|
epa_face,
|
||||||
d.epa_pr,
|
epa_pr,
|
||||||
d.epa_norm2,
|
epa_norm2,
|
||||||
d.epa_index,
|
epa_index,
|
||||||
d.epa_map,
|
epa_map,
|
||||||
d.epa_horizon,
|
epa_horizon,
|
||||||
d.multiccd_polygon,
|
multiccd_polygon,
|
||||||
d.multiccd_clipped,
|
multiccd_clipped,
|
||||||
d.multiccd_pnormal,
|
multiccd_pnormal,
|
||||||
d.multiccd_pdist,
|
multiccd_pdist,
|
||||||
d.multiccd_idx1,
|
multiccd_idx1,
|
||||||
d.multiccd_idx2,
|
multiccd_idx2,
|
||||||
d.multiccd_n1,
|
multiccd_n1,
|
||||||
d.multiccd_n2,
|
multiccd_n2,
|
||||||
d.multiccd_endvert,
|
multiccd_endvert,
|
||||||
d.multiccd_face1,
|
multiccd_face1,
|
||||||
d.multiccd_face2,
|
multiccd_face2,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
d.nacon,
|
d.nacon,
|
||||||
@@ -723,5 +835,7 @@ def convex_narrowphase(m: Model, d: Data):
|
|||||||
d.contact.dim,
|
d.contact.dim,
|
||||||
d.contact.geom,
|
d.contact.geom,
|
||||||
d.contact.worldid,
|
d.contact.worldid,
|
||||||
|
d.contact.type,
|
||||||
|
d.contact.geomcollisionid,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
+130
-128
@@ -26,7 +26,6 @@ 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 BroadphaseType
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Data
|
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 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 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 cache_kernel
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import event_scope
|
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import event_scope
|
||||||
@@ -233,12 +232,11 @@ def _obb_filter(
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@cache_kernel
|
def _broadphase_filter(m: Model):
|
||||||
def _broadphase_filter(opt_broadphase_filter: int):
|
|
||||||
@wp.func
|
@wp.func
|
||||||
def func(
|
def func(
|
||||||
# Model:
|
# Model:
|
||||||
geom_aabb: wp.array2d(dtype=wp.vec3),
|
geom_aabb: wp.array3d(dtype=wp.vec3),
|
||||||
geom_rbound: wp.array2d(dtype=float),
|
geom_rbound: wp.array2d(dtype=float),
|
||||||
geom_margin: wp.array2d(dtype=float),
|
geom_margin: wp.array2d(dtype=float),
|
||||||
# Data in:
|
# Data in:
|
||||||
@@ -254,30 +252,28 @@ def _broadphase_filter(opt_broadphase_filter: int):
|
|||||||
# 4: aabb
|
# 4: aabb
|
||||||
# 8: obb
|
# 8: obb
|
||||||
|
|
||||||
center1 = geom_aabb[geom1, 0]
|
aabb_id = worldid % geom_aabb.shape[0] if wp.static(m.geom_aabb.shape[0] > 1) else 0
|
||||||
center2 = geom_aabb[geom2, 0]
|
center1, center2 = geom_aabb[aabb_id, geom1, 0], geom_aabb[aabb_id, geom2, 0]
|
||||||
size1 = geom_aabb[geom1, 1]
|
size1, size2 = geom_aabb[aabb_id, geom1, 1], geom_aabb[aabb_id, geom2, 1]
|
||||||
size2 = geom_aabb[geom2, 1]
|
|
||||||
rbound1 = geom_rbound[worldid, geom1]
|
rbound_id = worldid % geom_rbound.shape[0] if wp.static(m.geom_rbound.shape[0] > 1) else 0
|
||||||
rbound2 = geom_rbound[worldid, geom2]
|
rbound1, rbound2 = geom_rbound[rbound_id, geom1], geom_rbound[rbound_id, geom2]
|
||||||
margin1 = geom_margin[worldid, geom1]
|
margin_id = worldid % geom_margin.shape[0] if wp.static(m.geom_margin.shape[0] > 1) else 0
|
||||||
margin2 = geom_margin[worldid, geom2]
|
margin1, margin2 = geom_margin[margin_id, geom1], geom_margin[margin_id, geom2]
|
||||||
xpos1 = geom_xpos_in[worldid, geom1]
|
xpos1, xpos2 = geom_xpos_in[worldid, geom1], geom_xpos_in[worldid, geom2]
|
||||||
xpos2 = geom_xpos_in[worldid, geom2]
|
xmat1, xmat2 = geom_xmat_in[worldid, geom1], geom_xmat_in[worldid, geom2]
|
||||||
xmat1 = geom_xmat_in[worldid, geom1]
|
|
||||||
xmat2 = geom_xmat_in[worldid, geom2]
|
|
||||||
|
|
||||||
if rbound1 == 0.0 or rbound2 == 0.0:
|
if rbound1 == 0.0 or rbound2 == 0.0:
|
||||||
if wp.static(opt_broadphase_filter & BroadphaseFilter.PLANE):
|
if wp.static(m.opt.broadphase_filter & BroadphaseFilter.PLANE):
|
||||||
return _plane_filter(rbound1, rbound2, margin1, margin2, xpos1, xpos2, xmat1, xmat2)
|
return _plane_filter(rbound1, rbound2, margin1, margin2, xpos1, xpos2, xmat1, xmat2)
|
||||||
else:
|
else:
|
||||||
if wp.static(opt_broadphase_filter & BroadphaseFilter.SPHERE):
|
if wp.static(m.opt.broadphase_filter & BroadphaseFilter.SPHERE):
|
||||||
if not _sphere_filter(rbound1, rbound2, margin1, margin2, xpos1, xpos2):
|
if not _sphere_filter(rbound1, rbound2, margin1, margin2, xpos1, xpos2):
|
||||||
return False
|
return False
|
||||||
if wp.static(opt_broadphase_filter & BroadphaseFilter.AABB):
|
if wp.static(m.opt.broadphase_filter & BroadphaseFilter.AABB):
|
||||||
if not _aabb_filter(center1, center2, size1, size2, margin1, margin2, xpos1, xpos2, xmat1, xmat2):
|
if not _aabb_filter(center1, center2, size1, size2, margin1, margin2, xpos1, xpos2, xmat1, xmat2):
|
||||||
return False
|
return False
|
||||||
if wp.static(opt_broadphase_filter & BroadphaseFilter.OBB):
|
if wp.static(m.opt.broadphase_filter & BroadphaseFilter.OBB):
|
||||||
if not _obb_filter(center1, center2, size1, size2, margin1, margin2, xpos1, xpos2, xmat1, xmat2):
|
if not _obb_filter(center1, center2, size1, size2, margin1, margin2, xpos1, xpos2, xmat1, xmat2):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -290,7 +286,7 @@ def _broadphase_filter(opt_broadphase_filter: int):
|
|||||||
def _add_geom_pair(
|
def _add_geom_pair(
|
||||||
# Model:
|
# Model:
|
||||||
geom_type: wp.array(dtype=int),
|
geom_type: wp.array(dtype=int),
|
||||||
nxn_pairid: wp.array(dtype=int),
|
nxn_pairid: wp.array(dtype=wp.vec2i),
|
||||||
# Data in:
|
# Data in:
|
||||||
naconmax_in: int,
|
naconmax_in: int,
|
||||||
# In:
|
# In:
|
||||||
@@ -300,7 +296,7 @@ def _add_geom_pair(
|
|||||||
nxnid: int,
|
nxnid: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
collision_pair_out: wp.array(dtype=wp.vec2i),
|
collision_pair_out: wp.array(dtype=wp.vec2i),
|
||||||
collision_pairid_out: wp.array(dtype=int),
|
collision_pairid_out: wp.array(dtype=wp.vec2i),
|
||||||
collision_worldid_out: wp.array(dtype=int),
|
collision_worldid_out: wp.array(dtype=int),
|
||||||
ncollision_out: wp.array(dtype=int),
|
ncollision_out: wp.array(dtype=int),
|
||||||
):
|
):
|
||||||
@@ -334,64 +330,76 @@ def _binary_search(values: wp.array(dtype=Any), value: Any, lower: int, upper: i
|
|||||||
return upper
|
return upper
|
||||||
|
|
||||||
|
|
||||||
@wp.kernel
|
def _sap_project(opt_broadphase: int):
|
||||||
def _sap_project(
|
@nested_kernel(module="unique", enable_backward=False)
|
||||||
# Model:
|
def sap_project(
|
||||||
geom_rbound: wp.array2d(dtype=float),
|
# Model:
|
||||||
geom_margin: wp.array2d(dtype=float),
|
ngeom: int,
|
||||||
# Data in:
|
geom_rbound: wp.array2d(dtype=float),
|
||||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
geom_margin: wp.array2d(dtype=float),
|
||||||
# In:
|
# Data in:
|
||||||
direction_in: wp.vec3,
|
nworld_in: int,
|
||||||
# Data out:
|
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||||
sap_projection_lower_out: wp.array2d(dtype=float), # kernel_analyzer: ignore
|
# In:
|
||||||
sap_projection_upper_out: wp.array2d(dtype=float),
|
direction_in: wp.vec3,
|
||||||
sap_sort_index_out: wp.array2d(dtype=int), # kernel_analyzer: ignore
|
# Out:
|
||||||
):
|
projection_lower_out: wp.array2d(dtype=float),
|
||||||
worldid, geomid = wp.tid()
|
projection_upper_out: wp.array2d(dtype=float),
|
||||||
|
sort_index_out: wp.array2d(dtype=int),
|
||||||
|
segmented_index_out: wp.array(dtype=int),
|
||||||
|
):
|
||||||
|
worldid, geomid = wp.tid()
|
||||||
|
|
||||||
xpos = geom_xpos_in[worldid, geomid]
|
xpos = geom_xpos_in[worldid, geomid]
|
||||||
rbound = geom_rbound[worldid, geomid]
|
rbound = geom_rbound[worldid % geom_rbound.shape[0], geomid]
|
||||||
|
|
||||||
if rbound == 0.0:
|
if rbound == 0.0:
|
||||||
# geom is a plane
|
# geom is a plane
|
||||||
rbound = MJ_MAXVAL
|
rbound = MJ_MAXVAL
|
||||||
|
|
||||||
radius = rbound + geom_margin[worldid, geomid]
|
radius = rbound + geom_margin[worldid % geom_margin.shape[0], geomid]
|
||||||
center = wp.dot(direction_in, xpos)
|
center = wp.dot(direction_in, xpos)
|
||||||
|
|
||||||
sap_sort_index_out[worldid, geomid] = geomid
|
sort_index_out[worldid, geomid] = geomid
|
||||||
if not wp.isnan(center):
|
if not wp.isnan(center):
|
||||||
sap_projection_lower_out[worldid, geomid] = center - radius
|
projection_lower_out[worldid, geomid] = center - radius
|
||||||
sap_projection_upper_out[worldid, geomid] = center + radius
|
projection_upper_out[worldid, geomid] = center + radius
|
||||||
else:
|
else:
|
||||||
sap_projection_lower_out[worldid, geomid] = MJ_MAXVAL
|
projection_lower_out[worldid, geomid] = MJ_MAXVAL
|
||||||
sap_projection_upper_out[worldid, geomid] = MJ_MAXVAL
|
projection_upper_out[worldid, geomid] = MJ_MAXVAL
|
||||||
|
|
||||||
|
if wp.static(opt_broadphase == BroadphaseType.SAP_SEGMENTED):
|
||||||
|
if geomid == 0:
|
||||||
|
segmented_index_out[worldid] = worldid * ngeom
|
||||||
|
if worldid == nworld_in - 1:
|
||||||
|
segmented_index_out[nworld_in] = nworld_in * ngeom
|
||||||
|
|
||||||
|
return sap_project
|
||||||
|
|
||||||
|
|
||||||
@wp.kernel
|
@wp.kernel
|
||||||
def _sap_range(
|
def _sap_range(
|
||||||
# Model:
|
# Model:
|
||||||
ngeom: int,
|
ngeom: int,
|
||||||
# Data in:
|
# In:
|
||||||
sap_projection_lower_in: wp.array2d(dtype=float), # kernel_analyzer: ignore
|
projection_lower_in: wp.array2d(dtype=float),
|
||||||
sap_projection_upper_in: wp.array2d(dtype=float),
|
projection_upper_in: wp.array2d(dtype=float),
|
||||||
sap_sort_index_in: wp.array2d(dtype=int), # kernel_analyzer: ignore
|
sort_index_in: wp.array2d(dtype=int),
|
||||||
# Data out:
|
# Out:
|
||||||
sap_range_out: wp.array2d(dtype=int),
|
range_out: wp.array2d(dtype=int),
|
||||||
):
|
):
|
||||||
worldid, geomid = wp.tid()
|
worldid, geomid = wp.tid()
|
||||||
|
|
||||||
# current bounding geom
|
# current bounding geom
|
||||||
idx = sap_sort_index_in[worldid, geomid]
|
idx = sort_index_in[worldid, geomid]
|
||||||
|
|
||||||
upper = sap_projection_upper_in[worldid, idx]
|
upper = projection_upper_in[worldid, idx]
|
||||||
|
|
||||||
limit = _binary_search(sap_projection_lower_in[worldid], upper, geomid + 1, ngeom)
|
limit = _binary_search(projection_lower_in[worldid], upper, geomid + 1, ngeom)
|
||||||
limit = wp.min(ngeom - 1, limit)
|
limit = wp.min(ngeom - 1, limit)
|
||||||
|
|
||||||
# range of geoms for the sweep and prune process
|
# range of geoms for the sweep and prune process
|
||||||
sap_range_out[worldid, geomid] = limit - geomid
|
range_out[worldid, geomid] = limit - geomid
|
||||||
|
|
||||||
|
|
||||||
@cache_kernel
|
@cache_kernel
|
||||||
@@ -401,45 +409,45 @@ def _sap_broadphase(broadphase_filter):
|
|||||||
# Model:
|
# Model:
|
||||||
ngeom: int,
|
ngeom: int,
|
||||||
geom_type: wp.array(dtype=int),
|
geom_type: wp.array(dtype=int),
|
||||||
geom_aabb: wp.array2d(dtype=wp.vec3),
|
geom_aabb: wp.array3d(dtype=wp.vec3),
|
||||||
geom_rbound: wp.array2d(dtype=float),
|
geom_rbound: wp.array2d(dtype=float),
|
||||||
geom_margin: wp.array2d(dtype=float),
|
geom_margin: wp.array2d(dtype=float),
|
||||||
nxn_pairid: wp.array(dtype=int),
|
nxn_pairid: wp.array(dtype=wp.vec2i),
|
||||||
# Data in:
|
# Data in:
|
||||||
nworld_in: int,
|
nworld_in: int,
|
||||||
naconmax_in: int,
|
naconmax_in: int,
|
||||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||||
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
||||||
sap_sort_index_in: wp.array2d(dtype=int), # kernel_analyzer: ignore
|
|
||||||
sap_cumulative_sum_in: wp.array(dtype=int), # kernel_analyzer: ignore
|
|
||||||
# In:
|
# In:
|
||||||
|
sort_index_in: wp.array2d(dtype=int),
|
||||||
|
cumulative_sum_in: wp.array(dtype=int),
|
||||||
nsweep_in: int,
|
nsweep_in: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
collision_pair_out: wp.array(dtype=wp.vec2i),
|
collision_pair_out: wp.array(dtype=wp.vec2i),
|
||||||
collision_pairid_out: wp.array(dtype=int),
|
collision_pairid_out: wp.array(dtype=wp.vec2i),
|
||||||
collision_worldid_out: wp.array(dtype=int),
|
collision_worldid_out: wp.array(dtype=int),
|
||||||
ncollision_out: wp.array(dtype=int),
|
ncollision_out: wp.array(dtype=int),
|
||||||
):
|
):
|
||||||
worldgeomid = wp.tid()
|
worldgeomid = wp.tid()
|
||||||
|
|
||||||
nworldgeom = nworld_in * ngeom
|
nworldgeom = nworld_in * ngeom
|
||||||
nworkpackages = sap_cumulative_sum_in[nworldgeom - 1]
|
nworkpackages = cumulative_sum_in[nworldgeom - 1]
|
||||||
|
|
||||||
while worldgeomid < nworkpackages:
|
while worldgeomid < nworkpackages:
|
||||||
# binary search to find current and next geom pair indices
|
# binary search to find current and next geom pair indices
|
||||||
i = _binary_search(sap_cumulative_sum_in, worldgeomid, 0, nworldgeom)
|
i = _binary_search(cumulative_sum_in, worldgeomid, 0, nworldgeom)
|
||||||
j = i + worldgeomid + 1
|
j = i + worldgeomid + 1
|
||||||
|
|
||||||
if i > 0:
|
if i > 0:
|
||||||
j -= sap_cumulative_sum_in[i - 1]
|
j -= cumulative_sum_in[i - 1]
|
||||||
|
|
||||||
worldid = i // ngeom
|
worldid = i // ngeom
|
||||||
i = i % ngeom
|
i = i % ngeom
|
||||||
j = j % ngeom
|
j = j % ngeom
|
||||||
|
|
||||||
# get geom indices and swap if necessary
|
# get geom indices and swap if necessary
|
||||||
geom1 = sap_sort_index_in[worldid, i]
|
geom1 = sort_index_in[worldid, i]
|
||||||
geom2 = sap_sort_index_in[worldid, j]
|
geom2 = sort_index_in[worldid, j]
|
||||||
|
|
||||||
# find linear index of (geom1, geom2) in upper triangular nxn_pairid
|
# find linear index of (geom1, geom2) in upper triangular nxn_pairid
|
||||||
if geom2 < geom1:
|
if geom2 < geom1:
|
||||||
@@ -448,10 +456,14 @@ def _sap_broadphase(broadphase_filter):
|
|||||||
idx = upper_tri_index(ngeom, geom1, geom2)
|
idx = upper_tri_index(ngeom, geom1, geom2)
|
||||||
|
|
||||||
worldgeomid += nsweep_in
|
worldgeomid += nsweep_in
|
||||||
if nxn_pairid[idx] < -1:
|
pairid = nxn_pairid[idx]
|
||||||
|
if pairid[0] < -1 and pairid[1] < 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if broadphase_filter(geom_aabb, geom_rbound, geom_margin, geom_xpos_in, geom_xmat_in, geom1, geom2, worldid):
|
if (
|
||||||
|
broadphase_filter(geom_aabb, geom_rbound, geom_margin, geom_xpos_in, geom_xmat_in, geom1, geom2, worldid)
|
||||||
|
or pairid[1] >= 0
|
||||||
|
):
|
||||||
_add_geom_pair(
|
_add_geom_pair(
|
||||||
geom_type,
|
geom_type,
|
||||||
nxn_pairid,
|
nxn_pairid,
|
||||||
@@ -472,22 +484,25 @@ def _sap_broadphase(broadphase_filter):
|
|||||||
def _segmented_sort(tile_size: int):
|
def _segmented_sort(tile_size: int):
|
||||||
@wp.kernel
|
@wp.kernel
|
||||||
def segmented_sort(
|
def segmented_sort(
|
||||||
# Data in:
|
# In:
|
||||||
sap_projection_lower_in: wp.array2d(dtype=float), # kernel_analyzer: ignore
|
projection_lower_in: wp.array2d(dtype=float),
|
||||||
sap_sort_index_in: wp.array2d(dtype=int), # kernel_analyzer: ignore
|
sort_index_in: wp.array2d(dtype=int),
|
||||||
|
# Out:
|
||||||
|
projection_lower_out: wp.array2d(dtype=float),
|
||||||
|
sort_index_out: wp.array2d(dtype=int),
|
||||||
):
|
):
|
||||||
worldid = wp.tid()
|
worldid = wp.tid()
|
||||||
|
|
||||||
# Load input into shared memory
|
# Load input into shared memory
|
||||||
keys = wp.tile_load(sap_projection_lower_in[worldid], shape=tile_size, storage="shared")
|
keys = wp.tile_load(projection_lower_in[worldid], shape=tile_size, storage="shared")
|
||||||
values = wp.tile_load(sap_sort_index_in[worldid], shape=tile_size, storage="shared")
|
values = wp.tile_load(sort_index_in[worldid], shape=tile_size, storage="shared")
|
||||||
|
|
||||||
# Perform in-place sorting
|
# Perform in-place sorting
|
||||||
wp.tile_sort(keys, values)
|
wp.tile_sort(keys, values)
|
||||||
|
|
||||||
# Store sorted shared memory into output arrays
|
# Store sorted shared memory into output arrays
|
||||||
wp.tile_store(sap_projection_lower_in[worldid], keys)
|
wp.tile_store(projection_lower_out[worldid], keys)
|
||||||
wp.tile_store(sap_sort_index_in[worldid], values)
|
wp.tile_store(sort_index_out[worldid], values)
|
||||||
|
|
||||||
return segmented_sort
|
return segmented_sort
|
||||||
|
|
||||||
@@ -505,11 +520,11 @@ def sap_broadphase(m: Model, d: Data):
|
|||||||
bounding sphere check is performed. If this check passes, the pair is added
|
bounding sphere check is performed. If this check passes, the pair is added
|
||||||
to the collision arrays in `d` for the narrowphase stage.
|
to the collision arrays in `d` for the narrowphase stage.
|
||||||
|
|
||||||
Two sorting strategies are supported, controlled by `m.opt.broadphase`:
|
Two sorting strategies are supported, controlled by `m.opt.broadphase`
|
||||||
|
|
||||||
- `SAP_TILE`: Uses a tile-based sort.
|
- `SAP_TILE`: Uses a tile-based sort.
|
||||||
- `SAP_SEGMENTED`: Uses a segmented sort.
|
- `SAP_SEGMENTED`: Uses a segmented sort.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
nworldgeom = d.nworld * m.ngeom
|
nworldgeom = d.nworld * m.ngeom
|
||||||
|
|
||||||
# TODO(team): direction
|
# TODO(team): direction
|
||||||
@@ -518,58 +533,52 @@ def sap_broadphase(m: Model, d: Data):
|
|||||||
direction = wp.vec3(0.5935, 0.7790, 0.1235)
|
direction = wp.vec3(0.5935, 0.7790, 0.1235)
|
||||||
direction = wp.normalize(direction)
|
direction = wp.normalize(direction)
|
||||||
|
|
||||||
|
projection_lower = wp.empty((d.nworld, m.ngeom, 2), dtype=float)
|
||||||
|
projection_upper = wp.empty((d.nworld, m.ngeom), dtype=float)
|
||||||
|
sort_index = wp.empty((d.nworld, m.ngeom, 2), dtype=int)
|
||||||
|
range_ = wp.empty((d.nworld, m.ngeom), dtype=int)
|
||||||
|
cumulative_sum = wp.empty((d.nworld, m.ngeom), dtype=int)
|
||||||
|
segmented_index = wp.empty(d.nworld + 1 if m.opt.broadphase == BroadphaseType.SAP_SEGMENTED else 0, dtype=int)
|
||||||
|
|
||||||
wp.launch(
|
wp.launch(
|
||||||
kernel=_sap_project,
|
kernel=_sap_project(m.opt.broadphase),
|
||||||
dim=(d.nworld, m.ngeom),
|
dim=(d.nworld, m.ngeom),
|
||||||
inputs=[
|
inputs=[m.ngeom, m.geom_rbound, m.geom_margin, d.nworld, d.geom_xpos, direction],
|
||||||
m.geom_rbound,
|
|
||||||
m.geom_margin,
|
|
||||||
d.geom_xpos,
|
|
||||||
direction,
|
|
||||||
],
|
|
||||||
outputs=[
|
outputs=[
|
||||||
d.sap_projection_lower.reshape((-1, m.ngeom)),
|
projection_lower.reshape((-1, m.ngeom)),
|
||||||
d.sap_projection_upper,
|
projection_upper,
|
||||||
d.sap_sort_index.reshape((-1, m.ngeom)),
|
sort_index.reshape((-1, m.ngeom)),
|
||||||
|
segmented_index,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
if m.opt.broadphase == BroadphaseType.SAP_TILE:
|
if m.opt.broadphase == BroadphaseType.SAP_TILE:
|
||||||
wp.launch_tiled(
|
wp.launch_tiled(
|
||||||
kernel=_segmented_sort(m.ngeom),
|
kernel=_segmented_sort(m.ngeom),
|
||||||
dim=(d.nworld),
|
dim=d.nworld,
|
||||||
inputs=[d.sap_projection_lower.reshape((-1, m.ngeom)), d.sap_sort_index.reshape((-1, m.ngeom))],
|
inputs=[projection_lower.reshape((-1, m.ngeom)), sort_index.reshape((-1, m.ngeom))],
|
||||||
|
outputs=[projection_lower.reshape((-1, m.ngeom)), sort_index.reshape((-1, m.ngeom))],
|
||||||
block_dim=m.block_dim.segmented_sort,
|
block_dim=m.block_dim.segmented_sort,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
wp.utils.segmented_sort_pairs(
|
wp.utils.segmented_sort_pairs(
|
||||||
d.sap_projection_lower.reshape((-1, m.ngeom)),
|
projection_lower.reshape((-1, m.ngeom)), sort_index.reshape((-1, m.ngeom)), nworldgeom, segmented_index
|
||||||
d.sap_sort_index.reshape((-1, m.ngeom)),
|
|
||||||
nworldgeom,
|
|
||||||
d.sap_segment_index.reshape(-1),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
wp.launch(
|
wp.launch(
|
||||||
kernel=_sap_range,
|
kernel=_sap_range,
|
||||||
dim=(d.nworld, m.ngeom),
|
dim=(d.nworld, m.ngeom),
|
||||||
inputs=[
|
inputs=[m.ngeom, projection_lower.reshape((-1, m.ngeom)), projection_upper, sort_index.reshape((-1, m.ngeom))],
|
||||||
m.ngeom,
|
outputs=[range_],
|
||||||
d.sap_projection_lower.reshape((-1, m.ngeom)),
|
|
||||||
d.sap_projection_upper,
|
|
||||||
d.sap_sort_index.reshape((-1, m.ngeom)),
|
|
||||||
],
|
|
||||||
outputs=[
|
|
||||||
d.sap_range,
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# scan is used for load balancing among the threads
|
# scan is used for load balancing among the threads
|
||||||
wp.utils.array_scan(d.sap_range.reshape(-1), d.sap_cumulative_sum.reshape(-1), True)
|
wp.utils.array_scan(range_.reshape(-1), cumulative_sum.reshape(-1), True)
|
||||||
|
|
||||||
# estimate number of overlap checks
|
# estimate number of overlap checks
|
||||||
# assumes each geom has 5 other geoms (batched over all worlds)
|
# assumes each geom has 5 other geoms (batched over all worlds)
|
||||||
nsweep = 5 * nworldgeom
|
nsweep = 5 * nworldgeom
|
||||||
broadphase_filter = _broadphase_filter(m.opt.broadphase_filter)
|
broadphase_filter = _broadphase_filter(m)
|
||||||
wp.launch(
|
wp.launch(
|
||||||
kernel=_sap_broadphase(broadphase_filter),
|
kernel=_sap_broadphase(broadphase_filter),
|
||||||
dim=nsweep,
|
dim=nsweep,
|
||||||
@@ -584,16 +593,11 @@ def sap_broadphase(m: Model, d: Data):
|
|||||||
d.naconmax,
|
d.naconmax,
|
||||||
d.geom_xpos,
|
d.geom_xpos,
|
||||||
d.geom_xmat,
|
d.geom_xmat,
|
||||||
d.sap_sort_index.reshape((-1, m.ngeom)),
|
sort_index.reshape((-1, m.ngeom)),
|
||||||
d.sap_cumulative_sum.reshape(-1),
|
cumulative_sum.reshape(-1),
|
||||||
nsweep,
|
nsweep,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[d.collision_pair, d.collision_pairid, d.collision_worldid, d.ncollision],
|
||||||
d.collision_pair,
|
|
||||||
d.collision_pairid,
|
|
||||||
d.collision_worldid,
|
|
||||||
d.ncollision,
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -603,18 +607,18 @@ def _nxn_broadphase(broadphase_filter):
|
|||||||
def kernel(
|
def kernel(
|
||||||
# Model:
|
# Model:
|
||||||
geom_type: wp.array(dtype=int),
|
geom_type: wp.array(dtype=int),
|
||||||
geom_aabb: wp.array2d(dtype=wp.vec3),
|
geom_aabb: wp.array3d(dtype=wp.vec3),
|
||||||
geom_rbound: wp.array2d(dtype=float),
|
geom_rbound: wp.array2d(dtype=float),
|
||||||
geom_margin: wp.array2d(dtype=float),
|
geom_margin: wp.array2d(dtype=float),
|
||||||
nxn_geom_pair: wp.array(dtype=wp.vec2i),
|
nxn_geom_pair: wp.array(dtype=wp.vec2i),
|
||||||
nxn_pairid: wp.array(dtype=int),
|
nxn_pairid: wp.array(dtype=wp.vec2i),
|
||||||
# Data in:
|
# Data in:
|
||||||
naconmax_in: int,
|
naconmax_in: int,
|
||||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||||
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
||||||
# Data out:
|
# Data out:
|
||||||
collision_pair_out: wp.array(dtype=wp.vec2i),
|
collision_pair_out: wp.array(dtype=wp.vec2i),
|
||||||
collision_pairid_out: wp.array(dtype=int),
|
collision_pairid_out: wp.array(dtype=wp.vec2i),
|
||||||
collision_worldid_out: wp.array(dtype=int),
|
collision_worldid_out: wp.array(dtype=int),
|
||||||
ncollision_out: wp.array(dtype=int),
|
ncollision_out: wp.array(dtype=int),
|
||||||
):
|
):
|
||||||
@@ -624,7 +628,10 @@ def _nxn_broadphase(broadphase_filter):
|
|||||||
geom1 = geom[0]
|
geom1 = geom[0]
|
||||||
geom2 = geom[1]
|
geom2 = geom[1]
|
||||||
|
|
||||||
if broadphase_filter(geom_aabb, geom_rbound, geom_margin, geom_xpos_in, geom_xmat_in, geom1, geom2, worldid):
|
if (
|
||||||
|
broadphase_filter(geom_aabb, geom_rbound, geom_margin, geom_xpos_in, geom_xmat_in, geom1, geom2, worldid)
|
||||||
|
or nxn_pairid[elementid][1] >= 0
|
||||||
|
):
|
||||||
_add_geom_pair(
|
_add_geom_pair(
|
||||||
geom_type,
|
geom_type,
|
||||||
nxn_pairid,
|
nxn_pairid,
|
||||||
@@ -656,8 +663,7 @@ def nxn_broadphase(m: Model, d: Data):
|
|||||||
The initial list of pairs is filtered at model creation time to exclude pairs based on
|
The initial list of pairs is filtered at model creation time to exclude pairs based on
|
||||||
`contype`/`conaffinity`, parent-child relationships, and explicit `<exclude>` tags.
|
`contype`/`conaffinity`, parent-child relationships, and explicit `<exclude>` tags.
|
||||||
"""
|
"""
|
||||||
|
broadphase_filter = _broadphase_filter(m)
|
||||||
broadphase_filter = _broadphase_filter(m.opt.broadphase_filter)
|
|
||||||
wp.launch(
|
wp.launch(
|
||||||
_nxn_broadphase(broadphase_filter),
|
_nxn_broadphase(broadphase_filter),
|
||||||
dim=(d.nworld, m.nxn_geom_pair_filtered.shape[0]),
|
dim=(d.nworld, m.nxn_geom_pair_filtered.shape[0]),
|
||||||
@@ -709,7 +715,6 @@ def collision(m: Model, d: Data):
|
|||||||
This function will do nothing except zero out arrays if collision detection is disabled
|
This function will do nothing except zero out arrays if collision detection is disabled
|
||||||
via `m.opt.disableflags` or if `d.nacon` is 0.
|
via `m.opt.disableflags` or if `d.nacon` is 0.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# zero contact and collision counters
|
# zero contact and collision counters
|
||||||
wp.launch(_zero_nacon_ncollision, dim=1, outputs=[d.nacon, d.ncollision])
|
wp.launch(_zero_nacon_ncollision, dim=1, outputs=[d.nacon, d.ncollision])
|
||||||
|
|
||||||
@@ -721,7 +726,4 @@ def collision(m: Model, d: Data):
|
|||||||
else:
|
else:
|
||||||
sap_broadphase(m, d)
|
sap_broadphase(m, d)
|
||||||
|
|
||||||
if m.opt.graph_conditional:
|
_narrowphase(m, d)
|
||||||
wp.capture_if(condition=d.ncollision, on_true=_narrowphase, m=m, d=d)
|
|
||||||
else:
|
|
||||||
_narrowphase(m, d)
|
|
||||||
|
|||||||
+19
-74
@@ -924,7 +924,7 @@ def _polytope2(
|
|||||||
geomtype1: int,
|
geomtype1: int,
|
||||||
geomtype2: int,
|
geomtype2: int,
|
||||||
) -> Tuple[Polytope, GJKResult]:
|
) -> Tuple[Polytope, GJKResult]:
|
||||||
"""Create polytope for EPA given a 1-simplex from GJK"""
|
"""Create polytope for EPA given a 1-simplex from GJK."""
|
||||||
diff = simplex[1] - simplex[0]
|
diff = simplex[1] - simplex[0]
|
||||||
|
|
||||||
# find component with smallest magnitude (so cross product is largest)
|
# find component with smallest magnitude (so cross product is largest)
|
||||||
@@ -1023,7 +1023,7 @@ def _polytope3(
|
|||||||
geomtype1: int,
|
geomtype1: int,
|
||||||
geomtype2: int,
|
geomtype2: int,
|
||||||
) -> Polytope:
|
) -> Polytope:
|
||||||
"""Create polytope for EPA given a 2-simplex from GJK"""
|
"""Create polytope for EPA given a 2-simplex from GJK."""
|
||||||
# get normals in both directions
|
# get normals in both directions
|
||||||
n = wp.cross(simplex[1] - simplex[0], simplex[2] - simplex[0])
|
n = wp.cross(simplex[1] - simplex[0], simplex[2] - simplex[0])
|
||||||
if wp.norm_l2(n) < MJ_MINVAL:
|
if wp.norm_l2(n) < MJ_MINVAL:
|
||||||
@@ -1123,7 +1123,7 @@ def _polytope4(
|
|||||||
geomtype1: int,
|
geomtype1: int,
|
||||||
geomtype2: int,
|
geomtype2: int,
|
||||||
) -> Tuple[Polytope, GJKResult]:
|
) -> Tuple[Polytope, GJKResult]:
|
||||||
"""Create polytope for EPA given a 3-simplex from GJK"""
|
"""Create polytope for EPA given a 3-simplex from GJK."""
|
||||||
pt.vert[0] = simplex[0]
|
pt.vert[0] = simplex[0]
|
||||||
pt.vert[1] = simplex[1]
|
pt.vert[1] = simplex[1]
|
||||||
pt.vert[2] = simplex[2]
|
pt.vert[2] = simplex[2]
|
||||||
@@ -1906,7 +1906,7 @@ def _set_edge(
|
|||||||
|
|
||||||
# recover multiple contacts from EPA polytope
|
# recover multiple contacts from EPA polytope
|
||||||
@wp.func
|
@wp.func
|
||||||
def _multicontact(
|
def multicontact(
|
||||||
# In:
|
# In:
|
||||||
polygon: wp.array(dtype=wp.vec3),
|
polygon: wp.array(dtype=wp.vec3),
|
||||||
clipped: wp.array(dtype=wp.vec3),
|
clipped: wp.array(dtype=wp.vec3),
|
||||||
@@ -1919,7 +1919,10 @@ def _multicontact(
|
|||||||
endvert: wp.array(dtype=wp.vec3),
|
endvert: wp.array(dtype=wp.vec3),
|
||||||
face1: wp.array(dtype=wp.vec3),
|
face1: wp.array(dtype=wp.vec3),
|
||||||
face2: wp.array(dtype=wp.vec3),
|
face2: wp.array(dtype=wp.vec3),
|
||||||
pt: Polytope,
|
epa_vert1: wp.array(dtype=wp.vec3),
|
||||||
|
epa_vert2: wp.array(dtype=wp.vec3),
|
||||||
|
epa_vert_index1: wp.array(dtype=int),
|
||||||
|
epa_vert_index2: wp.array(dtype=int),
|
||||||
face: wp.vec3i,
|
face: wp.vec3i,
|
||||||
x1: wp.vec3,
|
x1: wp.vec3,
|
||||||
x2: wp.vec3,
|
x2: wp.vec3,
|
||||||
@@ -1953,8 +1956,8 @@ def _multicontact(
|
|||||||
polymap = geom2.mesh_polymap
|
polymap = geom2.mesh_polymap
|
||||||
|
|
||||||
# get dimensions of features of geoms 1 and 2
|
# get dimensions of features of geoms 1 and 2
|
||||||
nface1, feature_index1, feature_vertex1 = _feature_dim(face, pt.vert_index1, pt.vert1)
|
nface1, feature_index1, feature_vertex1 = _feature_dim(face, epa_vert_index1, epa_vert1)
|
||||||
nface2, feature_index2, feature_vertex2 = _feature_dim(face, pt.vert_index2, pt.vert2)
|
nface2, feature_index2, feature_vertex2 = _feature_dim(face, epa_vert_index2, epa_vert2)
|
||||||
|
|
||||||
dir = x2 - x1
|
dir = x2 - x1
|
||||||
dir_neg = -dir
|
dir_neg = -dir
|
||||||
@@ -2070,7 +2073,7 @@ def _multicontact(
|
|||||||
|
|
||||||
# recover geom1 matching edge or face
|
# recover geom1 matching edge or face
|
||||||
if is_edge_contact_geom1:
|
if is_edge_contact_geom1:
|
||||||
nface1 = _set_edge(pt.vert1, endvert, face[0], i, face1)
|
nface1 = _set_edge(epa_vert1, endvert, face[0], i, face1)
|
||||||
else:
|
else:
|
||||||
ind = wp.where(is_edge_contact_geom2, idx1[j], idx1[i])
|
ind = wp.where(is_edge_contact_geom2, idx1[j], idx1[i])
|
||||||
if geomtype1 == GeomType.BOX:
|
if geomtype1 == GeomType.BOX:
|
||||||
@@ -2091,7 +2094,7 @@ def _multicontact(
|
|||||||
|
|
||||||
# recover geom2 matching edge or face
|
# recover geom2 matching edge or face
|
||||||
if is_edge_contact_geom2:
|
if is_edge_contact_geom2:
|
||||||
nface2 = _set_edge(pt.vert2, endvert, face[0], i, face2)
|
nface2 = _set_edge(epa_vert2, endvert, face[0], i, face2)
|
||||||
else:
|
else:
|
||||||
if geomtype2 == GeomType.BOX:
|
if geomtype2 == GeomType.BOX:
|
||||||
nface2 = _box_face(geom2.rot, geom2.pos, geom2.size, idx2[j], face2)
|
nface2 = _box_face(geom2.rot, geom2.pos, geom2.size, idx2[j], face2)
|
||||||
@@ -2147,7 +2150,6 @@ def _inflate(dist: float, x1: wp.vec3, x2: wp.vec3, margin1: float, margin2: flo
|
|||||||
@wp.func
|
@wp.func
|
||||||
def ccd(
|
def ccd(
|
||||||
# In:
|
# In:
|
||||||
multiccd: bool,
|
|
||||||
tolerance: float,
|
tolerance: float,
|
||||||
cutoff: float,
|
cutoff: float,
|
||||||
ccd_iterations: int,
|
ccd_iterations: int,
|
||||||
@@ -2168,21 +2170,8 @@ def ccd(
|
|||||||
face_index: wp.array(dtype=int),
|
face_index: wp.array(dtype=int),
|
||||||
face_map: wp.array(dtype=int),
|
face_map: wp.array(dtype=int),
|
||||||
horizon: wp.array(dtype=int),
|
horizon: wp.array(dtype=int),
|
||||||
polygon: wp.array(dtype=wp.vec3),
|
) -> Tuple[float, int, wp.vec3, wp.vec3, int]:
|
||||||
clipped: wp.array(dtype=wp.vec3),
|
|
||||||
plane_normal: wp.array(dtype=wp.vec3),
|
|
||||||
plane_dist: wp.array(dtype=float),
|
|
||||||
idx1: wp.array(dtype=int),
|
|
||||||
idx2: wp.array(dtype=int),
|
|
||||||
n1: wp.array(dtype=wp.vec3),
|
|
||||||
n2: wp.array(dtype=wp.vec3),
|
|
||||||
endvert: wp.array(dtype=wp.vec3),
|
|
||||||
face1: wp.array(dtype=wp.vec3),
|
|
||||||
face2: wp.array(dtype=wp.vec3),
|
|
||||||
) -> Tuple[float, int, mat3c, mat3c]:
|
|
||||||
"""General convex collision detection via GJK/EPA."""
|
"""General convex collision detection via GJK/EPA."""
|
||||||
witness1 = mat3c()
|
|
||||||
witness2 = mat3c()
|
|
||||||
full_margin1 = 0.0
|
full_margin1 = 0.0
|
||||||
full_margin2 = 0.0
|
full_margin2 = 0.0
|
||||||
size1 = 0.0
|
size1 = 0.0
|
||||||
@@ -2211,13 +2200,9 @@ def ccd(
|
|||||||
# shallow penetration, inflate contact
|
# shallow penetration, inflate contact
|
||||||
if result.dist > tolerance:
|
if result.dist > tolerance:
|
||||||
if result.dist == FLOAT_MAX:
|
if result.dist == FLOAT_MAX:
|
||||||
witness1[0] = result.x1
|
return result.dist, 1, result.x1, result.x2, -1
|
||||||
witness2[0] = result.x2
|
|
||||||
return result.dist, 1, witness1, witness2
|
|
||||||
dist, x1, x2 = _inflate(result.dist, result.x1, result.x2, full_margin1, full_margin2)
|
dist, x1, x2 = _inflate(result.dist, result.x1, result.x2, full_margin1, full_margin2)
|
||||||
witness1[0] = x1
|
return dist, 1, x1, x2, -1
|
||||||
witness2[0] = x2
|
|
||||||
return dist, 1, witness1, witness2
|
|
||||||
|
|
||||||
# deep penetration, reset initial conditions and rerun GJK + EPA
|
# deep penetration, reset initial conditions and rerun GJK + EPA
|
||||||
geom1.margin = full_margin1 - size1
|
geom1.margin = full_margin1 - size1
|
||||||
@@ -2230,9 +2215,7 @@ def ccd(
|
|||||||
|
|
||||||
# no penetration depth to recover
|
# no penetration depth to recover
|
||||||
if result.dist > tolerance or result.dim < 2:
|
if result.dist > tolerance or result.dim < 2:
|
||||||
witness1[0] = result.x1
|
return result.dist, 1, result.x1, result.x2, -1
|
||||||
witness2[0] = result.x2
|
|
||||||
return result.dist, 1, witness1, witness2
|
|
||||||
|
|
||||||
pt = Polytope()
|
pt = Polytope()
|
||||||
pt.nface = 0
|
pt.nface = 0
|
||||||
@@ -2312,47 +2295,9 @@ def ccd(
|
|||||||
|
|
||||||
# origin on boundary (objects are not considered penetrating)
|
# origin on boundary (objects are not considered penetrating)
|
||||||
if pt.status:
|
if pt.status:
|
||||||
witness1[0] = result.x1
|
return result.dist, 1, result.x1, result.x2, -1
|
||||||
witness2[0] = result.x2
|
|
||||||
return result.dist, 1, witness1, witness2
|
|
||||||
|
|
||||||
dist, x1, x2, idx = _epa(tolerance, ccd_iterations, pt, geom1, geom2, geomtype1, geomtype2, is_discrete)
|
dist, x1, x2, idx = _epa(tolerance, ccd_iterations, pt, geom1, geom2, geomtype1, geomtype2, is_discrete)
|
||||||
if idx == -1:
|
if idx == -1:
|
||||||
return FLOAT_MAX, 0, witness1, witness2
|
return FLOAT_MAX, 0, wp.vec3(), wp.vec3(), -1
|
||||||
|
return dist, 1, x1, x2, idx
|
||||||
# multiccd is always on for box-box collisions
|
|
||||||
if geomtype1 == GeomType.BOX and geomtype2 == GeomType.BOX:
|
|
||||||
multiccd = True
|
|
||||||
|
|
||||||
if (
|
|
||||||
multiccd
|
|
||||||
and (geom1.margin == 0.0 and geom2.margin == 0.0)
|
|
||||||
and (geomtype1 == GeomType.BOX or (geomtype1 == GeomType.MESH and geom1.mesh_polyadr > -1))
|
|
||||||
and (geomtype2 == GeomType.BOX or (geomtype2 == GeomType.MESH and geom2.mesh_polyadr > -1))
|
|
||||||
):
|
|
||||||
num, w1, w2 = _multicontact(
|
|
||||||
polygon,
|
|
||||||
clipped,
|
|
||||||
plane_normal,
|
|
||||||
plane_dist,
|
|
||||||
idx1,
|
|
||||||
idx2,
|
|
||||||
n1,
|
|
||||||
n2,
|
|
||||||
endvert,
|
|
||||||
face1,
|
|
||||||
face2,
|
|
||||||
pt,
|
|
||||||
pt.face[idx],
|
|
||||||
x1,
|
|
||||||
x2,
|
|
||||||
geom1,
|
|
||||||
geom2,
|
|
||||||
geomtype1,
|
|
||||||
geomtype2,
|
|
||||||
)
|
|
||||||
if num > 0:
|
|
||||||
return dist, num, w1, w2
|
|
||||||
witness1[0] = x1
|
|
||||||
witness2[0] = x2
|
|
||||||
return dist, 1, witness1, witness2
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAXVAL
|
|||||||
def hfield_filter(
|
def hfield_filter(
|
||||||
# Model:
|
# Model:
|
||||||
geom_dataid: wp.array(dtype=int),
|
geom_dataid: wp.array(dtype=int),
|
||||||
geom_aabb: wp.array2d(dtype=wp.vec3),
|
geom_aabb: wp.array3d(dtype=wp.vec3),
|
||||||
geom_rbound: wp.array2d(dtype=float),
|
geom_rbound: wp.array2d(dtype=float),
|
||||||
geom_margin: wp.array2d(dtype=float),
|
geom_margin: wp.array2d(dtype=float),
|
||||||
hfield_size: wp.array(dtype=wp.vec4),
|
hfield_size: wp.array(dtype=wp.vec4),
|
||||||
@@ -43,17 +43,20 @@ def hfield_filter(
|
|||||||
# height field info
|
# height field info
|
||||||
hfdataid = geom_dataid[g1]
|
hfdataid = geom_dataid[g1]
|
||||||
size1 = hfield_size[hfdataid]
|
size1 = hfield_size[hfdataid]
|
||||||
|
|
||||||
|
# geom info
|
||||||
|
rbound_id = worldid % geom_rbound.shape[0]
|
||||||
|
margin_id = worldid % geom_margin.shape[0]
|
||||||
|
|
||||||
pos1 = geom_xpos_in[worldid, g1]
|
pos1 = geom_xpos_in[worldid, g1]
|
||||||
mat1 = geom_xmat_in[worldid, g1]
|
mat1 = geom_xmat_in[worldid, g1]
|
||||||
mat1T = wp.transpose(mat1)
|
mat1T = wp.transpose(mat1)
|
||||||
|
|
||||||
# geom info
|
|
||||||
pos2 = geom_xpos_in[worldid, g2]
|
pos2 = geom_xpos_in[worldid, g2]
|
||||||
pos = mat1T @ (pos2 - pos1)
|
pos = mat1T @ (pos2 - pos1)
|
||||||
r2 = geom_rbound[worldid, g2]
|
r2 = geom_rbound[rbound_id, g2]
|
||||||
|
|
||||||
# TODO(team): margin?
|
# TODO(team): margin?
|
||||||
margin = wp.max(geom_margin[worldid, g1], geom_margin[worldid, g2])
|
margin = wp.max(geom_margin[margin_id, g1], geom_margin[margin_id, g2])
|
||||||
|
|
||||||
# box-sphere test: horizontal plane
|
# box-sphere test: horizontal plane
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
@@ -78,8 +81,9 @@ def hfield_filter(
|
|||||||
ymin = MJ_MAXVAL
|
ymin = MJ_MAXVAL
|
||||||
zmin = MJ_MAXVAL
|
zmin = MJ_MAXVAL
|
||||||
|
|
||||||
center2 = geom_aabb[g2, 0]
|
aabb_id = worldid % geom_aabb.shape[0]
|
||||||
size2 = geom_aabb[g2, 1]
|
center2 = geom_aabb[aabb_id, g2, 0]
|
||||||
|
size2 = geom_aabb[aabb_id, g2, 1]
|
||||||
|
|
||||||
pos += mat1T @ center2
|
pos += mat1T @ center2
|
||||||
|
|
||||||
|
|||||||
+530
-427
File diff suppressed because it is too large
Load Diff
+107
-124
@@ -55,7 +55,6 @@ def closest_segment_point_and_dist(a: wp.vec3, b: wp.vec3, pt: wp.vec3) -> Tuple
|
|||||||
@wp.func
|
@wp.func
|
||||||
def closest_segment_to_segment_points(a0: wp.vec3, a1: wp.vec3, b0: wp.vec3, b1: wp.vec3) -> Tuple[wp.vec3, wp.vec3]:
|
def closest_segment_to_segment_points(a0: wp.vec3, a1: wp.vec3, b0: wp.vec3, b1: wp.vec3) -> Tuple[wp.vec3, wp.vec3]:
|
||||||
"""Returns closest points between two line segments."""
|
"""Returns closest points between two line segments."""
|
||||||
|
|
||||||
dir_a, len_a = normalize_with_norm(a1 - a0)
|
dir_a, len_a = normalize_with_norm(a1 - a0)
|
||||||
dir_b, len_b = normalize_with_norm(b1 - b0)
|
dir_b, len_b = normalize_with_norm(b1 - b0)
|
||||||
|
|
||||||
@@ -122,16 +121,15 @@ def sphere_sphere(
|
|||||||
"""Sphere-sphere collision calculation.
|
"""Sphere-sphere collision calculation.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
pos1: Center position of the first sphere
|
pos1: Center position of the first sphere.
|
||||||
radius1: Radius of the first sphere
|
radius1: Radius of the first sphere.
|
||||||
pos2: Center position of the second sphere
|
pos2: Center position of the second sphere.
|
||||||
radius2: Radius of the second sphere
|
radius2: Radius of the second sphere.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple containing:
|
- Distance between sphere surfaces (negative if overlapping).
|
||||||
dist: Distance between sphere surfaces (negative if overlapping)
|
- Contact position.
|
||||||
pos: Contact position
|
- Contact normal vector.
|
||||||
n: Contact normal vector
|
|
||||||
"""
|
"""
|
||||||
dir = pos2 - pos1
|
dir = pos2 - pos1
|
||||||
dist = wp.length(dir)
|
dist = wp.length(dir)
|
||||||
@@ -157,20 +155,18 @@ def sphere_capsule(
|
|||||||
"""Core contact geometry calculation for sphere-capsule collision.
|
"""Core contact geometry calculation for sphere-capsule collision.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
sphere_pos: Center position of the sphere
|
sphere_pos: Center position of the sphere.
|
||||||
sphere_radius: Radius of the sphere
|
sphere_radius: Radius of the sphere.
|
||||||
capsule_pos: Center position of the capsule
|
capsule_pos: Center position of the capsule.
|
||||||
capsule_axis: Axis direction of the capsule
|
capsule_axis: Axis direction of the capsule.
|
||||||
capsule_radius: Radius of the capsule
|
capsule_radius: Radius of the capsule.
|
||||||
capsule_half_length: Half length of the capsule
|
capsule_half_length: Half length of the capsule.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple containing:
|
- Vector of contact distances.
|
||||||
contact_dist: Vector of contact distances
|
- Matrix of contact positions (one per row).
|
||||||
contact_pos: Matrix of contact positions (one per row)
|
- Matrix of contact normal vectors (one per row).
|
||||||
contact_normals: Matrix of contact normal vectors (one per row)
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Calculate capsule segment
|
# Calculate capsule segment
|
||||||
segment = capsule_axis * capsule_half_length
|
segment = capsule_axis * capsule_half_length
|
||||||
|
|
||||||
@@ -196,22 +192,20 @@ def capsule_capsule(
|
|||||||
"""Core contact geometry calculation for capsule-capsule collision.
|
"""Core contact geometry calculation for capsule-capsule collision.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
cap1_pos: Center position of the first capsule
|
cap1_pos: Center position of the first capsule.
|
||||||
cap1_axis: Axis direction of the first capsule
|
cap1_axis: Axis direction of the first capsule.
|
||||||
cap1_radius: Radius of the first capsule
|
cap1_radius: Radius of the first capsule.
|
||||||
cap1_half_length: Half length of the first capsule
|
cap1_half_length: Half length of the first capsule.
|
||||||
cap2_pos: Center position of the second capsule
|
cap2_pos: Center position of the second capsule.
|
||||||
cap2_axis: Axis direction of the second capsule
|
cap2_axis: Axis direction of the second capsule.
|
||||||
cap2_radius: Radius of the second capsule
|
cap2_radius: Radius of the second capsule.
|
||||||
cap2_half_length: Half length of the second capsule
|
cap2_half_length: Half length of the second capsule.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple containing:
|
- Vector of contact distances.
|
||||||
contact_dist: Vector of contact distances
|
- Matrix of contact positions (one per row).
|
||||||
contact_pos: Matrix of contact positions (one per row)
|
- Matrix of contact normal vectors (one per row).
|
||||||
contact_normals: Matrix of contact normal vectors (one per row)
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# TODO(team): parallel axes case
|
# TODO(team): parallel axes case
|
||||||
|
|
||||||
# Calculate capsule segments
|
# Calculate capsule segments
|
||||||
@@ -243,20 +237,18 @@ def plane_capsule(
|
|||||||
"""Core contact geometry calculation for plane-capsule collision.
|
"""Core contact geometry calculation for plane-capsule collision.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
plane_normal: Normal vector of the plane
|
plane_normal: Normal vector of the plane.
|
||||||
plane_pos: Position point on the plane
|
plane_pos: Position point on the plane.
|
||||||
capsule_pos: Center position of the capsule
|
capsule_pos: Center position of the capsule.
|
||||||
capsule_axis: Axis direction of the capsule
|
capsule_axis: Axis direction of the capsule.
|
||||||
capsule_radius: Radius of the capsule
|
capsule_radius: Radius of the capsule.
|
||||||
capsule_half_length: Half length of the capsule
|
capsule_half_length: Half length of the capsule.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple containing:
|
- Vector of contact distances.
|
||||||
contact_dist: Vector of contact distances
|
- Matrix of contact positions (one per row).
|
||||||
contact_pos: Matrix of contact positions (one per row)
|
- Contact frame for both contacts.
|
||||||
contact_frame: Contact frame for both contacts
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
n = plane_normal
|
n = plane_normal
|
||||||
axis = capsule_axis
|
axis = capsule_axis
|
||||||
|
|
||||||
@@ -297,17 +289,16 @@ def plane_ellipsoid(
|
|||||||
"""Core contact geometry calculation for plane-ellipsoid collision.
|
"""Core contact geometry calculation for plane-ellipsoid collision.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
plane_normal: Normal vector of the plane
|
plane_normal: Normal vector of the plane.
|
||||||
plane_pos: Position point on the plane
|
plane_pos: Position point on the plane.
|
||||||
ellipsoid_pos: Center position of the ellipsoid
|
ellipsoid_pos: Center position of the ellipsoid.
|
||||||
ellipsoid_rot: Rotation matrix of the ellipsoid
|
ellipsoid_rot: Rotation matrix of the ellipsoid.
|
||||||
ellipsoid_size: Size (radii) of the ellipsoid along each axis
|
ellipsoid_size: Size (radii) of the ellipsoid along each axis.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple containing:
|
- Vector of contact distances.
|
||||||
contact_dist: Vector of contact distances
|
- Matrix of contact positions (one per row).
|
||||||
contact_pos: Matrix of contact positions (one per row)
|
- Matrix of contact normal vectors (one per row).
|
||||||
contact_normals: Matrix of contact normal vectors (one per row)
|
|
||||||
"""
|
"""
|
||||||
sphere_support = -wp.normalize(wp.cw_mul(wp.transpose(ellipsoid_rot) @ plane_normal, ellipsoid_size))
|
sphere_support = -wp.normalize(wp.cw_mul(wp.transpose(ellipsoid_rot) @ plane_normal, ellipsoid_size))
|
||||||
pos = ellipsoid_pos + ellipsoid_rot @ wp.cw_mul(sphere_support, ellipsoid_size)
|
pos = ellipsoid_pos + ellipsoid_rot @ wp.cw_mul(sphere_support, ellipsoid_size)
|
||||||
@@ -329,19 +320,17 @@ def plane_box(
|
|||||||
"""Core contact geometry calculation for plane-box collision.
|
"""Core contact geometry calculation for plane-box collision.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
plane_normal: Normal vector of the plane
|
plane_normal: Normal vector of the plane.
|
||||||
plane_pos: Position point on the plane
|
plane_pos: Position point on the plane.
|
||||||
box_pos: Center position of the box
|
box_pos: Center position of the box.
|
||||||
box_rot: Rotation matrix of the box
|
box_rot: Rotation matrix of the box.
|
||||||
box_size: Half-extents of the box along each axis
|
box_size: Half-extents of the box along each axis.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple containing:
|
- Vector of contact distances (wp.inf for unpopulated contacts).
|
||||||
contact_dist: Vector of contact distances (wp.inf for unpopulated contacts)
|
- Matrix of contact positions (one per row).
|
||||||
contact_pos: Matrix of contact positions (one per row)
|
- Contact normal vector.
|
||||||
contact_normal: contact normal vector
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
corner = wp.vec3()
|
corner = wp.vec3()
|
||||||
center_dist = wp.dot(box_pos - plane_pos, plane_normal)
|
center_dist = wp.dot(box_pos - plane_pos, plane_normal)
|
||||||
|
|
||||||
@@ -389,18 +378,17 @@ def sphere_cylinder(
|
|||||||
"""Core contact geometry calculation for sphere-cylinder collision.
|
"""Core contact geometry calculation for sphere-cylinder collision.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
sphere_pos: Center position of the sphere
|
sphere_pos: Center position of the sphere.
|
||||||
sphere_radius: Radius of the sphere
|
sphere_radius: Radius of the sphere.
|
||||||
cylinder_pos: Center position of the cylinder
|
cylinder_pos: Center position of the cylinder.
|
||||||
cylinder_axis: Axis direction of the cylinder
|
cylinder_axis: Axis direction of the cylinder.
|
||||||
cylinder_radius: Radius of the cylinder
|
cylinder_radius: Radius of the cylinder.
|
||||||
cylinder_half_height: Half height of the cylinder
|
cylinder_half_height: Half height of the cylinder.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple containing:
|
- Vector of contact distances.
|
||||||
contact_dist: Vector of contact distances
|
- Matrix of contact positions (one per row).
|
||||||
contact_pos: Matrix of contact positions (one per row)
|
- Matrix of contact normal vectors (one per row).
|
||||||
contact_normals: Matrix of contact normal vectors (one per row)
|
|
||||||
"""
|
"""
|
||||||
vec = sphere_pos - cylinder_pos
|
vec = sphere_pos - cylinder_pos
|
||||||
x = wp.dot(vec, cylinder_axis)
|
x = wp.dot(vec, cylinder_axis)
|
||||||
@@ -462,20 +450,18 @@ def plane_cylinder(
|
|||||||
"""Core contact geometry calculation for plane-cylinder collision.
|
"""Core contact geometry calculation for plane-cylinder collision.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
plane_normal: Normal vector of the plane
|
plane_normal: Normal vector of the plane.
|
||||||
plane_pos: Position point on the plane
|
plane_pos: Position point on the plane.
|
||||||
cylinder_center: Center position of the cylinder
|
cylinder_center: Center position of the cylinder.
|
||||||
cylinder_axis: Axis direction of the cylinder
|
cylinder_axis: Axis direction of the cylinder.
|
||||||
cylinder_radius: Radius of the cylinder
|
cylinder_radius: Radius of the cylinder.
|
||||||
cylinder_half_height: Half height of the cylinder
|
cylinder_half_height: Half height of the cylinder.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple containing:
|
- Vector of contact distances.
|
||||||
contact_dist: Vector of contact distances
|
- Matrix of contact positions (one per row).
|
||||||
contact_pos: Matrix of contact positions (one per row)
|
- Matrix of contact normal vectors (one per row).
|
||||||
contact_normals: Matrix of contact normal vectors (one per row)
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Initialize output matrices
|
# Initialize output matrices
|
||||||
contact_dist = wp.vec4(wp.inf)
|
contact_dist = wp.vec4(wp.inf)
|
||||||
contact_pos = mat43f()
|
contact_pos = mat43f()
|
||||||
@@ -589,24 +575,25 @@ def box_box(
|
|||||||
box2_pos: wp.vec3,
|
box2_pos: wp.vec3,
|
||||||
box2_rot: wp.mat33,
|
box2_rot: wp.mat33,
|
||||||
box2_size: wp.vec3,
|
box2_size: wp.vec3,
|
||||||
|
margin: float = 0.0, # kernel_analyzer: off
|
||||||
) -> Tuple[vec8f, mat83f, mat83f]:
|
) -> Tuple[vec8f, mat83f, mat83f]:
|
||||||
"""Core contact geometry calculation for box-box collision.
|
"""Core contact geometry calculation for box-box collision.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
box1_pos: Center position of the first box
|
box1_pos: Center position of the first box.
|
||||||
box1_rot: Rotation matrix of the first box
|
box1_rot: Rotation matrix of the first box.
|
||||||
box1_size: Half-extents of the first box along each axis
|
box1_size: Half-extents of the first box along each axis.
|
||||||
box2_pos: Center position of the second box
|
box2_pos: Center position of the second box.
|
||||||
box2_rot: Rotation matrix of the second box
|
box2_rot: Rotation matrix of the second box.
|
||||||
box2_size: Half-extents of the second box along each axis
|
box2_size: Half-extents of the second box along each axis.
|
||||||
|
margin: Distance threshold for early contact generation (default: 0.0).
|
||||||
|
When positive, contacts are generated before boxes overlap.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple containing:
|
- Vector of contact distances (wp.inf for unpopulated contacts).
|
||||||
contact_dist: Vector of contact distances (wp.inf for unpopulated contacts)
|
- Matrix of contact positions (one per row).
|
||||||
contact_pos: Matrix of contact positions (one per row)
|
- Matrix of contact normal vectors (one per row).
|
||||||
contact_normals: Matrix of contact normal vectors (one per row)
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Initialize output matrices
|
# Initialize output matrices
|
||||||
contact_dist = vec8f()
|
contact_dist = vec8f()
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
@@ -630,7 +617,7 @@ def box_box(
|
|||||||
|
|
||||||
# Compute axis of maximum separation
|
# Compute axis of maximum separation
|
||||||
s_sum_3 = 3.0 * (box1_size + box2_size)
|
s_sum_3 = 3.0 * (box1_size + box2_size)
|
||||||
separation = wp.float32(s_sum_3[0] + s_sum_3[1] + s_sum_3[2])
|
separation = wp.float32(margin + s_sum_3[0] + s_sum_3[1] + s_sum_3[2])
|
||||||
axis_code = wp.int32(-1)
|
axis_code = wp.int32(-1)
|
||||||
|
|
||||||
# First test: consider boxes' face normals
|
# First test: consider boxes' face normals
|
||||||
@@ -639,7 +626,7 @@ def box_box(
|
|||||||
|
|
||||||
c2 = -wp.abs(pos12[i]) + box2_size[i] + plen1[i]
|
c2 = -wp.abs(pos12[i]) + box2_size[i] + plen1[i]
|
||||||
|
|
||||||
if c1 < 0.0 or c2 < 0.0:
|
if c1 < -margin or c2 < -margin:
|
||||||
return contact_dist, contact_pos, contact_normals
|
return contact_dist, contact_pos, contact_normals
|
||||||
|
|
||||||
if c1 < separation:
|
if c1 < separation:
|
||||||
@@ -684,7 +671,7 @@ def box_box(
|
|||||||
c3 -= wp.abs(box_dist)
|
c3 -= wp.abs(box_dist)
|
||||||
|
|
||||||
# Early exit: no collision if separated along this axis
|
# Early exit: no collision if separated along this axis
|
||||||
if c3 < 0.0:
|
if c3 < -margin:
|
||||||
return contact_dist, contact_pos, contact_normals
|
return contact_dist, contact_pos, contact_normals
|
||||||
|
|
||||||
# Track minimum separation and which edge-edge pair it occurs on
|
# Track minimum separation and which edge-edge pair it occurs on
|
||||||
@@ -811,7 +798,7 @@ def box_box(
|
|||||||
n = wp.int32(0)
|
n = wp.int32(0)
|
||||||
|
|
||||||
for i in range(m):
|
for i in range(m):
|
||||||
if points[i][2] > 0.0:
|
if points[i][2] > margin:
|
||||||
continue
|
continue
|
||||||
if i != n:
|
if i != n:
|
||||||
points[n] = points[i]
|
points[n] = points[i]
|
||||||
@@ -925,7 +912,7 @@ def box_box(
|
|||||||
c2 = lc + ld * c1
|
c2 = lc + ld * c1
|
||||||
if wp.abs(c2) > s[1 - q]:
|
if wp.abs(c2) > s[1 - q]:
|
||||||
continue
|
continue
|
||||||
if (lua[2] + lub[2] * c1) * innorm > 0.0:
|
if (lua[2] + lub[2] * c1) * innorm > margin:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
points[n] = lua * 0.5 + c1 * lub * 0.5
|
points[n] = lua * 0.5 + c1 * lub * 0.5
|
||||||
@@ -969,7 +956,7 @@ def box_box(
|
|||||||
|
|
||||||
vtmp2 = points[n] - vtmp
|
vtmp2 = points[n] - vtmp
|
||||||
tc1 = wp.length_sq(vtmp2)
|
tc1 = wp.length_sq(vtmp2)
|
||||||
if vtmp[2] > 0 and tc1 > 0.0:
|
if vtmp[2] > 0 and tc1 > margin * margin:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
points[n] = 0.5 * (points[n] + vtmp)
|
points[n] = 0.5 * (points[n] + vtmp)
|
||||||
@@ -1000,7 +987,7 @@ def box_box(
|
|||||||
|
|
||||||
c1 += pu[i, 2] * innorm * pu[i, 2] * innorm
|
c1 += pu[i, 2] * innorm * pu[i, 2] * innorm
|
||||||
|
|
||||||
if pu[i, 2] > 0 and c1 > 0.0:
|
if pu[i, 2] > 0 and c1 > margin * margin:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
tmp_p = wp.vec3(pu[i, 0], pu[i, 1], 0.0)
|
tmp_p = wp.vec3(pu[i, 0], pu[i, 1], 0.0)
|
||||||
@@ -1047,19 +1034,17 @@ def sphere_box(
|
|||||||
"""Core contact geometry calculation for sphere-box collision.
|
"""Core contact geometry calculation for sphere-box collision.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
sphere_pos: Center position of the sphere
|
sphere_pos: Center position of the sphere.
|
||||||
sphere_radius: Radius of the sphere
|
sphere_radius: Radius of the sphere.
|
||||||
box_pos: Center position of the box
|
box_pos: Center position of the box.
|
||||||
box_rot: Rotation matrix of the box
|
box_rot: Rotation matrix of the box.
|
||||||
box_size: Half-extents of the box along each axis
|
box_size: Half-extents of the box along each axis.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple containing:
|
- Vector of contact distances.
|
||||||
contact_dist: Vector of contact distances
|
- Contact positions.
|
||||||
contact_pos: contact positions
|
- Contact normal vectors.
|
||||||
contact_normal: contact normal vectors
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
center = wp.transpose(box_rot) @ (sphere_pos - box_pos)
|
center = wp.transpose(box_rot) @ (sphere_pos - box_pos)
|
||||||
|
|
||||||
clamped = wp.max(-box_size, wp.min(box_size, center))
|
clamped = wp.max(-box_size, wp.min(box_size, center))
|
||||||
@@ -1106,21 +1091,19 @@ def capsule_box(
|
|||||||
"""Core contact geometry calculation for capsule-box collision.
|
"""Core contact geometry calculation for capsule-box collision.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
capsule_pos: Center position of the capsule
|
capsule_pos: Center position of the capsule.
|
||||||
capsule_axis: Axis direction of the capsule
|
capsule_axis: Axis direction of the capsule.
|
||||||
capsule_radius: Radius of the capsule
|
capsule_radius: Radius of the capsule.
|
||||||
capsule_half_length: Half length of the capsule
|
capsule_half_length: Half length of the capsule.
|
||||||
box_pos: Center position of the box
|
box_pos: Center position of the box.
|
||||||
box_rot: Rotation matrix of the box
|
box_rot: Rotation matrix of the box.
|
||||||
box_size: Half-extents of the box along each axis
|
box_size: Half-extents of the box along each axis.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple containing:
|
- Vector of contact distances (wp.inf for unpopulated contacts).
|
||||||
contact_dist: Vector of contact distances (wp.inf for unpopulated contacts)
|
- Matrix of contact positions (one per row).
|
||||||
contact_pos: Matrix of contact positions (one per row)
|
- Matrix of contact normal vectors (one per row).
|
||||||
contact_normals: Matrix of contact normal vectors (one per row)
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Based on the mjc implementation
|
# Based on the mjc implementation
|
||||||
boxmatT = wp.transpose(box_rot)
|
boxmatT = wp.transpose(box_rot)
|
||||||
pos = boxmatT @ (capsule_pos - box_pos)
|
pos = boxmatT @ (capsule_pos - box_pos)
|
||||||
|
|||||||
+56
-47
@@ -17,7 +17,6 @@ from typing import Tuple
|
|||||||
|
|
||||||
import warp as wp
|
import warp as wp
|
||||||
|
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src import math
|
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import contact_params
|
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
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import write_contact
|
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import write_contact
|
||||||
@@ -78,8 +77,8 @@ class MeshData:
|
|||||||
@wp.func
|
@wp.func
|
||||||
def get_sdf_params(
|
def get_sdf_params(
|
||||||
# Model:
|
# Model:
|
||||||
oct_aabb: wp.array2d(dtype=wp.vec3),
|
|
||||||
oct_child: wp.array(dtype=vec8i),
|
oct_child: wp.array(dtype=vec8i),
|
||||||
|
oct_aabb: wp.array2d(dtype=wp.vec3),
|
||||||
oct_coeff: wp.array(dtype=vec8f),
|
oct_coeff: wp.array(dtype=vec8f),
|
||||||
plugin: wp.array(dtype=int),
|
plugin: wp.array(dtype=int),
|
||||||
plugin_attr: wp.array(dtype=wp.vec3f),
|
plugin_attr: wp.array(dtype=wp.vec3f),
|
||||||
@@ -225,7 +224,7 @@ def user_sdf_grad(p: wp.vec3, attr: wp.vec3, sdf_type: int) -> wp.vec3:
|
|||||||
|
|
||||||
@wp.func
|
@wp.func
|
||||||
def find_oct(
|
def find_oct(
|
||||||
oct_aabb: wp.array2d(dtype=wp.vec3), oct_child: wp.array(dtype=vec8i), p: wp.vec3, grad: bool
|
oct_child: wp.array(dtype=vec8i), oct_aabb: wp.array2d(dtype=wp.vec3), p: wp.vec3, grad: bool
|
||||||
) -> Tuple[int, Tuple[vec8f, vec8f, vec8f]]:
|
) -> Tuple[int, Tuple[vec8f, vec8f, vec8f]]:
|
||||||
stack = int(0)
|
stack = int(0)
|
||||||
niter = int(100)
|
niter = int(100)
|
||||||
@@ -331,7 +330,7 @@ def box_project(center: wp.vec3, half_size: wp.vec3, xyz: wp.vec3) -> Tuple[floa
|
|||||||
@wp.func
|
@wp.func
|
||||||
def sample_volume_sdf(xyz: wp.vec3, volume_data: VolumeData) -> float:
|
def sample_volume_sdf(xyz: wp.vec3, volume_data: VolumeData) -> float:
|
||||||
dist0, point = box_project(volume_data.center, volume_data.half_size, xyz)
|
dist0, point = box_project(volume_data.center, volume_data.half_size, xyz)
|
||||||
node, weights = find_oct(volume_data.oct_aabb, volume_data.oct_child, point, grad=False)
|
node, weights = find_oct(volume_data.oct_child, volume_data.oct_aabb, point, grad=False)
|
||||||
return dist0 + wp.dot(weights[0], volume_data.oct_coeff[node])
|
return dist0 + wp.dot(weights[0], volume_data.oct_coeff[node])
|
||||||
|
|
||||||
|
|
||||||
@@ -348,7 +347,7 @@ def sample_volume_grad(xyz: wp.vec3, volume_data: VolumeData) -> wp.vec3:
|
|||||||
grad_y = (sample_volume_sdf(xyz + dy, volume_data) - f) / h
|
grad_y = (sample_volume_sdf(xyz + dy, volume_data) - f) / h
|
||||||
grad_z = (sample_volume_sdf(xyz + dz, volume_data) - f) / h
|
grad_z = (sample_volume_sdf(xyz + dz, volume_data) - f) / h
|
||||||
return wp.vec3(grad_x, grad_y, grad_z)
|
return wp.vec3(grad_x, grad_y, grad_z)
|
||||||
node, weights = find_oct(volume_data.oct_aabb, volume_data.oct_child, point, grad=True)
|
node, weights = find_oct(volume_data.oct_child, volume_data.oct_aabb, point, grad=True)
|
||||||
grad_x = wp.dot(weights[0], volume_data.oct_coeff[node])
|
grad_x = wp.dot(weights[0], volume_data.oct_coeff[node])
|
||||||
grad_y = wp.dot(weights[1], 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])
|
grad_z = wp.dot(weights[2], volume_data.oct_coeff[node])
|
||||||
@@ -371,8 +370,8 @@ def sdf(type: int, p: wp.vec3, attr: wp.vec3, sdf_type: int, volume_data: Volume
|
|||||||
dist = ray_mesh(
|
dist = ray_mesh(
|
||||||
mesh_data.nmeshface,
|
mesh_data.nmeshface,
|
||||||
mesh_data.mesh_vertadr,
|
mesh_data.mesh_vertadr,
|
||||||
mesh_data.mesh_vert,
|
|
||||||
mesh_data.mesh_faceadr,
|
mesh_data.mesh_faceadr,
|
||||||
|
mesh_data.mesh_vert,
|
||||||
mesh_data.mesh_face,
|
mesh_data.mesh_face,
|
||||||
mesh_data.data_id,
|
mesh_data.data_id,
|
||||||
mesh_data.pos,
|
mesh_data.pos,
|
||||||
@@ -384,8 +383,8 @@ def sdf(type: int, p: wp.vec3, attr: wp.vec3, sdf_type: int, volume_data: Volume
|
|||||||
return -ray_mesh(
|
return -ray_mesh(
|
||||||
mesh_data.nmeshface,
|
mesh_data.nmeshface,
|
||||||
mesh_data.mesh_vertadr,
|
mesh_data.mesh_vertadr,
|
||||||
mesh_data.mesh_vert,
|
|
||||||
mesh_data.mesh_faceadr,
|
mesh_data.mesh_faceadr,
|
||||||
|
mesh_data.mesh_vert,
|
||||||
mesh_data.mesh_face,
|
mesh_data.mesh_face,
|
||||||
mesh_data.data_id,
|
mesh_data.data_id,
|
||||||
mesh_data.pos,
|
mesh_data.pos,
|
||||||
@@ -420,8 +419,8 @@ def sdf_grad(type: int, p: wp.vec3, attr: wp.vec3, sdf_type: int, volume_data: V
|
|||||||
dist = ray_mesh(
|
dist = ray_mesh(
|
||||||
mesh_data.nmeshface,
|
mesh_data.nmeshface,
|
||||||
mesh_data.mesh_vertadr,
|
mesh_data.mesh_vertadr,
|
||||||
mesh_data.mesh_vert,
|
|
||||||
mesh_data.mesh_faceadr,
|
mesh_data.mesh_faceadr,
|
||||||
|
mesh_data.mesh_vert,
|
||||||
mesh_data.mesh_face,
|
mesh_data.mesh_face,
|
||||||
mesh_data.data_id,
|
mesh_data.data_id,
|
||||||
mesh_data.pos,
|
mesh_data.pos,
|
||||||
@@ -620,6 +619,9 @@ def gradient_descent(
|
|||||||
def _sdf_narrowphase(
|
def _sdf_narrowphase(
|
||||||
# Model:
|
# Model:
|
||||||
nmeshface: int,
|
nmeshface: int,
|
||||||
|
oct_child: wp.array(dtype=vec8i),
|
||||||
|
oct_aabb: wp.array2d(dtype=wp.vec3),
|
||||||
|
oct_coeff: wp.array(dtype=vec8f),
|
||||||
geom_type: wp.array(dtype=int),
|
geom_type: wp.array(dtype=int),
|
||||||
geom_condim: wp.array(dtype=int),
|
geom_condim: wp.array(dtype=int),
|
||||||
geom_dataid: wp.array(dtype=int),
|
geom_dataid: wp.array(dtype=int),
|
||||||
@@ -628,21 +630,16 @@ def _sdf_narrowphase(
|
|||||||
geom_solref: wp.array2d(dtype=wp.vec2),
|
geom_solref: wp.array2d(dtype=wp.vec2),
|
||||||
geom_solimp: wp.array2d(dtype=vec5),
|
geom_solimp: wp.array2d(dtype=vec5),
|
||||||
geom_size: wp.array2d(dtype=wp.vec3),
|
geom_size: wp.array2d(dtype=wp.vec3),
|
||||||
geom_aabb: wp.array2d(dtype=wp.vec3),
|
geom_aabb: wp.array3d(dtype=wp.vec3),
|
||||||
geom_friction: wp.array2d(dtype=wp.vec3),
|
geom_friction: wp.array2d(dtype=wp.vec3),
|
||||||
geom_margin: wp.array2d(dtype=float),
|
geom_margin: wp.array2d(dtype=float),
|
||||||
geom_gap: wp.array2d(dtype=float),
|
geom_gap: wp.array2d(dtype=float),
|
||||||
hfield_adr: wp.array(dtype=int),
|
|
||||||
hfield_nrow: wp.array(dtype=int),
|
|
||||||
hfield_ncol: wp.array(dtype=int),
|
|
||||||
hfield_size: wp.array(dtype=wp.vec4),
|
|
||||||
hfield_data: wp.array(dtype=float),
|
|
||||||
mesh_vertadr: wp.array(dtype=int),
|
mesh_vertadr: wp.array(dtype=int),
|
||||||
mesh_vertnum: wp.array(dtype=int),
|
mesh_vertnum: wp.array(dtype=int),
|
||||||
mesh_vert: wp.array(dtype=wp.vec3),
|
|
||||||
mesh_faceadr: wp.array(dtype=int),
|
mesh_faceadr: wp.array(dtype=int),
|
||||||
mesh_face: wp.array(dtype=wp.vec3i),
|
|
||||||
mesh_graphadr: 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_graph: wp.array(dtype=int),
|
||||||
mesh_polynum: wp.array(dtype=int),
|
mesh_polynum: wp.array(dtype=int),
|
||||||
mesh_polyadr: wp.array(dtype=int),
|
mesh_polyadr: wp.array(dtype=int),
|
||||||
@@ -653,9 +650,11 @@ def _sdf_narrowphase(
|
|||||||
mesh_polymapadr: wp.array(dtype=int),
|
mesh_polymapadr: wp.array(dtype=int),
|
||||||
mesh_polymapnum: wp.array(dtype=int),
|
mesh_polymapnum: wp.array(dtype=int),
|
||||||
mesh_polymap: wp.array(dtype=int),
|
mesh_polymap: wp.array(dtype=int),
|
||||||
oct_aabb: wp.array2d(dtype=wp.vec3),
|
hfield_size: wp.array(dtype=wp.vec4),
|
||||||
oct_child: wp.array(dtype=vec8i),
|
hfield_nrow: wp.array(dtype=int),
|
||||||
oct_coeff: wp.array(dtype=vec8f),
|
hfield_ncol: wp.array(dtype=int),
|
||||||
|
hfield_adr: wp.array(dtype=int),
|
||||||
|
hfield_data: wp.array(dtype=float),
|
||||||
pair_dim: wp.array(dtype=int),
|
pair_dim: wp.array(dtype=int),
|
||||||
pair_solref: wp.array2d(dtype=wp.vec2),
|
pair_solref: wp.array2d(dtype=wp.vec2),
|
||||||
pair_solreffriction: wp.array2d(dtype=wp.vec2),
|
pair_solreffriction: wp.array2d(dtype=wp.vec2),
|
||||||
@@ -663,23 +662,21 @@ def _sdf_narrowphase(
|
|||||||
pair_margin: wp.array2d(dtype=float),
|
pair_margin: wp.array2d(dtype=float),
|
||||||
pair_gap: wp.array2d(dtype=float),
|
pair_gap: wp.array2d(dtype=float),
|
||||||
pair_friction: wp.array2d(dtype=vec5),
|
pair_friction: wp.array2d(dtype=vec5),
|
||||||
# In:
|
|
||||||
plugin: wp.array(dtype=int),
|
plugin: wp.array(dtype=int),
|
||||||
plugin_attr: wp.array(dtype=wp.vec3f),
|
plugin_attr: wp.array(dtype=wp.vec3f),
|
||||||
geom_plugin_index: wp.array(dtype=int),
|
geom_plugin_index: wp.array(dtype=int),
|
||||||
# Data in:
|
# Data in:
|
||||||
naconmax_in: int,
|
|
||||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||||
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
||||||
|
naconmax_in: int,
|
||||||
collision_pair_in: wp.array(dtype=wp.vec2i),
|
collision_pair_in: wp.array(dtype=wp.vec2i),
|
||||||
collision_pairid_in: wp.array(dtype=int),
|
collision_pairid_in: wp.array(dtype=wp.vec2i),
|
||||||
collision_worldid_in: wp.array(dtype=int),
|
collision_worldid_in: wp.array(dtype=int),
|
||||||
ncollision_in: wp.array(dtype=int),
|
ncollision_in: wp.array(dtype=int),
|
||||||
# In:
|
# In:
|
||||||
sdf_initpoints: int,
|
sdf_initpoints: int,
|
||||||
sdf_iterations: int,
|
sdf_iterations: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
nacon_out: wp.array(dtype=int),
|
|
||||||
contact_dist_out: wp.array(dtype=float),
|
contact_dist_out: wp.array(dtype=float),
|
||||||
contact_pos_out: wp.array(dtype=wp.vec3),
|
contact_pos_out: wp.array(dtype=wp.vec3),
|
||||||
contact_frame_out: wp.array(dtype=wp.mat33),
|
contact_frame_out: wp.array(dtype=wp.mat33),
|
||||||
@@ -691,6 +688,9 @@ def _sdf_narrowphase(
|
|||||||
contact_dim_out: wp.array(dtype=int),
|
contact_dim_out: wp.array(dtype=int),
|
||||||
contact_geom_out: wp.array(dtype=wp.vec2i),
|
contact_geom_out: wp.array(dtype=wp.vec2i),
|
||||||
contact_worldid_out: wp.array(dtype=int),
|
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()
|
i, contact_tid = wp.tid()
|
||||||
if i >= sdf_initpoints:
|
if i >= sdf_initpoints:
|
||||||
@@ -724,18 +724,21 @@ def _sdf_narrowphase(
|
|||||||
contact_tid,
|
contact_tid,
|
||||||
worldid,
|
worldid,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
geom_size_id = worldid % geom_size.shape[0]
|
||||||
|
aabb_id = worldid % geom_aabb.shape[0]
|
||||||
|
|
||||||
g1 = geoms[0]
|
g1 = geoms[0]
|
||||||
type1 = geom_type[g1]
|
type1 = geom_type[g1]
|
||||||
|
|
||||||
geom1_dataid = geom_dataid[g1]
|
geom1_dataid = geom_dataid[g1]
|
||||||
geom1 = geom(
|
geom1 = geom(
|
||||||
type1,
|
type1,
|
||||||
geom1_dataid,
|
geom1_dataid,
|
||||||
geom_size[worldid, g1],
|
geom_size[geom_size_id, g1],
|
||||||
mesh_vertadr,
|
mesh_vertadr,
|
||||||
mesh_vertnum,
|
mesh_vertnum,
|
||||||
mesh_vert,
|
|
||||||
mesh_graphadr,
|
mesh_graphadr,
|
||||||
|
mesh_vert,
|
||||||
mesh_graph,
|
mesh_graph,
|
||||||
mesh_polynum,
|
mesh_polynum,
|
||||||
mesh_polyadr,
|
mesh_polyadr,
|
||||||
@@ -754,11 +757,11 @@ def _sdf_narrowphase(
|
|||||||
geom2 = geom(
|
geom2 = geom(
|
||||||
type2,
|
type2,
|
||||||
geom2_dataid,
|
geom2_dataid,
|
||||||
geom_size[worldid, g2],
|
geom_size[geom_size_id, g2],
|
||||||
mesh_vertadr,
|
mesh_vertadr,
|
||||||
mesh_vertnum,
|
mesh_vertnum,
|
||||||
mesh_vert,
|
|
||||||
mesh_graphadr,
|
mesh_graphadr,
|
||||||
|
mesh_vert,
|
||||||
mesh_graph,
|
mesh_graph,
|
||||||
mesh_polynum,
|
mesh_polynum,
|
||||||
mesh_polyadr,
|
mesh_polyadr,
|
||||||
@@ -777,12 +780,12 @@ def _sdf_narrowphase(
|
|||||||
|
|
||||||
g1_to_g2_rot = wp.transpose(geom1.rot) * geom2.rot
|
g1_to_g2_rot = wp.transpose(geom1.rot) * geom2.rot
|
||||||
g1_to_g2_pos = wp.transpose(geom1.rot) * (geom2.pos - geom1.pos)
|
g1_to_g2_pos = wp.transpose(geom1.rot) * (geom2.pos - geom1.pos)
|
||||||
aabb_pos = geom_aabb[g1, 0]
|
aabb_pos = geom_aabb[aabb_id, g1, 0]
|
||||||
aabb_size = geom_aabb[g1, 1]
|
aabb_size = geom_aabb[aabb_id, g1, 1]
|
||||||
identity = wp.identity(3, dtype=float)
|
identity = wp.identity(3, dtype=float)
|
||||||
aabb1 = transform_aabb(aabb_pos, aabb_size, wp.vec3(0.0), identity)
|
aabb1 = transform_aabb(aabb_pos, aabb_size, wp.vec3(0.0), identity)
|
||||||
aabb_pos = geom_aabb[g2, 0]
|
aabb_pos = geom_aabb[aabb_id, g2, 0]
|
||||||
aabb_size = geom_aabb[g2, 1]
|
aabb_size = geom_aabb[aabb_id, g2, 1]
|
||||||
aabb2 = transform_aabb(aabb_pos, aabb_size, g1_to_g2_pos, g1_to_g2_rot)
|
aabb2 = transform_aabb(aabb_pos, aabb_size, g1_to_g2_pos, g1_to_g2_rot)
|
||||||
aabb_intersection = AABB()
|
aabb_intersection = AABB()
|
||||||
aabb_intersection.min = wp.max(aabb1.min, aabb2.min)
|
aabb_intersection.min = wp.max(aabb1.min, aabb2.min)
|
||||||
@@ -794,11 +797,11 @@ def _sdf_narrowphase(
|
|||||||
rot1 = geom1.rot
|
rot1 = geom1.rot
|
||||||
|
|
||||||
attr1, g1_plugin_id, volume_data1, mesh_data1 = get_sdf_params(
|
attr1, g1_plugin_id, volume_data1, mesh_data1 = get_sdf_params(
|
||||||
oct_aabb, oct_child, oct_coeff, plugin, plugin_attr, type1, geom1.size, g1_plugin, geom_dataid[g1]
|
oct_child, oct_aabb, oct_coeff, plugin, plugin_attr, type1, geom1.size, g1_plugin, geom_dataid[g1]
|
||||||
)
|
)
|
||||||
|
|
||||||
attr2, g2_plugin_id, volume_data2, mesh_data2 = get_sdf_params(
|
attr2, g2_plugin_id, volume_data2, mesh_data2 = get_sdf_params(
|
||||||
oct_aabb, oct_child, oct_coeff, plugin, plugin_attr, type2, geom2.size, g2_plugin, geom_dataid[g2]
|
oct_child, oct_aabb, oct_coeff, plugin, plugin_attr, type2, geom2.size, g2_plugin, geom_dataid[g2]
|
||||||
)
|
)
|
||||||
|
|
||||||
mesh_data1.nmeshface = nmeshface
|
mesh_data1.nmeshface = nmeshface
|
||||||
@@ -851,6 +854,7 @@ def _sdf_narrowphase(
|
|||||||
)
|
)
|
||||||
write_contact(
|
write_contact(
|
||||||
naconmax_in,
|
naconmax_in,
|
||||||
|
0,
|
||||||
dist,
|
dist,
|
||||||
pos,
|
pos,
|
||||||
make_frame(n),
|
make_frame(n),
|
||||||
@@ -862,8 +866,8 @@ def _sdf_narrowphase(
|
|||||||
solreffriction,
|
solreffriction,
|
||||||
solimp,
|
solimp,
|
||||||
geoms,
|
geoms,
|
||||||
|
collision_pairid_in[contact_tid],
|
||||||
worldid,
|
worldid,
|
||||||
nacon_out,
|
|
||||||
contact_dist_out,
|
contact_dist_out,
|
||||||
contact_pos_out,
|
contact_pos_out,
|
||||||
contact_frame_out,
|
contact_frame_out,
|
||||||
@@ -875,6 +879,9 @@ def _sdf_narrowphase(
|
|||||||
contact_dim_out,
|
contact_dim_out,
|
||||||
contact_geom_out,
|
contact_geom_out,
|
||||||
contact_worldid_out,
|
contact_worldid_out,
|
||||||
|
contact_type_out,
|
||||||
|
contact_geomcollisionid_out,
|
||||||
|
nacon_out,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -885,6 +892,9 @@ def sdf_narrowphase(m: Model, d: Data):
|
|||||||
dim=(m.opt.sdf_initpoints, d.naconmax),
|
dim=(m.opt.sdf_initpoints, d.naconmax),
|
||||||
inputs=[
|
inputs=[
|
||||||
m.nmeshface,
|
m.nmeshface,
|
||||||
|
m.oct_child,
|
||||||
|
m.oct_aabb,
|
||||||
|
m.oct_coeff,
|
||||||
m.geom_type,
|
m.geom_type,
|
||||||
m.geom_condim,
|
m.geom_condim,
|
||||||
m.geom_dataid,
|
m.geom_dataid,
|
||||||
@@ -897,17 +907,12 @@ def sdf_narrowphase(m: Model, d: Data):
|
|||||||
m.geom_friction,
|
m.geom_friction,
|
||||||
m.geom_margin,
|
m.geom_margin,
|
||||||
m.geom_gap,
|
m.geom_gap,
|
||||||
m.hfield_adr,
|
|
||||||
m.hfield_nrow,
|
|
||||||
m.hfield_ncol,
|
|
||||||
m.hfield_size,
|
|
||||||
m.hfield_data,
|
|
||||||
m.mesh_vertadr,
|
m.mesh_vertadr,
|
||||||
m.mesh_vertnum,
|
m.mesh_vertnum,
|
||||||
m.mesh_vert,
|
|
||||||
m.mesh_faceadr,
|
m.mesh_faceadr,
|
||||||
m.mesh_face,
|
|
||||||
m.mesh_graphadr,
|
m.mesh_graphadr,
|
||||||
|
m.mesh_vert,
|
||||||
|
m.mesh_face,
|
||||||
m.mesh_graph,
|
m.mesh_graph,
|
||||||
m.mesh_polynum,
|
m.mesh_polynum,
|
||||||
m.mesh_polyadr,
|
m.mesh_polyadr,
|
||||||
@@ -918,9 +923,11 @@ def sdf_narrowphase(m: Model, d: Data):
|
|||||||
m.mesh_polymapadr,
|
m.mesh_polymapadr,
|
||||||
m.mesh_polymapnum,
|
m.mesh_polymapnum,
|
||||||
m.mesh_polymap,
|
m.mesh_polymap,
|
||||||
m.oct_aabb,
|
m.hfield_size,
|
||||||
m.oct_child,
|
m.hfield_nrow,
|
||||||
m.oct_coeff,
|
m.hfield_ncol,
|
||||||
|
m.hfield_adr,
|
||||||
|
m.hfield_data,
|
||||||
m.pair_dim,
|
m.pair_dim,
|
||||||
m.pair_solref,
|
m.pair_solref,
|
||||||
m.pair_solreffriction,
|
m.pair_solreffriction,
|
||||||
@@ -931,9 +938,9 @@ def sdf_narrowphase(m: Model, d: Data):
|
|||||||
m.plugin,
|
m.plugin,
|
||||||
m.plugin_attr,
|
m.plugin_attr,
|
||||||
m.geom_plugin_index,
|
m.geom_plugin_index,
|
||||||
d.naconmax,
|
|
||||||
d.geom_xpos,
|
d.geom_xpos,
|
||||||
d.geom_xmat,
|
d.geom_xmat,
|
||||||
|
d.naconmax,
|
||||||
d.collision_pair,
|
d.collision_pair,
|
||||||
d.collision_pairid,
|
d.collision_pairid,
|
||||||
d.collision_worldid,
|
d.collision_worldid,
|
||||||
@@ -942,7 +949,6 @@ def sdf_narrowphase(m: Model, d: Data):
|
|||||||
m.opt.sdf_iterations,
|
m.opt.sdf_iterations,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
d.nacon,
|
|
||||||
d.contact.dist,
|
d.contact.dist,
|
||||||
d.contact.pos,
|
d.contact.pos,
|
||||||
d.contact.frame,
|
d.contact.frame,
|
||||||
@@ -954,5 +960,8 @@ def sdf_narrowphase(m: Model, d: Data):
|
|||||||
d.contact.dim,
|
d.contact.dim,
|
||||||
d.contact.geom,
|
d.contact.geom,
|
||||||
d.contact.worldid,
|
d.contact.worldid,
|
||||||
|
d.contact.type,
|
||||||
|
d.contact.geomcollisionid,
|
||||||
|
d.nacon,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
+172
-126
@@ -19,6 +19,7 @@ from mujoco.mjx.third_party.mujoco_warp._src import math
|
|||||||
from mujoco.mjx.third_party.mujoco_warp._src import support
|
from mujoco.mjx.third_party.mujoco_warp._src import support
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src import types
|
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 ConstraintType
|
||||||
|
from mujoco.mjx.third_party.mujoco_warp._src.types import ContactType
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import vec5
|
from mujoco.mjx.third_party.mujoco_warp._src.types import vec5
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import vec11
|
from mujoco.mjx.third_party.mujoco_warp._src.types import vec11
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import event_scope
|
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import event_scope
|
||||||
@@ -27,16 +28,16 @@ wp.set_module_options({"enable_backward": False})
|
|||||||
|
|
||||||
|
|
||||||
@wp.kernel
|
@wp.kernel
|
||||||
def zero_constraint_counts(
|
def _zero_constraint_counts(
|
||||||
# Data out:
|
# Data out:
|
||||||
ne_out: wp.array(dtype=int),
|
ne_out: wp.array(dtype=int),
|
||||||
|
nf_out: wp.array(dtype=int),
|
||||||
|
nl_out: wp.array(dtype=int),
|
||||||
|
nefc_out: wp.array(dtype=int),
|
||||||
ne_connect_out: wp.array(dtype=int),
|
ne_connect_out: wp.array(dtype=int),
|
||||||
ne_weld_out: wp.array(dtype=int),
|
ne_weld_out: wp.array(dtype=int),
|
||||||
ne_jnt_out: wp.array(dtype=int),
|
ne_jnt_out: wp.array(dtype=int),
|
||||||
ne_ten_out: wp.array(dtype=int),
|
ne_ten_out: wp.array(dtype=int),
|
||||||
nf_out: wp.array(dtype=int),
|
|
||||||
nl_out: wp.array(dtype=int),
|
|
||||||
nefc_out: wp.array(dtype=int),
|
|
||||||
):
|
):
|
||||||
worldid = wp.tid()
|
worldid = wp.tid()
|
||||||
|
|
||||||
@@ -141,7 +142,6 @@ def _efc_equality_connect(
|
|||||||
eq_data: wp.array2d(dtype=vec11),
|
eq_data: wp.array2d(dtype=vec11),
|
||||||
eq_connect_adr: wp.array(dtype=int),
|
eq_connect_adr: wp.array(dtype=int),
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
qvel_in: wp.array2d(dtype=float),
|
qvel_in: wp.array2d(dtype=float),
|
||||||
eq_active_in: wp.array2d(dtype=bool),
|
eq_active_in: wp.array2d(dtype=bool),
|
||||||
xpos_in: wp.array2d(dtype=wp.vec3),
|
xpos_in: wp.array2d(dtype=wp.vec3),
|
||||||
@@ -149,10 +149,10 @@ def _efc_equality_connect(
|
|||||||
site_xpos_in: wp.array2d(dtype=wp.vec3),
|
site_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||||
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
||||||
cdof_in: wp.array2d(dtype=wp.spatial_vector),
|
cdof_in: wp.array2d(dtype=wp.spatial_vector),
|
||||||
|
njmax_in: int,
|
||||||
# In:
|
# In:
|
||||||
refsafe_in: int,
|
refsafe_in: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
ne_connect_out: wp.array(dtype=int),
|
|
||||||
nefc_out: wp.array(dtype=int),
|
nefc_out: wp.array(dtype=int),
|
||||||
efc_type_out: wp.array2d(dtype=int),
|
efc_type_out: wp.array2d(dtype=int),
|
||||||
efc_id_out: wp.array2d(dtype=int),
|
efc_id_out: wp.array2d(dtype=int),
|
||||||
@@ -163,9 +163,9 @@ def _efc_equality_connect(
|
|||||||
efc_vel_out: wp.array2d(dtype=float),
|
efc_vel_out: wp.array2d(dtype=float),
|
||||||
efc_aref_out: wp.array2d(dtype=float),
|
efc_aref_out: wp.array2d(dtype=float),
|
||||||
efc_frictionloss_out: wp.array2d(dtype=float),
|
efc_frictionloss_out: wp.array2d(dtype=float),
|
||||||
|
ne_connect_out: wp.array(dtype=int),
|
||||||
):
|
):
|
||||||
"""Calculates constraint rows for connect equality constraints."""
|
"""Calculates constraint rows for connect equality constraints."""
|
||||||
|
|
||||||
worldid, eqconnectid = wp.tid()
|
worldid, eqconnectid = wp.tid()
|
||||||
eqid = eq_connect_adr[eqconnectid]
|
eqid = eq_connect_adr[eqconnectid]
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ def _efc_equality_connect(
|
|||||||
if efcid + 3 >= njmax_in:
|
if efcid + 3 >= njmax_in:
|
||||||
return
|
return
|
||||||
|
|
||||||
data = eq_data[worldid, eqid]
|
data = eq_data[worldid % eq_data.shape[0], eqid]
|
||||||
anchor1 = wp.vec3f(data[0], data[1], data[2])
|
anchor1 = wp.vec3f(data[0], data[1], data[2])
|
||||||
anchor2 = wp.vec3f(data[3], data[4], data[5])
|
anchor2 = wp.vec3f(data[3], data[4], data[5])
|
||||||
|
|
||||||
@@ -231,18 +231,20 @@ def _efc_equality_connect(
|
|||||||
efc_J_out[worldid, efcid + 2, dofid] = j1mj2[2]
|
efc_J_out[worldid, efcid + 2, dofid] = j1mj2[2]
|
||||||
Jqvel += j1mj2 * qvel_in[worldid, dofid]
|
Jqvel += j1mj2 * qvel_in[worldid, dofid]
|
||||||
|
|
||||||
invweight = body_invweight0[worldid, body1id][0] + body_invweight0[worldid, body2id][0]
|
body_invweight0_id = worldid % body_invweight0.shape[0]
|
||||||
|
invweight = body_invweight0[body_invweight0_id, body1id][0] + body_invweight0[body_invweight0_id, body2id][0]
|
||||||
pos_imp = wp.length(pos)
|
pos_imp = wp.length(pos)
|
||||||
|
|
||||||
solref = eq_solref[worldid, eqid]
|
solref = eq_solref[worldid % eq_solref.shape[0], eqid]
|
||||||
solimp = eq_solimp[worldid, eqid]
|
solimp = eq_solimp[worldid % eq_solimp.shape[0], eqid]
|
||||||
|
timestep = opt_timestep[worldid % opt_timestep.shape[0]]
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
efcidi = efcid + i
|
efcidi = efcid + i
|
||||||
|
|
||||||
_update_efc_row(
|
_update_efc_row(
|
||||||
worldid,
|
worldid,
|
||||||
opt_timestep[worldid],
|
timestep,
|
||||||
refsafe_in,
|
refsafe_in,
|
||||||
efcidi,
|
efcidi,
|
||||||
pos[i],
|
pos[i],
|
||||||
@@ -282,14 +284,13 @@ def _efc_equality_joint(
|
|||||||
eq_data: wp.array2d(dtype=vec11),
|
eq_data: wp.array2d(dtype=vec11),
|
||||||
eq_jnt_adr: wp.array(dtype=int),
|
eq_jnt_adr: wp.array(dtype=int),
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
qpos_in: wp.array2d(dtype=float),
|
qpos_in: wp.array2d(dtype=float),
|
||||||
qvel_in: wp.array2d(dtype=float),
|
qvel_in: wp.array2d(dtype=float),
|
||||||
eq_active_in: wp.array2d(dtype=bool),
|
eq_active_in: wp.array2d(dtype=bool),
|
||||||
|
njmax_in: int,
|
||||||
# In:
|
# In:
|
||||||
refsafe_in: int,
|
refsafe_in: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
ne_jnt_out: wp.array(dtype=int),
|
|
||||||
nefc_out: wp.array(dtype=int),
|
nefc_out: wp.array(dtype=int),
|
||||||
efc_type_out: wp.array2d(dtype=int),
|
efc_type_out: wp.array2d(dtype=int),
|
||||||
efc_id_out: wp.array2d(dtype=int),
|
efc_id_out: wp.array2d(dtype=int),
|
||||||
@@ -300,6 +301,7 @@ def _efc_equality_joint(
|
|||||||
efc_vel_out: wp.array2d(dtype=float),
|
efc_vel_out: wp.array2d(dtype=float),
|
||||||
efc_aref_out: wp.array2d(dtype=float),
|
efc_aref_out: wp.array2d(dtype=float),
|
||||||
efc_frictionloss_out: wp.array2d(dtype=float),
|
efc_frictionloss_out: wp.array2d(dtype=float),
|
||||||
|
ne_jnt_out: wp.array(dtype=int),
|
||||||
):
|
):
|
||||||
worldid, eqjntid = wp.tid()
|
worldid, eqjntid = wp.tid()
|
||||||
eqid = eq_jnt_adr[eqjntid]
|
eqid = eq_jnt_adr[eqjntid]
|
||||||
@@ -318,10 +320,12 @@ def _efc_equality_joint(
|
|||||||
|
|
||||||
jntid_1 = eq_obj1id[eqid]
|
jntid_1 = eq_obj1id[eqid]
|
||||||
jntid_2 = eq_obj2id[eqid]
|
jntid_2 = eq_obj2id[eqid]
|
||||||
data = eq_data[worldid, eqid]
|
data = eq_data[worldid % eq_data.shape[0], eqid]
|
||||||
dofadr1 = jnt_dofadr[jntid_1]
|
dofadr1 = jnt_dofadr[jntid_1]
|
||||||
qposadr1 = jnt_qposadr[jntid_1]
|
qposadr1 = jnt_qposadr[jntid_1]
|
||||||
efc_J_out[worldid, efcid, dofadr1] = 1.0
|
efc_J_out[worldid, efcid, dofadr1] = 1.0
|
||||||
|
qpos0_id = worldid % qpos0.shape[0]
|
||||||
|
dof_invweight0_id = worldid % dof_invweight0.shape[0]
|
||||||
|
|
||||||
if jntid_2 > -1:
|
if jntid_2 > -1:
|
||||||
# Two joint constraint
|
# Two joint constraint
|
||||||
@@ -333,28 +337,28 @@ def _efc_equality_joint(
|
|||||||
rhs = data[0] + dif * (data[1] + dif * (data[2] + dif * (data[3] + dif * data[4])))
|
rhs = data[0] + dif * (data[1] + dif * (data[2] + dif * (data[3] + dif * data[4])))
|
||||||
deriv_2 = data[1] + dif * (2.0 * data[2] + dif * (3.0 * data[3] + dif * 4.0 * data[4]))
|
deriv_2 = data[1] + dif * (2.0 * data[2] + dif * (3.0 * data[3] + dif * 4.0 * data[4]))
|
||||||
|
|
||||||
pos = qpos_in[worldid, qposadr1] - qpos0[worldid, qposadr1] - rhs
|
pos = qpos_in[worldid, qposadr1] - qpos0[qpos0_id, qposadr1] - rhs
|
||||||
Jqvel = qvel_in[worldid, dofadr1] - qvel_in[worldid, dofadr2] * deriv_2
|
Jqvel = qvel_in[worldid, dofadr1] - qvel_in[worldid, dofadr2] * deriv_2
|
||||||
invweight = dof_invweight0[worldid, dofadr1] + dof_invweight0[worldid, dofadr2]
|
invweight = dof_invweight0[dof_invweight0_id, dofadr1] + dof_invweight0[dof_invweight0_id, dofadr2]
|
||||||
|
|
||||||
efc_J_out[worldid, efcid, dofadr2] = -deriv_2
|
efc_J_out[worldid, efcid, dofadr2] = -deriv_2
|
||||||
else:
|
else:
|
||||||
# Single joint constraint
|
# Single joint constraint
|
||||||
pos = qpos_in[worldid, qposadr1] - qpos0[worldid, qposadr1] - data[0]
|
pos = qpos_in[worldid, qposadr1] - qpos0[qpos0_id, qposadr1] - data[0]
|
||||||
Jqvel = qvel_in[worldid, dofadr1]
|
Jqvel = qvel_in[worldid, dofadr1]
|
||||||
invweight = dof_invweight0[worldid, dofadr1]
|
invweight = dof_invweight0[dof_invweight0_id, dofadr1]
|
||||||
|
|
||||||
# Update constraint parameters
|
# Update constraint parameters
|
||||||
_update_efc_row(
|
_update_efc_row(
|
||||||
worldid,
|
worldid,
|
||||||
opt_timestep[worldid],
|
opt_timestep[worldid % opt_timestep.shape[0]],
|
||||||
refsafe_in,
|
refsafe_in,
|
||||||
efcid,
|
efcid,
|
||||||
pos,
|
pos,
|
||||||
pos,
|
pos,
|
||||||
invweight,
|
invweight,
|
||||||
eq_solref[worldid, eqid],
|
eq_solref[worldid % eq_solref.shape[0], eqid],
|
||||||
eq_solimp[worldid, eqid],
|
eq_solimp[worldid % eq_solimp.shape[0], eqid],
|
||||||
0.0,
|
0.0,
|
||||||
Jqvel,
|
Jqvel,
|
||||||
0.0,
|
0.0,
|
||||||
@@ -381,19 +385,18 @@ def _efc_equality_tendon(
|
|||||||
eq_solref: wp.array2d(dtype=wp.vec2),
|
eq_solref: wp.array2d(dtype=wp.vec2),
|
||||||
eq_solimp: wp.array2d(dtype=vec5),
|
eq_solimp: wp.array2d(dtype=vec5),
|
||||||
eq_data: wp.array2d(dtype=vec11),
|
eq_data: wp.array2d(dtype=vec11),
|
||||||
eq_ten_adr: wp.array(dtype=int),
|
|
||||||
tendon_length0: wp.array2d(dtype=float),
|
tendon_length0: wp.array2d(dtype=float),
|
||||||
tendon_invweight0: wp.array2d(dtype=float),
|
tendon_invweight0: wp.array2d(dtype=float),
|
||||||
|
eq_ten_adr: wp.array(dtype=int),
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
qvel_in: wp.array2d(dtype=float),
|
qvel_in: wp.array2d(dtype=float),
|
||||||
eq_active_in: wp.array2d(dtype=bool),
|
eq_active_in: wp.array2d(dtype=bool),
|
||||||
ten_length_in: wp.array2d(dtype=float),
|
|
||||||
ten_J_in: wp.array3d(dtype=float),
|
ten_J_in: wp.array3d(dtype=float),
|
||||||
|
ten_length_in: wp.array2d(dtype=float),
|
||||||
|
njmax_in: int,
|
||||||
# In:
|
# In:
|
||||||
refsafe_in: int,
|
refsafe_in: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
ne_ten_out: wp.array(dtype=int),
|
|
||||||
nefc_out: wp.array(dtype=int),
|
nefc_out: wp.array(dtype=int),
|
||||||
efc_type_out: wp.array2d(dtype=int),
|
efc_type_out: wp.array2d(dtype=int),
|
||||||
efc_id_out: wp.array2d(dtype=int),
|
efc_id_out: wp.array2d(dtype=int),
|
||||||
@@ -404,6 +407,7 @@ def _efc_equality_tendon(
|
|||||||
efc_vel_out: wp.array2d(dtype=float),
|
efc_vel_out: wp.array2d(dtype=float),
|
||||||
efc_aref_out: wp.array2d(dtype=float),
|
efc_aref_out: wp.array2d(dtype=float),
|
||||||
efc_frictionloss_out: wp.array2d(dtype=float),
|
efc_frictionloss_out: wp.array2d(dtype=float),
|
||||||
|
ne_ten_out: wp.array(dtype=int),
|
||||||
):
|
):
|
||||||
worldid, eqtenid = wp.tid()
|
worldid, eqtenid = wp.tid()
|
||||||
eqid = eq_ten_adr[eqtenid]
|
eqid = eq_ten_adr[eqtenid]
|
||||||
@@ -420,16 +424,18 @@ def _efc_equality_tendon(
|
|||||||
obj1id = eq_obj1id[eqid]
|
obj1id = eq_obj1id[eqid]
|
||||||
obj2id = eq_obj2id[eqid]
|
obj2id = eq_obj2id[eqid]
|
||||||
|
|
||||||
data = eq_data[worldid, eqid]
|
data = eq_data[worldid % eq_data.shape[0], eqid]
|
||||||
solref = eq_solref[worldid, eqid]
|
solref = eq_solref[worldid % eq_solref.shape[0], eqid]
|
||||||
solimp = eq_solimp[worldid, eqid]
|
solimp = eq_solimp[worldid % eq_solimp.shape[0], eqid]
|
||||||
pos1 = ten_length_in[worldid, obj1id] - tendon_length0[worldid, obj1id]
|
tendon_length0_id = worldid % tendon_length0.shape[0]
|
||||||
|
tendon_invweight0_id = worldid % tendon_invweight0.shape[0]
|
||||||
|
pos1 = ten_length_in[worldid, obj1id] - tendon_length0[tendon_length0_id, obj1id]
|
||||||
jac1 = ten_J_in[worldid, obj1id]
|
jac1 = ten_J_in[worldid, obj1id]
|
||||||
|
|
||||||
if obj2id > -1:
|
if obj2id > -1:
|
||||||
invweight = tendon_invweight0[worldid, obj1id] + tendon_invweight0[worldid, obj2id]
|
invweight = tendon_invweight0[tendon_invweight0_id, obj1id] + tendon_invweight0[tendon_invweight0_id, obj2id]
|
||||||
|
|
||||||
pos2 = ten_length_in[worldid, obj2id] - tendon_length0[worldid, obj2id]
|
pos2 = ten_length_in[worldid, obj2id] - tendon_length0[tendon_length0_id, obj2id]
|
||||||
jac2 = ten_J_in[worldid, obj2id]
|
jac2 = ten_J_in[worldid, obj2id]
|
||||||
|
|
||||||
dif = pos2
|
dif = pos2
|
||||||
@@ -440,7 +446,7 @@ def _efc_equality_tendon(
|
|||||||
pos = pos1 - (data[0] + data[1] * dif + data[2] * dif2 + data[3] * dif3 + data[4] * dif4)
|
pos = pos1 - (data[0] + data[1] * dif + data[2] * dif2 + data[3] * dif3 + data[4] * dif4)
|
||||||
deriv = data[1] + 2.0 * data[2] * dif + 3.0 * data[3] * dif2 + 4.0 * data[4] * dif3
|
deriv = data[1] + 2.0 * data[2] * dif + 3.0 * data[3] * dif2 + 4.0 * data[4] * dif3
|
||||||
else:
|
else:
|
||||||
invweight = tendon_invweight0[worldid, obj1id]
|
invweight = tendon_invweight0[tendon_invweight0_id, obj1id]
|
||||||
pos = pos1 - data[0]
|
pos = pos1 - data[0]
|
||||||
deriv = 0.0
|
deriv = 0.0
|
||||||
|
|
||||||
@@ -455,7 +461,7 @@ def _efc_equality_tendon(
|
|||||||
|
|
||||||
_update_efc_row(
|
_update_efc_row(
|
||||||
worldid,
|
worldid,
|
||||||
opt_timestep[worldid],
|
opt_timestep[worldid % opt_timestep.shape[0]],
|
||||||
refsafe_in,
|
refsafe_in,
|
||||||
efcid,
|
efcid,
|
||||||
pos,
|
pos,
|
||||||
@@ -484,13 +490,13 @@ def _efc_friction_dof(
|
|||||||
# Model:
|
# Model:
|
||||||
nv: int,
|
nv: int,
|
||||||
opt_timestep: wp.array(dtype=float),
|
opt_timestep: wp.array(dtype=float),
|
||||||
dof_invweight0: wp.array2d(dtype=float),
|
|
||||||
dof_frictionloss: wp.array2d(dtype=float),
|
|
||||||
dof_solimp: wp.array2d(dtype=vec5),
|
|
||||||
dof_solref: wp.array2d(dtype=wp.vec2),
|
dof_solref: wp.array2d(dtype=wp.vec2),
|
||||||
|
dof_solimp: wp.array2d(dtype=vec5),
|
||||||
|
dof_frictionloss: wp.array2d(dtype=float),
|
||||||
|
dof_invweight0: wp.array2d(dtype=float),
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
qvel_in: wp.array2d(dtype=float),
|
qvel_in: wp.array2d(dtype=float),
|
||||||
|
njmax_in: int,
|
||||||
# In:
|
# In:
|
||||||
refsafe_in: int,
|
refsafe_in: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
@@ -508,7 +514,9 @@ def _efc_friction_dof(
|
|||||||
):
|
):
|
||||||
worldid, dofid = wp.tid()
|
worldid, dofid = wp.tid()
|
||||||
|
|
||||||
if dof_frictionloss[worldid, dofid] <= 0.0:
|
dof_frictionloss_id = worldid % dof_frictionloss.shape[0]
|
||||||
|
|
||||||
|
if dof_frictionloss[dof_frictionloss_id, dofid] <= 0.0:
|
||||||
return
|
return
|
||||||
|
|
||||||
wp.atomic_add(nf_out, worldid, 1)
|
wp.atomic_add(nf_out, worldid, 1)
|
||||||
@@ -523,19 +531,22 @@ def _efc_friction_dof(
|
|||||||
efc_J_out[worldid, efcid, dofid] = 1.0
|
efc_J_out[worldid, efcid, dofid] = 1.0
|
||||||
Jqvel = qvel_in[worldid, dofid]
|
Jqvel = qvel_in[worldid, dofid]
|
||||||
|
|
||||||
|
dof_invweight0_id = worldid % dof_invweight0.shape[0]
|
||||||
|
dof_solref_id = worldid % dof_solref.shape[0]
|
||||||
|
dof_solimp_id = worldid % dof_solimp.shape[0]
|
||||||
_update_efc_row(
|
_update_efc_row(
|
||||||
worldid,
|
worldid,
|
||||||
opt_timestep[worldid],
|
opt_timestep[worldid % opt_timestep.shape[0]],
|
||||||
refsafe_in,
|
refsafe_in,
|
||||||
efcid,
|
efcid,
|
||||||
0.0,
|
0.0,
|
||||||
0.0,
|
0.0,
|
||||||
dof_invweight0[worldid, dofid],
|
dof_invweight0[dof_invweight0_id, dofid],
|
||||||
dof_solref[worldid, dofid],
|
dof_solref[dof_solref_id, dofid],
|
||||||
dof_solimp[worldid, dofid],
|
dof_solimp[dof_solimp_id, dofid],
|
||||||
0.0,
|
0.0,
|
||||||
Jqvel,
|
Jqvel,
|
||||||
dof_frictionloss[worldid, dofid],
|
dof_frictionloss[dof_frictionloss_id, dofid],
|
||||||
ConstraintType.FRICTION_DOF,
|
ConstraintType.FRICTION_DOF,
|
||||||
dofid,
|
dofid,
|
||||||
efc_type_out,
|
efc_type_out,
|
||||||
@@ -559,9 +570,9 @@ def _efc_friction_tendon(
|
|||||||
tendon_frictionloss: wp.array2d(dtype=float),
|
tendon_frictionloss: wp.array2d(dtype=float),
|
||||||
tendon_invweight0: wp.array2d(dtype=float),
|
tendon_invweight0: wp.array2d(dtype=float),
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
qvel_in: wp.array2d(dtype=float),
|
qvel_in: wp.array2d(dtype=float),
|
||||||
ten_J_in: wp.array3d(dtype=float),
|
ten_J_in: wp.array3d(dtype=float),
|
||||||
|
njmax_in: int,
|
||||||
# In:
|
# In:
|
||||||
refsafe_in: int,
|
refsafe_in: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
@@ -579,7 +590,9 @@ def _efc_friction_tendon(
|
|||||||
):
|
):
|
||||||
worldid, tenid = wp.tid()
|
worldid, tenid = wp.tid()
|
||||||
|
|
||||||
frictionloss = tendon_frictionloss[worldid, tenid]
|
tendon_frictionloss_id = worldid % tendon_frictionloss.shape[0]
|
||||||
|
|
||||||
|
frictionloss = tendon_frictionloss[tendon_frictionloss_id, tenid]
|
||||||
if frictionloss <= 0.0:
|
if frictionloss <= 0.0:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -597,16 +610,19 @@ def _efc_friction_tendon(
|
|||||||
efc_J_out[worldid, efcid, i] = J
|
efc_J_out[worldid, efcid, i] = J
|
||||||
Jqvel += J * qvel_in[worldid, i]
|
Jqvel += J * qvel_in[worldid, i]
|
||||||
|
|
||||||
|
tendon_invweight0_id = worldid % tendon_invweight0.shape[0]
|
||||||
|
tendon_solref_fri_id = worldid % tendon_solref_fri.shape[0]
|
||||||
|
tendon_solimp_fri_id = worldid % tendon_solimp_fri.shape[0]
|
||||||
_update_efc_row(
|
_update_efc_row(
|
||||||
worldid,
|
worldid,
|
||||||
opt_timestep[worldid],
|
opt_timestep[worldid % opt_timestep.shape[0]],
|
||||||
refsafe_in,
|
refsafe_in,
|
||||||
efcid,
|
efcid,
|
||||||
0.0,
|
0.0,
|
||||||
0.0,
|
0.0,
|
||||||
tendon_invweight0[worldid, tenid],
|
tendon_invweight0[tendon_invweight0_id, tenid],
|
||||||
tendon_solref_fri[worldid, tenid],
|
tendon_solref_fri[tendon_solref_fri_id, tenid],
|
||||||
tendon_solimp_fri[worldid, tenid],
|
tendon_solimp_fri[tendon_solimp_fri_id, tenid],
|
||||||
0.0,
|
0.0,
|
||||||
Jqvel,
|
Jqvel,
|
||||||
frictionloss,
|
frictionloss,
|
||||||
@@ -643,7 +659,6 @@ def _efc_equality_weld(
|
|||||||
eq_data: wp.array2d(dtype=vec11),
|
eq_data: wp.array2d(dtype=vec11),
|
||||||
eq_wld_adr: wp.array(dtype=int),
|
eq_wld_adr: wp.array(dtype=int),
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
qvel_in: wp.array2d(dtype=float),
|
qvel_in: wp.array2d(dtype=float),
|
||||||
eq_active_in: wp.array2d(dtype=bool),
|
eq_active_in: wp.array2d(dtype=bool),
|
||||||
xpos_in: wp.array2d(dtype=wp.vec3),
|
xpos_in: wp.array2d(dtype=wp.vec3),
|
||||||
@@ -652,10 +667,10 @@ def _efc_equality_weld(
|
|||||||
site_xpos_in: wp.array2d(dtype=wp.vec3),
|
site_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||||
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
||||||
cdof_in: wp.array2d(dtype=wp.spatial_vector),
|
cdof_in: wp.array2d(dtype=wp.spatial_vector),
|
||||||
|
njmax_in: int,
|
||||||
# In:
|
# In:
|
||||||
refsafe_in: int,
|
refsafe_in: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
ne_weld_out: wp.array(dtype=int),
|
|
||||||
nefc_out: wp.array(dtype=int),
|
nefc_out: wp.array(dtype=int),
|
||||||
efc_type_out: wp.array2d(dtype=int),
|
efc_type_out: wp.array2d(dtype=int),
|
||||||
efc_id_out: wp.array2d(dtype=int),
|
efc_id_out: wp.array2d(dtype=int),
|
||||||
@@ -666,6 +681,7 @@ def _efc_equality_weld(
|
|||||||
efc_vel_out: wp.array2d(dtype=float),
|
efc_vel_out: wp.array2d(dtype=float),
|
||||||
efc_aref_out: wp.array2d(dtype=float),
|
efc_aref_out: wp.array2d(dtype=float),
|
||||||
efc_frictionloss_out: wp.array2d(dtype=float),
|
efc_frictionloss_out: wp.array2d(dtype=float),
|
||||||
|
ne_weld_out: wp.array(dtype=int),
|
||||||
):
|
):
|
||||||
worldid, eqweldid = wp.tid()
|
worldid, eqweldid = wp.tid()
|
||||||
eqid = eq_wld_adr[eqweldid]
|
eqid = eq_wld_adr[eqweldid]
|
||||||
@@ -684,7 +700,7 @@ def _efc_equality_weld(
|
|||||||
obj1id = eq_obj1id[eqid]
|
obj1id = eq_obj1id[eqid]
|
||||||
obj2id = eq_obj2id[eqid]
|
obj2id = eq_obj2id[eqid]
|
||||||
|
|
||||||
data = eq_data[worldid, eqid]
|
data = eq_data[worldid % eq_data.shape[0], eqid]
|
||||||
anchor1 = wp.vec3(data[0], data[1], data[2])
|
anchor1 = wp.vec3(data[0], data[1], data[2])
|
||||||
anchor2 = wp.vec3(data[3], data[4], data[5])
|
anchor2 = wp.vec3(data[3], data[4], data[5])
|
||||||
relpose = wp.quat(data[6], data[7], data[8], data[9])
|
relpose = wp.quat(data[6], data[7], data[8], data[9])
|
||||||
@@ -697,8 +713,9 @@ def _efc_equality_weld(
|
|||||||
pos1 = site_xpos_in[worldid, obj1id]
|
pos1 = site_xpos_in[worldid, obj1id]
|
||||||
pos2 = site_xpos_in[worldid, obj2id]
|
pos2 = site_xpos_in[worldid, obj2id]
|
||||||
|
|
||||||
quat = math.mul_quat(xquat_in[worldid, body1id], site_quat[worldid, obj1id])
|
site_quat_id = worldid % site_quat.shape[0]
|
||||||
quat1 = math.quat_inv(math.mul_quat(xquat_in[worldid, body2id], site_quat[worldid, obj2id]))
|
quat = math.mul_quat(xquat_in[worldid, body1id], site_quat[site_quat_id, obj1id])
|
||||||
|
quat1 = math.quat_inv(math.mul_quat(xquat_in[worldid, body2id], site_quat[site_quat_id, obj2id]))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
body1id = obj1id
|
body1id = obj1id
|
||||||
@@ -757,14 +774,15 @@ def _efc_equality_weld(
|
|||||||
crotq = math.mul_quat(quat1, quat) # copy axis components
|
crotq = math.mul_quat(quat1, quat) # copy axis components
|
||||||
crot = wp.vec3(crotq[1], crotq[2], crotq[3]) * torquescale
|
crot = wp.vec3(crotq[1], crotq[2], crotq[3]) * torquescale
|
||||||
|
|
||||||
invweight_t = body_invweight0[worldid, body1id][0] + body_invweight0[worldid, body2id][0]
|
body_invweight0_id = worldid % body_invweight0.shape[0]
|
||||||
|
invweight_t = body_invweight0[body_invweight0_id, body1id][0] + body_invweight0[body_invweight0_id, body2id][0]
|
||||||
|
|
||||||
pos_imp = wp.sqrt(wp.length_sq(cpos) + wp.length_sq(crot))
|
pos_imp = wp.sqrt(wp.length_sq(cpos) + wp.length_sq(crot))
|
||||||
|
|
||||||
solref = eq_solref[worldid, eqid]
|
solref = eq_solref[worldid % eq_solref.shape[0], eqid]
|
||||||
solimp = eq_solimp[worldid, eqid]
|
solimp = eq_solimp[worldid % eq_solimp.shape[0], eqid]
|
||||||
|
|
||||||
timestep = opt_timestep[worldid]
|
timestep = opt_timestep[worldid % opt_timestep.shape[0]]
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
_update_efc_row(
|
_update_efc_row(
|
||||||
@@ -792,7 +810,7 @@ def _efc_equality_weld(
|
|||||||
efc_frictionloss_out,
|
efc_frictionloss_out,
|
||||||
)
|
)
|
||||||
|
|
||||||
invweight_r = body_invweight0[worldid, body1id][1] + body_invweight0[worldid, body2id][1]
|
invweight_r = body_invweight0[body_invweight0_id, body1id][1] + body_invweight0[body_invweight0_id, body2id][1]
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
_update_efc_row(
|
_update_efc_row(
|
||||||
@@ -832,12 +850,12 @@ def _efc_limit_slide_hinge(
|
|||||||
jnt_solimp: wp.array2d(dtype=vec5),
|
jnt_solimp: wp.array2d(dtype=vec5),
|
||||||
jnt_range: wp.array2d(dtype=wp.vec2),
|
jnt_range: wp.array2d(dtype=wp.vec2),
|
||||||
jnt_margin: wp.array2d(dtype=float),
|
jnt_margin: wp.array2d(dtype=float),
|
||||||
jnt_limited_slide_hinge_adr: wp.array(dtype=int),
|
|
||||||
dof_invweight0: wp.array2d(dtype=float),
|
dof_invweight0: wp.array2d(dtype=float),
|
||||||
|
jnt_limited_slide_hinge_adr: wp.array(dtype=int),
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
qpos_in: wp.array2d(dtype=float),
|
qpos_in: wp.array2d(dtype=float),
|
||||||
qvel_in: wp.array2d(dtype=float),
|
qvel_in: wp.array2d(dtype=float),
|
||||||
|
njmax_in: int,
|
||||||
# In:
|
# In:
|
||||||
refsafe_in: int,
|
refsafe_in: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
@@ -855,10 +873,12 @@ def _efc_limit_slide_hinge(
|
|||||||
):
|
):
|
||||||
worldid, jntlimitedid = wp.tid()
|
worldid, jntlimitedid = wp.tid()
|
||||||
jntid = jnt_limited_slide_hinge_adr[jntlimitedid]
|
jntid = jnt_limited_slide_hinge_adr[jntlimitedid]
|
||||||
jntrange = jnt_range[worldid, jntid]
|
jnt_range_id = worldid % jnt_range.shape[0]
|
||||||
|
jntrange = jnt_range[jnt_range_id, jntid]
|
||||||
|
|
||||||
qpos = qpos_in[worldid, jnt_qposadr[jntid]]
|
qpos = qpos_in[worldid, jnt_qposadr[jntid]]
|
||||||
jntmargin = jnt_margin[worldid, jntid]
|
jnt_margin_id = worldid % jnt_margin.shape[0]
|
||||||
|
jntmargin = jnt_margin[jnt_margin_id, jntid]
|
||||||
dist_min, dist_max = qpos - jntrange[0], jntrange[1] - qpos
|
dist_min, dist_max = qpos - jntrange[0], jntrange[1] - qpos
|
||||||
pos = wp.min(dist_min, dist_max) - jntmargin
|
pos = wp.min(dist_min, dist_max) - jntmargin
|
||||||
active = pos < 0
|
active = pos < 0
|
||||||
@@ -879,16 +899,19 @@ def _efc_limit_slide_hinge(
|
|||||||
efc_J_out[worldid, efcid, dofadr] = J
|
efc_J_out[worldid, efcid, dofadr] = J
|
||||||
Jqvel = J * qvel_in[worldid, dofadr]
|
Jqvel = J * qvel_in[worldid, dofadr]
|
||||||
|
|
||||||
|
dof_invweight0_id = worldid % dof_invweight0.shape[0]
|
||||||
|
jnt_solref_id = worldid % jnt_solref.shape[0]
|
||||||
|
jnt_solimp_id = worldid % jnt_solimp.shape[0]
|
||||||
_update_efc_row(
|
_update_efc_row(
|
||||||
worldid,
|
worldid,
|
||||||
opt_timestep[worldid],
|
opt_timestep[worldid % opt_timestep.shape[0]],
|
||||||
refsafe_in,
|
refsafe_in,
|
||||||
efcid,
|
efcid,
|
||||||
pos,
|
pos,
|
||||||
pos,
|
pos,
|
||||||
dof_invweight0[worldid, dofadr],
|
dof_invweight0[dof_invweight0_id, dofadr],
|
||||||
jnt_solref[worldid, jntid],
|
jnt_solref[jnt_solref_id, jntid],
|
||||||
jnt_solimp[worldid, jntid],
|
jnt_solimp[jnt_solimp_id, jntid],
|
||||||
jntmargin,
|
jntmargin,
|
||||||
Jqvel,
|
Jqvel,
|
||||||
0.0,
|
0.0,
|
||||||
@@ -916,12 +939,12 @@ def _efc_limit_ball(
|
|||||||
jnt_solimp: wp.array2d(dtype=vec5),
|
jnt_solimp: wp.array2d(dtype=vec5),
|
||||||
jnt_range: wp.array2d(dtype=wp.vec2),
|
jnt_range: wp.array2d(dtype=wp.vec2),
|
||||||
jnt_margin: wp.array2d(dtype=float),
|
jnt_margin: wp.array2d(dtype=float),
|
||||||
jnt_limited_ball_adr: wp.array(dtype=int),
|
|
||||||
dof_invweight0: wp.array2d(dtype=float),
|
dof_invweight0: wp.array2d(dtype=float),
|
||||||
|
jnt_limited_ball_adr: wp.array(dtype=int),
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
qpos_in: wp.array2d(dtype=float),
|
qpos_in: wp.array2d(dtype=float),
|
||||||
qvel_in: wp.array2d(dtype=float),
|
qvel_in: wp.array2d(dtype=float),
|
||||||
|
njmax_in: int,
|
||||||
# In:
|
# In:
|
||||||
refsafe_in: int,
|
refsafe_in: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
@@ -945,9 +968,11 @@ def _efc_limit_ball(
|
|||||||
jnt_quat = wp.quat(qpos[qposadr + 0], qpos[qposadr + 1], qpos[qposadr + 2], qpos[qposadr + 3])
|
jnt_quat = wp.quat(qpos[qposadr + 0], qpos[qposadr + 1], qpos[qposadr + 2], qpos[qposadr + 3])
|
||||||
jnt_quat = wp.normalize(jnt_quat)
|
jnt_quat = wp.normalize(jnt_quat)
|
||||||
axis_angle = math.quat_to_vel(jnt_quat)
|
axis_angle = math.quat_to_vel(jnt_quat)
|
||||||
jntrange = jnt_range[worldid, jntid]
|
jnt_range_id = worldid % jnt_range.shape[0]
|
||||||
|
jntrange = jnt_range[jnt_range_id, jntid]
|
||||||
axis, angle = math.normalize_with_norm(axis_angle)
|
axis, angle = math.normalize_with_norm(axis_angle)
|
||||||
jntmargin = jnt_margin[worldid, jntid]
|
jnt_margin_id = worldid % jnt_margin.shape[0]
|
||||||
|
jntmargin = jnt_margin[jnt_margin_id, jntid]
|
||||||
|
|
||||||
pos = wp.max(jntrange[0], jntrange[1]) - angle - jntmargin
|
pos = wp.max(jntrange[0], jntrange[1]) - angle - jntmargin
|
||||||
active = pos < 0
|
active = pos < 0
|
||||||
@@ -972,16 +997,19 @@ def _efc_limit_ball(
|
|||||||
Jqvel -= axis[1] * qvel_in[worldid, dofadr + 1]
|
Jqvel -= axis[1] * qvel_in[worldid, dofadr + 1]
|
||||||
Jqvel -= axis[2] * qvel_in[worldid, dofadr + 2]
|
Jqvel -= axis[2] * qvel_in[worldid, dofadr + 2]
|
||||||
|
|
||||||
|
dof_invweight0_id = worldid % dof_invweight0.shape[0]
|
||||||
|
jnt_solref_id = worldid % jnt_solref.shape[0]
|
||||||
|
jnt_solimp_id = worldid % jnt_solimp.shape[0]
|
||||||
_update_efc_row(
|
_update_efc_row(
|
||||||
worldid,
|
worldid,
|
||||||
opt_timestep[worldid],
|
opt_timestep[worldid % opt_timestep.shape[0]],
|
||||||
refsafe_in,
|
refsafe_in,
|
||||||
efcid,
|
efcid,
|
||||||
pos,
|
pos,
|
||||||
pos,
|
pos,
|
||||||
dof_invweight0[worldid, dofadr],
|
dof_invweight0[dof_invweight0_id, dofadr],
|
||||||
jnt_solref[worldid, jntid],
|
jnt_solref[jnt_solref_id, jntid],
|
||||||
jnt_solimp[worldid, jntid],
|
jnt_solimp[jnt_solimp_id, jntid],
|
||||||
jntmargin,
|
jntmargin,
|
||||||
Jqvel,
|
Jqvel,
|
||||||
0.0,
|
0.0,
|
||||||
@@ -1006,19 +1034,19 @@ def _efc_limit_tendon(
|
|||||||
jnt_dofadr: wp.array(dtype=int),
|
jnt_dofadr: wp.array(dtype=int),
|
||||||
tendon_adr: wp.array(dtype=int),
|
tendon_adr: wp.array(dtype=int),
|
||||||
tendon_num: wp.array(dtype=int),
|
tendon_num: wp.array(dtype=int),
|
||||||
tendon_limited_adr: wp.array(dtype=int),
|
|
||||||
tendon_solref_lim: wp.array2d(dtype=wp.vec2),
|
tendon_solref_lim: wp.array2d(dtype=wp.vec2),
|
||||||
tendon_solimp_lim: wp.array2d(dtype=vec5),
|
tendon_solimp_lim: wp.array2d(dtype=vec5),
|
||||||
tendon_range: wp.array2d(dtype=wp.vec2),
|
tendon_range: wp.array2d(dtype=wp.vec2),
|
||||||
tendon_margin: wp.array2d(dtype=float),
|
tendon_margin: wp.array2d(dtype=float),
|
||||||
tendon_invweight0: wp.array2d(dtype=float),
|
tendon_invweight0: wp.array2d(dtype=float),
|
||||||
wrap_objid: wp.array(dtype=int),
|
|
||||||
wrap_type: wp.array(dtype=int),
|
wrap_type: wp.array(dtype=int),
|
||||||
|
wrap_objid: wp.array(dtype=int),
|
||||||
|
tendon_limited_adr: wp.array(dtype=int),
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
qvel_in: wp.array2d(dtype=float),
|
qvel_in: wp.array2d(dtype=float),
|
||||||
ten_length_in: wp.array2d(dtype=float),
|
|
||||||
ten_J_in: wp.array3d(dtype=float),
|
ten_J_in: wp.array3d(dtype=float),
|
||||||
|
ten_length_in: wp.array2d(dtype=float),
|
||||||
|
njmax_in: int,
|
||||||
# In:
|
# In:
|
||||||
refsafe_in: int,
|
refsafe_in: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
@@ -1037,10 +1065,12 @@ def _efc_limit_tendon(
|
|||||||
worldid, tenlimitedid = wp.tid()
|
worldid, tenlimitedid = wp.tid()
|
||||||
tenid = tendon_limited_adr[tenlimitedid]
|
tenid = tendon_limited_adr[tenlimitedid]
|
||||||
|
|
||||||
tenrange = tendon_range[worldid, tenid]
|
tendon_range_id = worldid % tendon_range.shape[0]
|
||||||
|
tenrange = tendon_range[tendon_range_id, tenid]
|
||||||
length = ten_length_in[worldid, tenid]
|
length = ten_length_in[worldid, tenid]
|
||||||
dist_min, dist_max = length - tenrange[0], tenrange[1] - length
|
dist_min, dist_max = length - tenrange[0], tenrange[1] - length
|
||||||
tenmargin = tendon_margin[worldid, tenid]
|
tendon_margin_id = worldid % tendon_margin.shape[0]
|
||||||
|
tenmargin = tendon_margin[tendon_margin_id, tenid]
|
||||||
pos = wp.min(dist_min, dist_max) - tenmargin
|
pos = wp.min(dist_min, dist_max) - tenmargin
|
||||||
active = pos < 0
|
active = pos < 0
|
||||||
|
|
||||||
@@ -1071,16 +1101,19 @@ def _efc_limit_tendon(
|
|||||||
efc_J_out[worldid, efcid, i] = J
|
efc_J_out[worldid, efcid, i] = J
|
||||||
Jqvel += J * qvel_in[worldid, i]
|
Jqvel += J * qvel_in[worldid, i]
|
||||||
|
|
||||||
|
tendon_invweight0_id = worldid % tendon_invweight0.shape[0]
|
||||||
|
tendon_solref_lim_id = worldid % tendon_solref_lim.shape[0]
|
||||||
|
tendon_solimp_lim_id = worldid % tendon_solimp_lim.shape[0]
|
||||||
_update_efc_row(
|
_update_efc_row(
|
||||||
worldid,
|
worldid,
|
||||||
opt_timestep[worldid],
|
opt_timestep[worldid % opt_timestep.shape[0]],
|
||||||
refsafe_in,
|
refsafe_in,
|
||||||
efcid,
|
efcid,
|
||||||
pos,
|
pos,
|
||||||
pos,
|
pos,
|
||||||
tendon_invweight0[worldid, tenid],
|
tendon_invweight0[tendon_invweight0_id, tenid],
|
||||||
tendon_solref_lim[worldid, tenid],
|
tendon_solref_lim[tendon_solref_lim_id, tenid],
|
||||||
tendon_solimp_lim[worldid, tenid],
|
tendon_solimp_lim[tendon_solimp_lim_id, tenid],
|
||||||
tenmargin,
|
tenmargin,
|
||||||
Jqvel,
|
Jqvel,
|
||||||
0.0,
|
0.0,
|
||||||
@@ -1109,11 +1142,11 @@ def _efc_contact_pyramidal(
|
|||||||
dof_bodyid: wp.array(dtype=int),
|
dof_bodyid: wp.array(dtype=int),
|
||||||
geom_bodyid: wp.array(dtype=int),
|
geom_bodyid: wp.array(dtype=int),
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
nacon_in: wp.array(dtype=int),
|
|
||||||
qvel_in: wp.array2d(dtype=float),
|
qvel_in: wp.array2d(dtype=float),
|
||||||
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
||||||
cdof_in: wp.array2d(dtype=wp.spatial_vector),
|
cdof_in: wp.array2d(dtype=wp.spatial_vector),
|
||||||
|
njmax_in: int,
|
||||||
|
nacon_in: wp.array(dtype=int),
|
||||||
# In:
|
# In:
|
||||||
refsafe_in: int,
|
refsafe_in: int,
|
||||||
dist_in: wp.array(dtype=float),
|
dist_in: wp.array(dtype=float),
|
||||||
@@ -1126,6 +1159,7 @@ def _efc_contact_pyramidal(
|
|||||||
friction_in: wp.array(dtype=vec5),
|
friction_in: wp.array(dtype=vec5),
|
||||||
solref_in: wp.array(dtype=wp.vec2),
|
solref_in: wp.array(dtype=wp.vec2),
|
||||||
solimp_in: wp.array(dtype=vec5),
|
solimp_in: wp.array(dtype=vec5),
|
||||||
|
type_in: wp.array(dtype=int),
|
||||||
# Data out:
|
# Data out:
|
||||||
nefc_out: wp.array(dtype=int),
|
nefc_out: wp.array(dtype=int),
|
||||||
contact_efc_address_out: wp.array2d(dtype=int),
|
contact_efc_address_out: wp.array2d(dtype=int),
|
||||||
@@ -1144,6 +1178,9 @@ def _efc_contact_pyramidal(
|
|||||||
if conid >= nacon_in[0]:
|
if conid >= nacon_in[0]:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not type_in[conid] & ContactType.CONSTRAINT:
|
||||||
|
return
|
||||||
|
|
||||||
condim = condim_in[conid]
|
condim = condim_in[conid]
|
||||||
|
|
||||||
if condim == 1 and dimid > 0:
|
if condim == 1 and dimid > 0:
|
||||||
@@ -1163,8 +1200,9 @@ def _efc_contact_pyramidal(
|
|||||||
contact_efc_address_out[conid, dimid] = -1
|
contact_efc_address_out[conid, dimid] = -1
|
||||||
return
|
return
|
||||||
|
|
||||||
timestep = opt_timestep[worldid]
|
opt_timestep_id = worldid % opt_timestep.shape[0]
|
||||||
impratio = opt_impratio[worldid]
|
timestep = opt_timestep[opt_timestep_id]
|
||||||
|
impratio = opt_impratio[opt_timestep_id]
|
||||||
contact_efc_address_out[conid, dimid] = efcid
|
contact_efc_address_out[conid, dimid] = efcid
|
||||||
|
|
||||||
geom = geom_in[conid]
|
geom = geom_in[conid]
|
||||||
@@ -1175,7 +1213,8 @@ def _efc_contact_pyramidal(
|
|||||||
frame = frame_in[conid]
|
frame = frame_in[conid]
|
||||||
|
|
||||||
# pyramidal has common invweight across all edges
|
# pyramidal has common invweight across all edges
|
||||||
invweight = body_invweight0[worldid, body1][0] + body_invweight0[worldid, body2][0]
|
body_invweight0_id = worldid % body_invweight0.shape[0]
|
||||||
|
invweight = body_invweight0[body_invweight0_id, body1][0] + body_invweight0[body_invweight0_id, body2][0]
|
||||||
|
|
||||||
if condim > 1:
|
if condim > 1:
|
||||||
dimid2 = dimid / 2 + 1
|
dimid2 = dimid / 2 + 1
|
||||||
@@ -1274,11 +1313,11 @@ def _efc_contact_elliptic(
|
|||||||
dof_bodyid: wp.array(dtype=int),
|
dof_bodyid: wp.array(dtype=int),
|
||||||
geom_bodyid: wp.array(dtype=int),
|
geom_bodyid: wp.array(dtype=int),
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
nacon_in: wp.array(dtype=int),
|
|
||||||
qvel_in: wp.array2d(dtype=float),
|
qvel_in: wp.array2d(dtype=float),
|
||||||
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
||||||
cdof_in: wp.array2d(dtype=wp.spatial_vector),
|
cdof_in: wp.array2d(dtype=wp.spatial_vector),
|
||||||
|
njmax_in: int,
|
||||||
|
nacon_in: wp.array(dtype=int),
|
||||||
# In:
|
# In:
|
||||||
refsafe_in: int,
|
refsafe_in: int,
|
||||||
dist_in: wp.array(dtype=float),
|
dist_in: wp.array(dtype=float),
|
||||||
@@ -1292,6 +1331,7 @@ def _efc_contact_elliptic(
|
|||||||
solref_in: wp.array(dtype=wp.vec2),
|
solref_in: wp.array(dtype=wp.vec2),
|
||||||
solreffriction_in: wp.array(dtype=wp.vec2),
|
solreffriction_in: wp.array(dtype=wp.vec2),
|
||||||
solimp_in: wp.array(dtype=vec5),
|
solimp_in: wp.array(dtype=vec5),
|
||||||
|
type_in: wp.array(dtype=int),
|
||||||
# Data out:
|
# Data out:
|
||||||
nefc_out: wp.array(dtype=int),
|
nefc_out: wp.array(dtype=int),
|
||||||
contact_efc_address_out: wp.array2d(dtype=int),
|
contact_efc_address_out: wp.array2d(dtype=int),
|
||||||
@@ -1310,6 +1350,9 @@ def _efc_contact_elliptic(
|
|||||||
if conid >= nacon_in[0]:
|
if conid >= nacon_in[0]:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not type_in[conid] & ContactType.CONSTRAINT:
|
||||||
|
return
|
||||||
|
|
||||||
condim = condim_in[conid]
|
condim = condim_in[conid]
|
||||||
|
|
||||||
if dimid > condim - 1:
|
if dimid > condim - 1:
|
||||||
@@ -1327,8 +1370,9 @@ def _efc_contact_elliptic(
|
|||||||
contact_efc_address_out[conid, dimid] = -1
|
contact_efc_address_out[conid, dimid] = -1
|
||||||
return
|
return
|
||||||
|
|
||||||
timestep = opt_timestep[worldid]
|
opt_timestep_id = worldid % opt_timestep.shape[0]
|
||||||
impratio = opt_impratio[worldid]
|
timestep = opt_timestep[opt_timestep_id]
|
||||||
|
impratio = opt_impratio[opt_timestep_id]
|
||||||
contact_efc_address_out[conid, dimid] = efcid
|
contact_efc_address_out[conid, dimid] = efcid
|
||||||
|
|
||||||
geom = geom_in[conid]
|
geom = geom_in[conid]
|
||||||
@@ -1375,7 +1419,8 @@ def _efc_contact_elliptic(
|
|||||||
efc_J_out[worldid, efcid, i] = J
|
efc_J_out[worldid, efcid, i] = J
|
||||||
Jqvel += J * qvel_in[worldid, i]
|
Jqvel += J * qvel_in[worldid, i]
|
||||||
|
|
||||||
invweight = body_invweight0[worldid, body1][0] + body_invweight0[worldid, body2][0]
|
body_invweight0_id = worldid % body_invweight0.shape[0]
|
||||||
|
invweight = body_invweight0[body_invweight0_id, body1][0] + body_invweight0[body_invweight0_id, body2][0]
|
||||||
|
|
||||||
ref = solref_in[conid]
|
ref = solref_in[conid]
|
||||||
pos_aref = pos
|
pos_aref = pos
|
||||||
@@ -1448,11 +1493,10 @@ def _num_equality(
|
|||||||
@event_scope
|
@event_scope
|
||||||
def make_constraint(m: types.Model, d: types.Data):
|
def make_constraint(m: types.Model, d: types.Data):
|
||||||
"""Creates constraint jacobians and other supporting data."""
|
"""Creates constraint jacobians and other supporting data."""
|
||||||
|
|
||||||
wp.launch(
|
wp.launch(
|
||||||
zero_constraint_counts,
|
_zero_constraint_counts,
|
||||||
dim=d.nworld,
|
dim=d.nworld,
|
||||||
inputs=[d.ne, d.ne_connect, d.ne_weld, d.ne_jnt, d.ne_ten, d.nf, d.nl, d.nefc],
|
inputs=[d.ne, d.nf, d.nl, d.nefc, d.ne_connect, d.ne_weld, d.ne_jnt, d.ne_ten],
|
||||||
)
|
)
|
||||||
|
|
||||||
if not (m.opt.disableflags & types.DisableBit.CONSTRAINT):
|
if not (m.opt.disableflags & types.DisableBit.CONSTRAINT):
|
||||||
@@ -1478,7 +1522,6 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
m.eq_solimp,
|
m.eq_solimp,
|
||||||
m.eq_data,
|
m.eq_data,
|
||||||
m.eq_connect_adr,
|
m.eq_connect_adr,
|
||||||
d.njmax,
|
|
||||||
d.qvel,
|
d.qvel,
|
||||||
d.eq_active,
|
d.eq_active,
|
||||||
d.xpos,
|
d.xpos,
|
||||||
@@ -1486,10 +1529,10 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
d.site_xpos,
|
d.site_xpos,
|
||||||
d.subtree_com,
|
d.subtree_com,
|
||||||
d.cdof,
|
d.cdof,
|
||||||
|
d.njmax,
|
||||||
refsafe,
|
refsafe,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
d.ne_connect,
|
|
||||||
d.nefc,
|
d.nefc,
|
||||||
d.efc.type,
|
d.efc.type,
|
||||||
d.efc.id,
|
d.efc.id,
|
||||||
@@ -1500,6 +1543,7 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
d.efc.vel,
|
d.efc.vel,
|
||||||
d.efc.aref,
|
d.efc.aref,
|
||||||
d.efc.frictionloss,
|
d.efc.frictionloss,
|
||||||
|
d.ne_connect,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
wp.launch(
|
wp.launch(
|
||||||
@@ -1522,7 +1566,6 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
m.eq_solimp,
|
m.eq_solimp,
|
||||||
m.eq_data,
|
m.eq_data,
|
||||||
m.eq_wld_adr,
|
m.eq_wld_adr,
|
||||||
d.njmax,
|
|
||||||
d.qvel,
|
d.qvel,
|
||||||
d.eq_active,
|
d.eq_active,
|
||||||
d.xpos,
|
d.xpos,
|
||||||
@@ -1531,10 +1574,10 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
d.site_xpos,
|
d.site_xpos,
|
||||||
d.subtree_com,
|
d.subtree_com,
|
||||||
d.cdof,
|
d.cdof,
|
||||||
|
d.njmax,
|
||||||
refsafe,
|
refsafe,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
d.ne_weld,
|
|
||||||
d.nefc,
|
d.nefc,
|
||||||
d.efc.type,
|
d.efc.type,
|
||||||
d.efc.id,
|
d.efc.id,
|
||||||
@@ -1545,6 +1588,7 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
d.efc.vel,
|
d.efc.vel,
|
||||||
d.efc.aref,
|
d.efc.aref,
|
||||||
d.efc.frictionloss,
|
d.efc.frictionloss,
|
||||||
|
d.ne_weld,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
wp.launch(
|
wp.launch(
|
||||||
@@ -1563,14 +1607,13 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
m.eq_solimp,
|
m.eq_solimp,
|
||||||
m.eq_data,
|
m.eq_data,
|
||||||
m.eq_jnt_adr,
|
m.eq_jnt_adr,
|
||||||
d.njmax,
|
|
||||||
d.qpos,
|
d.qpos,
|
||||||
d.qvel,
|
d.qvel,
|
||||||
d.eq_active,
|
d.eq_active,
|
||||||
|
d.njmax,
|
||||||
refsafe,
|
refsafe,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
d.ne_jnt,
|
|
||||||
d.nefc,
|
d.nefc,
|
||||||
d.efc.type,
|
d.efc.type,
|
||||||
d.efc.id,
|
d.efc.id,
|
||||||
@@ -1581,6 +1624,7 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
d.efc.vel,
|
d.efc.vel,
|
||||||
d.efc.aref,
|
d.efc.aref,
|
||||||
d.efc.frictionloss,
|
d.efc.frictionloss,
|
||||||
|
d.ne_jnt,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
wp.launch(
|
wp.launch(
|
||||||
@@ -1594,18 +1638,17 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
m.eq_solref,
|
m.eq_solref,
|
||||||
m.eq_solimp,
|
m.eq_solimp,
|
||||||
m.eq_data,
|
m.eq_data,
|
||||||
m.eq_ten_adr,
|
|
||||||
m.tendon_length0,
|
m.tendon_length0,
|
||||||
m.tendon_invweight0,
|
m.tendon_invweight0,
|
||||||
d.njmax,
|
m.eq_ten_adr,
|
||||||
d.qvel,
|
d.qvel,
|
||||||
d.eq_active,
|
d.eq_active,
|
||||||
d.ten_length,
|
|
||||||
d.ten_J,
|
d.ten_J,
|
||||||
|
d.ten_length,
|
||||||
|
d.njmax,
|
||||||
refsafe,
|
refsafe,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
d.ne_ten,
|
|
||||||
d.nefc,
|
d.nefc,
|
||||||
d.efc.type,
|
d.efc.type,
|
||||||
d.efc.id,
|
d.efc.id,
|
||||||
@@ -1616,6 +1659,7 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
d.efc.vel,
|
d.efc.vel,
|
||||||
d.efc.aref,
|
d.efc.aref,
|
||||||
d.efc.frictionloss,
|
d.efc.frictionloss,
|
||||||
|
d.ne_ten,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1633,12 +1677,12 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
inputs=[
|
inputs=[
|
||||||
m.nv,
|
m.nv,
|
||||||
m.opt.timestep,
|
m.opt.timestep,
|
||||||
m.dof_invweight0,
|
|
||||||
m.dof_frictionloss,
|
|
||||||
m.dof_solimp,
|
|
||||||
m.dof_solref,
|
m.dof_solref,
|
||||||
d.njmax,
|
m.dof_solimp,
|
||||||
|
m.dof_frictionloss,
|
||||||
|
m.dof_invweight0,
|
||||||
d.qvel,
|
d.qvel,
|
||||||
|
d.njmax,
|
||||||
refsafe,
|
refsafe,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
@@ -1666,9 +1710,9 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
m.tendon_solimp_fri,
|
m.tendon_solimp_fri,
|
||||||
m.tendon_frictionloss,
|
m.tendon_frictionloss,
|
||||||
m.tendon_invweight0,
|
m.tendon_invweight0,
|
||||||
d.njmax,
|
|
||||||
d.qvel,
|
d.qvel,
|
||||||
d.ten_J,
|
d.ten_J,
|
||||||
|
d.njmax,
|
||||||
refsafe,
|
refsafe,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
@@ -1700,11 +1744,11 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
m.jnt_solimp,
|
m.jnt_solimp,
|
||||||
m.jnt_range,
|
m.jnt_range,
|
||||||
m.jnt_margin,
|
m.jnt_margin,
|
||||||
m.jnt_limited_ball_adr,
|
|
||||||
m.dof_invweight0,
|
m.dof_invweight0,
|
||||||
d.njmax,
|
m.jnt_limited_ball_adr,
|
||||||
d.qpos,
|
d.qpos,
|
||||||
d.qvel,
|
d.qvel,
|
||||||
|
d.njmax,
|
||||||
refsafe,
|
refsafe,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
@@ -1734,11 +1778,11 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
m.jnt_solimp,
|
m.jnt_solimp,
|
||||||
m.jnt_range,
|
m.jnt_range,
|
||||||
m.jnt_margin,
|
m.jnt_margin,
|
||||||
m.jnt_limited_slide_hinge_adr,
|
|
||||||
m.dof_invweight0,
|
m.dof_invweight0,
|
||||||
d.njmax,
|
m.jnt_limited_slide_hinge_adr,
|
||||||
d.qpos,
|
d.qpos,
|
||||||
d.qvel,
|
d.qvel,
|
||||||
|
d.njmax,
|
||||||
refsafe,
|
refsafe,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
@@ -1765,18 +1809,18 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
m.jnt_dofadr,
|
m.jnt_dofadr,
|
||||||
m.tendon_adr,
|
m.tendon_adr,
|
||||||
m.tendon_num,
|
m.tendon_num,
|
||||||
m.tendon_limited_adr,
|
|
||||||
m.tendon_solref_lim,
|
m.tendon_solref_lim,
|
||||||
m.tendon_solimp_lim,
|
m.tendon_solimp_lim,
|
||||||
m.tendon_range,
|
m.tendon_range,
|
||||||
m.tendon_margin,
|
m.tendon_margin,
|
||||||
m.tendon_invweight0,
|
m.tendon_invweight0,
|
||||||
m.wrap_objid,
|
|
||||||
m.wrap_type,
|
m.wrap_type,
|
||||||
d.njmax,
|
m.wrap_objid,
|
||||||
|
m.tendon_limited_adr,
|
||||||
d.qvel,
|
d.qvel,
|
||||||
d.ten_length,
|
|
||||||
d.ten_J,
|
d.ten_J,
|
||||||
|
d.ten_length,
|
||||||
|
d.njmax,
|
||||||
refsafe,
|
refsafe,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
@@ -1809,11 +1853,11 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
m.body_invweight0,
|
m.body_invweight0,
|
||||||
m.dof_bodyid,
|
m.dof_bodyid,
|
||||||
m.geom_bodyid,
|
m.geom_bodyid,
|
||||||
d.njmax,
|
|
||||||
d.nacon,
|
|
||||||
d.qvel,
|
d.qvel,
|
||||||
d.subtree_com,
|
d.subtree_com,
|
||||||
d.cdof,
|
d.cdof,
|
||||||
|
d.njmax,
|
||||||
|
d.nacon,
|
||||||
refsafe,
|
refsafe,
|
||||||
d.contact.dist,
|
d.contact.dist,
|
||||||
d.contact.dim,
|
d.contact.dim,
|
||||||
@@ -1825,6 +1869,7 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
d.contact.friction,
|
d.contact.friction,
|
||||||
d.contact.solref,
|
d.contact.solref,
|
||||||
d.contact.solimp,
|
d.contact.solimp,
|
||||||
|
d.contact.type,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
d.nefc,
|
d.nefc,
|
||||||
@@ -1853,11 +1898,11 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
m.body_invweight0,
|
m.body_invweight0,
|
||||||
m.dof_bodyid,
|
m.dof_bodyid,
|
||||||
m.geom_bodyid,
|
m.geom_bodyid,
|
||||||
d.njmax,
|
|
||||||
d.nacon,
|
|
||||||
d.qvel,
|
d.qvel,
|
||||||
d.subtree_com,
|
d.subtree_com,
|
||||||
d.cdof,
|
d.cdof,
|
||||||
|
d.njmax,
|
||||||
|
d.nacon,
|
||||||
refsafe,
|
refsafe,
|
||||||
d.contact.dist,
|
d.contact.dist,
|
||||||
d.contact.dim,
|
d.contact.dim,
|
||||||
@@ -1870,6 +1915,7 @@ def make_constraint(m: types.Model, d: types.Data):
|
|||||||
d.contact.solref,
|
d.contact.solref,
|
||||||
d.contact.solreffriction,
|
d.contact.solreffriction,
|
||||||
d.contact.solimp,
|
d.contact.solimp,
|
||||||
|
d.contact.type,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
d.nefc,
|
d.nefc,
|
||||||
|
|||||||
+28
-31
@@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
import warp as wp
|
import warp as wp
|
||||||
|
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.support import mul_m
|
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import BiasType
|
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 Data
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import DisableBit
|
from mujoco.mjx.third_party.mujoco_warp._src.types import DisableBit
|
||||||
@@ -52,8 +51,8 @@ def _qderiv_actuator_passive(
|
|||||||
# In:
|
# In:
|
||||||
qMi: wp.array(dtype=int),
|
qMi: wp.array(dtype=int),
|
||||||
qMj: wp.array(dtype=int),
|
qMj: wp.array(dtype=int),
|
||||||
# Data out:
|
# Out:
|
||||||
qM_integration_out: wp.array3d(dtype=float),
|
qDeriv_out: wp.array3d(dtype=float),
|
||||||
):
|
):
|
||||||
worldid, elemid = wp.tid()
|
worldid, elemid = wp.tid()
|
||||||
|
|
||||||
@@ -62,14 +61,17 @@ def _qderiv_actuator_passive(
|
|||||||
|
|
||||||
qderiv = float(0.0)
|
qderiv = float(0.0)
|
||||||
if not opt_disableflags & DisableBit.ACTUATION:
|
if not opt_disableflags & DisableBit.ACTUATION:
|
||||||
|
actuator_gainprm_id = worldid % actuator_gainprm.shape[0]
|
||||||
|
actuator_biasprm_id = worldid % actuator_biasprm.shape[0]
|
||||||
|
|
||||||
for actid in range(nu):
|
for actid in range(nu):
|
||||||
if actuator_gaintype[actid] == GainType.AFFINE:
|
if actuator_gaintype[actid] == GainType.AFFINE:
|
||||||
gain = actuator_gainprm[worldid, actid][2]
|
gain = actuator_gainprm[actuator_gainprm_id, actid][2]
|
||||||
else:
|
else:
|
||||||
gain = 0.0
|
gain = 0.0
|
||||||
|
|
||||||
if actuator_biastype[actid] == BiasType.AFFINE:
|
if actuator_biastype[actid] == BiasType.AFFINE:
|
||||||
bias = actuator_biasprm[worldid, actid][2]
|
bias = actuator_biasprm[actuator_biasprm_id, actid][2]
|
||||||
else:
|
else:
|
||||||
bias = 0.0
|
bias = 0.0
|
||||||
|
|
||||||
@@ -85,17 +87,17 @@ def _qderiv_actuator_passive(
|
|||||||
# TODO(team): fluid model derivative
|
# TODO(team): fluid model derivative
|
||||||
|
|
||||||
if not opt_disableflags & DisableBit.DAMPER and dofiid == dofjid:
|
if not opt_disableflags & DisableBit.DAMPER and dofiid == dofjid:
|
||||||
qderiv -= dof_damping[worldid, dofiid]
|
qderiv -= dof_damping[worldid % dof_damping.shape[0], dofiid]
|
||||||
|
|
||||||
qderiv *= opt_timestep[worldid]
|
qderiv *= opt_timestep[worldid % opt_timestep.shape[0]]
|
||||||
|
|
||||||
if opt_is_sparse:
|
if opt_is_sparse:
|
||||||
qM_integration_out[worldid, 0, elemid] = qM_in[worldid, 0, elemid] - qderiv
|
qDeriv_out[worldid, 0, elemid] = qM_in[worldid, 0, elemid] - qderiv
|
||||||
else:
|
else:
|
||||||
qM = qM_in[worldid, dofiid, dofjid] - qderiv
|
qM = qM_in[worldid, dofiid, dofjid] - qderiv
|
||||||
qM_integration_out[worldid, dofiid, dofjid] = qM
|
qDeriv_out[worldid, dofiid, dofjid] = qM
|
||||||
if dofiid != dofjid:
|
if dofiid != dofjid:
|
||||||
qM_integration_out[worldid, dofjid, dofiid] = qM
|
qDeriv_out[worldid, dofjid, dofiid] = qM
|
||||||
|
|
||||||
|
|
||||||
# TODO(team): improve performance with tile operations?
|
# TODO(team): improve performance with tile operations?
|
||||||
@@ -111,35 +113,36 @@ def _qderiv_tendon_damping(
|
|||||||
# In:
|
# In:
|
||||||
qMi: wp.array(dtype=int),
|
qMi: wp.array(dtype=int),
|
||||||
qMj: wp.array(dtype=int),
|
qMj: wp.array(dtype=int),
|
||||||
# Data out:
|
# Out:
|
||||||
qM_integration_out: wp.array3d(dtype=float),
|
qDeriv_out: wp.array3d(dtype=float),
|
||||||
):
|
):
|
||||||
worldid, elemid = wp.tid()
|
worldid, elemid = wp.tid()
|
||||||
dofiid = qMi[elemid]
|
dofiid = qMi[elemid]
|
||||||
dofjid = qMj[elemid]
|
dofjid = qMj[elemid]
|
||||||
|
|
||||||
qderiv = float(0.0)
|
qderiv = float(0.0)
|
||||||
|
tendon_damping_id = worldid % tendon_damping.shape[0]
|
||||||
for tenid in range(ntendon):
|
for tenid in range(ntendon):
|
||||||
qderiv -= ten_J_in[worldid, tenid, dofiid] * ten_J_in[worldid, tenid, dofjid] * tendon_damping[worldid, tenid]
|
qderiv -= ten_J_in[worldid, tenid, dofiid] * ten_J_in[worldid, tenid, dofjid] * tendon_damping[tendon_damping_id, tenid]
|
||||||
qderiv *= opt_timestep[worldid]
|
|
||||||
|
qderiv *= opt_timestep[worldid % opt_timestep.shape[0]]
|
||||||
|
|
||||||
if opt_is_sparse:
|
if opt_is_sparse:
|
||||||
qM_integration_out[worldid, 0, elemid] -= qderiv
|
qDeriv_out[worldid, 0, elemid] -= qderiv
|
||||||
else:
|
else:
|
||||||
qM_integration_out[worldid, dofiid, dofjid] -= qderiv
|
qDeriv_out[worldid, dofiid, dofjid] -= qderiv
|
||||||
if dofiid != dofjid:
|
if dofiid != dofjid:
|
||||||
qM_integration_out[worldid, dofjid, dofiid] -= qderiv
|
qDeriv_out[worldid, dofjid, dofiid] -= qderiv
|
||||||
|
|
||||||
|
|
||||||
@event_scope
|
@event_scope
|
||||||
def deriv_smooth_vel(m: Model, d: Data, flg_forward: bool = True):
|
def deriv_smooth_vel(m: Model, d: Data, qDeriv: wp.array2d(dtype=float)):
|
||||||
"""Analytical derivative of smooth forces w.r.t. velocities.
|
"""Analytical derivative of smooth forces w.r.t. velocities.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
m (Model): The model containing kinematic and dynamic information (device).
|
m: The model containing kinematic and dynamic information (device).
|
||||||
d (Data): The data object containing the current state and output arrays (device).
|
d: The data object containing the current state and output arrays (device).
|
||||||
flg_forward (bool, optional): If True forward dynamics else inverse dynamics routine.
|
qDeriv: Analytical derivative of smooth forces w.r.t. velocity.
|
||||||
Default is True.
|
|
||||||
"""
|
"""
|
||||||
qMi = m.qM_fullm_i if m.opt.is_sparse else m.dof_tri_row
|
qMi = m.qM_fullm_i if m.opt.is_sparse else m.dof_tri_row
|
||||||
qMj = m.qM_fullm_j if m.opt.is_sparse else m.dof_tri_col
|
qMj = m.qM_fullm_j if m.opt.is_sparse else m.dof_tri_col
|
||||||
@@ -168,24 +171,18 @@ def deriv_smooth_vel(m: Model, d: Data, flg_forward: bool = True):
|
|||||||
qMi,
|
qMi,
|
||||||
qMj,
|
qMj,
|
||||||
],
|
],
|
||||||
outputs=[d.qM_integration],
|
outputs=[qDeriv],
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# TODO(team): directly utilize qM for these settings
|
# TODO(team): directly utilize qM for these settings
|
||||||
wp.copy(d.qM_integration, d.qM)
|
wp.copy(qDeriv, d.qM)
|
||||||
|
|
||||||
if not m.opt.disableflags & DisableBit.DAMPER:
|
if not m.opt.disableflags & DisableBit.DAMPER:
|
||||||
wp.launch(
|
wp.launch(
|
||||||
_qderiv_tendon_damping,
|
_qderiv_tendon_damping,
|
||||||
dim=(d.nworld, qMi.size),
|
dim=(d.nworld, qMi.size),
|
||||||
inputs=[m.ntendon, m.opt.timestep, m.opt.is_sparse, m.tendon_damping, d.ten_J, qMi, qMj],
|
inputs=[m.ntendon, m.opt.timestep, m.opt.is_sparse, m.tendon_damping, d.ten_J, qMi, qMj],
|
||||||
outputs=[d.qM_integration],
|
outputs=[qDeriv],
|
||||||
)
|
)
|
||||||
|
|
||||||
if flg_forward:
|
|
||||||
wp.copy(d.qfrc_integration, d.efc.Ma)
|
|
||||||
else:
|
|
||||||
# qfrc = qM @ qacc
|
|
||||||
mul_m(m, d, d.qfrc_integration, d.qacc, d.inverse_mul_m_skip, d.qM_integration)
|
|
||||||
|
|
||||||
# TODO(team): rne derivative
|
# TODO(team): rne derivative
|
||||||
|
|||||||
+128
-118
@@ -71,7 +71,7 @@ def _next_position(
|
|||||||
qpos_out: wp.array2d(dtype=float),
|
qpos_out: wp.array2d(dtype=float),
|
||||||
):
|
):
|
||||||
worldid, jntid = wp.tid()
|
worldid, jntid = wp.tid()
|
||||||
timestep = opt_timestep[worldid]
|
timestep = opt_timestep[worldid % opt_timestep.shape[0]]
|
||||||
|
|
||||||
jnttype = jnt_type[jntid]
|
jnttype = jnt_type[jntid]
|
||||||
qpos_adr = jnt_qposadr[jntid]
|
qpos_adr = jnt_qposadr[jntid]
|
||||||
@@ -137,7 +137,7 @@ def _next_velocity(
|
|||||||
qvel_out: wp.array2d(dtype=float),
|
qvel_out: wp.array2d(dtype=float),
|
||||||
):
|
):
|
||||||
worldid, dofid = wp.tid()
|
worldid, dofid = wp.tid()
|
||||||
timestep = opt_timestep[worldid]
|
timestep = opt_timestep[worldid % opt_timestep.shape[0]]
|
||||||
qvel_out[worldid, dofid] = qvel_in[worldid, dofid] + qacc_scale_in * qacc_in[worldid, dofid] * timestep
|
qvel_out[worldid, dofid] = qvel_in[worldid, dofid] + qacc_scale_in * qacc_in[worldid, dofid] * timestep
|
||||||
|
|
||||||
|
|
||||||
@@ -188,11 +188,14 @@ def _next_activation(
|
|||||||
act_out: wp.array2d(dtype=float),
|
act_out: wp.array2d(dtype=float),
|
||||||
):
|
):
|
||||||
worldid, actid = wp.tid()
|
worldid, actid = 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(
|
act = _next_act(
|
||||||
opt_timestep[worldid],
|
opt_timestep[opt_timestep_id],
|
||||||
actuator_dyntype[actid],
|
actuator_dyntype[actid],
|
||||||
actuator_dynprm[worldid, actid],
|
actuator_dynprm[actuator_dynprm_id, actid],
|
||||||
actuator_actrange[worldid, actid],
|
actuator_actrange[actuator_actrange_id, actid],
|
||||||
act_in[worldid, actid],
|
act_in[worldid, actid],
|
||||||
act_dot_in[worldid, actid],
|
act_dot_in[worldid, actid],
|
||||||
act_dot_scale,
|
act_dot_scale,
|
||||||
@@ -206,18 +209,18 @@ def _next_time(
|
|||||||
# Model:
|
# Model:
|
||||||
opt_timestep: wp.array(dtype=float),
|
opt_timestep: wp.array(dtype=float),
|
||||||
# Data in:
|
# Data in:
|
||||||
|
nefc_in: wp.array(dtype=int),
|
||||||
|
time_in: wp.array(dtype=float),
|
||||||
nworld_in: int,
|
nworld_in: int,
|
||||||
naconmax_in: int,
|
naconmax_in: int,
|
||||||
njmax_in: int,
|
njmax_in: int,
|
||||||
nacon_in: wp.array(dtype=int),
|
nacon_in: wp.array(dtype=int),
|
||||||
nefc_in: wp.array(dtype=int),
|
|
||||||
time_in: wp.array(dtype=float),
|
|
||||||
ncollision_in: wp.array(dtype=int),
|
ncollision_in: wp.array(dtype=int),
|
||||||
# Data out:
|
# Data out:
|
||||||
time_out: wp.array(dtype=float),
|
time_out: wp.array(dtype=float),
|
||||||
):
|
):
|
||||||
worldid = wp.tid()
|
worldid = wp.tid()
|
||||||
time_out[worldid] = time_in[worldid] + opt_timestep[worldid]
|
time_out[worldid] = time_in[worldid] + opt_timestep[worldid % opt_timestep.shape[0]]
|
||||||
nefc = nefc_in[worldid]
|
nefc = nefc_in[worldid]
|
||||||
|
|
||||||
if nefc > njmax_in:
|
if nefc > njmax_in:
|
||||||
@@ -227,16 +230,15 @@ def _next_time(
|
|||||||
ncollision = ncollision_in[0]
|
ncollision = ncollision_in[0]
|
||||||
if ncollision > naconmax_in:
|
if ncollision > naconmax_in:
|
||||||
nconmax = int(wp.ceil(float(ncollision) / float(nworld_in)))
|
nconmax = int(wp.ceil(float(ncollision) / float(nworld_in)))
|
||||||
wp.printf("ncollision overflow - please increase nconmax to %u\n", nconmax)
|
wp.printf("broadphase overflow - please increase nconmax to %u or naconmax to %u\n", nconmax, ncollision)
|
||||||
|
|
||||||
if nacon_in[0] > naconmax_in:
|
if nacon_in[0] > naconmax_in:
|
||||||
nconmax = int(wp.ceil(float(ncollision) / float(nworld_in)))
|
nconmax = int(wp.ceil(float(nacon_in[0]) / float(nworld_in)))
|
||||||
wp.printf("nacon overflow - please increase nconmax to %u\n", nconmax)
|
wp.printf("narrowphase overflow - please increase nconmax to %u or naconmax to %u\n", nconmax, nacon_in[0])
|
||||||
|
|
||||||
|
|
||||||
def _advance(m: Model, d: Data, qacc: wp.array, qvel: Optional[wp.array] = None):
|
def _advance(m: Model, d: Data, qacc: wp.array, qvel: Optional[wp.array] = None):
|
||||||
"""Advance state and time given activation derivatives and acceleration."""
|
"""Advance state and time given activation derivatives and acceleration."""
|
||||||
|
|
||||||
# TODO(team): can we assume static timesteps?
|
# TODO(team): can we assume static timesteps?
|
||||||
|
|
||||||
# advance activations
|
# advance activations
|
||||||
@@ -302,12 +304,12 @@ def _advance(m: Model, d: Data, qacc: wp.array, qvel: Optional[wp.array] = None)
|
|||||||
dim=(d.nworld,),
|
dim=(d.nworld,),
|
||||||
inputs=[
|
inputs=[
|
||||||
m.opt.timestep,
|
m.opt.timestep,
|
||||||
|
d.nefc,
|
||||||
|
d.time,
|
||||||
d.nworld,
|
d.nworld,
|
||||||
d.naconmax,
|
d.naconmax,
|
||||||
d.njmax,
|
d.njmax,
|
||||||
d.nacon,
|
d.nacon,
|
||||||
d.nefc,
|
|
||||||
d.time,
|
|
||||||
d.ncollision,
|
d.ncollision,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
@@ -324,41 +326,16 @@ def _euler_damp_qfrc_sparse(
|
|||||||
opt_timestep: wp.array(dtype=float),
|
opt_timestep: wp.array(dtype=float),
|
||||||
dof_Madr: wp.array(dtype=int),
|
dof_Madr: wp.array(dtype=int),
|
||||||
dof_damping: wp.array2d(dtype=float),
|
dof_damping: wp.array2d(dtype=float),
|
||||||
# Data out:
|
# Out:
|
||||||
qM_integration_out: wp.array3d(dtype=float),
|
qM_integration_out: wp.array3d(dtype=float),
|
||||||
):
|
):
|
||||||
worldid, tid = wp.tid()
|
worldid, tid = wp.tid()
|
||||||
timestep = opt_timestep[worldid]
|
timestep = opt_timestep[worldid % opt_timestep.shape[0]]
|
||||||
|
|
||||||
adr = dof_Madr[tid]
|
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, tid]
|
||||||
|
|
||||||
|
|
||||||
def _euler_sparse(m: Model, d: Data):
|
|
||||||
wp.copy(d.qM_integration, d.qM)
|
|
||||||
wp.launch(
|
|
||||||
_euler_damp_qfrc_sparse,
|
|
||||||
dim=(d.nworld, m.nv),
|
|
||||||
inputs=[
|
|
||||||
m.opt.timestep,
|
|
||||||
m.dof_Madr,
|
|
||||||
m.dof_damping,
|
|
||||||
],
|
|
||||||
outputs=[
|
|
||||||
d.qM_integration,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
smooth.factor_solve_i(
|
|
||||||
m,
|
|
||||||
d,
|
|
||||||
d.qM_integration,
|
|
||||||
d.qLD_integration,
|
|
||||||
d.qLDiagInv_integration,
|
|
||||||
d.qacc_integration,
|
|
||||||
d.efc.Ma,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@cache_kernel
|
@cache_kernel
|
||||||
def _tile_euler_dense(tile: TileSet):
|
def _tile_euler_dense(tile: TileSet):
|
||||||
@nested_kernel(module="unique", enable_backward=False)
|
@nested_kernel(module="unique", enable_backward=False)
|
||||||
@@ -371,23 +348,23 @@ def _tile_euler_dense(tile: TileSet):
|
|||||||
efc_Ma_in: wp.array2d(dtype=float),
|
efc_Ma_in: wp.array2d(dtype=float),
|
||||||
# In:
|
# In:
|
||||||
adr_in: wp.array(dtype=int),
|
adr_in: wp.array(dtype=int),
|
||||||
# Data out:
|
# Out:
|
||||||
qacc_integration_out: wp.array2d(dtype=float),
|
qacc_out: wp.array2d(dtype=float),
|
||||||
):
|
):
|
||||||
worldid, nodeid = wp.tid()
|
worldid, nodeid = wp.tid()
|
||||||
timestep = opt_timestep[worldid]
|
timestep = opt_timestep[worldid % opt_timestep.shape[0]]
|
||||||
TILE_SIZE = wp.static(tile.size)
|
TILE_SIZE = wp.static(tile.size)
|
||||||
|
|
||||||
dofid = adr_in[nodeid]
|
dofid = adr_in[nodeid]
|
||||||
M_tile = wp.tile_load(qM_in[worldid], shape=(TILE_SIZE, TILE_SIZE), offset=(dofid, dofid))
|
M_tile = wp.tile_load(qM_in[worldid], shape=(TILE_SIZE, TILE_SIZE), offset=(dofid, dofid))
|
||||||
damping_tile = wp.tile_load(dof_damping[worldid], shape=(TILE_SIZE,), offset=(dofid,))
|
damping_tile = wp.tile_load(dof_damping[worldid % dof_damping.shape[0]], shape=(TILE_SIZE,), offset=(dofid,))
|
||||||
damping_scaled = damping_tile * timestep
|
damping_scaled = damping_tile * timestep
|
||||||
qm_integration_tile = wp.tile_diag_add(M_tile, damping_scaled)
|
qm_integration_tile = wp.tile_diag_add(M_tile, damping_scaled)
|
||||||
|
|
||||||
Ma_tile = wp.tile_load(efc_Ma_in[worldid], shape=(TILE_SIZE,), offset=(dofid,))
|
Ma_tile = wp.tile_load(efc_Ma_in[worldid], shape=(TILE_SIZE,), offset=(dofid,))
|
||||||
L_tile = wp.tile_cholesky(qm_integration_tile)
|
L_tile = wp.tile_cholesky(qm_integration_tile)
|
||||||
qacc_integration_tile = wp.tile_cholesky_solve(L_tile, Ma_tile)
|
qacc_tile = wp.tile_cholesky_solve(L_tile, Ma_tile)
|
||||||
wp.tile_store(qacc_integration_out[worldid], qacc_integration_tile, offset=(dofid))
|
wp.tile_store(qacc_out[worldid], qacc_tile, offset=(dofid))
|
||||||
|
|
||||||
return euler_dense
|
return euler_dense
|
||||||
|
|
||||||
@@ -395,32 +372,47 @@ def _tile_euler_dense(tile: TileSet):
|
|||||||
@event_scope
|
@event_scope
|
||||||
def euler(m: Model, d: Data):
|
def euler(m: Model, d: Data):
|
||||||
"""Euler integrator, semi-implicit in velocity."""
|
"""Euler integrator, semi-implicit in velocity."""
|
||||||
|
|
||||||
# integrate damping implicitly
|
# integrate damping implicitly
|
||||||
if not m.opt.disableflags & (DisableBit.EULERDAMP | DisableBit.DAMPER):
|
if not m.opt.disableflags & (DisableBit.EULERDAMP | DisableBit.DAMPER):
|
||||||
|
qacc = wp.empty((d.nworld, m.nv), dtype=float)
|
||||||
if m.opt.is_sparse:
|
if m.opt.is_sparse:
|
||||||
_euler_sparse(m, d)
|
qM = wp.clone(d.qM)
|
||||||
|
qLD = wp.empty((d.nworld, 1, m.nC), dtype=float)
|
||||||
|
qLDiagInv = wp.empty((d.nworld, m.nv), dtype=float)
|
||||||
|
wp.launch(
|
||||||
|
_euler_damp_qfrc_sparse,
|
||||||
|
dim=(d.nworld, m.nv),
|
||||||
|
inputs=[m.opt.timestep, m.dof_Madr, m.dof_damping],
|
||||||
|
outputs=[qM],
|
||||||
|
)
|
||||||
|
smooth.factor_solve_i(m, d, qM, qLD, qLDiagInv, qacc, d.efc.Ma)
|
||||||
else:
|
else:
|
||||||
for tile in m.qM_tiles:
|
for tile in m.qM_tiles:
|
||||||
wp.launch_tiled(
|
wp.launch_tiled(
|
||||||
_tile_euler_dense(tile),
|
_tile_euler_dense(tile),
|
||||||
dim=(d.nworld, tile.adr.size),
|
dim=(d.nworld, tile.adr.size),
|
||||||
inputs=[m.dof_damping, m.opt.timestep, d.qM, d.efc.Ma, tile.adr],
|
inputs=[m.dof_damping, m.opt.timestep, d.qM, d.efc.Ma, tile.adr],
|
||||||
outputs=[d.qacc_integration],
|
outputs=[qacc],
|
||||||
block_dim=m.block_dim.euler_dense,
|
block_dim=m.block_dim.euler_dense,
|
||||||
)
|
)
|
||||||
|
_advance(m, d, qacc)
|
||||||
_advance(m, d, d.qacc_integration)
|
|
||||||
else:
|
else:
|
||||||
_advance(m, d, d.qacc)
|
_advance(m, d, d.qacc)
|
||||||
|
|
||||||
|
|
||||||
def _rk_perturb_state(m: Model, d: Data, scale: float):
|
def _rk_perturb_state(
|
||||||
|
m: Model,
|
||||||
|
d: Data,
|
||||||
|
scale: float,
|
||||||
|
qpos_t0: wp.array2d(dtype=float),
|
||||||
|
qvel_t0: wp.array2d(dtype=float),
|
||||||
|
act_t0: Optional[wp.array] = None,
|
||||||
|
):
|
||||||
# position
|
# position
|
||||||
wp.launch(
|
wp.launch(
|
||||||
_next_position,
|
_next_position,
|
||||||
dim=(d.nworld, m.njnt),
|
dim=(d.nworld, m.njnt),
|
||||||
inputs=[m.opt.timestep, m.jnt_type, m.jnt_qposadr, m.jnt_dofadr, d.qpos_t0, d.qvel, scale],
|
inputs=[m.opt.timestep, m.jnt_type, m.jnt_qposadr, m.jnt_dofadr, qpos_t0, d.qvel, scale],
|
||||||
outputs=[d.qpos],
|
outputs=[d.qpos],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -428,16 +420,16 @@ def _rk_perturb_state(m: Model, d: Data, scale: float):
|
|||||||
wp.launch(
|
wp.launch(
|
||||||
_next_velocity,
|
_next_velocity,
|
||||||
dim=(d.nworld, m.nv),
|
dim=(d.nworld, m.nv),
|
||||||
inputs=[m.opt.timestep, d.qvel_t0, d.qacc, scale],
|
inputs=[m.opt.timestep, qvel_t0, d.qacc, scale],
|
||||||
outputs=[d.qvel],
|
outputs=[d.qvel],
|
||||||
)
|
)
|
||||||
|
|
||||||
# activation
|
# activation
|
||||||
if m.na:
|
if m.na and act_t0 is not None:
|
||||||
wp.launch(
|
wp.launch(
|
||||||
_next_activation,
|
_next_activation,
|
||||||
dim=(d.nworld, m.na),
|
dim=(d.nworld, m.na),
|
||||||
inputs=[m.opt.timestep, d.act_t0, d.act_dot, scale, False],
|
inputs=[m.opt.timestep, act_t0, d.act_dot, scale, False],
|
||||||
outputs=[d.act],
|
outputs=[d.act],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -471,73 +463,94 @@ def _rk_accumulate_activation_velocity(
|
|||||||
act_dot_out[worldid, actid] += scale * act_dot_in[worldid, actid]
|
act_dot_out[worldid, actid] += scale * act_dot_in[worldid, actid]
|
||||||
|
|
||||||
|
|
||||||
def _rk_accumulate(m: Model, d: Data, scale: float):
|
def _rk_accumulate(
|
||||||
"""Computes one term of 1/6 k_1 + 1/3 k_2 + 1/3 k_3 + 1/6 k_4"""
|
m: Model,
|
||||||
|
d: Data,
|
||||||
|
scale: float,
|
||||||
|
qvel_rk: wp.array2d(dtype=float),
|
||||||
|
qacc_rk: wp.array2d(dtype=float),
|
||||||
|
act_dot_rk: Optional[wp.array] = None,
|
||||||
|
):
|
||||||
|
"""Computes one term of 1/6 k_1 + 1/3 k_2 + 1/3 k_3 + 1/6 k_4."""
|
||||||
wp.launch(
|
wp.launch(
|
||||||
_rk_accumulate_velocity_acceleration,
|
_rk_accumulate_velocity_acceleration,
|
||||||
dim=(d.nworld, m.nv),
|
dim=(d.nworld, m.nv),
|
||||||
inputs=[d.qvel, d.qacc, scale],
|
inputs=[d.qvel, d.qacc, scale],
|
||||||
outputs=[d.qvel_rk, d.qacc_rk],
|
outputs=[qvel_rk, qacc_rk],
|
||||||
)
|
)
|
||||||
|
|
||||||
if m.na:
|
if m.na and act_dot_rk is not None:
|
||||||
wp.launch(
|
wp.launch(
|
||||||
_rk_accumulate_activation_velocity,
|
_rk_accumulate_activation_velocity,
|
||||||
dim=(d.nworld, m.na),
|
dim=(d.nworld, m.na),
|
||||||
inputs=[d.act_dot, scale],
|
inputs=[d.act_dot, scale],
|
||||||
outputs=[d.act_dot_rk],
|
outputs=[act_dot_rk],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@event_scope
|
@event_scope
|
||||||
def rungekutta4(m: Model, d: Data):
|
def rungekutta4(m: Model, d: Data):
|
||||||
"""Runge-Kutta explicit order 4 integrator."""
|
"""Runge-Kutta explicit order 4 integrator."""
|
||||||
|
qpos_t0 = wp.clone(d.qpos)
|
||||||
wp.copy(d.qpos_t0, d.qpos)
|
qvel_t0 = wp.clone(d.qvel)
|
||||||
wp.copy(d.qvel_t0, d.qvel)
|
qvel_rk = wp.zeros((d.nworld, m.nv), dtype=float)
|
||||||
|
qacc_rk = wp.zeros((d.nworld, m.nv), dtype=float)
|
||||||
d.qvel_rk.zero_()
|
|
||||||
d.qacc_rk.zero_()
|
|
||||||
d.act_dot_rk.zero_()
|
|
||||||
|
|
||||||
if m.na:
|
if m.na:
|
||||||
wp.copy(d.act_t0, d.act)
|
act_t0 = wp.clone(d.act)
|
||||||
|
act_dot_rk = wp.zeros((d.nworld, m.na), dtype=float)
|
||||||
|
else:
|
||||||
|
act_t0 = None
|
||||||
|
act_dot_rk = None
|
||||||
|
|
||||||
A, B = _RK4_A, _RK4_B
|
A, B = _RK4_A, _RK4_B
|
||||||
|
|
||||||
_rk_accumulate(m, d, B[0])
|
_rk_accumulate(m, d, B[0], qvel_rk, qacc_rk, act_dot_rk)
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
a, b = float(A[i][i]), B[i + 1]
|
a, b = float(A[i][i]), B[i + 1]
|
||||||
_rk_perturb_state(m, d, a)
|
_rk_perturb_state(m, d, a, qpos_t0, qvel_t0, act_t0)
|
||||||
forward(m, d)
|
forward(m, d)
|
||||||
_rk_accumulate(m, d, b)
|
_rk_accumulate(m, d, b, qvel_rk, qacc_rk, act_dot_rk)
|
||||||
|
|
||||||
|
wp.copy(d.qpos, qpos_t0)
|
||||||
|
wp.copy(d.qvel, qvel_t0)
|
||||||
|
|
||||||
wp.copy(d.qpos, d.qpos_t0)
|
|
||||||
wp.copy(d.qvel, d.qvel_t0)
|
|
||||||
if m.na:
|
if m.na:
|
||||||
wp.copy(d.act, d.act_t0)
|
wp.copy(d.act, act_t0)
|
||||||
wp.copy(d.act_dot, d.act_dot_rk)
|
wp.copy(d.act_dot, act_dot_rk)
|
||||||
_advance(m, d, d.qacc_rk, d.qvel_rk)
|
|
||||||
|
_advance(m, d, qacc_rk, qvel_rk)
|
||||||
|
|
||||||
|
|
||||||
@event_scope
|
@event_scope
|
||||||
def implicit(m: Model, d: Data):
|
def implicit(m: Model, d: Data):
|
||||||
"""Integrates fully implicit in velocity."""
|
"""Integrates fully implicit in velocity."""
|
||||||
if ~(m.opt.disableflags | ~(DisableBit.ACTUATION | DisableBit.SPRING | DisableBit.DAMPER)):
|
if ~(m.opt.disableflags | ~(DisableBit.ACTUATION | DisableBit.SPRING | DisableBit.DAMPER)):
|
||||||
derivative.deriv_smooth_vel(m, d)
|
if m.opt.is_sparse:
|
||||||
smooth.factor_solve_i(
|
qDeriv = wp.empty((d.nworld, 1, m.nM), dtype=float)
|
||||||
m, d, d.qM_integration, d.qLD_integration, d.qLDiagInv_integration, d.qacc_integration, d.qfrc_integration
|
qLD = wp.empty((d.nworld, 1, m.nC), dtype=float)
|
||||||
)
|
else:
|
||||||
_advance(m, d, d.qacc_integration)
|
qDeriv = wp.empty((d.nworld, m.nv, m.nv), dtype=float)
|
||||||
|
qLD = wp.empty((d.nworld, m.nv, m.nv), dtype=float)
|
||||||
|
qLDiagInv = wp.empty((d.nworld, m.nv), dtype=float)
|
||||||
|
derivative.deriv_smooth_vel(m, d, qDeriv)
|
||||||
|
qacc = wp.empty((d.nworld, m.nv), dtype=float)
|
||||||
|
smooth.factor_solve_i(m, d, qDeriv, qLD, qLDiagInv, qacc, d.efc.Ma)
|
||||||
|
_advance(m, d, qacc)
|
||||||
else:
|
else:
|
||||||
_advance(m, d, d.qacc)
|
_advance(m, d, d.qacc)
|
||||||
|
|
||||||
|
|
||||||
@event_scope
|
@event_scope
|
||||||
def fwd_position(m: Model, d: Data, factorize: bool = True):
|
def fwd_position(m: Model, d: Data, factorize: bool = True):
|
||||||
"""Position-dependent computations."""
|
"""Position-dependent computations.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
m: The model containing kinematic and dynamic information.
|
||||||
|
d: The data object containing the current state and output arrays.
|
||||||
|
factorize: Flag to factorize interia matrix.
|
||||||
|
"""
|
||||||
smooth.kinematics(m, d)
|
smooth.kinematics(m, d)
|
||||||
smooth.com_pos(m, d)
|
smooth.com_pos(m, d)
|
||||||
smooth.camlight(m, d)
|
smooth.camlight(m, d)
|
||||||
@@ -625,7 +638,6 @@ def _tendon_velocity(m: Model, d: Data):
|
|||||||
@event_scope
|
@event_scope
|
||||||
def fwd_velocity(m: Model, d: Data):
|
def fwd_velocity(m: Model, d: Data):
|
||||||
"""Velocity-dependent computations."""
|
"""Velocity-dependent computations."""
|
||||||
|
|
||||||
_actuator_velocity(m, d)
|
_actuator_velocity(m, d)
|
||||||
|
|
||||||
if m.ntendon > 0:
|
if m.ntendon > 0:
|
||||||
@@ -673,10 +685,12 @@ def _actuator_force(
|
|||||||
):
|
):
|
||||||
worldid, uid = wp.tid()
|
worldid, uid = wp.tid()
|
||||||
|
|
||||||
|
actuator_ctrlrange_id = worldid % actuator_ctrlrange.shape[0]
|
||||||
|
|
||||||
ctrl = ctrl_in[worldid, uid]
|
ctrl = ctrl_in[worldid, uid]
|
||||||
|
|
||||||
if actuator_ctrllimited[uid] and not dsbl_clampctrl:
|
if actuator_ctrllimited[uid] and not dsbl_clampctrl:
|
||||||
ctrlrange = actuator_ctrlrange[worldid, uid]
|
ctrlrange = actuator_ctrlrange[actuator_ctrlrange_id, uid]
|
||||||
ctrl = wp.clamp(ctrl, ctrlrange[0], ctrlrange[1])
|
ctrl = wp.clamp(ctrl, ctrlrange[0], ctrlrange[1])
|
||||||
ctrl_act = ctrl
|
ctrl_act = ctrl
|
||||||
|
|
||||||
@@ -684,11 +698,11 @@ def _actuator_force(
|
|||||||
if na and act_first >= 0:
|
if na and act_first >= 0:
|
||||||
act_last = act_first + actuator_actnum[uid] - 1
|
act_last = act_first + actuator_actnum[uid] - 1
|
||||||
dyntype = actuator_dyntype[uid]
|
dyntype = actuator_dyntype[uid]
|
||||||
|
dynprm = actuator_dynprm[worldid % actuator_dynprm.shape[0], uid]
|
||||||
|
|
||||||
if dyntype == DynType.INTEGRATOR:
|
if dyntype == DynType.INTEGRATOR:
|
||||||
act_dot = ctrl
|
act_dot = ctrl
|
||||||
elif dyntype == DynType.FILTER or dyntype == DynType.FILTEREXACT:
|
elif dyntype == DynType.FILTER or dyntype == DynType.FILTEREXACT:
|
||||||
dynprm = actuator_dynprm[worldid, uid]
|
|
||||||
act = act_in[worldid, act_last]
|
act = act_in[worldid, act_last]
|
||||||
act_dot = (ctrl - act) / wp.max(dynprm[0], MJ_MINVAL)
|
act_dot = (ctrl - act) / wp.max(dynprm[0], MJ_MINVAL)
|
||||||
elif dyntype == DynType.MUSCLE:
|
elif dyntype == DynType.MUSCLE:
|
||||||
@@ -701,15 +715,16 @@ def _actuator_force(
|
|||||||
act_dot_out[worldid, act_last] = act_dot
|
act_dot_out[worldid, act_last] = act_dot
|
||||||
|
|
||||||
if actuator_actearly[uid]:
|
if actuator_actearly[uid]:
|
||||||
|
opt_timestep_id = worldid % opt_timestep.shape[0]
|
||||||
|
actuator_actrange_id = worldid % actuator_actrange.shape[0]
|
||||||
if dyntype == DynType.INTEGRATOR or dyntype == DynType.NONE:
|
if dyntype == DynType.INTEGRATOR or dyntype == DynType.NONE:
|
||||||
dynprm = actuator_dynprm[worldid, uid]
|
|
||||||
act = act_in[worldid, act_last]
|
act = act_in[worldid, act_last]
|
||||||
|
|
||||||
ctrl_act = _next_act(
|
ctrl_act = _next_act(
|
||||||
opt_timestep[worldid],
|
opt_timestep[opt_timestep_id],
|
||||||
dyntype,
|
dyntype,
|
||||||
dynprm,
|
dynprm,
|
||||||
actuator_actrange[worldid, uid],
|
actuator_actrange[actuator_actrange_id, uid],
|
||||||
act,
|
act,
|
||||||
act_dot,
|
act_dot,
|
||||||
1.0,
|
1.0,
|
||||||
@@ -723,7 +738,7 @@ def _actuator_force(
|
|||||||
|
|
||||||
# gain
|
# gain
|
||||||
gaintype = actuator_gaintype[uid]
|
gaintype = actuator_gaintype[uid]
|
||||||
gainprm = actuator_gainprm[worldid, uid]
|
gainprm = actuator_gainprm[worldid % actuator_gainprm.shape[0], uid]
|
||||||
|
|
||||||
gain = 0.0
|
gain = 0.0
|
||||||
if gaintype == GainType.FIXED:
|
if gaintype == GainType.FIXED:
|
||||||
@@ -737,7 +752,7 @@ def _actuator_force(
|
|||||||
|
|
||||||
# bias
|
# bias
|
||||||
biastype = actuator_biastype[uid]
|
biastype = actuator_biastype[uid]
|
||||||
biasprm = actuator_biasprm[worldid, uid]
|
biasprm = actuator_biasprm[worldid % actuator_biasprm.shape[0], uid]
|
||||||
|
|
||||||
bias = 0.0 # BiasType.NONE
|
bias = 0.0 # BiasType.NONE
|
||||||
if biastype == BiasType.AFFINE:
|
if biastype == BiasType.AFFINE:
|
||||||
@@ -752,7 +767,7 @@ def _actuator_force(
|
|||||||
# TODO(team): tendon total force clamping
|
# TODO(team): tendon total force clamping
|
||||||
|
|
||||||
if actuator_forcelimited[uid]:
|
if actuator_forcelimited[uid]:
|
||||||
forcerange = actuator_forcerange[worldid, uid]
|
forcerange = actuator_forcerange[worldid % actuator_forcerange.shape[0], uid]
|
||||||
force = wp.clamp(force, forcerange[0], forcerange[1])
|
force = wp.clamp(force, forcerange[0], forcerange[1])
|
||||||
|
|
||||||
actuator_force_out[worldid, uid] = force
|
actuator_force_out[worldid, uid] = force
|
||||||
@@ -765,7 +780,7 @@ def _tendon_actuator_force(
|
|||||||
actuator_trnid: wp.array(dtype=wp.vec2i),
|
actuator_trnid: wp.array(dtype=wp.vec2i),
|
||||||
# Data in:
|
# Data in:
|
||||||
actuator_force_in: wp.array2d(dtype=float),
|
actuator_force_in: wp.array2d(dtype=float),
|
||||||
# Data out:
|
# Out:
|
||||||
ten_actfrc_out: wp.array2d(dtype=float),
|
ten_actfrc_out: wp.array2d(dtype=float),
|
||||||
):
|
):
|
||||||
worldid, actid = wp.tid()
|
worldid, actid = wp.tid()
|
||||||
@@ -779,11 +794,11 @@ def _tendon_actuator_force(
|
|||||||
@wp.kernel
|
@wp.kernel
|
||||||
def _tendon_actuator_force_clamp(
|
def _tendon_actuator_force_clamp(
|
||||||
# Model:
|
# Model:
|
||||||
actuator_trntype: wp.array(dtype=int),
|
|
||||||
actuator_trnid: wp.array(dtype=wp.vec2i),
|
|
||||||
tendon_actfrclimited: wp.array(dtype=bool),
|
tendon_actfrclimited: wp.array(dtype=bool),
|
||||||
tendon_actfrcrange: wp.array2d(dtype=wp.vec2),
|
tendon_actfrcrange: wp.array2d(dtype=wp.vec2),
|
||||||
# Data in:
|
actuator_trntype: wp.array(dtype=int),
|
||||||
|
actuator_trnid: wp.array(dtype=wp.vec2i),
|
||||||
|
# In:
|
||||||
ten_actfrc_in: wp.array2d(dtype=float),
|
ten_actfrc_in: wp.array2d(dtype=float),
|
||||||
# Data out:
|
# Data out:
|
||||||
actuator_force_out: wp.array2d(dtype=float),
|
actuator_force_out: wp.array2d(dtype=float),
|
||||||
@@ -794,7 +809,7 @@ def _tendon_actuator_force_clamp(
|
|||||||
tenid = actuator_trnid[actid][0]
|
tenid = actuator_trnid[actid][0]
|
||||||
if tendon_actfrclimited[tenid]:
|
if tendon_actfrclimited[tenid]:
|
||||||
ten_actfrc = ten_actfrc_in[worldid, tenid]
|
ten_actfrc = ten_actfrc_in[worldid, tenid]
|
||||||
actfrcrange = tendon_actfrcrange[worldid, tenid]
|
actfrcrange = tendon_actfrcrange[worldid % tendon_actfrcrange.shape[0], tenid]
|
||||||
|
|
||||||
if ten_actfrc < actfrcrange[0]:
|
if ten_actfrc < actfrcrange[0]:
|
||||||
actuator_force_out[worldid, actid] *= actfrcrange[0] / ten_actfrc
|
actuator_force_out[worldid, actid] *= actfrcrange[0] / ten_actfrc
|
||||||
@@ -808,8 +823,8 @@ def _qfrc_actuator(
|
|||||||
nu: int,
|
nu: int,
|
||||||
ngravcomp: int,
|
ngravcomp: int,
|
||||||
jnt_actfrclimited: wp.array(dtype=bool),
|
jnt_actfrclimited: wp.array(dtype=bool),
|
||||||
jnt_actfrcrange: wp.array2d(dtype=wp.vec2),
|
|
||||||
jnt_actgravcomp: wp.array(dtype=int),
|
jnt_actgravcomp: wp.array(dtype=int),
|
||||||
|
jnt_actfrcrange: wp.array2d(dtype=wp.vec2),
|
||||||
dof_jntid: wp.array(dtype=int),
|
dof_jntid: wp.array(dtype=int),
|
||||||
# Data in:
|
# Data in:
|
||||||
actuator_moment_in: wp.array3d(dtype=float),
|
actuator_moment_in: wp.array3d(dtype=float),
|
||||||
@@ -831,7 +846,7 @@ def _qfrc_actuator(
|
|||||||
qfrc += qfrc_gravcomp_in[worldid, dofid]
|
qfrc += qfrc_gravcomp_in[worldid, dofid]
|
||||||
|
|
||||||
if jnt_actfrclimited[jntid]:
|
if jnt_actfrclimited[jntid]:
|
||||||
frcrange = jnt_actfrcrange[worldid, jntid]
|
frcrange = jnt_actfrcrange[worldid % jnt_actfrcrange.shape[0], jntid]
|
||||||
qfrc = wp.clamp(qfrc, frcrange[0], frcrange[1])
|
qfrc = wp.clamp(qfrc, frcrange[0], frcrange[1])
|
||||||
|
|
||||||
qfrc_actuator_out[worldid, dofid] = qfrc
|
qfrc_actuator_out[worldid, dofid] = qfrc
|
||||||
@@ -878,29 +893,19 @@ def fwd_actuation(m: Model, d: Data):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if m.ntendon:
|
if m.ntendon:
|
||||||
d.ten_actfrc.zero_()
|
# total actuator force at tendon
|
||||||
|
ten_actfrc = wp.zeros((d.nworld, m.ntendon), dtype=float)
|
||||||
wp.launch(
|
wp.launch(
|
||||||
_tendon_actuator_force,
|
_tendon_actuator_force,
|
||||||
dim=(d.nworld, m.nu),
|
dim=(d.nworld, m.nu),
|
||||||
inputs=[
|
inputs=[m.actuator_trntype, m.actuator_trnid, d.actuator_force],
|
||||||
m.actuator_trntype,
|
outputs=[ten_actfrc],
|
||||||
m.actuator_trnid,
|
|
||||||
d.actuator_force,
|
|
||||||
],
|
|
||||||
outputs=[d.ten_actfrc],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
wp.launch(
|
wp.launch(
|
||||||
_tendon_actuator_force_clamp,
|
_tendon_actuator_force_clamp,
|
||||||
dim=(d.nworld, m.nu),
|
dim=(d.nworld, m.nu),
|
||||||
inputs=[
|
inputs=[m.tendon_actfrclimited, m.tendon_actfrcrange, m.actuator_trntype, m.actuator_trnid, ten_actfrc],
|
||||||
m.actuator_trntype,
|
|
||||||
m.actuator_trnid,
|
|
||||||
m.tendon_actfrclimited,
|
|
||||||
m.tendon_actfrcrange,
|
|
||||||
d.ten_actfrc,
|
|
||||||
],
|
|
||||||
outputs=[d.actuator_force],
|
outputs=[d.actuator_force],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -911,8 +916,8 @@ def fwd_actuation(m: Model, d: Data):
|
|||||||
m.nu,
|
m.nu,
|
||||||
m.ngravcomp,
|
m.ngravcomp,
|
||||||
m.jnt_actfrclimited,
|
m.jnt_actfrclimited,
|
||||||
m.jnt_actfrcrange,
|
|
||||||
m.jnt_actgravcomp,
|
m.jnt_actgravcomp,
|
||||||
|
m.jnt_actfrcrange,
|
||||||
m.dof_jntid,
|
m.dof_jntid,
|
||||||
d.actuator_moment,
|
d.actuator_moment,
|
||||||
d.qfrc_gravcomp,
|
d.qfrc_gravcomp,
|
||||||
@@ -943,8 +948,13 @@ def _qfrc_smooth(
|
|||||||
|
|
||||||
@event_scope
|
@event_scope
|
||||||
def fwd_acceleration(m: Model, d: Data, factorize: bool = False):
|
def fwd_acceleration(m: Model, d: Data, factorize: bool = False):
|
||||||
"""Add up all non-constraint forces, compute qacc_smooth."""
|
"""Add up all non-constraint forces, compute qacc_smooth.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
m: The model containing kinematic and dynamic information.
|
||||||
|
d: The data object containing the current state and output arrays.
|
||||||
|
factorize: Flag to factorize inertia matrix.
|
||||||
|
"""
|
||||||
wp.launch(
|
wp.launch(
|
||||||
_qfrc_smooth,
|
_qfrc_smooth,
|
||||||
dim=(d.nworld, m.nv),
|
dim=(d.nworld, m.nv),
|
||||||
|
|||||||
+23
-11
@@ -21,6 +21,7 @@ from mujoco.mjx.third_party.mujoco_warp._src import sensor
|
|||||||
from mujoco.mjx.third_party.mujoco_warp._src import smooth
|
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 solver
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src import support
|
from mujoco.mjx.third_party.mujoco_warp._src import support
|
||||||
|
from mujoco.mjx.third_party.mujoco_warp._src.support import mul_m
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Data
|
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 DisableBit
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import EnableBit
|
from mujoco.mjx.third_party.mujoco_warp._src.types import EnableBit
|
||||||
@@ -41,8 +42,8 @@ def _qfrc_eulerdamp(
|
|||||||
qfrc_out: wp.array2d(dtype=float),
|
qfrc_out: wp.array2d(dtype=float),
|
||||||
):
|
):
|
||||||
worldid, dofid = wp.tid()
|
worldid, dofid = wp.tid()
|
||||||
timestep = opt_timestep[worldid]
|
timestep = opt_timestep[worldid % opt_timestep.shape[0]]
|
||||||
qfrc_out[worldid, dofid] += timestep * dof_damping[worldid, dofid] * qacc_in[worldid, dofid]
|
qfrc_out[worldid, dofid] += timestep * dof_damping[worldid % dof_damping.shape[0], dofid] * qacc_in[worldid, dofid]
|
||||||
|
|
||||||
|
|
||||||
@wp.kernel
|
@wp.kernel
|
||||||
@@ -66,8 +67,15 @@ def _qfrc_inverse(
|
|||||||
qfrc_inverse_out[worldid, dofid] = qfrc_inverse
|
qfrc_inverse_out[worldid, dofid] = qfrc_inverse
|
||||||
|
|
||||||
|
|
||||||
def discrete_acc(m: Model, d: Data, qacc: wp.array2d(dtype=float), qfrc: wp.array2d(dtype=float)):
|
def discrete_acc(m: Model, d: Data, qacc: wp.array2d(dtype=float)):
|
||||||
"""Convert discrete-time qacc to continuous-time qacc."""
|
"""Convert discrete-time qacc to continuous-time qacc.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
m: The model containing kinematic and dynamic information.
|
||||||
|
d: The data object containing the current state and output arrays.
|
||||||
|
qacc: Acceleration.
|
||||||
|
"""
|
||||||
|
qfrc = wp.empty((d.nworld, m.nv), dtype=float)
|
||||||
|
|
||||||
if m.opt.integrator == IntegratorType.RK4:
|
if m.opt.integrator == IntegratorType.RK4:
|
||||||
raise NotImplementedError("discrete inverse dynamics is not supported by RK4 integrator")
|
raise NotImplementedError("discrete inverse dynamics is not supported by RK4 integrator")
|
||||||
@@ -81,7 +89,7 @@ def discrete_acc(m: Model, d: Data, qacc: wp.array2d(dtype=float), qfrc: wp.arra
|
|||||||
# set qfrc = (d.qM + m.opt.timestep * diag(m.dof_damping)) * d.qacc
|
# set qfrc = (d.qM + m.opt.timestep * diag(m.dof_damping)) * d.qacc
|
||||||
|
|
||||||
# d.qM @ d.qacc
|
# d.qM @ d.qacc
|
||||||
support.mul_m(m, d, qfrc, d.qacc, d.inverse_mul_m_skip)
|
support.mul_m(m, d, qfrc, d.qacc)
|
||||||
|
|
||||||
# qfrc += m.opt.timestep * m.dof_damping * d.qacc
|
# qfrc += m.opt.timestep * m.dof_damping * d.qacc
|
||||||
wp.launch(
|
wp.launch(
|
||||||
@@ -91,7 +99,12 @@ def discrete_acc(m: Model, d: Data, qacc: wp.array2d(dtype=float), qfrc: wp.arra
|
|||||||
outputs=[qfrc],
|
outputs=[qfrc],
|
||||||
)
|
)
|
||||||
elif m.opt.integrator == IntegratorType.IMPLICITFAST:
|
elif m.opt.integrator == IntegratorType.IMPLICITFAST:
|
||||||
derivative.deriv_smooth_vel(m, d, flg_forward=False)
|
if m.opt.is_sparse:
|
||||||
|
qDeriv = wp.empty((d.nworld, 1, m.nM), dtype=float)
|
||||||
|
else:
|
||||||
|
qDeriv = wp.empty((d.nworld, m.nv, m.nv), dtype=float)
|
||||||
|
derivative.deriv_smooth_vel(m, d, qDeriv)
|
||||||
|
mul_m(m, d, qfrc, d.qacc, M=qDeriv)
|
||||||
smooth.factor_solve_i(m, d, d.qM, d.qLD, d.qLDiagInv, qacc, qfrc)
|
smooth.factor_solve_i(m, d, d.qM, d.qLD, d.qLDiagInv, qacc, qfrc)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(f"integrator {m.opt.integrator} not implemented.")
|
raise NotImplementedError(f"integrator {m.opt.integrator} not implemented.")
|
||||||
@@ -102,7 +115,6 @@ def discrete_acc(m: Model, d: Data, qacc: wp.array2d(dtype=float), qfrc: wp.arra
|
|||||||
|
|
||||||
def inv_constraint(m: Model, d: Data):
|
def inv_constraint(m: Model, d: Data):
|
||||||
"""Inverse constraint solver."""
|
"""Inverse constraint solver."""
|
||||||
|
|
||||||
# no constraints
|
# no constraints
|
||||||
if d.njmax == 0:
|
if d.njmax == 0:
|
||||||
d.qfrc_constraint.zero_()
|
d.qfrc_constraint.zero_()
|
||||||
@@ -122,15 +134,15 @@ def inverse(m: Model, d: Data):
|
|||||||
invdiscrete = m.opt.enableflags & EnableBit.INVDISCRETE
|
invdiscrete = m.opt.enableflags & EnableBit.INVDISCRETE
|
||||||
if invdiscrete:
|
if invdiscrete:
|
||||||
# save discrete-time qacc and compute continuous-time qacc
|
# save discrete-time qacc and compute continuous-time qacc
|
||||||
wp.copy(d.qacc_discrete, d.qacc)
|
qacc_discrete = wp.clone(d.qacc)
|
||||||
discrete_acc(m, d, d.qacc, d.qfrc_integration)
|
discrete_acc(m, d, d.qacc)
|
||||||
|
|
||||||
inv_constraint(m, d)
|
inv_constraint(m, d)
|
||||||
smooth.rne(m, d)
|
smooth.rne(m, d)
|
||||||
smooth.tendon_bias(m, d, d.qfrc_bias)
|
smooth.tendon_bias(m, d, d.qfrc_bias)
|
||||||
sensor.sensor_acc(m, d)
|
sensor.sensor_acc(m, d)
|
||||||
|
|
||||||
support.mul_m(m, d, d.qfrc_inverse, d.qacc, d.inverse_mul_m_skip)
|
support.mul_m(m, d, d.qfrc_inverse, d.qacc)
|
||||||
|
|
||||||
wp.launch(
|
wp.launch(
|
||||||
_qfrc_inverse,
|
_qfrc_inverse,
|
||||||
@@ -146,4 +158,4 @@ def inverse(m: Model, d: Data):
|
|||||||
|
|
||||||
if invdiscrete:
|
if invdiscrete:
|
||||||
# restore discrete-time qacc
|
# restore discrete-time qacc
|
||||||
wp.copy(d.qacc, d.qacc_discrete)
|
wp.copy(d.qacc, qacc_discrete)
|
||||||
|
|||||||
+754
-978
File diff suppressed because it is too large
Load Diff
@@ -96,7 +96,6 @@ def inert_vec(i: types.vec10, v: wp.spatial_vector) -> wp.spatial_vector:
|
|||||||
@wp.func
|
@wp.func
|
||||||
def motion_cross(u: wp.spatial_vector, v: wp.spatial_vector) -> wp.spatial_vector:
|
def motion_cross(u: wp.spatial_vector, v: wp.spatial_vector) -> wp.spatial_vector:
|
||||||
"""Cross product of two motions."""
|
"""Cross product of two motions."""
|
||||||
|
|
||||||
u0 = wp.vec3(u[0], u[1], u[2])
|
u0 = wp.vec3(u[0], u[1], u[2])
|
||||||
u1 = wp.vec3(u[3], u[4], u[5])
|
u1 = wp.vec3(u[3], u[4], u[5])
|
||||||
v0 = wp.vec3(v[0], v[1], v[2])
|
v0 = wp.vec3(v[0], v[1], v[2])
|
||||||
@@ -111,7 +110,6 @@ def motion_cross(u: wp.spatial_vector, v: wp.spatial_vector) -> wp.spatial_vecto
|
|||||||
@wp.func
|
@wp.func
|
||||||
def motion_cross_force(v: wp.spatial_vector, f: wp.spatial_vector) -> wp.spatial_vector:
|
def motion_cross_force(v: wp.spatial_vector, f: wp.spatial_vector) -> wp.spatial_vector:
|
||||||
"""Cross product of a motion and a force."""
|
"""Cross product of a motion and a force."""
|
||||||
|
|
||||||
v0 = wp.vec3(v[0], v[1], v[2])
|
v0 = wp.vec3(v[0], v[1], v[2])
|
||||||
v1 = wp.vec3(v[3], v[4], v[5])
|
v1 = wp.vec3(v[3], v[4], v[5])
|
||||||
f0 = wp.vec3(f[0], f[1], f[2])
|
f0 = wp.vec3(f[0], f[1], f[2])
|
||||||
@@ -249,7 +247,6 @@ def closest_segment_point_and_dist(a: wp.vec3, b: wp.vec3, pt: wp.vec3) -> Tuple
|
|||||||
@wp.func
|
@wp.func
|
||||||
def closest_segment_to_segment_points(a0: wp.vec3, a1: wp.vec3, b0: wp.vec3, b1: wp.vec3) -> Tuple[wp.vec3, wp.vec3]:
|
def closest_segment_to_segment_points(a0: wp.vec3, a1: wp.vec3, b0: wp.vec3, b1: wp.vec3) -> Tuple[wp.vec3, wp.vec3]:
|
||||||
"""Returns closest points between two line segments."""
|
"""Returns closest points between two line segments."""
|
||||||
|
|
||||||
dir_a, len_a = normalize_with_norm(a1 - a0)
|
dir_a, len_a = normalize_with_norm(a1 - a0)
|
||||||
dir_b, len_b = normalize_with_norm(b1 - b0)
|
dir_b, len_b = normalize_with_norm(b1 - b0)
|
||||||
|
|
||||||
|
|||||||
+41
-42
@@ -86,8 +86,8 @@ def _spring_damper_dof_passive(
|
|||||||
):
|
):
|
||||||
worldid, jntid = wp.tid()
|
worldid, jntid = wp.tid()
|
||||||
dofid = jnt_dofadr[jntid]
|
dofid = jnt_dofadr[jntid]
|
||||||
stiffness = jnt_stiffness[worldid, jntid]
|
stiffness = jnt_stiffness[worldid % jnt_stiffness.shape[0], jntid]
|
||||||
damping = dof_damping[worldid, dofid]
|
damping = dof_damping[worldid % dof_damping.shape[0], dofid]
|
||||||
|
|
||||||
has_stiffness = stiffness != 0.0 and not opt_disableflags & DisableBit.SPRING
|
has_stiffness = stiffness != 0.0 and not opt_disableflags & DisableBit.SPRING
|
||||||
has_damping = damping != 0.0 and not opt_disableflags & DisableBit.DAMPER
|
has_damping = damping != 0.0 and not opt_disableflags & DisableBit.DAMPER
|
||||||
@@ -103,14 +103,15 @@ def _spring_damper_dof_passive(
|
|||||||
|
|
||||||
jnttype = jnt_type[jntid]
|
jnttype = jnt_type[jntid]
|
||||||
qposid = jnt_qposadr[jntid]
|
qposid = jnt_qposadr[jntid]
|
||||||
|
qpos_spring_id = worldid % qpos_spring.shape[0]
|
||||||
|
|
||||||
if jnttype == JointType.FREE:
|
if jnttype == JointType.FREE:
|
||||||
# spring
|
# spring
|
||||||
if has_stiffness:
|
if has_stiffness:
|
||||||
dif = wp.vec3(
|
dif = wp.vec3(
|
||||||
qpos_in[worldid, qposid + 0] - qpos_spring[worldid, qposid + 0],
|
qpos_in[worldid, qposid + 0] - qpos_spring[qpos_spring_id, qposid + 0],
|
||||||
qpos_in[worldid, qposid + 1] - qpos_spring[worldid, qposid + 1],
|
qpos_in[worldid, qposid + 1] - qpos_spring[qpos_spring_id, qposid + 1],
|
||||||
qpos_in[worldid, qposid + 2] - qpos_spring[worldid, qposid + 2],
|
qpos_in[worldid, qposid + 2] - qpos_spring[qpos_spring_id, qposid + 2],
|
||||||
)
|
)
|
||||||
qfrc_spring_out[worldid, dofid + 0] = -stiffness * dif[0]
|
qfrc_spring_out[worldid, dofid + 0] = -stiffness * dif[0]
|
||||||
qfrc_spring_out[worldid, dofid + 1] = -stiffness * dif[1]
|
qfrc_spring_out[worldid, dofid + 1] = -stiffness * dif[1]
|
||||||
@@ -123,10 +124,10 @@ def _spring_damper_dof_passive(
|
|||||||
)
|
)
|
||||||
rot = wp.normalize(rot)
|
rot = wp.normalize(rot)
|
||||||
ref = wp.quat(
|
ref = wp.quat(
|
||||||
qpos_spring[worldid, qposid + 3],
|
qpos_spring[qpos_spring_id, qposid + 3],
|
||||||
qpos_spring[worldid, qposid + 4],
|
qpos_spring[qpos_spring_id, qposid + 4],
|
||||||
qpos_spring[worldid, qposid + 5],
|
qpos_spring[qpos_spring_id, qposid + 5],
|
||||||
qpos_spring[worldid, qposid + 6],
|
qpos_spring[qpos_spring_id, qposid + 6],
|
||||||
)
|
)
|
||||||
dif = math.quat_sub(rot, ref)
|
dif = math.quat_sub(rot, ref)
|
||||||
qfrc_spring_out[worldid, dofid + 3] = -stiffness * dif[0]
|
qfrc_spring_out[worldid, dofid + 3] = -stiffness * dif[0]
|
||||||
@@ -152,10 +153,10 @@ def _spring_damper_dof_passive(
|
|||||||
)
|
)
|
||||||
rot = wp.normalize(rot)
|
rot = wp.normalize(rot)
|
||||||
ref = wp.quat(
|
ref = wp.quat(
|
||||||
qpos_spring[worldid, qposid + 0],
|
qpos_spring[qpos_spring_id, qposid + 0],
|
||||||
qpos_spring[worldid, qposid + 1],
|
qpos_spring[qpos_spring_id, qposid + 1],
|
||||||
qpos_spring[worldid, qposid + 2],
|
qpos_spring[qpos_spring_id, qposid + 2],
|
||||||
qpos_spring[worldid, qposid + 3],
|
qpos_spring[qpos_spring_id, qposid + 3],
|
||||||
)
|
)
|
||||||
dif = math.quat_sub(rot, ref)
|
dif = math.quat_sub(rot, ref)
|
||||||
qfrc_spring_out[worldid, dofid + 0] = -stiffness * dif[0]
|
qfrc_spring_out[worldid, dofid + 0] = -stiffness * dif[0]
|
||||||
@@ -170,7 +171,7 @@ def _spring_damper_dof_passive(
|
|||||||
else: # mjJNT_SLIDE, mjJNT_HINGE
|
else: # mjJNT_SLIDE, mjJNT_HINGE
|
||||||
# spring
|
# spring
|
||||||
if has_stiffness:
|
if has_stiffness:
|
||||||
fdif = qpos_in[worldid, qposid] - qpos_spring[worldid, qposid]
|
fdif = qpos_in[worldid, qposid] - qpos_spring[qpos_spring_id, qposid]
|
||||||
qfrc_spring_out[worldid, dofid] = -stiffness * fdif
|
qfrc_spring_out[worldid, dofid] = -stiffness * fdif
|
||||||
|
|
||||||
# damper
|
# damper
|
||||||
@@ -185,9 +186,9 @@ def _spring_damper_tendon_passive(
|
|||||||
tendon_damping: wp.array2d(dtype=float),
|
tendon_damping: wp.array2d(dtype=float),
|
||||||
tendon_lengthspring: wp.array2d(dtype=wp.vec2),
|
tendon_lengthspring: wp.array2d(dtype=wp.vec2),
|
||||||
# Data in:
|
# Data in:
|
||||||
ten_velocity_in: wp.array2d(dtype=float),
|
|
||||||
ten_length_in: wp.array2d(dtype=float),
|
|
||||||
ten_J_in: wp.array3d(dtype=float),
|
ten_J_in: wp.array3d(dtype=float),
|
||||||
|
ten_length_in: wp.array2d(dtype=float),
|
||||||
|
ten_velocity_in: wp.array2d(dtype=float),
|
||||||
# In:
|
# In:
|
||||||
dsbl_spring: bool,
|
dsbl_spring: bool,
|
||||||
dsbl_damper: bool,
|
dsbl_damper: bool,
|
||||||
@@ -197,8 +198,8 @@ def _spring_damper_tendon_passive(
|
|||||||
):
|
):
|
||||||
worldid, tenid, dofid = wp.tid()
|
worldid, tenid, dofid = wp.tid()
|
||||||
|
|
||||||
stiffness = tendon_stiffness[worldid, tenid]
|
stiffness = tendon_stiffness[worldid % tendon_stiffness.shape[0], tenid]
|
||||||
damping = tendon_damping[worldid, tenid]
|
damping = tendon_damping[worldid % tendon_damping.shape[0], tenid]
|
||||||
|
|
||||||
has_stiffness = stiffness != 0.0 and not dsbl_spring
|
has_stiffness = stiffness != 0.0 and not dsbl_spring
|
||||||
has_damping = damping != 0.0 and not dsbl_damper
|
has_damping = damping != 0.0 and not dsbl_damper
|
||||||
@@ -211,7 +212,7 @@ def _spring_damper_tendon_passive(
|
|||||||
if has_stiffness:
|
if has_stiffness:
|
||||||
# compute spring force along tendon
|
# compute spring force along tendon
|
||||||
length = ten_length_in[worldid, tenid]
|
length = ten_length_in[worldid, tenid]
|
||||||
lengthspring = tendon_lengthspring[worldid, tenid]
|
lengthspring = tendon_lengthspring[worldid % tendon_lengthspring.shape[0], tenid]
|
||||||
lower = lengthspring[0]
|
lower = lengthspring[0]
|
||||||
upper = lengthspring[1]
|
upper = lengthspring[1]
|
||||||
|
|
||||||
@@ -251,12 +252,11 @@ def _gravity_force(
|
|||||||
):
|
):
|
||||||
worldid, bodyid, dofid = wp.tid()
|
worldid, bodyid, dofid = wp.tid()
|
||||||
bodyid += 1 # skip world body
|
bodyid += 1 # skip world body
|
||||||
gravcomp = body_gravcomp[worldid, bodyid]
|
gravcomp = body_gravcomp[worldid % body_gravcomp.shape[0], bodyid]
|
||||||
gravity = opt_gravity[worldid]
|
gravity = opt_gravity[worldid % opt_gravity.shape[0]]
|
||||||
|
|
||||||
if gravcomp:
|
if gravcomp:
|
||||||
force = -gravity * body_mass[worldid, bodyid] * gravcomp
|
force = -gravity * body_mass[worldid % body_mass.shape[0], bodyid] * gravcomp
|
||||||
|
|
||||||
pos = xipos_in[worldid, bodyid]
|
pos = xipos_in[worldid, bodyid]
|
||||||
jac, _ = support.jac(body_parentid, body_rootid, dof_bodyid, subtree_com_in, cdof_in, pos, bodyid, dofid, worldid)
|
jac, _ = support.jac(body_parentid, body_rootid, dof_bodyid, subtree_com_in, cdof_in, pos, bodyid, dofid, worldid)
|
||||||
|
|
||||||
@@ -266,18 +266,18 @@ def _gravity_force(
|
|||||||
@wp.kernel
|
@wp.kernel
|
||||||
def _fluid_force(
|
def _fluid_force(
|
||||||
# Model:
|
# Model:
|
||||||
opt_wind: wp.array(dtype=wp.vec3),
|
|
||||||
opt_density: wp.array(dtype=float),
|
opt_density: wp.array(dtype=float),
|
||||||
opt_viscosity: wp.array(dtype=float),
|
opt_viscosity: wp.array(dtype=float),
|
||||||
|
opt_wind: wp.array(dtype=wp.vec3),
|
||||||
body_rootid: wp.array(dtype=int),
|
body_rootid: wp.array(dtype=int),
|
||||||
body_geomnum: wp.array(dtype=int),
|
body_geomnum: wp.array(dtype=int),
|
||||||
body_geomadr: wp.array(dtype=int),
|
body_geomadr: wp.array(dtype=int),
|
||||||
body_mass: wp.array2d(dtype=float),
|
body_mass: wp.array2d(dtype=float),
|
||||||
body_inertia: wp.array2d(dtype=wp.vec3),
|
body_inertia: wp.array2d(dtype=wp.vec3),
|
||||||
body_fluid_ellipsoid: wp.array(dtype=bool),
|
|
||||||
geom_type: wp.array(dtype=int),
|
geom_type: wp.array(dtype=int),
|
||||||
geom_size: wp.array2d(dtype=wp.vec3),
|
geom_size: wp.array2d(dtype=wp.vec3),
|
||||||
geom_fluid: wp.array2d(dtype=float),
|
geom_fluid: wp.array2d(dtype=float),
|
||||||
|
body_fluid_ellipsoid: wp.array(dtype=bool),
|
||||||
# Data in:
|
# Data in:
|
||||||
xipos_in: wp.array2d(dtype=wp.vec3),
|
xipos_in: wp.array2d(dtype=wp.vec3),
|
||||||
ximat_in: wp.array2d(dtype=wp.mat33),
|
ximat_in: wp.array2d(dtype=wp.mat33),
|
||||||
@@ -285,11 +285,10 @@ def _fluid_force(
|
|||||||
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
geom_xmat_in: wp.array2d(dtype=wp.mat33),
|
||||||
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
subtree_com_in: wp.array2d(dtype=wp.vec3),
|
||||||
cvel_in: wp.array2d(dtype=wp.spatial_vector),
|
cvel_in: wp.array2d(dtype=wp.spatial_vector),
|
||||||
# Data out:
|
# Out:
|
||||||
fluid_applied_out: wp.array2d(dtype=wp.spatial_vector),
|
fluid_applied_out: wp.array2d(dtype=wp.spatial_vector),
|
||||||
):
|
):
|
||||||
"""Computes body-space fluid forces for both inertia-box and ellipsoid models."""
|
"""Computes body-space fluid forces for both inertia-box and ellipsoid models."""
|
||||||
|
|
||||||
worldid, bodyid = wp.tid()
|
worldid, bodyid = wp.tid()
|
||||||
zero_force = wp.spatial_vector(wp.vec3(0.0), wp.vec3(0.0))
|
zero_force = wp.spatial_vector(wp.vec3(0.0), wp.vec3(0.0))
|
||||||
|
|
||||||
@@ -297,9 +296,9 @@ def _fluid_force(
|
|||||||
fluid_applied_out[worldid, bodyid] = zero_force
|
fluid_applied_out[worldid, bodyid] = zero_force
|
||||||
return
|
return
|
||||||
|
|
||||||
wind = opt_wind[worldid]
|
wind = opt_wind[worldid % opt_wind.shape[0]]
|
||||||
density = opt_density[worldid]
|
density = opt_density[worldid % opt_density.shape[0]]
|
||||||
viscosity = opt_viscosity[worldid]
|
viscosity = opt_viscosity[worldid % opt_viscosity.shape[0]]
|
||||||
|
|
||||||
# Body kinematics
|
# Body kinematics
|
||||||
xipos = xipos_in[worldid, bodyid]
|
xipos = xipos_in[worldid, bodyid]
|
||||||
@@ -324,7 +323,7 @@ def _fluid_force(
|
|||||||
if coef <= 0.0:
|
if coef <= 0.0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
size = geom_size[worldid, geomid]
|
size = geom_size[worldid % geom_size.shape[0], geomid]
|
||||||
semiaxes = _geom_semiaxes(size, geom_type[geomid])
|
semiaxes = _geom_semiaxes(size, geom_type[geomid])
|
||||||
geom_rot = geom_xmat_in[worldid, geomid]
|
geom_rot = geom_xmat_in[worldid, geomid]
|
||||||
geom_rotT = wp.transpose(geom_rot)
|
geom_rotT = wp.transpose(geom_rot)
|
||||||
@@ -451,8 +450,8 @@ def _fluid_force(
|
|||||||
has_density = density > 0.0
|
has_density = density > 0.0
|
||||||
|
|
||||||
if has_viscosity or has_density:
|
if has_viscosity or has_density:
|
||||||
inertia = body_inertia[worldid, bodyid]
|
inertia = body_inertia[worldid % body_inertia.shape[0], bodyid]
|
||||||
mass = body_mass[worldid, bodyid]
|
mass = body_mass[worldid % body_mass.shape[0], bodyid]
|
||||||
scl = 6.0 / mass
|
scl = 6.0 / mass
|
||||||
box0 = wp.sqrt(wp.max(MJ_MINVAL, inertia[1] + inertia[2] - inertia[0]) * scl)
|
box0 = wp.sqrt(wp.max(MJ_MINVAL, inertia[1] + inertia[2] - inertia[0]) * scl)
|
||||||
box1 = wp.sqrt(wp.max(MJ_MINVAL, inertia[0] + inertia[2] - inertia[1]) * scl)
|
box1 = wp.sqrt(wp.max(MJ_MINVAL, inertia[0] + inertia[2] - inertia[1]) * scl)
|
||||||
@@ -487,22 +486,24 @@ def _fluid_force(
|
|||||||
|
|
||||||
|
|
||||||
def _fluid(m: Model, d: Data):
|
def _fluid(m: Model, d: Data):
|
||||||
|
fluid_applied = wp.empty((d.nworld, m.nbody), dtype=wp.spatial_vector)
|
||||||
|
|
||||||
wp.launch(
|
wp.launch(
|
||||||
_fluid_force,
|
_fluid_force,
|
||||||
dim=(d.nworld, m.nbody),
|
dim=(d.nworld, m.nbody),
|
||||||
inputs=[
|
inputs=[
|
||||||
m.opt.wind,
|
|
||||||
m.opt.density,
|
m.opt.density,
|
||||||
m.opt.viscosity,
|
m.opt.viscosity,
|
||||||
|
m.opt.wind,
|
||||||
m.body_rootid,
|
m.body_rootid,
|
||||||
m.body_geomnum,
|
m.body_geomnum,
|
||||||
m.body_geomadr,
|
m.body_geomadr,
|
||||||
m.body_mass,
|
m.body_mass,
|
||||||
m.body_inertia,
|
m.body_inertia,
|
||||||
m.body_fluid_ellipsoid,
|
|
||||||
m.geom_type,
|
m.geom_type,
|
||||||
m.geom_size,
|
m.geom_size,
|
||||||
m.geom_fluid,
|
m.geom_fluid,
|
||||||
|
m.body_fluid_ellipsoid,
|
||||||
d.xipos,
|
d.xipos,
|
||||||
d.ximat,
|
d.ximat,
|
||||||
d.geom_xpos,
|
d.geom_xpos,
|
||||||
@@ -510,12 +511,10 @@ def _fluid(m: Model, d: Data):
|
|||||||
d.subtree_com,
|
d.subtree_com,
|
||||||
d.cvel,
|
d.cvel,
|
||||||
],
|
],
|
||||||
outputs=[
|
outputs=[fluid_applied],
|
||||||
d.fluid_applied,
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
support.apply_ft(m, d, d.fluid_applied, d.qfrc_fluid, False)
|
support.apply_ft(m, d, fluid_applied, d.qfrc_fluid, False)
|
||||||
|
|
||||||
|
|
||||||
@wp.kernel
|
@wp.kernel
|
||||||
@@ -574,7 +573,7 @@ def _flex_elasticity(
|
|||||||
qfrc_spring_out: wp.array2d(dtype=float),
|
qfrc_spring_out: wp.array2d(dtype=float),
|
||||||
):
|
):
|
||||||
worldid, elemid = wp.tid()
|
worldid, elemid = wp.tid()
|
||||||
timestep = opt_timestep[worldid]
|
timestep = opt_timestep[worldid % opt_timestep.shape[0]]
|
||||||
f = 0 # TODO(quaglino): this should become a function of t
|
f = 0 # TODO(quaglino): this should become a function of t
|
||||||
|
|
||||||
dim = flex_dim[f]
|
dim = flex_dim[f]
|
||||||
@@ -727,9 +726,9 @@ def passive(m: Model, d: Data):
|
|||||||
m.tendon_stiffness,
|
m.tendon_stiffness,
|
||||||
m.tendon_damping,
|
m.tendon_damping,
|
||||||
m.tendon_lengthspring,
|
m.tendon_lengthspring,
|
||||||
d.ten_velocity,
|
|
||||||
d.ten_length,
|
|
||||||
d.ten_J,
|
d.ten_J,
|
||||||
|
d.ten_length,
|
||||||
|
d.ten_velocity,
|
||||||
dsbl_spring,
|
dsbl_spring,
|
||||||
dsbl_damper,
|
dsbl_damper,
|
||||||
],
|
],
|
||||||
|
|||||||
+57
-65
@@ -13,7 +13,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
from typing import Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
import warp as wp
|
import warp as wp
|
||||||
|
|
||||||
@@ -40,7 +40,6 @@ def _ray_map(pos: wp.vec3, mat: wp.mat33, pnt: wp.vec3, vec: wp.vec3) -> Tuple[w
|
|||||||
Returns:
|
Returns:
|
||||||
3D point and 3D direction in local geom frame
|
3D point and 3D direction in local geom frame
|
||||||
"""
|
"""
|
||||||
|
|
||||||
matT = wp.transpose(mat)
|
matT = wp.transpose(mat)
|
||||||
lpnt = matT @ (pnt - pos)
|
lpnt = matT @ (pnt - pos)
|
||||||
lvec = matT @ vec
|
lvec = matT @ vec
|
||||||
@@ -53,8 +52,8 @@ def _ray_eliminate(
|
|||||||
# Model:
|
# Model:
|
||||||
body_weldid: wp.array(dtype=int),
|
body_weldid: wp.array(dtype=int),
|
||||||
geom_bodyid: wp.array(dtype=int),
|
geom_bodyid: wp.array(dtype=int),
|
||||||
geom_group: wp.array(dtype=int),
|
|
||||||
geom_matid: wp.array(dtype=int), # kernel_analyzer: ignore
|
geom_matid: wp.array(dtype=int), # kernel_analyzer: ignore
|
||||||
|
geom_group: wp.array(dtype=int),
|
||||||
geom_rgba: wp.array(dtype=wp.vec4), # kernel_analyzer: ignore
|
geom_rgba: wp.array(dtype=wp.vec4), # kernel_analyzer: ignore
|
||||||
mat_rgba: wp.array(dtype=wp.vec4), # kernel_analyzer: ignore
|
mat_rgba: wp.array(dtype=wp.vec4), # kernel_analyzer: ignore
|
||||||
# In:
|
# In:
|
||||||
@@ -184,7 +183,6 @@ def _ray_triangle(v0: wp.vec3, v1: wp.vec3, v2: wp.vec3, pnt: wp.vec3, vec: wp.v
|
|||||||
@wp.func
|
@wp.func
|
||||||
def _ray_plane(pos: wp.vec3, mat: wp.mat33, size: wp.vec3, pnt: wp.vec3, vec: wp.vec3) -> float:
|
def _ray_plane(pos: wp.vec3, mat: wp.mat33, size: wp.vec3, pnt: wp.vec3, vec: wp.vec3) -> float:
|
||||||
"""Returns the distance at which a ray intersects with a plane."""
|
"""Returns the distance at which a ray intersects with a plane."""
|
||||||
|
|
||||||
# map to local frame
|
# map to local frame
|
||||||
lpnt, lvec = _ray_map(pos, mat, pnt, vec)
|
lpnt, lvec = _ray_map(pos, mat, pnt, vec)
|
||||||
|
|
||||||
@@ -222,7 +220,6 @@ def _ray_sphere(pos: wp.vec3, dist_sqr: float, pnt: wp.vec3, vec: wp.vec3) -> fl
|
|||||||
@wp.func
|
@wp.func
|
||||||
def _ray_capsule(pos: wp.vec3, mat: wp.mat33, size: wp.vec3, pnt: wp.vec3, vec: wp.vec3) -> float:
|
def _ray_capsule(pos: wp.vec3, mat: wp.mat33, size: wp.vec3, pnt: wp.vec3, vec: wp.vec3) -> float:
|
||||||
"""Returns the distance at which a ray intersects with a capsule."""
|
"""Returns the distance at which a ray intersects with a capsule."""
|
||||||
|
|
||||||
# bounding sphere test
|
# bounding sphere test
|
||||||
ssz = size[0] + size[1]
|
ssz = size[0] + size[1]
|
||||||
if _ray_sphere(pos, ssz * ssz, pnt, vec) < 0.0:
|
if _ray_sphere(pos, ssz * ssz, pnt, vec) < 0.0:
|
||||||
@@ -279,7 +276,6 @@ def _ray_capsule(pos: wp.vec3, mat: wp.mat33, size: wp.vec3, pnt: wp.vec3, vec:
|
|||||||
@wp.func
|
@wp.func
|
||||||
def _ray_ellipsoid(pos: wp.vec3, mat: wp.mat33, size: wp.vec3, pnt: wp.vec3, vec: wp.vec3) -> float:
|
def _ray_ellipsoid(pos: wp.vec3, mat: wp.mat33, size: wp.vec3, pnt: wp.vec3, vec: wp.vec3) -> float:
|
||||||
"""Returns the distance at which a ray intersects with an ellipsoid."""
|
"""Returns the distance at which a ray intersects with an ellipsoid."""
|
||||||
|
|
||||||
# map to local frame
|
# map to local frame
|
||||||
lpnt, lvec = _ray_map(pos, mat, pnt, vec)
|
lpnt, lvec = _ray_map(pos, mat, pnt, vec)
|
||||||
|
|
||||||
@@ -395,10 +391,10 @@ def _ray_hfield(
|
|||||||
# Model:
|
# Model:
|
||||||
geom_type: wp.array(dtype=int),
|
geom_type: wp.array(dtype=int),
|
||||||
geom_dataid: wp.array(dtype=int),
|
geom_dataid: wp.array(dtype=int),
|
||||||
hfield_adr: wp.array(dtype=int),
|
hfield_size: wp.array(dtype=wp.vec4),
|
||||||
hfield_nrow: wp.array(dtype=int),
|
hfield_nrow: wp.array(dtype=int),
|
||||||
hfield_ncol: wp.array(dtype=int),
|
hfield_ncol: wp.array(dtype=int),
|
||||||
hfield_size: wp.array(dtype=wp.vec4),
|
hfield_adr: wp.array(dtype=int),
|
||||||
hfield_data: wp.array(dtype=float),
|
hfield_data: wp.array(dtype=float),
|
||||||
# In:
|
# In:
|
||||||
pos: wp.vec3,
|
pos: wp.vec3,
|
||||||
@@ -540,8 +536,8 @@ def ray_mesh(
|
|||||||
# Model:
|
# Model:
|
||||||
nmeshface: int,
|
nmeshface: int,
|
||||||
mesh_vertadr: wp.array(dtype=int),
|
mesh_vertadr: wp.array(dtype=int),
|
||||||
mesh_vert: wp.array(dtype=wp.vec3),
|
|
||||||
mesh_faceadr: wp.array(dtype=int),
|
mesh_faceadr: wp.array(dtype=int),
|
||||||
|
mesh_vert: wp.array(dtype=wp.vec3),
|
||||||
mesh_face: wp.array(dtype=wp.vec3i),
|
mesh_face: wp.array(dtype=wp.vec3i),
|
||||||
# In:
|
# In:
|
||||||
data_id: int,
|
data_id: int,
|
||||||
@@ -606,7 +602,6 @@ def ray_mesh(
|
|||||||
@wp.func
|
@wp.func
|
||||||
def ray_geom(pos: wp.vec3, mat: wp.mat33, size: wp.vec3, pnt: wp.vec3, vec: wp.vec3, geomtype: int) -> float:
|
def ray_geom(pos: wp.vec3, mat: wp.mat33, size: wp.vec3, pnt: wp.vec3, vec: wp.vec3, geomtype: int) -> float:
|
||||||
"""Returns distance along ray to intersection with geom, or infinity if none."""
|
"""Returns distance along ray to intersection with geom, or infinity if none."""
|
||||||
|
|
||||||
# TODO(team): static loop unrolling to remove unnecessary branching
|
# TODO(team): static loop unrolling to remove unnecessary branching
|
||||||
if geomtype == GeomType.PLANE:
|
if geomtype == GeomType.PLANE:
|
||||||
return _ray_plane(pos, mat, size, pnt, vec)
|
return _ray_plane(pos, mat, size, pnt, vec)
|
||||||
@@ -633,19 +628,19 @@ def _ray_geom_mesh(
|
|||||||
geom_type: wp.array(dtype=int),
|
geom_type: wp.array(dtype=int),
|
||||||
geom_bodyid: wp.array(dtype=int),
|
geom_bodyid: wp.array(dtype=int),
|
||||||
geom_dataid: wp.array(dtype=int),
|
geom_dataid: wp.array(dtype=int),
|
||||||
geom_group: wp.array(dtype=int),
|
|
||||||
geom_matid: wp.array2d(dtype=int),
|
geom_matid: wp.array2d(dtype=int),
|
||||||
|
geom_group: wp.array(dtype=int),
|
||||||
geom_size: wp.array2d(dtype=wp.vec3),
|
geom_size: wp.array2d(dtype=wp.vec3),
|
||||||
geom_rgba: wp.array2d(dtype=wp.vec4),
|
geom_rgba: wp.array2d(dtype=wp.vec4),
|
||||||
hfield_adr: wp.array(dtype=int),
|
mesh_vertadr: wp.array(dtype=int),
|
||||||
|
mesh_faceadr: wp.array(dtype=int),
|
||||||
|
mesh_vert: wp.array(dtype=wp.vec3),
|
||||||
|
mesh_face: wp.array(dtype=wp.vec3i),
|
||||||
|
hfield_size: wp.array(dtype=wp.vec4),
|
||||||
hfield_nrow: wp.array(dtype=int),
|
hfield_nrow: wp.array(dtype=int),
|
||||||
hfield_ncol: wp.array(dtype=int),
|
hfield_ncol: wp.array(dtype=int),
|
||||||
hfield_size: wp.array(dtype=wp.vec4),
|
hfield_adr: wp.array(dtype=int),
|
||||||
hfield_data: wp.array(dtype=float),
|
hfield_data: wp.array(dtype=float),
|
||||||
mesh_vertadr: wp.array(dtype=int),
|
|
||||||
mesh_vert: wp.array(dtype=wp.vec3),
|
|
||||||
mesh_faceadr: wp.array(dtype=int),
|
|
||||||
mesh_face: wp.array(dtype=wp.vec3i),
|
|
||||||
mat_rgba: wp.array2d(dtype=wp.vec4),
|
mat_rgba: wp.array2d(dtype=wp.vec4),
|
||||||
# Data in:
|
# Data in:
|
||||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||||
@@ -662,10 +657,10 @@ def _ray_geom_mesh(
|
|||||||
if not _ray_eliminate(
|
if not _ray_eliminate(
|
||||||
body_weldid,
|
body_weldid,
|
||||||
geom_bodyid,
|
geom_bodyid,
|
||||||
|
geom_matid[worldid % geom_matid.shape[0]],
|
||||||
geom_group,
|
geom_group,
|
||||||
geom_matid[worldid],
|
geom_rgba[worldid % geom_rgba.shape[0]],
|
||||||
geom_rgba[worldid],
|
mat_rgba[worldid % mat_rgba.shape[0]],
|
||||||
mat_rgba[worldid],
|
|
||||||
geomid,
|
geomid,
|
||||||
geomgroup,
|
geomgroup,
|
||||||
flg_static,
|
flg_static,
|
||||||
@@ -679,8 +674,8 @@ def _ray_geom_mesh(
|
|||||||
return ray_mesh(
|
return ray_mesh(
|
||||||
nmeshface,
|
nmeshface,
|
||||||
mesh_vertadr,
|
mesh_vertadr,
|
||||||
mesh_vert,
|
|
||||||
mesh_faceadr,
|
mesh_faceadr,
|
||||||
|
mesh_vert,
|
||||||
mesh_face,
|
mesh_face,
|
||||||
geom_dataid[geomid],
|
geom_dataid[geomid],
|
||||||
pos,
|
pos,
|
||||||
@@ -692,10 +687,10 @@ def _ray_geom_mesh(
|
|||||||
return _ray_hfield(
|
return _ray_hfield(
|
||||||
geom_type,
|
geom_type,
|
||||||
geom_dataid,
|
geom_dataid,
|
||||||
hfield_adr,
|
hfield_size,
|
||||||
hfield_nrow,
|
hfield_nrow,
|
||||||
hfield_ncol,
|
hfield_ncol,
|
||||||
hfield_size,
|
hfield_adr,
|
||||||
hfield_data,
|
hfield_data,
|
||||||
pos,
|
pos,
|
||||||
mat,
|
mat,
|
||||||
@@ -704,7 +699,7 @@ def _ray_geom_mesh(
|
|||||||
geomid,
|
geomid,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return ray_geom(pos, mat, geom_size[worldid, geomid], pnt, vec, type)
|
return ray_geom(pos, mat, geom_size[worldid % geom_size.shape[0], geomid], pnt, vec, type)
|
||||||
else:
|
else:
|
||||||
return wp.inf
|
return wp.inf
|
||||||
|
|
||||||
@@ -718,19 +713,19 @@ def _ray(
|
|||||||
geom_type: wp.array(dtype=int),
|
geom_type: wp.array(dtype=int),
|
||||||
geom_bodyid: wp.array(dtype=int),
|
geom_bodyid: wp.array(dtype=int),
|
||||||
geom_dataid: wp.array(dtype=int),
|
geom_dataid: wp.array(dtype=int),
|
||||||
geom_group: wp.array(dtype=int),
|
|
||||||
geom_matid: wp.array2d(dtype=int),
|
geom_matid: wp.array2d(dtype=int),
|
||||||
|
geom_group: wp.array(dtype=int),
|
||||||
geom_size: wp.array2d(dtype=wp.vec3),
|
geom_size: wp.array2d(dtype=wp.vec3),
|
||||||
geom_rgba: wp.array2d(dtype=wp.vec4),
|
geom_rgba: wp.array2d(dtype=wp.vec4),
|
||||||
hfield_adr: wp.array(dtype=int),
|
mesh_vertadr: wp.array(dtype=int),
|
||||||
|
mesh_faceadr: wp.array(dtype=int),
|
||||||
|
mesh_vert: wp.array(dtype=wp.vec3),
|
||||||
|
mesh_face: wp.array(dtype=wp.vec3i),
|
||||||
|
hfield_size: wp.array(dtype=wp.vec4),
|
||||||
hfield_nrow: wp.array(dtype=int),
|
hfield_nrow: wp.array(dtype=int),
|
||||||
hfield_ncol: wp.array(dtype=int),
|
hfield_ncol: wp.array(dtype=int),
|
||||||
hfield_size: wp.array(dtype=wp.vec4),
|
hfield_adr: wp.array(dtype=int),
|
||||||
hfield_data: wp.array(dtype=float),
|
hfield_data: wp.array(dtype=float),
|
||||||
mesh_vertadr: wp.array(dtype=int),
|
|
||||||
mesh_vert: wp.array(dtype=wp.vec3),
|
|
||||||
mesh_faceadr: wp.array(dtype=int),
|
|
||||||
mesh_face: wp.array(dtype=wp.vec3i),
|
|
||||||
mat_rgba: wp.array2d(dtype=wp.vec4),
|
mat_rgba: wp.array2d(dtype=wp.vec4),
|
||||||
# Data in:
|
# Data in:
|
||||||
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
geom_xpos_in: wp.array2d(dtype=wp.vec3),
|
||||||
@@ -761,19 +756,19 @@ def _ray(
|
|||||||
geom_type,
|
geom_type,
|
||||||
geom_bodyid,
|
geom_bodyid,
|
||||||
geom_dataid,
|
geom_dataid,
|
||||||
geom_group,
|
|
||||||
geom_matid,
|
geom_matid,
|
||||||
|
geom_group,
|
||||||
geom_size,
|
geom_size,
|
||||||
geom_rgba,
|
geom_rgba,
|
||||||
hfield_adr,
|
mesh_vertadr,
|
||||||
|
mesh_faceadr,
|
||||||
|
mesh_vert,
|
||||||
|
mesh_face,
|
||||||
|
hfield_size,
|
||||||
hfield_nrow,
|
hfield_nrow,
|
||||||
hfield_ncol,
|
hfield_ncol,
|
||||||
hfield_size,
|
hfield_adr,
|
||||||
hfield_data,
|
hfield_data,
|
||||||
mesh_vertadr,
|
|
||||||
mesh_vert,
|
|
||||||
mesh_faceadr,
|
|
||||||
mesh_face,
|
|
||||||
mat_rgba,
|
mat_rgba,
|
||||||
geom_xpos_in,
|
geom_xpos_in,
|
||||||
geom_xmat_in,
|
geom_xmat_in,
|
||||||
@@ -810,41 +805,38 @@ def ray(
|
|||||||
d: Data,
|
d: Data,
|
||||||
pnt: wp.array2d(dtype=wp.vec3),
|
pnt: wp.array2d(dtype=wp.vec3),
|
||||||
vec: wp.array2d(dtype=wp.vec3),
|
vec: wp.array2d(dtype=wp.vec3),
|
||||||
geomgroup: vec6 = None,
|
geomgroup: Optional[vec6] = None,
|
||||||
flg_static: bool = True,
|
flg_static: bool = True,
|
||||||
bodyexclude: int = -1,
|
bodyexclude: int = -1,
|
||||||
) -> tuple[wp.array2d(dtype=float), wp.array2d(dtype=int)]:
|
) -> Tuple[wp.array, wp.array]:
|
||||||
"""Returns the distance at which rays intersect with primitive geoms.
|
"""Returns the distance at which rays intersect with primitive geoms.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
m (Model): The model containing kinematic and dynamic information (device).
|
m: The model containing kinematic and dynamic information (device).
|
||||||
d (Data): The data object containing the current state and output arrays (device).
|
d: The data object containing the current state and output arrays (device).
|
||||||
pnt (wp.array2d(dtype=wp.vec3)): Ray origin points.
|
pnt: Ray origin points.
|
||||||
vec (wp.array2d(dtype=wp.vec3)): Ray directions.
|
vec: Ray directions.
|
||||||
geomgroup (vec6, optional): Group inclusion/exclusion mask.
|
geomgroup: Group inclusion/exclusion mask. If all are wp.inf, ignore.
|
||||||
If all are wp.inf, ignore.
|
flg_static: If True, allows rays to intersect with static geoms.
|
||||||
flg_static (bool, optional): If True, allows rays to intersect with static geoms.
|
bodyexclude: Ignore geoms on specified body id (-1 to disable).
|
||||||
Defaults to True.
|
|
||||||
bodyexclude (int, optional): Ignore geoms on specified body id (-1 to disable).
|
|
||||||
Defaults to -1.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
wp.array2d(dtype=float): Distances from ray origins to geom surfaces.
|
Distances from ray origins to geom surfaces and IDs of intersected geoms (-1 if none).
|
||||||
wp.array2d(dtype=int): IDs of intersected geoms (-1 if none).
|
|
||||||
"""
|
"""
|
||||||
|
assert pnt.shape[0] == 1
|
||||||
assert pnt.shape[0] == vec.shape[0]
|
assert pnt.shape[0] == vec.shape[0]
|
||||||
assert d.ray_dist.shape[1] == d.ray_geomid.shape[1]
|
|
||||||
assert pnt.shape[0] == d.ray_dist.shape[1]
|
|
||||||
|
|
||||||
if geomgroup is None:
|
if geomgroup is None:
|
||||||
geomgroup = vec6(-1, -1, -1, -1, -1, -1)
|
geomgroup = vec6(-1, -1, -1, -1, -1, -1)
|
||||||
|
|
||||||
d.ray_bodyexclude.fill_(bodyexclude)
|
ray_bodyexclude = wp.empty(1, dtype=int)
|
||||||
|
ray_bodyexclude.fill_(bodyexclude)
|
||||||
|
ray_dist = wp.empty((d.nworld, 1), dtype=float)
|
||||||
|
ray_geomid = wp.empty((d.nworld, 1), dtype=int)
|
||||||
|
|
||||||
rays(m, d, pnt, vec, geomgroup, flg_static, d.ray_bodyexclude, d.ray_dist, d.ray_geomid)
|
rays(m, d, pnt, vec, geomgroup, flg_static, ray_bodyexclude, ray_dist, ray_geomid)
|
||||||
|
|
||||||
return d.ray_dist, d.ray_geomid
|
return ray_dist, ray_geomid
|
||||||
|
|
||||||
|
|
||||||
def rays(
|
def rays(
|
||||||
@@ -868,19 +860,19 @@ def rays(
|
|||||||
m.geom_type,
|
m.geom_type,
|
||||||
m.geom_bodyid,
|
m.geom_bodyid,
|
||||||
m.geom_dataid,
|
m.geom_dataid,
|
||||||
m.geom_group,
|
|
||||||
m.geom_matid,
|
m.geom_matid,
|
||||||
|
m.geom_group,
|
||||||
m.geom_size,
|
m.geom_size,
|
||||||
m.geom_rgba,
|
m.geom_rgba,
|
||||||
m.hfield_adr,
|
m.mesh_vertadr,
|
||||||
|
m.mesh_faceadr,
|
||||||
|
m.mesh_vert,
|
||||||
|
m.mesh_face,
|
||||||
|
m.hfield_size,
|
||||||
m.hfield_nrow,
|
m.hfield_nrow,
|
||||||
m.hfield_ncol,
|
m.hfield_ncol,
|
||||||
m.hfield_size,
|
m.hfield_adr,
|
||||||
m.hfield_data,
|
m.hfield_data,
|
||||||
m.mesh_vertadr,
|
|
||||||
m.mesh_vert,
|
|
||||||
m.mesh_faceadr,
|
|
||||||
m.mesh_face,
|
|
||||||
m.mat_rgba,
|
m.mat_rgba,
|
||||||
d.geom_xpos,
|
d.geom_xpos,
|
||||||
d.geom_xmat,
|
d.geom_xmat,
|
||||||
|
|||||||
+251
-309
File diff suppressed because it is too large
Load Diff
+202
-202
File diff suppressed because it is too large
Load Diff
+195
-141
@@ -297,7 +297,6 @@ def linesearch_iterative(
|
|||||||
opt_ls_iterations: int,
|
opt_ls_iterations: int,
|
||||||
stat_meaninertia: float,
|
stat_meaninertia: float,
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
ne_in: wp.array(dtype=int),
|
ne_in: wp.array(dtype=int),
|
||||||
nf_in: wp.array(dtype=int),
|
nf_in: wp.array(dtype=int),
|
||||||
nefc_in: wp.array(dtype=int),
|
nefc_in: wp.array(dtype=int),
|
||||||
@@ -313,6 +312,7 @@ def linesearch_iterative(
|
|||||||
efc_quad_in: wp.array2d(dtype=wp.vec3),
|
efc_quad_in: wp.array2d(dtype=wp.vec3),
|
||||||
efc_quad_gauss_in: wp.array(dtype=wp.vec3),
|
efc_quad_gauss_in: wp.array(dtype=wp.vec3),
|
||||||
efc_done_in: wp.array(dtype=bool),
|
efc_done_in: wp.array(dtype=bool),
|
||||||
|
njmax_in: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
efc_alpha_out: wp.array(dtype=float),
|
efc_alpha_out: wp.array(dtype=float),
|
||||||
):
|
):
|
||||||
@@ -321,7 +321,7 @@ def linesearch_iterative(
|
|||||||
if efc_done_in[worldid]:
|
if efc_done_in[worldid]:
|
||||||
return
|
return
|
||||||
|
|
||||||
impratio = opt_impratio[worldid]
|
impratio = opt_impratio[worldid % opt_impratio.shape[0]]
|
||||||
efc_type = efc_type_in[worldid]
|
efc_type = efc_type_in[worldid]
|
||||||
efc_id = efc_id_in[worldid]
|
efc_id = efc_id_in[worldid]
|
||||||
efc_D = efc_D_in[worldid]
|
efc_D = efc_D_in[worldid]
|
||||||
@@ -330,8 +330,8 @@ def linesearch_iterative(
|
|||||||
efc_jv = efc_jv_in[worldid]
|
efc_jv = efc_jv_in[worldid]
|
||||||
efc_quad = efc_quad_in[worldid]
|
efc_quad = efc_quad_in[worldid]
|
||||||
efc_quad_gauss = efc_quad_gauss_in[worldid]
|
efc_quad_gauss = efc_quad_gauss_in[worldid]
|
||||||
tolerance = opt_tolerance[worldid]
|
tolerance = opt_tolerance[worldid % opt_tolerance.shape[0]]
|
||||||
ls_tolerance = opt_ls_tolerance[worldid]
|
ls_tolerance = opt_ls_tolerance[worldid % opt_ls_tolerance.shape[0]]
|
||||||
ne_clip = min(njmax_in, ne_in[worldid])
|
ne_clip = min(njmax_in, ne_in[worldid])
|
||||||
nef_clip = min(njmax_in, ne_clip + nf_in[worldid])
|
nef_clip = min(njmax_in, ne_clip + nf_in[worldid])
|
||||||
nefc_clip = min(njmax_in, nefc_in[worldid])
|
nefc_clip = min(njmax_in, nefc_in[worldid])
|
||||||
@@ -466,7 +466,6 @@ def _linesearch_iterative(m: types.Model, d: types.Data):
|
|||||||
m.opt.ls_tolerance,
|
m.opt.ls_tolerance,
|
||||||
m.opt.ls_iterations,
|
m.opt.ls_iterations,
|
||||||
m.stat.meaninertia,
|
m.stat.meaninertia,
|
||||||
d.njmax,
|
|
||||||
d.ne,
|
d.ne,
|
||||||
d.nf,
|
d.nf,
|
||||||
d.nefc,
|
d.nefc,
|
||||||
@@ -482,6 +481,7 @@ def _linesearch_iterative(m: types.Model, d: types.Data):
|
|||||||
d.efc.quad,
|
d.efc.quad,
|
||||||
d.efc.quad_gauss,
|
d.efc.quad_gauss,
|
||||||
d.efc.done,
|
d.efc.done,
|
||||||
|
d.njmax,
|
||||||
],
|
],
|
||||||
outputs=[d.efc.alpha],
|
outputs=[d.efc.alpha],
|
||||||
)
|
)
|
||||||
@@ -496,12 +496,10 @@ def _log_scale(min_value: float, max_value: float, num_values: int, i: int) -> f
|
|||||||
@wp.kernel
|
@wp.kernel
|
||||||
def linesearch_parallel_fused(
|
def linesearch_parallel_fused(
|
||||||
# Model:
|
# Model:
|
||||||
nlsp: int,
|
|
||||||
opt_impratio: wp.array(dtype=float),
|
opt_impratio: wp.array(dtype=float),
|
||||||
|
opt_ls_iterations: int,
|
||||||
opt_ls_parallel_min_step: float,
|
opt_ls_parallel_min_step: float,
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
nacon_in: wp.array(dtype=int),
|
|
||||||
ne_in: wp.array(dtype=int),
|
ne_in: wp.array(dtype=int),
|
||||||
nf_in: wp.array(dtype=int),
|
nf_in: wp.array(dtype=int),
|
||||||
nefc_in: wp.array(dtype=int),
|
nefc_in: wp.array(dtype=int),
|
||||||
@@ -516,15 +514,17 @@ def linesearch_parallel_fused(
|
|||||||
efc_quad_in: wp.array2d(dtype=wp.vec3),
|
efc_quad_in: wp.array2d(dtype=wp.vec3),
|
||||||
efc_quad_gauss_in: wp.array(dtype=wp.vec3),
|
efc_quad_gauss_in: wp.array(dtype=wp.vec3),
|
||||||
efc_done_in: wp.array(dtype=bool),
|
efc_done_in: wp.array(dtype=bool),
|
||||||
# Data out:
|
njmax_in: int,
|
||||||
efc_cost_candidate_out: wp.array2d(dtype=float),
|
nacon_in: wp.array(dtype=int),
|
||||||
|
# Out:
|
||||||
|
cost_out: wp.array2d(dtype=float),
|
||||||
):
|
):
|
||||||
worldid, alphaid = wp.tid()
|
worldid, alphaid = wp.tid()
|
||||||
|
|
||||||
if efc_done_in[worldid]:
|
if efc_done_in[worldid]:
|
||||||
return
|
return
|
||||||
|
|
||||||
alpha = _log_scale(opt_ls_parallel_min_step, 1.0, nlsp, alphaid)
|
alpha = _log_scale(opt_ls_parallel_min_step, 1.0, opt_ls_iterations, alphaid)
|
||||||
|
|
||||||
out = _eval_cost(efc_quad_gauss_in[worldid], alpha)
|
out = _eval_cost(efc_quad_gauss_in[worldid], alpha)
|
||||||
|
|
||||||
@@ -569,7 +569,7 @@ def linesearch_parallel_fused(
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
friction = contact_friction_in[conid]
|
friction = contact_friction_in[conid]
|
||||||
mu = friction[0] / wp.sqrt(opt_impratio[worldid])
|
mu = friction[0] / wp.sqrt(opt_impratio[worldid % opt_impratio.shape[0]])
|
||||||
|
|
||||||
# unpack quad
|
# unpack quad
|
||||||
efcid1 = contact_efc_address_in[conid, 1]
|
efcid1 = contact_efc_address_in[conid, 1]
|
||||||
@@ -613,17 +613,18 @@ def linesearch_parallel_fused(
|
|||||||
if x < 0.0:
|
if x < 0.0:
|
||||||
out += _eval_cost(efc_quad_in[worldid, efcid], alpha)
|
out += _eval_cost(efc_quad_in[worldid, efcid], alpha)
|
||||||
|
|
||||||
efc_cost_candidate_out[worldid, alphaid] = out
|
cost_out[worldid, alphaid] = out
|
||||||
|
|
||||||
|
|
||||||
@wp.kernel
|
@wp.kernel
|
||||||
def linesearch_parallel_best_alpha(
|
def linesearch_parallel_best_alpha(
|
||||||
# Model:
|
# Model:
|
||||||
nlsp: int,
|
opt_ls_iterations: int,
|
||||||
opt_ls_parallel_min_step: float,
|
opt_ls_parallel_min_step: float,
|
||||||
# Data in:
|
# Data in:
|
||||||
efc_done_in: wp.array(dtype=bool),
|
efc_done_in: wp.array(dtype=bool),
|
||||||
efc_cost_candidate_in: wp.array2d(dtype=float),
|
# In:
|
||||||
|
cost_in: wp.array2d(dtype=float),
|
||||||
# Data out:
|
# Data out:
|
||||||
efc_alpha_out: wp.array(dtype=float),
|
efc_alpha_out: wp.array(dtype=float),
|
||||||
):
|
):
|
||||||
@@ -632,29 +633,25 @@ def linesearch_parallel_best_alpha(
|
|||||||
if efc_done_in[worldid]:
|
if efc_done_in[worldid]:
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO(team): investigate alternatives to wp.argmin
|
|
||||||
# TODO(thowell): how did this use to work?
|
|
||||||
bestid = int(0)
|
bestid = int(0)
|
||||||
best_cost = float(wp.inf)
|
best_cost = float(wp.inf)
|
||||||
for i in range(nlsp):
|
for i in range(opt_ls_iterations):
|
||||||
cost = efc_cost_candidate_in[worldid, i]
|
cost = cost_in[worldid, i]
|
||||||
if cost < best_cost:
|
if cost < best_cost:
|
||||||
best_cost = cost
|
best_cost = cost
|
||||||
bestid = i
|
bestid = i
|
||||||
|
|
||||||
efc_alpha_out[worldid] = _log_scale(opt_ls_parallel_min_step, 1.0, nlsp, bestid)
|
efc_alpha_out[worldid] = _log_scale(opt_ls_parallel_min_step, 1.0, opt_ls_iterations, bestid)
|
||||||
|
|
||||||
|
|
||||||
def _linesearch_parallel(m: types.Model, d: types.Data):
|
def _linesearch_parallel(m: types.Model, d: types.Data, cost: wp.array2d(dtype=float)):
|
||||||
wp.launch(
|
wp.launch(
|
||||||
linesearch_parallel_fused,
|
linesearch_parallel_fused,
|
||||||
dim=(d.nworld, m.nlsp),
|
dim=(d.nworld, m.opt.ls_iterations),
|
||||||
inputs=[
|
inputs=[
|
||||||
m.nlsp,
|
|
||||||
m.opt.impratio,
|
m.opt.impratio,
|
||||||
|
m.opt.ls_iterations,
|
||||||
m.opt.ls_parallel_min_step,
|
m.opt.ls_parallel_min_step,
|
||||||
d.njmax,
|
|
||||||
d.nacon,
|
|
||||||
d.ne,
|
d.ne,
|
||||||
d.nf,
|
d.nf,
|
||||||
d.nefc,
|
d.nefc,
|
||||||
@@ -669,14 +666,16 @@ def _linesearch_parallel(m: types.Model, d: types.Data):
|
|||||||
d.efc.quad,
|
d.efc.quad,
|
||||||
d.efc.quad_gauss,
|
d.efc.quad_gauss,
|
||||||
d.efc.done,
|
d.efc.done,
|
||||||
|
d.njmax,
|
||||||
|
d.nacon,
|
||||||
],
|
],
|
||||||
outputs=[d.efc.cost_candidate],
|
outputs=[cost],
|
||||||
)
|
)
|
||||||
|
|
||||||
wp.launch(
|
wp.launch(
|
||||||
linesearch_parallel_best_alpha,
|
linesearch_parallel_best_alpha,
|
||||||
dim=(d.nworld),
|
dim=(d.nworld),
|
||||||
inputs=[m.nlsp, m.opt.ls_parallel_min_step, d.efc.done, d.efc.cost_candidate],
|
inputs=[m.opt.ls_iterations, m.opt.ls_parallel_min_step, d.efc.done, cost],
|
||||||
outputs=[d.efc.alpha],
|
outputs=[d.efc.alpha],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -771,7 +770,6 @@ def linesearch_prepare_quad(
|
|||||||
# Model:
|
# Model:
|
||||||
opt_impratio: wp.array(dtype=float),
|
opt_impratio: wp.array(dtype=float),
|
||||||
# Data in:
|
# Data in:
|
||||||
nacon_in: wp.array(dtype=int),
|
|
||||||
nefc_in: wp.array(dtype=int),
|
nefc_in: wp.array(dtype=int),
|
||||||
contact_friction_in: wp.array(dtype=types.vec5),
|
contact_friction_in: wp.array(dtype=types.vec5),
|
||||||
contact_dim_in: wp.array(dtype=int),
|
contact_dim_in: wp.array(dtype=int),
|
||||||
@@ -782,6 +780,7 @@ def linesearch_prepare_quad(
|
|||||||
efc_Jaref_in: wp.array2d(dtype=float),
|
efc_Jaref_in: wp.array2d(dtype=float),
|
||||||
efc_jv_in: wp.array2d(dtype=float),
|
efc_jv_in: wp.array2d(dtype=float),
|
||||||
efc_done_in: wp.array(dtype=bool),
|
efc_done_in: wp.array(dtype=bool),
|
||||||
|
nacon_in: wp.array(dtype=int),
|
||||||
# Data out:
|
# Data out:
|
||||||
efc_quad_out: wp.array2d(dtype=wp.vec3),
|
efc_quad_out: wp.array2d(dtype=wp.vec3),
|
||||||
):
|
):
|
||||||
@@ -904,9 +903,9 @@ def linesearch_jaref(
|
|||||||
|
|
||||||
|
|
||||||
@event_scope
|
@event_scope
|
||||||
def _linesearch(m: types.Model, d: types.Data):
|
def _linesearch(m: types.Model, d: types.Data, cost: wp.array2d(dtype=float)):
|
||||||
# mv = qM @ search
|
# mv = qM @ search
|
||||||
support.mul_m(m, d, d.efc.mv, d.efc.search, d.efc.done)
|
support.mul_m(m, d, d.efc.mv, d.efc.search, skip=d.efc.done)
|
||||||
|
|
||||||
# jv = efc_J @ search
|
# jv = efc_J @ search
|
||||||
# TODO(team): is there a better way of doing batched matmuls with dynamic array sizes?
|
# TODO(team): is there a better way of doing batched matmuls with dynamic array sizes?
|
||||||
@@ -951,7 +950,6 @@ def _linesearch(m: types.Model, d: types.Data):
|
|||||||
dim=(d.nworld, d.njmax),
|
dim=(d.nworld, d.njmax),
|
||||||
inputs=[
|
inputs=[
|
||||||
m.opt.impratio,
|
m.opt.impratio,
|
||||||
d.nacon,
|
|
||||||
d.nefc,
|
d.nefc,
|
||||||
d.contact.friction,
|
d.contact.friction,
|
||||||
d.contact.dim,
|
d.contact.dim,
|
||||||
@@ -962,12 +960,13 @@ def _linesearch(m: types.Model, d: types.Data):
|
|||||||
d.efc.Jaref,
|
d.efc.Jaref,
|
||||||
d.efc.jv,
|
d.efc.jv,
|
||||||
d.efc.done,
|
d.efc.done,
|
||||||
|
d.nacon,
|
||||||
],
|
],
|
||||||
outputs=[d.efc.quad],
|
outputs=[d.efc.quad],
|
||||||
)
|
)
|
||||||
|
|
||||||
if m.opt.ls_parallel:
|
if m.opt.ls_parallel:
|
||||||
_linesearch_parallel(m, d)
|
_linesearch_parallel(m, d, cost)
|
||||||
else:
|
else:
|
||||||
_linesearch_iterative(m, d)
|
_linesearch_iterative(m, d)
|
||||||
|
|
||||||
@@ -1064,7 +1063,6 @@ def update_constraint_efc(
|
|||||||
# Model:
|
# Model:
|
||||||
opt_impratio: wp.array(dtype=float),
|
opt_impratio: wp.array(dtype=float),
|
||||||
# Data in:
|
# Data in:
|
||||||
nacon_in: wp.array(dtype=int),
|
|
||||||
ne_in: wp.array(dtype=int),
|
ne_in: wp.array(dtype=int),
|
||||||
nf_in: wp.array(dtype=int),
|
nf_in: wp.array(dtype=int),
|
||||||
nefc_in: wp.array(dtype=int),
|
nefc_in: wp.array(dtype=int),
|
||||||
@@ -1077,6 +1075,7 @@ def update_constraint_efc(
|
|||||||
efc_frictionloss_in: wp.array2d(dtype=float),
|
efc_frictionloss_in: wp.array2d(dtype=float),
|
||||||
efc_Jaref_in: wp.array2d(dtype=float),
|
efc_Jaref_in: wp.array2d(dtype=float),
|
||||||
efc_done_in: wp.array(dtype=bool),
|
efc_done_in: wp.array(dtype=bool),
|
||||||
|
nacon_in: wp.array(dtype=int),
|
||||||
# Data out:
|
# Data out:
|
||||||
efc_force_out: wp.array2d(dtype=float),
|
efc_force_out: wp.array2d(dtype=float),
|
||||||
efc_cost_out: wp.array(dtype=float),
|
efc_cost_out: wp.array(dtype=float),
|
||||||
@@ -1187,11 +1186,11 @@ def update_constraint_efc(
|
|||||||
@wp.kernel
|
@wp.kernel
|
||||||
def update_constraint_init_qfrc_constraint(
|
def update_constraint_init_qfrc_constraint(
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
nefc_in: wp.array(dtype=int),
|
nefc_in: wp.array(dtype=int),
|
||||||
efc_J_in: wp.array3d(dtype=float),
|
efc_J_in: wp.array3d(dtype=float),
|
||||||
efc_force_in: wp.array2d(dtype=float),
|
efc_force_in: wp.array2d(dtype=float),
|
||||||
efc_done_in: wp.array(dtype=bool),
|
efc_done_in: wp.array(dtype=bool),
|
||||||
|
njmax_in: int,
|
||||||
# Data out:
|
# Data out:
|
||||||
qfrc_constraint_out: wp.array2d(dtype=float),
|
qfrc_constraint_out: wp.array2d(dtype=float),
|
||||||
):
|
):
|
||||||
@@ -1251,7 +1250,6 @@ def update_constraint_gauss_cost(nv: int, dofs_per_thread: int):
|
|||||||
|
|
||||||
def _update_constraint(m: types.Model, d: types.Data):
|
def _update_constraint(m: types.Model, d: types.Data):
|
||||||
"""Update constraint arrays after each solve iteration."""
|
"""Update constraint arrays after each solve iteration."""
|
||||||
|
|
||||||
wp.launch(
|
wp.launch(
|
||||||
update_constraint_init_cost,
|
update_constraint_init_cost,
|
||||||
dim=(d.nworld),
|
dim=(d.nworld),
|
||||||
@@ -1264,7 +1262,6 @@ def _update_constraint(m: types.Model, d: types.Data):
|
|||||||
dim=(d.nworld, d.njmax),
|
dim=(d.nworld, d.njmax),
|
||||||
inputs=[
|
inputs=[
|
||||||
m.opt.impratio,
|
m.opt.impratio,
|
||||||
d.nacon,
|
|
||||||
d.ne,
|
d.ne,
|
||||||
d.nf,
|
d.nf,
|
||||||
d.nefc,
|
d.nefc,
|
||||||
@@ -1277,6 +1274,7 @@ def _update_constraint(m: types.Model, d: types.Data):
|
|||||||
d.efc.frictionloss,
|
d.efc.frictionloss,
|
||||||
d.efc.Jaref,
|
d.efc.Jaref,
|
||||||
d.efc.done,
|
d.efc.done,
|
||||||
|
d.nacon,
|
||||||
],
|
],
|
||||||
outputs=[d.efc.force, d.efc.cost, d.efc.state],
|
outputs=[d.efc.force, d.efc.cost, d.efc.state],
|
||||||
)
|
)
|
||||||
@@ -1285,7 +1283,7 @@ def _update_constraint(m: types.Model, d: types.Data):
|
|||||||
wp.launch(
|
wp.launch(
|
||||||
update_constraint_init_qfrc_constraint,
|
update_constraint_init_qfrc_constraint,
|
||||||
dim=(d.nworld, m.nv),
|
dim=(d.nworld, m.nv),
|
||||||
inputs=[d.njmax, d.nefc, d.efc.J, d.efc.force, d.efc.done],
|
inputs=[d.nefc, d.efc.J, d.efc.force, d.efc.done, d.njmax],
|
||||||
outputs=[d.qfrc_constraint],
|
outputs=[d.qfrc_constraint],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1364,100 +1362,150 @@ def update_gradient_set_h_qM_lower_sparse(
|
|||||||
efc_h_out[worldid, i, j] += qM_in[worldid, 0, elementid]
|
efc_h_out[worldid, i, j] += qM_in[worldid, 0, elementid]
|
||||||
|
|
||||||
|
|
||||||
@wp.kernel
|
@wp.func
|
||||||
def update_gradient_JTDAJ_sparse(
|
def state_check(D: float, state: int) -> float:
|
||||||
# Data in:
|
if state == types.ConstraintState.QUADRATIC.value:
|
||||||
njmax_in: int,
|
return D
|
||||||
nefc_in: wp.array(dtype=int),
|
else:
|
||||||
efc_J_in: wp.array3d(dtype=float),
|
return 0.0
|
||||||
efc_D_in: wp.array2d(dtype=float),
|
|
||||||
efc_state_in: wp.array2d(dtype=int),
|
|
||||||
efc_done_in: wp.array(dtype=bool),
|
|
||||||
# Data out:
|
|
||||||
efc_h_out: wp.array3d(dtype=float),
|
|
||||||
):
|
|
||||||
worldid, elementid = wp.tid()
|
|
||||||
|
|
||||||
if efc_done_in[worldid]:
|
|
||||||
return
|
|
||||||
|
|
||||||
nefc = nefc_in[worldid]
|
|
||||||
|
|
||||||
dofi = (int(sqrt(float(1 + 8 * elementid))) - 1) // 2
|
|
||||||
dofj = elementid - (dofi * (dofi + 1)) // 2
|
|
||||||
|
|
||||||
# To optimize the loop, data for the next iteration is prefetched
|
|
||||||
# This allows to parallelize memory load and computation to hide memory latency
|
|
||||||
efc_state = efc_state_in[worldid, 0]
|
|
||||||
efc_D = efc_D_in[worldid, 0]
|
|
||||||
# TODO(team): sparse efc_J
|
|
||||||
efc_Ji = efc_J_in[worldid, 0, dofi]
|
|
||||||
efc_Jj = efc_J_in[worldid, 0, dofj]
|
|
||||||
sum_h = float(0.0)
|
|
||||||
for efcid in range(min(njmax_in, nefc) - 1):
|
|
||||||
if efc_state == types.ConstraintState.QUADRATIC and efc_D != 0.0:
|
|
||||||
sum_h += efc_Ji * efc_Jj * efc_D
|
|
||||||
|
|
||||||
jj = efcid + 1
|
|
||||||
efc_D = efc_D_in[worldid, jj]
|
|
||||||
efc_Ji = efc_J_in[worldid, jj, dofi]
|
|
||||||
efc_Jj = efc_J_in[worldid, jj, dofj]
|
|
||||||
efc_state = efc_state_in[worldid, jj]
|
|
||||||
|
|
||||||
# Adding the contribution from the last constraint row
|
|
||||||
if efc_state == types.ConstraintState.QUADRATIC and efc_D != 0.0:
|
|
||||||
sum_h += efc_Ji * efc_Jj * efc_D
|
|
||||||
|
|
||||||
efc_h_out[worldid, dofi, dofj] = sum_h
|
|
||||||
|
|
||||||
|
|
||||||
@wp.kernel
|
@wp.func
|
||||||
def update_gradient_JTDAJ_dense(
|
def active_check(tid: int, threshold: int) -> float:
|
||||||
# Data in:
|
if tid >= threshold:
|
||||||
njmax_in: int,
|
return 0.0
|
||||||
nefc_in: wp.array(dtype=int),
|
else:
|
||||||
qM_in: wp.array3d(dtype=float),
|
return 1.0
|
||||||
efc_J_in: wp.array3d(dtype=float),
|
|
||||||
efc_D_in: wp.array2d(dtype=float),
|
|
||||||
efc_state_in: wp.array2d(dtype=int),
|
|
||||||
efc_done_in: wp.array(dtype=bool),
|
|
||||||
# Data out:
|
|
||||||
efc_h_out: wp.array3d(dtype=float),
|
|
||||||
):
|
|
||||||
worldid, elementid = wp.tid()
|
|
||||||
|
|
||||||
if efc_done_in[worldid]:
|
|
||||||
return
|
|
||||||
|
|
||||||
nefc = nefc_in[worldid]
|
@cache_kernel
|
||||||
|
def update_gradient_JTDAJ_sparse_tiled(tile_size: int, njmax: int):
|
||||||
|
TILE_SIZE = tile_size
|
||||||
|
|
||||||
dofi = (int(sqrt(float(1 + 8 * elementid))) - 1) // 2
|
@nested_kernel(module="unique", enable_backward=False)
|
||||||
dofj = elementid - (dofi * (dofi + 1)) // 2
|
def kernel(
|
||||||
|
# Data in:
|
||||||
|
nefc_in: wp.array(dtype=int),
|
||||||
|
efc_J_in: wp.array3d(dtype=float),
|
||||||
|
efc_D_in: wp.array2d(dtype=float),
|
||||||
|
efc_state_in: wp.array2d(dtype=int),
|
||||||
|
efc_done_in: wp.array(dtype=bool),
|
||||||
|
# Data out:
|
||||||
|
efc_h_out: wp.array3d(dtype=float),
|
||||||
|
):
|
||||||
|
worldid, elementid = wp.tid()
|
||||||
|
|
||||||
# To optimize the loop, data for the next iteration is prefetched
|
if efc_done_in[worldid]:
|
||||||
# This allows to parallelize memory load and computation to hide memory latency
|
return
|
||||||
efc_state = efc_state_in[worldid, 0]
|
|
||||||
efc_D = efc_D_in[worldid, 0]
|
|
||||||
# TODO(team): sparse efc_J
|
|
||||||
efc_Ji = efc_J_in[worldid, 0, dofi]
|
|
||||||
efc_Jj = efc_J_in[worldid, 0, dofj]
|
|
||||||
sum_h = float(0.0)
|
|
||||||
for efcid in range(min(njmax_in, nefc) - 1):
|
|
||||||
if efc_state == types.ConstraintState.QUADRATIC and efc_D != 0.0:
|
|
||||||
sum_h += efc_Ji * efc_Jj * efc_D
|
|
||||||
|
|
||||||
jj = efcid + 1
|
nefc = nefc_in[worldid]
|
||||||
efc_D = efc_D_in[worldid, jj]
|
|
||||||
efc_Ji = efc_J_in[worldid, jj, dofi]
|
|
||||||
efc_Jj = efc_J_in[worldid, jj, dofj]
|
|
||||||
efc_state = efc_state_in[worldid, jj]
|
|
||||||
|
|
||||||
# Adding the contribution from the last constraint row
|
# get lower diagonal index
|
||||||
if efc_state == types.ConstraintState.QUADRATIC and efc_D != 0.0:
|
i = (int(sqrt(float(1 + 8 * elementid))) - 1) // 2
|
||||||
sum_h += efc_Ji * efc_Jj * efc_D
|
j = elementid - (i * (i + 1)) // 2
|
||||||
|
|
||||||
qM = qM_in[worldid, dofi, dofj]
|
offset_i = i * TILE_SIZE
|
||||||
efc_h_out[worldid, dofi, dofj] = qM + sum_h
|
offset_j = j * TILE_SIZE
|
||||||
|
|
||||||
|
sum_val = wp.tile_zeros(shape=(TILE_SIZE, TILE_SIZE), dtype=wp.float32)
|
||||||
|
|
||||||
|
# Each tile processes looping over all constraints, producing 1 output tile
|
||||||
|
for k in range(0, njmax, TILE_SIZE):
|
||||||
|
if k >= nefc:
|
||||||
|
break
|
||||||
|
|
||||||
|
# AD: leaving bounds-check disabled here because I'm not entirely sure that
|
||||||
|
# everything always hits the fast path. The padding takes care of any
|
||||||
|
# potential OOB accesses.
|
||||||
|
J_ki = wp.tile_load(efc_J_in[worldid], shape=(TILE_SIZE, TILE_SIZE), offset=(k, offset_i), bounds_check=False)
|
||||||
|
|
||||||
|
if offset_i != offset_j:
|
||||||
|
J_kj = wp.tile_load(efc_J_in[worldid], shape=(TILE_SIZE, TILE_SIZE), offset=(k, offset_j), bounds_check=False)
|
||||||
|
else:
|
||||||
|
wp.tile_assign(J_kj, J_ki, (0, 0))
|
||||||
|
|
||||||
|
D_k = wp.tile_load(efc_D_in[worldid], shape=TILE_SIZE, offset=k, bounds_check=False)
|
||||||
|
state = wp.tile_load(efc_state_in[worldid], shape=TILE_SIZE, offset=k, bounds_check=False)
|
||||||
|
|
||||||
|
D_k = wp.tile_map(state_check, D_k, state)
|
||||||
|
|
||||||
|
# force unused elements to be zero
|
||||||
|
tid_tile = wp.tile_arange(TILE_SIZE, dtype=int)
|
||||||
|
threshold_tile = wp.tile_ones(shape=TILE_SIZE, dtype=int) * (nefc - k)
|
||||||
|
|
||||||
|
active_tile = wp.tile_map(active_check, tid_tile, threshold_tile)
|
||||||
|
D_k = wp.tile_map(wp.mul, active_tile, D_k)
|
||||||
|
|
||||||
|
J_ki = wp.tile_map(wp.mul, wp.tile_transpose(J_ki), wp.tile_broadcast(D_k, shape=(TILE_SIZE, TILE_SIZE)))
|
||||||
|
|
||||||
|
sum_val += wp.tile_matmul(J_ki, J_kj)
|
||||||
|
|
||||||
|
# AD: setting bounds_check to True explicitly here because for some reason it was
|
||||||
|
# slower to disable it.
|
||||||
|
wp.tile_store(efc_h_out[worldid], sum_val, offset=(offset_i, offset_j), bounds_check=True)
|
||||||
|
|
||||||
|
return kernel
|
||||||
|
|
||||||
|
|
||||||
|
@cache_kernel
|
||||||
|
def update_gradient_JTDAJ_dense_tiled(nv: int, tile_size: int, njmax: int):
|
||||||
|
if njmax < tile_size:
|
||||||
|
tile_size = njmax
|
||||||
|
|
||||||
|
TILE_SIZE_K = tile_size
|
||||||
|
|
||||||
|
@nested_kernel(module="unique", enable_backward=False)
|
||||||
|
def kernel(
|
||||||
|
# Data in:
|
||||||
|
nefc_in: wp.array(dtype=int),
|
||||||
|
qM_in: wp.array3d(dtype=float),
|
||||||
|
efc_J_in: wp.array3d(dtype=float),
|
||||||
|
efc_D_in: wp.array2d(dtype=float),
|
||||||
|
efc_state_in: wp.array2d(dtype=int),
|
||||||
|
efc_done_in: wp.array(dtype=bool),
|
||||||
|
# Data out:
|
||||||
|
efc_h_out: wp.array3d(dtype=float),
|
||||||
|
):
|
||||||
|
worldid = wp.tid()
|
||||||
|
|
||||||
|
if efc_done_in[worldid]:
|
||||||
|
return
|
||||||
|
|
||||||
|
nefc = nefc_in[worldid]
|
||||||
|
|
||||||
|
sum_val = wp.tile_load(qM_in[worldid], shape=(nv, nv), bounds_check=False)
|
||||||
|
|
||||||
|
# Each tile processes one output tile by looping over all constraints
|
||||||
|
for k in range(0, njmax, TILE_SIZE_K):
|
||||||
|
if k >= nefc:
|
||||||
|
break
|
||||||
|
|
||||||
|
# AD: leaving bounds-check disabled here because I'm not entirely sure that
|
||||||
|
# everything always hits the fast path. The padding takes care of any
|
||||||
|
# potential OOB accesses.
|
||||||
|
J_ki = wp.tile_load(efc_J_in[worldid], shape=(TILE_SIZE_K, nv), offset=(k, 0), bounds_check=False)
|
||||||
|
J_kj = J_ki
|
||||||
|
|
||||||
|
# state check
|
||||||
|
D_k = wp.tile_load(efc_D_in[worldid], shape=TILE_SIZE_K, offset=k, bounds_check=False)
|
||||||
|
state = wp.tile_load(efc_state_in[worldid], shape=TILE_SIZE_K, offset=k, bounds_check=False)
|
||||||
|
|
||||||
|
D_k = wp.tile_map(state_check, D_k, state)
|
||||||
|
|
||||||
|
# force unused elements to be zero
|
||||||
|
tid_tile = wp.tile_arange(TILE_SIZE_K, dtype=int)
|
||||||
|
threshold_tile = wp.tile_ones(shape=TILE_SIZE_K, dtype=int) * (nefc - k)
|
||||||
|
|
||||||
|
active_tile = wp.tile_map(active_check, tid_tile, threshold_tile)
|
||||||
|
D_k = wp.tile_map(wp.mul, active_tile, D_k)
|
||||||
|
|
||||||
|
J_ki = wp.tile_map(wp.mul, wp.tile_transpose(J_ki), wp.tile_broadcast(D_k, shape=(nv, TILE_SIZE_K)))
|
||||||
|
|
||||||
|
sum_val += wp.tile_matmul(J_ki, J_kj)
|
||||||
|
|
||||||
|
wp.tile_store(efc_h_out[worldid], sum_val, bounds_check=False)
|
||||||
|
|
||||||
|
return kernel
|
||||||
|
|
||||||
|
|
||||||
# TODO(thowell): combine with JTDAJ ?
|
# TODO(thowell): combine with JTDAJ ?
|
||||||
@@ -1468,8 +1516,6 @@ def update_gradient_JTCJ(
|
|||||||
dof_tri_row: wp.array(dtype=int),
|
dof_tri_row: wp.array(dtype=int),
|
||||||
dof_tri_col: wp.array(dtype=int),
|
dof_tri_col: wp.array(dtype=int),
|
||||||
# Data in:
|
# Data in:
|
||||||
naconmax_in: int,
|
|
||||||
nacon_in: wp.array(dtype=int),
|
|
||||||
contact_dist_in: wp.array(dtype=float),
|
contact_dist_in: wp.array(dtype=float),
|
||||||
contact_includemargin_in: wp.array(dtype=float),
|
contact_includemargin_in: wp.array(dtype=float),
|
||||||
contact_friction_in: wp.array(dtype=types.vec5),
|
contact_friction_in: wp.array(dtype=types.vec5),
|
||||||
@@ -1481,6 +1527,8 @@ def update_gradient_JTCJ(
|
|||||||
efc_Jaref_in: wp.array2d(dtype=float),
|
efc_Jaref_in: wp.array2d(dtype=float),
|
||||||
efc_state_in: wp.array2d(dtype=int),
|
efc_state_in: wp.array2d(dtype=int),
|
||||||
efc_done_in: wp.array(dtype=bool),
|
efc_done_in: wp.array(dtype=bool),
|
||||||
|
naconmax_in: int,
|
||||||
|
nacon_in: wp.array(dtype=int),
|
||||||
# In:
|
# In:
|
||||||
nblocks_perblock: int,
|
nblocks_perblock: int,
|
||||||
dim_block: int,
|
dim_block: int,
|
||||||
@@ -1670,13 +1718,13 @@ def _update_gradient(m: types.Model, d: types.Data):
|
|||||||
smooth.solve_m(m, d, d.efc.Mgrad, d.efc.grad)
|
smooth.solve_m(m, d, d.efc.Mgrad, d.efc.grad)
|
||||||
elif m.opt.solver == types.SolverType.NEWTON:
|
elif m.opt.solver == types.SolverType.NEWTON:
|
||||||
# h = qM + (efc_J.T * efc_D * active) @ efc_J
|
# h = qM + (efc_J.T * efc_D * active) @ efc_J
|
||||||
lower_triangle_dim = int(m.nv * (m.nv + 1) / 2)
|
|
||||||
if m.opt.is_sparse:
|
if m.opt.is_sparse:
|
||||||
wp.launch(
|
num_blocks_ceil = ceil(m.nv / types.TILE_SIZE_JTDAJ_SPARSE)
|
||||||
update_gradient_JTDAJ_sparse,
|
lower_triangle_dim = int(num_blocks_ceil * (num_blocks_ceil + 1) / 2)
|
||||||
|
wp.launch_tiled(
|
||||||
|
update_gradient_JTDAJ_sparse_tiled(types.TILE_SIZE_JTDAJ_SPARSE, d.njmax),
|
||||||
dim=(d.nworld, lower_triangle_dim),
|
dim=(d.nworld, lower_triangle_dim),
|
||||||
inputs=[
|
inputs=[
|
||||||
d.njmax,
|
|
||||||
d.nefc,
|
d.nefc,
|
||||||
d.efc.J,
|
d.efc.J,
|
||||||
d.efc.D,
|
d.efc.D,
|
||||||
@@ -1684,7 +1732,9 @@ def _update_gradient(m: types.Model, d: types.Data):
|
|||||||
d.efc.done,
|
d.efc.done,
|
||||||
],
|
],
|
||||||
outputs=[d.efc.h],
|
outputs=[d.efc.h],
|
||||||
|
block_dim=m.block_dim.update_gradient_JTDAJ_sparse,
|
||||||
)
|
)
|
||||||
|
|
||||||
wp.launch(
|
wp.launch(
|
||||||
update_gradient_set_h_qM_lower_sparse,
|
update_gradient_set_h_qM_lower_sparse,
|
||||||
dim=(d.nworld, m.qM_fullm_i.size),
|
dim=(d.nworld, m.qM_fullm_i.size),
|
||||||
@@ -1692,11 +1742,10 @@ def _update_gradient(m: types.Model, d: types.Data):
|
|||||||
outputs=[d.efc.h],
|
outputs=[d.efc.h],
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
wp.launch(
|
wp.launch_tiled(
|
||||||
update_gradient_JTDAJ_dense,
|
update_gradient_JTDAJ_dense_tiled(m.nv, types.TILE_SIZE_JTDAJ_DENSE, d.njmax),
|
||||||
dim=(d.nworld, lower_triangle_dim),
|
dim=d.nworld,
|
||||||
inputs=[
|
inputs=[
|
||||||
d.njmax,
|
|
||||||
d.nefc,
|
d.nefc,
|
||||||
d.qM,
|
d.qM,
|
||||||
d.efc.J,
|
d.efc.J,
|
||||||
@@ -1705,6 +1754,7 @@ def _update_gradient(m: types.Model, d: types.Data):
|
|||||||
d.efc.done,
|
d.efc.done,
|
||||||
],
|
],
|
||||||
outputs=[d.efc.h],
|
outputs=[d.efc.h],
|
||||||
|
block_dim=m.block_dim.update_gradient_JTDAJ_dense,
|
||||||
)
|
)
|
||||||
|
|
||||||
if m.opt.cone == types.ConeType.ELLIPTIC:
|
if m.opt.cone == types.ConeType.ELLIPTIC:
|
||||||
@@ -1738,8 +1788,6 @@ def _update_gradient(m: types.Model, d: types.Data):
|
|||||||
m.opt.impratio,
|
m.opt.impratio,
|
||||||
m.dof_tri_row,
|
m.dof_tri_row,
|
||||||
m.dof_tri_col,
|
m.dof_tri_col,
|
||||||
d.naconmax,
|
|
||||||
d.nacon,
|
|
||||||
d.contact.dist,
|
d.contact.dist,
|
||||||
d.contact.includemargin,
|
d.contact.includemargin,
|
||||||
d.contact.friction,
|
d.contact.friction,
|
||||||
@@ -1751,6 +1799,8 @@ def _update_gradient(m: types.Model, d: types.Data):
|
|||||||
d.efc.Jaref,
|
d.efc.Jaref,
|
||||||
d.efc.state,
|
d.efc.state,
|
||||||
d.efc.done,
|
d.efc.done,
|
||||||
|
d.naconmax,
|
||||||
|
d.nacon,
|
||||||
nblocks_perblock,
|
nblocks_perblock,
|
||||||
dim_block,
|
dim_block,
|
||||||
],
|
],
|
||||||
@@ -1888,8 +1938,8 @@ def solve_done(
|
|||||||
efc_done_in: wp.array(dtype=bool),
|
efc_done_in: wp.array(dtype=bool),
|
||||||
# Data out:
|
# Data out:
|
||||||
solver_niter_out: wp.array(dtype=int),
|
solver_niter_out: wp.array(dtype=int),
|
||||||
nsolving_out: wp.array(dtype=int),
|
|
||||||
efc_done_out: wp.array(dtype=bool),
|
efc_done_out: wp.array(dtype=bool),
|
||||||
|
nsolving_out: wp.array(dtype=int),
|
||||||
):
|
):
|
||||||
worldid = wp.tid()
|
worldid = wp.tid()
|
||||||
|
|
||||||
@@ -1897,7 +1947,7 @@ def solve_done(
|
|||||||
return
|
return
|
||||||
|
|
||||||
solver_niter_out[worldid] += 1
|
solver_niter_out[worldid] += 1
|
||||||
tolerance = opt_tolerance[worldid]
|
tolerance = opt_tolerance[worldid % opt_tolerance.shape[0]]
|
||||||
|
|
||||||
improvement = _rescale(nv, stat_meaninertia, efc_prev_cost_in[worldid] - efc_cost_in[worldid])
|
improvement = _rescale(nv, stat_meaninertia, efc_prev_cost_in[worldid] - efc_cost_in[worldid])
|
||||||
gradient = _rescale(nv, stat_meaninertia, wp.math.sqrt(efc_grad_dot_in[worldid]))
|
gradient = _rescale(nv, stat_meaninertia, wp.math.sqrt(efc_grad_dot_in[worldid]))
|
||||||
@@ -1913,8 +1963,9 @@ def solve_done(
|
|||||||
def _solver_iteration(
|
def _solver_iteration(
|
||||||
m: types.Model,
|
m: types.Model,
|
||||||
d: types.Data,
|
d: types.Data,
|
||||||
|
step_size_cost: wp.array2d(dtype=float),
|
||||||
):
|
):
|
||||||
_linesearch(m, d)
|
_linesearch(m, d, step_size_cost)
|
||||||
|
|
||||||
if m.opt.solver == types.SolverType.CG:
|
if m.opt.solver == types.SolverType.CG:
|
||||||
wp.launch(
|
wp.launch(
|
||||||
@@ -1958,7 +2009,7 @@ def _solver_iteration(
|
|||||||
d.efc.prev_cost,
|
d.efc.prev_cost,
|
||||||
d.efc.done,
|
d.efc.done,
|
||||||
],
|
],
|
||||||
outputs=[d.solver_niter, d.nsolving, d.efc.done],
|
outputs=[d.solver_niter, d.efc.done, d.nsolving],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -1979,7 +2030,7 @@ def create_context(m: types.Model, d: types.Data, grad: bool = True):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Ma = qM @ qacc
|
# Ma = qM @ qacc
|
||||||
support.mul_m(m, d, d.efc.Ma, d.qacc, d.efc.done)
|
support.mul_m(m, d, d.efc.Ma, d.qacc, skip=d.efc.done)
|
||||||
|
|
||||||
_update_constraint(m, d)
|
_update_constraint(m, d)
|
||||||
|
|
||||||
@@ -1989,7 +2040,7 @@ def create_context(m: types.Model, d: types.Data, grad: bool = True):
|
|||||||
|
|
||||||
@event_scope
|
@event_scope
|
||||||
def solve(m: types.Model, d: types.Data):
|
def solve(m: types.Model, d: types.Data):
|
||||||
if d.njmax == 0:
|
if d.njmax == 0 or m.nv == 0:
|
||||||
wp.copy(d.qacc, d.qacc_smooth)
|
wp.copy(d.qacc, d.qacc_smooth)
|
||||||
d.solver_niter.fill_(0)
|
d.solver_niter.fill_(0)
|
||||||
else:
|
else:
|
||||||
@@ -2014,6 +2065,8 @@ def _solve(m: types.Model, d: types.Data):
|
|||||||
outputs=[d.efc.search, d.efc.search_dot],
|
outputs=[d.efc.search, d.efc.search_dot],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
step_size_cost = wp.empty((d.nworld, m.opt.ls_iterations if m.opt.ls_parallel else 0), dtype=float)
|
||||||
|
|
||||||
if m.opt.iterations != 0 and m.opt.graph_conditional:
|
if m.opt.iterations != 0 and m.opt.graph_conditional:
|
||||||
# Note: the iteration kernel (indicated by while_body) is repeatedly launched
|
# Note: the iteration kernel (indicated by while_body) is repeatedly launched
|
||||||
# as long as condition_iteration is not zero.
|
# as long as condition_iteration is not zero.
|
||||||
@@ -2028,10 +2081,11 @@ def _solve(m: types.Model, d: types.Data):
|
|||||||
while_body=_solver_iteration,
|
while_body=_solver_iteration,
|
||||||
m=m,
|
m=m,
|
||||||
d=d,
|
d=d,
|
||||||
|
step_size_cost=step_size_cost,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# This branch is mostly for when JAX is used as it is currently not compatible
|
# This branch is mostly for when JAX is used as it is currently not compatible
|
||||||
# with CUDA graph conditional.
|
# with CUDA graph conditional.
|
||||||
# It should be removed when JAX becomes compatible.
|
# It should be removed when JAX becomes compatible.
|
||||||
for _ in range(m.opt.iterations):
|
for _ in range(m.opt.iterations):
|
||||||
_solver_iteration(m, d)
|
_solver_iteration(m, d, step_size_cost)
|
||||||
|
|||||||
+384
-93
@@ -13,19 +13,18 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
from typing import Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
import warp as wp
|
import warp as wp
|
||||||
|
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.collision_primitive import Geom
|
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.math import motion_cross
|
from mujoco.mjx.third_party.mujoco_warp._src.math import motion_cross
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import ConeType
|
from mujoco.mjx.third_party.mujoco_warp._src.types import ConeType
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Data
|
from mujoco.mjx.third_party.mujoco_warp._src.types import Data
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import JointType
|
from mujoco.mjx.third_party.mujoco_warp._src.types import JointType
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import Model
|
from mujoco.mjx.third_party.mujoco_warp._src.types import Model
|
||||||
|
from mujoco.mjx.third_party.mujoco_warp._src.types import State
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import TileSet
|
from mujoco.mjx.third_party.mujoco_warp._src.types import TileSet
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import vec5
|
from mujoco.mjx.third_party.mujoco_warp._src.types import vec5
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.types import vec6
|
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import cache_kernel
|
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
|
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import event_scope
|
||||||
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import kernel as nested_kernel
|
from mujoco.mjx.third_party.mujoco_warp._src.warp_util import kernel as nested_kernel
|
||||||
@@ -33,63 +32,73 @@ from mujoco.mjx.third_party.mujoco_warp._src.warp_util import kernel as nested_k
|
|||||||
wp.set_module_options({"enable_backward": False})
|
wp.set_module_options({"enable_backward": False})
|
||||||
|
|
||||||
|
|
||||||
@wp.kernel
|
@cache_kernel
|
||||||
def mul_m_sparse_diag(
|
def mul_m_sparse_diag(check_skip: bool):
|
||||||
# Model:
|
@nested_kernel(module="unique", enable_backward=False)
|
||||||
dof_Madr: wp.array(dtype=int),
|
def _mul_m_sparse_diag(
|
||||||
# Data in:
|
# Model:
|
||||||
qM_in: wp.array3d(dtype=float),
|
dof_Madr: wp.array(dtype=int),
|
||||||
# In:
|
# Data in:
|
||||||
vec: wp.array2d(dtype=float),
|
qM_in: wp.array3d(dtype=float),
|
||||||
skip: wp.array(dtype=bool),
|
# In:
|
||||||
# Out:
|
vec: wp.array2d(dtype=float),
|
||||||
res: wp.array2d(dtype=float),
|
skip: wp.array(dtype=bool),
|
||||||
):
|
# Out:
|
||||||
"""Diagonal update for sparse matmul."""
|
res: wp.array2d(dtype=float),
|
||||||
worldid, dofid = wp.tid()
|
):
|
||||||
|
"""Diagonal update for sparse matmul."""
|
||||||
|
worldid, dofid = wp.tid()
|
||||||
|
|
||||||
if skip[worldid]:
|
if wp.static(check_skip):
|
||||||
return
|
if skip[worldid]:
|
||||||
|
return
|
||||||
|
|
||||||
res[worldid, dofid] = qM_in[worldid, 0, dof_Madr[dofid]] * vec[worldid, dofid]
|
res[worldid, dofid] = qM_in[worldid, 0, dof_Madr[dofid]] * vec[worldid, dofid]
|
||||||
|
|
||||||
|
return _mul_m_sparse_diag
|
||||||
@wp.kernel
|
|
||||||
def mul_m_sparse_ij(
|
|
||||||
# Model:
|
|
||||||
qM_mulm_i: wp.array(dtype=int),
|
|
||||||
qM_mulm_j: wp.array(dtype=int),
|
|
||||||
qM_madr_ij: wp.array(dtype=int),
|
|
||||||
# Data in:
|
|
||||||
qM_in: wp.array3d(dtype=float),
|
|
||||||
# In:
|
|
||||||
vec: wp.array2d(dtype=float),
|
|
||||||
skip: wp.array(dtype=bool),
|
|
||||||
# Out:
|
|
||||||
res: wp.array2d(dtype=float),
|
|
||||||
):
|
|
||||||
"""Off-diagonal update for sparse matmul."""
|
|
||||||
worldid, elementid = wp.tid()
|
|
||||||
|
|
||||||
if skip[worldid]:
|
|
||||||
return
|
|
||||||
|
|
||||||
i = qM_mulm_i[elementid]
|
|
||||||
j = qM_mulm_j[elementid]
|
|
||||||
madr_ij = qM_madr_ij[elementid]
|
|
||||||
|
|
||||||
qM_ij = qM_in[worldid, 0, madr_ij]
|
|
||||||
|
|
||||||
wp.atomic_add(res[worldid], i, qM_ij * vec[worldid, j])
|
|
||||||
wp.atomic_add(res[worldid], j, qM_ij * vec[worldid, i])
|
|
||||||
|
|
||||||
|
|
||||||
@cache_kernel
|
@cache_kernel
|
||||||
def mul_m_dense(tile: TileSet):
|
def mul_m_sparse_ij(check_skip: bool):
|
||||||
"""Returns a matmul kernel for some tile size"""
|
@nested_kernel(module="unique", enable_backward=False)
|
||||||
|
def _mul_m_sparse_ij(
|
||||||
|
# Model:
|
||||||
|
qM_mulm_i: wp.array(dtype=int),
|
||||||
|
qM_mulm_j: wp.array(dtype=int),
|
||||||
|
qM_madr_ij: wp.array(dtype=int),
|
||||||
|
# Data in:
|
||||||
|
qM_in: wp.array3d(dtype=float),
|
||||||
|
# In:
|
||||||
|
vec: wp.array2d(dtype=float),
|
||||||
|
skip: wp.array(dtype=bool),
|
||||||
|
# Out:
|
||||||
|
res: wp.array2d(dtype=float),
|
||||||
|
):
|
||||||
|
"""Off-diagonal update for sparse matmul."""
|
||||||
|
worldid, elementid = wp.tid()
|
||||||
|
|
||||||
|
if wp.static(check_skip):
|
||||||
|
if skip[worldid]:
|
||||||
|
return
|
||||||
|
|
||||||
|
i = qM_mulm_i[elementid]
|
||||||
|
j = qM_mulm_j[elementid]
|
||||||
|
madr_ij = qM_madr_ij[elementid]
|
||||||
|
|
||||||
|
qM_ij = qM_in[worldid, 0, madr_ij]
|
||||||
|
|
||||||
|
wp.atomic_add(res[worldid], i, qM_ij * vec[worldid, j])
|
||||||
|
wp.atomic_add(res[worldid], j, qM_ij * vec[worldid, i])
|
||||||
|
|
||||||
|
return _mul_m_sparse_ij
|
||||||
|
|
||||||
|
|
||||||
|
@cache_kernel
|
||||||
|
def mul_m_dense(tile: TileSet, check_skip: bool):
|
||||||
|
"""Returns a matmul kernel for some tile size."""
|
||||||
|
|
||||||
@nested_kernel(module="unique", enable_backward=False)
|
@nested_kernel(module="unique", enable_backward=False)
|
||||||
def kernel(
|
def _mul_m_dense(
|
||||||
# Data In:
|
# Data In:
|
||||||
qM_in: wp.array3d(dtype=float),
|
qM_in: wp.array3d(dtype=float),
|
||||||
# In:
|
# In:
|
||||||
@@ -102,8 +111,9 @@ def mul_m_dense(tile: TileSet):
|
|||||||
worldid, nodeid = wp.tid()
|
worldid, nodeid = wp.tid()
|
||||||
TILE_SIZE = wp.static(tile.size)
|
TILE_SIZE = wp.static(tile.size)
|
||||||
|
|
||||||
if skip[worldid]:
|
if wp.static(check_skip):
|
||||||
return
|
if skip[worldid]:
|
||||||
|
return
|
||||||
|
|
||||||
dofid = adr[nodeid]
|
dofid = adr[nodeid]
|
||||||
qM_tile = wp.tile_load(qM_in[worldid], shape=(TILE_SIZE, TILE_SIZE), offset=(dofid, dofid))
|
qM_tile = wp.tile_load(qM_in[worldid], shape=(TILE_SIZE, TILE_SIZE), offset=(dofid, dofid))
|
||||||
@@ -111,7 +121,7 @@ def mul_m_dense(tile: TileSet):
|
|||||||
res_tile = wp.tile_matmul(qM_tile, vec_tile)
|
res_tile = wp.tile_matmul(qM_tile, vec_tile)
|
||||||
wp.tile_store(res[worldid], res_tile, offset=(dofid, 0))
|
wp.tile_store(res[worldid], res_tile, offset=(dofid, 0))
|
||||||
|
|
||||||
return kernel
|
return _mul_m_dense
|
||||||
|
|
||||||
|
|
||||||
@event_scope
|
@event_scope
|
||||||
@@ -120,33 +130,35 @@ def mul_m(
|
|||||||
d: Data,
|
d: Data,
|
||||||
res: wp.array2d(dtype=float),
|
res: wp.array2d(dtype=float),
|
||||||
vec: wp.array2d(dtype=float),
|
vec: wp.array2d(dtype=float),
|
||||||
skip: wp.array(dtype=bool),
|
skip: Optional[wp.array] = None,
|
||||||
M: wp.array3d(dtype=float) = None,
|
M: Optional[wp.array] = None,
|
||||||
):
|
):
|
||||||
"""Multiply vectors by inertia matrix.
|
"""Multiply vectors by inertia matrix; optionally skip per world.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
m (Model): The model containing kinematic and dynamic information (device).
|
m: The model containing kinematic and dynamic information (device).
|
||||||
d (Data): The data object containing the current state and output arrays (device).
|
d: The data object containing the current state and output arrays (device).
|
||||||
res (wp.array2d(dtype=float)): Result: qM @ vec.
|
res: Result: qM @ vec.
|
||||||
vec (wp.array2d(dtype=float)): Input vector to multiply by qM.
|
vec: Input vector to multiply by qM.
|
||||||
skip (wp.array(dtype=flooat)): Skip output.
|
skip: Per-world bitmask to skip computing output.
|
||||||
M (wp.array3d(dtype=float), optional): Input matrix: M @ vec.
|
M: Input matrix: M @ vec.
|
||||||
"""
|
"""
|
||||||
|
check_skip = skip is not None
|
||||||
|
skip = skip or wp.empty(0, dtype=bool)
|
||||||
|
|
||||||
if M is None:
|
if M is None:
|
||||||
M = d.qM
|
M = d.qM
|
||||||
|
|
||||||
if m.opt.is_sparse:
|
if m.opt.is_sparse:
|
||||||
wp.launch(
|
wp.launch(
|
||||||
mul_m_sparse_diag,
|
mul_m_sparse_diag(check_skip),
|
||||||
dim=(d.nworld, m.nv),
|
dim=(d.nworld, m.nv),
|
||||||
inputs=[m.dof_Madr, M, vec, skip],
|
inputs=[m.dof_Madr, M, vec, skip],
|
||||||
outputs=[res],
|
outputs=[res],
|
||||||
)
|
)
|
||||||
|
|
||||||
wp.launch(
|
wp.launch(
|
||||||
mul_m_sparse_ij,
|
mul_m_sparse_ij(check_skip),
|
||||||
dim=(d.nworld, m.qM_madr_ij.size),
|
dim=(d.nworld, m.qM_madr_ij.size),
|
||||||
inputs=[m.qM_mulm_i, m.qM_mulm_j, m.qM_madr_ij, M, vec, skip],
|
inputs=[m.qM_mulm_i, m.qM_mulm_j, m.qM_madr_ij, M, vec, skip],
|
||||||
outputs=[res],
|
outputs=[res],
|
||||||
@@ -155,7 +167,7 @@ def mul_m(
|
|||||||
else:
|
else:
|
||||||
for tile in m.qM_tiles:
|
for tile in m.qM_tiles:
|
||||||
wp.launch_tiled(
|
wp.launch_tiled(
|
||||||
mul_m_dense(tile),
|
mul_m_dense(tile, check_skip),
|
||||||
dim=(d.nworld, tile.adr.size),
|
dim=(d.nworld, tile.adr.size),
|
||||||
inputs=[
|
inputs=[
|
||||||
M,
|
M,
|
||||||
@@ -225,13 +237,12 @@ def apply_ft(m: Model, d: Data, ft: wp.array2d(dtype=wp.spatial_vector), qfrc: w
|
|||||||
|
|
||||||
@event_scope
|
@event_scope
|
||||||
def xfrc_accumulate(m: Model, d: Data, qfrc: wp.array2d(dtype=float)):
|
def xfrc_accumulate(m: Model, d: Data, qfrc: wp.array2d(dtype=float)):
|
||||||
"""
|
"""Map applied forces at each body via Jacobians to dof space and accumulate.
|
||||||
Map applied forces at each body via Jacobians to dof space and accumulate.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
m (Model): The model containing kinematic and dynamic information (device).
|
m: The model containing kinematic and dynamic information (device).
|
||||||
d (Data): The data object containing the current state and output arrays (device).
|
d: The data object containing the current state and output arrays (device).
|
||||||
qfrc (wp.array2d(dtype=float)): Total applied force mapped to dof space.
|
qfrc: Total applied force mapped to dof space.
|
||||||
"""
|
"""
|
||||||
apply_ft(m, d, d.xfrc_applied, qfrc, True)
|
apply_ft(m, d, d.xfrc_applied, qfrc, True)
|
||||||
|
|
||||||
@@ -295,13 +306,13 @@ def contact_force_fn(
|
|||||||
# Model:
|
# Model:
|
||||||
opt_cone: int,
|
opt_cone: int,
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
nacon_in: wp.array(dtype=int),
|
|
||||||
contact_frame_in: wp.array(dtype=wp.mat33),
|
contact_frame_in: wp.array(dtype=wp.mat33),
|
||||||
contact_friction_in: wp.array(dtype=vec5),
|
contact_friction_in: wp.array(dtype=vec5),
|
||||||
contact_dim_in: wp.array(dtype=int),
|
contact_dim_in: wp.array(dtype=int),
|
||||||
contact_efc_address_in: wp.array2d(dtype=int),
|
contact_efc_address_in: wp.array2d(dtype=int),
|
||||||
efc_force_in: wp.array2d(dtype=float),
|
efc_force_in: wp.array2d(dtype=float),
|
||||||
|
njmax_in: int,
|
||||||
|
nacon_in: wp.array(dtype=int),
|
||||||
# In:
|
# In:
|
||||||
worldid: int,
|
worldid: int,
|
||||||
contact_id: int,
|
contact_id: int,
|
||||||
@@ -340,14 +351,14 @@ def contact_force_kernel(
|
|||||||
# Model:
|
# Model:
|
||||||
opt_cone: int,
|
opt_cone: int,
|
||||||
# Data in:
|
# Data in:
|
||||||
njmax_in: int,
|
|
||||||
nacon_in: wp.array(dtype=int),
|
|
||||||
contact_frame_in: wp.array(dtype=wp.mat33),
|
contact_frame_in: wp.array(dtype=wp.mat33),
|
||||||
contact_friction_in: wp.array(dtype=vec5),
|
contact_friction_in: wp.array(dtype=vec5),
|
||||||
contact_dim_in: wp.array(dtype=int),
|
contact_dim_in: wp.array(dtype=int),
|
||||||
contact_efc_address_in: wp.array2d(dtype=int),
|
contact_efc_address_in: wp.array2d(dtype=int),
|
||||||
contact_worldid_in: wp.array(dtype=int),
|
contact_worldid_in: wp.array(dtype=int),
|
||||||
efc_force_in: wp.array2d(dtype=float),
|
efc_force_in: wp.array2d(dtype=float),
|
||||||
|
njmax_in: int,
|
||||||
|
nacon_in: wp.array(dtype=int),
|
||||||
# In:
|
# In:
|
||||||
contact_ids: wp.array(dtype=int),
|
contact_ids: wp.array(dtype=int),
|
||||||
to_world_frame: bool,
|
to_world_frame: bool,
|
||||||
@@ -365,13 +376,13 @@ def contact_force_kernel(
|
|||||||
|
|
||||||
out[tid] = contact_force_fn(
|
out[tid] = contact_force_fn(
|
||||||
opt_cone,
|
opt_cone,
|
||||||
njmax_in,
|
|
||||||
nacon_in,
|
|
||||||
contact_frame_in,
|
contact_frame_in,
|
||||||
contact_friction_in,
|
contact_friction_in,
|
||||||
contact_dim_in,
|
contact_dim_in,
|
||||||
contact_efc_address_in,
|
contact_efc_address_in,
|
||||||
efc_force_in,
|
efc_force_in,
|
||||||
|
njmax_in,
|
||||||
|
nacon_in,
|
||||||
worldid,
|
worldid,
|
||||||
contactid,
|
contactid,
|
||||||
to_world_frame,
|
to_world_frame,
|
||||||
@@ -379,35 +390,30 @@ def contact_force_kernel(
|
|||||||
|
|
||||||
|
|
||||||
def contact_force(
|
def contact_force(
|
||||||
m: Model,
|
m: Model, d: Data, contact_ids: wp.array(dtype=int), to_world_frame: bool, force: wp.array(dtype=wp.spatial_vector)
|
||||||
d: Data,
|
|
||||||
contact_ids: wp.array(dtype=int),
|
|
||||||
to_world_frame: bool,
|
|
||||||
force: wp.array(dtype=wp.spatial_vector),
|
|
||||||
):
|
):
|
||||||
"""
|
"""Compute forces for contacts in Data.
|
||||||
Compute forces for contacts in Data.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
m (Model): The model containing kinematic and dynamic information (device).
|
m: The model containing kinematic and dynamic information (device).
|
||||||
d (Data): The data object containing the current state and output arrays (device).
|
d: The data object containing the current state and output arrays (device).
|
||||||
contact_ids (wp.array(dtype=int)): IDs for each contact.
|
contact_ids: IDs for each contact.
|
||||||
to_world_frame (bool): If True, map force from contact to world frame.
|
to_world_frame: If True, map force from contact to world frame.
|
||||||
force (wp.array(dtype=wp.spatial_vector)): Contact forces.
|
force: Contact forces.
|
||||||
"""
|
"""
|
||||||
wp.launch(
|
wp.launch(
|
||||||
contact_force_kernel,
|
contact_force_kernel,
|
||||||
dim=(contact_ids.size,),
|
dim=contact_ids.size,
|
||||||
inputs=[
|
inputs=[
|
||||||
m.opt.cone,
|
m.opt.cone,
|
||||||
d.njmax,
|
|
||||||
d.nacon,
|
|
||||||
d.contact.frame,
|
d.contact.frame,
|
||||||
d.contact.friction,
|
d.contact.friction,
|
||||||
d.contact.dim,
|
d.contact.dim,
|
||||||
d.contact.efc_address,
|
d.contact.efc_address,
|
||||||
d.contact.worldid,
|
d.contact.worldid,
|
||||||
d.efc.force,
|
d.efc.force,
|
||||||
|
d.njmax,
|
||||||
|
d.nacon,
|
||||||
contact_ids,
|
contact_ids,
|
||||||
to_world_frame,
|
to_world_frame,
|
||||||
],
|
],
|
||||||
@@ -532,3 +538,288 @@ def jac_dot(
|
|||||||
jacr = cdof_dot_ang
|
jacr = cdof_dot_ang
|
||||||
|
|
||||||
return jacp, jacr
|
return jacp, jacr
|
||||||
|
|
||||||
|
|
||||||
|
def get_state(m: Model, d: Data, state: wp.array2d(dtype=float), sig: int, active: Optional[wp.array] = None):
|
||||||
|
"""Copy concatenated state components specified by sig from Data into state.
|
||||||
|
|
||||||
|
The bits of the integer sig correspond to element fields of State.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
m: The model containing kinematic and dynamic information (device).
|
||||||
|
d: The data object containing the current state and output information (device).
|
||||||
|
state: Concatenation of state components.
|
||||||
|
sig: Bitflag specifying state components.
|
||||||
|
active: Per-world bitmask for getting state.
|
||||||
|
"""
|
||||||
|
if sig >= (1 << State.NSTATE):
|
||||||
|
raise ValueError(f"invalid state signature {sig} >= 2^mjNSTATE")
|
||||||
|
|
||||||
|
@nested_kernel(module="unique", enable_backward=False)
|
||||||
|
def _get_state(
|
||||||
|
# Model:
|
||||||
|
nq: int,
|
||||||
|
nv: int,
|
||||||
|
nu: int,
|
||||||
|
na: int,
|
||||||
|
nbody: int,
|
||||||
|
neq: int,
|
||||||
|
nmocap: int,
|
||||||
|
# Data in:
|
||||||
|
time_in: wp.array(dtype=float),
|
||||||
|
qpos_in: wp.array2d(dtype=float),
|
||||||
|
qvel_in: wp.array2d(dtype=float),
|
||||||
|
act_in: wp.array2d(dtype=float),
|
||||||
|
qacc_warmstart_in: wp.array2d(dtype=float),
|
||||||
|
ctrl_in: wp.array2d(dtype=float),
|
||||||
|
qfrc_applied_in: wp.array2d(dtype=float),
|
||||||
|
xfrc_applied_in: wp.array2d(dtype=wp.spatial_vector),
|
||||||
|
eq_active_in: wp.array2d(dtype=bool),
|
||||||
|
mocap_pos_in: wp.array2d(dtype=wp.vec3),
|
||||||
|
mocap_quat_in: wp.array2d(dtype=wp.quat),
|
||||||
|
# In:
|
||||||
|
sig_in: int,
|
||||||
|
active_in: wp.array(dtype=bool),
|
||||||
|
# Out:
|
||||||
|
state_out: wp.array2d(dtype=float),
|
||||||
|
):
|
||||||
|
worldid = wp.tid()
|
||||||
|
|
||||||
|
if wp.static(active is not None):
|
||||||
|
if not active_in[worldid]:
|
||||||
|
return
|
||||||
|
|
||||||
|
adr = int(0)
|
||||||
|
for i in range(State.NSTATE.value):
|
||||||
|
element = 1 << i
|
||||||
|
if element & sig_in:
|
||||||
|
if element == State.TIME:
|
||||||
|
state_out[worldid, adr] = time_in[worldid]
|
||||||
|
adr += 1
|
||||||
|
elif element == State.QPOS:
|
||||||
|
for j in range(nq):
|
||||||
|
state_out[worldid, adr + j] = qpos_in[worldid, j]
|
||||||
|
adr += nq
|
||||||
|
elif element == State.QVEL:
|
||||||
|
for j in range(nv):
|
||||||
|
state_out[worldid, adr + j] = qvel_in[worldid, j]
|
||||||
|
adr += nv
|
||||||
|
elif element == State.ACT:
|
||||||
|
for j in range(na):
|
||||||
|
state_out[worldid, adr + j] = act_in[worldid, j]
|
||||||
|
adr += na
|
||||||
|
elif element == State.WARMSTART:
|
||||||
|
for j in range(nv):
|
||||||
|
state_out[worldid, adr + j] = qacc_warmstart_in[worldid, j]
|
||||||
|
adr += nv
|
||||||
|
elif element == State.CTRL:
|
||||||
|
for j in range(nu):
|
||||||
|
state_out[worldid, adr + j] = ctrl_in[worldid, j]
|
||||||
|
adr += nu
|
||||||
|
elif element == State.QFRC_APPLIED:
|
||||||
|
for j in range(nv):
|
||||||
|
state_out[worldid, adr + j] = qfrc_applied_in[worldid, j]
|
||||||
|
adr += nv
|
||||||
|
elif element == State.XFRC_APPLIED:
|
||||||
|
for j in range(nbody):
|
||||||
|
xfrc = xfrc_applied_in[worldid, j]
|
||||||
|
state_out[worldid, adr + 0] = xfrc[0]
|
||||||
|
state_out[worldid, adr + 1] = xfrc[1]
|
||||||
|
state_out[worldid, adr + 2] = xfrc[2]
|
||||||
|
state_out[worldid, adr + 3] = xfrc[3]
|
||||||
|
state_out[worldid, adr + 4] = xfrc[4]
|
||||||
|
state_out[worldid, adr + 5] = xfrc[5]
|
||||||
|
adr += 6
|
||||||
|
elif element == State.EQ_ACTIVE:
|
||||||
|
for j in range(neq):
|
||||||
|
state_out[worldid, adr + j] = float(eq_active_in[worldid, j])
|
||||||
|
adr += j
|
||||||
|
elif element == State.MOCAP_POS:
|
||||||
|
for j in range(nmocap):
|
||||||
|
pos = mocap_pos_in[worldid, j]
|
||||||
|
state_out[worldid, adr + 0] = pos[0]
|
||||||
|
state_out[worldid, adr + 1] = pos[1]
|
||||||
|
state_out[worldid, adr + 2] = pos[2]
|
||||||
|
adr += 3
|
||||||
|
elif element == State.MOCAP_QUAT:
|
||||||
|
for j in range(nmocap):
|
||||||
|
quat = mocap_quat_in[worldid, j]
|
||||||
|
state_out[worldid, adr + 0] = quat[0]
|
||||||
|
state_out[worldid, adr + 1] = quat[1]
|
||||||
|
state_out[worldid, adr + 2] = quat[2]
|
||||||
|
state_out[worldid, adr + 3] = quat[3]
|
||||||
|
adr += 4
|
||||||
|
|
||||||
|
wp.launch(
|
||||||
|
_get_state,
|
||||||
|
dim=d.nworld,
|
||||||
|
inputs=[
|
||||||
|
m.nq,
|
||||||
|
m.nv,
|
||||||
|
m.nu,
|
||||||
|
m.na,
|
||||||
|
m.nbody,
|
||||||
|
m.neq,
|
||||||
|
m.nmocap,
|
||||||
|
d.time,
|
||||||
|
d.qpos,
|
||||||
|
d.qvel,
|
||||||
|
d.act,
|
||||||
|
d.qacc_warmstart,
|
||||||
|
d.ctrl,
|
||||||
|
d.qfrc_applied,
|
||||||
|
d.xfrc_applied,
|
||||||
|
d.eq_active,
|
||||||
|
d.mocap_pos,
|
||||||
|
d.mocap_quat,
|
||||||
|
int(sig),
|
||||||
|
active or wp.ones(d.nworld, dtype=bool),
|
||||||
|
],
|
||||||
|
outputs=[state],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def set_state(m: Model, d: Data, state: wp.array2d(dtype=float), sig: int, active: Optional[wp.array] = None):
|
||||||
|
"""Copy concatenated state components specified by sig from state into Data.
|
||||||
|
|
||||||
|
The bits of the integer sig correspond to element fields of State.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
m: The model containing kinematic and dynamic information (device).
|
||||||
|
d: The data object containing the current state and output information (device).
|
||||||
|
state: Concatenation of state components.
|
||||||
|
sig: Bitflag specifying state components.
|
||||||
|
active: Per-world bitmask for setting state.
|
||||||
|
"""
|
||||||
|
if sig >= (1 << State.NSTATE):
|
||||||
|
raise ValueError(f"invalid state signature {sig} >= 2^mjNSTATE")
|
||||||
|
|
||||||
|
@nested_kernel(module="unique", enable_backward=False)
|
||||||
|
def _set_state(
|
||||||
|
# Model:
|
||||||
|
nq: int,
|
||||||
|
nv: int,
|
||||||
|
nu: int,
|
||||||
|
na: int,
|
||||||
|
nbody: int,
|
||||||
|
neq: int,
|
||||||
|
nmocap: int,
|
||||||
|
# In:
|
||||||
|
sig_in: int,
|
||||||
|
active_in: wp.array(dtype=bool),
|
||||||
|
state_in: wp.array2d(dtype=float),
|
||||||
|
# Data out:
|
||||||
|
time_out: wp.array(dtype=float),
|
||||||
|
qpos_out: wp.array2d(dtype=float),
|
||||||
|
qvel_out: wp.array2d(dtype=float),
|
||||||
|
act_out: wp.array2d(dtype=float),
|
||||||
|
qacc_warmstart_out: wp.array2d(dtype=float),
|
||||||
|
ctrl_out: wp.array2d(dtype=float),
|
||||||
|
qfrc_applied_out: wp.array2d(dtype=float),
|
||||||
|
xfrc_applied_out: wp.array2d(dtype=wp.spatial_vector),
|
||||||
|
eq_active_out: wp.array2d(dtype=bool),
|
||||||
|
mocap_pos_out: wp.array2d(dtype=wp.vec3),
|
||||||
|
mocap_quat_out: wp.array2d(dtype=wp.quat),
|
||||||
|
):
|
||||||
|
worldid = wp.tid()
|
||||||
|
|
||||||
|
if wp.static(active is not None):
|
||||||
|
if not active_in[worldid]:
|
||||||
|
return
|
||||||
|
|
||||||
|
adr = int(0)
|
||||||
|
for i in range(State.NSTATE.value):
|
||||||
|
element = 1 << i
|
||||||
|
if element & sig_in:
|
||||||
|
if element == State.TIME:
|
||||||
|
time_out[worldid] = state_in[worldid, adr]
|
||||||
|
adr += 1
|
||||||
|
elif element == State.QPOS:
|
||||||
|
for j in range(nq):
|
||||||
|
qpos_out[worldid, j] = state_in[worldid, adr + j]
|
||||||
|
adr += nq
|
||||||
|
elif element == State.QVEL:
|
||||||
|
for j in range(nv):
|
||||||
|
qvel_out[worldid, j] = state_in[worldid, adr + j]
|
||||||
|
adr += nv
|
||||||
|
elif element == State.ACT:
|
||||||
|
for j in range(na):
|
||||||
|
act_out[worldid, j] = state_in[worldid, adr + j]
|
||||||
|
adr += na
|
||||||
|
elif element == State.WARMSTART:
|
||||||
|
for j in range(nv):
|
||||||
|
qacc_warmstart_out[worldid, j] = state_in[worldid, adr + j]
|
||||||
|
adr += nv
|
||||||
|
elif element == State.CTRL:
|
||||||
|
for j in range(nu):
|
||||||
|
ctrl_out[worldid, j] = state_in[worldid, adr + j]
|
||||||
|
adr += nu
|
||||||
|
elif element == State.QFRC_APPLIED:
|
||||||
|
for j in range(nv):
|
||||||
|
qfrc_applied_out[worldid, j] = state_in[worldid, adr + j]
|
||||||
|
adr += nv
|
||||||
|
elif element == State.XFRC_APPLIED:
|
||||||
|
for j in range(nbody):
|
||||||
|
xfrc = wp.spatial_vector(
|
||||||
|
state_in[worldid, adr + 0],
|
||||||
|
state_in[worldid, adr + 1],
|
||||||
|
state_in[worldid, adr + 2],
|
||||||
|
state_in[worldid, adr + 3],
|
||||||
|
state_in[worldid, adr + 4],
|
||||||
|
state_in[worldid, adr + 5],
|
||||||
|
)
|
||||||
|
xfrc_applied_out[worldid, j] = xfrc
|
||||||
|
adr += 6
|
||||||
|
elif element == State.EQ_ACTIVE:
|
||||||
|
for j in range(neq):
|
||||||
|
eq_active_out[worldid, j] = bool(state_in[worldid, adr + j])
|
||||||
|
adr += j
|
||||||
|
elif element == State.MOCAP_POS:
|
||||||
|
for j in range(nmocap):
|
||||||
|
pos = wp.vec3(
|
||||||
|
state_in[worldid, adr + 1],
|
||||||
|
state_in[worldid, adr + 0],
|
||||||
|
state_in[worldid, adr + 2],
|
||||||
|
)
|
||||||
|
mocap_pos_out[worldid, j] = pos
|
||||||
|
adr += 3
|
||||||
|
elif element == State.MOCAP_QUAT:
|
||||||
|
for j in range(nmocap):
|
||||||
|
quat = wp.quat(
|
||||||
|
state_in[worldid, adr + 0],
|
||||||
|
state_in[worldid, adr + 1],
|
||||||
|
state_in[worldid, adr + 2],
|
||||||
|
state_in[worldid, adr + 3],
|
||||||
|
)
|
||||||
|
mocap_quat_out[worldid, j] = quat
|
||||||
|
adr += 4
|
||||||
|
|
||||||
|
wp.launch(
|
||||||
|
_set_state,
|
||||||
|
dim=d.nworld,
|
||||||
|
inputs=[
|
||||||
|
m.nq,
|
||||||
|
m.nv,
|
||||||
|
m.nu,
|
||||||
|
m.na,
|
||||||
|
m.nbody,
|
||||||
|
m.neq,
|
||||||
|
m.nmocap,
|
||||||
|
int(sig),
|
||||||
|
active or wp.ones(d.nworld, dtype=bool),
|
||||||
|
state,
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
d.time,
|
||||||
|
d.qpos,
|
||||||
|
d.qvel,
|
||||||
|
d.act,
|
||||||
|
d.qacc_warmstart,
|
||||||
|
d.ctrl,
|
||||||
|
d.qfrc_applied,
|
||||||
|
d.xfrc_applied,
|
||||||
|
d.eq_active,
|
||||||
|
d.mocap_pos,
|
||||||
|
d.mocap_quat,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|||||||
+455
-499
File diff suppressed because it is too large
Load Diff
+26
-32
@@ -37,7 +37,7 @@ def is_intersect(p1: wp.vec2, p2: wp.vec2, p3: wp.vec2, p4: wp.vec2) -> bool:
|
|||||||
p4: 2D point from segment 2
|
p4: 2D point from segment 2
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
intersection status of line segments
|
Intersection status of line segments.
|
||||||
"""
|
"""
|
||||||
# compute determinant, check
|
# compute determinant, check
|
||||||
det = (p4[1] - p3[1]) * (p2[0] - p1[0]) - (p4[0] - p3[0]) * (p2[1] - p1[1])
|
det = (p4[1] - p3[1]) * (p2[0] - p1[0]) - (p4[0] - p3[0]) * (p2[1] - p1[1])
|
||||||
@@ -77,13 +77,13 @@ def length_circle(p0: wp.vec2, p1: wp.vec2, ind: int, radius: float) -> float:
|
|||||||
"""Curve length along circle.
|
"""Curve length along circle.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
p0: 2D point
|
p0: 2D point.
|
||||||
p1: 2D point
|
p1: 2D point.
|
||||||
ind: input for flip
|
ind: input for flip.
|
||||||
radius: circle radius
|
radius: circle radius.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
curve length
|
Curve length.
|
||||||
"""
|
"""
|
||||||
# compute angle between 0 and pi
|
# compute angle between 0 and pi
|
||||||
p0n, _ = math.normalize_with_norm(p0)
|
p0n, _ = math.normalize_with_norm(p0)
|
||||||
@@ -104,12 +104,12 @@ def wrap_circle(end: wp.vec4, side: wp.vec2, radius: float) -> Tuple[float, wp.v
|
|||||||
"""2D circle wrap.
|
"""2D circle wrap.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
end: two 2D points
|
end: Two 2D points.
|
||||||
side: optional 2D side point, no side point: wp.vec2(wp.inf)
|
side: Optional 2D side point, no side point: wp.vec2(wp.inf).
|
||||||
radius: circle radius
|
radius: Circle radius.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
length of circular wrap or -1.0 if no wrap, pair of 2D wrap points
|
Length of circular wrap or -1.0 if no wrap, pair of 2D wrap points.
|
||||||
"""
|
"""
|
||||||
valid_side = wp.norm_l2(side) < wp.inf
|
valid_side = wp.norm_l2(side) < wp.inf
|
||||||
|
|
||||||
@@ -210,16 +210,15 @@ def wrap_inside(
|
|||||||
"""2D inside wrap.
|
"""2D inside wrap.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
end: two 2D points
|
end: Two 2D points.
|
||||||
radius: circle radius
|
radius: Circle radius.
|
||||||
maxiter: maximum number of solver iterations
|
maxiter: Maximum number of solver iterations.
|
||||||
zinit: initialization for solver
|
zinit: Initialization for solver.
|
||||||
tolerance: solver convergence tolerance
|
tolerance: Solver convergence tolerance.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
0.0 if wrap else -1.0, pair of 2D wrap points
|
0.0 if wrap else -1.0, pair of 2D wrap points.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
end0 = wp.vec2(end[0], end[1])
|
end0 = wp.vec2(end[0], end[1])
|
||||||
end1 = wp.vec2(end[2], end[3])
|
end1 = wp.vec2(end[2], end[3])
|
||||||
|
|
||||||
@@ -330,16 +329,16 @@ def wrap(
|
|||||||
"""Wrap tendons around spheres and cylinders.
|
"""Wrap tendons around spheres and cylinders.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
x0: 3D endpoint
|
x0: 3D endpoint.
|
||||||
x1: 3D endpoint
|
x1: 3D endpoint.
|
||||||
pos: position of geom
|
pos: Position of geom.
|
||||||
mat: orientation of geom
|
mat: Orientation of geom.
|
||||||
radius: geom radius
|
radius: Geom radius.
|
||||||
type: wrap type (mjtWrap)
|
geomtype: Wrap type (mjtWrap).
|
||||||
side: 3D position for sidesite, no side point: wp.vec3(wp.inf)
|
side: 3D position for sidesite, no side point: wp.vec3(wp.inf).
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
length of circular wrap else -1.0 if no wrap, pair of 3D wrap points
|
Length of circular wrap else -1.0 if no wrap, pair of 3D wrap points.
|
||||||
"""
|
"""
|
||||||
# check object type
|
# check object type
|
||||||
if geomtype != WrapType.SPHERE and geomtype != WrapType.CYLINDER:
|
if geomtype != WrapType.SPHERE and geomtype != WrapType.CYLINDER:
|
||||||
@@ -453,7 +452,6 @@ def wrap(
|
|||||||
@wp.func
|
@wp.func
|
||||||
def muscle_gain_length(length: float, lmin: float, lmax: float) -> float:
|
def muscle_gain_length(length: float, lmin: float, lmax: float) -> float:
|
||||||
"""Normalized muscle length-gain curve."""
|
"""Normalized muscle length-gain curve."""
|
||||||
|
|
||||||
if (lmin > length) or (length > lmax):
|
if (lmin > length) or (length > lmax):
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
@@ -478,7 +476,6 @@ def muscle_gain_length(length: float, lmin: float, lmax: float) -> float:
|
|||||||
@wp.func
|
@wp.func
|
||||||
def muscle_gain(len: float, vel: float, lengthrange: wp.vec2, acc0: float, prm: vec10) -> float:
|
def muscle_gain(len: float, vel: float, lengthrange: wp.vec2, acc0: float, prm: vec10) -> float:
|
||||||
"""Muscle active force, prm = (range[2], force, scale, lmin, lmax, vmax, fpmax, fvmax)."""
|
"""Muscle active force, prm = (range[2], force, scale, lmin, lmax, vmax, fpmax, fvmax)."""
|
||||||
|
|
||||||
# unpack parameters
|
# unpack parameters
|
||||||
range_ = wp.vec2(prm[0], prm[1])
|
range_ = wp.vec2(prm[0], prm[1])
|
||||||
force = prm[2]
|
force = prm[2]
|
||||||
@@ -521,8 +518,8 @@ def muscle_gain(len: float, vel: float, lengthrange: wp.vec2, acc0: float, prm:
|
|||||||
def muscle_bias(len: float, lengthrange: wp.vec2, acc0: float, prm: vec10) -> float:
|
def muscle_bias(len: float, lengthrange: wp.vec2, acc0: float, prm: vec10) -> float:
|
||||||
"""Calculates muscle passive force.
|
"""Calculates muscle passive force.
|
||||||
|
|
||||||
prm = (range[2], force, scale, lmin, lmax, vmax, fpmax, fvmax)."""
|
prm = (range[2], force, scale, lmin, lmax, vmax, fpmax, fvmax).
|
||||||
|
"""
|
||||||
# unpack parameters
|
# unpack parameters
|
||||||
range_ = wp.vec2(prm[0], prm[1])
|
range_ = wp.vec2(prm[0], prm[1])
|
||||||
force = prm[2]
|
force = prm[2]
|
||||||
@@ -555,7 +552,6 @@ def muscle_bias(len: float, lengthrange: wp.vec2, acc0: float, prm: vec10) -> fl
|
|||||||
@wp.func
|
@wp.func
|
||||||
def _sigmoid(x: float) -> float:
|
def _sigmoid(x: float) -> float:
|
||||||
"""Sigmoid function over 0 <= x <= 1 using quintic polynomial."""
|
"""Sigmoid function over 0 <= x <= 1 using quintic polynomial."""
|
||||||
|
|
||||||
if x <= 0.0:
|
if x <= 0.0:
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
@@ -570,7 +566,6 @@ def _sigmoid(x: float) -> float:
|
|||||||
@wp.func
|
@wp.func
|
||||||
def muscle_dynamics_timescale(dctrl: float, tau_act: float, tau_deact: float, smooth_width: float) -> float:
|
def muscle_dynamics_timescale(dctrl: float, tau_act: float, tau_deact: float, smooth_width: float) -> float:
|
||||||
"""Muscle time constant with optional smoothing."""
|
"""Muscle time constant with optional smoothing."""
|
||||||
|
|
||||||
# hard switching
|
# hard switching
|
||||||
if smooth_width < MJ_MINVAL:
|
if smooth_width < MJ_MINVAL:
|
||||||
if dctrl > 0.0:
|
if dctrl > 0.0:
|
||||||
@@ -585,7 +580,6 @@ def muscle_dynamics_timescale(dctrl: float, tau_act: float, tau_deact: float, sm
|
|||||||
@wp.func
|
@wp.func
|
||||||
def muscle_dynamics(control: float, activation: float, prm: vec10) -> float:
|
def muscle_dynamics(control: float, activation: float, prm: vec10) -> float:
|
||||||
"""Muscle activation dynamics, prm = (tau_act, tau_deact, smooth_width)."""
|
"""Muscle activation dynamics, prm = (tau_act, tau_deact, smooth_width)."""
|
||||||
|
|
||||||
# clamp control
|
# clamp control
|
||||||
ctrlclamp = wp.clamp(control, 0.0, 1.0)
|
ctrlclamp = wp.clamp(control, 0.0, 1.0)
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ from typing import Callable, Optional
|
|||||||
|
|
||||||
import warp as wp
|
import warp as wp
|
||||||
from warp.context import Module
|
from warp.context import Module
|
||||||
from warp.context import assert_conditional_graph_support
|
|
||||||
from warp.context import get_module
|
from warp.context import get_module
|
||||||
|
|
||||||
_STACK = None
|
_STACK = None
|
||||||
@@ -130,8 +129,8 @@ def kernel(
|
|||||||
enable_backward: Optional[bool] = None,
|
enable_backward: Optional[bool] = None,
|
||||||
module: Optional[Module] = None,
|
module: Optional[Module] = None,
|
||||||
):
|
):
|
||||||
"""
|
"""Decorator to register a Warp kernel from a Python function.
|
||||||
Decorator to register a Warp kernel from a Python function.
|
|
||||||
The function must be defined with type annotations for all arguments.
|
The function must be defined with type annotations for all arguments.
|
||||||
The function must not return anything.
|
The function must not return anything.
|
||||||
|
|
||||||
@@ -220,9 +219,9 @@ def cache_kernel(func):
|
|||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def conditional_graph_supported():
|
def check_toolkit_driver():
|
||||||
try:
|
if wp.context.runtime is None:
|
||||||
assert_conditional_graph_support()
|
wp.context.init()
|
||||||
except Exception:
|
if wp.get_device().is_cuda:
|
||||||
return False
|
if wp.context.runtime.toolkit_version < (12, 4) or wp.context.runtime.driver_version < (12, 4):
|
||||||
return True
|
RuntimeError("Minimum supported CUDA version: 12.4.")
|
||||||
|
|||||||
+17
-2
@@ -28,9 +28,9 @@ requires-python = ">=3.9"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"absl-py",
|
"absl-py",
|
||||||
"etils[epath]",
|
"etils[epath]",
|
||||||
"mujoco>=3.3.6.dev802089588",
|
"mujoco>=3.3.7",
|
||||||
"numpy",
|
"numpy",
|
||||||
"warp-lang>=1.9.0.dev20250825",
|
"warp-lang>=1.9.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[tool.uv.index]]
|
[[tool.uv.index]]
|
||||||
@@ -49,6 +49,7 @@ mujoco = {index = "mujoco"}
|
|||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
dev = [
|
dev = [
|
||||||
|
"asv",
|
||||||
"pre-commit",
|
"pre-commit",
|
||||||
"pytest",
|
"pytest",
|
||||||
"pytest-xdist",
|
"pytest-xdist",
|
||||||
@@ -81,8 +82,15 @@ extend-exclude = ["*.ipynb"]
|
|||||||
|
|
||||||
[tool.ruff.lint]
|
[tool.ruff.lint]
|
||||||
select = [
|
select = [
|
||||||
|
"D", # pydocstyle conventions and style
|
||||||
"I", # isort
|
"I", # isort
|
||||||
"W", # pycodestyle
|
"W", # pycodestyle
|
||||||
|
"F401", # unused imports
|
||||||
|
]
|
||||||
|
|
||||||
|
ignore = [
|
||||||
|
"D100", # missing docstring public module
|
||||||
|
"D103", # missing docstring public function
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.ruff.lint.isort]
|
[tool.ruff.lint.isort]
|
||||||
@@ -93,6 +101,13 @@ single-line-exclusions = ["typing"]
|
|||||||
max-doc-length = 100
|
max-doc-length = 100
|
||||||
max-line-length = 128
|
max-line-length = 128
|
||||||
|
|
||||||
|
[tool.ruff.lint.pydocstyle]
|
||||||
|
convention = "google"
|
||||||
|
|
||||||
|
[tool.ruff.lint.per-file-ignores]
|
||||||
|
"__init__.py" = ["D"]
|
||||||
|
"contrib/*" = ["D"]
|
||||||
|
|
||||||
[tool.ruff.format]
|
[tool.ruff.format]
|
||||||
docstring-code-format = true
|
docstring-code-format = true
|
||||||
docstring-code-line-length = 100
|
docstring-code-line-length = 100
|
||||||
|
|||||||
+6
-3
@@ -45,6 +45,8 @@ from mujoco.mjx.third_party.mujoco_warp._src.io import override_model
|
|||||||
|
|
||||||
|
|
||||||
class EngineOptions(enum.IntEnum):
|
class EngineOptions(enum.IntEnum):
|
||||||
|
"""Engine option."""
|
||||||
|
|
||||||
WARP = 0
|
WARP = 0
|
||||||
C = 1
|
C = 1
|
||||||
|
|
||||||
@@ -142,15 +144,16 @@ def _main(argv: Sequence[str]) -> None:
|
|||||||
broadphase, filter = mjw.BroadphaseType(m.opt.broadphase).name, mjw.BroadphaseFilter(m.opt.broadphase_filter).name
|
broadphase, filter = mjw.BroadphaseType(m.opt.broadphase).name, mjw.BroadphaseFilter(m.opt.broadphase_filter).name
|
||||||
solver, cone = mjw.SolverType(m.opt.solver).name, mjw.ConeType(m.opt.cone).name
|
solver, cone = mjw.SolverType(m.opt.solver).name, mjw.ConeType(m.opt.cone).name
|
||||||
integrator = mjw.IntegratorType(m.opt.integrator).name
|
integrator = mjw.IntegratorType(m.opt.integrator).name
|
||||||
iterations, ls_iterations, ls_parallel = m.opt.iterations, m.opt.ls_iterations, m.opt.ls_parallel
|
iterations, ls_iterations = m.opt.iterations, m.opt.ls_iterations
|
||||||
|
ls_str = f"{'parallel' if m.opt.ls_parallel else 'iterative'} linesearch iterations: {ls_iterations}"
|
||||||
print(
|
print(
|
||||||
f" nbody: {m.nbody} nv: {m.nv} ngeom: {m.ngeom} nu: {m.nu} is_sparse: {m.opt.is_sparse}\n"
|
f" nbody: {m.nbody} nv: {m.nv} ngeom: {m.ngeom} nu: {m.nu} is_sparse: {m.opt.is_sparse}\n"
|
||||||
f" broadphase: {broadphase} broadphase_filter: {filter}\n"
|
f" broadphase: {broadphase} broadphase_filter: {filter}\n"
|
||||||
f" solver: {solver} cone: {cone} iterations: {iterations} ls_iterations: {ls_iterations} ls_parallel: {ls_parallel}\n"
|
f" solver: {solver} cone: {cone} iterations: {iterations} {ls_str}\n"
|
||||||
f" integrator: {integrator} graph_conditional: {m.opt.graph_conditional}"
|
f" integrator: {integrator} graph_conditional: {m.opt.graph_conditional}"
|
||||||
)
|
)
|
||||||
d = mjw.put_data(mjm, mjd, nconmax=_NCONMAX.value, njmax=_NJMAX.value)
|
d = mjw.put_data(mjm, mjd, nconmax=_NCONMAX.value, njmax=_NJMAX.value)
|
||||||
print(f"Data\n nworld: {d.nworld} nconmax: {d.nconmax} njmax: {d.njmax}\n")
|
print(f"Data\n nworld: {d.nworld} nconmax: {d.naconmax / d.nworld} njmax: {d.njmax}\n")
|
||||||
graph = _compile_step(m, d)
|
graph = _compile_step(m, d)
|
||||||
print(f"MuJoCo Warp simulating with dt = {m.opt.timestep.numpy()[0]:.3f}...")
|
print(f"MuJoCo Warp simulating with dt = {m.opt.timestep.numpy()[0]:.3f}...")
|
||||||
|
|
||||||
|
|||||||
@@ -42,12 +42,13 @@ _e = mjwarp.Constraint(
|
|||||||
**{f.name: None for f in dataclasses.fields(mjwarp.Constraint) if f.init}
|
**{f.name: None for f in dataclasses.fields(mjwarp.Constraint) if f.init}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ffi.format_args_for_warp
|
@ffi.format_args_for_warp
|
||||||
def _collision_shim(
|
def _collision_shim(
|
||||||
# Model
|
# Model
|
||||||
nworld: int,
|
nworld: int,
|
||||||
block_dim: mjwp_types.BlockDim,
|
block_dim: mjwp_types.BlockDim,
|
||||||
geom_aabb: wp.array2d(dtype=wp.vec3),
|
geom_aabb: wp.array3d(dtype=wp.vec3),
|
||||||
geom_condim: wp.array(dtype=int),
|
geom_condim: wp.array(dtype=int),
|
||||||
geom_dataid: wp.array(dtype=int),
|
geom_dataid: wp.array(dtype=int),
|
||||||
geom_friction: wp.array2d(dtype=wp.vec3),
|
geom_friction: wp.array2d(dtype=wp.vec3),
|
||||||
@@ -85,10 +86,12 @@ def _collision_shim(
|
|||||||
mesh_vertadr: wp.array(dtype=int),
|
mesh_vertadr: wp.array(dtype=int),
|
||||||
mesh_vertnum: wp.array(dtype=int),
|
mesh_vertnum: wp.array(dtype=int),
|
||||||
ngeom: int,
|
ngeom: int,
|
||||||
|
nmaxmeshdeg: int,
|
||||||
|
nmaxpolygon: int,
|
||||||
nmeshface: int,
|
nmeshface: int,
|
||||||
nxn_geom_pair_filtered: wp.array(dtype=wp.vec2i),
|
nxn_geom_pair_filtered: wp.array(dtype=wp.vec2i),
|
||||||
nxn_pairid: wp.array(dtype=int),
|
nxn_pairid: wp.array(dtype=wp.vec2i),
|
||||||
nxn_pairid_filtered: wp.array(dtype=int),
|
nxn_pairid_filtered: wp.array(dtype=wp.vec2i),
|
||||||
oct_aabb: wp.array2d(dtype=wp.vec3),
|
oct_aabb: wp.array2d(dtype=wp.vec3),
|
||||||
oct_child: wp.array(dtype=mjwp_types.vec8i),
|
oct_child: wp.array(dtype=mjwp_types.vec8i),
|
||||||
oct_coeff: wp.array(dtype=mjwp_types.vec8f),
|
oct_coeff: wp.array(dtype=mjwp_types.vec8f),
|
||||||
@@ -106,57 +109,30 @@ def _collision_shim(
|
|||||||
opt__ccd_iterations: int,
|
opt__ccd_iterations: int,
|
||||||
opt__ccd_tolerance: wp.array(dtype=float),
|
opt__ccd_tolerance: wp.array(dtype=float),
|
||||||
opt__disableflags: int,
|
opt__disableflags: int,
|
||||||
opt__graph_conditional: bool,
|
|
||||||
opt__legacy_gjk: bool,
|
opt__legacy_gjk: bool,
|
||||||
opt__sdf_initpoints: int,
|
opt__sdf_initpoints: int,
|
||||||
opt__sdf_iterations: int,
|
opt__sdf_iterations: int,
|
||||||
# Data
|
# Data
|
||||||
naconmax: int,
|
naconmax: int,
|
||||||
collision_pair: wp.array(dtype=wp.vec2i),
|
collision_pair: wp.array(dtype=wp.vec2i),
|
||||||
collision_pairid: wp.array(dtype=int),
|
collision_pairid: wp.array(dtype=wp.vec2i),
|
||||||
collision_worldid: wp.array(dtype=int),
|
collision_worldid: wp.array(dtype=int),
|
||||||
epa_face: wp.array2d(dtype=wp.vec3i),
|
|
||||||
epa_horizon: wp.array2d(dtype=int),
|
|
||||||
epa_index: wp.array2d(dtype=int),
|
|
||||||
epa_map: wp.array2d(dtype=int),
|
|
||||||
epa_norm2: wp.array2d(dtype=float),
|
|
||||||
epa_pr: wp.array2d(dtype=wp.vec3),
|
|
||||||
epa_vert: wp.array2d(dtype=wp.vec3),
|
|
||||||
epa_vert1: wp.array2d(dtype=wp.vec3),
|
|
||||||
epa_vert2: wp.array2d(dtype=wp.vec3),
|
|
||||||
epa_vert_index1: wp.array2d(dtype=int),
|
|
||||||
epa_vert_index2: wp.array2d(dtype=int),
|
|
||||||
geom_xmat: wp.array2d(dtype=wp.mat33),
|
geom_xmat: wp.array2d(dtype=wp.mat33),
|
||||||
geom_xpos: wp.array2d(dtype=wp.vec3),
|
geom_xpos: wp.array2d(dtype=wp.vec3),
|
||||||
multiccd_clipped: wp.array2d(dtype=wp.vec3),
|
|
||||||
multiccd_endvert: wp.array2d(dtype=wp.vec3),
|
|
||||||
multiccd_face1: wp.array2d(dtype=wp.vec3),
|
|
||||||
multiccd_face2: wp.array2d(dtype=wp.vec3),
|
|
||||||
multiccd_idx1: wp.array2d(dtype=int),
|
|
||||||
multiccd_idx2: wp.array2d(dtype=int),
|
|
||||||
multiccd_n1: wp.array2d(dtype=wp.vec3),
|
|
||||||
multiccd_n2: wp.array2d(dtype=wp.vec3),
|
|
||||||
multiccd_pdist: wp.array2d(dtype=float),
|
|
||||||
multiccd_pnormal: wp.array2d(dtype=wp.vec3),
|
|
||||||
multiccd_polygon: wp.array2d(dtype=wp.vec3),
|
|
||||||
nacon: wp.array(dtype=int),
|
nacon: wp.array(dtype=int),
|
||||||
ncollision: wp.array(dtype=int),
|
ncollision: wp.array(dtype=int),
|
||||||
sap_cumulative_sum: wp.array2d(dtype=int),
|
|
||||||
sap_projection_lower: wp.array3d(dtype=float),
|
|
||||||
sap_projection_upper: wp.array2d(dtype=float),
|
|
||||||
sap_range: wp.array2d(dtype=int),
|
|
||||||
sap_segment_index: wp.array2d(dtype=int),
|
|
||||||
sap_sort_index: wp.array3d(dtype=int),
|
|
||||||
contact__dim: wp.array(dtype=int),
|
contact__dim: wp.array(dtype=int),
|
||||||
contact__dist: wp.array(dtype=float),
|
contact__dist: wp.array(dtype=float),
|
||||||
contact__frame: wp.array(dtype=wp.mat33),
|
contact__frame: wp.array(dtype=wp.mat33),
|
||||||
contact__friction: wp.array(dtype=mjwp_types.vec5),
|
contact__friction: wp.array(dtype=mjwp_types.vec5),
|
||||||
contact__geom: wp.array(dtype=wp.vec2i),
|
contact__geom: wp.array(dtype=wp.vec2i),
|
||||||
|
contact__geomcollisionid: wp.array(dtype=int),
|
||||||
contact__includemargin: wp.array(dtype=float),
|
contact__includemargin: wp.array(dtype=float),
|
||||||
contact__pos: wp.array(dtype=wp.vec3),
|
contact__pos: wp.array(dtype=wp.vec3),
|
||||||
contact__solimp: wp.array(dtype=mjwp_types.vec5),
|
contact__solimp: wp.array(dtype=mjwp_types.vec5),
|
||||||
contact__solref: wp.array(dtype=wp.vec2),
|
contact__solref: wp.array(dtype=wp.vec2),
|
||||||
contact__solreffriction: wp.array(dtype=wp.vec2),
|
contact__solreffriction: wp.array(dtype=wp.vec2),
|
||||||
|
contact__type: wp.array(dtype=int),
|
||||||
contact__worldid: wp.array(dtype=int),
|
contact__worldid: wp.array(dtype=int),
|
||||||
):
|
):
|
||||||
_m.stat = _s
|
_m.stat = _s
|
||||||
@@ -202,6 +178,8 @@ def _collision_shim(
|
|||||||
_m.mesh_vertadr = mesh_vertadr
|
_m.mesh_vertadr = mesh_vertadr
|
||||||
_m.mesh_vertnum = mesh_vertnum
|
_m.mesh_vertnum = mesh_vertnum
|
||||||
_m.ngeom = ngeom
|
_m.ngeom = ngeom
|
||||||
|
_m.nmaxmeshdeg = nmaxmeshdeg
|
||||||
|
_m.nmaxpolygon = nmaxpolygon
|
||||||
_m.nmeshface = nmeshface
|
_m.nmeshface = nmeshface
|
||||||
_m.nxn_geom_pair_filtered = nxn_geom_pair_filtered
|
_m.nxn_geom_pair_filtered = nxn_geom_pair_filtered
|
||||||
_m.nxn_pairid = nxn_pairid
|
_m.nxn_pairid = nxn_pairid
|
||||||
@@ -214,7 +192,6 @@ def _collision_shim(
|
|||||||
_m.opt.ccd_iterations = opt__ccd_iterations
|
_m.opt.ccd_iterations = opt__ccd_iterations
|
||||||
_m.opt.ccd_tolerance = opt__ccd_tolerance
|
_m.opt.ccd_tolerance = opt__ccd_tolerance
|
||||||
_m.opt.disableflags = opt__disableflags
|
_m.opt.disableflags = opt__disableflags
|
||||||
_m.opt.graph_conditional = opt__graph_conditional
|
|
||||||
_m.opt.legacy_gjk = opt__legacy_gjk
|
_m.opt.legacy_gjk = opt__legacy_gjk
|
||||||
_m.opt.sdf_initpoints = opt__sdf_initpoints
|
_m.opt.sdf_initpoints = opt__sdf_initpoints
|
||||||
_m.opt.sdf_iterations = opt__sdf_iterations
|
_m.opt.sdf_iterations = opt__sdf_iterations
|
||||||
@@ -235,45 +212,19 @@ def _collision_shim(
|
|||||||
_d.contact.frame = contact__frame
|
_d.contact.frame = contact__frame
|
||||||
_d.contact.friction = contact__friction
|
_d.contact.friction = contact__friction
|
||||||
_d.contact.geom = contact__geom
|
_d.contact.geom = contact__geom
|
||||||
|
_d.contact.geomcollisionid = contact__geomcollisionid
|
||||||
_d.contact.includemargin = contact__includemargin
|
_d.contact.includemargin = contact__includemargin
|
||||||
_d.contact.pos = contact__pos
|
_d.contact.pos = contact__pos
|
||||||
_d.contact.solimp = contact__solimp
|
_d.contact.solimp = contact__solimp
|
||||||
_d.contact.solref = contact__solref
|
_d.contact.solref = contact__solref
|
||||||
_d.contact.solreffriction = contact__solreffriction
|
_d.contact.solreffriction = contact__solreffriction
|
||||||
|
_d.contact.type = contact__type
|
||||||
_d.contact.worldid = contact__worldid
|
_d.contact.worldid = contact__worldid
|
||||||
_d.epa_face = epa_face
|
|
||||||
_d.epa_horizon = epa_horizon
|
|
||||||
_d.epa_index = epa_index
|
|
||||||
_d.epa_map = epa_map
|
|
||||||
_d.epa_norm2 = epa_norm2
|
|
||||||
_d.epa_pr = epa_pr
|
|
||||||
_d.epa_vert = epa_vert
|
|
||||||
_d.epa_vert1 = epa_vert1
|
|
||||||
_d.epa_vert2 = epa_vert2
|
|
||||||
_d.epa_vert_index1 = epa_vert_index1
|
|
||||||
_d.epa_vert_index2 = epa_vert_index2
|
|
||||||
_d.geom_xmat = geom_xmat
|
_d.geom_xmat = geom_xmat
|
||||||
_d.geom_xpos = geom_xpos
|
_d.geom_xpos = geom_xpos
|
||||||
_d.multiccd_clipped = multiccd_clipped
|
|
||||||
_d.multiccd_endvert = multiccd_endvert
|
|
||||||
_d.multiccd_face1 = multiccd_face1
|
|
||||||
_d.multiccd_face2 = multiccd_face2
|
|
||||||
_d.multiccd_idx1 = multiccd_idx1
|
|
||||||
_d.multiccd_idx2 = multiccd_idx2
|
|
||||||
_d.multiccd_n1 = multiccd_n1
|
|
||||||
_d.multiccd_n2 = multiccd_n2
|
|
||||||
_d.multiccd_pdist = multiccd_pdist
|
|
||||||
_d.multiccd_pnormal = multiccd_pnormal
|
|
||||||
_d.multiccd_polygon = multiccd_polygon
|
|
||||||
_d.nacon = nacon
|
_d.nacon = nacon
|
||||||
_d.naconmax = naconmax
|
_d.naconmax = naconmax
|
||||||
_d.ncollision = ncollision
|
_d.ncollision = ncollision
|
||||||
_d.sap_cumulative_sum = sap_cumulative_sum
|
|
||||||
_d.sap_projection_lower = sap_projection_lower
|
|
||||||
_d.sap_projection_upper = sap_projection_upper
|
|
||||||
_d.sap_range = sap_range
|
|
||||||
_d.sap_segment_index = sap_segment_index
|
|
||||||
_d.sap_sort_index = sap_sort_index
|
|
||||||
_d.nworld = nworld
|
_d.nworld = nworld
|
||||||
mjwarp.collision(_m, _d)
|
mjwarp.collision(_m, _d)
|
||||||
|
|
||||||
@@ -283,101 +234,49 @@ def _collision_jax_impl(m: types.Model, d: types.Data):
|
|||||||
'collision_pair': d._impl.collision_pair.shape,
|
'collision_pair': d._impl.collision_pair.shape,
|
||||||
'collision_pairid': d._impl.collision_pairid.shape,
|
'collision_pairid': d._impl.collision_pairid.shape,
|
||||||
'collision_worldid': d._impl.collision_worldid.shape,
|
'collision_worldid': d._impl.collision_worldid.shape,
|
||||||
'epa_face': d._impl.epa_face.shape,
|
|
||||||
'epa_horizon': d._impl.epa_horizon.shape,
|
|
||||||
'epa_index': d._impl.epa_index.shape,
|
|
||||||
'epa_map': d._impl.epa_map.shape,
|
|
||||||
'epa_norm2': d._impl.epa_norm2.shape,
|
|
||||||
'epa_pr': d._impl.epa_pr.shape,
|
|
||||||
'epa_vert': d._impl.epa_vert.shape,
|
|
||||||
'epa_vert1': d._impl.epa_vert1.shape,
|
|
||||||
'epa_vert2': d._impl.epa_vert2.shape,
|
|
||||||
'epa_vert_index1': d._impl.epa_vert_index1.shape,
|
|
||||||
'epa_vert_index2': d._impl.epa_vert_index2.shape,
|
|
||||||
'geom_xmat': d.geom_xmat.shape,
|
'geom_xmat': d.geom_xmat.shape,
|
||||||
'geom_xpos': d.geom_xpos.shape,
|
'geom_xpos': d.geom_xpos.shape,
|
||||||
'multiccd_clipped': d._impl.multiccd_clipped.shape,
|
|
||||||
'multiccd_endvert': d._impl.multiccd_endvert.shape,
|
|
||||||
'multiccd_face1': d._impl.multiccd_face1.shape,
|
|
||||||
'multiccd_face2': d._impl.multiccd_face2.shape,
|
|
||||||
'multiccd_idx1': d._impl.multiccd_idx1.shape,
|
|
||||||
'multiccd_idx2': d._impl.multiccd_idx2.shape,
|
|
||||||
'multiccd_n1': d._impl.multiccd_n1.shape,
|
|
||||||
'multiccd_n2': d._impl.multiccd_n2.shape,
|
|
||||||
'multiccd_pdist': d._impl.multiccd_pdist.shape,
|
|
||||||
'multiccd_pnormal': d._impl.multiccd_pnormal.shape,
|
|
||||||
'multiccd_polygon': d._impl.multiccd_polygon.shape,
|
|
||||||
'nacon': d._impl.nacon.shape,
|
'nacon': d._impl.nacon.shape,
|
||||||
'ncollision': d._impl.ncollision.shape,
|
'ncollision': d._impl.ncollision.shape,
|
||||||
'sap_cumulative_sum': d._impl.sap_cumulative_sum.shape,
|
|
||||||
'sap_projection_lower': d._impl.sap_projection_lower.shape,
|
|
||||||
'sap_projection_upper': d._impl.sap_projection_upper.shape,
|
|
||||||
'sap_range': d._impl.sap_range.shape,
|
|
||||||
'sap_segment_index': d._impl.sap_segment_index.shape,
|
|
||||||
'sap_sort_index': d._impl.sap_sort_index.shape,
|
|
||||||
'contact__dim': d._impl.contact__dim.shape,
|
'contact__dim': d._impl.contact__dim.shape,
|
||||||
'contact__dist': d._impl.contact__dist.shape,
|
'contact__dist': d._impl.contact__dist.shape,
|
||||||
'contact__frame': d._impl.contact__frame.shape,
|
'contact__frame': d._impl.contact__frame.shape,
|
||||||
'contact__friction': d._impl.contact__friction.shape,
|
'contact__friction': d._impl.contact__friction.shape,
|
||||||
'contact__geom': d._impl.contact__geom.shape,
|
'contact__geom': d._impl.contact__geom.shape,
|
||||||
|
'contact__geomcollisionid': d._impl.contact__geomcollisionid.shape,
|
||||||
'contact__includemargin': d._impl.contact__includemargin.shape,
|
'contact__includemargin': d._impl.contact__includemargin.shape,
|
||||||
'contact__pos': d._impl.contact__pos.shape,
|
'contact__pos': d._impl.contact__pos.shape,
|
||||||
'contact__solimp': d._impl.contact__solimp.shape,
|
'contact__solimp': d._impl.contact__solimp.shape,
|
||||||
'contact__solref': d._impl.contact__solref.shape,
|
'contact__solref': d._impl.contact__solref.shape,
|
||||||
'contact__solreffriction': d._impl.contact__solreffriction.shape,
|
'contact__solreffriction': d._impl.contact__solreffriction.shape,
|
||||||
|
'contact__type': d._impl.contact__type.shape,
|
||||||
'contact__worldid': d._impl.contact__worldid.shape,
|
'contact__worldid': d._impl.contact__worldid.shape,
|
||||||
}
|
}
|
||||||
jf = ffi.jax_callable_variadic_tuple(
|
jf = ffi.jax_callable_variadic_tuple(
|
||||||
_collision_shim,
|
_collision_shim,
|
||||||
num_outputs=46,
|
num_outputs=20,
|
||||||
output_dims=output_dims,
|
output_dims=output_dims,
|
||||||
vmap_method=None,
|
vmap_method=None,
|
||||||
in_out_argnames={
|
in_out_argnames={
|
||||||
'collision_pair',
|
'collision_pair',
|
||||||
'collision_pairid',
|
'collision_pairid',
|
||||||
'collision_worldid',
|
'collision_worldid',
|
||||||
'epa_face',
|
|
||||||
'epa_horizon',
|
|
||||||
'epa_index',
|
|
||||||
'epa_map',
|
|
||||||
'epa_norm2',
|
|
||||||
'epa_pr',
|
|
||||||
'epa_vert',
|
|
||||||
'epa_vert1',
|
|
||||||
'epa_vert2',
|
|
||||||
'epa_vert_index1',
|
|
||||||
'epa_vert_index2',
|
|
||||||
'geom_xmat',
|
'geom_xmat',
|
||||||
'geom_xpos',
|
'geom_xpos',
|
||||||
'multiccd_clipped',
|
|
||||||
'multiccd_endvert',
|
|
||||||
'multiccd_face1',
|
|
||||||
'multiccd_face2',
|
|
||||||
'multiccd_idx1',
|
|
||||||
'multiccd_idx2',
|
|
||||||
'multiccd_n1',
|
|
||||||
'multiccd_n2',
|
|
||||||
'multiccd_pdist',
|
|
||||||
'multiccd_pnormal',
|
|
||||||
'multiccd_polygon',
|
|
||||||
'nacon',
|
'nacon',
|
||||||
'ncollision',
|
'ncollision',
|
||||||
'sap_cumulative_sum',
|
|
||||||
'sap_projection_lower',
|
|
||||||
'sap_projection_upper',
|
|
||||||
'sap_range',
|
|
||||||
'sap_segment_index',
|
|
||||||
'sap_sort_index',
|
|
||||||
'contact__dim',
|
'contact__dim',
|
||||||
'contact__dist',
|
'contact__dist',
|
||||||
'contact__frame',
|
'contact__frame',
|
||||||
'contact__friction',
|
'contact__friction',
|
||||||
'contact__geom',
|
'contact__geom',
|
||||||
|
'contact__geomcollisionid',
|
||||||
'contact__includemargin',
|
'contact__includemargin',
|
||||||
'contact__pos',
|
'contact__pos',
|
||||||
'contact__solimp',
|
'contact__solimp',
|
||||||
'contact__solref',
|
'contact__solref',
|
||||||
'contact__solreffriction',
|
'contact__solreffriction',
|
||||||
|
'contact__type',
|
||||||
'contact__worldid',
|
'contact__worldid',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -422,6 +321,8 @@ def _collision_jax_impl(m: types.Model, d: types.Data):
|
|||||||
m.mesh_vertadr,
|
m.mesh_vertadr,
|
||||||
m.mesh_vertnum,
|
m.mesh_vertnum,
|
||||||
m.ngeom,
|
m.ngeom,
|
||||||
|
m._impl.nmaxmeshdeg,
|
||||||
|
m._impl.nmaxpolygon,
|
||||||
m.nmeshface,
|
m.nmeshface,
|
||||||
m._impl.nxn_geom_pair_filtered,
|
m._impl.nxn_geom_pair_filtered,
|
||||||
m._impl.nxn_pairid,
|
m._impl.nxn_pairid,
|
||||||
@@ -443,7 +344,6 @@ def _collision_jax_impl(m: types.Model, d: types.Data):
|
|||||||
m.opt._impl.ccd_iterations,
|
m.opt._impl.ccd_iterations,
|
||||||
m.opt._impl.ccd_tolerance,
|
m.opt._impl.ccd_tolerance,
|
||||||
m.opt.disableflags,
|
m.opt.disableflags,
|
||||||
m.opt._impl.graph_conditional,
|
|
||||||
m.opt._impl.legacy_gjk,
|
m.opt._impl.legacy_gjk,
|
||||||
m.opt._impl.sdf_initpoints,
|
m.opt._impl.sdf_initpoints,
|
||||||
m.opt._impl.sdf_iterations,
|
m.opt._impl.sdf_iterations,
|
||||||
@@ -451,97 +351,45 @@ def _collision_jax_impl(m: types.Model, d: types.Data):
|
|||||||
d._impl.collision_pair,
|
d._impl.collision_pair,
|
||||||
d._impl.collision_pairid,
|
d._impl.collision_pairid,
|
||||||
d._impl.collision_worldid,
|
d._impl.collision_worldid,
|
||||||
d._impl.epa_face,
|
|
||||||
d._impl.epa_horizon,
|
|
||||||
d._impl.epa_index,
|
|
||||||
d._impl.epa_map,
|
|
||||||
d._impl.epa_norm2,
|
|
||||||
d._impl.epa_pr,
|
|
||||||
d._impl.epa_vert,
|
|
||||||
d._impl.epa_vert1,
|
|
||||||
d._impl.epa_vert2,
|
|
||||||
d._impl.epa_vert_index1,
|
|
||||||
d._impl.epa_vert_index2,
|
|
||||||
d.geom_xmat,
|
d.geom_xmat,
|
||||||
d.geom_xpos,
|
d.geom_xpos,
|
||||||
d._impl.multiccd_clipped,
|
|
||||||
d._impl.multiccd_endvert,
|
|
||||||
d._impl.multiccd_face1,
|
|
||||||
d._impl.multiccd_face2,
|
|
||||||
d._impl.multiccd_idx1,
|
|
||||||
d._impl.multiccd_idx2,
|
|
||||||
d._impl.multiccd_n1,
|
|
||||||
d._impl.multiccd_n2,
|
|
||||||
d._impl.multiccd_pdist,
|
|
||||||
d._impl.multiccd_pnormal,
|
|
||||||
d._impl.multiccd_polygon,
|
|
||||||
d._impl.nacon,
|
d._impl.nacon,
|
||||||
d._impl.ncollision,
|
d._impl.ncollision,
|
||||||
d._impl.sap_cumulative_sum,
|
|
||||||
d._impl.sap_projection_lower,
|
|
||||||
d._impl.sap_projection_upper,
|
|
||||||
d._impl.sap_range,
|
|
||||||
d._impl.sap_segment_index,
|
|
||||||
d._impl.sap_sort_index,
|
|
||||||
d._impl.contact__dim,
|
d._impl.contact__dim,
|
||||||
d._impl.contact__dist,
|
d._impl.contact__dist,
|
||||||
d._impl.contact__frame,
|
d._impl.contact__frame,
|
||||||
d._impl.contact__friction,
|
d._impl.contact__friction,
|
||||||
d._impl.contact__geom,
|
d._impl.contact__geom,
|
||||||
|
d._impl.contact__geomcollisionid,
|
||||||
d._impl.contact__includemargin,
|
d._impl.contact__includemargin,
|
||||||
d._impl.contact__pos,
|
d._impl.contact__pos,
|
||||||
d._impl.contact__solimp,
|
d._impl.contact__solimp,
|
||||||
d._impl.contact__solref,
|
d._impl.contact__solref,
|
||||||
d._impl.contact__solreffriction,
|
d._impl.contact__solreffriction,
|
||||||
|
d._impl.contact__type,
|
||||||
d._impl.contact__worldid,
|
d._impl.contact__worldid,
|
||||||
)
|
)
|
||||||
d = d.tree_replace({
|
d = d.tree_replace({
|
||||||
'_impl.collision_pair': out[0],
|
'_impl.collision_pair': out[0],
|
||||||
'_impl.collision_pairid': out[1],
|
'_impl.collision_pairid': out[1],
|
||||||
'_impl.collision_worldid': out[2],
|
'_impl.collision_worldid': out[2],
|
||||||
'_impl.epa_face': out[3],
|
'geom_xmat': out[3],
|
||||||
'_impl.epa_horizon': out[4],
|
'geom_xpos': out[4],
|
||||||
'_impl.epa_index': out[5],
|
'_impl.nacon': out[5],
|
||||||
'_impl.epa_map': out[6],
|
'_impl.ncollision': out[6],
|
||||||
'_impl.epa_norm2': out[7],
|
'_impl.contact__dim': out[7],
|
||||||
'_impl.epa_pr': out[8],
|
'_impl.contact__dist': out[8],
|
||||||
'_impl.epa_vert': out[9],
|
'_impl.contact__frame': out[9],
|
||||||
'_impl.epa_vert1': out[10],
|
'_impl.contact__friction': out[10],
|
||||||
'_impl.epa_vert2': out[11],
|
'_impl.contact__geom': out[11],
|
||||||
'_impl.epa_vert_index1': out[12],
|
'_impl.contact__geomcollisionid': out[12],
|
||||||
'_impl.epa_vert_index2': out[13],
|
'_impl.contact__includemargin': out[13],
|
||||||
'geom_xmat': out[14],
|
'_impl.contact__pos': out[14],
|
||||||
'geom_xpos': out[15],
|
'_impl.contact__solimp': out[15],
|
||||||
'_impl.multiccd_clipped': out[16],
|
'_impl.contact__solref': out[16],
|
||||||
'_impl.multiccd_endvert': out[17],
|
'_impl.contact__solreffriction': out[17],
|
||||||
'_impl.multiccd_face1': out[18],
|
'_impl.contact__type': out[18],
|
||||||
'_impl.multiccd_face2': out[19],
|
'_impl.contact__worldid': out[19],
|
||||||
'_impl.multiccd_idx1': out[20],
|
|
||||||
'_impl.multiccd_idx2': out[21],
|
|
||||||
'_impl.multiccd_n1': out[22],
|
|
||||||
'_impl.multiccd_n2': out[23],
|
|
||||||
'_impl.multiccd_pdist': out[24],
|
|
||||||
'_impl.multiccd_pnormal': out[25],
|
|
||||||
'_impl.multiccd_polygon': out[26],
|
|
||||||
'_impl.nacon': out[27],
|
|
||||||
'_impl.ncollision': out[28],
|
|
||||||
'_impl.sap_cumulative_sum': out[29],
|
|
||||||
'_impl.sap_projection_lower': out[30],
|
|
||||||
'_impl.sap_projection_upper': out[31],
|
|
||||||
'_impl.sap_range': out[32],
|
|
||||||
'_impl.sap_segment_index': out[33],
|
|
||||||
'_impl.sap_sort_index': out[34],
|
|
||||||
'_impl.contact__dim': out[35],
|
|
||||||
'_impl.contact__dist': out[36],
|
|
||||||
'_impl.contact__frame': out[37],
|
|
||||||
'_impl.contact__friction': out[38],
|
|
||||||
'_impl.contact__geom': out[39],
|
|
||||||
'_impl.contact__includemargin': out[40],
|
|
||||||
'_impl.contact__pos': out[41],
|
|
||||||
'_impl.contact__solimp': out[42],
|
|
||||||
'_impl.contact__solref': out[43],
|
|
||||||
'_impl.contact__solreffriction': out[44],
|
|
||||||
'_impl.contact__worldid': out[45],
|
|
||||||
})
|
})
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|||||||
+344
-873
File diff suppressed because it is too large
Load Diff
@@ -42,6 +42,7 @@ _e = mjwarp.Constraint(
|
|||||||
**{f.name: None for f in dataclasses.fields(mjwarp.Constraint) if f.init}
|
**{f.name: None for f in dataclasses.fields(mjwarp.Constraint) if f.init}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ffi.format_args_for_warp
|
@ffi.format_args_for_warp
|
||||||
def _kinematics_shim(
|
def _kinematics_shim(
|
||||||
# Model
|
# Model
|
||||||
@@ -51,10 +52,13 @@ def _kinematics_shim(
|
|||||||
body_iquat: wp.array2d(dtype=wp.quat),
|
body_iquat: wp.array2d(dtype=wp.quat),
|
||||||
body_jntadr: wp.array(dtype=int),
|
body_jntadr: wp.array(dtype=int),
|
||||||
body_jntnum: wp.array(dtype=int),
|
body_jntnum: wp.array(dtype=int),
|
||||||
|
body_mocapid: wp.array(dtype=int),
|
||||||
body_parentid: wp.array(dtype=int),
|
body_parentid: wp.array(dtype=int),
|
||||||
body_pos: wp.array2d(dtype=wp.vec3),
|
body_pos: wp.array2d(dtype=wp.vec3),
|
||||||
body_quat: wp.array2d(dtype=wp.quat),
|
body_quat: wp.array2d(dtype=wp.quat),
|
||||||
|
body_rootid: wp.array(dtype=int),
|
||||||
body_tree: tuple[wp.array(dtype=int), ...],
|
body_tree: tuple[wp.array(dtype=int), ...],
|
||||||
|
body_weldid: wp.array(dtype=int),
|
||||||
flex_edge: wp.array(dtype=wp.vec2i),
|
flex_edge: wp.array(dtype=wp.vec2i),
|
||||||
flex_vertadr: wp.array(dtype=int),
|
flex_vertadr: wp.array(dtype=int),
|
||||||
flex_vertbodyid: wp.array(dtype=int),
|
flex_vertbodyid: wp.array(dtype=int),
|
||||||
@@ -79,7 +83,6 @@ def _kinematics_shim(
|
|||||||
flexedge_length: wp.array2d(dtype=float),
|
flexedge_length: wp.array2d(dtype=float),
|
||||||
flexedge_velocity: wp.array2d(dtype=float),
|
flexedge_velocity: wp.array2d(dtype=float),
|
||||||
flexvert_xpos: wp.array2d(dtype=wp.vec3),
|
flexvert_xpos: wp.array2d(dtype=wp.vec3),
|
||||||
geom_skip: wp.array(dtype=bool),
|
|
||||||
geom_xmat: wp.array2d(dtype=wp.mat33),
|
geom_xmat: wp.array2d(dtype=wp.mat33),
|
||||||
geom_xpos: wp.array2d(dtype=wp.vec3),
|
geom_xpos: wp.array2d(dtype=wp.vec3),
|
||||||
mocap_pos: wp.array2d(dtype=wp.vec3),
|
mocap_pos: wp.array2d(dtype=wp.vec3),
|
||||||
@@ -105,10 +108,13 @@ def _kinematics_shim(
|
|||||||
_m.body_iquat = body_iquat
|
_m.body_iquat = body_iquat
|
||||||
_m.body_jntadr = body_jntadr
|
_m.body_jntadr = body_jntadr
|
||||||
_m.body_jntnum = body_jntnum
|
_m.body_jntnum = body_jntnum
|
||||||
|
_m.body_mocapid = body_mocapid
|
||||||
_m.body_parentid = body_parentid
|
_m.body_parentid = body_parentid
|
||||||
_m.body_pos = body_pos
|
_m.body_pos = body_pos
|
||||||
_m.body_quat = body_quat
|
_m.body_quat = body_quat
|
||||||
|
_m.body_rootid = body_rootid
|
||||||
_m.body_tree = body_tree
|
_m.body_tree = body_tree
|
||||||
|
_m.body_weldid = body_weldid
|
||||||
_m.flex_edge = flex_edge
|
_m.flex_edge = flex_edge
|
||||||
_m.flex_vertadr = flex_vertadr
|
_m.flex_vertadr = flex_vertadr
|
||||||
_m.flex_vertbodyid = flex_vertbodyid
|
_m.flex_vertbodyid = flex_vertbodyid
|
||||||
@@ -132,7 +138,6 @@ def _kinematics_shim(
|
|||||||
_d.flexedge_length = flexedge_length
|
_d.flexedge_length = flexedge_length
|
||||||
_d.flexedge_velocity = flexedge_velocity
|
_d.flexedge_velocity = flexedge_velocity
|
||||||
_d.flexvert_xpos = flexvert_xpos
|
_d.flexvert_xpos = flexvert_xpos
|
||||||
_d.geom_skip = geom_skip
|
|
||||||
_d.geom_xmat = geom_xmat
|
_d.geom_xmat = geom_xmat
|
||||||
_d.geom_xpos = geom_xpos
|
_d.geom_xpos = geom_xpos
|
||||||
_d.mocap_pos = mocap_pos
|
_d.mocap_pos = mocap_pos
|
||||||
@@ -157,7 +162,6 @@ def _kinematics_jax_impl(m: types.Model, d: types.Data):
|
|||||||
'flexedge_length': d._impl.flexedge_length.shape,
|
'flexedge_length': d._impl.flexedge_length.shape,
|
||||||
'flexedge_velocity': d._impl.flexedge_velocity.shape,
|
'flexedge_velocity': d._impl.flexedge_velocity.shape,
|
||||||
'flexvert_xpos': d._impl.flexvert_xpos.shape,
|
'flexvert_xpos': d._impl.flexvert_xpos.shape,
|
||||||
'geom_skip': d._impl.geom_skip.shape,
|
|
||||||
'geom_xmat': d.geom_xmat.shape,
|
'geom_xmat': d.geom_xmat.shape,
|
||||||
'geom_xpos': d.geom_xpos.shape,
|
'geom_xpos': d.geom_xpos.shape,
|
||||||
'mocap_pos': d.mocap_pos.shape,
|
'mocap_pos': d.mocap_pos.shape,
|
||||||
@@ -176,14 +180,13 @@ def _kinematics_jax_impl(m: types.Model, d: types.Data):
|
|||||||
}
|
}
|
||||||
jf = ffi.jax_callable_variadic_tuple(
|
jf = ffi.jax_callable_variadic_tuple(
|
||||||
_kinematics_shim,
|
_kinematics_shim,
|
||||||
num_outputs=19,
|
num_outputs=18,
|
||||||
output_dims=output_dims,
|
output_dims=output_dims,
|
||||||
vmap_method=None,
|
vmap_method=None,
|
||||||
in_out_argnames={
|
in_out_argnames={
|
||||||
'flexedge_length',
|
'flexedge_length',
|
||||||
'flexedge_velocity',
|
'flexedge_velocity',
|
||||||
'flexvert_xpos',
|
'flexvert_xpos',
|
||||||
'geom_skip',
|
|
||||||
'geom_xmat',
|
'geom_xmat',
|
||||||
'geom_xpos',
|
'geom_xpos',
|
||||||
'mocap_pos',
|
'mocap_pos',
|
||||||
@@ -208,10 +211,13 @@ def _kinematics_jax_impl(m: types.Model, d: types.Data):
|
|||||||
m.body_iquat,
|
m.body_iquat,
|
||||||
m.body_jntadr,
|
m.body_jntadr,
|
||||||
m.body_jntnum,
|
m.body_jntnum,
|
||||||
|
m.body_mocapid,
|
||||||
m.body_parentid,
|
m.body_parentid,
|
||||||
m.body_pos,
|
m.body_pos,
|
||||||
m.body_quat,
|
m.body_quat,
|
||||||
|
m.body_rootid,
|
||||||
m._impl.body_tree,
|
m._impl.body_tree,
|
||||||
|
m.body_weldid,
|
||||||
m._impl.flex_edge,
|
m._impl.flex_edge,
|
||||||
m._impl.flex_vertadr,
|
m._impl.flex_vertadr,
|
||||||
m._impl.flex_vertbodyid,
|
m._impl.flex_vertbodyid,
|
||||||
@@ -235,7 +241,6 @@ def _kinematics_jax_impl(m: types.Model, d: types.Data):
|
|||||||
d._impl.flexedge_length,
|
d._impl.flexedge_length,
|
||||||
d._impl.flexedge_velocity,
|
d._impl.flexedge_velocity,
|
||||||
d._impl.flexvert_xpos,
|
d._impl.flexvert_xpos,
|
||||||
d._impl.geom_skip,
|
|
||||||
d.geom_xmat,
|
d.geom_xmat,
|
||||||
d.geom_xpos,
|
d.geom_xpos,
|
||||||
d.mocap_pos,
|
d.mocap_pos,
|
||||||
@@ -256,22 +261,21 @@ def _kinematics_jax_impl(m: types.Model, d: types.Data):
|
|||||||
'_impl.flexedge_length': out[0],
|
'_impl.flexedge_length': out[0],
|
||||||
'_impl.flexedge_velocity': out[1],
|
'_impl.flexedge_velocity': out[1],
|
||||||
'_impl.flexvert_xpos': out[2],
|
'_impl.flexvert_xpos': out[2],
|
||||||
'_impl.geom_skip': out[3],
|
'geom_xmat': out[3],
|
||||||
'geom_xmat': out[4],
|
'geom_xpos': out[4],
|
||||||
'geom_xpos': out[5],
|
'mocap_pos': out[5],
|
||||||
'mocap_pos': out[6],
|
'mocap_quat': out[6],
|
||||||
'mocap_quat': out[7],
|
'qpos': out[7],
|
||||||
'qpos': out[8],
|
'qvel': out[8],
|
||||||
'qvel': out[9],
|
'site_xmat': out[9],
|
||||||
'site_xmat': out[10],
|
'site_xpos': out[10],
|
||||||
'site_xpos': out[11],
|
'xanchor': out[11],
|
||||||
'xanchor': out[12],
|
'xaxis': out[12],
|
||||||
'xaxis': out[13],
|
'ximat': out[13],
|
||||||
'ximat': out[14],
|
'xipos': out[14],
|
||||||
'xipos': out[15],
|
'xmat': out[15],
|
||||||
'xmat': out[16],
|
'xpos': out[16],
|
||||||
'xpos': out[17],
|
'xquat': out[17],
|
||||||
'xquat': out[18],
|
|
||||||
})
|
})
|
||||||
return d
|
return d
|
||||||
|
|
||||||
@@ -306,6 +310,7 @@ _e = mjwarp.Constraint(
|
|||||||
**{f.name: None for f in dataclasses.fields(mjwarp.Constraint) if f.init}
|
**{f.name: None for f in dataclasses.fields(mjwarp.Constraint) if f.init}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ffi.format_args_for_warp
|
@ffi.format_args_for_warp
|
||||||
def _tendon_shim(
|
def _tendon_shim(
|
||||||
# Model
|
# Model
|
||||||
@@ -319,6 +324,7 @@ def _tendon_shim(
|
|||||||
jnt_qposadr: wp.array(dtype=int),
|
jnt_qposadr: wp.array(dtype=int),
|
||||||
ntendon: int,
|
ntendon: int,
|
||||||
nv: int,
|
nv: int,
|
||||||
|
nwrap: int,
|
||||||
site_bodyid: wp.array(dtype=int),
|
site_bodyid: wp.array(dtype=int),
|
||||||
tendon_adr: wp.array(dtype=int),
|
tendon_adr: wp.array(dtype=int),
|
||||||
tendon_geom_adr: wp.array(dtype=int),
|
tendon_geom_adr: wp.array(dtype=int),
|
||||||
@@ -343,7 +349,6 @@ def _tendon_shim(
|
|||||||
ten_length: wp.array2d(dtype=float),
|
ten_length: wp.array2d(dtype=float),
|
||||||
ten_wrapadr: wp.array2d(dtype=int),
|
ten_wrapadr: wp.array2d(dtype=int),
|
||||||
ten_wrapnum: wp.array2d(dtype=int),
|
ten_wrapnum: wp.array2d(dtype=int),
|
||||||
wrap_geom_xpos: wp.array2d(dtype=wp.spatial_vector),
|
|
||||||
wrap_obj: wp.array2d(dtype=wp.vec2i),
|
wrap_obj: wp.array2d(dtype=wp.vec2i),
|
||||||
wrap_xpos: wp.array2d(dtype=wp.spatial_vector),
|
wrap_xpos: wp.array2d(dtype=wp.spatial_vector),
|
||||||
):
|
):
|
||||||
@@ -360,6 +365,7 @@ def _tendon_shim(
|
|||||||
_m.jnt_qposadr = jnt_qposadr
|
_m.jnt_qposadr = jnt_qposadr
|
||||||
_m.ntendon = ntendon
|
_m.ntendon = ntendon
|
||||||
_m.nv = nv
|
_m.nv = nv
|
||||||
|
_m.nwrap = nwrap
|
||||||
_m.site_bodyid = site_bodyid
|
_m.site_bodyid = site_bodyid
|
||||||
_m.tendon_adr = tendon_adr
|
_m.tendon_adr = tendon_adr
|
||||||
_m.tendon_geom_adr = tendon_geom_adr
|
_m.tendon_geom_adr = tendon_geom_adr
|
||||||
@@ -383,7 +389,6 @@ def _tendon_shim(
|
|||||||
_d.ten_length = ten_length
|
_d.ten_length = ten_length
|
||||||
_d.ten_wrapadr = ten_wrapadr
|
_d.ten_wrapadr = ten_wrapadr
|
||||||
_d.ten_wrapnum = ten_wrapnum
|
_d.ten_wrapnum = ten_wrapnum
|
||||||
_d.wrap_geom_xpos = wrap_geom_xpos
|
|
||||||
_d.wrap_obj = wrap_obj
|
_d.wrap_obj = wrap_obj
|
||||||
_d.wrap_xpos = wrap_xpos
|
_d.wrap_xpos = wrap_xpos
|
||||||
_d.nworld = nworld
|
_d.nworld = nworld
|
||||||
@@ -402,13 +407,12 @@ def _tendon_jax_impl(m: types.Model, d: types.Data):
|
|||||||
'ten_length': d.ten_length.shape,
|
'ten_length': d.ten_length.shape,
|
||||||
'ten_wrapadr': d._impl.ten_wrapadr.shape,
|
'ten_wrapadr': d._impl.ten_wrapadr.shape,
|
||||||
'ten_wrapnum': d._impl.ten_wrapnum.shape,
|
'ten_wrapnum': d._impl.ten_wrapnum.shape,
|
||||||
'wrap_geom_xpos': d._impl.wrap_geom_xpos.shape,
|
|
||||||
'wrap_obj': d._impl.wrap_obj.shape,
|
'wrap_obj': d._impl.wrap_obj.shape,
|
||||||
'wrap_xpos': d._impl.wrap_xpos.shape,
|
'wrap_xpos': d._impl.wrap_xpos.shape,
|
||||||
}
|
}
|
||||||
jf = ffi.jax_callable_variadic_tuple(
|
jf = ffi.jax_callable_variadic_tuple(
|
||||||
_tendon_shim,
|
_tendon_shim,
|
||||||
num_outputs=13,
|
num_outputs=12,
|
||||||
output_dims=output_dims,
|
output_dims=output_dims,
|
||||||
vmap_method=None,
|
vmap_method=None,
|
||||||
in_out_argnames={
|
in_out_argnames={
|
||||||
@@ -422,7 +426,6 @@ def _tendon_jax_impl(m: types.Model, d: types.Data):
|
|||||||
'ten_length',
|
'ten_length',
|
||||||
'ten_wrapadr',
|
'ten_wrapadr',
|
||||||
'ten_wrapnum',
|
'ten_wrapnum',
|
||||||
'wrap_geom_xpos',
|
|
||||||
'wrap_obj',
|
'wrap_obj',
|
||||||
'wrap_xpos',
|
'wrap_xpos',
|
||||||
},
|
},
|
||||||
@@ -438,6 +441,7 @@ def _tendon_jax_impl(m: types.Model, d: types.Data):
|
|||||||
m.jnt_qposadr,
|
m.jnt_qposadr,
|
||||||
m.ntendon,
|
m.ntendon,
|
||||||
m.nv,
|
m.nv,
|
||||||
|
m.nwrap,
|
||||||
m.site_bodyid,
|
m.site_bodyid,
|
||||||
m.tendon_adr,
|
m.tendon_adr,
|
||||||
m._impl.tendon_geom_adr,
|
m._impl.tendon_geom_adr,
|
||||||
@@ -461,7 +465,6 @@ def _tendon_jax_impl(m: types.Model, d: types.Data):
|
|||||||
d.ten_length,
|
d.ten_length,
|
||||||
d._impl.ten_wrapadr,
|
d._impl.ten_wrapadr,
|
||||||
d._impl.ten_wrapnum,
|
d._impl.ten_wrapnum,
|
||||||
d._impl.wrap_geom_xpos,
|
|
||||||
d._impl.wrap_obj,
|
d._impl.wrap_obj,
|
||||||
d._impl.wrap_xpos,
|
d._impl.wrap_xpos,
|
||||||
)
|
)
|
||||||
@@ -476,9 +479,8 @@ def _tendon_jax_impl(m: types.Model, d: types.Data):
|
|||||||
'ten_length': out[7],
|
'ten_length': out[7],
|
||||||
'_impl.ten_wrapadr': out[8],
|
'_impl.ten_wrapadr': out[8],
|
||||||
'_impl.ten_wrapnum': out[9],
|
'_impl.ten_wrapnum': out[9],
|
||||||
'_impl.wrap_geom_xpos': out[10],
|
'_impl.wrap_obj': out[10],
|
||||||
'_impl.wrap_obj': out[11],
|
'_impl.wrap_xpos': out[11],
|
||||||
'_impl.wrap_xpos': out[12],
|
|
||||||
})
|
})
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ def assert_attr_eq(a, b, attr):
|
|||||||
|
|
||||||
|
|
||||||
def make_data(
|
def make_data(
|
||||||
m: mujoco.MjModel, worldid: int, nconmax: int = 1_000, njmax: int = 100
|
m: mujoco.MjModel, worldid: int, nconmax: int = 1_000, njmax: int = 200
|
||||||
):
|
):
|
||||||
"""Make data for a given worldid using keyframes when available."""
|
"""Make data for a given worldid using keyframes when available."""
|
||||||
dx = mjx.make_data(m, impl='warp', nconmax=nconmax, njmax=njmax)
|
dx = mjx.make_data(m, impl='warp', nconmax=nconmax, njmax=njmax)
|
||||||
@@ -149,19 +149,20 @@ def _mjx_efc(dx, worldid: int):
|
|||||||
keys = np.arange(nefc)
|
keys = np.arange(nefc)
|
||||||
if not keys.size:
|
if not keys.size:
|
||||||
empty = np.array([])
|
empty = np.array([])
|
||||||
return 0, empty, empty, np.zeros((0, dx.qvel.shape[0])), empty, empty
|
return 0, empty, empty, np.zeros((0, dx.qvel.shape[-1])), empty, empty
|
||||||
efc_pos = select(dx._impl.efc__pos[:nefc])
|
efc_pos = select(dx._impl.efc__pos)[:nefc]
|
||||||
efc_type = select(dx._impl.efc__type[:nefc])
|
efc_type = select(dx._impl.efc__type)[:nefc]
|
||||||
efc_d = select(dx._impl.efc__D[:nefc])
|
efc_d = select(dx._impl.efc__D)[:nefc]
|
||||||
keys_sorted = np.lexsort((-efc_pos, efc_type, efc_d))
|
keys_sorted = np.lexsort((-efc_pos, efc_type, efc_d))
|
||||||
keys = keys[keys_sorted]
|
keys = keys[keys_sorted]
|
||||||
|
|
||||||
nefc = len(keys)
|
nefc = len(keys)
|
||||||
type_ = efc_type[keys]
|
type_ = efc_type[keys]
|
||||||
pos = efc_pos[keys]
|
pos = efc_pos[keys]
|
||||||
j = select(dx._impl.efc__J[:nefc])[keys]
|
# MuJoCo Warp may pad efc_J for tiled ops.
|
||||||
aref = select(dx._impl.efc__aref[:nefc])[keys]
|
j = select(dx._impl.efc__J)[:nefc][keys][:, :dx.qvel.shape[-1]]
|
||||||
d_ = select(dx._impl.efc__D[:nefc])[keys]
|
aref = select(dx._impl.efc__aref)[:nefc][keys]
|
||||||
|
d_ = select(dx._impl.efc__D)[:nefc][keys]
|
||||||
return nefc, type_, pos, j, aref, d_
|
return nefc, type_, pos, j, aref, d_
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+40
-227
@@ -63,11 +63,11 @@ class BlockDim:
|
|||||||
energy_vel_kinetic: int
|
energy_vel_kinetic: int
|
||||||
euler_dense: int
|
euler_dense: int
|
||||||
mul_m_dense: int
|
mul_m_dense: int
|
||||||
qderiv_actuator_passive_actuation: int
|
|
||||||
qderiv_actuator_passive_no_actuation: int
|
|
||||||
ray: int
|
ray: int
|
||||||
segmented_sort: int
|
segmented_sort: int
|
||||||
tendon_velocity: int
|
tendon_velocity: int
|
||||||
|
update_gradient_JTDAJ_dense: int
|
||||||
|
update_gradient_JTDAJ_sparse: int
|
||||||
update_gradient_cholesky: int
|
update_gradient_cholesky: int
|
||||||
|
|
||||||
def tree_flatten(self):
|
def tree_flatten(self):
|
||||||
@@ -154,12 +154,17 @@ class ModelWarp(PyTreeNode):
|
|||||||
mesh_polyvertadr: np.ndarray
|
mesh_polyvertadr: np.ndarray
|
||||||
mesh_polyvertnum: np.ndarray
|
mesh_polyvertnum: np.ndarray
|
||||||
mocap_bodyid: np.ndarray
|
mocap_bodyid: np.ndarray
|
||||||
|
nacttrnbody: int
|
||||||
nflex: int
|
nflex: int
|
||||||
nflexedge: int
|
nflexedge: int
|
||||||
nflexelem: int
|
nflexelem: int
|
||||||
nflexelemdata: int
|
nflexelemdata: int
|
||||||
nflexvert: int
|
nflexvert: int
|
||||||
nlsp: int
|
nmaxmeshdeg: int
|
||||||
|
nmaxpolygon: int
|
||||||
|
nrangefinder: int
|
||||||
|
nsensorcollision: int
|
||||||
|
nsensorcontact: int
|
||||||
nsensortaxel: int
|
nsensortaxel: int
|
||||||
nxn_geom_pair: np.ndarray
|
nxn_geom_pair: np.ndarray
|
||||||
nxn_geom_pair_filtered: np.ndarray
|
nxn_geom_pair_filtered: np.ndarray
|
||||||
@@ -180,6 +185,7 @@ class ModelWarp(PyTreeNode):
|
|||||||
rangefinder_sensor_adr: np.ndarray
|
rangefinder_sensor_adr: np.ndarray
|
||||||
sensor_acc_adr: np.ndarray
|
sensor_acc_adr: np.ndarray
|
||||||
sensor_adr_to_contact_adr: np.ndarray
|
sensor_adr_to_contact_adr: np.ndarray
|
||||||
|
sensor_collision_start_adr: np.ndarray
|
||||||
sensor_contact_adr: np.ndarray
|
sensor_contact_adr: np.ndarray
|
||||||
sensor_e_kinetic: bool
|
sensor_e_kinetic: bool
|
||||||
sensor_e_potential: bool
|
sensor_e_potential: bool
|
||||||
@@ -194,7 +200,6 @@ class ModelWarp(PyTreeNode):
|
|||||||
sensor_tendonactfrc_adr: np.ndarray
|
sensor_tendonactfrc_adr: np.ndarray
|
||||||
sensor_touch_adr: np.ndarray
|
sensor_touch_adr: np.ndarray
|
||||||
sensor_vel_adr: np.ndarray
|
sensor_vel_adr: np.ndarray
|
||||||
subtree_mass: jax.Array
|
|
||||||
taxel_sensorid: np.ndarray
|
taxel_sensorid: np.ndarray
|
||||||
taxel_vertadr: np.ndarray
|
taxel_vertadr: np.ndarray
|
||||||
ten_wrapadr_site: np.ndarray
|
ten_wrapadr_site: np.ndarray
|
||||||
@@ -211,12 +216,8 @@ class ModelWarp(PyTreeNode):
|
|||||||
|
|
||||||
class DataWarp(PyTreeNode):
|
class DataWarp(PyTreeNode):
|
||||||
"""Derived fields from Data."""
|
"""Derived fields from Data."""
|
||||||
act_dot_rk: jax.Array
|
|
||||||
act_t0: jax.Array
|
|
||||||
act_vel_integration: jax.Array
|
|
||||||
actuator_length: jax.Array
|
actuator_length: jax.Array
|
||||||
actuator_moment: jax.Array
|
actuator_moment: jax.Array
|
||||||
actuator_trntype_body_ncon: jax.Array
|
|
||||||
actuator_velocity: jax.Array
|
actuator_velocity: jax.Array
|
||||||
cacc: jax.Array
|
cacc: jax.Array
|
||||||
cdof: jax.Array
|
cdof: jax.Array
|
||||||
@@ -233,11 +234,13 @@ class DataWarp(PyTreeNode):
|
|||||||
contact__frame: jax.Array
|
contact__frame: jax.Array
|
||||||
contact__friction: jax.Array
|
contact__friction: jax.Array
|
||||||
contact__geom: jax.Array
|
contact__geom: jax.Array
|
||||||
|
contact__geomcollisionid: jax.Array
|
||||||
contact__includemargin: jax.Array
|
contact__includemargin: jax.Array
|
||||||
contact__pos: jax.Array
|
contact__pos: jax.Array
|
||||||
contact__solimp: jax.Array
|
contact__solimp: jax.Array
|
||||||
contact__solref: jax.Array
|
contact__solref: jax.Array
|
||||||
contact__solreffriction: jax.Array
|
contact__solreffriction: jax.Array
|
||||||
|
contact__type: jax.Array
|
||||||
contact__worldid: jax.Array
|
contact__worldid: jax.Array
|
||||||
crb: jax.Array
|
crb: jax.Array
|
||||||
efc__D: jax.Array
|
efc__D: jax.Array
|
||||||
@@ -251,7 +254,6 @@ class DataWarp(PyTreeNode):
|
|||||||
efc__cholesky_L_tmp: jax.Array
|
efc__cholesky_L_tmp: jax.Array
|
||||||
efc__cholesky_y_tmp: jax.Array
|
efc__cholesky_y_tmp: jax.Array
|
||||||
efc__cost: jax.Array
|
efc__cost: jax.Array
|
||||||
efc__cost_candidate: jax.Array
|
|
||||||
efc__done: jax.Array
|
efc__done: jax.Array
|
||||||
efc__force: jax.Array
|
efc__force: jax.Array
|
||||||
efc__frictionloss: jax.Array
|
efc__frictionloss: jax.Array
|
||||||
@@ -275,37 +277,11 @@ class DataWarp(PyTreeNode):
|
|||||||
efc__type: jax.Array
|
efc__type: jax.Array
|
||||||
efc__vel: jax.Array
|
efc__vel: jax.Array
|
||||||
energy: jax.Array
|
energy: jax.Array
|
||||||
energy_vel_mul_m_skip: jax.Array
|
|
||||||
epa_face: jax.Array
|
|
||||||
epa_horizon: jax.Array
|
|
||||||
epa_index: jax.Array
|
|
||||||
epa_map: jax.Array
|
|
||||||
epa_norm2: jax.Array
|
|
||||||
epa_pr: jax.Array
|
|
||||||
epa_vert: jax.Array
|
|
||||||
epa_vert1: jax.Array
|
|
||||||
epa_vert2: jax.Array
|
|
||||||
epa_vert_index1: jax.Array
|
|
||||||
epa_vert_index2: jax.Array
|
|
||||||
flexedge_length: jax.Array
|
flexedge_length: jax.Array
|
||||||
flexedge_velocity: jax.Array
|
flexedge_velocity: jax.Array
|
||||||
flexvert_xpos: jax.Array
|
flexvert_xpos: jax.Array
|
||||||
fluid_applied: jax.Array
|
|
||||||
geom_skip: jax.Array
|
|
||||||
inverse_mul_m_skip: jax.Array
|
|
||||||
light_xdir: jax.Array
|
light_xdir: jax.Array
|
||||||
light_xpos: jax.Array
|
light_xpos: jax.Array
|
||||||
multiccd_clipped: jax.Array
|
|
||||||
multiccd_endvert: jax.Array
|
|
||||||
multiccd_face1: jax.Array
|
|
||||||
multiccd_face2: jax.Array
|
|
||||||
multiccd_idx1: jax.Array
|
|
||||||
multiccd_idx2: jax.Array
|
|
||||||
multiccd_n1: jax.Array
|
|
||||||
multiccd_n2: jax.Array
|
|
||||||
multiccd_pdist: jax.Array
|
|
||||||
multiccd_pnormal: jax.Array
|
|
||||||
multiccd_polygon: jax.Array
|
|
||||||
nacon: jax.Array
|
nacon: jax.Array
|
||||||
naconmax: int
|
naconmax: int
|
||||||
ncollision: jax.Array
|
ncollision: jax.Array
|
||||||
@@ -321,49 +297,18 @@ class DataWarp(PyTreeNode):
|
|||||||
nsolving: jax.Array
|
nsolving: jax.Array
|
||||||
nworld: int
|
nworld: int
|
||||||
qLD: jax.Array
|
qLD: jax.Array
|
||||||
qLD_integration: jax.Array
|
|
||||||
qLDiagInv: jax.Array
|
qLDiagInv: jax.Array
|
||||||
qLDiagInv_integration: jax.Array
|
|
||||||
qM: jax.Array
|
qM: jax.Array
|
||||||
qM_integration: jax.Array
|
|
||||||
qacc_discrete: jax.Array
|
|
||||||
qacc_integration: jax.Array
|
|
||||||
qacc_rk: jax.Array
|
|
||||||
qfrc_damper: jax.Array
|
qfrc_damper: jax.Array
|
||||||
qfrc_integration: jax.Array
|
|
||||||
qfrc_spring: jax.Array
|
qfrc_spring: jax.Array
|
||||||
qpos_t0: jax.Array
|
|
||||||
qvel_rk: jax.Array
|
|
||||||
qvel_t0: jax.Array
|
|
||||||
ray_bodyexclude: jax.Array
|
|
||||||
ray_dist: jax.Array
|
|
||||||
ray_geomid: jax.Array
|
|
||||||
sap_cumulative_sum: jax.Array
|
|
||||||
sap_projection_lower: jax.Array
|
|
||||||
sap_projection_upper: jax.Array
|
|
||||||
sap_range: jax.Array
|
|
||||||
sap_segment_index: jax.Array
|
|
||||||
sap_sort_index: jax.Array
|
|
||||||
sensor_contact_criteria: jax.Array
|
|
||||||
sensor_contact_direction: jax.Array
|
|
||||||
sensor_contact_matchid: jax.Array
|
|
||||||
sensor_contact_nmatch: jax.Array
|
|
||||||
sensor_rangefinder_dist: jax.Array
|
|
||||||
sensor_rangefinder_geomid: jax.Array
|
|
||||||
sensor_rangefinder_pnt: jax.Array
|
|
||||||
sensor_rangefinder_vec: jax.Array
|
|
||||||
solver_niter: jax.Array
|
solver_niter: jax.Array
|
||||||
subtree_angmom: jax.Array
|
subtree_angmom: jax.Array
|
||||||
subtree_bodyvel: jax.Array
|
subtree_bodyvel: jax.Array
|
||||||
subtree_linvel: jax.Array
|
subtree_linvel: jax.Array
|
||||||
ten_J: jax.Array
|
ten_J: jax.Array
|
||||||
ten_Jdot: jax.Array
|
|
||||||
ten_actfrc: jax.Array
|
|
||||||
ten_bias_coef: jax.Array
|
|
||||||
ten_velocity: jax.Array
|
ten_velocity: jax.Array
|
||||||
ten_wrapadr: jax.Array
|
ten_wrapadr: jax.Array
|
||||||
ten_wrapnum: jax.Array
|
ten_wrapnum: jax.Array
|
||||||
wrap_geom_xpos: jax.Array
|
|
||||||
wrap_obj: jax.Array
|
wrap_obj: jax.Array
|
||||||
wrap_xpos: jax.Array
|
wrap_xpos: jax.Array
|
||||||
shape = property(lambda self: self.cacc.shape)
|
shape = property(lambda self: self.cacc.shape)
|
||||||
@@ -377,42 +322,20 @@ DATA_NON_VMAP = {
|
|||||||
'contact__frame',
|
'contact__frame',
|
||||||
'contact__friction',
|
'contact__friction',
|
||||||
'contact__geom',
|
'contact__geom',
|
||||||
|
'contact__geomcollisionid',
|
||||||
'contact__includemargin',
|
'contact__includemargin',
|
||||||
'contact__pos',
|
'contact__pos',
|
||||||
'contact__solimp',
|
'contact__solimp',
|
||||||
'contact__solref',
|
'contact__solref',
|
||||||
'contact__solreffriction',
|
'contact__solreffriction',
|
||||||
|
'contact__type',
|
||||||
'contact__worldid',
|
'contact__worldid',
|
||||||
'epa_face',
|
|
||||||
'epa_horizon',
|
|
||||||
'epa_index',
|
|
||||||
'epa_map',
|
|
||||||
'epa_norm2',
|
|
||||||
'epa_pr',
|
|
||||||
'epa_vert',
|
|
||||||
'epa_vert1',
|
|
||||||
'epa_vert2',
|
|
||||||
'epa_vert_index1',
|
|
||||||
'epa_vert_index2',
|
|
||||||
'geom_skip',
|
|
||||||
'multiccd_clipped',
|
|
||||||
'multiccd_endvert',
|
|
||||||
'multiccd_face1',
|
|
||||||
'multiccd_face2',
|
|
||||||
'multiccd_idx1',
|
|
||||||
'multiccd_idx2',
|
|
||||||
'multiccd_n1',
|
|
||||||
'multiccd_n2',
|
|
||||||
'multiccd_pdist',
|
|
||||||
'multiccd_pnormal',
|
|
||||||
'multiccd_polygon',
|
|
||||||
'nacon',
|
'nacon',
|
||||||
'naconmax',
|
'naconmax',
|
||||||
'ncollision',
|
'ncollision',
|
||||||
'njmax',
|
'njmax',
|
||||||
'nsolving',
|
'nsolving',
|
||||||
'nworld',
|
'nworld',
|
||||||
'ray_bodyexclude',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def _to_elt(cont, _, d, axis):
|
def _to_elt(cont, _, d, axis):
|
||||||
@@ -443,13 +366,9 @@ _NDIM = {
|
|||||||
'Data': {
|
'Data': {
|
||||||
'act': 2,
|
'act': 2,
|
||||||
'act_dot': 2,
|
'act_dot': 2,
|
||||||
'act_dot_rk': 2,
|
|
||||||
'act_t0': 2,
|
|
||||||
'act_vel_integration': 2,
|
|
||||||
'actuator_force': 2,
|
'actuator_force': 2,
|
||||||
'actuator_length': 2,
|
'actuator_length': 2,
|
||||||
'actuator_moment': 3,
|
'actuator_moment': 3,
|
||||||
'actuator_trntype_body_ncon': 2,
|
|
||||||
'actuator_velocity': 2,
|
'actuator_velocity': 2,
|
||||||
'cacc': 3,
|
'cacc': 3,
|
||||||
'cam_xmat': 4,
|
'cam_xmat': 4,
|
||||||
@@ -460,7 +379,7 @@ _NDIM = {
|
|||||||
'cfrc_int': 3,
|
'cfrc_int': 3,
|
||||||
'cinert': 3,
|
'cinert': 3,
|
||||||
'collision_pair': 2,
|
'collision_pair': 2,
|
||||||
'collision_pairid': 1,
|
'collision_pairid': 2,
|
||||||
'collision_worldid': 1,
|
'collision_worldid': 1,
|
||||||
'contact__dim': 1,
|
'contact__dim': 1,
|
||||||
'contact__dist': 1,
|
'contact__dist': 1,
|
||||||
@@ -468,11 +387,13 @@ _NDIM = {
|
|||||||
'contact__frame': 3,
|
'contact__frame': 3,
|
||||||
'contact__friction': 2,
|
'contact__friction': 2,
|
||||||
'contact__geom': 2,
|
'contact__geom': 2,
|
||||||
|
'contact__geomcollisionid': 1,
|
||||||
'contact__includemargin': 1,
|
'contact__includemargin': 1,
|
||||||
'contact__pos': 2,
|
'contact__pos': 2,
|
||||||
'contact__solimp': 2,
|
'contact__solimp': 2,
|
||||||
'contact__solref': 2,
|
'contact__solref': 2,
|
||||||
'contact__solreffriction': 2,
|
'contact__solreffriction': 2,
|
||||||
|
'contact__type': 1,
|
||||||
'contact__worldid': 1,
|
'contact__worldid': 1,
|
||||||
'crb': 3,
|
'crb': 3,
|
||||||
'ctrl': 2,
|
'ctrl': 2,
|
||||||
@@ -488,7 +409,6 @@ _NDIM = {
|
|||||||
'efc__cholesky_L_tmp': 3,
|
'efc__cholesky_L_tmp': 3,
|
||||||
'efc__cholesky_y_tmp': 2,
|
'efc__cholesky_y_tmp': 2,
|
||||||
'efc__cost': 1,
|
'efc__cost': 1,
|
||||||
'efc__cost_candidate': 2,
|
|
||||||
'efc__done': 1,
|
'efc__done': 1,
|
||||||
'efc__force': 2,
|
'efc__force': 2,
|
||||||
'efc__frictionloss': 2,
|
'efc__frictionloss': 2,
|
||||||
@@ -512,42 +432,16 @@ _NDIM = {
|
|||||||
'efc__type': 2,
|
'efc__type': 2,
|
||||||
'efc__vel': 2,
|
'efc__vel': 2,
|
||||||
'energy': 2,
|
'energy': 2,
|
||||||
'energy_vel_mul_m_skip': 1,
|
|
||||||
'epa_face': 3,
|
|
||||||
'epa_horizon': 2,
|
|
||||||
'epa_index': 2,
|
|
||||||
'epa_map': 2,
|
|
||||||
'epa_norm2': 2,
|
|
||||||
'epa_pr': 3,
|
|
||||||
'epa_vert': 3,
|
|
||||||
'epa_vert1': 3,
|
|
||||||
'epa_vert2': 3,
|
|
||||||
'epa_vert_index1': 2,
|
|
||||||
'epa_vert_index2': 2,
|
|
||||||
'eq_active': 2,
|
'eq_active': 2,
|
||||||
'flexedge_length': 2,
|
'flexedge_length': 2,
|
||||||
'flexedge_velocity': 2,
|
'flexedge_velocity': 2,
|
||||||
'flexvert_xpos': 3,
|
'flexvert_xpos': 3,
|
||||||
'fluid_applied': 3,
|
|
||||||
'geom_skip': 1,
|
|
||||||
'geom_xmat': 4,
|
'geom_xmat': 4,
|
||||||
'geom_xpos': 3,
|
'geom_xpos': 3,
|
||||||
'inverse_mul_m_skip': 1,
|
|
||||||
'light_xdir': 3,
|
'light_xdir': 3,
|
||||||
'light_xpos': 3,
|
'light_xpos': 3,
|
||||||
'mocap_pos': 3,
|
'mocap_pos': 3,
|
||||||
'mocap_quat': 3,
|
'mocap_quat': 3,
|
||||||
'multiccd_clipped': 3,
|
|
||||||
'multiccd_endvert': 3,
|
|
||||||
'multiccd_face1': 3,
|
|
||||||
'multiccd_face2': 3,
|
|
||||||
'multiccd_idx1': 2,
|
|
||||||
'multiccd_idx2': 2,
|
|
||||||
'multiccd_n1': 3,
|
|
||||||
'multiccd_n2': 3,
|
|
||||||
'multiccd_pdist': 2,
|
|
||||||
'multiccd_pnormal': 3,
|
|
||||||
'multiccd_polygon': 3,
|
|
||||||
'nacon': 1,
|
'nacon': 1,
|
||||||
'naconmax': 0,
|
'naconmax': 0,
|
||||||
'ncollision': 1,
|
'ncollision': 1,
|
||||||
@@ -563,15 +457,9 @@ _NDIM = {
|
|||||||
'nsolving': 1,
|
'nsolving': 1,
|
||||||
'nworld': 0,
|
'nworld': 0,
|
||||||
'qLD': 3,
|
'qLD': 3,
|
||||||
'qLD_integration': 3,
|
|
||||||
'qLDiagInv': 2,
|
'qLDiagInv': 2,
|
||||||
'qLDiagInv_integration': 2,
|
|
||||||
'qM': 3,
|
'qM': 3,
|
||||||
'qM_integration': 3,
|
|
||||||
'qacc': 2,
|
'qacc': 2,
|
||||||
'qacc_discrete': 2,
|
|
||||||
'qacc_integration': 2,
|
|
||||||
'qacc_rk': 2,
|
|
||||||
'qacc_smooth': 2,
|
'qacc_smooth': 2,
|
||||||
'qacc_warmstart': 2,
|
'qacc_warmstart': 2,
|
||||||
'qfrc_actuator': 2,
|
'qfrc_actuator': 2,
|
||||||
@@ -581,33 +469,12 @@ _NDIM = {
|
|||||||
'qfrc_damper': 2,
|
'qfrc_damper': 2,
|
||||||
'qfrc_fluid': 2,
|
'qfrc_fluid': 2,
|
||||||
'qfrc_gravcomp': 2,
|
'qfrc_gravcomp': 2,
|
||||||
'qfrc_integration': 2,
|
|
||||||
'qfrc_inverse': 2,
|
'qfrc_inverse': 2,
|
||||||
'qfrc_passive': 2,
|
'qfrc_passive': 2,
|
||||||
'qfrc_smooth': 2,
|
'qfrc_smooth': 2,
|
||||||
'qfrc_spring': 2,
|
'qfrc_spring': 2,
|
||||||
'qpos': 2,
|
'qpos': 2,
|
||||||
'qpos_t0': 2,
|
|
||||||
'qvel': 2,
|
'qvel': 2,
|
||||||
'qvel_rk': 2,
|
|
||||||
'qvel_t0': 2,
|
|
||||||
'ray_bodyexclude': 1,
|
|
||||||
'ray_dist': 2,
|
|
||||||
'ray_geomid': 2,
|
|
||||||
'sap_cumulative_sum': 2,
|
|
||||||
'sap_projection_lower': 3,
|
|
||||||
'sap_projection_upper': 2,
|
|
||||||
'sap_range': 2,
|
|
||||||
'sap_segment_index': 2,
|
|
||||||
'sap_sort_index': 3,
|
|
||||||
'sensor_contact_criteria': 3,
|
|
||||||
'sensor_contact_direction': 3,
|
|
||||||
'sensor_contact_matchid': 3,
|
|
||||||
'sensor_contact_nmatch': 2,
|
|
||||||
'sensor_rangefinder_dist': 2,
|
|
||||||
'sensor_rangefinder_geomid': 2,
|
|
||||||
'sensor_rangefinder_pnt': 3,
|
|
||||||
'sensor_rangefinder_vec': 3,
|
|
||||||
'sensordata': 2,
|
'sensordata': 2,
|
||||||
'site_xmat': 4,
|
'site_xmat': 4,
|
||||||
'site_xpos': 3,
|
'site_xpos': 3,
|
||||||
@@ -617,15 +484,11 @@ _NDIM = {
|
|||||||
'subtree_com': 3,
|
'subtree_com': 3,
|
||||||
'subtree_linvel': 3,
|
'subtree_linvel': 3,
|
||||||
'ten_J': 3,
|
'ten_J': 3,
|
||||||
'ten_Jdot': 3,
|
|
||||||
'ten_actfrc': 2,
|
|
||||||
'ten_bias_coef': 2,
|
|
||||||
'ten_length': 2,
|
'ten_length': 2,
|
||||||
'ten_velocity': 2,
|
'ten_velocity': 2,
|
||||||
'ten_wrapadr': 2,
|
'ten_wrapadr': 2,
|
||||||
'ten_wrapnum': 2,
|
'ten_wrapnum': 2,
|
||||||
'time': 1,
|
'time': 1,
|
||||||
'wrap_geom_xpos': 3,
|
|
||||||
'wrap_obj': 3,
|
'wrap_obj': 3,
|
||||||
'wrap_xpos': 3,
|
'wrap_xpos': 3,
|
||||||
'xanchor': 3,
|
'xanchor': 3,
|
||||||
@@ -673,11 +536,11 @@ _NDIM = {
|
|||||||
'block_dim__energy_vel_kinetic': 0,
|
'block_dim__energy_vel_kinetic': 0,
|
||||||
'block_dim__euler_dense': 0,
|
'block_dim__euler_dense': 0,
|
||||||
'block_dim__mul_m_dense': 0,
|
'block_dim__mul_m_dense': 0,
|
||||||
'block_dim__qderiv_actuator_passive_actuation': 0,
|
|
||||||
'block_dim__qderiv_actuator_passive_no_actuation': 0,
|
|
||||||
'block_dim__ray': 0,
|
'block_dim__ray': 0,
|
||||||
'block_dim__segmented_sort': 0,
|
'block_dim__segmented_sort': 0,
|
||||||
'block_dim__tendon_velocity': 0,
|
'block_dim__tendon_velocity': 0,
|
||||||
|
'block_dim__update_gradient_JTDAJ_dense': 0,
|
||||||
|
'block_dim__update_gradient_JTDAJ_sparse': 0,
|
||||||
'block_dim__update_gradient_cholesky': 0,
|
'block_dim__update_gradient_cholesky': 0,
|
||||||
'body_conaffinity': 1,
|
'body_conaffinity': 1,
|
||||||
'body_contype': 1,
|
'body_contype': 1,
|
||||||
@@ -755,7 +618,7 @@ _NDIM = {
|
|||||||
'flex_vertbodyid': 1,
|
'flex_vertbodyid': 1,
|
||||||
'flex_vertnum': 1,
|
'flex_vertnum': 1,
|
||||||
'flexedge_length0': 1,
|
'flexedge_length0': 1,
|
||||||
'geom_aabb': 3,
|
'geom_aabb': 4,
|
||||||
'geom_bodyid': 1,
|
'geom_bodyid': 1,
|
||||||
'geom_conaffinity': 1,
|
'geom_conaffinity': 1,
|
||||||
'geom_condim': 1,
|
'geom_condim': 1,
|
||||||
@@ -840,6 +703,7 @@ _NDIM = {
|
|||||||
'nC': 0,
|
'nC': 0,
|
||||||
'nM': 0,
|
'nM': 0,
|
||||||
'na': 0,
|
'na': 0,
|
||||||
|
'nacttrnbody': 0,
|
||||||
'nbody': 0,
|
'nbody': 0,
|
||||||
'ncam': 0,
|
'ncam': 0,
|
||||||
'neq': 0,
|
'neq': 0,
|
||||||
@@ -855,8 +719,9 @@ _NDIM = {
|
|||||||
'nhfielddata': 0,
|
'nhfielddata': 0,
|
||||||
'njnt': 0,
|
'njnt': 0,
|
||||||
'nlight': 0,
|
'nlight': 0,
|
||||||
'nlsp': 0,
|
|
||||||
'nmat': 0,
|
'nmat': 0,
|
||||||
|
'nmaxmeshdeg': 0,
|
||||||
|
'nmaxpolygon': 0,
|
||||||
'nmeshface': 0,
|
'nmeshface': 0,
|
||||||
'nmeshgraph': 0,
|
'nmeshgraph': 0,
|
||||||
'nmeshpoly': 0,
|
'nmeshpoly': 0,
|
||||||
@@ -866,7 +731,10 @@ _NDIM = {
|
|||||||
'nmocap': 0,
|
'nmocap': 0,
|
||||||
'npair': 0,
|
'npair': 0,
|
||||||
'nq': 0,
|
'nq': 0,
|
||||||
|
'nrangefinder': 0,
|
||||||
'nsensor': 0,
|
'nsensor': 0,
|
||||||
|
'nsensorcollision': 0,
|
||||||
|
'nsensorcontact': 0,
|
||||||
'nsensordata': 0,
|
'nsensordata': 0,
|
||||||
'nsensortaxel': 0,
|
'nsensortaxel': 0,
|
||||||
'nsite': 0,
|
'nsite': 0,
|
||||||
@@ -876,8 +744,8 @@ _NDIM = {
|
|||||||
'nwrap': 0,
|
'nwrap': 0,
|
||||||
'nxn_geom_pair': 2,
|
'nxn_geom_pair': 2,
|
||||||
'nxn_geom_pair_filtered': 2,
|
'nxn_geom_pair_filtered': 2,
|
||||||
'nxn_pairid': 1,
|
'nxn_pairid': 2,
|
||||||
'nxn_pairid_filtered': 1,
|
'nxn_pairid_filtered': 2,
|
||||||
'oct_aabb': 3,
|
'oct_aabb': 3,
|
||||||
'oct_child': 2,
|
'oct_child': 2,
|
||||||
'oct_coeff': 2,
|
'oct_coeff': 2,
|
||||||
@@ -935,6 +803,7 @@ _NDIM = {
|
|||||||
'sensor_acc_adr': 1,
|
'sensor_acc_adr': 1,
|
||||||
'sensor_adr': 1,
|
'sensor_adr': 1,
|
||||||
'sensor_adr_to_contact_adr': 1,
|
'sensor_adr_to_contact_adr': 1,
|
||||||
|
'sensor_collision_start_adr': 1,
|
||||||
'sensor_contact_adr': 1,
|
'sensor_contact_adr': 1,
|
||||||
'sensor_cutoff': 1,
|
'sensor_cutoff': 1,
|
||||||
'sensor_datatype': 1,
|
'sensor_datatype': 1,
|
||||||
@@ -964,7 +833,6 @@ _NDIM = {
|
|||||||
'site_size': 2,
|
'site_size': 2,
|
||||||
'site_type': 1,
|
'site_type': 1,
|
||||||
'stat__meaninertia': 0,
|
'stat__meaninertia': 0,
|
||||||
'subtree_mass': 2,
|
|
||||||
'taxel_sensorid': 1,
|
'taxel_sensorid': 1,
|
||||||
'taxel_vertadr': 1,
|
'taxel_vertadr': 1,
|
||||||
'ten_wrapadr_site': 1,
|
'ten_wrapadr_site': 1,
|
||||||
@@ -1038,13 +906,9 @@ _BATCH_DIM = {
|
|||||||
'Data': {
|
'Data': {
|
||||||
'act': True,
|
'act': True,
|
||||||
'act_dot': True,
|
'act_dot': True,
|
||||||
'act_dot_rk': True,
|
|
||||||
'act_t0': True,
|
|
||||||
'act_vel_integration': True,
|
|
||||||
'actuator_force': True,
|
'actuator_force': True,
|
||||||
'actuator_length': True,
|
'actuator_length': True,
|
||||||
'actuator_moment': True,
|
'actuator_moment': True,
|
||||||
'actuator_trntype_body_ncon': True,
|
|
||||||
'actuator_velocity': True,
|
'actuator_velocity': True,
|
||||||
'cacc': True,
|
'cacc': True,
|
||||||
'cam_xmat': True,
|
'cam_xmat': True,
|
||||||
@@ -1063,11 +927,13 @@ _BATCH_DIM = {
|
|||||||
'contact__frame': False,
|
'contact__frame': False,
|
||||||
'contact__friction': False,
|
'contact__friction': False,
|
||||||
'contact__geom': False,
|
'contact__geom': False,
|
||||||
|
'contact__geomcollisionid': False,
|
||||||
'contact__includemargin': False,
|
'contact__includemargin': False,
|
||||||
'contact__pos': False,
|
'contact__pos': False,
|
||||||
'contact__solimp': False,
|
'contact__solimp': False,
|
||||||
'contact__solref': False,
|
'contact__solref': False,
|
||||||
'contact__solreffriction': False,
|
'contact__solreffriction': False,
|
||||||
|
'contact__type': False,
|
||||||
'contact__worldid': False,
|
'contact__worldid': False,
|
||||||
'crb': True,
|
'crb': True,
|
||||||
'ctrl': True,
|
'ctrl': True,
|
||||||
@@ -1083,7 +949,6 @@ _BATCH_DIM = {
|
|||||||
'efc__cholesky_L_tmp': True,
|
'efc__cholesky_L_tmp': True,
|
||||||
'efc__cholesky_y_tmp': True,
|
'efc__cholesky_y_tmp': True,
|
||||||
'efc__cost': True,
|
'efc__cost': True,
|
||||||
'efc__cost_candidate': True,
|
|
||||||
'efc__done': True,
|
'efc__done': True,
|
||||||
'efc__force': True,
|
'efc__force': True,
|
||||||
'efc__frictionloss': True,
|
'efc__frictionloss': True,
|
||||||
@@ -1107,42 +972,16 @@ _BATCH_DIM = {
|
|||||||
'efc__type': True,
|
'efc__type': True,
|
||||||
'efc__vel': True,
|
'efc__vel': True,
|
||||||
'energy': True,
|
'energy': True,
|
||||||
'energy_vel_mul_m_skip': True,
|
|
||||||
'epa_face': False,
|
|
||||||
'epa_horizon': False,
|
|
||||||
'epa_index': False,
|
|
||||||
'epa_map': False,
|
|
||||||
'epa_norm2': False,
|
|
||||||
'epa_pr': False,
|
|
||||||
'epa_vert': False,
|
|
||||||
'epa_vert1': False,
|
|
||||||
'epa_vert2': False,
|
|
||||||
'epa_vert_index1': False,
|
|
||||||
'epa_vert_index2': False,
|
|
||||||
'eq_active': True,
|
'eq_active': True,
|
||||||
'flexedge_length': True,
|
'flexedge_length': True,
|
||||||
'flexedge_velocity': True,
|
'flexedge_velocity': True,
|
||||||
'flexvert_xpos': True,
|
'flexvert_xpos': True,
|
||||||
'fluid_applied': True,
|
|
||||||
'geom_skip': False,
|
|
||||||
'geom_xmat': True,
|
'geom_xmat': True,
|
||||||
'geom_xpos': True,
|
'geom_xpos': True,
|
||||||
'inverse_mul_m_skip': True,
|
|
||||||
'light_xdir': True,
|
'light_xdir': True,
|
||||||
'light_xpos': True,
|
'light_xpos': True,
|
||||||
'mocap_pos': True,
|
'mocap_pos': True,
|
||||||
'mocap_quat': True,
|
'mocap_quat': True,
|
||||||
'multiccd_clipped': False,
|
|
||||||
'multiccd_endvert': False,
|
|
||||||
'multiccd_face1': False,
|
|
||||||
'multiccd_face2': False,
|
|
||||||
'multiccd_idx1': False,
|
|
||||||
'multiccd_idx2': False,
|
|
||||||
'multiccd_n1': False,
|
|
||||||
'multiccd_n2': False,
|
|
||||||
'multiccd_pdist': False,
|
|
||||||
'multiccd_pnormal': False,
|
|
||||||
'multiccd_polygon': False,
|
|
||||||
'nacon': False,
|
'nacon': False,
|
||||||
'naconmax': False,
|
'naconmax': False,
|
||||||
'ncollision': False,
|
'ncollision': False,
|
||||||
@@ -1158,15 +997,9 @@ _BATCH_DIM = {
|
|||||||
'nsolving': False,
|
'nsolving': False,
|
||||||
'nworld': False,
|
'nworld': False,
|
||||||
'qLD': True,
|
'qLD': True,
|
||||||
'qLD_integration': True,
|
|
||||||
'qLDiagInv': True,
|
'qLDiagInv': True,
|
||||||
'qLDiagInv_integration': True,
|
|
||||||
'qM': True,
|
'qM': True,
|
||||||
'qM_integration': True,
|
|
||||||
'qacc': True,
|
'qacc': True,
|
||||||
'qacc_discrete': True,
|
|
||||||
'qacc_integration': True,
|
|
||||||
'qacc_rk': True,
|
|
||||||
'qacc_smooth': True,
|
'qacc_smooth': True,
|
||||||
'qacc_warmstart': True,
|
'qacc_warmstart': True,
|
||||||
'qfrc_actuator': True,
|
'qfrc_actuator': True,
|
||||||
@@ -1176,33 +1009,12 @@ _BATCH_DIM = {
|
|||||||
'qfrc_damper': True,
|
'qfrc_damper': True,
|
||||||
'qfrc_fluid': True,
|
'qfrc_fluid': True,
|
||||||
'qfrc_gravcomp': True,
|
'qfrc_gravcomp': True,
|
||||||
'qfrc_integration': True,
|
|
||||||
'qfrc_inverse': True,
|
'qfrc_inverse': True,
|
||||||
'qfrc_passive': True,
|
'qfrc_passive': True,
|
||||||
'qfrc_smooth': True,
|
'qfrc_smooth': True,
|
||||||
'qfrc_spring': True,
|
'qfrc_spring': True,
|
||||||
'qpos': True,
|
'qpos': True,
|
||||||
'qpos_t0': True,
|
|
||||||
'qvel': True,
|
'qvel': True,
|
||||||
'qvel_rk': True,
|
|
||||||
'qvel_t0': True,
|
|
||||||
'ray_bodyexclude': False,
|
|
||||||
'ray_dist': True,
|
|
||||||
'ray_geomid': True,
|
|
||||||
'sap_cumulative_sum': True,
|
|
||||||
'sap_projection_lower': True,
|
|
||||||
'sap_projection_upper': True,
|
|
||||||
'sap_range': True,
|
|
||||||
'sap_segment_index': True,
|
|
||||||
'sap_sort_index': True,
|
|
||||||
'sensor_contact_criteria': True,
|
|
||||||
'sensor_contact_direction': True,
|
|
||||||
'sensor_contact_matchid': True,
|
|
||||||
'sensor_contact_nmatch': True,
|
|
||||||
'sensor_rangefinder_dist': True,
|
|
||||||
'sensor_rangefinder_geomid': True,
|
|
||||||
'sensor_rangefinder_pnt': True,
|
|
||||||
'sensor_rangefinder_vec': True,
|
|
||||||
'sensordata': True,
|
'sensordata': True,
|
||||||
'site_xmat': True,
|
'site_xmat': True,
|
||||||
'site_xpos': True,
|
'site_xpos': True,
|
||||||
@@ -1212,15 +1024,11 @@ _BATCH_DIM = {
|
|||||||
'subtree_com': True,
|
'subtree_com': True,
|
||||||
'subtree_linvel': True,
|
'subtree_linvel': True,
|
||||||
'ten_J': True,
|
'ten_J': True,
|
||||||
'ten_Jdot': True,
|
|
||||||
'ten_actfrc': True,
|
|
||||||
'ten_bias_coef': True,
|
|
||||||
'ten_length': True,
|
'ten_length': True,
|
||||||
'ten_velocity': True,
|
'ten_velocity': True,
|
||||||
'ten_wrapadr': True,
|
'ten_wrapadr': True,
|
||||||
'ten_wrapnum': True,
|
'ten_wrapnum': True,
|
||||||
'time': True,
|
'time': True,
|
||||||
'wrap_geom_xpos': True,
|
|
||||||
'wrap_obj': True,
|
'wrap_obj': True,
|
||||||
'wrap_xpos': True,
|
'wrap_xpos': True,
|
||||||
'xanchor': True,
|
'xanchor': True,
|
||||||
@@ -1268,11 +1076,11 @@ _BATCH_DIM = {
|
|||||||
'block_dim__energy_vel_kinetic': False,
|
'block_dim__energy_vel_kinetic': False,
|
||||||
'block_dim__euler_dense': False,
|
'block_dim__euler_dense': False,
|
||||||
'block_dim__mul_m_dense': False,
|
'block_dim__mul_m_dense': False,
|
||||||
'block_dim__qderiv_actuator_passive_actuation': False,
|
|
||||||
'block_dim__qderiv_actuator_passive_no_actuation': False,
|
|
||||||
'block_dim__ray': False,
|
'block_dim__ray': False,
|
||||||
'block_dim__segmented_sort': False,
|
'block_dim__segmented_sort': False,
|
||||||
'block_dim__tendon_velocity': False,
|
'block_dim__tendon_velocity': False,
|
||||||
|
'block_dim__update_gradient_JTDAJ_dense': False,
|
||||||
|
'block_dim__update_gradient_JTDAJ_sparse': False,
|
||||||
'block_dim__update_gradient_cholesky': False,
|
'block_dim__update_gradient_cholesky': False,
|
||||||
'body_conaffinity': False,
|
'body_conaffinity': False,
|
||||||
'body_contype': False,
|
'body_contype': False,
|
||||||
@@ -1350,7 +1158,7 @@ _BATCH_DIM = {
|
|||||||
'flex_vertbodyid': False,
|
'flex_vertbodyid': False,
|
||||||
'flex_vertnum': False,
|
'flex_vertnum': False,
|
||||||
'flexedge_length0': False,
|
'flexedge_length0': False,
|
||||||
'geom_aabb': False,
|
'geom_aabb': True,
|
||||||
'geom_bodyid': False,
|
'geom_bodyid': False,
|
||||||
'geom_conaffinity': False,
|
'geom_conaffinity': False,
|
||||||
'geom_condim': False,
|
'geom_condim': False,
|
||||||
@@ -1435,6 +1243,7 @@ _BATCH_DIM = {
|
|||||||
'nC': False,
|
'nC': False,
|
||||||
'nM': False,
|
'nM': False,
|
||||||
'na': False,
|
'na': False,
|
||||||
|
'nacttrnbody': False,
|
||||||
'nbody': False,
|
'nbody': False,
|
||||||
'ncam': False,
|
'ncam': False,
|
||||||
'neq': False,
|
'neq': False,
|
||||||
@@ -1450,8 +1259,9 @@ _BATCH_DIM = {
|
|||||||
'nhfielddata': False,
|
'nhfielddata': False,
|
||||||
'njnt': False,
|
'njnt': False,
|
||||||
'nlight': False,
|
'nlight': False,
|
||||||
'nlsp': False,
|
|
||||||
'nmat': False,
|
'nmat': False,
|
||||||
|
'nmaxmeshdeg': False,
|
||||||
|
'nmaxpolygon': False,
|
||||||
'nmeshface': False,
|
'nmeshface': False,
|
||||||
'nmeshgraph': False,
|
'nmeshgraph': False,
|
||||||
'nmeshpoly': False,
|
'nmeshpoly': False,
|
||||||
@@ -1461,7 +1271,10 @@ _BATCH_DIM = {
|
|||||||
'nmocap': False,
|
'nmocap': False,
|
||||||
'npair': False,
|
'npair': False,
|
||||||
'nq': False,
|
'nq': False,
|
||||||
|
'nrangefinder': False,
|
||||||
'nsensor': False,
|
'nsensor': False,
|
||||||
|
'nsensorcollision': False,
|
||||||
|
'nsensorcontact': False,
|
||||||
'nsensordata': False,
|
'nsensordata': False,
|
||||||
'nsensortaxel': False,
|
'nsensortaxel': False,
|
||||||
'nsite': False,
|
'nsite': False,
|
||||||
@@ -1530,6 +1343,7 @@ _BATCH_DIM = {
|
|||||||
'sensor_acc_adr': False,
|
'sensor_acc_adr': False,
|
||||||
'sensor_adr': False,
|
'sensor_adr': False,
|
||||||
'sensor_adr_to_contact_adr': False,
|
'sensor_adr_to_contact_adr': False,
|
||||||
|
'sensor_collision_start_adr': False,
|
||||||
'sensor_contact_adr': False,
|
'sensor_contact_adr': False,
|
||||||
'sensor_cutoff': False,
|
'sensor_cutoff': False,
|
||||||
'sensor_datatype': False,
|
'sensor_datatype': False,
|
||||||
@@ -1559,7 +1373,6 @@ _BATCH_DIM = {
|
|||||||
'site_size': False,
|
'site_size': False,
|
||||||
'site_type': False,
|
'site_type': False,
|
||||||
'stat__meaninertia': False,
|
'stat__meaninertia': False,
|
||||||
'subtree_mass': True,
|
|
||||||
'taxel_sensorid': False,
|
'taxel_sensorid': False,
|
||||||
'taxel_vertadr': False,
|
'taxel_vertadr': False,
|
||||||
'ten_wrapadr_site': False,
|
'ten_wrapadr_site': False,
|
||||||
|
|||||||
Reference in New Issue
Block a user