Conversation
…l model) Agent-Logs-Url: https://github.com/VoxleOne/SpinStep/sessions/dc0f5515-1df0-43c9-8b5e-28e75d27e046 Co-authored-by: VoxleOne <119956342+VoxleOne@users.noreply.github.com>
- spinstep/math/: core, interpolation (slerp/squad), geometry, conversions, analysis, constraints — 6 modules with 20+ public functions - spinstep/control/: OrientationState (quaternion+distance), ControlCommand, P and PID controllers with angular+radial channels, trajectory tracking - spinstep/traversal/: relocated node, continuous, discrete, discrete_iterator - Updated __init__.py with new top-level API exports - 73 new tests (131 total pass, 5 skipped CUDA/healpy) - All ruff lint clean on new code Agent-Logs-Url: https://github.com/VoxleOne/SpinStep/sessions/dc0f5515-1df0-43c9-8b5e-28e75d27e046 Co-authored-by: VoxleOne <119956342+VoxleOne@users.noreply.github.com>
…ts, improve packaging - Replace utils/quaternion_utils.py with re-exports from spinstep.math - Replace utils/quaternion_math.py with re-export from spinstep.math.analysis - Update utils/__init__.py with deprecation documentation - Add test_api.py with comprehensive API stability tests (92 new tests) - Bump version to 0.5.0a0 - Update pyproject.toml: add Typing::Typed classifier, Changelog/Docs URLs, py.typed package-data, mypy overrides for third-party stubs - Fix lint issues in test_discrete_traversal.py, test_spinstep.py, test_traversal.py Agent-Logs-Url: https://github.com/VoxleOne/SpinStep/sessions/378ceebc-cb82-487b-8c8a-abb3c5806f7c Co-authored-by: VoxleOne <119956342+VoxleOne@users.noreply.github.com>
VoxleOne
left a comment
There was a problem hiding this comment.
-
Implementation Plan: Multi-Observer / Any-Node-as-Observer Upgrade
Concept
Currently, SpinStep's observer-centered spherical model places a single, implicit observer at the origin. All OrientationState instances describe position relative to this fixed observer. The proposed upgrade extends this so that any node can be an observer, enabling:
• Relative state computation between any two nodes
• Scene graphs where each node has its own local frame
• Multi-agent control where each agent sees the world from its own perspective
• Rich spatial queries like "what does Node B see from its position?"
Phase 1: Foundation — Node ↔ State Unification (MVP)
Goal: Bridge the gap between Node (traversal) and OrientationState (control), creating a unified spatial entity.
Key Tasks:- Create SpatialNode (or extend Node) — Add distance: float, angular_velocity, radial_velocity, timestamp fields to nodes. This unifies the traversal node with control state.
- Define NodeProtocol — A typing.Protocol with .orientation, .distance, .name attributes. Replace object type hints in get_relative_spin() and similar functions with this Protocol.
- Create RelativeState function — compute_relative_state(observer: SpatialNode, target: SpatialNode) -> OrientationState that computes the target's state as seen from the observer's frame.
- Add Node.as_state() and OrientationState.as_node() — Bidirectional conversion methods.
Dependencies: None (builds on existing code) Risks: API break for Node constructor if fields are added. Mitigate with optional parameters and backward-compatible defaults. Estimated Complexity: Medium (~400-600 LOC, ~20-30 new tests)
Phase 2: Frame Transforms — Observer-Relative Computation
Goal: Enable any node to act as a local reference frame with proper coordinate transforms.
Key Tasks: - Create ReferenceFrame class — Encapsulates an observer position (quaternion + distance from world origin) and provides to_local(state) -> OrientationState and to_world(state) -> OrientationState transforms.
- Implement rebase_state(state, from_frame, to_frame) — Transform a state from one observer's frame to another's. This is the core of multi-observer support.
- Add frame parameter to OrientationController.update() — Controllers can now operate in any frame, not just the implicit world frame.
- Extend OrientationTrajectory to support frame-relative waypoints — Waypoints can be specified relative to a moving observer.
Dependencies: Phase 1 (SpatialNode, RelativeState) Risks: Quaternion composition errors in frame transforms are subtle. Requires extensive numerical testing with known ground-truth scenarios. Estimated Complexity: High (~600-800 LOC, ~40-50 new tests)
Phase 3: Scene Graph — Multi-Node Topology
Goal: Replace tree-only traversal with a graph-aware spatial scene that supports any-node observation.
Key Tasks: - Create SceneGraph class — A container of SpatialNode instances with adjacency relationships (directed or undirected edges). Support both tree and general graph topologies.
- Implement SceneGraph.observe_from(node) — Returns all other nodes' states as seen from the given node's frame. This is the "any node as observer" capability.
- Create graph traversal iterators — BreadthFirstIterator, GraphQuaternionIterator that work on SceneGraph instead of trees.
- Add spatial indexing — Replace sklearn BallTree with an integrated spatial index (scipy KDTree or custom) that supports efficient nearest-neighbor queries in the spherical domain.
Dependencies: Phase 1 + Phase 2 (SpatialNode, ReferenceFrame) Risks: Graph cycles, disconnected components, and large graphs (1M+ nodes) need careful handling. Spatial indexing performance is critical. Estimated Complexity: High (~800-1200 LOC, ~50-70 new tests)
Phase 4: Multi-Agent Control — Production
Goal: Enable multiple controlled agents, each with their own observer frame, operating in a shared scene.
Key Tasks: - Create Agent class — Wraps a SpatialNode + OrientationController + optional TrajectoryController. Each agent has its own reference frame.
- Implement AgentManager — Coordinates multiple agents: parallel state updates, inter-agent proximity queries, collision avoidance hooks.
- Add event system — on_state_change, on_proximity_threshold, on_trajectory_complete callbacks for reactive behavior.
- Add serialization — JSON/MessagePack serialization for SceneGraph, Agent, and OrientationTrajectory for persistence and network transport.
Dependencies: All prior phases Risks: Multi-agent coordination introduces concurrency concerns. Event ordering must be deterministic. Estimated Complexity: Very High (~1000-1500 LOC, ~80-100 new tests)
-
Recommendations
3.1 Immediate Refactoring (Pre-Phase 1)- Resolve utils/ ↔ math/ duplication. Make utils/ re-export from math/ modules instead of maintaining independent implementations. Add deprecation warnings to direct utils imports. This is the single highest-priority cleanup.
- Add NodeProtocol typing. Replace object type hints in get_relative_spin() and get_unique_relative_spins() with a Protocol defining .orientation: np.ndarray.
- Add mypy overrides for scipy/sklearn/healpy/cupy. Add [[tool.mypy.overrides]] sections to pyproject.toml — this eliminates ~620 of 650 mypy errors immediately.
- Update CI workflow triggers. Add feature/* to the CI branch triggers so the feature branch gets automated testing.
- Update CHANGELOG.md for the 0.4.0a0 work (control subsystem, math library refactor).
3.2 Library/Framework Suggestions
Need
Current
Recommended
Spatial queries
sklearn.BallTree (~200MB)
scipy.spatial.KDTree (already a dependency) — drop scikit-learn
Serialization
None
dataclasses_json or manual to_dict()/from_dict() methods
Event system
None
Simple callback lists (no external dependency needed)
Graph data structure
None
networkx (for prototyping) or custom adjacency-list (for performance)
GPU acceleration
cupy (optional)
Keep as-is; consider jax for future differentiable control
3.3 Tooling Improvements - Add scipy-stubs to dev dependencies — Eliminates 500+ mypy import-untyped errors.
- Add pytest-cov to CI — Track coverage metrics; current coverage is likely 80%+ but unmeasured.
- Add pre-commit hooks — Enforce ruff, black, and mypy checks before commits.
- Consider sphinx for docs — The existing docstrings are rich enough for auto-generated API reference.
- Add benchmarking to CI — The benchmark/ directory exists but isn't integrated with CI.
3.4 Target Environment Guidance
For production use targeting 1M+ vertices at 60 FPS:
• The current numpy-based math is suitable for ~10K nodes at interactive rates
• For 100K+ nodes: vectorize batch_quaternion_angle and state updates (already partially done)
• For 1M+ nodes: GPU path via cupy is essential; consider sparse graph representations
• For real-time (16ms budget): pre-allocate arrays, avoid Python-level iteration, profile DiscreteOrientationSet.query_within_angle
3.5 Use Case Alignment
Use Case
Current Support
After Phase 4
Single robot orientation control
✅ Full
✅ Full
3D scene tree traversal
✅ Full
✅ Full
Multi-robot coordination
❌
✅ Full
Scientific visualization (globe)
Partial (HEALPix)
✅ Full
CAD / scene graph editing
❌
✅ With SceneGraph
Real-time simulation (60 FPS)
⚠️ Small scenes only
✅ With GPU path
Autonomous navigation mesh
❌
✅ With graph traversal
Summary
SpinStep feature/0.5.0a0 is a well-engineered alpha with strong fundamentals: clean domain model, production-quality controllers (P/PID with anti-windup), comprehensive math library, and good test coverage (131/136 tests passing). The primary architectural limitation — a single, implicit observer — is the exact target of the proposed upgrade.
The 4-phase plan (Node-State Unification → Frame Transforms → Scene Graph → Multi-Agent) is designed to extend the centered-observer metaphor to any node incrementally, preserving backward compatibility at each phase. The most urgent pre-work is resolving the utils/↔math/ duplication and improving type-checking hygiene.
…NGELOG - Add NodeProtocol (typing.Protocol) in spinstep.math.analysis, replacing `object` type hints in get_relative_spin() and get_unique_relative_spins() - Add Node.add_child() convenience method - Update CI workflow to trigger on feature/* branches - Update CHANGELOG.md with 0.5.0a0 release notes - Add tests for NodeProtocol and Node.add_child() - 228 tests pass, 5 skipped Agent-Logs-Url: https://github.com/VoxleOne/SpinStep/sessions/b6207769-cd62-43d2-83dd-af4b5a36fdba Co-authored-by: VoxleOne <119956342+VoxleOne@users.noreply.github.com>
Agent-Logs-Url: https://github.com/VoxleOne/SpinStep/sessions/b6207769-cd62-43d2-83dd-af4b5a36fdba Co-authored-by: VoxleOne <119956342+VoxleOne@users.noreply.github.com>
Addressed the immediate Pre-Phase 1 refactoring items:
Also added |
13 quaternion functions had independent duplicate implementations in both
spinstep/utils/andspinstep/math/. This PR makesmath/the single source of truth and convertsutils/to a backward-compatible re-export layer. It also addresses all 5 immediate Pre-Phase 1 refactoring items from the multi-observer implementation plan.Duplication resolution
utils/quaternion_utils.py: replaced 230 LOC of duplicate implementations with re-exports fromspinstep.math.{core,geometry,conversions,analysis}utils/quaternion_math.py: replaced with re-export fromspinstep.math.analysisutils/__init__.py: marked as deprecated, points users tospinstep.mathNodeProtocol typing
NodeProtocol(typing.Protocol) inspinstep.math.analysiswithorientation: np.ndarrayobjecttype hints inget_relative_spin()andget_unique_relative_spins()withNodeProtocol# type: ignore[union-attr]comments — structural typing validates.orientationaccessNodeProtocolfromspinstep.mathNode.add_child()
Node.add_child(child) -> Nodeconvenience method for ergonomic tree buildingCI workflow
.github/workflows/ci.ymlto trigger onfeature/*branches (push and PR)CHANGELOG
API stability tests (
test_api.py)__all__exports for all 4 subpackagespy.typedmarker and PEP 440 version formatNodeProtocolstructural typing (real Node + custom class)Node.add_child()methodPackaging (
pyproject.toml)0.5.0a0Typing :: Typedclassifier,Changelog/DocumentationURLs,py.typedin package-datascipy.*,sklearn.*,healpy.*,cupy.*Lint fixes
== True, unused variables)Test results: 228 passed, 5 skipped (CUDA/healpy unavailable)