31
31
from isaaclab .assets import Articulation , ArticulationCfg
32
32
from isaaclab .sim import build_simulation_context
33
33
from isaaclab .utils .assets import ISAAC_NUCLEUS_DIR
34
+ from isaaclab .managers import SceneEntityCfg
35
+ from isaaclab .envs .mdp .terminations import joint_pos_out_of_limit
34
36
35
37
##
36
38
# Pre-defined configs
@@ -657,25 +659,21 @@ def test_out_of_range_default_joint_vel(sim, device):
657
659
@pytest .mark .parametrize ("device" , ["cuda:0" , "cpu" ])
658
660
@pytest .mark .parametrize ("add_ground_plane" , [True ])
659
661
def test_joint_pos_limits (sim , num_articulations , device , add_ground_plane ):
660
- """Test write_joint_limits_to_sim API and when default pos falls outside of the new limits.
661
-
662
- This test verifies that:
663
- 1. Joint limits can be set correctly
664
- 2. Default positions are preserved when setting new limits
665
- 3. Joint limits can be set with indexing
666
- 4. Invalid joint positions are properly handled
667
-
668
- Args:
669
- sim: The simulation fixture
670
- num_articulations: Number of articulations to test
671
- """
662
+ """Test write_joint_limits_to_sim API and validate limits via joint_pos_out_of_limit()."""
672
663
# Create articulation
673
664
articulation_cfg = generate_articulation_cfg (articulation_type = "panda" )
674
665
articulation , _ = generate_articulation (articulation_cfg , num_articulations , device )
675
666
667
+ # Minimal fake env that exposes scene["robot"] -> articulation
668
+ class _Env :
669
+ def __init__ (self , art ):
670
+ self .scene = {"robot" : art }
671
+
672
+ env = _Env (articulation )
673
+ robot_all = SceneEntityCfg (name = "robot" ) # all joints
674
+
676
675
# Play sim
677
676
sim .reset ()
678
- # Check if articulation is initialized
679
677
assert articulation .is_initialized
680
678
681
679
# Get current default joint pos
@@ -691,6 +689,10 @@ def test_joint_pos_limits(sim, num_articulations, device, add_ground_plane):
691
689
torch .testing .assert_close (articulation ._data .joint_pos_limits , limits )
692
690
torch .testing .assert_close (articulation ._data .default_joint_pos , default_joint_pos )
693
691
692
+ # Validate via function: no joint should be out of limits
693
+ out = joint_pos_out_of_limit (env , robot_all ) # [N]
694
+ assert torch .all (~ out )
695
+
694
696
# Set new joint limits with indexing
695
697
env_ids = torch .arange (1 , device = device )
696
698
joint_ids = torch .arange (2 , device = device )
@@ -703,29 +705,30 @@ def test_joint_pos_limits(sim, num_articulations, device, add_ground_plane):
703
705
torch .testing .assert_close (articulation ._data .joint_pos_limits [env_ids ][:, joint_ids ], limits )
704
706
torch .testing .assert_close (articulation ._data .default_joint_pos , default_joint_pos )
705
707
706
- # Set new joint limits that invalidate default joint pos
708
+ # Validate via function on selected joints
709
+ robot_subset = SceneEntityCfg (name = "robot" , joint_ids = joint_ids .tolist ())
710
+ out = joint_pos_out_of_limit (env , robot_subset ) # [N]
711
+ assert torch .all (~ out )
712
+
713
+ # Set new joint limits that (narrowly) constrain default joint pos
707
714
limits = torch .zeros (num_articulations , articulation .num_joints , 2 , device = device )
708
715
limits [..., 0 ] = torch .rand (num_articulations , articulation .num_joints , device = device ) * - 0.1
709
716
limits [..., 1 ] = torch .rand (num_articulations , articulation .num_joints , device = device ) * 0.1
710
717
articulation .write_joint_position_limit_to_sim (limits )
711
718
712
- # Check if all values are within the bounds
713
- within_bounds = (articulation ._data .default_joint_pos >= limits [..., 0 ]) & (
714
- articulation ._data .default_joint_pos <= limits [..., 1 ]
715
- )
716
- assert torch .all (within_bounds )
719
+ # Validate via function: defaults should still be within new limits
720
+ out = joint_pos_out_of_limit (env , robot_all ) # [N]
721
+ assert torch .all (~ out )
717
722
718
- # Set new joint limits that invalidate default joint pos with indexing
723
+ # Set new joint limits that constrain default joint pos with indexing
719
724
limits = torch .zeros (env_ids .shape [0 ], joint_ids .shape [0 ], 2 , device = device )
720
725
limits [..., 0 ] = torch .rand (env_ids .shape [0 ], joint_ids .shape [0 ], device = device ) * - 0.1
721
726
limits [..., 1 ] = torch .rand (env_ids .shape [0 ], joint_ids .shape [0 ], device = device ) * 0.1
722
727
articulation .write_joint_position_limit_to_sim (limits , env_ids = env_ids , joint_ids = joint_ids )
723
728
724
- # Check if all values are within the bounds
725
- within_bounds = (articulation ._data .default_joint_pos [env_ids ][:, joint_ids ] >= limits [..., 0 ]) & (
726
- articulation ._data .default_joint_pos [env_ids ][:, joint_ids ] <= limits [..., 1 ]
727
- )
728
- assert torch .all (within_bounds )
729
+ # Validate via function on selected joints
730
+ out = joint_pos_out_of_limit (env , robot_subset ) # [N]
731
+ assert torch .all (~ out )
729
732
730
733
731
734
@pytest .mark .parametrize ("num_articulations" , [1 , 2 ])
0 commit comments