warp-lang 0.15.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 +1 -0
- warp/codegen.py +7 -3
- warp/config.py +2 -1
- warp/constants.py +3 -0
- warp/context.py +44 -21
- 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/core/example_dem.py +6 -6
- warp/examples/core/example_fluid.py +3 -3
- warp/examples/core/example_graph_capture.py +3 -6
- warp/examples/optim/example_bounce.py +9 -8
- warp/examples/optim/example_cloth_throw.py +12 -8
- warp/examples/optim/example_diffray.py +10 -12
- warp/examples/optim/example_drone.py +31 -14
- warp/examples/optim/example_spring_cage.py +10 -15
- warp/examples/optim/example_trajectory.py +7 -24
- warp/examples/sim/example_cartpole.py +3 -9
- warp/examples/sim/example_cloth.py +10 -10
- warp/examples/sim/example_granular.py +3 -3
- warp/examples/sim/example_granular_collision_sdf.py +9 -4
- warp/examples/sim/example_jacobian_ik.py +0 -10
- warp/examples/sim/example_particle_chain.py +4 -4
- warp/examples/sim/example_quadruped.py +15 -11
- warp/examples/sim/example_rigid_chain.py +13 -8
- warp/examples/sim/example_rigid_contact.py +4 -4
- warp/examples/sim/example_rigid_force.py +7 -7
- warp/examples/sim/example_rigid_soft_contact.py +4 -4
- warp/examples/sim/example_soft_body.py +3 -3
- warp/jax.py +45 -0
- warp/jax_experimental.py +339 -0
- warp/render/render_opengl.py +188 -95
- warp/render/render_usd.py +34 -10
- 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 +741 -487
- warp/sim/particles.py +2 -1
- warp/sim/render.py +18 -2
- warp/sim/utils.py +222 -11
- warp/stubs.py +1 -0
- warp/tape.py +6 -9
- warp/tests/test_examples.py +87 -20
- warp/tests/test_grad_customs.py +122 -0
- warp/tests/test_jax.py +254 -0
- warp/tests/test_options.py +13 -53
- warp/tests/test_quat.py +23 -0
- warp/tests/test_snippet.py +2 -0
- warp/tests/test_utils.py +31 -26
- warp/tests/test_verify_fp.py +65 -0
- warp/tests/unittest_suites.py +4 -0
- warp/utils.py +50 -1
- {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/METADATA +1 -1
- {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/RECORD +73 -64
- warp/examples/env/__init__.py +0 -0
- warp/examples/env/env_ant.py +0 -61
- warp/examples/env/env_cartpole.py +0 -63
- warp/examples/env/env_humanoid.py +0 -65
- warp/examples/env/env_usd.py +0 -97
- warp/examples/env/environment.py +0 -526
- warp/sim/optimizer.py +0 -138
- {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/LICENSE.md +0 -0
- {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/WHEEL +0 -0
- {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/top_level.txt +0 -0
warp/sim/collide.py
CHANGED
|
@@ -222,6 +222,13 @@ def closest_point_box(upper: wp.vec3, point: wp.vec3):
|
|
|
222
222
|
|
|
223
223
|
@wp.func
|
|
224
224
|
def get_box_vertex(point_id: int, upper: wp.vec3):
|
|
225
|
+
# box vertex numbering:
|
|
226
|
+
# 6---7
|
|
227
|
+
# |\ |\ y
|
|
228
|
+
# | 2-+-3 |
|
|
229
|
+
# 4-+-5 | z \|
|
|
230
|
+
# \| \| o---x
|
|
231
|
+
# 0---1
|
|
225
232
|
# get the vertex of the box given its ID (0-7)
|
|
226
233
|
sign_x = float(point_id % 2) * 2.0 - 1.0
|
|
227
234
|
sign_y = float((point_id // 2) % 2) * 2.0 - 1.0
|
|
@@ -474,6 +481,39 @@ def volume_grad(volume: wp.uint64, p: wp.vec3):
|
|
|
474
481
|
return wp.normalize(wp.vec3(dx, dy, dz))
|
|
475
482
|
|
|
476
483
|
|
|
484
|
+
@wp.func
|
|
485
|
+
def counter_increment(counter: wp.array(dtype=int), counter_index: int, tids: wp.array(dtype=int), tid: int):
|
|
486
|
+
# increment counter, remember which thread received which counter value
|
|
487
|
+
next_count = wp.atomic_add(counter, counter_index, 1)
|
|
488
|
+
tids[tid] = next_count
|
|
489
|
+
return next_count
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
@wp.func_replay(counter_increment)
|
|
493
|
+
def replay_counter_increment(counter: wp.array(dtype=int), counter_index: int, tids: wp.array(dtype=int), tid: int):
|
|
494
|
+
return tids[tid]
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
@wp.func
|
|
498
|
+
def limited_counter_increment(
|
|
499
|
+
counter: wp.array(dtype=int), counter_index: int, tids: wp.array(dtype=int), tid: int, index_limit: int
|
|
500
|
+
):
|
|
501
|
+
# increment counter but only if it is smaller than index_limit, remember which thread received which counter value
|
|
502
|
+
next_count = wp.atomic_add(counter, counter_index, 1)
|
|
503
|
+
if next_count < index_limit or index_limit < 0:
|
|
504
|
+
tids[tid] = next_count
|
|
505
|
+
return next_count
|
|
506
|
+
tids[tid] = -1
|
|
507
|
+
return -1
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
@wp.func_replay(limited_counter_increment)
|
|
511
|
+
def replay_limited_counter_increment(
|
|
512
|
+
counter: wp.array(dtype=int), counter_index: int, tids: wp.array(dtype=int), tid: int, index_limit: int
|
|
513
|
+
):
|
|
514
|
+
return tids[tid]
|
|
515
|
+
|
|
516
|
+
|
|
477
517
|
@wp.kernel
|
|
478
518
|
def create_soft_contacts(
|
|
479
519
|
particle_x: wp.array(dtype=wp.vec3),
|
|
@@ -485,6 +525,7 @@ def create_soft_contacts(
|
|
|
485
525
|
geo: ModelShapeGeometry,
|
|
486
526
|
margin: float,
|
|
487
527
|
soft_contact_max: int,
|
|
528
|
+
shape_count: int,
|
|
488
529
|
# outputs
|
|
489
530
|
soft_contact_count: wp.array(dtype=int),
|
|
490
531
|
soft_contact_particle: wp.array(dtype=int),
|
|
@@ -492,8 +533,10 @@ def create_soft_contacts(
|
|
|
492
533
|
soft_contact_body_pos: wp.array(dtype=wp.vec3),
|
|
493
534
|
soft_contact_body_vel: wp.array(dtype=wp.vec3),
|
|
494
535
|
soft_contact_normal: wp.array(dtype=wp.vec3),
|
|
536
|
+
soft_contact_tids: wp.array(dtype=int),
|
|
495
537
|
):
|
|
496
|
-
|
|
538
|
+
tid = wp.tid()
|
|
539
|
+
particle_index, shape_index = tid // shape_count, tid % shape_count
|
|
497
540
|
if (particle_flags[particle_index] & PARTICLE_FLAG_ACTIVE) == 0:
|
|
498
541
|
return
|
|
499
542
|
|
|
@@ -551,8 +594,9 @@ def create_soft_contacts(
|
|
|
551
594
|
face_v = float(0.0)
|
|
552
595
|
sign = float(0.0)
|
|
553
596
|
|
|
597
|
+
min_scale = wp.min(geo_scale)
|
|
554
598
|
if wp.mesh_query_point_sign_normal(
|
|
555
|
-
mesh, wp.cw_div(x_local, geo_scale), margin + radius, sign, face_index, face_u, face_v
|
|
599
|
+
mesh, wp.cw_div(x_local, geo_scale), margin + radius / min_scale, sign, face_index, face_u, face_v
|
|
556
600
|
):
|
|
557
601
|
shape_p = wp.mesh_eval_position(mesh, face_index, face_u, face_v)
|
|
558
602
|
shape_v = wp.mesh_eval_velocity(mesh, face_index, face_u, face_v)
|
|
@@ -561,24 +605,24 @@ def create_soft_contacts(
|
|
|
561
605
|
shape_v = wp.cw_mul(shape_v, geo_scale)
|
|
562
606
|
|
|
563
607
|
delta = x_local - shape_p
|
|
564
|
-
|
|
608
|
+
|
|
565
609
|
d = wp.length(delta) * sign
|
|
566
610
|
n = wp.normalize(delta) * sign
|
|
567
611
|
v = shape_v
|
|
568
|
-
|
|
612
|
+
|
|
569
613
|
if geo_type == wp.sim.GEO_SDF:
|
|
570
614
|
volume = geo.source[shape_index]
|
|
571
615
|
xpred_local = wp.volume_world_to_index(volume, wp.cw_div(x_local, geo_scale))
|
|
572
616
|
nn = wp.vec3(0.0, 0.0, 0.0)
|
|
573
617
|
d = wp.volume_sample_grad_f(volume, xpred_local, wp.Volume.LINEAR, nn)
|
|
574
|
-
n = wp.normalize(nn)
|
|
618
|
+
n = wp.normalize(nn)
|
|
575
619
|
|
|
576
620
|
if geo_type == wp.sim.GEO_PLANE:
|
|
577
621
|
d = plane_sdf(geo_scale[0], geo_scale[1], x_local)
|
|
578
622
|
n = wp.vec3(0.0, 1.0, 0.0)
|
|
579
623
|
|
|
580
624
|
if d < margin + radius:
|
|
581
|
-
index =
|
|
625
|
+
index = counter_increment(soft_contact_count, 0, soft_contact_tids, tid)
|
|
582
626
|
|
|
583
627
|
if index < soft_contact_max:
|
|
584
628
|
# compute contact point in body local space
|
|
@@ -594,10 +638,11 @@ def create_soft_contacts(
|
|
|
594
638
|
soft_contact_normal[index] = world_normal
|
|
595
639
|
|
|
596
640
|
|
|
597
|
-
@wp.kernel
|
|
641
|
+
@wp.kernel(enable_backward=False)
|
|
598
642
|
def count_contact_points(
|
|
599
643
|
contact_pairs: wp.array(dtype=int, ndim=2),
|
|
600
644
|
geo: ModelShapeGeometry,
|
|
645
|
+
mesh_contact_max: int,
|
|
601
646
|
# outputs
|
|
602
647
|
contact_count: wp.array(dtype=int),
|
|
603
648
|
):
|
|
@@ -606,9 +651,11 @@ def count_contact_points(
|
|
|
606
651
|
shape_b = contact_pairs[tid, 1]
|
|
607
652
|
|
|
608
653
|
if shape_b == -1:
|
|
654
|
+
actual_shape_a = shape_a
|
|
609
655
|
actual_type_a = geo.type[shape_a]
|
|
610
656
|
# ground plane
|
|
611
657
|
actual_type_b = wp.sim.GEO_PLANE
|
|
658
|
+
actual_shape_b = -1
|
|
612
659
|
else:
|
|
613
660
|
type_a = geo.type[shape_a]
|
|
614
661
|
type_b = geo.type[shape_b]
|
|
@@ -626,85 +673,118 @@ def count_contact_points(
|
|
|
626
673
|
|
|
627
674
|
# determine how many contact points need to be evaluated
|
|
628
675
|
num_contacts = 0
|
|
676
|
+
num_actual_contacts = 0
|
|
629
677
|
if actual_type_a == wp.sim.GEO_SPHERE:
|
|
630
678
|
num_contacts = 1
|
|
679
|
+
num_actual_contacts = 1
|
|
631
680
|
elif actual_type_a == wp.sim.GEO_CAPSULE:
|
|
632
681
|
if actual_type_b == wp.sim.GEO_PLANE:
|
|
633
682
|
if geo.scale[actual_shape_b][0] == 0.0 and geo.scale[actual_shape_b][1] == 0.0:
|
|
634
683
|
num_contacts = 2 # vertex-based collision for infinite plane
|
|
684
|
+
num_actual_contacts = 2
|
|
635
685
|
else:
|
|
636
686
|
num_contacts = 2 + 4 # vertex-based collision + plane edges
|
|
687
|
+
num_actual_contacts = 2 + 4
|
|
637
688
|
elif actual_type_b == wp.sim.GEO_MESH:
|
|
638
689
|
num_contacts_a = 2
|
|
639
690
|
mesh_b = wp.mesh_get(geo.source[actual_shape_b])
|
|
640
691
|
num_contacts_b = mesh_b.points.shape[0]
|
|
641
692
|
num_contacts = num_contacts_a + num_contacts_b
|
|
693
|
+
if mesh_contact_max > 0:
|
|
694
|
+
num_contacts_b = wp.min(mesh_contact_max, num_contacts_b)
|
|
695
|
+
num_actual_contacts = num_contacts_a + num_contacts_b
|
|
642
696
|
else:
|
|
643
697
|
num_contacts = 2
|
|
698
|
+
num_actual_contacts = 2
|
|
644
699
|
elif actual_type_a == wp.sim.GEO_BOX:
|
|
645
700
|
if actual_type_b == wp.sim.GEO_BOX:
|
|
646
701
|
num_contacts = 24
|
|
702
|
+
num_actual_contacts = 24
|
|
647
703
|
elif actual_type_b == wp.sim.GEO_MESH:
|
|
648
704
|
num_contacts_a = 8
|
|
649
705
|
mesh_b = wp.mesh_get(geo.source[actual_shape_b])
|
|
650
706
|
num_contacts_b = mesh_b.points.shape[0]
|
|
651
707
|
num_contacts = num_contacts_a + num_contacts_b
|
|
708
|
+
if mesh_contact_max > 0:
|
|
709
|
+
num_contacts_b = wp.min(mesh_contact_max, num_contacts_b)
|
|
710
|
+
num_actual_contacts = num_contacts_a + num_contacts_b
|
|
652
711
|
elif actual_type_b == wp.sim.GEO_PLANE:
|
|
653
712
|
if geo.scale[actual_shape_b][0] == 0.0 and geo.scale[actual_shape_b][1] == 0.0:
|
|
654
713
|
num_contacts = 8 # vertex-based collision
|
|
714
|
+
num_actual_contacts = 8
|
|
655
715
|
else:
|
|
656
716
|
num_contacts = 8 + 4 # vertex-based collision + plane edges
|
|
717
|
+
num_actual_contacts = 8 + 4
|
|
657
718
|
else:
|
|
658
719
|
num_contacts = 8
|
|
659
720
|
elif actual_type_a == wp.sim.GEO_MESH:
|
|
660
721
|
mesh_a = wp.mesh_get(geo.source[actual_shape_a])
|
|
661
722
|
num_contacts_a = mesh_a.points.shape[0]
|
|
723
|
+
if mesh_contact_max > 0:
|
|
724
|
+
num_contacts_a = wp.min(mesh_contact_max, num_contacts_a)
|
|
662
725
|
if actual_type_b == wp.sim.GEO_MESH:
|
|
663
726
|
mesh_b = wp.mesh_get(geo.source[actual_shape_b])
|
|
664
727
|
num_contacts_b = mesh_b.points.shape[0]
|
|
728
|
+
num_contacts = num_contacts_a + num_contacts_b
|
|
729
|
+
if mesh_contact_max > 0:
|
|
730
|
+
num_contacts_b = wp.min(mesh_contact_max, num_contacts_b)
|
|
665
731
|
else:
|
|
666
732
|
num_contacts_b = 0
|
|
667
733
|
num_contacts = num_contacts_a + num_contacts_b
|
|
734
|
+
num_actual_contacts = num_contacts_a + num_contacts_b
|
|
668
735
|
elif actual_type_a == wp.sim.GEO_PLANE:
|
|
669
736
|
return # no plane-plane contacts
|
|
670
737
|
else:
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
738
|
+
wp.printf(
|
|
739
|
+
"count_contact_points: unsupported geometry type combination %d and %d\n", actual_type_a, actual_type_b
|
|
740
|
+
)
|
|
674
741
|
|
|
675
742
|
wp.atomic_add(contact_count, 0, num_contacts)
|
|
743
|
+
wp.atomic_add(contact_count, 1, num_actual_contacts)
|
|
676
744
|
|
|
677
745
|
|
|
678
|
-
@wp.kernel
|
|
746
|
+
@wp.kernel(enable_backward=False)
|
|
679
747
|
def broadphase_collision_pairs(
|
|
680
748
|
contact_pairs: wp.array(dtype=int, ndim=2),
|
|
681
749
|
body_q: wp.array(dtype=wp.transform),
|
|
682
750
|
shape_X_bs: wp.array(dtype=wp.transform),
|
|
683
751
|
shape_body: wp.array(dtype=int),
|
|
752
|
+
body_mass: wp.array(dtype=float),
|
|
753
|
+
num_shapes: int,
|
|
684
754
|
geo: ModelShapeGeometry,
|
|
685
755
|
collision_radius: wp.array(dtype=float),
|
|
686
756
|
rigid_contact_max: int,
|
|
687
757
|
rigid_contact_margin: float,
|
|
758
|
+
mesh_contact_max: int,
|
|
759
|
+
iterate_mesh_vertices: bool,
|
|
688
760
|
# outputs
|
|
689
761
|
contact_count: wp.array(dtype=int),
|
|
690
762
|
contact_shape0: wp.array(dtype=int),
|
|
691
763
|
contact_shape1: wp.array(dtype=int),
|
|
692
764
|
contact_point_id: wp.array(dtype=int),
|
|
765
|
+
contact_point_limit: wp.array(dtype=int),
|
|
693
766
|
):
|
|
694
767
|
tid = wp.tid()
|
|
695
768
|
shape_a = contact_pairs[tid, 0]
|
|
696
769
|
shape_b = contact_pairs[tid, 1]
|
|
697
770
|
|
|
771
|
+
mass_a = 0.0
|
|
772
|
+
mass_b = 0.0
|
|
698
773
|
rigid_a = shape_body[shape_a]
|
|
699
774
|
if rigid_a == -1:
|
|
700
775
|
X_ws_a = shape_X_bs[shape_a]
|
|
701
776
|
else:
|
|
702
777
|
X_ws_a = wp.transform_multiply(body_q[rigid_a], shape_X_bs[shape_a])
|
|
778
|
+
mass_a = body_mass[rigid_a]
|
|
703
779
|
rigid_b = shape_body[shape_b]
|
|
704
780
|
if rigid_b == -1:
|
|
705
781
|
X_ws_b = shape_X_bs[shape_b]
|
|
706
782
|
else:
|
|
707
783
|
X_ws_b = wp.transform_multiply(body_q[rigid_b], shape_X_bs[shape_b])
|
|
784
|
+
mass_b = body_mass[rigid_b]
|
|
785
|
+
if mass_a == 0.0 and mass_b == 0.0:
|
|
786
|
+
# skip if both bodies are static
|
|
787
|
+
return
|
|
708
788
|
|
|
709
789
|
type_a = geo.type[shape_a]
|
|
710
790
|
type_b = geo.type[shape_b]
|
|
@@ -743,6 +823,9 @@ def broadphase_collision_pairs(
|
|
|
743
823
|
if d > r_a + r_b + rigid_contact_margin:
|
|
744
824
|
return
|
|
745
825
|
|
|
826
|
+
pair_index_ab = actual_shape_a * num_shapes + actual_shape_b
|
|
827
|
+
pair_index_ba = actual_shape_b * num_shapes + actual_shape_a
|
|
828
|
+
|
|
746
829
|
# determine how many contact points need to be evaluated
|
|
747
830
|
num_contacts = 0
|
|
748
831
|
if actual_type_a == wp.sim.GEO_SPHERE:
|
|
@@ -756,7 +839,10 @@ def broadphase_collision_pairs(
|
|
|
756
839
|
elif actual_type_b == wp.sim.GEO_MESH:
|
|
757
840
|
num_contacts_a = 2
|
|
758
841
|
mesh_b = wp.mesh_get(geo.source[actual_shape_b])
|
|
759
|
-
|
|
842
|
+
if iterate_mesh_vertices:
|
|
843
|
+
num_contacts_b = mesh_b.points.shape[0]
|
|
844
|
+
else:
|
|
845
|
+
num_contacts_b = 0
|
|
760
846
|
num_contacts = num_contacts_a + num_contacts_b
|
|
761
847
|
index = wp.atomic_add(contact_count, 0, num_contacts)
|
|
762
848
|
if index + num_contacts - 1 >= rigid_contact_max:
|
|
@@ -772,6 +858,10 @@ def broadphase_collision_pairs(
|
|
|
772
858
|
contact_shape0[index + num_contacts_a + i] = actual_shape_b
|
|
773
859
|
contact_shape1[index + num_contacts_a + i] = actual_shape_a
|
|
774
860
|
contact_point_id[index + num_contacts_a + i] = i
|
|
861
|
+
contact_point_limit[pair_index_ab] = 2
|
|
862
|
+
if mesh_contact_max > 0:
|
|
863
|
+
num_contacts_b = wp.min(mesh_contact_max, num_contacts_b)
|
|
864
|
+
contact_point_limit[pair_index_ba] = num_contacts_b
|
|
775
865
|
return
|
|
776
866
|
else:
|
|
777
867
|
num_contacts = 2
|
|
@@ -786,16 +876,21 @@ def broadphase_collision_pairs(
|
|
|
786
876
|
contact_shape0[index + i] = shape_a
|
|
787
877
|
contact_shape1[index + i] = shape_b
|
|
788
878
|
contact_point_id[index + i] = i
|
|
879
|
+
contact_point_limit[pair_index_ab] = 12
|
|
789
880
|
# allocate contact points from box B against A
|
|
790
881
|
for i in range(12):
|
|
791
882
|
contact_shape0[index + 12 + i] = shape_b
|
|
792
883
|
contact_shape1[index + 12 + i] = shape_a
|
|
793
884
|
contact_point_id[index + 12 + i] = i
|
|
885
|
+
contact_point_limit[pair_index_ba] = 12
|
|
794
886
|
return
|
|
795
887
|
elif actual_type_b == wp.sim.GEO_MESH:
|
|
796
888
|
num_contacts_a = 8
|
|
797
889
|
mesh_b = wp.mesh_get(geo.source[actual_shape_b])
|
|
798
|
-
|
|
890
|
+
if iterate_mesh_vertices:
|
|
891
|
+
num_contacts_b = mesh_b.points.shape[0]
|
|
892
|
+
else:
|
|
893
|
+
num_contacts_b = 0
|
|
799
894
|
num_contacts = num_contacts_a + num_contacts_b
|
|
800
895
|
index = wp.atomic_add(contact_count, 0, num_contacts)
|
|
801
896
|
if index + num_contacts - 1 >= rigid_contact_max:
|
|
@@ -811,6 +906,11 @@ def broadphase_collision_pairs(
|
|
|
811
906
|
contact_shape0[index + num_contacts_a + i] = actual_shape_b
|
|
812
907
|
contact_shape1[index + num_contacts_a + i] = actual_shape_a
|
|
813
908
|
contact_point_id[index + num_contacts_a + i] = i
|
|
909
|
+
|
|
910
|
+
contact_point_limit[pair_index_ab] = num_contacts_a
|
|
911
|
+
if mesh_contact_max > 0:
|
|
912
|
+
num_contacts_b = wp.min(mesh_contact_max, num_contacts_b)
|
|
913
|
+
contact_point_limit[pair_index_ba] = num_contacts_b
|
|
814
914
|
return
|
|
815
915
|
elif actual_type_b == wp.sim.GEO_PLANE:
|
|
816
916
|
if geo.scale[actual_shape_b][0] == 0.0 and geo.scale[actual_shape_b][1] == 0.0:
|
|
@@ -845,6 +945,12 @@ def broadphase_collision_pairs(
|
|
|
845
945
|
contact_shape0[index + num_contacts_a + i] = actual_shape_b
|
|
846
946
|
contact_shape1[index + num_contacts_a + i] = actual_shape_a
|
|
847
947
|
contact_point_id[index + num_contacts_a + i] = i
|
|
948
|
+
|
|
949
|
+
if mesh_contact_max > 0:
|
|
950
|
+
num_contacts_a = wp.min(mesh_contact_max, num_contacts_a)
|
|
951
|
+
num_contacts_b = wp.min(mesh_contact_max, num_contacts_b)
|
|
952
|
+
contact_point_limit[pair_index_ab] = num_contacts_a
|
|
953
|
+
contact_point_limit[pair_index_ba] = num_contacts_b
|
|
848
954
|
return
|
|
849
955
|
elif actual_type_a == wp.sim.GEO_PLANE:
|
|
850
956
|
return # no plane-plane contacts
|
|
@@ -858,9 +964,12 @@ def broadphase_collision_pairs(
|
|
|
858
964
|
return
|
|
859
965
|
# allocate contact points
|
|
860
966
|
for i in range(num_contacts):
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
967
|
+
cp_index = index + i
|
|
968
|
+
contact_shape0[cp_index] = actual_shape_a
|
|
969
|
+
contact_shape1[cp_index] = actual_shape_b
|
|
970
|
+
contact_point_id[cp_index] = i
|
|
971
|
+
contact_point_limit[pair_index_ab] = num_contacts
|
|
972
|
+
contact_point_limit[pair_index_ba] = 0
|
|
864
973
|
|
|
865
974
|
|
|
866
975
|
@wp.kernel
|
|
@@ -870,31 +979,37 @@ def handle_contact_pairs(
|
|
|
870
979
|
shape_body: wp.array(dtype=int),
|
|
871
980
|
geo: ModelShapeGeometry,
|
|
872
981
|
rigid_contact_margin: float,
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
982
|
+
contact_broad_shape0: wp.array(dtype=int),
|
|
983
|
+
contact_broad_shape1: wp.array(dtype=int),
|
|
984
|
+
num_shapes: int,
|
|
876
985
|
contact_point_id: wp.array(dtype=int),
|
|
877
|
-
|
|
986
|
+
contact_point_limit: wp.array(dtype=int),
|
|
878
987
|
edge_sdf_iter: int,
|
|
879
988
|
# outputs
|
|
880
|
-
|
|
881
|
-
|
|
989
|
+
contact_count: wp.array(dtype=int),
|
|
990
|
+
contact_shape0: wp.array(dtype=int),
|
|
991
|
+
contact_shape1: wp.array(dtype=int),
|
|
882
992
|
contact_point0: wp.array(dtype=wp.vec3),
|
|
883
993
|
contact_point1: wp.array(dtype=wp.vec3),
|
|
884
994
|
contact_offset0: wp.array(dtype=wp.vec3),
|
|
885
995
|
contact_offset1: wp.array(dtype=wp.vec3),
|
|
886
996
|
contact_normal: wp.array(dtype=wp.vec3),
|
|
887
997
|
contact_thickness: wp.array(dtype=float),
|
|
998
|
+
contact_pairwise_counter: wp.array(dtype=int),
|
|
999
|
+
contact_tids: wp.array(dtype=int),
|
|
888
1000
|
):
|
|
889
1001
|
tid = wp.tid()
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
shape_a = contact_shape0[tid]
|
|
893
|
-
shape_b = contact_shape1[tid]
|
|
1002
|
+
shape_a = contact_broad_shape0[tid]
|
|
1003
|
+
shape_b = contact_broad_shape1[tid]
|
|
894
1004
|
if shape_a == shape_b:
|
|
895
1005
|
return
|
|
896
1006
|
|
|
897
1007
|
point_id = contact_point_id[tid]
|
|
1008
|
+
pair_index = shape_a * num_shapes + shape_b
|
|
1009
|
+
contact_limit = contact_point_limit[pair_index]
|
|
1010
|
+
if contact_pairwise_counter[pair_index] >= contact_limit:
|
|
1011
|
+
# reached limit of contact points per contact pair
|
|
1012
|
+
return
|
|
898
1013
|
|
|
899
1014
|
rigid_a = shape_body[shape_a]
|
|
900
1015
|
X_wb_a = wp.transform_identity()
|
|
@@ -924,12 +1039,9 @@ def handle_contact_pairs(
|
|
|
924
1039
|
thickness_b = geo.thickness[shape_b]
|
|
925
1040
|
# is_solid_b = geo.is_solid[shape_b]
|
|
926
1041
|
|
|
927
|
-
# fill in contact rigid body ids
|
|
928
|
-
contact_body0[tid] = rigid_a
|
|
929
|
-
contact_body1[tid] = rigid_b
|
|
930
|
-
|
|
931
1042
|
distance = 1.0e6
|
|
932
1043
|
u = float(0.0)
|
|
1044
|
+
thickness = thickness_a + thickness_b
|
|
933
1045
|
|
|
934
1046
|
if geo_type_a == wp.sim.GEO_SPHERE:
|
|
935
1047
|
p_a_world = wp.transform_get_translation(X_ws_a)
|
|
@@ -953,7 +1065,7 @@ def handle_contact_pairs(
|
|
|
953
1065
|
face_u = float(0.0)
|
|
954
1066
|
face_v = float(0.0)
|
|
955
1067
|
sign = float(0.0)
|
|
956
|
-
max_dist = (
|
|
1068
|
+
max_dist = (thickness + rigid_contact_margin) / min_scale_b
|
|
957
1069
|
res = wp.mesh_query_point_sign_normal(
|
|
958
1070
|
mesh_b, wp.cw_div(query_b_local, geo_scale_b), max_dist, sign, face_index, face_u, face_v
|
|
959
1071
|
)
|
|
@@ -962,8 +1074,6 @@ def handle_contact_pairs(
|
|
|
962
1074
|
shape_p = wp.cw_mul(shape_p, geo_scale_b)
|
|
963
1075
|
p_b_world = wp.transform_point(X_ws_b, shape_p)
|
|
964
1076
|
else:
|
|
965
|
-
contact_shape0[tid] = -1
|
|
966
|
-
contact_shape1[tid] = -1
|
|
967
1077
|
return
|
|
968
1078
|
elif geo_type_b == wp.sim.GEO_PLANE:
|
|
969
1079
|
p_b_body = closest_point_plane(geo_scale_b[0], geo_scale_b[1], wp.transform_point(X_sw_b, p_a_world))
|
|
@@ -1034,15 +1144,11 @@ def handle_contact_pairs(
|
|
|
1034
1144
|
if plane_width > 0.0 and plane_length > 0.0:
|
|
1035
1145
|
if wp.abs(query_b[0]) > plane_width or wp.abs(query_b[2]) > plane_length:
|
|
1036
1146
|
# skip, we will evaluate the plane edge contact with the box later
|
|
1037
|
-
contact_shape0[tid] = -1
|
|
1038
|
-
contact_shape1[tid] = -1
|
|
1039
1147
|
return
|
|
1040
1148
|
# check whether the COM is above the plane
|
|
1041
1149
|
# sign = wp.sign(wp.dot(wp.transform_get_translation(X_ws_a) - p_b_world, normal))
|
|
1042
1150
|
# if sign < 0.0:
|
|
1043
1151
|
# # the entire box is most likely below the plane
|
|
1044
|
-
# contact_shape0[tid] = -1
|
|
1045
|
-
# contact_shape1[tid] = -1
|
|
1046
1152
|
# return
|
|
1047
1153
|
# the contact point is within plane boundaries
|
|
1048
1154
|
distance = wp.dot(diff, normal)
|
|
@@ -1064,8 +1170,6 @@ def handle_contact_pairs(
|
|
|
1064
1170
|
query_b = wp.transform_point(X_sw_b, p_a_world)
|
|
1065
1171
|
if wp.abs(query_b[0]) > plane_width or wp.abs(query_b[2]) > plane_length:
|
|
1066
1172
|
# ensure that the closest point is actually inside the plane
|
|
1067
|
-
contact_shape0[tid] = -1
|
|
1068
|
-
contact_shape1[tid] = -1
|
|
1069
1173
|
return
|
|
1070
1174
|
diff = p_a_world - p_b_world
|
|
1071
1175
|
com_a = wp.transform_get_translation(X_ws_a)
|
|
@@ -1111,7 +1215,7 @@ def handle_contact_pairs(
|
|
|
1111
1215
|
edge0_b = wp.transform_point(X_sw_b, edge0_world)
|
|
1112
1216
|
edge1_b = wp.transform_point(X_sw_b, edge1_world)
|
|
1113
1217
|
max_iter = edge_sdf_iter
|
|
1114
|
-
max_dist = (rigid_contact_margin +
|
|
1218
|
+
max_dist = (rigid_contact_margin + thickness) / min_scale_b
|
|
1115
1219
|
mesh_b = geo.source[shape_b]
|
|
1116
1220
|
u = closest_edge_coordinate_mesh(
|
|
1117
1221
|
mesh_b, wp.cw_div(edge0_b, geo_scale_b), wp.cw_div(edge1_b, geo_scale_b), max_iter, max_dist
|
|
@@ -1127,7 +1231,6 @@ def handle_contact_pairs(
|
|
|
1127
1231
|
res = wp.mesh_query_point_sign_normal(
|
|
1128
1232
|
mesh_b, wp.cw_div(query_b_local, geo_scale_b), max_dist, sign, face_index, face_u, face_v
|
|
1129
1233
|
)
|
|
1130
|
-
|
|
1131
1234
|
if res:
|
|
1132
1235
|
shape_p = wp.mesh_eval_position(mesh_b, face_index, face_u, face_v)
|
|
1133
1236
|
shape_p = wp.cw_mul(shape_p, geo_scale_b)
|
|
@@ -1138,8 +1241,6 @@ def handle_contact_pairs(
|
|
|
1138
1241
|
normal = wp.normalize(diff)
|
|
1139
1242
|
distance = wp.dot(diff, normal)
|
|
1140
1243
|
else:
|
|
1141
|
-
contact_shape0[tid] = -1
|
|
1142
|
-
contact_shape1[tid] = -1
|
|
1143
1244
|
return
|
|
1144
1245
|
|
|
1145
1246
|
elif geo_type_a == wp.sim.GEO_MESH and geo_type_b == wp.sim.GEO_CAPSULE:
|
|
@@ -1219,7 +1320,7 @@ def handle_contact_pairs(
|
|
|
1219
1320
|
p_a_world = wp.transform_point(X_ws_a, query_a)
|
|
1220
1321
|
query_b_local = wp.transform_point(X_sw_b, p_a_world)
|
|
1221
1322
|
mesh_b = geo.source[shape_b]
|
|
1222
|
-
max_dist = (rigid_contact_margin +
|
|
1323
|
+
max_dist = (rigid_contact_margin + thickness) / min_scale_b
|
|
1223
1324
|
face_index = int(0)
|
|
1224
1325
|
face_u = float(0.0)
|
|
1225
1326
|
face_v = float(0.0)
|
|
@@ -1237,8 +1338,6 @@ def handle_contact_pairs(
|
|
|
1237
1338
|
normal = wp.normalize(diff_b) * sign
|
|
1238
1339
|
distance = wp.dot(diff_b, normal)
|
|
1239
1340
|
else:
|
|
1240
|
-
contact_shape0[tid] = -1
|
|
1241
|
-
contact_shape1[tid] = -1
|
|
1242
1341
|
return
|
|
1243
1342
|
|
|
1244
1343
|
elif geo_type_a == wp.sim.GEO_MESH and geo_type_b == wp.sim.GEO_MESH:
|
|
@@ -1255,7 +1354,7 @@ def handle_contact_pairs(
|
|
|
1255
1354
|
face_v = float(0.0)
|
|
1256
1355
|
sign = float(0.0)
|
|
1257
1356
|
min_scale = min(min_scale_a, min_scale_b)
|
|
1258
|
-
max_dist = (rigid_contact_margin +
|
|
1357
|
+
max_dist = (rigid_contact_margin + thickness) / min_scale
|
|
1259
1358
|
|
|
1260
1359
|
res = wp.mesh_query_point_sign_normal(
|
|
1261
1360
|
mesh_b, wp.cw_div(query_b_local, geo_scale_b), max_dist, sign, face_index, face_u, face_v
|
|
@@ -1270,8 +1369,6 @@ def handle_contact_pairs(
|
|
|
1270
1369
|
normal = wp.normalize(diff_b) * sign
|
|
1271
1370
|
distance = wp.dot(diff_b, normal)
|
|
1272
1371
|
else:
|
|
1273
|
-
contact_shape0[tid] = -1
|
|
1274
|
-
contact_shape1[tid] = -1
|
|
1275
1372
|
return
|
|
1276
1373
|
|
|
1277
1374
|
elif geo_type_a == wp.sim.GEO_MESH and geo_type_b == wp.sim.GEO_PLANE:
|
|
@@ -1283,8 +1380,6 @@ def handle_contact_pairs(
|
|
|
1283
1380
|
p_b_body = closest_point_plane(geo_scale_b[0], geo_scale_b[1], query_b)
|
|
1284
1381
|
p_b_world = wp.transform_point(X_ws_b, p_b_body)
|
|
1285
1382
|
diff = p_a_world - p_b_world
|
|
1286
|
-
normal = wp.transform_vector(X_ws_b, wp.vec3(0.0, 1.0, 0.0))
|
|
1287
|
-
distance = wp.length(diff)
|
|
1288
1383
|
|
|
1289
1384
|
# if the plane is infinite or the point is within the plane we fix the normal to prevent intersections
|
|
1290
1385
|
if (
|
|
@@ -1294,36 +1389,41 @@ def handle_contact_pairs(
|
|
|
1294
1389
|
and wp.abs(query_b[2]) < geo_scale_b[1]
|
|
1295
1390
|
):
|
|
1296
1391
|
normal = wp.transform_vector(X_ws_b, wp.vec3(0.0, 1.0, 0.0))
|
|
1392
|
+
distance = wp.dot(diff, normal)
|
|
1297
1393
|
else:
|
|
1298
1394
|
normal = wp.normalize(diff)
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
contact_shape1[tid] = -1
|
|
1304
|
-
return
|
|
1395
|
+
distance = wp.dot(diff, normal)
|
|
1396
|
+
# ignore extreme penetrations (e.g. when mesh is below the plane)
|
|
1397
|
+
if distance < -rigid_contact_margin:
|
|
1398
|
+
return
|
|
1305
1399
|
|
|
1306
1400
|
else:
|
|
1307
1401
|
print("Unsupported geometry pair in collision handling")
|
|
1308
1402
|
return
|
|
1309
1403
|
|
|
1310
|
-
thickness = thickness_a + thickness_b
|
|
1311
1404
|
d = distance - thickness
|
|
1312
1405
|
if d < rigid_contact_margin:
|
|
1406
|
+
pair_contact_id = limited_counter_increment(
|
|
1407
|
+
contact_pairwise_counter, pair_index, contact_tids, tid, contact_limit
|
|
1408
|
+
)
|
|
1409
|
+
if pair_contact_id == -1:
|
|
1410
|
+
# wp.printf("Reached contact point limit %d >= %d for shape pair %d and %d (pair_index: %d)\n",
|
|
1411
|
+
# contact_pairwise_counter[pair_index], contact_limit, shape_a, shape_b, pair_index)
|
|
1412
|
+
# reached contact point limit
|
|
1413
|
+
return
|
|
1414
|
+
index = limited_counter_increment(contact_count, 0, contact_tids, tid, -1)
|
|
1415
|
+
contact_shape0[index] = shape_a
|
|
1416
|
+
contact_shape1[index] = shape_b
|
|
1313
1417
|
# transform from world into body frame (so the contact point includes the shape transform)
|
|
1314
|
-
contact_point0[
|
|
1315
|
-
contact_point1[
|
|
1316
|
-
contact_offset0[
|
|
1317
|
-
contact_offset1[
|
|
1318
|
-
contact_normal[
|
|
1319
|
-
contact_thickness[
|
|
1320
|
-
# wp.printf("distance: %f\tnormal: %.3f %.3f %.3f\tp_a_world: %.3f %.3f %.3f\tp_b_world: %.3f %.3f %.3f\n", distance, normal[0], normal[1], normal[2], p_a_world[0], p_a_world[1], p_a_world[2], p_b_world[0], p_b_world[1], p_b_world[2])
|
|
1321
|
-
else:
|
|
1322
|
-
contact_shape0[tid] = -1
|
|
1323
|
-
contact_shape1[tid] = -1
|
|
1418
|
+
contact_point0[index] = wp.transform_point(X_bw_a, p_a_world)
|
|
1419
|
+
contact_point1[index] = wp.transform_point(X_bw_b, p_b_world)
|
|
1420
|
+
contact_offset0[index] = wp.transform_vector(X_bw_a, -thickness_a * normal)
|
|
1421
|
+
contact_offset1[index] = wp.transform_vector(X_bw_b, thickness_b * normal)
|
|
1422
|
+
contact_normal[index] = normal
|
|
1423
|
+
contact_thickness[index] = thickness
|
|
1324
1424
|
|
|
1325
1425
|
|
|
1326
|
-
def collide(model, state, edge_sdf_iter: int = 10):
|
|
1426
|
+
def collide(model, state, edge_sdf_iter: int = 10, iterate_mesh_vertices: bool = True, requires_grad: bool = None):
|
|
1327
1427
|
"""
|
|
1328
1428
|
Generates contact points for the particles and rigid bodies in the model,
|
|
1329
1429
|
to be used in the contact dynamics kernel of the integrator.
|
|
@@ -1332,114 +1432,159 @@ def collide(model, state, edge_sdf_iter: int = 10):
|
|
|
1332
1432
|
model: the model to be simulated
|
|
1333
1433
|
state: the state of the model
|
|
1334
1434
|
edge_sdf_iter: number of search iterations for finding closest contact points between edges and SDF
|
|
1435
|
+
iterate_mesh_vertices: whether to iterate over all vertices of a mesh for contact generation (used for capsule/box <> mesh collision)
|
|
1436
|
+
requires_grad: whether to duplicate contact arrays for gradient computation (if None uses model.requires_grad)
|
|
1335
1437
|
"""
|
|
1336
1438
|
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
model.
|
|
1347
|
-
model.
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
model.
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1439
|
+
if requires_grad is None:
|
|
1440
|
+
requires_grad = model.requires_grad
|
|
1441
|
+
|
|
1442
|
+
with wp.ScopedTimer("collide", False):
|
|
1443
|
+
|
|
1444
|
+
# generate soft contacts for particles and shapes except ground plane (last shape)
|
|
1445
|
+
if model.particle_count and model.shape_count > 1:
|
|
1446
|
+
if requires_grad:
|
|
1447
|
+
model.soft_contact_body_pos = wp.clone(model.soft_contact_body_pos)
|
|
1448
|
+
model.soft_contact_body_vel = wp.clone(model.soft_contact_body_vel)
|
|
1449
|
+
model.soft_contact_normal = wp.clone(model.soft_contact_normal)
|
|
1450
|
+
# clear old count
|
|
1451
|
+
model.soft_contact_count.zero_()
|
|
1452
|
+
wp.launch(
|
|
1453
|
+
kernel=create_soft_contacts,
|
|
1454
|
+
dim=model.particle_count * (model.shape_count - 1),
|
|
1455
|
+
inputs=[
|
|
1456
|
+
state.particle_q,
|
|
1457
|
+
model.particle_radius,
|
|
1458
|
+
model.particle_flags,
|
|
1459
|
+
state.body_q,
|
|
1460
|
+
model.shape_transform,
|
|
1461
|
+
model.shape_body,
|
|
1462
|
+
model.shape_geo,
|
|
1463
|
+
model.soft_contact_margin,
|
|
1464
|
+
model.soft_contact_max,
|
|
1465
|
+
model.shape_count - 1,
|
|
1466
|
+
],
|
|
1467
|
+
outputs=[
|
|
1468
|
+
model.soft_contact_count,
|
|
1469
|
+
model.soft_contact_particle,
|
|
1470
|
+
model.soft_contact_shape,
|
|
1471
|
+
model.soft_contact_body_pos,
|
|
1472
|
+
model.soft_contact_body_vel,
|
|
1473
|
+
model.soft_contact_normal,
|
|
1474
|
+
model.soft_contact_tids,
|
|
1475
|
+
],
|
|
1476
|
+
device=model.device,
|
|
1477
|
+
)
|
|
1365
1478
|
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
model.
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1479
|
+
if model.shape_contact_pair_count or model.ground and model.shape_ground_contact_pair_count:
|
|
1480
|
+
# clear old count
|
|
1481
|
+
model.rigid_contact_count.zero_()
|
|
1482
|
+
|
|
1483
|
+
model.rigid_contact_broad_shape0.fill_(-1)
|
|
1484
|
+
model.rigid_contact_broad_shape1.fill_(-1)
|
|
1485
|
+
|
|
1486
|
+
if model.shape_contact_pair_count:
|
|
1487
|
+
wp.launch(
|
|
1488
|
+
kernel=broadphase_collision_pairs,
|
|
1489
|
+
dim=model.shape_contact_pair_count,
|
|
1490
|
+
inputs=[
|
|
1491
|
+
model.shape_contact_pairs,
|
|
1492
|
+
state.body_q,
|
|
1493
|
+
model.shape_transform,
|
|
1494
|
+
model.shape_body,
|
|
1495
|
+
model.body_mass,
|
|
1496
|
+
model.shape_count,
|
|
1497
|
+
model.shape_geo,
|
|
1498
|
+
model.shape_collision_radius,
|
|
1499
|
+
model.rigid_contact_max,
|
|
1500
|
+
model.rigid_contact_margin,
|
|
1501
|
+
model.rigid_mesh_contact_max,
|
|
1502
|
+
iterate_mesh_vertices,
|
|
1503
|
+
],
|
|
1504
|
+
outputs=[
|
|
1505
|
+
model.rigid_contact_count,
|
|
1506
|
+
model.rigid_contact_broad_shape0,
|
|
1507
|
+
model.rigid_contact_broad_shape1,
|
|
1508
|
+
model.rigid_contact_point_id,
|
|
1509
|
+
model.rigid_contact_point_limit,
|
|
1510
|
+
],
|
|
1511
|
+
device=model.device,
|
|
1512
|
+
record_tape=False,
|
|
1513
|
+
)
|
|
1392
1514
|
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1515
|
+
if model.ground and model.shape_ground_contact_pair_count:
|
|
1516
|
+
wp.launch(
|
|
1517
|
+
kernel=broadphase_collision_pairs,
|
|
1518
|
+
dim=model.shape_ground_contact_pair_count,
|
|
1519
|
+
inputs=[
|
|
1520
|
+
model.shape_ground_contact_pairs,
|
|
1521
|
+
state.body_q,
|
|
1522
|
+
model.shape_transform,
|
|
1523
|
+
model.shape_body,
|
|
1524
|
+
model.body_mass,
|
|
1525
|
+
model.shape_count,
|
|
1526
|
+
model.shape_geo,
|
|
1527
|
+
model.shape_collision_radius,
|
|
1528
|
+
model.rigid_contact_max,
|
|
1529
|
+
model.rigid_contact_margin,
|
|
1530
|
+
model.rigid_mesh_contact_max,
|
|
1531
|
+
iterate_mesh_vertices,
|
|
1532
|
+
],
|
|
1533
|
+
outputs=[
|
|
1534
|
+
model.rigid_contact_count,
|
|
1535
|
+
model.rigid_contact_broad_shape0,
|
|
1536
|
+
model.rigid_contact_broad_shape1,
|
|
1537
|
+
model.rigid_contact_point_id,
|
|
1538
|
+
model.rigid_contact_point_limit,
|
|
1539
|
+
],
|
|
1540
|
+
device=model.device,
|
|
1541
|
+
record_tape=False,
|
|
1542
|
+
)
|
|
1416
1543
|
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
model.
|
|
1427
|
-
model.
|
|
1428
|
-
model.
|
|
1429
|
-
model.
|
|
1430
|
-
model.
|
|
1431
|
-
model.
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
model.
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1544
|
+
if model.shape_contact_pair_count or model.ground and model.shape_ground_contact_pair_count:
|
|
1545
|
+
|
|
1546
|
+
model.rigid_contact_count.zero_()
|
|
1547
|
+
model.rigid_contact_pairwise_counter.zero_()
|
|
1548
|
+
model.rigid_contact_tids.zero_()
|
|
1549
|
+
model.rigid_contact_shape0.fill_(-1)
|
|
1550
|
+
model.rigid_contact_shape1.fill_(-1)
|
|
1551
|
+
|
|
1552
|
+
if requires_grad:
|
|
1553
|
+
model.rigid_contact_point0 = wp.clone(model.rigid_contact_point0)
|
|
1554
|
+
model.rigid_contact_point1 = wp.clone(model.rigid_contact_point1)
|
|
1555
|
+
model.rigid_contact_offset0 = wp.clone(model.rigid_contact_offset0)
|
|
1556
|
+
model.rigid_contact_offset1 = wp.clone(model.rigid_contact_offset1)
|
|
1557
|
+
model.rigid_contact_normal = wp.clone(model.rigid_contact_normal)
|
|
1558
|
+
model.rigid_contact_thickness = wp.clone(model.rigid_contact_thickness)
|
|
1559
|
+
|
|
1560
|
+
wp.launch(
|
|
1561
|
+
kernel=handle_contact_pairs,
|
|
1562
|
+
dim=model.rigid_contact_max,
|
|
1563
|
+
inputs=[
|
|
1564
|
+
state.body_q,
|
|
1565
|
+
model.shape_transform,
|
|
1566
|
+
model.shape_body,
|
|
1567
|
+
model.shape_geo,
|
|
1568
|
+
model.rigid_contact_margin,
|
|
1569
|
+
model.rigid_contact_broad_shape0,
|
|
1570
|
+
model.rigid_contact_broad_shape1,
|
|
1571
|
+
model.shape_count,
|
|
1572
|
+
model.rigid_contact_point_id,
|
|
1573
|
+
model.rigid_contact_point_limit,
|
|
1574
|
+
edge_sdf_iter,
|
|
1575
|
+
],
|
|
1576
|
+
outputs=[
|
|
1577
|
+
model.rigid_contact_count,
|
|
1578
|
+
model.rigid_contact_shape0,
|
|
1579
|
+
model.rigid_contact_shape1,
|
|
1580
|
+
model.rigid_contact_point0,
|
|
1581
|
+
model.rigid_contact_point1,
|
|
1582
|
+
model.rigid_contact_offset0,
|
|
1583
|
+
model.rigid_contact_offset1,
|
|
1584
|
+
model.rigid_contact_normal,
|
|
1585
|
+
model.rigid_contact_thickness,
|
|
1586
|
+
model.rigid_contact_pairwise_counter,
|
|
1587
|
+
model.rigid_contact_tids,
|
|
1588
|
+
],
|
|
1589
|
+
device=model.device,
|
|
1590
|
+
)
|