Genesis-Embodied-AI/genesis-world · error · ValueError
cap_axis must be non-zero
Error message
cap_axis must be non-zero
What it means
The cap-sphere sampling helper normalizes cap_axis to get the pole direction of the spherical cap; a zero vector cannot be normalized into a direction, so it is rejected. The norm is compared against gs.EPS, meaning near-zero axes (denormalized or extremely small components) also fail. This mirrors the radius and arc_spacing checks in the same function: all cap geometry parameters must be well-formed before sampling.
Source
Thrown at genesis/utils/geom.py:2364
Returns
-------
points : np.ndarray, shape (N, 3)
Points on the sphere surface.
normals : np.ndarray, shape (N, 3), optional
Normal vectors of the points. Only returned if ``return_normals`` is True.
"""
if radius <= 0.0:
raise ValueError(f"radius must be positive, got {radius}")
if n_rings < 1:
raise ValueError(f"n_rings must be >= 1, got {n_rings}")
if arc_spacing <= 0.0:
raise ValueError(f"probe_arc_spacing must be positive, got {arc_spacing}")
pole = np.asarray(cap_axis, dtype=gs.np_float)
p_norm = float(np.linalg.norm(pole))
if p_norm < gs.EPS:
raise ValueError("cap_axis must be non-zero")
pole = pole / p_norm
t0, t1 = orthogonals(pole)
pts: list[np.ndarray] = []
denom = max(n_rings - 1, 1)
for i in range(n_rings):
theta = (i / denom) * (0.5 * np.pi)
sin_t, cos_t = np.sin(theta), np.cos(theta)
ring_r = radius * sin_t
circ = 2.0 * np.pi * ring_r
if ring_r <= radius * gs.EPS:
n_pts = 1
else:
n_pts = max(3, int(np.ceil(circ / arc_spacing)))
for j in range(n_pts):
psi = (j / n_pts) * (2.0 * np.pi)
direction = sin_t * (np.cos(psi) * t0 + np.sin(psi) * t1) + cos_t * pole
pts.append(radius * direction)View on GitHub (pinned to 56e4aa5d82)
Solutions
- Pass an explicit unit axis such as cap_axis=[0, 0, 1].
- If the axis comes from a cross product, verify the inputs are not parallel before calling.
- If the axis is computed, fall back to a default direction when its norm falls below gs.EPS.
Example fix
# before
axis = np.cross(v1, v2) # v1 parallel to v2 -> zero vector
pts = sample_cap_probe_points(radius=r, n_rings=5, arc_spacing=s, cap_axis=axis)
# after
axis = np.cross(v1, v2)
if np.linalg.norm(axis) < gs.EPS:
axis = np.array([0.0, 0.0, 1.0])
pts = sample_cap_probe_points(radius=r, n_rings=5, arc_spacing=s, cap_axis=axis) Defensive patterns
Strategy: validation
Validate before calling
axis = np.asarray(axis, dtype=gs.np_float) assert np.linalg.norm(axis) >= gs.EPS, 'cap_axis is (near-)zero'
Prevention
- Never feed unnormalized cross products straight into direction parameters.
- Fall back to a canonical axis when a computed direction degenerates.
When it happens
Trigger: Calling the cap-sphere sampling helper with cap_axis=[0,0,0] or [0,0,1e-12], or with an axis computed as a cross product of two (near-)parallel vectors, which yields a zero norm.
Common situations: Deriving cap_axis from surface normals of degenerate geometry, or from cross(a, b) where a and b are parallel; also passing an uninitialized np.zeros(3) default.
Related errors
- probe_arc_spacing must be positive, got {arc_spacing}
- Python module 'uipc' is required by IPCCoupler but is not in
- `morph` in hybrid entity should be either URDF or Mesh
- Cannot handle soft material {material_soft}
- Compounding joints of types 'FREE' or 'FIXED' with any other
AI-assisted analysis of Genesis-Embodied-AI/genesis-world@56e4aa5d82 (2026-08-28).
Data as JSON: /api/errors/602a99a6677b4157.
Report an issue: GitHub.