warp-lang 0.11.0__py3-none-manylinux2014_x86_64.whl → 1.0.0__py3-none-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of warp-lang might be problematic. Click here for more details.
- warp/__init__.py +8 -0
- warp/bin/warp-clang.so +0 -0
- warp/bin/warp.so +0 -0
- warp/build.py +7 -6
- warp/build_dll.py +70 -79
- warp/builtins.py +10 -6
- warp/codegen.py +51 -19
- warp/config.py +7 -8
- warp/constants.py +3 -0
- warp/context.py +948 -245
- warp/dlpack.py +198 -113
- warp/examples/assets/bunny.usd +0 -0
- warp/examples/assets/cartpole.urdf +110 -0
- warp/examples/assets/crazyflie.usd +0 -0
- warp/examples/assets/cube.usda +42 -0
- warp/examples/assets/nv_ant.xml +92 -0
- warp/examples/assets/nv_humanoid.xml +183 -0
- warp/examples/assets/quadruped.urdf +268 -0
- warp/examples/assets/rocks.nvdb +0 -0
- warp/examples/assets/rocks.usd +0 -0
- warp/examples/assets/sphere.usda +56 -0
- warp/examples/assets/torus.usda +105 -0
- warp/examples/benchmarks/benchmark_api.py +383 -0
- warp/examples/benchmarks/benchmark_cloth.py +279 -0
- warp/examples/benchmarks/benchmark_cloth_cupy.py +88 -0
- warp/examples/benchmarks/benchmark_cloth_jax.py +100 -0
- warp/examples/benchmarks/benchmark_cloth_numba.py +142 -0
- warp/examples/benchmarks/benchmark_cloth_numpy.py +77 -0
- warp/examples/benchmarks/benchmark_cloth_pytorch.py +86 -0
- warp/examples/benchmarks/benchmark_cloth_taichi.py +112 -0
- warp/examples/benchmarks/benchmark_cloth_warp.py +146 -0
- warp/examples/benchmarks/benchmark_launches.py +295 -0
- warp/examples/core/example_dem.py +221 -0
- warp/examples/core/example_fluid.py +267 -0
- warp/examples/core/example_graph_capture.py +129 -0
- warp/examples/core/example_marching_cubes.py +177 -0
- warp/examples/core/example_mesh.py +154 -0
- warp/examples/core/example_mesh_intersect.py +193 -0
- warp/examples/core/example_nvdb.py +169 -0
- warp/examples/core/example_raycast.py +89 -0
- warp/examples/core/example_raymarch.py +178 -0
- warp/examples/core/example_render_opengl.py +141 -0
- warp/examples/core/example_sph.py +389 -0
- warp/examples/core/example_torch.py +181 -0
- warp/examples/core/example_wave.py +249 -0
- warp/examples/fem/bsr_utils.py +380 -0
- warp/examples/fem/example_apic_fluid.py +391 -0
- warp/examples/fem/example_convection_diffusion.py +168 -0
- warp/examples/fem/example_convection_diffusion_dg.py +209 -0
- warp/examples/fem/example_convection_diffusion_dg0.py +194 -0
- warp/examples/fem/example_deformed_geometry.py +159 -0
- warp/examples/fem/example_diffusion.py +173 -0
- warp/examples/fem/example_diffusion_3d.py +152 -0
- warp/examples/fem/example_diffusion_mgpu.py +214 -0
- warp/examples/fem/example_mixed_elasticity.py +222 -0
- warp/examples/fem/example_navier_stokes.py +243 -0
- warp/examples/fem/example_stokes.py +192 -0
- warp/examples/fem/example_stokes_transfer.py +249 -0
- warp/examples/fem/mesh_utils.py +109 -0
- warp/examples/fem/plot_utils.py +287 -0
- warp/examples/optim/example_bounce.py +248 -0
- warp/examples/optim/example_cloth_throw.py +210 -0
- warp/examples/optim/example_diffray.py +535 -0
- warp/examples/optim/example_drone.py +850 -0
- warp/examples/optim/example_inverse_kinematics.py +169 -0
- warp/examples/optim/example_inverse_kinematics_torch.py +170 -0
- warp/examples/optim/example_spring_cage.py +234 -0
- warp/examples/optim/example_trajectory.py +201 -0
- warp/examples/sim/example_cartpole.py +128 -0
- warp/examples/sim/example_cloth.py +184 -0
- warp/examples/sim/example_granular.py +113 -0
- warp/examples/sim/example_granular_collision_sdf.py +185 -0
- warp/examples/sim/example_jacobian_ik.py +213 -0
- warp/examples/sim/example_particle_chain.py +106 -0
- warp/examples/sim/example_quadruped.py +179 -0
- warp/examples/sim/example_rigid_chain.py +191 -0
- warp/examples/sim/example_rigid_contact.py +176 -0
- warp/examples/sim/example_rigid_force.py +126 -0
- warp/examples/sim/example_rigid_gyroscopic.py +97 -0
- warp/examples/sim/example_rigid_soft_contact.py +124 -0
- warp/examples/sim/example_soft_body.py +178 -0
- warp/fabric.py +29 -20
- warp/fem/cache.py +0 -1
- warp/fem/dirichlet.py +0 -2
- warp/fem/integrate.py +0 -1
- warp/jax.py +45 -0
- warp/jax_experimental.py +339 -0
- warp/native/builtin.h +12 -0
- warp/native/bvh.cu +18 -18
- warp/native/clang/clang.cpp +8 -3
- warp/native/cuda_util.cpp +94 -5
- warp/native/cuda_util.h +35 -6
- warp/native/cutlass_gemm.cpp +1 -1
- warp/native/cutlass_gemm.cu +4 -1
- warp/native/error.cpp +66 -0
- warp/native/error.h +27 -0
- warp/native/mesh.cu +2 -2
- warp/native/reduce.cu +4 -4
- warp/native/runlength_encode.cu +2 -2
- warp/native/scan.cu +2 -2
- warp/native/sparse.cu +0 -1
- warp/native/temp_buffer.h +2 -2
- warp/native/warp.cpp +95 -60
- warp/native/warp.cu +1053 -218
- warp/native/warp.h +49 -32
- warp/optim/linear.py +33 -16
- warp/render/render_opengl.py +202 -101
- warp/render/render_usd.py +82 -40
- warp/sim/__init__.py +13 -4
- warp/sim/articulation.py +4 -5
- warp/sim/collide.py +320 -175
- warp/sim/import_mjcf.py +25 -30
- warp/sim/import_urdf.py +94 -63
- warp/sim/import_usd.py +51 -36
- warp/sim/inertia.py +3 -2
- warp/sim/integrator.py +233 -0
- warp/sim/integrator_euler.py +447 -469
- warp/sim/integrator_featherstone.py +1991 -0
- warp/sim/integrator_xpbd.py +1420 -640
- warp/sim/model.py +765 -487
- warp/sim/particles.py +2 -1
- warp/sim/render.py +35 -13
- warp/sim/utils.py +222 -11
- warp/stubs.py +8 -0
- warp/tape.py +16 -1
- warp/tests/aux_test_grad_customs.py +23 -0
- warp/tests/test_array.py +190 -1
- warp/tests/test_async.py +656 -0
- warp/tests/test_bool.py +50 -0
- warp/tests/test_dlpack.py +164 -11
- warp/tests/test_examples.py +166 -74
- warp/tests/test_fem.py +8 -1
- warp/tests/test_generics.py +15 -5
- warp/tests/test_grad.py +1 -1
- warp/tests/test_grad_customs.py +172 -12
- warp/tests/test_jax.py +254 -0
- warp/tests/test_large.py +29 -6
- warp/tests/test_launch.py +25 -0
- warp/tests/test_linear_solvers.py +20 -3
- warp/tests/test_matmul.py +61 -16
- warp/tests/test_matmul_lite.py +13 -13
- warp/tests/test_mempool.py +186 -0
- warp/tests/test_multigpu.py +3 -0
- warp/tests/test_options.py +16 -2
- warp/tests/test_peer.py +137 -0
- warp/tests/test_print.py +3 -1
- warp/tests/test_quat.py +23 -0
- warp/tests/test_sim_kinematics.py +97 -0
- warp/tests/test_snippet.py +126 -3
- warp/tests/test_streams.py +108 -79
- warp/tests/test_torch.py +16 -8
- warp/tests/test_utils.py +32 -27
- warp/tests/test_verify_fp.py +65 -0
- warp/tests/test_volume.py +1 -1
- warp/tests/unittest_serial.py +2 -0
- warp/tests/unittest_suites.py +12 -0
- warp/tests/unittest_utils.py +14 -7
- warp/thirdparty/unittest_parallel.py +15 -3
- warp/torch.py +10 -8
- warp/types.py +363 -246
- warp/utils.py +143 -19
- warp_lang-1.0.0.dist-info/LICENSE.md +126 -0
- warp_lang-1.0.0.dist-info/METADATA +394 -0
- {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/RECORD +167 -86
- warp/sim/optimizer.py +0 -138
- warp_lang-0.11.0.dist-info/LICENSE.md +0 -36
- warp_lang-0.11.0.dist-info/METADATA +0 -238
- /warp/tests/{walkthough_debug.py → walkthrough_debug.py} +0 -0
- {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/WHEEL +0 -0
- {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/top_level.txt +0 -0
warp/sim/integrator_euler.py
CHANGED
|
@@ -12,112 +12,13 @@ models + state forward in time.
|
|
|
12
12
|
|
|
13
13
|
import warp as wp
|
|
14
14
|
|
|
15
|
+
from .integrator import Integrator
|
|
15
16
|
from .collide import triangle_closest_point_barycentric
|
|
16
|
-
from .model import PARTICLE_FLAG_ACTIVE, ModelShapeGeometry, ModelShapeMaterials
|
|
17
|
-
from .optimizer import Optimizer
|
|
17
|
+
from .model import Model, State, Control, PARTICLE_FLAG_ACTIVE, ModelShapeGeometry, ModelShapeMaterials
|
|
18
18
|
from .particles import eval_particle_forces
|
|
19
19
|
from .utils import quat_decompose, quat_twist
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
@wp.kernel
|
|
23
|
-
def integrate_particles(
|
|
24
|
-
x: wp.array(dtype=wp.vec3),
|
|
25
|
-
v: wp.array(dtype=wp.vec3),
|
|
26
|
-
f: wp.array(dtype=wp.vec3),
|
|
27
|
-
w: wp.array(dtype=float),
|
|
28
|
-
particle_flags: wp.array(dtype=wp.uint32),
|
|
29
|
-
gravity: wp.vec3,
|
|
30
|
-
dt: float,
|
|
31
|
-
v_max: float,
|
|
32
|
-
x_new: wp.array(dtype=wp.vec3),
|
|
33
|
-
v_new: wp.array(dtype=wp.vec3),
|
|
34
|
-
):
|
|
35
|
-
tid = wp.tid()
|
|
36
|
-
if (particle_flags[tid] & PARTICLE_FLAG_ACTIVE) == 0:
|
|
37
|
-
return
|
|
38
|
-
|
|
39
|
-
x0 = x[tid]
|
|
40
|
-
v0 = v[tid]
|
|
41
|
-
f0 = f[tid]
|
|
42
|
-
|
|
43
|
-
inv_mass = w[tid]
|
|
44
|
-
|
|
45
|
-
# simple semi-implicit Euler. v1 = v0 + a dt, x1 = x0 + v1 dt
|
|
46
|
-
v1 = v0 + (f0 * inv_mass + gravity * wp.step(0.0 - inv_mass)) * dt
|
|
47
|
-
# enforce velocity limit to prevent instability
|
|
48
|
-
v1_mag = wp.length(v1)
|
|
49
|
-
if v1_mag > v_max:
|
|
50
|
-
v1 *= v_max / v1_mag
|
|
51
|
-
x1 = x0 + v1 * dt
|
|
52
|
-
|
|
53
|
-
x_new[tid] = x1
|
|
54
|
-
v_new[tid] = v1
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
# semi-implicit Euler integration
|
|
58
|
-
@wp.kernel
|
|
59
|
-
def integrate_bodies(
|
|
60
|
-
body_q: wp.array(dtype=wp.transform),
|
|
61
|
-
body_qd: wp.array(dtype=wp.spatial_vector),
|
|
62
|
-
body_f: wp.array(dtype=wp.spatial_vector),
|
|
63
|
-
body_com: wp.array(dtype=wp.vec3),
|
|
64
|
-
m: wp.array(dtype=float),
|
|
65
|
-
I: wp.array(dtype=wp.mat33),
|
|
66
|
-
inv_m: wp.array(dtype=float),
|
|
67
|
-
inv_I: wp.array(dtype=wp.mat33),
|
|
68
|
-
gravity: wp.vec3,
|
|
69
|
-
angular_damping: float,
|
|
70
|
-
dt: float,
|
|
71
|
-
# outputs
|
|
72
|
-
body_q_new: wp.array(dtype=wp.transform),
|
|
73
|
-
body_qd_new: wp.array(dtype=wp.spatial_vector),
|
|
74
|
-
):
|
|
75
|
-
tid = wp.tid()
|
|
76
|
-
|
|
77
|
-
# positions
|
|
78
|
-
q = body_q[tid]
|
|
79
|
-
qd = body_qd[tid]
|
|
80
|
-
f = body_f[tid]
|
|
81
|
-
|
|
82
|
-
# masses
|
|
83
|
-
mass = m[tid]
|
|
84
|
-
inv_mass = inv_m[tid] # 1 / mass
|
|
85
|
-
|
|
86
|
-
inertia = I[tid]
|
|
87
|
-
inv_inertia = inv_I[tid] # inverse of 3x3 inertia matrix
|
|
88
|
-
|
|
89
|
-
# unpack transform
|
|
90
|
-
x0 = wp.transform_get_translation(q)
|
|
91
|
-
r0 = wp.transform_get_rotation(q)
|
|
92
|
-
|
|
93
|
-
# unpack spatial twist
|
|
94
|
-
w0 = wp.spatial_top(qd)
|
|
95
|
-
v0 = wp.spatial_bottom(qd)
|
|
96
|
-
|
|
97
|
-
# unpack spatial wrench
|
|
98
|
-
t0 = wp.spatial_top(f)
|
|
99
|
-
f0 = wp.spatial_bottom(f)
|
|
100
|
-
|
|
101
|
-
x_com = x0 + wp.quat_rotate(r0, body_com[tid])
|
|
102
|
-
|
|
103
|
-
# linear part
|
|
104
|
-
v1 = v0 + (f0 * inv_mass + gravity * wp.nonzero(inv_mass)) * dt
|
|
105
|
-
x1 = x_com + v1 * dt
|
|
106
|
-
|
|
107
|
-
# angular part (compute in body frame)
|
|
108
|
-
wb = wp.quat_rotate_inv(r0, w0)
|
|
109
|
-
tb = wp.quat_rotate_inv(r0, t0) - wp.cross(wb, inertia * wb) # coriolis forces
|
|
110
|
-
|
|
111
|
-
w1 = wp.quat_rotate(r0, wb + inv_inertia * tb * dt)
|
|
112
|
-
r1 = wp.normalize(r0 + wp.quat(w1, 0.0) * r0 * 0.5 * dt)
|
|
113
|
-
|
|
114
|
-
# angular damping
|
|
115
|
-
w1 *= 1.0 - angular_damping * dt
|
|
116
|
-
|
|
117
|
-
body_q_new[tid] = wp.transform(x1 - wp.quat_rotate(r1, body_com[tid]), r1)
|
|
118
|
-
body_qd_new[tid] = wp.spatial_vector(w1, v1)
|
|
119
|
-
|
|
120
|
-
|
|
121
22
|
@wp.kernel
|
|
122
23
|
def eval_springs(
|
|
123
24
|
x: wp.array(dtype=wp.vec3),
|
|
@@ -155,7 +56,7 @@ def eval_springs(
|
|
|
155
56
|
c = l - rest
|
|
156
57
|
dcdt = wp.dot(dir, vij)
|
|
157
58
|
|
|
158
|
-
# damping based on relative velocity
|
|
59
|
+
# damping based on relative velocity
|
|
159
60
|
fs = dir * (ke * c + kd * dcdt)
|
|
160
61
|
|
|
161
62
|
wp.atomic_sub(f, i, fs)
|
|
@@ -281,7 +182,7 @@ def eval_triangles(
|
|
|
281
182
|
# -----------------------------
|
|
282
183
|
# Area Damping
|
|
283
184
|
|
|
284
|
-
dcdt = dot(dcdq, v1) + dot(dcdr, v2) - dot(dcdq + dcdr, v0)
|
|
185
|
+
dcdt = wp.dot(dcdq, v1) + wp.dot(dcdr, v2) - wp.dot(dcdq + dcdr, v0)
|
|
285
186
|
f_damp = k_damp * dcdt
|
|
286
187
|
|
|
287
188
|
f1 = f1 + dcdq * (f_area + f_damp)
|
|
@@ -295,9 +196,8 @@ def eval_triangles(
|
|
|
295
196
|
vdir = wp.normalize(vmid)
|
|
296
197
|
|
|
297
198
|
f_drag = vmid * (k_drag * area * wp.abs(wp.dot(n, vmid)))
|
|
298
|
-
f_lift = n * (k_lift * area * (
|
|
199
|
+
f_lift = n * (k_lift * area * (wp.HALF_PI - wp.acos(wp.dot(n, vdir)))) * wp.dot(vmid, vmid)
|
|
299
200
|
|
|
300
|
-
# note reversed sign due to atomic_add below.. need to write the unary op -
|
|
301
201
|
f0 = f0 - f_drag - f_lift
|
|
302
202
|
f1 = f1 + f_drag + f_lift
|
|
303
203
|
f2 = f2 + f_drag + f_lift
|
|
@@ -363,8 +263,6 @@ def eval_triangles_contact(
|
|
|
363
263
|
x: wp.array(dtype=wp.vec3),
|
|
364
264
|
v: wp.array(dtype=wp.vec3),
|
|
365
265
|
indices: wp.array2d(dtype=int),
|
|
366
|
-
pose: wp.array(dtype=wp.mat22),
|
|
367
|
-
activation: wp.array(dtype=float),
|
|
368
266
|
materials: wp.array2d(dtype=float),
|
|
369
267
|
f: wp.array(dtype=wp.vec3),
|
|
370
268
|
):
|
|
@@ -493,7 +391,7 @@ def eval_triangles_body_contacts(
|
|
|
493
391
|
dist = wp.dot(diff, diff) # squared distance
|
|
494
392
|
n = wp.normalize(diff) # points into the object
|
|
495
393
|
c = wp.min(dist - 0.05, 0.0) # 0 unless within 0.05 of surface
|
|
496
|
-
# c = wp.leaky_min(dot(n, x0)-0.01, 0.0, 0.0)
|
|
394
|
+
# c = wp.leaky_min(wp.dot(n, x0)-0.01, 0.0, 0.0)
|
|
497
395
|
# fn = n * c * 1e6 # points towards cloth (both n and c are negative)
|
|
498
396
|
|
|
499
397
|
# wp.atomic_sub(tri_f, particle_no, fn)
|
|
@@ -503,29 +401,29 @@ def eval_triangles_body_contacts(
|
|
|
503
401
|
vtri = vp * bary[0] + vq * bary[1] + vr * bary[2] # bad approximation for centroid velocity
|
|
504
402
|
vrel = vtri - dpdt
|
|
505
403
|
|
|
506
|
-
vn = dot(n, vrel) # velocity component of body in negative normal direction
|
|
404
|
+
vn = wp.dot(n, vrel) # velocity component of body in negative normal direction
|
|
507
405
|
vt = vrel - n * vn # velocity component not in normal direction
|
|
508
406
|
|
|
509
407
|
# contact damping
|
|
510
|
-
fd =
|
|
408
|
+
fd = -wp.max(vn, 0.0) * kd * wp.step(c) # again, negative, into the ground
|
|
511
409
|
|
|
512
410
|
# # viscous friction
|
|
513
411
|
# ft = vt*kf
|
|
514
412
|
|
|
515
413
|
# Coulomb friction (box)
|
|
516
414
|
lower = mu * (fn + fd)
|
|
517
|
-
upper =
|
|
415
|
+
upper = -lower
|
|
518
416
|
|
|
519
|
-
nx = cross(n, vec3(0.0, 0.0, 1.0)) # basis vectors for tangent
|
|
520
|
-
nz = cross(n, vec3(1.0, 0.0, 0.0))
|
|
417
|
+
nx = wp.cross(n, wp.vec3(0.0, 0.0, 1.0)) # basis vectors for tangent
|
|
418
|
+
nz = wp.cross(n, wp.vec3(1.0, 0.0, 0.0))
|
|
521
419
|
|
|
522
|
-
vx = wp.clamp(dot(nx * kf, vt), lower, upper)
|
|
523
|
-
vz = wp.clamp(dot(nz * kf, vt), lower, upper)
|
|
420
|
+
vx = wp.clamp(wp.dot(nx * kf, vt), lower, upper)
|
|
421
|
+
vz = wp.clamp(wp.dot(nz * kf, vt), lower, upper)
|
|
524
422
|
|
|
525
|
-
ft = (nx * vx + nz * vz) * (
|
|
423
|
+
ft = (nx * vx + nz * vz) * (-wp.step(c)) # wp.vec3(vx, 0.0, vz)*wp.step(c)
|
|
526
424
|
|
|
527
425
|
# # Coulomb friction (smooth, but gradients are numerically unstable around |vt| = 0)
|
|
528
|
-
# #ft = wp.normalize(vt)*wp.min(kf*wp.length(vt),
|
|
426
|
+
# #ft = wp.normalize(vt)*wp.min(kf*wp.length(vt), -mu*c*ke)
|
|
529
427
|
|
|
530
428
|
f_total = n * (fn + fd) + ft
|
|
531
429
|
|
|
@@ -600,7 +498,7 @@ def eval_bending(
|
|
|
600
498
|
f_damp = kd * (wp.dot(d1, v1) + wp.dot(d2, v2) + wp.dot(d3, v3) + wp.dot(d4, v4))
|
|
601
499
|
|
|
602
500
|
# total force, proportional to edge length
|
|
603
|
-
f_total =
|
|
501
|
+
f_total = -e_length * (f_elastic + f_damp)
|
|
604
502
|
|
|
605
503
|
wp.atomic_add(f, i, d1 * f_total)
|
|
606
504
|
wp.atomic_add(f, j, d2 * f_total)
|
|
@@ -673,7 +571,7 @@ def eval_tetrahedra(
|
|
|
673
571
|
# -----------------------------
|
|
674
572
|
# Neo-Hookean (with rest stability [Smith et al 2018])
|
|
675
573
|
|
|
676
|
-
Ic = dot(col1, col1) + dot(col2, col2) + dot(col3, col3)
|
|
574
|
+
Ic = wp.dot(col1, col1) + wp.dot(col2, col2) + wp.dot(col3, col3)
|
|
677
575
|
|
|
678
576
|
# deviatoric part
|
|
679
577
|
P = F * k_mu * (1.0 - 1.0 / (Ic + 1.0)) + dFdt * k_damp
|
|
@@ -778,7 +676,7 @@ def eval_tetrahedra(
|
|
|
778
676
|
f1 = f1 + dJdx1 * f_total
|
|
779
677
|
f2 = f2 + dJdx2 * f_total
|
|
780
678
|
f3 = f3 + dJdx3 * f_total
|
|
781
|
-
f0 = (f1 + f2 + f3)
|
|
679
|
+
f0 = -(f1 + f2 + f3)
|
|
782
680
|
|
|
783
681
|
# apply forces
|
|
784
682
|
wp.atomic_sub(f, i, f0)
|
|
@@ -928,7 +826,7 @@ def eval_particle_contacts(
|
|
|
928
826
|
|
|
929
827
|
# Coulomb friction (box)
|
|
930
828
|
# lower = mu * c * ke
|
|
931
|
-
# upper =
|
|
829
|
+
# upper = -lower
|
|
932
830
|
|
|
933
831
|
# vx = wp.clamp(wp.dot(wp.vec3(kf, 0.0, 0.0), vt), lower, upper)
|
|
934
832
|
# vz = wp.clamp(wp.dot(wp.vec3(0.0, 0.0, kf), vt), lower, upper)
|
|
@@ -954,59 +852,64 @@ def eval_rigid_contacts(
|
|
|
954
852
|
body_com: wp.array(dtype=wp.vec3),
|
|
955
853
|
shape_materials: ModelShapeMaterials,
|
|
956
854
|
geo: ModelShapeGeometry,
|
|
855
|
+
shape_body: wp.array(dtype=int),
|
|
957
856
|
contact_count: wp.array(dtype=int),
|
|
958
|
-
contact_body0: wp.array(dtype=int),
|
|
959
|
-
contact_body1: wp.array(dtype=int),
|
|
960
857
|
contact_point0: wp.array(dtype=wp.vec3),
|
|
961
858
|
contact_point1: wp.array(dtype=wp.vec3),
|
|
962
859
|
contact_normal: wp.array(dtype=wp.vec3),
|
|
963
860
|
contact_shape0: wp.array(dtype=int),
|
|
964
861
|
contact_shape1: wp.array(dtype=int),
|
|
862
|
+
force_in_world_frame: bool,
|
|
965
863
|
# outputs
|
|
966
864
|
body_f: wp.array(dtype=wp.spatial_vector),
|
|
967
865
|
):
|
|
968
866
|
tid = wp.tid()
|
|
969
|
-
if contact_shape0[tid] == contact_shape1[tid]:
|
|
970
|
-
return
|
|
971
867
|
|
|
972
868
|
count = contact_count[0]
|
|
973
869
|
if tid >= count:
|
|
974
870
|
return
|
|
975
871
|
|
|
976
872
|
# retrieve contact thickness, compute average contact material properties
|
|
977
|
-
ke = 0.0 #
|
|
873
|
+
ke = 0.0 # contact normal force stiffness
|
|
978
874
|
kd = 0.0 # damping coefficient
|
|
979
|
-
kf = 0.0 # friction
|
|
980
|
-
|
|
875
|
+
kf = 0.0 # friction force stiffness
|
|
876
|
+
ka = 0.0 # adhesion distance
|
|
877
|
+
mu = 0.0 # friction coefficient
|
|
981
878
|
mat_nonzero = 0
|
|
982
879
|
thickness_a = 0.0
|
|
983
880
|
thickness_b = 0.0
|
|
984
881
|
shape_a = contact_shape0[tid]
|
|
985
882
|
shape_b = contact_shape1[tid]
|
|
883
|
+
if shape_a == shape_b:
|
|
884
|
+
return
|
|
885
|
+
body_a = -1
|
|
886
|
+
body_b = -1
|
|
986
887
|
if shape_a >= 0:
|
|
987
888
|
mat_nonzero += 1
|
|
988
889
|
ke += shape_materials.ke[shape_a]
|
|
989
890
|
kd += shape_materials.kd[shape_a]
|
|
990
891
|
kf += shape_materials.kf[shape_a]
|
|
892
|
+
ka += shape_materials.ka[shape_a]
|
|
991
893
|
mu += shape_materials.mu[shape_a]
|
|
992
894
|
thickness_a = geo.thickness[shape_a]
|
|
895
|
+
body_a = shape_body[shape_a]
|
|
993
896
|
if shape_b >= 0:
|
|
994
897
|
mat_nonzero += 1
|
|
995
898
|
ke += shape_materials.ke[shape_b]
|
|
996
899
|
kd += shape_materials.kd[shape_b]
|
|
997
900
|
kf += shape_materials.kf[shape_b]
|
|
901
|
+
ka += shape_materials.ka[shape_b]
|
|
998
902
|
mu += shape_materials.mu[shape_b]
|
|
999
903
|
thickness_b = geo.thickness[shape_b]
|
|
904
|
+
body_b = shape_body[shape_b]
|
|
1000
905
|
if mat_nonzero > 0:
|
|
1001
|
-
ke
|
|
1002
|
-
kd
|
|
1003
|
-
kf
|
|
1004
|
-
|
|
906
|
+
ke /= float(mat_nonzero)
|
|
907
|
+
kd /= float(mat_nonzero)
|
|
908
|
+
kf /= float(mat_nonzero)
|
|
909
|
+
ka /= float(mat_nonzero)
|
|
910
|
+
mu /= float(mat_nonzero)
|
|
1005
911
|
|
|
1006
|
-
|
|
1007
|
-
body_b = contact_body1[tid]
|
|
1008
|
-
|
|
1009
|
-
# body position in world space
|
|
912
|
+
# contact normal in world space
|
|
1010
913
|
n = contact_normal[tid]
|
|
1011
914
|
bx_a = contact_point0[tid]
|
|
1012
915
|
bx_b = contact_point1[tid]
|
|
@@ -1024,7 +927,7 @@ def eval_rigid_contacts(
|
|
|
1024
927
|
|
|
1025
928
|
d = wp.dot(n, bx_a - bx_b)
|
|
1026
929
|
|
|
1027
|
-
if d >=
|
|
930
|
+
if d >= ka:
|
|
1028
931
|
return
|
|
1029
932
|
|
|
1030
933
|
# compute contact point velocity
|
|
@@ -1034,13 +937,19 @@ def eval_rigid_contacts(
|
|
|
1034
937
|
body_v_s_a = body_qd[body_a]
|
|
1035
938
|
body_w_a = wp.spatial_top(body_v_s_a)
|
|
1036
939
|
body_v_a = wp.spatial_bottom(body_v_s_a)
|
|
1037
|
-
|
|
940
|
+
if force_in_world_frame:
|
|
941
|
+
bv_a = body_v_a + wp.cross(body_w_a, bx_a)
|
|
942
|
+
else:
|
|
943
|
+
bv_a = body_v_a + wp.cross(body_w_a, r_a)
|
|
1038
944
|
|
|
1039
945
|
if body_b >= 0:
|
|
1040
946
|
body_v_s_b = body_qd[body_b]
|
|
1041
947
|
body_w_b = wp.spatial_top(body_v_s_b)
|
|
1042
948
|
body_v_b = wp.spatial_bottom(body_v_s_b)
|
|
1043
|
-
|
|
949
|
+
if force_in_world_frame:
|
|
950
|
+
bv_b = body_v_b + wp.cross(body_w_b, bx_b)
|
|
951
|
+
else:
|
|
952
|
+
bv_b = body_v_b + wp.cross(body_w_b, r_b)
|
|
1044
953
|
|
|
1045
954
|
# relative velocity
|
|
1046
955
|
v = bv_a - bv_b
|
|
@@ -1062,7 +971,7 @@ def eval_rigid_contacts(
|
|
|
1062
971
|
|
|
1063
972
|
# Coulomb friction (box)
|
|
1064
973
|
# lower = mu * d * ke
|
|
1065
|
-
# upper =
|
|
974
|
+
# upper = -lower
|
|
1066
975
|
|
|
1067
976
|
# vx = wp.clamp(wp.dot(wp.vec3(kf, 0.0, 0.0), vt), lower, upper)
|
|
1068
977
|
# vz = wp.clamp(wp.dot(wp.vec3(0.0, 0.0, kf), vt), lower, upper)
|
|
@@ -1071,48 +980,65 @@ def eval_rigid_contacts(
|
|
|
1071
980
|
|
|
1072
981
|
# Coulomb friction (smooth, but gradients are numerically unstable around |vt| = 0)
|
|
1073
982
|
# ft = wp.normalize(vt)*wp.min(kf*wp.length(vt), abs(mu*d*ke))
|
|
1074
|
-
ft = wp.
|
|
983
|
+
ft = wp.vec3(0.0)
|
|
984
|
+
if d < 0.0:
|
|
985
|
+
ft = wp.normalize(vt) * wp.min(kf * wp.length(vt), -mu * (fn + fd))
|
|
1075
986
|
|
|
1076
|
-
# f_total = fn + (fd + ft)
|
|
1077
987
|
f_total = n * (fn + fd) + ft
|
|
1078
|
-
#
|
|
1079
|
-
|
|
1080
|
-
# print("apply contact force")
|
|
1081
|
-
# print(f_total)
|
|
988
|
+
# f_total = n * fn
|
|
1082
989
|
|
|
1083
990
|
if body_a >= 0:
|
|
1084
|
-
|
|
991
|
+
if force_in_world_frame:
|
|
992
|
+
wp.atomic_add(body_f, body_a, wp.spatial_vector(wp.cross(bx_a, f_total), f_total))
|
|
993
|
+
else:
|
|
994
|
+
wp.atomic_sub(body_f, body_a, wp.spatial_vector(wp.cross(r_a, f_total), f_total))
|
|
995
|
+
|
|
1085
996
|
if body_b >= 0:
|
|
1086
|
-
|
|
997
|
+
if force_in_world_frame:
|
|
998
|
+
wp.atomic_sub(body_f, body_b, wp.spatial_vector(wp.cross(bx_b, f_total), f_total))
|
|
999
|
+
else:
|
|
1000
|
+
wp.atomic_add(body_f, body_b, wp.spatial_vector(wp.cross(r_b, f_total), f_total))
|
|
1087
1001
|
|
|
1088
1002
|
|
|
1089
1003
|
@wp.func
|
|
1090
1004
|
def eval_joint_force(
|
|
1091
1005
|
q: float,
|
|
1092
1006
|
qd: float,
|
|
1093
|
-
|
|
1007
|
+
act: float,
|
|
1094
1008
|
target_ke: float,
|
|
1095
1009
|
target_kd: float,
|
|
1096
|
-
act: float,
|
|
1097
1010
|
limit_lower: float,
|
|
1098
1011
|
limit_upper: float,
|
|
1099
1012
|
limit_ke: float,
|
|
1100
1013
|
limit_kd: float,
|
|
1101
|
-
|
|
1102
|
-
):
|
|
1014
|
+
mode: wp.int32,
|
|
1015
|
+
) -> float:
|
|
1016
|
+
"""Joint force evaluation for a single degree of freedom."""
|
|
1017
|
+
|
|
1103
1018
|
limit_f = 0.0
|
|
1019
|
+
damping_f = 0.0
|
|
1020
|
+
target_f = 0.0
|
|
1021
|
+
|
|
1022
|
+
if mode == wp.sim.JOINT_MODE_FORCE:
|
|
1023
|
+
target_f = act
|
|
1024
|
+
elif mode == wp.sim.JOINT_MODE_TARGET_POSITION:
|
|
1025
|
+
target_f = target_ke * (act - q) - target_kd * qd
|
|
1026
|
+
elif mode == wp.sim.JOINT_MODE_TARGET_VELOCITY:
|
|
1027
|
+
target_f = target_ke * (act - qd)
|
|
1104
1028
|
|
|
1105
1029
|
# compute limit forces, damping only active when limit is violated
|
|
1106
1030
|
if q < limit_lower:
|
|
1107
|
-
limit_f = limit_ke * (limit_lower - q)
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1031
|
+
limit_f = limit_ke * (limit_lower - q)
|
|
1032
|
+
damping_f = -limit_kd * qd
|
|
1033
|
+
if mode == wp.sim.JOINT_MODE_TARGET_VELOCITY:
|
|
1034
|
+
target_f = 0.0 # override target force when limit is violated
|
|
1035
|
+
elif q > limit_upper:
|
|
1036
|
+
limit_f = limit_ke * (limit_upper - q)
|
|
1037
|
+
damping_f = -limit_kd * qd
|
|
1038
|
+
if mode == wp.sim.JOINT_MODE_TARGET_VELOCITY:
|
|
1039
|
+
target_f = 0.0 # override target force when limit is violated
|
|
1114
1040
|
|
|
1115
|
-
return
|
|
1041
|
+
return limit_f + damping_f + target_f
|
|
1116
1042
|
|
|
1117
1043
|
|
|
1118
1044
|
@wp.kernel
|
|
@@ -1120,7 +1046,6 @@ def eval_body_joints(
|
|
|
1120
1046
|
body_q: wp.array(dtype=wp.transform),
|
|
1121
1047
|
body_qd: wp.array(dtype=wp.spatial_vector),
|
|
1122
1048
|
body_com: wp.array(dtype=wp.vec3),
|
|
1123
|
-
joint_q_start: wp.array(dtype=int),
|
|
1124
1049
|
joint_qd_start: wp.array(dtype=int),
|
|
1125
1050
|
joint_type: wp.array(dtype=int),
|
|
1126
1051
|
joint_enabled: wp.array(dtype=int),
|
|
@@ -1131,7 +1056,7 @@ def eval_body_joints(
|
|
|
1131
1056
|
joint_axis: wp.array(dtype=wp.vec3),
|
|
1132
1057
|
joint_axis_start: wp.array(dtype=int),
|
|
1133
1058
|
joint_axis_dim: wp.array(dtype=int, ndim=2),
|
|
1134
|
-
|
|
1059
|
+
joint_axis_mode: wp.array(dtype=int),
|
|
1135
1060
|
joint_act: wp.array(dtype=float),
|
|
1136
1061
|
joint_target_ke: wp.array(dtype=float),
|
|
1137
1062
|
joint_target_kd: wp.array(dtype=float),
|
|
@@ -1181,19 +1106,12 @@ def eval_body_joints(
|
|
|
1181
1106
|
v_c = wp.spatial_bottom(twist_c) + wp.cross(w_c, r_c)
|
|
1182
1107
|
|
|
1183
1108
|
# joint properties (for 1D joints)
|
|
1184
|
-
q_start = joint_q_start[tid]
|
|
1109
|
+
# q_start = joint_q_start[tid]
|
|
1185
1110
|
qd_start = joint_qd_start[tid]
|
|
1186
1111
|
axis_start = joint_axis_start[tid]
|
|
1187
1112
|
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
target_kd = joint_target_kd[axis_start]
|
|
1191
|
-
limit_ke = joint_limit_ke[axis_start]
|
|
1192
|
-
limit_kd = joint_limit_kd[axis_start]
|
|
1193
|
-
limit_lower = joint_limit_lower[axis_start]
|
|
1194
|
-
limit_upper = joint_limit_upper[axis_start]
|
|
1195
|
-
|
|
1196
|
-
act = joint_act[qd_start]
|
|
1113
|
+
lin_axis_count = joint_axis_dim[tid, 0]
|
|
1114
|
+
ang_axis_count = joint_axis_dim[tid, 1]
|
|
1197
1115
|
|
|
1198
1116
|
x_p = wp.transform_get_translation(X_wp)
|
|
1199
1117
|
x_c = wp.transform_get_translation(X_wc)
|
|
@@ -1231,9 +1149,19 @@ def eval_body_joints(
|
|
|
1231
1149
|
# evaluate joint coordinates
|
|
1232
1150
|
q = wp.dot(x_err, axis_p)
|
|
1233
1151
|
qd = wp.dot(v_err, axis_p)
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1152
|
+
act = joint_act[axis_start]
|
|
1153
|
+
|
|
1154
|
+
f_total = axis_p * -eval_joint_force(
|
|
1155
|
+
q,
|
|
1156
|
+
qd,
|
|
1157
|
+
act,
|
|
1158
|
+
joint_target_ke[axis_start],
|
|
1159
|
+
joint_target_kd[axis_start],
|
|
1160
|
+
joint_limit_lower[axis_start],
|
|
1161
|
+
joint_limit_upper[axis_start],
|
|
1162
|
+
joint_limit_ke[axis_start],
|
|
1163
|
+
joint_limit_kd[axis_start],
|
|
1164
|
+
joint_axis_mode[axis_start],
|
|
1237
1165
|
)
|
|
1238
1166
|
|
|
1239
1167
|
# attachment dynamics
|
|
@@ -1256,9 +1184,19 @@ def eval_body_joints(
|
|
|
1256
1184
|
|
|
1257
1185
|
q = wp.acos(twist[3]) * 2.0 * wp.sign(wp.dot(axis, wp.vec3(twist[0], twist[1], twist[2])))
|
|
1258
1186
|
qd = wp.dot(w_err, axis_p)
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1187
|
+
act = joint_act[axis_start]
|
|
1188
|
+
|
|
1189
|
+
t_total = axis_p * -eval_joint_force(
|
|
1190
|
+
q,
|
|
1191
|
+
qd,
|
|
1192
|
+
act,
|
|
1193
|
+
joint_target_ke[axis_start],
|
|
1194
|
+
joint_target_kd[axis_start],
|
|
1195
|
+
joint_limit_lower[axis_start],
|
|
1196
|
+
joint_limit_upper[axis_start],
|
|
1197
|
+
joint_limit_ke[axis_start],
|
|
1198
|
+
joint_limit_kd[axis_start],
|
|
1199
|
+
joint_axis_mode[axis_start],
|
|
1262
1200
|
)
|
|
1263
1201
|
|
|
1264
1202
|
# attachment dynamics
|
|
@@ -1270,8 +1208,9 @@ def eval_body_joints(
|
|
|
1270
1208
|
if type == wp.sim.JOINT_BALL:
|
|
1271
1209
|
ang_err = wp.normalize(wp.vec3(r_err[0], r_err[1], r_err[2])) * wp.acos(r_err[3]) * 2.0
|
|
1272
1210
|
|
|
1273
|
-
#
|
|
1274
|
-
|
|
1211
|
+
# TODO joint limits
|
|
1212
|
+
# TODO expose target_kd or target_ke for ball joints
|
|
1213
|
+
# t_total += target_kd * w_err + target_ke * wp.transform_vector(X_wp, ang_err)
|
|
1275
1214
|
f_total += x_err * joint_attach_ke + v_err * joint_attach_kd
|
|
1276
1215
|
|
|
1277
1216
|
if type == wp.sim.JOINT_COMPOUND:
|
|
@@ -1288,59 +1227,55 @@ def eval_body_joints(
|
|
|
1288
1227
|
q_1 = wp.quat_from_axis_angle(axis_1, angles[1])
|
|
1289
1228
|
|
|
1290
1229
|
axis_2 = wp.quat_rotate(q_1 * q_0, wp.vec3(0.0, 0.0, 1.0))
|
|
1291
|
-
q_2 = wp.quat_from_axis_angle(axis_2, angles[2])
|
|
1230
|
+
# q_2 = wp.quat_from_axis_angle(axis_2, angles[2])
|
|
1292
1231
|
|
|
1293
|
-
q_w = q_p
|
|
1232
|
+
# q_w = q_p
|
|
1294
1233
|
|
|
1295
1234
|
axis_0 = wp.transform_vector(X_wp, axis_0)
|
|
1296
1235
|
axis_1 = wp.transform_vector(X_wp, axis_1)
|
|
1297
1236
|
axis_2 = wp.transform_vector(X_wp, axis_2)
|
|
1298
1237
|
|
|
1299
1238
|
# joint dynamics
|
|
1300
|
-
t_total = wp.vec3()
|
|
1301
1239
|
# # TODO remove wp.quat_rotate(q_w, ...)?
|
|
1302
1240
|
# t_total += eval_joint_force(angles[0], wp.dot(wp.quat_rotate(q_w, axis_0), w_err), joint_target[axis_start+0], joint_target_ke[axis_start+0],joint_target_kd[axis_start+0], joint_act[axis_start+0], joint_limit_lower[axis_start+0], joint_limit_upper[axis_start+0], joint_limit_ke[axis_start+0], joint_limit_kd[axis_start+0], wp.quat_rotate(q_w, axis_0))
|
|
1303
1241
|
# t_total += eval_joint_force(angles[1], wp.dot(wp.quat_rotate(q_w, axis_1), w_err), joint_target[axis_start+1], joint_target_ke[axis_start+1],joint_target_kd[axis_start+1], joint_act[axis_start+1], joint_limit_lower[axis_start+1], joint_limit_upper[axis_start+1], joint_limit_ke[axis_start+1], joint_limit_kd[axis_start+1], wp.quat_rotate(q_w, axis_1))
|
|
1304
1242
|
# t_total += eval_joint_force(angles[2], wp.dot(wp.quat_rotate(q_w, axis_2), w_err), joint_target[axis_start+2], joint_target_ke[axis_start+2],joint_target_kd[axis_start+2], joint_act[axis_start+2], joint_limit_lower[axis_start+2], joint_limit_upper[axis_start+2], joint_limit_ke[axis_start+2], joint_limit_kd[axis_start+2], wp.quat_rotate(q_w, axis_2))
|
|
1305
1243
|
|
|
1306
|
-
t_total += eval_joint_force(
|
|
1244
|
+
t_total += axis_0 * -eval_joint_force(
|
|
1307
1245
|
angles[0],
|
|
1308
1246
|
wp.dot(axis_0, w_err),
|
|
1309
|
-
|
|
1247
|
+
joint_act[axis_start + 0],
|
|
1310
1248
|
joint_target_ke[axis_start + 0],
|
|
1311
1249
|
joint_target_kd[axis_start + 0],
|
|
1312
|
-
joint_act[axis_start + 0],
|
|
1313
1250
|
joint_limit_lower[axis_start + 0],
|
|
1314
1251
|
joint_limit_upper[axis_start + 0],
|
|
1315
1252
|
joint_limit_ke[axis_start + 0],
|
|
1316
1253
|
joint_limit_kd[axis_start + 0],
|
|
1317
|
-
|
|
1254
|
+
joint_axis_mode[axis_start + 0],
|
|
1318
1255
|
)
|
|
1319
|
-
t_total += eval_joint_force(
|
|
1256
|
+
t_total += axis_1 * -eval_joint_force(
|
|
1320
1257
|
angles[1],
|
|
1321
1258
|
wp.dot(axis_1, w_err),
|
|
1322
|
-
|
|
1259
|
+
joint_act[axis_start + 1],
|
|
1323
1260
|
joint_target_ke[axis_start + 1],
|
|
1324
1261
|
joint_target_kd[axis_start + 1],
|
|
1325
|
-
joint_act[axis_start + 1],
|
|
1326
1262
|
joint_limit_lower[axis_start + 1],
|
|
1327
1263
|
joint_limit_upper[axis_start + 1],
|
|
1328
1264
|
joint_limit_ke[axis_start + 1],
|
|
1329
1265
|
joint_limit_kd[axis_start + 1],
|
|
1330
|
-
|
|
1266
|
+
joint_axis_mode[axis_start + 1],
|
|
1331
1267
|
)
|
|
1332
|
-
t_total += eval_joint_force(
|
|
1268
|
+
t_total += axis_2 * -eval_joint_force(
|
|
1333
1269
|
angles[2],
|
|
1334
1270
|
wp.dot(axis_2, w_err),
|
|
1335
|
-
|
|
1271
|
+
joint_act[axis_start + 2],
|
|
1336
1272
|
joint_target_ke[axis_start + 2],
|
|
1337
1273
|
joint_target_kd[axis_start + 2],
|
|
1338
|
-
joint_act[axis_start + 2],
|
|
1339
1274
|
joint_limit_lower[axis_start + 2],
|
|
1340
1275
|
joint_limit_upper[axis_start + 2],
|
|
1341
1276
|
joint_limit_ke[axis_start + 2],
|
|
1342
1277
|
joint_limit_kd[axis_start + 2],
|
|
1343
|
-
|
|
1278
|
+
joint_axis_mode[axis_start + 2],
|
|
1344
1279
|
)
|
|
1345
1280
|
|
|
1346
1281
|
f_total += x_err * joint_attach_ke + v_err * joint_attach_kd
|
|
@@ -1359,55 +1294,40 @@ def eval_body_joints(
|
|
|
1359
1294
|
q_1 = wp.quat_from_axis_angle(axis_1, angles[1])
|
|
1360
1295
|
|
|
1361
1296
|
axis_2 = wp.quat_rotate(q_1 * q_0, wp.vec3(0.0, 0.0, 1.0))
|
|
1362
|
-
q_2 = wp.quat_from_axis_angle(axis_2, angles[2])
|
|
1363
|
-
|
|
1364
|
-
q_w = q_p
|
|
1365
1297
|
|
|
1366
1298
|
axis_0 = wp.transform_vector(X_wp, axis_0)
|
|
1367
1299
|
axis_1 = wp.transform_vector(X_wp, axis_1)
|
|
1368
1300
|
axis_2 = wp.transform_vector(X_wp, axis_2)
|
|
1369
1301
|
|
|
1370
1302
|
# joint dynamics
|
|
1371
|
-
t_total = wp.vec3()
|
|
1372
|
-
|
|
1373
|
-
# free axes
|
|
1374
|
-
# # TODO remove wp.quat_rotate(q_w, ...)?
|
|
1375
|
-
# t_total += eval_joint_force(angles[0], wp.dot(wp.quat_rotate(q_w, axis_0), w_err), joint_target[axis_start+0], joint_target_ke[axis_start+0],joint_target_kd[axis_start+0], joint_act[axis_start+0], joint_limit_lower[axis_start+0], joint_limit_upper[axis_start+0], joint_limit_ke[axis_start+0], joint_limit_kd[axis_start+0], wp.quat_rotate(q_w, axis_0))
|
|
1376
|
-
# t_total += eval_joint_force(angles[1], wp.dot(wp.quat_rotate(q_w, axis_1), w_err), joint_target[axis_start+1], joint_target_ke[axis_start+1],joint_target_kd[axis_start+1], joint_act[axis_start+1], joint_limit_lower[axis_start+1], joint_limit_upper[axis_start+1], joint_limit_ke[axis_start+1], joint_limit_kd[axis_start+1], wp.quat_rotate(q_w, axis_1))
|
|
1377
1303
|
|
|
1378
|
-
|
|
1379
|
-
# t_total += eval_joint_force(angles[2], wp.dot(wp.quat_rotate(q_w, axis_2), w_err), 0.0, joint_attach_ke, joint_attach_kd*angular_damping_scale, 0.0, 0.0, 0.0, 0.0, 0.0, wp.quat_rotate(q_w, axis_2))
|
|
1380
|
-
|
|
1381
|
-
# TODO remove wp.quat_rotate(q_w, ...)?
|
|
1382
|
-
t_total += eval_joint_force(
|
|
1304
|
+
t_total += axis_0 * -eval_joint_force(
|
|
1383
1305
|
angles[0],
|
|
1384
1306
|
wp.dot(axis_0, w_err),
|
|
1385
|
-
|
|
1307
|
+
joint_act[axis_start + 0],
|
|
1386
1308
|
joint_target_ke[axis_start + 0],
|
|
1387
1309
|
joint_target_kd[axis_start + 0],
|
|
1388
|
-
joint_act[axis_start + 0],
|
|
1389
1310
|
joint_limit_lower[axis_start + 0],
|
|
1390
1311
|
joint_limit_upper[axis_start + 0],
|
|
1391
1312
|
joint_limit_ke[axis_start + 0],
|
|
1392
1313
|
joint_limit_kd[axis_start + 0],
|
|
1393
|
-
|
|
1314
|
+
joint_axis_mode[axis_start + 0],
|
|
1394
1315
|
)
|
|
1395
|
-
t_total += eval_joint_force(
|
|
1316
|
+
t_total += axis_1 * -eval_joint_force(
|
|
1396
1317
|
angles[1],
|
|
1397
1318
|
wp.dot(axis_1, w_err),
|
|
1398
|
-
|
|
1319
|
+
joint_act[axis_start + 1],
|
|
1399
1320
|
joint_target_ke[axis_start + 1],
|
|
1400
1321
|
joint_target_kd[axis_start + 1],
|
|
1401
|
-
joint_act[axis_start + 1],
|
|
1402
1322
|
joint_limit_lower[axis_start + 1],
|
|
1403
1323
|
joint_limit_upper[axis_start + 1],
|
|
1404
1324
|
joint_limit_ke[axis_start + 1],
|
|
1405
1325
|
joint_limit_kd[axis_start + 1],
|
|
1406
|
-
|
|
1326
|
+
joint_axis_mode[axis_start + 1],
|
|
1407
1327
|
)
|
|
1408
1328
|
|
|
1409
1329
|
# last axis (fixed)
|
|
1410
|
-
t_total += eval_joint_force(
|
|
1330
|
+
t_total += axis_2 * -eval_joint_force(
|
|
1411
1331
|
angles[2],
|
|
1412
1332
|
wp.dot(axis_2, w_err),
|
|
1413
1333
|
0.0,
|
|
@@ -1417,12 +1337,243 @@ def eval_body_joints(
|
|
|
1417
1337
|
0.0,
|
|
1418
1338
|
0.0,
|
|
1419
1339
|
0.0,
|
|
1420
|
-
|
|
1421
|
-
axis_2,
|
|
1340
|
+
wp.sim.JOINT_MODE_FORCE,
|
|
1422
1341
|
)
|
|
1423
1342
|
|
|
1424
1343
|
f_total += x_err * joint_attach_ke + v_err * joint_attach_kd
|
|
1425
1344
|
|
|
1345
|
+
if type == wp.sim.JOINT_D6:
|
|
1346
|
+
pos = wp.vec3(0.0)
|
|
1347
|
+
vel = wp.vec3(0.0)
|
|
1348
|
+
if lin_axis_count >= 1:
|
|
1349
|
+
axis_0 = wp.transform_vector(X_wp, joint_axis[axis_start + 0])
|
|
1350
|
+
q0 = wp.dot(x_err, axis_0)
|
|
1351
|
+
qd0 = wp.dot(v_err, axis_0)
|
|
1352
|
+
|
|
1353
|
+
f_total += axis_0 * -eval_joint_force(
|
|
1354
|
+
q0,
|
|
1355
|
+
qd0,
|
|
1356
|
+
joint_act[axis_start + 0],
|
|
1357
|
+
joint_target_ke[axis_start + 0],
|
|
1358
|
+
joint_target_kd[axis_start + 0],
|
|
1359
|
+
joint_limit_lower[axis_start + 0],
|
|
1360
|
+
joint_limit_upper[axis_start + 0],
|
|
1361
|
+
joint_limit_ke[axis_start + 0],
|
|
1362
|
+
joint_limit_kd[axis_start + 0],
|
|
1363
|
+
joint_axis_mode[axis_start + 0],
|
|
1364
|
+
)
|
|
1365
|
+
|
|
1366
|
+
pos += q0 * axis_0
|
|
1367
|
+
vel += qd0 * axis_0
|
|
1368
|
+
|
|
1369
|
+
if lin_axis_count >= 2:
|
|
1370
|
+
axis_1 = wp.transform_vector(X_wp, joint_axis[axis_start + 1])
|
|
1371
|
+
q1 = wp.dot(x_err, axis_1)
|
|
1372
|
+
qd1 = wp.dot(v_err, axis_1)
|
|
1373
|
+
|
|
1374
|
+
f_total += axis_1 * -eval_joint_force(
|
|
1375
|
+
q1,
|
|
1376
|
+
qd1,
|
|
1377
|
+
joint_act[axis_start + 1],
|
|
1378
|
+
joint_target_ke[axis_start + 1],
|
|
1379
|
+
joint_target_kd[axis_start + 1],
|
|
1380
|
+
joint_limit_lower[axis_start + 1],
|
|
1381
|
+
joint_limit_upper[axis_start + 1],
|
|
1382
|
+
joint_limit_ke[axis_start + 1],
|
|
1383
|
+
joint_limit_kd[axis_start + 1],
|
|
1384
|
+
joint_axis_mode[axis_start + 1],
|
|
1385
|
+
)
|
|
1386
|
+
|
|
1387
|
+
pos += q1 * axis_1
|
|
1388
|
+
vel += qd1 * axis_1
|
|
1389
|
+
|
|
1390
|
+
if lin_axis_count == 3:
|
|
1391
|
+
axis_2 = wp.transform_vector(X_wp, joint_axis[axis_start + 2])
|
|
1392
|
+
q2 = wp.dot(x_err, axis_2)
|
|
1393
|
+
qd2 = wp.dot(v_err, axis_2)
|
|
1394
|
+
|
|
1395
|
+
f_total += axis_2 * -eval_joint_force(
|
|
1396
|
+
q2,
|
|
1397
|
+
qd2,
|
|
1398
|
+
joint_act[axis_start + 2],
|
|
1399
|
+
joint_target_ke[axis_start + 2],
|
|
1400
|
+
joint_target_kd[axis_start + 2],
|
|
1401
|
+
joint_limit_lower[axis_start + 2],
|
|
1402
|
+
joint_limit_upper[axis_start + 2],
|
|
1403
|
+
joint_limit_ke[axis_start + 2],
|
|
1404
|
+
joint_limit_kd[axis_start + 2],
|
|
1405
|
+
joint_axis_mode[axis_start + 2],
|
|
1406
|
+
)
|
|
1407
|
+
|
|
1408
|
+
pos += q2 * axis_2
|
|
1409
|
+
vel += qd2 * axis_2
|
|
1410
|
+
|
|
1411
|
+
f_total += (x_err - pos) * joint_attach_ke + (v_err - vel) * joint_attach_kd
|
|
1412
|
+
|
|
1413
|
+
if ang_axis_count == 0:
|
|
1414
|
+
ang_err = wp.normalize(wp.vec3(r_err[0], r_err[1], r_err[2])) * wp.acos(r_err[3]) * 2.0
|
|
1415
|
+
t_total += (
|
|
1416
|
+
wp.transform_vector(X_wp, ang_err) * joint_attach_ke + w_err * joint_attach_kd * angular_damping_scale
|
|
1417
|
+
)
|
|
1418
|
+
|
|
1419
|
+
i_0 = lin_axis_count + axis_start + 0
|
|
1420
|
+
i_1 = lin_axis_count + axis_start + 1
|
|
1421
|
+
i_2 = lin_axis_count + axis_start + 2
|
|
1422
|
+
|
|
1423
|
+
if ang_axis_count == 1:
|
|
1424
|
+
axis = joint_axis[i_0]
|
|
1425
|
+
|
|
1426
|
+
axis_p = wp.transform_vector(X_wp, axis)
|
|
1427
|
+
axis_c = wp.transform_vector(X_wc, axis)
|
|
1428
|
+
|
|
1429
|
+
# swing twist decomposition
|
|
1430
|
+
twist = quat_twist(axis, r_err)
|
|
1431
|
+
|
|
1432
|
+
q = wp.acos(twist[3]) * 2.0 * wp.sign(wp.dot(axis, wp.vec3(twist[0], twist[1], twist[2])))
|
|
1433
|
+
qd = wp.dot(w_err, axis_p)
|
|
1434
|
+
|
|
1435
|
+
t_total = axis_p * -eval_joint_force(
|
|
1436
|
+
q,
|
|
1437
|
+
qd,
|
|
1438
|
+
joint_act[i_0],
|
|
1439
|
+
joint_target_ke[i_0],
|
|
1440
|
+
joint_target_kd[i_0],
|
|
1441
|
+
joint_limit_lower[i_0],
|
|
1442
|
+
joint_limit_upper[i_0],
|
|
1443
|
+
joint_limit_ke[i_0],
|
|
1444
|
+
joint_limit_kd[i_0],
|
|
1445
|
+
joint_axis_mode[i_0],
|
|
1446
|
+
)
|
|
1447
|
+
|
|
1448
|
+
# attachment dynamics
|
|
1449
|
+
swing_err = wp.cross(axis_p, axis_c)
|
|
1450
|
+
|
|
1451
|
+
t_total += swing_err * joint_attach_ke + (w_err - qd * axis_p) * joint_attach_kd * angular_damping_scale
|
|
1452
|
+
|
|
1453
|
+
if ang_axis_count == 2:
|
|
1454
|
+
q_pc = wp.quat_inverse(q_p) * q_c
|
|
1455
|
+
|
|
1456
|
+
# decompose to a compound rotation each axis
|
|
1457
|
+
angles = quat_decompose(q_pc)
|
|
1458
|
+
|
|
1459
|
+
orig_axis_0 = joint_axis[i_0]
|
|
1460
|
+
orig_axis_1 = joint_axis[i_1]
|
|
1461
|
+
orig_axis_2 = wp.cross(orig_axis_0, orig_axis_1)
|
|
1462
|
+
|
|
1463
|
+
# reconstruct rotation axes
|
|
1464
|
+
axis_0 = orig_axis_0
|
|
1465
|
+
q_0 = wp.quat_from_axis_angle(axis_0, angles[0])
|
|
1466
|
+
|
|
1467
|
+
axis_1 = wp.quat_rotate(q_0, orig_axis_1)
|
|
1468
|
+
q_1 = wp.quat_from_axis_angle(axis_1, angles[1])
|
|
1469
|
+
|
|
1470
|
+
axis_2 = wp.quat_rotate(q_1 * q_0, orig_axis_2)
|
|
1471
|
+
|
|
1472
|
+
axis_0 = wp.transform_vector(X_wp, axis_0)
|
|
1473
|
+
axis_1 = wp.transform_vector(X_wp, axis_1)
|
|
1474
|
+
axis_2 = wp.transform_vector(X_wp, axis_2)
|
|
1475
|
+
|
|
1476
|
+
# joint dynamics
|
|
1477
|
+
|
|
1478
|
+
t_total += axis_0 * -eval_joint_force(
|
|
1479
|
+
angles[0],
|
|
1480
|
+
wp.dot(axis_0, w_err),
|
|
1481
|
+
joint_act[i_0],
|
|
1482
|
+
joint_target_ke[i_0],
|
|
1483
|
+
joint_target_kd[i_0],
|
|
1484
|
+
joint_limit_lower[i_0],
|
|
1485
|
+
joint_limit_upper[i_0],
|
|
1486
|
+
joint_limit_ke[i_0],
|
|
1487
|
+
joint_limit_kd[i_0],
|
|
1488
|
+
joint_axis_mode[i_0],
|
|
1489
|
+
)
|
|
1490
|
+
t_total += axis_1 * -eval_joint_force(
|
|
1491
|
+
angles[1],
|
|
1492
|
+
wp.dot(axis_1, w_err),
|
|
1493
|
+
joint_act[i_1],
|
|
1494
|
+
joint_target_ke[i_1],
|
|
1495
|
+
joint_target_kd[i_1],
|
|
1496
|
+
joint_limit_lower[i_1],
|
|
1497
|
+
joint_limit_upper[i_1],
|
|
1498
|
+
joint_limit_ke[i_1],
|
|
1499
|
+
joint_limit_kd[i_1],
|
|
1500
|
+
joint_axis_mode[i_1],
|
|
1501
|
+
)
|
|
1502
|
+
|
|
1503
|
+
# last axis (fixed)
|
|
1504
|
+
t_total += axis_2 * -eval_joint_force(
|
|
1505
|
+
angles[2],
|
|
1506
|
+
wp.dot(axis_2, w_err),
|
|
1507
|
+
0.0,
|
|
1508
|
+
joint_attach_ke,
|
|
1509
|
+
joint_attach_kd * angular_damping_scale,
|
|
1510
|
+
0.0,
|
|
1511
|
+
0.0,
|
|
1512
|
+
0.0,
|
|
1513
|
+
0.0,
|
|
1514
|
+
wp.sim.JOINT_MODE_FORCE,
|
|
1515
|
+
)
|
|
1516
|
+
|
|
1517
|
+
if ang_axis_count == 3:
|
|
1518
|
+
q_pc = wp.quat_inverse(q_p) * q_c
|
|
1519
|
+
|
|
1520
|
+
# decompose to a compound rotation each axis
|
|
1521
|
+
angles = quat_decompose(q_pc)
|
|
1522
|
+
|
|
1523
|
+
orig_axis_0 = joint_axis[i_0]
|
|
1524
|
+
orig_axis_1 = joint_axis[i_1]
|
|
1525
|
+
orig_axis_2 = joint_axis[i_2]
|
|
1526
|
+
|
|
1527
|
+
# reconstruct rotation axes
|
|
1528
|
+
axis_0 = orig_axis_0
|
|
1529
|
+
q_0 = wp.quat_from_axis_angle(axis_0, angles[0])
|
|
1530
|
+
|
|
1531
|
+
axis_1 = wp.quat_rotate(q_0, orig_axis_1)
|
|
1532
|
+
q_1 = wp.quat_from_axis_angle(axis_1, angles[1])
|
|
1533
|
+
|
|
1534
|
+
axis_2 = wp.quat_rotate(q_1 * q_0, orig_axis_2)
|
|
1535
|
+
|
|
1536
|
+
axis_0 = wp.transform_vector(X_wp, axis_0)
|
|
1537
|
+
axis_1 = wp.transform_vector(X_wp, axis_1)
|
|
1538
|
+
axis_2 = wp.transform_vector(X_wp, axis_2)
|
|
1539
|
+
|
|
1540
|
+
t_total += axis_0 * -eval_joint_force(
|
|
1541
|
+
angles[0],
|
|
1542
|
+
wp.dot(axis_0, w_err),
|
|
1543
|
+
joint_act[i_0],
|
|
1544
|
+
joint_target_ke[i_0],
|
|
1545
|
+
joint_target_kd[i_0],
|
|
1546
|
+
joint_limit_lower[i_0],
|
|
1547
|
+
joint_limit_upper[i_0],
|
|
1548
|
+
joint_limit_ke[i_0],
|
|
1549
|
+
joint_limit_kd[i_0],
|
|
1550
|
+
joint_axis_mode[i_0],
|
|
1551
|
+
)
|
|
1552
|
+
t_total += axis_1 * -eval_joint_force(
|
|
1553
|
+
angles[1],
|
|
1554
|
+
wp.dot(axis_1, w_err),
|
|
1555
|
+
joint_act[i_1],
|
|
1556
|
+
joint_target_ke[i_1],
|
|
1557
|
+
joint_target_kd[i_1],
|
|
1558
|
+
joint_limit_lower[i_1],
|
|
1559
|
+
joint_limit_upper[i_1],
|
|
1560
|
+
joint_limit_ke[i_1],
|
|
1561
|
+
joint_limit_kd[i_1],
|
|
1562
|
+
joint_axis_mode[i_1],
|
|
1563
|
+
)
|
|
1564
|
+
t_total += axis_2 * -eval_joint_force(
|
|
1565
|
+
angles[2],
|
|
1566
|
+
wp.dot(axis_2, w_err),
|
|
1567
|
+
joint_act[i_2],
|
|
1568
|
+
joint_target_ke[i_2],
|
|
1569
|
+
joint_target_kd[i_2],
|
|
1570
|
+
joint_limit_lower[i_2],
|
|
1571
|
+
joint_limit_upper[i_2],
|
|
1572
|
+
joint_limit_ke[i_2],
|
|
1573
|
+
joint_limit_kd[i_2],
|
|
1574
|
+
joint_axis_mode[i_2],
|
|
1575
|
+
)
|
|
1576
|
+
|
|
1426
1577
|
# write forces
|
|
1427
1578
|
if c_parent >= 0:
|
|
1428
1579
|
wp.atomic_add(body_f, c_parent, wp.spatial_vector(t_total + wp.cross(r_p, f_total), f_total))
|
|
@@ -1464,8 +1615,6 @@ def compute_muscle_force(
|
|
|
1464
1615
|
wp.atomic_sub(body_f_s, link_0, wp.spatial_vector(f, wp.cross(pos_0, f)))
|
|
1465
1616
|
wp.atomic_add(body_f_s, link_1, wp.spatial_vector(f, wp.cross(pos_1, f)))
|
|
1466
1617
|
|
|
1467
|
-
return 0
|
|
1468
|
-
|
|
1469
1618
|
|
|
1470
1619
|
@wp.kernel
|
|
1471
1620
|
def eval_muscles(
|
|
@@ -1491,8 +1640,7 @@ def eval_muscles(
|
|
|
1491
1640
|
compute_muscle_force(i, body_X_s, body_v_s, body_com, muscle_links, muscle_points, activation, body_f_s)
|
|
1492
1641
|
|
|
1493
1642
|
|
|
1494
|
-
def
|
|
1495
|
-
# damped springs
|
|
1643
|
+
def eval_spring_forces(model: Model, state: State, particle_f: wp.array):
|
|
1496
1644
|
if model.spring_count:
|
|
1497
1645
|
wp.launch(
|
|
1498
1646
|
kernel=eval_springs,
|
|
@@ -1509,11 +1657,8 @@ def compute_forces(model, state, particle_f, body_f, requires_grad):
|
|
|
1509
1657
|
device=model.device,
|
|
1510
1658
|
)
|
|
1511
1659
|
|
|
1512
|
-
# particle-particle interactions
|
|
1513
|
-
if model.particle_count:
|
|
1514
|
-
eval_particle_forces(model, state, particle_f)
|
|
1515
1660
|
|
|
1516
|
-
|
|
1661
|
+
def eval_triangle_forces(model: Model, state: State, control: Control, particle_f: wp.array):
|
|
1517
1662
|
if model.tri_count:
|
|
1518
1663
|
wp.launch(
|
|
1519
1664
|
kernel=eval_triangles,
|
|
@@ -1523,15 +1668,16 @@ def compute_forces(model, state, particle_f, body_f, requires_grad):
|
|
|
1523
1668
|
state.particle_qd,
|
|
1524
1669
|
model.tri_indices,
|
|
1525
1670
|
model.tri_poses,
|
|
1526
|
-
|
|
1671
|
+
control.tri_activations,
|
|
1527
1672
|
model.tri_materials,
|
|
1528
1673
|
],
|
|
1529
1674
|
outputs=[particle_f],
|
|
1530
1675
|
device=model.device,
|
|
1531
1676
|
)
|
|
1532
1677
|
|
|
1533
|
-
|
|
1534
|
-
|
|
1678
|
+
|
|
1679
|
+
def eval_triangle_contact_forces(model: Model, state: State, particle_f: wp.array):
|
|
1680
|
+
if model.enable_tri_collisions:
|
|
1535
1681
|
wp.launch(
|
|
1536
1682
|
kernel=eval_triangles_contact,
|
|
1537
1683
|
dim=model.tri_count * model.particle_count,
|
|
@@ -1540,15 +1686,14 @@ def compute_forces(model, state, particle_f, body_f, requires_grad):
|
|
|
1540
1686
|
state.particle_q,
|
|
1541
1687
|
state.particle_qd,
|
|
1542
1688
|
model.tri_indices,
|
|
1543
|
-
model.tri_poses,
|
|
1544
|
-
model.tri_activations,
|
|
1545
1689
|
model.tri_materials,
|
|
1546
1690
|
],
|
|
1547
1691
|
outputs=[particle_f],
|
|
1548
1692
|
device=model.device,
|
|
1549
1693
|
)
|
|
1550
1694
|
|
|
1551
|
-
|
|
1695
|
+
|
|
1696
|
+
def eval_bending_forces(model: Model, state: State, particle_f: wp.array):
|
|
1552
1697
|
if model.edge_count:
|
|
1553
1698
|
wp.launch(
|
|
1554
1699
|
kernel=eval_bending,
|
|
@@ -1564,7 +1709,8 @@ def compute_forces(model, state, particle_f, body_f, requires_grad):
|
|
|
1564
1709
|
device=model.device,
|
|
1565
1710
|
)
|
|
1566
1711
|
|
|
1567
|
-
|
|
1712
|
+
|
|
1713
|
+
def eval_particle_ground_contact_forces(model: Model, state: State, particle_f: wp.array):
|
|
1568
1714
|
if model.ground and model.particle_count:
|
|
1569
1715
|
wp.launch(
|
|
1570
1716
|
kernel=eval_particle_ground_contacts,
|
|
@@ -1584,7 +1730,8 @@ def compute_forces(model, state, particle_f, body_f, requires_grad):
|
|
|
1584
1730
|
device=model.device,
|
|
1585
1731
|
)
|
|
1586
1732
|
|
|
1587
|
-
|
|
1733
|
+
|
|
1734
|
+
def eval_tetrahedral_forces(model: Model, state: State, control: Control, particle_f: wp.array):
|
|
1588
1735
|
if model.tet_count:
|
|
1589
1736
|
wp.launch(
|
|
1590
1737
|
kernel=eval_tetrahedra,
|
|
@@ -1594,13 +1741,15 @@ def compute_forces(model, state, particle_f, body_f, requires_grad):
|
|
|
1594
1741
|
state.particle_qd,
|
|
1595
1742
|
model.tet_indices,
|
|
1596
1743
|
model.tet_poses,
|
|
1597
|
-
|
|
1744
|
+
control.tet_activations,
|
|
1598
1745
|
model.tet_materials,
|
|
1599
1746
|
],
|
|
1600
1747
|
outputs=[particle_f],
|
|
1601
1748
|
device=model.device,
|
|
1602
1749
|
)
|
|
1603
1750
|
|
|
1751
|
+
|
|
1752
|
+
def eval_body_contact_forces(model: Model, state: State, particle_f: wp.array):
|
|
1604
1753
|
if model.rigid_contact_max and (
|
|
1605
1754
|
model.ground and model.shape_ground_contact_pair_count or model.shape_contact_pair_count
|
|
1606
1755
|
):
|
|
@@ -1613,19 +1762,21 @@ def compute_forces(model, state, particle_f, body_f, requires_grad):
|
|
|
1613
1762
|
model.body_com,
|
|
1614
1763
|
model.shape_materials,
|
|
1615
1764
|
model.shape_geo,
|
|
1765
|
+
model.shape_body,
|
|
1616
1766
|
model.rigid_contact_count,
|
|
1617
|
-
model.rigid_contact_body0,
|
|
1618
|
-
model.rigid_contact_body1,
|
|
1619
1767
|
model.rigid_contact_point0,
|
|
1620
1768
|
model.rigid_contact_point1,
|
|
1621
1769
|
model.rigid_contact_normal,
|
|
1622
1770
|
model.rigid_contact_shape0,
|
|
1623
1771
|
model.rigid_contact_shape1,
|
|
1772
|
+
False,
|
|
1624
1773
|
],
|
|
1625
|
-
outputs=[body_f],
|
|
1774
|
+
outputs=[state.body_f],
|
|
1626
1775
|
device=model.device,
|
|
1627
1776
|
)
|
|
1628
1777
|
|
|
1778
|
+
|
|
1779
|
+
def eval_body_joint_forces(model: Model, state: State, control: Control, body_f: wp.array):
|
|
1629
1780
|
if model.joint_count:
|
|
1630
1781
|
wp.launch(
|
|
1631
1782
|
kernel=eval_body_joints,
|
|
@@ -1634,7 +1785,6 @@ def compute_forces(model, state, particle_f, body_f, requires_grad):
|
|
|
1634
1785
|
state.body_q,
|
|
1635
1786
|
state.body_qd,
|
|
1636
1787
|
model.body_com,
|
|
1637
|
-
model.joint_q_start,
|
|
1638
1788
|
model.joint_qd_start,
|
|
1639
1789
|
model.joint_type,
|
|
1640
1790
|
model.joint_enabled,
|
|
@@ -1645,8 +1795,8 @@ def compute_forces(model, state, particle_f, body_f, requires_grad):
|
|
|
1645
1795
|
model.joint_axis,
|
|
1646
1796
|
model.joint_axis_start,
|
|
1647
1797
|
model.joint_axis_dim,
|
|
1648
|
-
model.
|
|
1649
|
-
|
|
1798
|
+
model.joint_axis_mode,
|
|
1799
|
+
control.joint_act,
|
|
1650
1800
|
model.joint_target_ke,
|
|
1651
1801
|
model.joint_target_kd,
|
|
1652
1802
|
model.joint_limit_lower,
|
|
@@ -1660,7 +1810,8 @@ def compute_forces(model, state, particle_f, body_f, requires_grad):
|
|
|
1660
1810
|
device=model.device,
|
|
1661
1811
|
)
|
|
1662
1812
|
|
|
1663
|
-
|
|
1813
|
+
|
|
1814
|
+
def eval_particle_body_contact_forces(model: Model, state: State, particle_f: wp.array, body_f: wp.array):
|
|
1664
1815
|
if model.particle_count and model.shape_count > 1:
|
|
1665
1816
|
wp.launch(
|
|
1666
1817
|
kernel=eval_particle_contacts,
|
|
@@ -1693,8 +1844,9 @@ def compute_forces(model, state, particle_f, body_f, requires_grad):
|
|
|
1693
1844
|
device=model.device,
|
|
1694
1845
|
)
|
|
1695
1846
|
|
|
1696
|
-
|
|
1697
|
-
|
|
1847
|
+
|
|
1848
|
+
def eval_muscle_forces(model: Model, state: State, control: Control, body_f: wp.array):
|
|
1849
|
+
if model.muscle_count:
|
|
1698
1850
|
wp.launch(
|
|
1699
1851
|
kernel=eval_muscles,
|
|
1700
1852
|
dim=model.muscle_count,
|
|
@@ -1706,50 +1858,50 @@ def compute_forces(model, state, particle_f, body_f, requires_grad):
|
|
|
1706
1858
|
model.muscle_params,
|
|
1707
1859
|
model.muscle_bodies,
|
|
1708
1860
|
model.muscle_points,
|
|
1709
|
-
|
|
1861
|
+
control.muscle_activations,
|
|
1710
1862
|
],
|
|
1711
1863
|
outputs=[body_f],
|
|
1712
1864
|
device=model.device,
|
|
1713
1865
|
)
|
|
1714
1866
|
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
#
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
#
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
#
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
#
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
#
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
#
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
#
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
#
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
#
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
#
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
class SemiImplicitIntegrator:
|
|
1867
|
+
|
|
1868
|
+
def compute_forces(model: Model, state: State, control: Control, particle_f: wp.array, body_f: wp.array, dt: float):
|
|
1869
|
+
# damped springs
|
|
1870
|
+
eval_spring_forces(model, state, particle_f)
|
|
1871
|
+
|
|
1872
|
+
# triangle elastic and lift/drag forces
|
|
1873
|
+
eval_triangle_forces(model, state, control, particle_f)
|
|
1874
|
+
|
|
1875
|
+
# triangle/triangle contacts
|
|
1876
|
+
eval_triangle_contact_forces(model, state, particle_f)
|
|
1877
|
+
|
|
1878
|
+
# triangle bending
|
|
1879
|
+
eval_bending_forces(model, state, particle_f)
|
|
1880
|
+
|
|
1881
|
+
# tetrahedral FEM
|
|
1882
|
+
eval_tetrahedral_forces(model, state, control, particle_f)
|
|
1883
|
+
|
|
1884
|
+
# body joints
|
|
1885
|
+
eval_body_joint_forces(model, state, control, body_f)
|
|
1886
|
+
|
|
1887
|
+
# particle-particle interactions
|
|
1888
|
+
eval_particle_forces(model, state, particle_f)
|
|
1889
|
+
|
|
1890
|
+
# particle ground contacts
|
|
1891
|
+
eval_particle_ground_contact_forces(model, state, particle_f)
|
|
1892
|
+
|
|
1893
|
+
# body contacts
|
|
1894
|
+
eval_body_contact_forces(model, state, particle_f)
|
|
1895
|
+
|
|
1896
|
+
# particle shape contact
|
|
1897
|
+
eval_particle_body_contact_forces(model, state, particle_f, body_f)
|
|
1898
|
+
|
|
1899
|
+
# muscles
|
|
1900
|
+
if False:
|
|
1901
|
+
eval_muscle_forces(model, state, control, body_f)
|
|
1902
|
+
|
|
1903
|
+
|
|
1904
|
+
class SemiImplicitIntegrator(Integrator):
|
|
1753
1905
|
"""A semi-implicit integrator using symplectic Euler
|
|
1754
1906
|
|
|
1755
1907
|
After constructing `Model` and `State` objects this time-integrator
|
|
@@ -1774,10 +1926,14 @@ class SemiImplicitIntegrator:
|
|
|
1774
1926
|
|
|
1775
1927
|
"""
|
|
1776
1928
|
|
|
1777
|
-
def __init__(self, angular_damping=0.05):
|
|
1929
|
+
def __init__(self, angular_damping: float = 0.05):
|
|
1930
|
+
"""
|
|
1931
|
+
Args:
|
|
1932
|
+
angular_damping (float, optional): Angular damping factor. Defaults to 0.05.
|
|
1933
|
+
"""
|
|
1778
1934
|
self.angular_damping = angular_damping
|
|
1779
1935
|
|
|
1780
|
-
def simulate(self, model, state_in, state_out, dt,
|
|
1936
|
+
def simulate(self, model: Model, state_in: State, state_out: State, dt: float, control: Control = None):
|
|
1781
1937
|
with wp.ScopedTimer("simulate", False):
|
|
1782
1938
|
particle_f = None
|
|
1783
1939
|
body_f = None
|
|
@@ -1788,191 +1944,13 @@ class SemiImplicitIntegrator:
|
|
|
1788
1944
|
if state_in.body_count:
|
|
1789
1945
|
body_f = state_in.body_f
|
|
1790
1946
|
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
# -------------------------------------
|
|
1794
|
-
# integrate bodies
|
|
1795
|
-
|
|
1796
|
-
if model.body_count:
|
|
1797
|
-
wp.launch(
|
|
1798
|
-
kernel=integrate_bodies,
|
|
1799
|
-
dim=model.body_count,
|
|
1800
|
-
inputs=[
|
|
1801
|
-
state_in.body_q,
|
|
1802
|
-
state_in.body_qd,
|
|
1803
|
-
state_in.body_f,
|
|
1804
|
-
model.body_com,
|
|
1805
|
-
model.body_mass,
|
|
1806
|
-
model.body_inertia,
|
|
1807
|
-
model.body_inv_mass,
|
|
1808
|
-
model.body_inv_inertia,
|
|
1809
|
-
model.gravity,
|
|
1810
|
-
self.angular_damping,
|
|
1811
|
-
dt,
|
|
1812
|
-
],
|
|
1813
|
-
outputs=[state_out.body_q, state_out.body_qd],
|
|
1814
|
-
device=model.device,
|
|
1815
|
-
)
|
|
1816
|
-
|
|
1817
|
-
# ----------------------------
|
|
1818
|
-
# integrate particles
|
|
1819
|
-
|
|
1820
|
-
if model.particle_count:
|
|
1821
|
-
wp.launch(
|
|
1822
|
-
kernel=integrate_particles,
|
|
1823
|
-
dim=model.particle_count,
|
|
1824
|
-
inputs=[
|
|
1825
|
-
state_in.particle_q,
|
|
1826
|
-
state_in.particle_qd,
|
|
1827
|
-
state_in.particle_f,
|
|
1828
|
-
model.particle_inv_mass,
|
|
1829
|
-
model.particle_flags,
|
|
1830
|
-
model.gravity,
|
|
1831
|
-
dt,
|
|
1832
|
-
model.particle_max_velocity,
|
|
1833
|
-
],
|
|
1834
|
-
outputs=[state_out.particle_q, state_out.particle_qd],
|
|
1835
|
-
device=model.device,
|
|
1836
|
-
)
|
|
1837
|
-
|
|
1838
|
-
return state_out
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
@wp.kernel
|
|
1842
|
-
def compute_particle_residual(
|
|
1843
|
-
particle_qd_0: wp.array(dtype=wp.vec3),
|
|
1844
|
-
particle_qd_1: wp.array(dtype=wp.vec3),
|
|
1845
|
-
particle_f: wp.array(dtype=wp.vec3),
|
|
1846
|
-
particle_m: wp.array(dtype=float),
|
|
1847
|
-
particle_flags: wp.array(dtype=wp.uint32),
|
|
1848
|
-
gravity: wp.vec3,
|
|
1849
|
-
dt: float,
|
|
1850
|
-
residual: wp.array(dtype=wp.vec3),
|
|
1851
|
-
):
|
|
1852
|
-
tid = wp.tid()
|
|
1853
|
-
if (particle_flags[tid] & PARTICLE_FLAG_ACTIVE) == 0:
|
|
1854
|
-
return
|
|
1855
|
-
|
|
1856
|
-
m = particle_m[tid]
|
|
1857
|
-
v1 = particle_qd_1[tid]
|
|
1858
|
-
v0 = particle_qd_0[tid]
|
|
1859
|
-
f = particle_f[tid]
|
|
1860
|
-
|
|
1861
|
-
err = wp.vec3()
|
|
1862
|
-
|
|
1863
|
-
if m > 0.0:
|
|
1864
|
-
err = (v1 - v0) * m - f * dt - gravity * dt * m
|
|
1865
|
-
|
|
1866
|
-
residual[tid] = err
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
@wp.kernel
|
|
1870
|
-
def update_particle_position(
|
|
1871
|
-
particle_q_0: wp.array(dtype=wp.vec3),
|
|
1872
|
-
particle_q_1: wp.array(dtype=wp.vec3),
|
|
1873
|
-
particle_qd_1: wp.array(dtype=wp.vec3),
|
|
1874
|
-
x: wp.array(dtype=wp.vec3),
|
|
1875
|
-
particle_flags: wp.array(dtype=wp.uint32),
|
|
1876
|
-
dt: float,
|
|
1877
|
-
):
|
|
1878
|
-
tid = wp.tid()
|
|
1879
|
-
if (particle_flags[tid] & PARTICLE_FLAG_ACTIVE) == 0:
|
|
1880
|
-
return
|
|
1881
|
-
|
|
1882
|
-
qd_1 = x[tid]
|
|
1883
|
-
|
|
1884
|
-
q_0 = particle_q_0[tid]
|
|
1885
|
-
q_1 = q_0 + qd_1 * dt
|
|
1886
|
-
|
|
1887
|
-
particle_q_1[tid] = q_1
|
|
1888
|
-
particle_qd_1[tid] = qd_1
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
def compute_residual(model, state_in, state_out, particle_f, residual, dt):
|
|
1892
|
-
wp.launch(
|
|
1893
|
-
kernel=compute_particle_residual,
|
|
1894
|
-
dim=model.particle_count,
|
|
1895
|
-
inputs=[
|
|
1896
|
-
state_in.particle_qd,
|
|
1897
|
-
state_out.particle_qd,
|
|
1898
|
-
particle_f,
|
|
1899
|
-
model.particle_mass,
|
|
1900
|
-
model.particle_flags,
|
|
1901
|
-
model.gravity,
|
|
1902
|
-
dt,
|
|
1903
|
-
residual.astype(dtype=wp.vec3),
|
|
1904
|
-
],
|
|
1905
|
-
device=model.device,
|
|
1906
|
-
)
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
def init_state(model, state_in, state_out, dt):
|
|
1910
|
-
wp.launch(
|
|
1911
|
-
kernel=integrate_particles,
|
|
1912
|
-
dim=model.particle_count,
|
|
1913
|
-
inputs=[
|
|
1914
|
-
state_in.particle_q,
|
|
1915
|
-
state_in.particle_qd,
|
|
1916
|
-
state_in.particle_f,
|
|
1917
|
-
model.particle_inv_mass,
|
|
1918
|
-
model.particle_flags,
|
|
1919
|
-
model.gravity,
|
|
1920
|
-
dt,
|
|
1921
|
-
model.particle_max_velocity,
|
|
1922
|
-
],
|
|
1923
|
-
outputs=[state_out.particle_q, state_out.particle_qd],
|
|
1924
|
-
device=model.device,
|
|
1925
|
-
)
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
# compute the final positions given output velocity (x)
|
|
1929
|
-
def update_state(model, state_in, state_out, x, dt):
|
|
1930
|
-
wp.launch(
|
|
1931
|
-
kernel=update_particle_position,
|
|
1932
|
-
dim=model.particle_count,
|
|
1933
|
-
inputs=[state_in.particle_q, state_out.particle_q, state_out.particle_qd, x, model.particle_flags, dt],
|
|
1934
|
-
device=model.device,
|
|
1935
|
-
)
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
class VariationalImplicitIntegrator:
|
|
1939
|
-
def __init__(self, model, solver="gd", alpha=0.1, max_iters=32, report=False):
|
|
1940
|
-
self.solver = solver
|
|
1941
|
-
self.alpha = alpha
|
|
1942
|
-
self.max_iters = max_iters
|
|
1943
|
-
self.report = report
|
|
1944
|
-
|
|
1945
|
-
self.opt = Optimizer(model.particle_count * 3, mode=self.solver, device=model.device)
|
|
1946
|
-
|
|
1947
|
-
# allocate temporary space for evaluating particle forces
|
|
1948
|
-
self.particle_f = wp.zeros(model.particle_count, dtype=wp.vec3, device=model.device)
|
|
1949
|
-
|
|
1950
|
-
def simulate(self, model, state_in, state_out, dt, requires_grad=False):
|
|
1951
|
-
if state_in is state_out:
|
|
1952
|
-
raise RuntimeError("Implicit integrators require state objects to not alias each other")
|
|
1953
|
-
|
|
1954
|
-
with wp.ScopedTimer("simulate", False):
|
|
1955
|
-
# alloc particle force buffer
|
|
1956
|
-
if model.particle_count:
|
|
1957
|
-
|
|
1958
|
-
def residual_func(x, dfdx):
|
|
1959
|
-
self.particle_f.zero_()
|
|
1960
|
-
|
|
1961
|
-
update_state(model, state_in, state_out, x.astype(wp.vec3), dt)
|
|
1962
|
-
compute_forces(model, state_out, self.particle_f, None)
|
|
1963
|
-
compute_residual(model, state_in, state_out, self.particle_f, dfdx, dt)
|
|
1964
|
-
|
|
1965
|
-
# initialize output state using the input velocity to create 'predicted state'
|
|
1966
|
-
init_state(model, state_in, state_out, dt)
|
|
1947
|
+
if control is None:
|
|
1948
|
+
control = model.control(clone_variables=False)
|
|
1967
1949
|
|
|
1968
|
-
|
|
1969
|
-
x = state_out.particle_qd.astype(dtype=float)
|
|
1950
|
+
compute_forces(model, state_in, control, particle_f, body_f, dt)
|
|
1970
1951
|
|
|
1971
|
-
|
|
1972
|
-
x=x, grad_func=residual_func, max_iters=self.max_iters, alpha=self.alpha, report=self.report
|
|
1973
|
-
)
|
|
1952
|
+
self.integrate_bodies(model, state_in, state_out, dt, self.angular_damping)
|
|
1974
1953
|
|
|
1975
|
-
|
|
1976
|
-
update_state(model, state_in, state_out, x.astype(wp.vec3), dt)
|
|
1954
|
+
self.integrate_particles(model, state_in, state_out, dt)
|
|
1977
1955
|
|
|
1978
1956
|
return state_out
|