⚡ Caspar
Caspar is a library for GPU-accelerated nonlinear optimization, powered by SymForce. It's designed for Bundle Adjustment (BA) and Structure from Motion (SfM), but transfers well to other problems also. Caspar supports SymForce expressions and types, and achieves state-of-the-art performance (5x to 20x improved runtime, and similar or lower GPU memory) through expression manipulation and code generation optimized for the GPU, as well as careful kernel fusion. Check out the paper on arXiv (and at ICRA 2026), and check out the code in SymForce here. It's also available in COLMAP as one of the optimizers there.
- b3d3073 Minor fix: Add initial score to Caspar SolveResult metrics @tordnat
- 2ee2978 GPU device selection for solver @tordnat
- 202d738 Python bindings opt-out @tordnat
- fa57973 Fix examples + pybinding PascalCase @tordnat
- ce64f16 Replace legacy FindCUDA with modern CMake CUDA language support + minor compile function improvements @tordnat
- e2d8465 Fix non-snake case conversion to pascal case @tordnat
- bdbd9dd Move Caspar out of experimental/ @aaron-skydio
- 7369b24 Make Caspar conform to PascalCase in C++ and snake_case in Python. @emil-martens-skydio
- f0e52ad Added SolveResult Type @emil-martens-skydio
- 0b1b72d Fix Norm2d Namings @emil-martens-skydio
- 7f9fc25 Skip directories when copying runtime files. @B1ueber2y
- ca54a30 Added float64 support to Caspar. @emil-martens-skydio
- e7d1a28 Changes to Caspar @emil-martens-skydio
🚨 Breaking Changes
Dropped support for Python 3.8 and C++14, requirements are now Python 3.9 or newer and C++17 or newer
We also now support SymPy 1.13 and 1.14.
- 82cba17 Deprecate py38 @aaron-skydio
- 83b07f8 Fix Rust printer on sympy 1.14 @aaron-skydio
- b0e5679 Loosen sympy version @aaron-skydio
- 12ddd48 Upgrade sympy to 1.13 @aaron-skydio
- b06b6e7 Use structured bindings @aaron-skydio
- f46d3ab Remove additional C++14 references @aaron-skydio
- 2355e09 Drop C++14 support @aaron-skydio
We no longer build wheels for Intel Macs in CI or publish them to PyPI
- f9420dc Remove intel macos wheels @aaron-skydio
Changed the argument order for Values::LocalCoordinates
to be consistent with other LocalCoordinates functions
- cda3a08 fix Values::LocalCoordinates inversion @dominic-skydio
Removed some deprecated function signatures
Mostly for the Optimizer. These have been deprecated for a while, and have newer equivalents described in the commit:
- 5d20b8a Remove deprecated things @aaron-skydio
CUDA backend header extensions changed to .cuh
These are files containing __device__ functions that can only be compiled as CUDA C++, not as regular C++, so they're correctly marked as .cuh and not .h
- da8a9e4 Generate CUDA headers as .cuh @aaron-skydio
🦾 New Features
📐 Marginalization
Marginalization now comes built into SymForce, at symforce/opt/marginalization.h
- 5f94d97 Performance improvements in MarginalizationFactor relinearization @aaron-skydio
- 4fd4700 Populate the MarginalizationFactor jacobian @aaron-skydio
- 995d1f7 Add serialization for MarginalizationFactor @aaron-skydio
- 75aa725 Move marginalization functions into symforce @aaron-skydio
🌐 Unit3 Type
We've significantly improved the formulation of our Unit3 type (for 3D unit vectors, i.e. elements of S(2)), to be more stable and use a more minimal parameterization. See the commit message and new docstring for more details.
- b1e6089 Small Unit3 Updates @chet-kruse-skydio
- 4b412fd New Unit3 @chet-kruse-skydio
🧑💻 Experimental TypeScript backend
Currently supports codegen of functions, but doesn't have TypeScript Geo and Cam types, so generated functions must convert to vector/matrix/scalar inputs/outputs.
- d9cd898 Add typescript codegen backend @nathan-skydio
🔣 Improvements to lambdify
Lambdify is now imported to sf, so you can use it just as sf.lambdify. It also now supports both the original SymForce lambdify signature (which takes a symbolic function), and SymPy's lambdify signature, which takes a list of inputs and an expression.
- 61f8899 Support sympy-style signature for lambdify @aaron-skydio
- 0300a0f Import symforce.util.lambdify to sf @aaron-skydio
- f9b20cc Fix lambdify for nested lcmtypes @aaron-skydio
Other Small Feature Improvements
- bda9eee Fix Matrix arithmetic with numpy scalars and ndarrays @aaron-skydio
- f2b6920 Add default epsilons in geo_factors_codegen @aaron-skydio
- e37f753 data vs Data for cpp geo and cam types @jianwei-sun-skydio
- c2caa31 Codegen lists of types @jianwei-sun-skydio
- bac2012 Generate Rot2.to_angle @aaron-skydio
- 9098d7e add Values::LocalCoordinates w/o index w/ provided key order @dominic-skydio
- 11a680a add a version of Values::LocalCoordinates without a provided index @dominic-skydio
- d6afc27 make values::LocalCoordinates const @dominic-skydio
- a86b25a Sparse ComputeCovariances supports arbitrary sparse C @xipeng-wang-skydio
- fb26c8d Update
sf.atan2to usesf.copysign_no_zero@aaron-skydio
🏃 Performance Improvements
Various improvements especially to the C++ Optimizer
- 0c02031 Only compute jacobians when include_jacobians is true @aaron-skydio
- 87949e2 set is_initialized_ on initial call to DenseLinearizer::Relinearize @dominic-skydio
- 852cd33 Maps @aaron-skydio
- 5291b84 Don't use ternaries for index_entry_cache @aaron-skydio
- 97807d4 Only save jacobian sparsity on iteration 0 @aaron-skydio
- dfd45df Don't deallocate on ResetValues @aaron-skydio
- 17c66f6 Values::Key(sort_by_offset=true) is faster @aaron-skydio
- 436911c No aligned storage @aaron-skydio
🔏 SkyMarshal
- 4f4755d Convert Eigen vectors of NaN to null in json @nathan-skydio
- f7c6ad1 Move djinni enum converters under their lcm_package @jerry-skydio
- 76eff1c escape special characters when encoding LCM strings @michael-dresser-skydio
- 4a8197f replace removed imp module with importlib @alan-rager-skydio
- 5861275 Convert float-signals to JSON null @philipp-foehn-skydio
- 506cd13 Fix unused imports in TypeScript @rafael-reyes-skydio
- d1c9633 Fix precision of printed floating point types @aaron-skydio
- 97ef11e Improve has_eigen_format @ryan-brott-skydio
- de6ff03 Fix eigen_lcm precision @aaron-skydio
- 873d07f LCM JSON serialization can optionally output Eigen types as 1D arrays wrapped in an object @michael-dresser-skydio
- 3580964 Give LCM types schema() and get_schema() @michael-dresser-skydio
- d6c505f Convert skymarshal templates from py2 to py3 style annotations @aaron-skydio
- 0c8e528 Remove Python 2 compatibility code @aaron-skydio
- f2b98c3 Remove nullptr dereference in decltypes @brian-kubisiak-skydio
- f3e20c3 Add ::data method to Quaternion @roy-vorster-skydio
- f494476 Always Generate Print Helpers for cpp @philipp-foehn-skydio
- e6a04d6 Rip out some py2 code @aaron-skydio
- 665a5ce Set clang-format InsertBraces @aaron-skydio
- 47285a3 Remove pylint disables @aaron-skydio
- 84f69ef Check if array size can be represented in dimension size type @rochan-avlur-skydio
- 72c22e2
Eigen::VectorXpb types @roy-vorster-skydio - 623c5bd Fix translation of byte arrays @tom-skydio
🐞 Internal Maintenance and Bugfixes
- b78c11d Python 3.13 and 3.14 @aaron-skydio
- cd05477 Update Symengine @alan-rager-skydio
- 2b1e371 [Symengine] fix literal warnings @roy-vorster-skydio
- 4cf8034 Check spec is defined before using during C++ codegen @nathan-skydio
- 8ff055d Fix some clang-tidy checks @aaron-skydio
- 506e612 Use correct generator in geo_package_cpp_test @aaron-skydio
- 7314f01 Fix LLT default initialization @aaron-skydio
- 392fa0d Update Catch2 @aaron-skydio
- 2678640 Silence warnings on GCC 13 @aaron-skydio
- 9a7f452 Rearrange some things in factor.* @aaron-skydio
- 9b2faf3 Bump requirements to latest @aaron-skydio
- 0216418 Update cibuildwheel to v3 @aaron-skydio
- 633f3c7 Fix geo_package_python_test flakiness @aaron-skydio
- 1310ee6 Use Python 3 type annotations in PyTorch backend @aaron-skydio
- 2580422 Remove legacy type annotations - ruff UP006 @william-almy-skydio
- 5f1e493 Convert Python codegen templates from py2 to py3 style annotations @aaron-skydio
- 2764239 Fix ruff format of types from wheel @aaron-skydio
- 6774512 Remove '# mypy: disallow-untyped-defs' lines from all Python files @aaron-skydio
- c00a11e Exclude tic_toc sources when not used @aaron-skydio
- ddad846 Fix typechecking on mypy 1.19 @william-almy-skydio
- e1ccb37 Upgrade macos-13 to macos-15-intel @aaron-skydio
- 37b9e5b Fix wheels build failure due to missing prettier @nathan-skydio
- 57114d8 Pin clang-format @aaron-skydio
- 5ec982f Fix build_wheels running on all export commits @aaron-skydio
- 37ef63f Forward CMAKE_LIBRARY_ARCHITECTURE to symengine @aaron-skydio
- 7676740 Clean future imports @aaron-skydio
- 5c26fe9 Fix stubs tests on py39+ @aaron-skydio
- 8a21bb2 Fix pybind wheel builds @aaron-skydio
- 5c9aa5f Remove prints from stubs generation @aaron-skydio
- c07b4ba Upgrade pybind11 to 3.0.1 @aaron-skydio
- c41d2b6 Fix name of default params function @aaron-skydio
- 399a373 update Optimizer class docstring @dominic-skydio
- dc87d56 Fix covariance_test_matrix.bin @aaron-skydio
- 554af60 Use tighter epsilon for geo_package_python_test @aaron-skydio
- 7b68f76 Build on CMake 4 in CI @aaron-skydio
- e58b67e Fix build on CMake 4 @aaron-skydio
- 09cc154 C++20 build fix: wrap fmt argument with fmt::runtime @mikoff
- 7632a16 Add support for latest cmake @Pandapip1
- e270c02 Fix wheel tests again @aaron-skydio
- 4fdbde8 Correct tolerance in slam_imu_preintegration_test @aaron-skydio
- 81f752d Split build requirements by version @aaron-skydio
- d241925 Fix valgrind on symforce_optimizer_test @aaron-skydio
- bece5a2 Publish automatically to PyPI @aaron-skydio
- bc159b2 Add typing_extensions for py38 @aaron-skydio
- 49f20e7 Fix #435 @aaron-skydio
- 453b175 Add test for populate_best_linearization @aaron-skydio
Full Changelog: v0.10.0...v0.11.0