Skip to content

Latest commit

 

History

History
257 lines (196 loc) · 12.5 KB

File metadata and controls

257 lines (196 loc) · 12.5 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Pylinkage is a Python library for building and optimizing planar linkages using Particle Swarm Optimization (PSO). It provides tools to define kinematic linkages, simulate their motion, optimize their geometry against objective functions, and visualize the results.

Common Commands

Setup and Dependencies

uv sync                              # Install all dependencies (including dev)
uv sync --no-dev                     # Install only production dependencies

Testing

uv run task test                     # Run all tests
uv run task test-cov                 # Run with coverage
uv run pytest tests/joints/          # Run specific test directory
uv run pytest -k "test_buildable"    # Run tests matching pattern

Linting and Type Checking

uv run task lint                     # Lint code
uv run task lint-fix                 # Lint and auto-fix
uv run task format                   # Format code
uv run task typecheck                # Type check

Building

uv build                             # Build wheel and sdist
uv run task docs                     # Build documentation
uv run task docs-clean               # Clean documentation artifacts

Architecture

Package Structure

  • src/pylinkage/components/: Base classes and fixed frame elements

    • Component: Abstract base class for all kinematic elements
    • ConnectedComponent: Base for elements with parent connections
    • Ground: Fixed point on the frame (ground link)
    • PointTracker: Sensor component that tracks a point on a moving link
    • _AnchorProxy: Proxy for actuator output connections
  • src/pylinkage/actuators/: Motor-driven input drivers

    • Crank: Motor-driven rotary input (rotating around ground)
    • ArcCrank: Crank with limited angular range (oscillating arc motion)
    • LinearActuator: Motor-driven linear input (oscillating piston/cylinder)
  • src/pylinkage/dyads/: Pure Assur groups (0 DOF structural units)

    • RRRDyad: Circle-circle intersection (two links meeting at one joint)
    • RRPDyad: Circle-line intersection (slider mechanism)
    • PPDyad: Line-line intersection (double slider mechanism)
    • FixedDyad: Deterministic polar projection
    • BinaryDyad: Base class for binary Assur groups
    • TranslatingCamFollower: Translating follower driven by cam profile
    • OscillatingCamFollower: Oscillating (rocker) follower driven by cam profile
    • create_dyad(): Factory function to create dyads from isomer signatures
    • Note: Re-exports Ground, Crank, LinearActuator, Linkage for backwards compatibility
  • src/pylinkage/cam/: Cam profile definitions for cam-follower mechanisms

    • CamProfile: Base class for cam profiles
    • FunctionProfile: Profile from motion law + timing parameters
    • PointArrayProfile: Profile from discrete points with spline interpolation
    • Motion laws: HarmonicMotionLaw, CycloidalMotionLaw, ModifiedTrapezoidalMotionLaw, PolynomialMotionLaw
    • Factory functions: polynomial_345(), polynomial_4567()
  • src/pylinkage/simulation/: Simulation containers

    • Linkage: Container orchestrating components into a mechanism
  • src/pylinkage/mechanism/: Low-level Links + Joints model

    • Joint, RevoluteJoint, PrismaticJoint, GroundJoint: Joint classes
    • Link, DriverLink, GroundLink: Rigid body classes
    • Mechanism: Main orchestrator class
    • Conversion: pylinkage.dyads.to_mechanism() builds a Mechanism from a component Linkage. The reverse direction does not exist: mechanism_to_linkage() and mechanism_from_linkage() were deleted in b0cbc3b with the legacy joints module.
    • Serialization: mechanism_to_json(), mechanism_from_json()
  • src/pylinkage/linkage/: Linkage class that orchestrates joint collections

    • Linkage: Main class managing joints, solving order, and simulation via step() method
    • Simulation: Container for simulation results (loci, steps)
    • analysis.py: Helper functions like bounding_box() and kinematic_default_test()
    • sensitivity.py: Sensitivity analysis (sensitivity_analysis()) and tolerance analysis (tolerance_analysis()) for manufacturing/dimensional variation
  • src/pylinkage/optimization/: Optimization algorithms

    • grid_search.py: trials_and_errors_optimization() - exhaustive search
    • particle_swarm.py: particle_swarm_optimization() - PSO using PySwarms
    • scipy_optimize.py: differential_evolution_optimization(), minimize_linkage() - scipy-based
    • multi_objective.py: multi_objective_optimization() - Pareto-optimal solutions using NSGA-II/III (requires pymoo)
    • async_optimization.py: Async variants of all optimizers with progress tracking (OptimizationProgress)
    • collections/pareto.py: ParetoFront, ParetoSolution for multi-objective results
    • utils.py: @kinematic_minimization/@kinematic_maximization decorators and generate_bounds()
  • src/pylinkage/geometry/: 2D geometry utilities

    • core.py: Distance calculations, coordinate conversions
    • secants.py: Circle-circle and circle-line intersections
  • src/pylinkage/visualizer/: Multi-backend visualization

    • static.py, animated.py: Matplotlib backend (show_linkage(), GIF output)
    • plotly_viz.py: Plotly backend for interactive HTML (plot_linkage_plotly())
    • drawsvg_viz.py: drawsvg backend for publication-quality SVG (save_linkage_svg())
    • pso_plots.py: PSO visualization dashboards
  • src/pylinkage/hypergraph/: Hierarchical hypergraph representation (new)

    • Abstract mathematical foundation for linkage definition
    • HypergraphLinkage: Graph with nodes, edges, and hyperedges
    • Component: Reusable linkage subgraph with ports and parameters
    • HierarchicalLinkage: Composition of component instances
    • Built-in components: FOURBAR, CRANK_SLIDER, DYAD
    • Conversion functions: to_linkage(), from_linkage(), to_assur_graph()
  • src/pylinkage/assur/: Assur group decomposition

    • Graph-based representation using formal kinematic theory
    • LinkageGraph: Nodes (joints) and edges (links)
    • Assur groups: DyadRRR, DyadRRP, DyadRPR, DyadPRR
    • decompose_assur_groups(): Structural decomposition algorithm
    • graph_to_linkage(): Convert graph representation to Linkage
  • src/pylinkage/solver/: High-performance numba simulation backend

    • Pure-numba JIT-compiled solver for optimization hot loops
    • SolverData: Numeric arrays replacing Python objects
    • simulate(): Fast trajectory computation
    • linkage_to_solver_data(): Convert Linkage for fast simulation
  • src/pylinkage/synthesis/: Classical mechanism synthesis methods

    • function_generation.py: Match input/output angle relationships (Freudenstein)
    • path_generation.py: Coupler point traces through specified points
    • motion_generation.py: Guide body through specified poses
    • burmester.py: Burmester theory for circle point/center point curves
    • utils.py: Grashof criterion checking (is_grashof(), is_crank_rocker())
    • conversion.py: fourbar_from_lengths(), solution_to_linkage()
  • src/pylinkage/symbolic/: Symbolic computation using SymPy

    • joints.py: SymStatic, SymCrank, SymRevolute symbolic joint classes
    • linkage.py: SymbolicLinkage for symbolic trajectory expressions
    • solver.py: solve_linkage_symbolically(), compute_trajectory_numeric()
    • optimization.py: SymbolicOptimizer for gradient-based optimization
    • geometry.py: Symbolic geometry primitives
  • src/pylinkage/bridge/: Conversion utilities between representations

    • Bridges between Linkage, Assur graph, Hypergraph, and Solver representations

Key Patterns

Component-Based Definition Flow (Preferred API):

  1. Create Ground points for fixed frame locations (from pylinkage.components)
  2. Create Crank or LinearActuator for motor-driven input (from pylinkage.actuators)
  3. Add RRRDyad or RRPDyad for constrained connections (from pylinkage.dyads)
  4. Wrap in Linkage and call step() to simulate (from pylinkage.simulation)
  5. Use show_linkage() to visualize

Note: For backwards compatibility, Ground, Crank, LinearActuator, and Linkage are also re-exported from pylinkage.dyads.

Alternative Definition via Hypergraph:

  1. Use component instances from library (FOURBAR, DYAD, etc.)
  2. Connect via HierarchicalLinkage with Connection objects
  3. Call flatten() then to_linkage() to get simulatable Linkage

Alternative Definition via Assur Graph:

  1. Create LinkageGraph with Node and Edge objects
  2. Use decompose_assur_groups() for structural analysis
  3. Call graph_to_linkage() to convert to Linkage

Optimization Flow:

  1. Define a fitness function decorated with @kinematic_minimization or @kinematic_maximization
  2. Generate bounds with generate_bounds(linkage.get_constraints())
  3. Call particle_swarm_optimization() or trials_and_errors_optimization(); every optimizer returns an Ensemble
  4. Apply results via linkage.set_constraints(results[0].dimensions) (or results.show(0) to draw a member)

Synthesis Flow (Design from requirements):

  1. Define precision points, angle pairs, or poses depending on synthesis type
  2. Call function_generation(), path_generation(), or motion_generation()
  3. Iterate over SynthesisResult.solutions to get candidate linkages
  4. Validate with grashof_check() or is_crank_rocker()
  5. Convert to Linkage with solution_to_linkage() for simulation

Symbolic Computation Flow:

  1. Create symbolic linkage with fourbar_symbolic() or linkage_to_symbolic()
  2. Get closed-form expressions via solve_linkage_symbolically()
  3. Evaluate numerically with compute_trajectory_numeric()
  4. Optional: Use SymbolicOptimizer for gradient-based optimization

Constraint System:

  • get_constraints(): Returns flat list of distances/angles
  • set_constraints(): Applies constraints back to joints
  • get_num_constraints()/set_num_constraints(): deprecated aliases since 1.2.0 (warn, removed in 2.0)
  • get_coords()/set_coords(): Joint positions (used for initial positions in optimization)

Exceptions:

  • UnbuildableError: Raised when a linkage cannot be assembled (geometric impossibility)
  • UnderconstrainedError: Raised when a linkage is underconstrained (too few constraints)
  • NotCompletelyDefinedError: Raised when joint parameters are incomplete

Multi-Objective Optimization Flow:

  1. Define multiple objective functions decorated with @kinematic_minimization
  2. Call multi_objective_optimization() with list of objectives (requires pymoo: pip install pylinkage[moo])
  3. Get ParetoFront containing non-dominated ParetoSolution objects
  4. Iterate solutions to explore trade-offs between competing objectives

Sensitivity/Tolerance Analysis Flow:

  1. Define linkage with named joints for interpretable results
  2. Call sensitivity_analysis(linkage) to compute sensitivity indices per constraint
  3. Call tolerance_analysis(linkage, tolerances, n_samples) for Monte Carlo simulation
  4. Results include mean/std deviation of output paths and statistical distributions

Historical note — legacy pylinkage.joints removal:

The legacy pylinkage.joints module (with Static, Revolute, Linear, Fixed, and the old Crank signature) was removed in commit 9c1515f. All code now uses the components/actuators/dyads API. If you encounter old snippets elsewhere, the mapping was:

  • Static(x, y) → Ground(x, y) from pylinkage.components
  • Crank(joint0=A, distance=r, angle=v) → Crank(anchor=A, radius=r, angular_velocity=v) from pylinkage.actuators
  • Revolute(joint0=A, joint1=B, distance0=d0, distance1=d1) → RRRDyad(anchor1=A, anchor2=B, distance1=d0, distance2=d1) from pylinkage.dyads
  • Linear(...) → RRPDyad(...) from pylinkage.dyads
  • Fixed(...) → FixedDyad(...) from pylinkage.dyads

Note: the local submodules src/pylinkage/solver/joints.py and src/pylinkage/symbolic/joints.py are unrelated internal helpers (numba joint solvers and symbolic joint classes) — they are not the deprecated API.

Dependencies

Requires Python >= 3.10

Core: numpy, numba, scipy, matplotlib, pyswarms, tqdm, plotly, drawsvg, sympy

Optional extras:

  • moo: pymoo (for multi-objective optimization)
  • cad: ezdxf, build123d (for CAD export)
  • analysis: pandas (for data analysis)

Dev (managed via uv): pytest, pytest-cov, hypothesis, mypy, ruff, sphinx, sphinx-rtd-theme, myst-parser, taskipy