@@ -288,6 +288,7 @@ static constexpr char kQuat[] = R"(
288
288
<body name="query">
289
289
<joint type="ball"/>
290
290
<geom size="1"/>
291
+ <site name="query" pos=".1 .2 .3"/>
291
292
</body>
292
293
</worldbody>
293
294
<keyframe>
@@ -315,6 +316,7 @@ static constexpr char kFreeBall[] = R"(
315
316
<body name="query" pos="0 .2 0">
316
317
<joint type="slide" axis="1 1 1"/>
317
318
<geom size=".05"/>
319
+ <site name="query" pos=".1 .2 .3"/>
318
320
</body>
319
321
</body>
320
322
</body>
@@ -350,6 +352,7 @@ static constexpr char kQuatlessPendulum[] = R"(
350
352
<body name="query" pos="0 .1 0">
351
353
<joint axis="1 0 0"/>
352
354
<geom type="capsule" size="0.02" fromto="0 0 0 0 .1 0"/>
355
+ <site name="query" pos=".1 0 0"/>
353
356
</body>
354
357
</body>
355
358
</body>
@@ -373,6 +376,7 @@ static constexpr char kTelescope[] = R"(
373
376
<body pos=".1 .02 0" name="query">
374
377
<joint type="slide" axis="1 0 0"/>
375
378
<geom type="capsule" size="0.02" fromto="0 0 0 .1 0 0"/>
379
+ <site name="query" pos=".1 0 0"/>
376
380
</body>
377
381
</body>
378
382
</body>
@@ -384,12 +388,27 @@ static constexpr char kTelescope[] = R"(
384
388
</mujoco>
385
389
)" ;
386
390
391
+ static constexpr char kHinge [] = R"(
392
+ <mujoco>
393
+ <worldbody>
394
+ <body name="query">
395
+ <joint name="link1" axis="0 1 0"/>
396
+ <geom type="capsule" size=".02" fromto="0 0 0 0 0 -1"/>
397
+ <site name="query" pos="0 0 -1"/>
398
+ </body>
399
+ </worldbody>
400
+
401
+ <keyframe>
402
+ <key qpos="1" qvel="1"/>
403
+ </keyframe>
404
+ </mujoco>
405
+ )" ;
406
+
387
407
// compare mj_jacDot with finite-differenced mj_jac
388
408
TEST_F (JacobianTest, JacDot) {
389
- for (auto xml : {kQuat , kFreeBall , kQuatlessPendulum , kTelescope }) {
409
+ for (auto xml : {kHinge , kQuat , kTelescope , kFreeBall , kQuatlessPendulum }) {
390
410
mjModel* model = LoadModelFromString (xml);
391
411
int nv = model->nv ;
392
- mjtNum point[3 ] = {.01 , .02 , .03 };
393
412
mjData* data = mj_makeData (model);
394
413
395
414
// load keyframe if present, step for a bit
@@ -407,34 +426,43 @@ TEST_F(JacobianTest, JacDot) {
407
426
int bodyid = mj_name2id (model, mjOBJ_BODY, " query" );
408
427
EXPECT_GT (bodyid, 0 );
409
428
429
+ // get site position
430
+ int siteid = mj_name2id (model, mjOBJ_SITE, " query" );
431
+ EXPECT_GT (siteid, -1 );
432
+ mjtNum point[3 ];
433
+ mju_copy3 (point, data->site_xpos +3 *siteid);
434
+
410
435
// jac, jac_dot
411
- mj_markStack (data);
412
- mjtNum* jac = mj_stackAllocNum (data, 6 *nv);
413
- mj_jac (model, data, jac, jac+3 *nv, point, bodyid);
414
- mjtNum* jac_dot = mj_stackAllocNum (data, 6 *nv);
415
- mj_jacDot (model, data, jac_dot, jac_dot+3 *nv, point, bodyid);
436
+ vector<mjtNum> jacp (3 *nv);
437
+ vector<mjtNum> jacr (3 *nv);
438
+ mj_jac (model, data, jacp.data (), jacr.data (), point, bodyid);
439
+ vector<mjtNum> jacp_dot (3 *nv);
440
+ vector<mjtNum> jacr_dot (3 *nv);
441
+ mj_jacDot (model, data, jacp_dot.data (), jacr_dot.data (), point, bodyid);
416
442
417
443
// jac_h: jacobian after integrating qpos with a timestep of h
418
444
mjtNum h = 1e-7 ;
419
445
mj_integratePos (model, data->qpos , data->qvel , h);
420
446
mj_kinematics (model, data);
421
447
mj_comPos (model, data);
422
- mjtNum* jac_h = mj_stackAllocNum (data, 6 *nv);;
423
- mj_jac (model, data, jac_h, jac_h+3 *nv, point, bodyid);
448
+ vector<mjtNum> jacp_h (3 *nv);
449
+ vector<mjtNum> jacr_h (3 *nv);
450
+ mju_copy3 (point, data->site_xpos +3 *siteid); // get updated site position
451
+ mj_jac (model, data, jacp_h.data (), jacr_h.data (), point, bodyid);
424
452
425
453
// jac_dot_h finite-difference approximation
426
- mjtNum* jac_dot_h = mj_stackAllocNum (data, 6 *nv);;
427
- mju_sub (jac_dot_h, jac_h, jac, 6 *nv);
428
- mju_scl (jac_dot_h, jac_dot_h, 1 /h, 6 *nv);
454
+ vector<mjtNum> jacp_dot_h (3 *nv);
455
+ mju_sub (jacp_dot_h.data (), jacp_h.data (), jacp.data (), 3 *nv);
456
+ mju_scl (jacp_dot_h.data (), jacp_dot_h.data (), 1 /h, 3 *nv);
457
+ vector<mjtNum> jacr_dot_h (3 *nv);
458
+ mju_sub (jacr_dot_h.data (), jacr_h.data (), jacr.data (), 3 *nv);
459
+ mju_scl (jacr_dot_h.data (), jacr_dot_h.data (), 1 /h, 3 *nv);
429
460
430
461
// compare finite-differenced and analytic
431
462
mjtNum tol = 1e-5 ;
432
- for (int j=0 ; j < 6 ; j++) {
433
- EXPECT_THAT (AsVector (jac_dot_h + j*nv, nv),
434
- Pointwise (DoubleNear (tol), AsVector (jac_dot + j*nv, nv)));
435
- }
463
+ EXPECT_THAT (jacp_dot, Pointwise (DoubleNear (tol), jacp_dot_h));
464
+ EXPECT_THAT (jacr_dot, Pointwise (DoubleNear (tol), jacr_dot_h));
436
465
437
- mj_freeStack (data);
438
466
mj_deleteData (data);
439
467
mj_deleteModel (model);
440
468
}
@@ -654,19 +682,19 @@ TEST_F(SupportTest, GetSetStateStepEqual) {
654
682
int size = mj_stateSize (model, spec);
655
683
656
684
// save the initial state and step
657
- std:: vector<mjtNum> state0a (size);
685
+ vector<mjtNum> state0a (size);
658
686
mj_getState (model, data, state0a.data (), spec);
659
687
660
688
// get the initial state, expect equality
661
- std:: vector<mjtNum> state0b (size);
689
+ vector<mjtNum> state0b (size);
662
690
mj_getState (model, data, state0b.data (), spec);
663
691
EXPECT_EQ (state0a, state0b);
664
692
665
693
// take one step
666
694
mj_step (model, data);
667
695
668
696
// save the resulting state
669
- std:: vector<mjtNum> state1a (size);
697
+ vector<mjtNum> state1a (size);
670
698
mj_getState (model, data, state1a.data (), spec);
671
699
672
700
// expect the state to be different after stepping
@@ -675,7 +703,7 @@ TEST_F(SupportTest, GetSetStateStepEqual) {
675
703
// reset to the saved state, step again, get the resulting state
676
704
mj_setState (model, data, state0a.data (), spec);
677
705
mj_step (model, data);
678
- std:: vector<mjtNum> state1b (size);
706
+ vector<mjtNum> state1b (size);
679
707
mj_getState (model, data, state1b.data (), spec);
680
708
681
709
// expect the state to be the same after re-stepping
@@ -701,13 +729,13 @@ TEST_F(InertiaTest, DenseSameAsSparse) {
701
729
}
702
730
703
731
// dense zero matrix
704
- std:: vector<mjtNum> dst_sparse (nv * nv, 0.0 );
732
+ vector<mjtNum> dst_sparse (nv * nv, 0.0 );
705
733
706
734
// sparse zero matrix
707
- std:: vector<mjtNum> dst_dense (nv * nv, 0.0 );
708
- std:: vector<int > rownnz (nv, nv);
709
- std:: vector<int > rowadr (nv, 0 );
710
- std:: vector<int > colind (nv * nv, 0 );
735
+ vector<mjtNum> dst_dense (nv * nv, 0.0 );
736
+ vector<int > rownnz (nv, nv);
737
+ vector<int > rowadr (nv, 0 );
738
+ vector<int > colind (nv * nv, 0 );
711
739
712
740
// set sparse structure
713
741
for (int i = 0 ; i < nv; i++) {
@@ -902,44 +930,44 @@ TEST_F(SupportTest, GeomDistance) {
902
930
EXPECT_EQ (mj_geomDistance (model, data, 0 , 1 , distmax, nullptr ), 0.5 );
903
931
mjtNum fromto[6 ];
904
932
EXPECT_EQ (mj_geomDistance (model, data, 0 , 1 , distmax, fromto), 0.5 );
905
- EXPECT_THAT (fromto, Pointwise (Eq (), std:: vector<mjtNum>{0 , 0 , 0 , 0 , 0 , 0 }));
933
+ EXPECT_THAT (fromto, Pointwise (Eq (), vector<mjtNum>{0 , 0 , 0 , 0 , 0 , 0 }));
906
934
907
935
// plane-sphere
908
936
distmax = 1.0 ;
909
937
EXPECT_DOUBLE_EQ (mj_geomDistance (model, data, 0 , 1 , 1.0 , fromto), 0.8 );
910
938
mjtNum eps = 1e-12 ;
911
939
EXPECT_THAT (fromto, Pointwise (DoubleNear (eps),
912
- std:: vector<mjtNum>{0 , 0 , 0 , 0 , 0 , 0.8 }));
940
+ vector<mjtNum>{0 , 0 , 0 , 0 , 0 , 0.8 }));
913
941
914
942
// sphere-plane
915
943
EXPECT_DOUBLE_EQ (mj_geomDistance (model, data, 1 , 0 , 1.0 , fromto), 0.8 );
916
944
EXPECT_THAT (fromto, Pointwise (DoubleNear (eps),
917
- std:: vector<mjtNum>{0 , 0 , 0.8 , 0 , 0 , 0 }));
945
+ vector<mjtNum>{0 , 0 , 0.8 , 0 , 0 , 0 }));
918
946
919
947
// sphere-sphere
920
948
EXPECT_DOUBLE_EQ (mj_geomDistance (model, data, 1 , 2 , 1.0 , fromto), 0.5 );
921
949
EXPECT_THAT (fromto, Pointwise (DoubleNear (eps),
922
- std:: vector<mjtNum>{.2 , 0 , 1 , .7 , 0 , 1 }));
950
+ vector<mjtNum>{.2 , 0 , 1 , .7 , 0 , 1 }));
923
951
924
952
// sphere-sphere, flipped order
925
953
EXPECT_DOUBLE_EQ (mj_geomDistance (model, data, 2 , 1 , 1.0 , fromto), 0.5 );
926
954
EXPECT_THAT (fromto, Pointwise (DoubleNear (eps),
927
- std:: vector<mjtNum>{.7 , 0 , 1 , .2 , 0 , 1 }));
955
+ vector<mjtNum>{.7 , 0 , 1 , .2 , 0 , 1 }));
928
956
929
957
// mesh-sphere (close distmax)
930
958
distmax = 0.701 ;
931
959
eps = model->opt .ccd_tolerance ;
932
960
EXPECT_THAT (mj_geomDistance (model, data, 3 , 1 , distmax, fromto),
933
961
DoubleNear (0.7 , eps));
934
962
EXPECT_THAT (fromto, Pointwise (DoubleNear (eps),
935
- std:: vector<mjtNum>{0 , 0 , .8 , 0 , 0 , .1 }));
963
+ vector<mjtNum>{0 , 0 , .8 , 0 , 0 , .1 }));
936
964
937
965
// mesh-sphere (far distmax)
938
966
distmax = 1.0 ;
939
967
EXPECT_THAT (mj_geomDistance (model, data, 3 , 1 , distmax, fromto),
940
968
DoubleNear (0.7 , eps));
941
969
EXPECT_THAT (fromto, Pointwise (DoubleNear (eps),
942
- std:: vector<mjtNum>{0 , 0 , .8 , 0 , 0 , .1 }));
970
+ vector<mjtNum>{0 , 0 , .8 , 0 , 0 , .1 }));
943
971
944
972
mj_deleteData (data);
945
973
mj_deleteModel (model);
0 commit comments