1313
1414
1515@pytest .fixture (autouse = True )
16- def set_seed ():
16+ def _set_seed ():
1717 """Automatically seed the RNG before every test to ensure reproducibility."""
1818 np .random .seed (42 )
1919
2020
21- def generate_random_q (q_min , q_max , n = 1 ):
21+ def generate_random_q (q_min , q_max ):
2222 q_min = np .array (q_min )
2323 q_max = np .array (q_max )
2424 range_span = q_max - q_min
2525
2626 # 1. Generate base random values (centered 90% of range)
27- unit_rand = np .random .rand (n , 7 )
27+ unit_rand = np .random .rand (1 , 7 )
2828 q_rand = q_min + (range_span * 0.05 ) + unit_rand * (range_span * 0.90 )
2929
3030 # 2. Singularity Avoidance
@@ -35,33 +35,18 @@ def generate_random_q(q_min, q_max, n=1):
3535 # Threshold in radians (approx 5 degrees to be safe)
3636 singularity_threshold = 0.08
3737
38- # Handle single sample case (1D array)
39- if n == 1 :
40- # Avoid Shoulder Singularity (q[1] ≈ 0)
41- if abs (q_rand [0 , 1 ]) < singularity_threshold :
42- # Push it away from 0, preserving the sign (default to positive if 0)
43- sign = np .sign (q_rand [0 , 1 ]) if q_rand [0 , 1 ] != 0 else 1.0
44- q_rand [0 , 1 ] = sign * singularity_threshold
38+ # Avoid Shoulder Singularity (q[1] ≈ 0)
39+ if abs (q_rand [0 , 1 ]) < singularity_threshold :
40+ # Push it away from 0, preserving the sign (default to positive if 0)
41+ sign = np .sign (q_rand [0 , 1 ]) if q_rand [0 , 1 ] != 0 else 1.0
42+ q_rand [0 , 1 ] = sign * singularity_threshold
4543
46- # Avoid Wrist Singularity (q[5] ≈ 0) - though less critical for this specific bug
47- if abs (q_rand [0 , 5 ]) < singularity_threshold :
48- sign = np .sign (q_rand [0 , 5 ]) if q_rand [0 , 5 ] != 0 else 1.0
49- q_rand [0 , 5 ] = sign * singularity_threshold
44+ # Avoid Wrist Singularity (q[5] ≈ 0) - though less critical for this specific bug
45+ if abs (q_rand [0 , 5 ]) < singularity_threshold :
46+ sign = np .sign (q_rand [0 , 5 ]) if q_rand [0 , 5 ] != 0 else 1.0
47+ q_rand [0 , 5 ] = sign * singularity_threshold
5048
51- return q_rand [0 ]
52-
53- # Handle batch case (2D array)
54- else :
55- # Vectorized fix for Shoulder (Index 1)
56- # Find indices where q is too close to 0
57- shoulder_mask = np .abs (q_rand [:, 1 ]) < singularity_threshold
58- # Create a sign vector (replace 0s with 1s)
59- signs = np .sign (q_rand [:, 1 ])
60- signs [signs == 0 ] = 1.0
61- # Apply shift
62- q_rand [shoulder_mask , 1 ] = signs [shoulder_mask ] * singularity_threshold
63-
64- return q_rand
49+ return q_rand [0 ]
6550
6651
6752def get_random_pose_in_isocube ():
@@ -177,7 +162,7 @@ def test_ik_full_consistency(robot_type):
177162 continue
178163
179164 valid_sols_count += 1
180- pose_check = frankik .fk (sol )
165+ pose_check = frankik .fk (sol ) # type: ignore
181166
182167 # Every returned solution must result in the target pose
183168 np .testing .assert_allclose (
@@ -193,6 +178,7 @@ def test_ik_full_consistency(robot_type):
193178def test_limits_respected ():
194179 """Sanity check that our random generator respects limits."""
195180 q_min , q_max = frankik .q_min_panda , frankik .q_max_panda
196- q = generate_random_q (q_min , q_max , n = 100 )
197- assert np .all (q >= q_min )
198- assert np .all (q <= q_max )
181+ for _ in range (100 ):
182+ q = generate_random_q (q_min , q_max )
183+ assert np .all (q >= q_min )
184+ assert np .all (q <= q_max )
0 commit comments