neclib.coordinates.angle_unwrap module#

Angle unwrap helpers for absolute modulo encoders.

This module is intentionally independent from ROS and device drivers. It converts an absolute modulo azimuth reading (for example 0..360 deg) into a continuous azimuth angle within a configured mechanical drive range.

exception AngleUnwrapError[source]#

Bases: RuntimeError

Base class for absolute encoder unwrap errors.

exception AmbiguousBranchError[source]#

Bases: AngleUnwrapError

Raised when a raw modulo angle maps to multiple valid branches.

exception NoValidBranchError[source]#

Bases: AngleUnwrapError

Raised when no continuous candidate is inside the drive range.

exception BranchJumpError[source]#

Bases: AngleUnwrapError

Raised when the selected continuous angle jumps implausibly.

exception RawAngleRangeError[source]#

Bases: AngleUnwrapError

Raised when an absolute encoder raw angle is unusable.

class AngleUnwrapResult(raw_deg: 'float', modulo_deg: 'float', continuous_deg: 'float', branch: 'int', branch_changed: 'bool', state: 'str')[source]#

Bases: object

Parameters:
  • raw_deg (float)

  • modulo_deg (float)

  • continuous_deg (float)

  • branch (int)

  • branch_changed (bool)

  • state (str)

raw_deg: float#
modulo_deg: float#
continuous_deg: float#
branch: int#
branch_changed: bool#
state: str#
class AbsoluteModuloUnwrapConfig(enabled: 'bool' = False, period_deg: 'float' = 360.0, raw_min_deg: 'float' = 0.0, raw_max_deg: 'float' = 360.0, drive_min_deg: 'float' = 0.0, drive_max_deg: 'float' = 360.0, zero_offset_deg: 'float' = 0.0, sign: 'int' = 1, max_jump_deg: 'Optional[float]' = None)[source]#

Bases: object

Parameters:
  • enabled (bool)

  • period_deg (float)

  • raw_min_deg (float)

  • raw_max_deg (float)

  • drive_min_deg (float)

  • drive_max_deg (float)

  • zero_offset_deg (float)

  • sign (int)

  • max_jump_deg (float | None)

enabled: bool = False#
period_deg: float = 360.0#
raw_min_deg: float = 0.0#
raw_max_deg: float = 360.0#
drive_min_deg: float = 0.0#
drive_max_deg: float = 360.0#
zero_offset_deg: float = 0.0#
sign: int = 1#
max_jump_deg: float | None = None#
validate()[source]#
Return type:

None

normalize_absolute_modulo_raw(raw_deg, cfg)[source]#

Return the calibrated modulo angle for a finite absolute-encoder raw value.

For a full-period raw range, finite periodic aliases outside the nominal raw range are accepted and folded back into the configured modulo interval. This preserves startup samples such as 727 deg while still rejecting NaN/inf and respecting stricter partial raw ranges.

Parameters:
Return type:

float

continuous_candidates(raw_deg, cfg, *, margin_periods=1)[source]#

Return valid continuous candidates for one raw modulo reading.

Parameters:
Return type:

List[float]

class AbsoluteModuloUnwrapper(cfg, *, previous_continuous_deg=None)[source]#

Bases: object

Stateful unwrap calculator for one absolute modulo encoder axis.

Parameters:
branch_for(continuous_deg, modulo_deg)[source]#
Parameters:
  • continuous_deg (float)

  • modulo_deg (float)

Return type:

int

unwrap(raw_deg)[source]#
Parameters:

raw_deg (float)

Return type:

AngleUnwrapResult