embodik 0.1.1__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {embodik-0.1.1 → embodik-0.3.0}/.gitignore +4 -0
- embodik-0.3.0/CHANGELOG.md +109 -0
- {embodik-0.1.1 → embodik-0.3.0}/CMakeLists.txt +1 -1
- embodik-0.3.0/PKG-INFO +548 -0
- embodik-0.3.0/README.md +499 -0
- {embodik-0.1.1 → embodik-0.3.0}/cpp_core/include/embodik/kinematics_solver.hpp +47 -1
- {embodik-0.1.1 → embodik-0.3.0}/cpp_core/include/embodik/types.hpp +11 -0
- {embodik-0.1.1 → embodik-0.3.0}/cpp_core/src/kinematics_solver.cpp +449 -55
- {embodik-0.1.1 → embodik-0.3.0}/docs/examples/index.md +9 -2
- embodik-0.3.0/docs/installation.md +462 -0
- {embodik-0.1.1 → embodik-0.3.0}/examples/01_basic_ik_simple.py +5 -7
- {embodik-0.1.1 → embodik-0.3.0}/examples/02_collision_aware_IK.py +286 -3
- embodik-0.3.0/examples/03_teleop_ik.py +851 -0
- embodik-0.3.0/examples/04_gpu_batch_ik.py +241 -0
- embodik-0.3.0/examples/05_gpu_collision_batch.py +218 -0
- embodik-0.3.0/examples/06_gpu_solver_demo.py +457 -0
- embodik-0.3.0/examples/07_parallel_trajectory_tracking.py +850 -0
- embodik-0.3.0/fn_velocity_solve.casadi +1 -0
- {embodik-0.1.1 → embodik-0.3.0}/pixi.lock +2632 -1059
- {embodik-0.1.1 → embodik-0.3.0}/pixi.toml +45 -2
- {embodik-0.1.1 → embodik-0.3.0}/pyproject.toml +11 -1
- {embodik-0.1.1 → embodik-0.3.0}/python/embodik/__init__.py +21 -0
- embodik-0.3.0/python/embodik/gpu/__init__.py +84 -0
- embodik-0.3.0/python/embodik/gpu/casadi_fi_pesns.py +382 -0
- embodik-0.3.0/python/embodik/gpu/export_casadi_velocity_solve.py +177 -0
- embodik-0.3.0/python/embodik/gpu/torch_kinematics.py +300 -0
- embodik-0.3.0/python/embodik/gpu/warp_collision.py +481 -0
- embodik-0.3.0/python/embodik/gpu_solver.py +419 -0
- {embodik-0.1.1 → embodik-0.3.0}/python_bindings/src/bindings.cpp +22 -4
- {embodik-0.1.1 → embodik-0.3.0}/python_bindings/src/kinematics_solver_bindings.cpp +28 -2
- {embodik-0.1.1 → embodik-0.3.0}/python_bindings/src/robot_model_bindings.cpp +96 -0
- embodik-0.3.0/scripts/benchmark_fi_pesns.py +488 -0
- embodik-0.3.0/scripts/benchmark_gpu_batched.py +322 -0
- embodik-0.3.0/scripts/install_cusadi.sh +33 -0
- embodik-0.3.0/scripts/microbench_solve_velocity.py +149 -0
- embodik-0.3.0/scripts/test_gpu_accuracy.py +51 -0
- {embodik-0.1.1 → embodik-0.3.0}/scripts/upload_pypi.sh +8 -4
- embodik-0.3.0/test/test_fi_pesns.py +413 -0
- embodik-0.3.0/test/test_gpu_collision.py +404 -0
- embodik-0.3.0/test/test_gpu_solver.py +424 -0
- embodik-0.1.1/CHANGELOG.md +0 -49
- embodik-0.1.1/PKG-INFO +0 -309
- embodik-0.1.1/README.md +0 -265
- embodik-0.1.1/docs/installation.md +0 -264
- {embodik-0.1.1 → embodik-0.3.0}/.gitattributes +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/.github/workflows/ci.yml +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/.github/workflows/docs.yml +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/.github/workflows/release.yml +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/CONTRIBUTING.md +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/LICENSE +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/MANIFEST.in +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/cpp_core/include/embodik/constraints.hpp +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/cpp_core/include/embodik/ik_baseline.hpp +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/cpp_core/include/embodik/robot_model.hpp +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/cpp_core/include/embodik/tasks.hpp +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/cpp_core/src/robot_model.cpp +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/cpp_core/src/tasks.cpp +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/docs/api/index.md +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/docs/api/kinematics_solver.md +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/docs/api/robot_model.md +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/docs/api/tasks.md +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/docs/api/utils.md +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/docs/api/visualization.md +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/docs/development.md +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/docs/examples/basic_ik.md +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/docs/examples/multi_task_ik.md +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/docs/index.md +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/docs/quickstart.md +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/docs/transforms.md +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/examples/example_helpers/__init__.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/examples/example_helpers/dual_arm_ik_helper.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/examples/example_helpers/limit_profiles/alpha_extended.yaml +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/examples/example_helpers/limit_profiles/alpha_extended_all.yaml +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/examples/example_helpers/limit_profiles/beta_uniform_plus21.yaml +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/examples/robot_model_example.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/examples/utils/__init__.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/examples/utils/robot_models.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/examples/visualization_example.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/mkdocs.yml +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/python/embodik/_runtime_deps.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/python/embodik/cli.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/python/embodik/examples/__init__.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/python/embodik/examples/basic_ik.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/python/embodik/examples/robot_model.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/python/embodik/robot_visualizer.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/python/embodik/utils.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/python/embodik/viser_helpers.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/python/embodik/visualization.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/python/embodik/visualization_pinocchio.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/python_bindings/CMakeLists.txt +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/python_bindings/src/tasks_bindings.cpp +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/scripts/patch_qhull_cmake.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/scripts/setup_pypirc.sh +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/scripts/test_cpp_extension.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/scripts/test_extension_direct.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/scripts/test_import.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/scripts/test_python_utils.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/scripts/upload_testpypi.sh +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/scripts/version.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/test/CMakeLists.txt +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/test/test_embodik.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/test/test_robot_model.cpp +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/test/test_robot_model.py +0 -0
- {embodik-0.1.1 → embodik-0.3.0}/test/test_tasks.py +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.3.0] - 2026-02-03
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **GPU Acceleration**: Batched velocity IK solving with massive parallelism (100-500x speedup)
|
|
12
|
+
- Achieves ~670,000 IK solves/second at batch size 10,000
|
|
13
|
+
- Ideal for RL training (4096+ parallel environments), motion planning, and dataset generation
|
|
14
|
+
- GPU batched solver via CusADi-compiled CUDA kernels
|
|
15
|
+
- **FI-PeSNS Solver**: Fixed-Iteration Penalized eSNS algorithm optimized for GPU
|
|
16
|
+
- Singularity-Robust Inverse (SRINV) for numerical stability
|
|
17
|
+
- Analytical scaling for feasible task scales without iterative saturation
|
|
18
|
+
- Penalty gradient approach for constraint enforcement
|
|
19
|
+
- Fixed iterations for predictable compute time (ideal for real-time RL)
|
|
20
|
+
- **GPU Collision Detection**: GPU-accelerated collision detection via NVIDIA Warp
|
|
21
|
+
- Batched collision queries for parallel processing
|
|
22
|
+
- Experimental support for GPU-accelerated self-collision avoidance
|
|
23
|
+
- **Parallel Trajectory Tracking Demo**: Visualize 100 robot instances simultaneously tracking different trajectories
|
|
24
|
+
- Interactive demo with Viser visualization
|
|
25
|
+
- Demonstrates GPU parallelization capabilities
|
|
26
|
+
- Achieves ~50,000+ IK solves/second with GPU acceleration
|
|
27
|
+
- **Teleoperation IK Example**: Interactive IK control using Seer wireless controller (Xvisio SDK)
|
|
28
|
+
- **GPU Benchmarks and Demos**: Comprehensive benchmarking tools for GPU performance
|
|
29
|
+
- Batch IK performance benchmarks
|
|
30
|
+
- FI-PeSNS vs CPU accuracy benchmarks
|
|
31
|
+
- Collision detection benchmarks
|
|
32
|
+
- GPU solver demonstration panels
|
|
33
|
+
- **CasADi Integration**: Export and compile velocity IK functions to CUDA kernels
|
|
34
|
+
- Symbolic function export for GPU compilation
|
|
35
|
+
- CusADi integration for CUDA kernel generation
|
|
36
|
+
- **GPU Environment Support**: CUDA feature in pixi.toml with GPU-specific tasks
|
|
37
|
+
- `check-cuda`, `check-gpu`, `install-cusadi` tasks
|
|
38
|
+
- GPU demos and benchmarks via pixi tasks
|
|
39
|
+
- CUDA environment configuration
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
- Enhanced examples with GPU acceleration support
|
|
43
|
+
- Updated dependencies to include xvisio SDK support for teleoperation examples
|
|
44
|
+
- Improved GPU documentation and setup instructions
|
|
45
|
+
|
|
46
|
+
### Dependencies
|
|
47
|
+
- Added `casadi>=3.6.0` and `torch>=2.0.0` to `[gpu]` optional dependencies
|
|
48
|
+
- Added `warp-lang>=1.0.0` to `[gpu-collision]` optional dependencies
|
|
49
|
+
- Added `xvisio>=0.3.1` to pixi dependencies for teleoperation examples
|
|
50
|
+
|
|
51
|
+
## [0.2.0] - 2026-01-30
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
- Position IK now supports `excluded_joint_indices` to lock joints during solves
|
|
55
|
+
- Position IK can enforce collision constraints during iterative solves (when configured)
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
- Velocity solver now groups same-priority tasks to make ordering within a priority level symmetric
|
|
59
|
+
- Collision constraint computation now uses cached allow-masks to skip excluded pairs efficiently
|
|
60
|
+
- Collision recovery near `min_distance` uses deadband + adaptive push to reduce jitter and stalling
|
|
61
|
+
- Collision constraint default `nearest_points_all_pairs` set to true
|
|
62
|
+
- Collision debug evaluation is side-effect free (no solver state mutation)
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
- Position IK now applies collision constraints and excluded joint indices consistently with velocity IK
|
|
66
|
+
- Collision constraint pair selection now uses hysteresis across frames for stability
|
|
67
|
+
|
|
68
|
+
## [0.1.1] - 2025-01-09
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
- **PyPI Publishing**: Full wheel building and publishing workflow for TestPyPI and PyPI
|
|
72
|
+
- **`embodik-sanitize-env` CLI**: Helper to sanitize `LD_LIBRARY_PATH` for clean pip installs
|
|
73
|
+
- **`embodik-examples` CLI**: Tool to list and copy examples for pip-installed users
|
|
74
|
+
- **Built-in robot presets**: `panda` and `iiwa` presets work without `robot_presets.yaml`
|
|
75
|
+
- **sdist build support**: Source distribution builds now auto-detect PyPI `pin` wheel's Pinocchio
|
|
76
|
+
|
|
77
|
+
### Changed
|
|
78
|
+
- Simplified `_runtime_deps.py` - removed complex preloading logic, now just provides `import_pinocchio()` helper
|
|
79
|
+
- Documentation updated to recommend `venv + pip + unset LD_LIBRARY_PATH` as primary user flow
|
|
80
|
+
- ViserVisualizer now uses empty GeometryModel instead of None when collisions disabled
|
|
81
|
+
|
|
82
|
+
### Fixed
|
|
83
|
+
- Fixed `KeyError: 'pinocchio/frames/universe'` in ViserVisualizer when `load_collisions=False`
|
|
84
|
+
- Fixed RPATH for `_embodik_impl.so` to correctly find `libembodik_core.so`
|
|
85
|
+
- Fixed sdist builds failing to find Pinocchio by auto-detecting `pin` wheel's CMake config
|
|
86
|
+
- Examples now work correctly for pip-installed users via `embodik-examples --copy`
|
|
87
|
+
|
|
88
|
+
### Dependencies
|
|
89
|
+
- Added `pin>=3.8.0` to build-system requirements for sdist builds
|
|
90
|
+
- Added `pyyaml`, `robot_descriptions`, `viser`, `yourdfpy` to `[examples]` optional dependencies
|
|
91
|
+
|
|
92
|
+
## [0.1.0] - 2025-12-12
|
|
93
|
+
|
|
94
|
+
### Added
|
|
95
|
+
- Initial release of embodiK
|
|
96
|
+
- High-performance inverse kinematics solver with hierarchical task resolution
|
|
97
|
+
- Python bindings using nanobind
|
|
98
|
+
- Support for multiple task types (FrameTask, PostureTask, COMTask, JointTask, MultiJointTask)
|
|
99
|
+
- Position and velocity IK solving
|
|
100
|
+
- Optional visualization tools using Viser
|
|
101
|
+
- Comprehensive test suite
|
|
102
|
+
- Example scripts demonstrating various use cases
|
|
103
|
+
|
|
104
|
+
### Technical Details
|
|
105
|
+
- C++17 core library built on Pinocchio and Eigen3
|
|
106
|
+
- Python 3.8+ support
|
|
107
|
+
- Linux x86_64 support
|
|
108
|
+
- CMake-based build system
|
|
109
|
+
- scikit-build-core for Python packaging
|
embodik-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: embodik
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: High-performance inverse kinematics solver optimized for cross-embodiment VLA/AI applications
|
|
5
|
+
Keywords: robotics,inverse-kinematics,optimization,motion-planning
|
|
6
|
+
Author-Email: Andy Park <andypark.purdue@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: C++
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Project-URL: Homepage, https://github.com/embodik/embodik
|
|
21
|
+
Project-URL: Repository, https://github.com/embodik/embodik
|
|
22
|
+
Project-URL: Documentation, https://embodik.readthedocs.io
|
|
23
|
+
Project-URL: Bug Reports, https://github.com/embodik/embodik/issues
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: numpy>=1.26.0
|
|
26
|
+
Requires-Dist: pin>=3.8.0
|
|
27
|
+
Provides-Extra: visualization
|
|
28
|
+
Requires-Dist: viser>=0.1.0; extra == "visualization"
|
|
29
|
+
Requires-Dist: trimesh>=3.0.0; extra == "visualization"
|
|
30
|
+
Provides-Extra: visualization-legacy
|
|
31
|
+
Requires-Dist: viser>=0.1.0; extra == "visualization-legacy"
|
|
32
|
+
Requires-Dist: yourdfpy>=0.0.52; extra == "visualization-legacy"
|
|
33
|
+
Provides-Extra: examples
|
|
34
|
+
Requires-Dist: pyyaml>=6.0; extra == "examples"
|
|
35
|
+
Requires-Dist: robot_descriptions>=1.0.0; extra == "examples"
|
|
36
|
+
Requires-Dist: viser>=0.1.0; extra == "examples"
|
|
37
|
+
Requires-Dist: yourdfpy>=0.0.52; extra == "examples"
|
|
38
|
+
Provides-Extra: gpu
|
|
39
|
+
Requires-Dist: casadi>=3.6.0; extra == "gpu"
|
|
40
|
+
Requires-Dist: torch>=2.0.0; extra == "gpu"
|
|
41
|
+
Provides-Extra: gpu-collision
|
|
42
|
+
Requires-Dist: warp-lang>=1.0.0; extra == "gpu-collision"
|
|
43
|
+
Provides-Extra: dev
|
|
44
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
45
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
46
|
+
Requires-Dist: black>=24.0; extra == "dev"
|
|
47
|
+
Requires-Dist: isort>=5.13.0; extra == "dev"
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
|
|
50
|
+
# EmbodiK: Cross-Embodiment Inverse Kinematics with Nanobind
|
|
51
|
+
|
|
52
|
+
EmbodiK is a high-performance inverse kinematics (IK) library for cross-embodiment VLA/AI applications.
|
|
53
|
+
|
|
54
|
+
- The core is implemented in C++, with Python bindings created using Nanobind.
|
|
55
|
+
- EmbodiK delivers robust and high-performance IK behaviors, particularly optimized for humanoid robots and AI/VLA integrations.
|
|
56
|
+
- The name "EmbodiK" highlights its focus on supporting various kinematic structures across different embodiment types.
|
|
57
|
+
- The library handles diverse constraint types, supporting both single-task and multi-task velocity IK solvers.
|
|
58
|
+
- Advanced inverse methods provide singularity-robustness.
|
|
59
|
+
- Features include self-collision avoidance and interactive 3D visualization tools.
|
|
60
|
+
|
|
61
|
+
**Author:** Andy Park <andypark.purdue@gmail.com>
|
|
62
|
+
|
|
63
|
+
## Features
|
|
64
|
+
|
|
65
|
+
- **High Performance**: C++ core with optimized Eigen linear algebra
|
|
66
|
+
- **Python Integration**: Seamless numpy array support via Nanobind
|
|
67
|
+
- **Multiple Solvers**: Single-step and full multi-task velocity IK
|
|
68
|
+
- **Singularity Robust**: Advanced inverse methods for stable solutions
|
|
69
|
+
- **Constraint Support**: Joint limits and operational space constraints
|
|
70
|
+
- **Collision Avoidance**: Self-collision detection and avoidance
|
|
71
|
+
- **Visualization**: Interactive 3D visualization with Viser
|
|
72
|
+
- **Robot Models**: Built-in support for common robots (Panda, IIWA)
|
|
73
|
+
- **GPU Acceleration**: Batched velocity IK via CusADi for massive parallelism (100-500x speedup)
|
|
74
|
+
|
|
75
|
+
## Installation
|
|
76
|
+
|
|
77
|
+
### Option A: Fresh Environment (No existing Pinocchio)
|
|
78
|
+
|
|
79
|
+
If you don't have Pinocchio/Boost installed locally, installation is straightforward:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
python3 -m venv .venv
|
|
83
|
+
source .venv/bin/activate
|
|
84
|
+
pip install -U pip
|
|
85
|
+
|
|
86
|
+
# Install build dependencies and Pinocchio
|
|
87
|
+
pip install pin scikit-build-core nanobind cmake ninja
|
|
88
|
+
|
|
89
|
+
# Set CMAKE_PREFIX_PATH and install
|
|
90
|
+
export CMAKE_PREFIX_PATH=$(python -c "import pinocchio, pathlib; print(pathlib.Path(pinocchio.__file__).resolve().parents[4])")
|
|
91
|
+
pip install --no-build-isolation embodik
|
|
92
|
+
|
|
93
|
+
# Verify
|
|
94
|
+
python -c "import embodik; print(embodik.__version__, embodik.RobotModel)"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Option B: Robotics Environment (Existing Pinocchio/ROS)
|
|
98
|
+
|
|
99
|
+
If you have local Pinocchio/Boost builds (e.g., from source or ROS), you **must** clear conflicting paths first:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
python3 -m venv .venv
|
|
103
|
+
source .venv/bin/activate
|
|
104
|
+
pip install -U pip
|
|
105
|
+
|
|
106
|
+
# IMPORTANT: Clear local Pinocchio paths to avoid library conflicts
|
|
107
|
+
unset LD_LIBRARY_PATH CMAKE_PREFIX_PATH pinocchio_DIR
|
|
108
|
+
|
|
109
|
+
# Install build dependencies and Pinocchio from PyPI
|
|
110
|
+
pip install pin scikit-build-core nanobind cmake ninja
|
|
111
|
+
|
|
112
|
+
# Set CMAKE_PREFIX_PATH to the PyPI pin package
|
|
113
|
+
export CMAKE_PREFIX_PATH=$(python -c "import pinocchio, pathlib; print(pathlib.Path(pinocchio.__file__).resolve().parents[4])")
|
|
114
|
+
|
|
115
|
+
# Install embodik
|
|
116
|
+
pip install --no-build-isolation embodik
|
|
117
|
+
|
|
118
|
+
# Verify
|
|
119
|
+
python -c "import embodik; print(embodik.__version__, embodik.RobotModel)"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Running Examples
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
pip install "embodik[examples]"
|
|
126
|
+
embodik-examples --copy
|
|
127
|
+
cd embodik_examples
|
|
128
|
+
python 01_basic_ik_simple.py --robot panda
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Troubleshooting
|
|
132
|
+
|
|
133
|
+
| Error | Cause | Fix |
|
|
134
|
+
|-------|-------|-----|
|
|
135
|
+
| `ImportError: libboost_*.so...` | `LD_LIBRARY_PATH` points to local Pinocchio | `unset LD_LIBRARY_PATH` |
|
|
136
|
+
| `CMake cannot find pinocchio` | Build can't find Pinocchio config | Set `CMAKE_PREFIX_PATH` (see above) |
|
|
137
|
+
| `Cannot import scikit_build_core` | Missing build deps with `--no-build-isolation` | `pip install scikit-build-core nanobind cmake ninja` |
|
|
138
|
+
|
|
139
|
+
### For Developers
|
|
140
|
+
|
|
141
|
+
See [docs/installation.md](docs/installation.md) for development setup with Pixi.
|
|
142
|
+
|
|
143
|
+
See [PUBLISHING.md](PUBLISHING.md) for wheel building and PyPI publishing.
|
|
144
|
+
|
|
145
|
+
## Quick Start
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
import embodik
|
|
149
|
+
import numpy as np
|
|
150
|
+
|
|
151
|
+
# Load robot model from URDF
|
|
152
|
+
robot = embodik.RobotModel("path/to/robot.urdf", floating_base=False)
|
|
153
|
+
|
|
154
|
+
# Create kinematics solver
|
|
155
|
+
solver = embodik.KinematicsSolver(robot)
|
|
156
|
+
|
|
157
|
+
# Add a frame task for end-effector control
|
|
158
|
+
frame_task = solver.add_frame_task("ee_task", "end_effector")
|
|
159
|
+
frame_task.priority = 0
|
|
160
|
+
frame_task.weight = 1.0
|
|
161
|
+
|
|
162
|
+
# Set target velocity (6D: 3 linear + 3 angular)
|
|
163
|
+
target_velocity = np.array([0.1, 0.0, 0.0, 0.0, 0.0, 0.0])
|
|
164
|
+
frame_task.set_target_velocity(target_velocity)
|
|
165
|
+
|
|
166
|
+
# Solve velocity IK
|
|
167
|
+
q = np.zeros(robot.nq)
|
|
168
|
+
result = solver.solve_velocity(q, apply_limits=True)
|
|
169
|
+
|
|
170
|
+
if result.status == embodik.SolverStatus.SUCCESS:
|
|
171
|
+
print(f"Joint velocities: {result.joint_velocities}")
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## API Overview
|
|
175
|
+
|
|
176
|
+
### High-Level API (Recommended)
|
|
177
|
+
|
|
178
|
+
EmbodiK provides a high-level API built on top of Pinocchio for easy robot modeling and IK solving:
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
import embodik
|
|
182
|
+
import numpy as np
|
|
183
|
+
|
|
184
|
+
# Create robot model
|
|
185
|
+
robot = embodik.RobotModel("robot.urdf", floating_base=False)
|
|
186
|
+
|
|
187
|
+
# Create solver
|
|
188
|
+
solver = embodik.KinematicsSolver(robot)
|
|
189
|
+
|
|
190
|
+
# Add tasks
|
|
191
|
+
frame_task = solver.add_frame_task("task1", "end_effector")
|
|
192
|
+
posture_task = solver.add_posture_task("posture")
|
|
193
|
+
|
|
194
|
+
# Configure tasks
|
|
195
|
+
frame_task.priority = 0
|
|
196
|
+
frame_task.weight = 1.0
|
|
197
|
+
posture_task.priority = 1
|
|
198
|
+
posture_task.weight = 0.1
|
|
199
|
+
|
|
200
|
+
# Solve
|
|
201
|
+
q = np.zeros(robot.nq)
|
|
202
|
+
result = solver.solve_velocity(q, apply_limits=True)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Low-Level API
|
|
206
|
+
|
|
207
|
+
For advanced users, EmbodiK also provides low-level multi-task velocity IK functions:
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
import embodik as eik
|
|
211
|
+
import numpy as np
|
|
212
|
+
|
|
213
|
+
# Multiple tasks with constraints
|
|
214
|
+
goals = [np.array([0.1, -0.2]), np.array([0.3])]
|
|
215
|
+
jacobians = [
|
|
216
|
+
np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]),
|
|
217
|
+
np.array([[0.0, 0.0, 1.0]])
|
|
218
|
+
]
|
|
219
|
+
|
|
220
|
+
# Constraint matrix and limits
|
|
221
|
+
C = np.eye(3)
|
|
222
|
+
lower = np.array([-1e6, -1e6, -1e6])
|
|
223
|
+
upper = np.array([1e6, 1e6, 1e6])
|
|
224
|
+
|
|
225
|
+
params = {
|
|
226
|
+
"epsilon": 1e-6,
|
|
227
|
+
"regularization_factor": 1e-1,
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
result = eik.solve_velocity_ik_multi_task_np(
|
|
231
|
+
goals, jacobians, C, lower, upper, params
|
|
232
|
+
)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Examples
|
|
236
|
+
|
|
237
|
+
The repository includes several example scripts:
|
|
238
|
+
|
|
239
|
+
| Script | Description |
|
|
240
|
+
|--------|-------------|
|
|
241
|
+
| `01_basic_ik_simple.py` | Basic IK solving with interactive visualization |
|
|
242
|
+
| `02_collision_aware_IK.py` | Collision-aware IK with self-collision avoidance + GPU benchmark panel |
|
|
243
|
+
| `04_gpu_batch_ik.py` | GPU-accelerated batched velocity IK benchmark |
|
|
244
|
+
| `05_gpu_collision_batch.py` | GPU-accelerated batch collision detection |
|
|
245
|
+
| `06_gpu_solver_demo.py` | Comprehensive GPU solver demonstration and benchmark |
|
|
246
|
+
| `07_parallel_trajectory_tracking.py` | **100 robots** tracking different trajectories in parallel (GPU demo) |
|
|
247
|
+
| `robot_model_example.py` | Robot model usage and configuration |
|
|
248
|
+
| `visualization_example.py` | Interactive 3D visualization examples |
|
|
249
|
+
| `scripts/benchmark_fi_pesns.py` | FI-PeSNS vs CPU accuracy and performance benchmark |
|
|
250
|
+
|
|
251
|
+
### Running Examples
|
|
252
|
+
|
|
253
|
+
**For pip-installed users:**
|
|
254
|
+
```bash
|
|
255
|
+
# Install with example dependencies
|
|
256
|
+
pip install embodik[examples]
|
|
257
|
+
|
|
258
|
+
# Copy examples to a local directory
|
|
259
|
+
embodik-examples --copy
|
|
260
|
+
|
|
261
|
+
# Run examples
|
|
262
|
+
cd embodik_examples
|
|
263
|
+
python 01_basic_ik_simple.py --robot panda
|
|
264
|
+
python 02_collision_aware_IK.py --robot panda
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**For developers (from repository):**
|
|
268
|
+
```bash
|
|
269
|
+
# Install example dependencies
|
|
270
|
+
pixi run install
|
|
271
|
+
|
|
272
|
+
# Run basic IK example
|
|
273
|
+
pixi run python examples/01_basic_ik_simple.py
|
|
274
|
+
|
|
275
|
+
# Run collision-aware IK example
|
|
276
|
+
pixi run python examples/02_collision_aware_IK.py --robot panda
|
|
277
|
+
|
|
278
|
+
# Run GPU examples (requires cuda environment)
|
|
279
|
+
pixi run -e cuda demo-gpu # GPU solver benchmark
|
|
280
|
+
pixi run -e cuda demo-ik-gpu # Interactive IK with GPU panel
|
|
281
|
+
pixi run -e cuda benchmark-gpu # Batch IK benchmark
|
|
282
|
+
pixi run -e cuda benchmark-collision # Collision detection benchmark
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
See the [Examples Documentation](docs/examples/index.md) for detailed guides.
|
|
286
|
+
|
|
287
|
+
## GPU Acceleration
|
|
288
|
+
|
|
289
|
+
EmbodiK supports GPU-accelerated batched velocity IK solving for massive parallelism, ideal for:
|
|
290
|
+
|
|
291
|
+
- **RL Training**: 4096+ parallel environments in Isaac Gym/Orbit
|
|
292
|
+
- **Motion Planning**: Batch trajectory validation
|
|
293
|
+
- **Dataset Generation**: Offline batch processing
|
|
294
|
+
|
|
295
|
+
### Performance
|
|
296
|
+
|
|
297
|
+
| Batch Size | CPU Sequential | GPU Batched | Speedup | Per-Sample | Constraint Sat |
|
|
298
|
+
|------------|----------------|-------------|---------|------------|----------------|
|
|
299
|
+
| 100 | 3.3 ms | 1.6 ms | **2x** | 16 µs | 100% |
|
|
300
|
+
| 1,000 | 29 ms | 3.1 ms | **9x** | 3 µs | 100% |
|
|
301
|
+
| 10,000 | 300 ms | 15 ms | **20x** | 1.5 µs | 100% |
|
|
302
|
+
|
|
303
|
+
*Benchmarks on NVIDIA RTX A2000 8GB. FI-PeSNS solver with k_max=12, 7-DOF robot, 6D task.*
|
|
304
|
+
|
|
305
|
+
**Key Results:**
|
|
306
|
+
- **~670,000 IK solves/second** at batch size 10,000
|
|
307
|
+
- **100% constraint satisfaction** with zero violations
|
|
308
|
+
- Speedup scales with batch size due to GPU parallelism
|
|
309
|
+
|
|
310
|
+
### Quick Start (GPU)
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
from embodik import solve_velocity_batched
|
|
314
|
+
|
|
315
|
+
# Batch of IK problems (e.g., 1000 parallel environments)
|
|
316
|
+
result = solve_velocity_batched(
|
|
317
|
+
targets_batch, # List of (task_dim,) arrays
|
|
318
|
+
jacobians_batch, # List of (task_dim, n_dof) arrays
|
|
319
|
+
constraints_batch, # List of (n_dof, n_dof) arrays
|
|
320
|
+
lower_bounds_batch,
|
|
321
|
+
upper_bounds_batch,
|
|
322
|
+
use_gpu=True,
|
|
323
|
+
casadi_path="path/to/fn_velocity_solve.casadi"
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
velocities = result.velocities # (batch_size, n_dof)
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Setup
|
|
330
|
+
|
|
331
|
+
1. **Install CUDA environment:**
|
|
332
|
+
```bash
|
|
333
|
+
cd embodik
|
|
334
|
+
pixi install -e cuda
|
|
335
|
+
pixi run -e cuda install # Install embodik in cuda env
|
|
336
|
+
pixi run -e cuda check-cuda # Verify PyTorch CUDA
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
2. **Install CusADi (one-time):**
|
|
340
|
+
```bash
|
|
341
|
+
pixi run -e cuda install-cusadi # Clones to ~/.local/cusadi and installs
|
|
342
|
+
pixi run -e cuda check-gpu # Verify all GPU components
|
|
343
|
+
# Output: CasADi: True, CusADi: True, CUDA: True
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
3. **Export and compile CasADi function:**
|
|
347
|
+
```bash
|
|
348
|
+
# Export symbolic function
|
|
349
|
+
pixi run -e cuda export-casadi
|
|
350
|
+
|
|
351
|
+
# Compile to CUDA kernel
|
|
352
|
+
mv fn_velocity_solve.casadi ~/.local/cusadi/src/casadi_functions/
|
|
353
|
+
cd ~/.local/cusadi
|
|
354
|
+
python run_codegen.py --fn=fn_velocity_solve
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
4. **Run GPU demos:**
|
|
358
|
+
```bash
|
|
359
|
+
pixi run -e cuda demo-gpu # Comprehensive benchmark
|
|
360
|
+
pixi run -e cuda demo-ik-gpu # Interactive IK with GPU panel
|
|
361
|
+
pixi run -e cuda benchmark-gpu # Batch IK benchmark
|
|
362
|
+
pixi run -e cuda benchmark-collision # Collision benchmark
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Available GPU Tasks
|
|
366
|
+
|
|
367
|
+
| Task | Description |
|
|
368
|
+
|------|-------------|
|
|
369
|
+
| `pixi run -e cuda check-cuda` | Verify PyTorch CUDA availability |
|
|
370
|
+
| `pixi run -e cuda check-gpu` | Verify CasADi + CusADi + CUDA |
|
|
371
|
+
| `pixi run -e cuda install-cusadi` | Install CusADi from GitHub |
|
|
372
|
+
| `pixi run -e cuda export-casadi` | Export FI-PeSNS velocity solve function |
|
|
373
|
+
| `pixi run -e cuda demo-gpu` | Run GPU solver demo/benchmark |
|
|
374
|
+
| `pixi run -e cuda demo-ik-gpu` | Interactive IK with GPU benchmark panel |
|
|
375
|
+
| `pixi run -e cuda benchmark-gpu` | Batch IK performance benchmark |
|
|
376
|
+
| `pixi run -e cuda benchmark-gpu-batched` | GPU batched IK benchmark (100/1000/10000) |
|
|
377
|
+
| `pixi run -e cuda benchmark-fi-pesns` | FI-PeSNS vs CPU accuracy benchmark |
|
|
378
|
+
| `pixi run -e cuda benchmark-collision` | Collision detection benchmark |
|
|
379
|
+
| `pixi run -e cuda demo-parallel-tracking` | 100 robots tracking trajectories in parallel |
|
|
380
|
+
| `pixi run -e cuda test-gpu` | Run GPU-specific tests |
|
|
381
|
+
|
|
382
|
+
### FI-PeSNS: Fixed-Iteration Penalized eSNS
|
|
383
|
+
|
|
384
|
+
EmbodiK includes **FI-PeSNS**, a GPU-optimized variant of the eSNS algorithm that trades exact constraint saturation for simpler, parallelizable penalty-based enforcement:
|
|
385
|
+
|
|
386
|
+
**Key Features:**
|
|
387
|
+
- **SRINV**: Singularity-Robust Inverse for numerical stability
|
|
388
|
+
- **Analytical Scaling**: Computes feasible task scales without iterative saturation
|
|
389
|
+
- **Penalty Gradient**: Nudges solution toward feasibility each iteration
|
|
390
|
+
- **Fixed Iterations**: Predictable compute time, ideal for real-time RL
|
|
391
|
+
|
|
392
|
+
**Algorithm:**
|
|
393
|
+
```
|
|
394
|
+
for i in range(k_max):
|
|
395
|
+
P = I # Reset projector
|
|
396
|
+
for each task:
|
|
397
|
+
J_pinv = srinv(J @ P)
|
|
398
|
+
delta = J_pinv @ (target - J @ dq)
|
|
399
|
+
scale = get_feasible_scale(...)
|
|
400
|
+
dq += scale * delta
|
|
401
|
+
P -= J_pinv @ J @ P
|
|
402
|
+
|
|
403
|
+
# Penalty nudge toward feasibility
|
|
404
|
+
violation = max(0, max(lower - C@dq, C@dq - upper))
|
|
405
|
+
dq += eta * mu * C.T @ grad_violation
|
|
406
|
+
mu *= gamma # Ramp penalty
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
**Benchmark (7-DOF Panda, 6D task):**
|
|
410
|
+
|
|
411
|
+
| Mode | Batch | Time | Per-Sample | Max Violation | Constraint Sat |
|
|
412
|
+
|------|-------|------|------------|---------------|----------------|
|
|
413
|
+
| CPU Sequential | 100 | 3.3 ms | 33 µs | 0.0 | 100% |
|
|
414
|
+
| CPU Sequential | 1,000 | 29 ms | 29 µs | 0.0 | 100% |
|
|
415
|
+
| **GPU Batched** | 100 | 1.6 ms | 16 µs | 0.0 | 100% |
|
|
416
|
+
| **GPU Batched** | 1,000 | 3.1 ms | 3 µs | 0.0 | 100% |
|
|
417
|
+
| **GPU Batched** | 10,000 | 15 ms | 1.5 µs | 0.0 | 100% |
|
|
418
|
+
|
|
419
|
+
*GPU benchmarks on NVIDIA RTX A2000 8GB with CusADi-compiled CUDA kernels.*
|
|
420
|
+
|
|
421
|
+
### Parallel Trajectory Tracking Demo
|
|
422
|
+
|
|
423
|
+
Visualize GPU parallelization with 100 robot instances simultaneously tracking different trajectories:
|
|
424
|
+
|
|
425
|
+
```bash
|
|
426
|
+
# Run the interactive demo (requires viser)
|
|
427
|
+
pixi run -e cuda demo-parallel-tracking
|
|
428
|
+
|
|
429
|
+
# Run benchmark only (no visualization)
|
|
430
|
+
pixi run -e cuda demo-parallel-tracking-benchmark
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
Each robot tracks a unique trajectory (circles, figure-8s, spirals, hearts) while the GPU solver computes all 100 IK solutions in parallel. With GPU acceleration, this achieves **~50,000+ IK solves/second**.
|
|
434
|
+
|
|
435
|
+
**Usage:**
|
|
436
|
+
```python
|
|
437
|
+
from embodik.gpu.casadi_fi_pesns import build_fi_pesns_single_task
|
|
438
|
+
|
|
439
|
+
# Build solver
|
|
440
|
+
fn = build_fi_pesns_single_task(
|
|
441
|
+
n_dof=7, task_dim=6, n_constraints=7,
|
|
442
|
+
k_max=10, # Fixed iterations
|
|
443
|
+
mu0=1e-2, # Initial penalty
|
|
444
|
+
gamma=2.0, # Penalty growth
|
|
445
|
+
eta=0.1, # Gradient step
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
# Solve
|
|
449
|
+
velocity, scales = fn(target, jacobian.flatten(), C, lower, upper)
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
**Export for CusADi:**
|
|
453
|
+
```bash
|
|
454
|
+
# Export FI-PeSNS for CusADi compilation
|
|
455
|
+
pixi run -e cuda python -m embodik.gpu.export_casadi_velocity_solve \
|
|
456
|
+
--robot panda --k_max 10 \
|
|
457
|
+
--out fn_velocity_solve.casadi
|
|
458
|
+
|
|
459
|
+
# Compile to CUDA kernel
|
|
460
|
+
mv fn_velocity_solve.casadi ~/.local/cusadi/src/casadi_functions/
|
|
461
|
+
cd ~/.local/cusadi && python run_codegen.py --fn=fn_velocity_solve
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### GPU Collision Detection (Experimental)
|
|
465
|
+
|
|
466
|
+
EmbodiK also supports GPU-accelerated collision detection via NVIDIA Warp:
|
|
467
|
+
|
|
468
|
+
```python
|
|
469
|
+
from embodik.gpu.warp_collision import compute_collision_distances_batched
|
|
470
|
+
|
|
471
|
+
# Batch collision queries
|
|
472
|
+
result = compute_collision_distances_batched(
|
|
473
|
+
robot_model,
|
|
474
|
+
q_batch, # (batch_size, n_dof) configurations
|
|
475
|
+
use_gpu=True
|
|
476
|
+
)
|
|
477
|
+
distances = result.distances # (batch_size,) minimum distances
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
See [docs/installation.md](docs/installation.md) for detailed GPU setup instructions.
|
|
481
|
+
|
|
482
|
+
## Testing
|
|
483
|
+
|
|
484
|
+
```bash
|
|
485
|
+
# Run all tests
|
|
486
|
+
pixi run test
|
|
487
|
+
|
|
488
|
+
# Run tests with verbose output
|
|
489
|
+
pixi run test-verbose
|
|
490
|
+
|
|
491
|
+
# Run tests with coverage
|
|
492
|
+
pixi run test-cov
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
## Architecture
|
|
496
|
+
|
|
497
|
+
```
|
|
498
|
+
embodik/
|
|
499
|
+
├── cpp_core/ # C++ core implementation
|
|
500
|
+
│ ├── include/embodik/ # Header files
|
|
501
|
+
│ └── src/ # Implementation files
|
|
502
|
+
├── python_bindings/ # Nanobind C++ bindings
|
|
503
|
+
│ └── src/ # Binding code
|
|
504
|
+
├── python/embodik/ # Python package
|
|
505
|
+
│ ├── utils.py # Utility functions
|
|
506
|
+
│ └── visualization.py # Visualization support
|
|
507
|
+
├── examples/ # Example scripts
|
|
508
|
+
│ ├── 01_basic_ik_simple.py
|
|
509
|
+
│ ├── 02_collision_aware_IK.py
|
|
510
|
+
│ └── robot_models/ # Robot URDF files
|
|
511
|
+
├── docs/ # Documentation (MkDocs)
|
|
512
|
+
└── test/ # Test suite
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
## Documentation
|
|
516
|
+
|
|
517
|
+
Full documentation is available at: **https://embodik.github.io/embodik/**
|
|
518
|
+
|
|
519
|
+
- [Installation Guide](docs/installation.md) - Detailed installation instructions
|
|
520
|
+
- [Quickstart](docs/quickstart.md) - Get started in 5 minutes
|
|
521
|
+
- [API Reference](docs/api/index.md) - Complete API documentation
|
|
522
|
+
- [Examples](docs/examples/index.md) - Example code and tutorials
|
|
523
|
+
- [Development Guide](docs/development.md) - Contributing and development
|
|
524
|
+
|
|
525
|
+
## Contributing
|
|
526
|
+
|
|
527
|
+
We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
528
|
+
|
|
529
|
+
Key principles:
|
|
530
|
+
1. Follow the existing code style
|
|
531
|
+
2. Add tests for new functionality
|
|
532
|
+
3. Ensure numerical accuracy and stability
|
|
533
|
+
4. Update documentation for API changes
|
|
534
|
+
|
|
535
|
+
## License
|
|
536
|
+
|
|
537
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
538
|
+
|
|
539
|
+
**Copyright (c) 2025 Andy Park <andypark.purdue@gmail.com>**
|
|
540
|
+
|
|
541
|
+
The MIT License is a permissive license that allows for:
|
|
542
|
+
- Commercial use
|
|
543
|
+
- Modification
|
|
544
|
+
- Distribution
|
|
545
|
+
- Private use
|
|
546
|
+
|
|
547
|
+
While providing liability protection for the authors. This makes it ideal for open-source projects that want to encourage widespread adoption and contribution.
|
|
548
|
+
|