|
| 1 | +# Momentum AI Assistant Guide |
| 2 | + |
| 3 | +Momentum is a C++ library for human kinematic motion, character representation, |
| 4 | +and numerical optimization solvers. The repository also contains PyMomentum, |
| 5 | +the Python bindings and Python utilities built on top of the C++ library. |
| 6 | + |
| 7 | +This guide is for AI coding agents working in the public repository. Keep future |
| 8 | +instructions codebase-focused and self-contained: use public paths, public |
| 9 | +commands, and public documentation. Do not add private organization-specific |
| 10 | +workflow, review, source-control, or infrastructure rules here. |
| 11 | + |
| 12 | +For end-user installation, building from source, and the contribution workflow, |
| 13 | +see `README.md` and `CONTRIBUTING.md`. |
| 14 | + |
| 15 | +## Repository Map |
| 16 | + |
| 17 | +- `momentum/` - C++ core library. |
| 18 | + - `common/` - exceptions, checks, logging, shared utilities. |
| 19 | + - `math/` - transforms, meshes, random utilities, numerical helpers. |
| 20 | + - `character/` - skeletons, characters, skinning, collision geometry. |
| 21 | + - `solver/` - generic solver framework. |
| 22 | + - `character_solver/` - character-specific inverse kinematics solvers. |
| 23 | + - `character_solver_simd/` - SIMD-accelerated solver error functions. |
| 24 | + - `character_sequence_solver/` - multi-frame sequence solvers. |
| 25 | + - `diff_ik/` - differentiable inverse kinematics support. |
| 26 | + - `simd/` - SIMD helpers and abstractions shared by the compute paths. |
| 27 | + - `io/` - file I/O including FBX, glTF, URDF, C3D, and related formats. |
| 28 | + - `marker_tracking/`, `rasterizer/`, `camera/`, `gui/` - application-facing |
| 29 | + support libraries. |
| 30 | + - `test/` - C++ unit tests and test helpers. |
| 31 | + - `examples/`, `tutorials/` - example applications and tutorials. |
| 32 | + - `website/` - documentation site sources. |
| 33 | +- `pymomentum/` - Python bindings and Python modules. |
| 34 | + - `geometry/` - NumPy-oriented character and geometry bindings. |
| 35 | + - `diff_geometry/`, `solver/`, `tensor_momentum/` - PyTorch-backed modules. |
| 36 | + - `solver2/`, `marker_tracking/`, `renderer/`, `camera/`, `axel/` - Python |
| 37 | + extension modules and helpers. |
| 38 | + - `test/` - Python tests. |
| 39 | +- `axel/` - bundled Axel acceleration library (sources under `axel/axel/`). |
| 40 | +- `cmake/` - CMake helper functions and source lists. `cmake/mt_defs.cmake` |
| 41 | + defines the `mt_library`, `mt_test`, and `mt_executable` helpers used |
| 42 | + throughout `CMakeLists.txt`. |
| 43 | +- `scripts/` - wheel, packaging, and CI helper scripts. |
| 44 | +- `.github/workflows/` - GitHub Actions CI, nightly, wheel, and docs workflows. |
| 45 | +- `CMakeLists.txt`, `pixi.toml`, `pyproject.toml` - top-level build, task, and |
| 46 | + Python packaging entry points. |
| 47 | + |
| 48 | +## Build And Test |
| 49 | + |
| 50 | +Use Pixi tasks for normal development. Dependencies install automatically on the |
| 51 | +first run. |
| 52 | + |
| 53 | +```bash |
| 54 | +pixi run build # Release C++ build, with Python bindings enabled |
| 55 | +pixi run build_dev # Debug C++ build |
| 56 | +pixi run test # Release C++ tests |
| 57 | +pixi run test_dev # Debug C++ tests |
| 58 | +pixi run test_verbose # Release C++ tests with verbose output |
| 59 | +pixi run build_py # Build Python bindings |
| 60 | +pixi run test_py # Python tests |
| 61 | +pixi run lint # Format C++ code with clang-format |
| 62 | +pixi run lint-check # Check C++ formatting |
| 63 | +pixi task list # Show all available tasks |
| 64 | +``` |
| 65 | + |
| 66 | +Useful environment-specific commands: |
| 67 | + |
| 68 | +```bash |
| 69 | +pixi run -e py313 build_py |
| 70 | +pixi run -e py313 test_py |
| 71 | +pixi run -e gpu build_py |
| 72 | +``` |
| 73 | + |
| 74 | +Windows developers can use `pixi run open_vs` to open the configured Visual |
| 75 | +Studio project. |
| 76 | + |
| 77 | +## Platform Notes |
| 78 | + |
| 79 | +- macOS builds are supported on both Intel and Apple Silicon. |
| 80 | +- On Linux the FBX SDK is downloaded automatically during environment setup |
| 81 | + (the `install_fbxsdk` task). |
| 82 | +- FBX I/O is available on Linux, macOS, and Windows (x86_64); USD I/O requires |
| 83 | + the optional USD dependencies. |
| 84 | +- SIMD-accelerated paths target x86_64 (AVX2/FMA); other architectures such as |
| 85 | + ARM fall back to scalar implementations. |
| 86 | + |
| 87 | +## Source Lists And Generated Files |
| 88 | + |
| 89 | +- When adding, removing, or renaming C++ files under `momentum/`, update |
| 90 | + `cmake/build_variables.bzl`. CMake reads these lists through |
| 91 | + `cmake/mt_defs.cmake`. |
| 92 | +- When adding, removing, or renaming PyMomentum C++ binding files, update |
| 93 | + `pymomentum/cmake/build_variables.bzl`. |
| 94 | +- When adding new public C++ classes that need forward declarations, update |
| 95 | + `momentum/gen_fwd_input.toml`. The per-module `fwd.h` files are generated from |
| 96 | + it — each class gets `_p`/`_u`/`_w` (and `_const_*`) smart-pointer aliases. Do |
| 97 | + not hand-edit `fwd.h`; change the TOML source instead. |
| 98 | +- When changing PyPI packaging, edit `pyproject-pypi.toml.j2` and regenerate the |
| 99 | + derived files with `pixi run generate_pyproject`. |
| 100 | +- Do not hand-edit generated build or packaging outputs when a source template |
| 101 | + exists. |
| 102 | + |
| 103 | +## C++ Conventions |
| 104 | + |
| 105 | +- Follow the C++ style guide in the developer guide on the documentation site: |
| 106 | + https://facebookresearch.github.io/momentum/docs_cpp/developer_guide/style_guide |
| 107 | +- Use Doxygen-style `///` comments in public headers. Use `@param` and `@return` |
| 108 | + tags, and document new public classes, structs, and functions. |
| 109 | +- Use `camelCase` for functions, variables, and members; `PascalCase` for class |
| 110 | + names; `ALL_CAPS` for macros; `snake_case` for files and directories; and a |
| 111 | + trailing underscore for private members. |
| 112 | +- Write abbreviations in `PascalCase` too, e.g. `Fbx` and `Gltf`, not `FBX` or |
| 113 | + `GLTF`. |
| 114 | +- Prefer early return, `continue`, or `break` over deeply nested control flow. |
| 115 | +- Prefer `std::span` for read-only or mutable contiguous ranges accepted by |
| 116 | + function parameters. |
| 117 | +- Use `MT_THROW("message: {}", value)` for exceptions and `MT_CHECK(cond, ...)` |
| 118 | + for runtime assertions, both from `<momentum/common/exception.h>`. |
| 119 | +- Use `momentum::pi<T>()` and `momentum::twopi<T>()` from |
| 120 | + `<momentum/math/constants.h>` instead of `M_PI` for Windows compatibility. |
| 121 | +- Include ordering: |
| 122 | + 1. Corresponding header. |
| 123 | + 2. Momentum headers. |
| 124 | + 3. Third-party headers. |
| 125 | + 4. Standard library headers. |
| 126 | +- Public headers should include Momentum headers with angle brackets, for |
| 127 | + example `#include <momentum/common/checks.h>`. Implementation files usually |
| 128 | + include local Momentum headers with quotes. |
| 129 | + |
| 130 | +## PyMomentum Conventions |
| 131 | + |
| 132 | +- Python-facing argument names use `snake_case`, even when the C++ API uses |
| 133 | + `camelCase`. |
| 134 | +- Bind multi-dimensional Eigen inputs as `pybind11::array_t<float>` to avoid |
| 135 | + NumPy row-major versus Eigen column-major confusion. One-dimensional vectors |
| 136 | + can use pybind11 Eigen conversion. |
| 137 | +- For quaternion inputs and outputs, include |
| 138 | + `pymomentum/python_utility/eigen_quaternion.h`; the Python format is |
| 139 | + `[x, y, z, w]`. |
| 140 | +- For optional Eigen arguments, prefer `std::optional<Eigen::...>` instead of |
| 141 | + default Eigen values in the binding declaration. |
| 142 | +- Use `py::ssize_t`, not POSIX `ssize_t`, in pybind11 code so Windows builds |
| 143 | + compile. |
| 144 | +- For constructors or option structs with multiple arguments, prefer |
| 145 | + `py::kw_only()` plus a lambda-based `py::init` to avoid silent bugs from |
| 146 | + positional argument reordering. |
| 147 | +- Public bindings should have Sphinx-friendly docstrings. Keep `:param:`, |
| 148 | + `:return:`, and cross-reference names aligned with the exposed Python |
| 149 | + argument names. |
| 150 | +- Format Python with `black` and follow PEP 8, including type hints on public |
| 151 | + APIs. |
| 152 | +- `pymomentum.geometry` is NumPy-oriented and should stay suitable for fast |
| 153 | + forward operations, visualization, and non-differentiable workflows. |
| 154 | +- `pymomentum.diff_geometry` and `pymomentum.solver` are PyTorch-backed modules |
| 155 | + for differentiable operations and must respect the supported PyTorch ABI. |
| 156 | +- After changing C++ bindings, rebuild before testing Python: `pixi run |
| 157 | + build_py`. Pure Python changes do not require a rebuild. |
| 158 | + |
| 159 | +## Tests |
| 160 | + |
| 161 | +- Add or update tests with behavior changes. |
| 162 | +- C++ tests live under `momentum/test/`; Python tests live under |
| 163 | + `pymomentum/test/`. |
| 164 | +- Prefer existing test helpers: |
| 165 | + - `createTestCharacter(numJoints)` (minimum 3 joints) from |
| 166 | + `<momentum/test/character/character_helpers.h>` instead of manually |
| 167 | + assembling skeletons, parameter transforms, meshes, locators, and collision |
| 168 | + geometry. |
| 169 | + - `temporaryFile()` and `temporaryDirectory()` from |
| 170 | + `<momentum/test/io/io_helpers.h>` instead of directly using |
| 171 | + `std::filesystem::temp_directory_path()`. |
| 172 | +- Seed random tests deterministically. Prefer a fixture-owned |
| 173 | + `Random<> rng{12345};` from `<momentum/math/random.h>`. When extending an |
| 174 | + older test that already uses the singleton helpers, seed |
| 175 | + `Random<>::GetSingleton()` at the start of each test. Do not use Eigen's |
| 176 | + `Random()` / `UnitRandom()` — they seed from `std::random_device` and produce |
| 177 | + different values every run. |
| 178 | +- For optional Python dependencies, gate the whole `unittest.TestCase` class |
| 179 | + behind an import flag rather than using per-test skip decorators. This keeps |
| 180 | + pytest collection clean when optional dependencies are unavailable. |
| 181 | +- To run a single Python test, enter `pixi shell` and invoke `pytest` directly |
| 182 | + with a `-k` filter. |
| 183 | + |
| 184 | +## Documentation |
| 185 | + |
| 186 | +- Keep code examples out of the `momentum/website/` docs — they go stale. |
| 187 | + Describe the approach and reference a test or example instead; when code is |
| 188 | + unavoidable, prefer pseudocode. |
| 189 | +- Public documentation lives on the docs site: the Python and C++ API references |
| 190 | + and the getting-started guides linked from `README.md`. |
| 191 | + |
| 192 | +## CI And Packaging |
| 193 | + |
| 194 | +- GitHub Actions workflows live in `.github/workflows/`. Keep platform matrices |
| 195 | + intentional and use existing workflow patterns before adding new mechanisms. |
| 196 | +- Wheel builds have three variants: |
| 197 | + - `core` - NumPy/SciPy modules and torch-backed pure Python helpers, without |
| 198 | + Torch C++ extension modules. |
| 199 | + - `cpu` - includes Torch C++ extension modules for CPU PyTorch. |
| 200 | + - `gpu` - includes Torch C++ extension modules for CUDA PyTorch. |
| 201 | +- Build and test wheel variants with: |
| 202 | + |
| 203 | +```bash |
| 204 | +pixi run -e py313 generate_pyproject |
| 205 | +PYMOMENTUM_VARIANT=core pixi run -e py313 wheel_build |
| 206 | +PYMOMENTUM_VARIANT=core pixi run -e py313 wheel_check |
| 207 | +PYMOMENTUM_VARIANT=core pixi run -e py313 wheel_test |
| 208 | +``` |
| 209 | + |
| 210 | +Use `PYMOMENTUM_VARIANT=cpu` or `PYMOMENTUM_VARIANT=gpu` for the other wheel |
| 211 | +families. `wheel_check` validates the generated packaging; `wheel_test` checks |
| 212 | +clean-environment imports and PyTorch import-order compatibility. |
| 213 | + |
| 214 | +## Change Checklist |
| 215 | + |
| 216 | +Before handing off code changes, run the smallest relevant checks first, then a |
| 217 | +broader pass when the change affects shared behavior. |
| 218 | + |
| 219 | +- C++ changes: `pixi run lint`, relevant C++ test target or `pixi run test`. |
| 220 | +- PyMomentum binding changes: `pixi run build_py`, relevant Python tests, then |
| 221 | + `pixi run test_py` when practical. |
| 222 | +- Packaging changes: `pixi run generate_pyproject`, then relevant |
| 223 | + `wheel_build`, `wheel_check`, and `wheel_test` tasks. |
| 224 | +- CI changes: inspect the affected workflow and, when possible, run the command |
| 225 | + the workflow invokes locally. |
0 commit comments