Skip to content

Commit aac02ce

Browse files
committed
Extract magic numbers as named constants for better maintainability
- Add module-level constants for geometric detection thresholds - Remove unused center calculation in _estimate_tcp_from_mesh - Replace hardcoded values with descriptive constants: - SYMMETRY_POSITION_TOLERANCE, MIN_POSITION_OFFSET, Z_SIMILARITY_TOLERANCE - MAX_SEARCH_DEPTH, POSITION_EPSILON, FINGERTIP_RATIO, ASYMMETRY_RATIO - Y_THRESHOLD_WEAK, Y_THRESHOLD_STRONG, MIN_ARM_JOINTS
1 parent dff80b3 commit aac02ce

File tree

1 file changed

+47
-25
lines changed

1 file changed

+47
-25
lines changed

skrobot/urdf/robot_class_generator.py

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,33 @@
2323
logger = logging.getLogger(__name__)
2424

2525

26+
# ============================================================================
27+
# Geometric Detection Constants
28+
# ============================================================================
29+
30+
# Symmetry detection thresholds for gripper finger detection
31+
SYMMETRY_POSITION_TOLERANCE = 0.01 # Max deviation for symmetric positions (m)
32+
MIN_POSITION_OFFSET = 0.005 # Min offset to consider as valid finger position (m)
33+
Z_SIMILARITY_TOLERANCE = 0.02 # Max Z-axis difference for symmetric fingers (m)
34+
35+
# Search depth for finding end-effector links
36+
MAX_SEARCH_DEPTH = 5
37+
38+
# Mesh analysis thresholds
39+
POSITION_EPSILON = 1e-6 # Threshold for near-zero position values
40+
FINGERTIP_RATIO = 0.1 # Top percentage of vertices considered as fingertip
41+
ASYMMETRY_RATIO = 2.0 # Ratio to determine asymmetric mesh extension
42+
43+
# Y-coordinate thresholds for left/right limb detection (assumes T-pose)
44+
Y_THRESHOLD_WEAK = 0.05 # Weak threshold for Y-coordinate detection (m)
45+
Y_THRESHOLD_STRONG = 0.1 # Strong threshold for Y-coordinate detection (m)
46+
47+
# Joint count thresholds for limb classification
48+
MIN_ARM_JOINTS = 5 # Minimum joints to classify as arm
49+
MIN_LEG_JOINTS = 2 # Minimum joints to classify as leg
50+
MIN_HEAD_JOINTS = 4 # Minimum joints to classify as head (with torso)
51+
52+
2653
# ============================================================================
2754
# Pattern Configuration
2855
# ============================================================================
@@ -384,12 +411,12 @@ def _find_symmetric_gripper_midpoint(descendants, link_map):
384411
for i, (child1, pos1) in enumerate(local_positions):
385412
for child2, pos2 in local_positions[i + 1:]:
386413
# Check if symmetric in x or y (signs opposite, similar magnitude)
387-
x_symmetric = (abs(pos1[0] + pos2[0]) < 0.01
388-
and abs(pos1[0]) > 0.005)
389-
y_symmetric = (abs(pos1[1] + pos2[1]) < 0.01
390-
and abs(pos1[1]) > 0.005)
414+
x_symmetric = (abs(pos1[0] + pos2[0]) < SYMMETRY_POSITION_TOLERANCE
415+
and abs(pos1[0]) > MIN_POSITION_OFFSET)
416+
y_symmetric = (abs(pos1[1] + pos2[1]) < SYMMETRY_POSITION_TOLERANCE
417+
and abs(pos1[1]) > MIN_POSITION_OFFSET)
391418
# z should be similar
392-
z_similar = abs(pos1[2] - pos2[2]) < 0.02
419+
z_similar = abs(pos1[2] - pos2[2]) < Z_SIMILARITY_TOLERANCE
393420

394421
if (x_symmetric or y_symmetric) and z_similar:
395422
# Found symmetric pair - use link origins midpoint
@@ -409,7 +436,7 @@ def _find_symmetric_gripper_midpoint(descendants, link_map):
409436

410437
# x-axis: forward direction (toward TCP from origin)
411438
# Use the direction from parent origin to midpoint
412-
if np.linalg.norm(midpoint_local) > 1e-6:
439+
if np.linalg.norm(midpoint_local) > POSITION_EPSILON:
413440
x_axis_local = midpoint_local / np.linalg.norm(
414441
midpoint_local)
415442
else:
@@ -420,7 +447,7 @@ def _find_symmetric_gripper_midpoint(descendants, link_map):
420447
tip1_local = parent_rot_inv.dot(tip1 - parent_pos)
421448
tip2_local = parent_rot_inv.dot(tip2 - parent_pos)
422449
tip_midpoint = (tip1_local + tip2_local) / 2
423-
if np.linalg.norm(tip_midpoint) > 1e-6:
450+
if np.linalg.norm(tip_midpoint) > POSITION_EPSILON:
424451
x_axis_local = tip_midpoint / np.linalg.norm(
425452
tip_midpoint)
426453
else:
@@ -431,7 +458,7 @@ def _find_symmetric_gripper_midpoint(descendants, link_map):
431458
x_axis_local = x_axis_local - np.dot(
432459
x_axis_local, y_axis_local) * y_axis_local
433460
x_norm = np.linalg.norm(x_axis_local)
434-
if x_norm > 1e-6:
461+
if x_norm > POSITION_EPSILON:
435462
x_axis_local = x_axis_local / x_norm
436463
else:
437464
# x and y are parallel, use perpendicular
@@ -514,17 +541,15 @@ def _find_best_end_coords_parent(G, link_map, tip_link_name, group_type,
514541
'rot': None,
515542
}
516543

517-
max_depth = 5
518-
519544
# First: Search DESCENDANTS for tool frame or hand link
520545
# (e.g., panda_link7 -> panda_hand)
521546
try:
522547
descendants = nx.descendants(G, tip_link_name)
523548
except nx.NetworkXError:
524549
descendants = set()
525550

526-
# Check descendants up to max_depth
527-
for depth in range(1, max_depth + 1):
551+
# Check descendants up to MAX_SEARCH_DEPTH
552+
for depth in range(1, MAX_SEARCH_DEPTH + 1):
528553
for desc in descendants:
529554
try:
530555
path_len = nx.shortest_path_length(G, tip_link_name, desc)
@@ -557,7 +582,7 @@ def _find_best_end_coords_parent(G, link_map, tip_link_name, group_type,
557582
visited = set()
558583
current = tip_link_name
559584

560-
for _ in range(max_depth):
585+
for _ in range(MAX_SEARCH_DEPTH):
561586
visited.add(current)
562587
neighbors = list(undirected.neighbors(current))
563588
parent_candidates = [n for n in neighbors if n not in visited
@@ -685,7 +710,7 @@ def _get_fingertip_position(link):
685710

686711
# Get the centroid of vertices at the tip (max along primary axis)
687712
max_val = np.max(vertices[:, primary_axis])
688-
threshold = max_val - extents[primary_axis] * 0.1 # Top 10%
713+
threshold = max_val - extents[primary_axis] * FINGERTIP_RATIO
689714
tip_vertices = vertices[vertices[:, primary_axis] > threshold]
690715
tip_local = np.mean(tip_vertices, axis=0)
691716

@@ -792,14 +817,14 @@ def _estimate_tcp_from_mesh(link):
792817

793818
# Check if mesh extends significantly more in one direction
794819
# (asymmetric = likely end effector direction)
795-
(bounds[0] + bounds[1]) / 2
796820
min_dist = abs(bounds[0][primary_axis])
797821
max_dist = abs(bounds[1][primary_axis])
798822

799823
# If asymmetric (one side extends more), use that as TCP direction
800-
asymmetry_ratio = max(min_dist, max_dist) / (min(min_dist, max_dist) + 1e-6)
824+
asymmetry_ratio = (max(min_dist, max_dist)
825+
/ (min(min_dist, max_dist) + POSITION_EPSILON))
801826

802-
if asymmetry_ratio > 2.0: # Significant asymmetry
827+
if asymmetry_ratio > ASYMMETRY_RATIO: # Significant asymmetry
803828
# TCP is at the extended end
804829
if min_dist > max_dist:
805830
# Extends in negative direction
@@ -975,7 +1000,7 @@ def _detect_limb_type(link_names, tip_link=None, tip_y_coord=None,
9751000

9761001
# Geometric detection: long kinematic chain without left/right pattern
9771002
# is likely a single arm (serial manipulator)
978-
if movable_joint_count >= 5:
1003+
if movable_joint_count >= MIN_ARM_JOINTS:
9791004
has_lr_pattern = (right_arm_count >= 2 or left_arm_count >= 2
9801005
or right_leg_count >= 2 or left_leg_count >= 2)
9811006
if not has_lr_pattern:
@@ -996,23 +1021,20 @@ def _detect_limb_type(link_names, tip_link=None, tip_y_coord=None,
9961021
# Use Y coordinate for geometric left/right detection
9971022
# WARNING: This assumes the robot is in T-pose or similar standard pose.
9981023
# For robots with non-standard initial poses, this detection may fail.
999-
y_threshold = 0.05
10001024
if tip_y_coord is not None:
10011025
has_arm_pattern = (right_arm_count >= 1 or left_arm_count >= 1
10021026
or single_arm_count >= 2)
10031027
has_leg_pattern = right_leg_count >= 1 or left_leg_count >= 1
10041028

1005-
strong_y_threshold = 0.1
1006-
10071029
if has_arm_pattern or has_leg_pattern:
1008-
if tip_y_coord > y_threshold:
1009-
boost = 4 if tip_y_coord > strong_y_threshold else 2
1030+
if tip_y_coord > Y_THRESHOLD_WEAK:
1031+
boost = 4 if tip_y_coord > Y_THRESHOLD_STRONG else 2
10101032
if has_arm_pattern:
10111033
counts['left_arm'] += boost
10121034
if has_leg_pattern:
10131035
counts['left_leg'] += boost
1014-
elif tip_y_coord < -y_threshold:
1015-
boost = 4 if tip_y_coord < -strong_y_threshold else 2
1036+
elif tip_y_coord < -Y_THRESHOLD_WEAK:
1037+
boost = 4 if tip_y_coord < -Y_THRESHOLD_STRONG else 2
10161038
if has_arm_pattern:
10171039
counts['right_arm'] += boost
10181040
if has_leg_pattern:

0 commit comments

Comments
 (0)