GTSAM: the smoothing and mapping library where the graph is the program
GTSAM is a library of C++ classes that implement smoothing and mapping (SAM) in robotics and vision, using factor graphs and Bayes networks as the underlying computing paradigm rather than sparse matrices.
At a glance
- What is it?
- A C++ library from Georgia Tech and the Georgia Tech Smoothing and Mapping Lab that does state estimation through factor graphs and Bayes networks instead of sparse matrices, with Python and MATLAB wrappers on top. Twenty years of academic code, actively rewritten, and a default branch that is deliberately unstable.
- Who is it for?
- GTSAM is the right choice when your estimation problem is genuinely a graph and you have the mathematics to own it: coupled landmarks, a camera rig, a loop closure that changes the whole trajectory, or an IMU stream fused with vision. It rewards you for reading Dellaert and Kaess, and the notebooks plus the certifiable optimization work mean a new user has a defensible path in rather than a stack of undocumented headers.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Jupyter Notebook, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 7, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The paradigm choice is the whole pitch
GTSAM does smoothing and mapping, which is the estimation half of perception: given noisy measurements, recover the latent state that best explains them. The description is precise about the method, saying that the library uses factor graphs and Bayes networks as the underlying computing paradigm rather than sparse matrices. That sentence is a design commitment, not marketing, and it decides what your code looks like.
With a sparse matrix approach you accumulate a Hessian, factor it, and recover an increment. The linear algebra is correct and the object you manipulate is a matrix. With GTSAM you assemble a graph: variable nodes for poses, landmarks, biases and calibration parameters, plus factor nodes for individual measurements and their covariance. Solving means running belief propagation or a Gauss-Newton style iteration over that graph, and the marginals you want come out as products of beliefs rather than as an inverse of a big matrix.
What that buys you is structural. A loop closure is a new factor between two nodes far apart in the graph. In the matrix view it perturbs every entry in a dense block; in the graph view it is one edge, and the propagation happens where it is needed. The same applies to IMU factors, which span a long window of states, and to discrete variables in hybrid inference, where a factor graph can hold finite-valued state mixed with continuous state. That mixed formulation is why the repository ships examples like `HMMExample.cpp`, `DiscreteBayesNetExample.cpp` and `DiscreteBayesNet_FG.cpp`.
The cost is that you are closer to the mathematics than a matrix library lets you be. Factors declare their dimension and their adjoint Jacobian, and the optimizer drives a Gauss-Newton or LM loop over your graph. Code written for another paradigm ports badly.
Building it, and what the build actually requires
GTSAM is a compiled C++ library, so the first real question is your toolchain. The build is three CMake commands from the root of the library folder:
cmake -S . -B build
cmake --build build --target check # optional, runs all unit tests
cmake --build build --target installThe prerequisites are CMake 3.16 or newer and a compiler with C++17 support. The continuously tested toolchains are specific: GCC 11, 13, 14 or 15 and Clang 11, 14 or 16 on Linux, Xcode 16 on macOS, and MSVC toolset 14.40 on Windows. The documentation says older C++17-capable toolchains may work but are not continuously tested, which is a distinction worth respecting if you are pinning an old container.
Boost is optional and controlled by two CMake flags, `GTSAM_USE_BOOST_FEATURES` and `GTSAM_ENABLE_BOOST_SERIALIZATION`, both defaulting to ON for ordinary CMake builds and OFF inside ROS 2 `colcon` builds. If either is on you need Boost 1.70 or newer. There is also a oneTBB dependency searched when `GTSAM_WITH_TBB=ON`, which is the default, and an Intel oneMKL path that engages only with `GTSAM_WITH_EIGEN_MKL=ON`, where the advice is to benchmark your workload both ways rather than assuming the optimized linear algebra wins.
The `check` target is worth running once on a new machine. It runs the unit tests, and it catches the class of problem, such as a missing include on a newer toolchain, that would otherwise surface as a confusing link error much later. CI runs on Ubuntu 22.04, macOS 15 and Windows 2022, which is a reasonable proxy for whether your environment is sane.
What the 4.3 release actually added
GTSAM 4.3.0 was published on 2026-09-18, five days before the last push to the repository on 2026-09-23. Its stated themes are faster inference, improved correctness, expanded navigation and estimation, certifiable and GPU-accelerated optimization, and a more modern developer experience. Those are release-note words, so it is worth looking at what sits behind them.
The examples directory grew into a catalogue of what the library can now do: `CertifiableLandmarkSLAM.cpp`, `CertifiableLocalizationExample.cpp`, `CertifiablePoseGraphOptimization.cpp`, `CertifiableRotationAveraging.cpp`, `CertifiableRangeAidedSLAM.cpp`, `GaussianProcessWnoaSE3Example.cpp`, `IEKF_NavstateExample.cpp`, `IEKF_SE2Example.cpp`, `FixedLagSmootherExample.cpp`, `CombinedImuFactorsExample.cpp`. Read that list as the feature matrix. Certifiable optimization means problems where you need a proof that the answer is correct rather than a solver convergence log, and the example files are named `CertifiableMosek.h` and `CertifiableLocalizationUtils.h`, which tells you there is a commercial solver involved.
Continuous-time estimation arrives through a white-noise-on-acceleration Gaussian process framework with continuous-time factors, trajectory interpolation and factor-graph construction, so a trajectory can be a first-class object rather than a chain of discrete states. Hybrid inference and constrained optimization arrive together, with linear programs, quadratic programs and quadratically constrained quadratic programs sharing the constrained framework, so a state estimate subject to physical or geometric equality constraints does not need a separate toolchain.
The alpha before it, 4.3a2 on 2026-08-04, is candid about the state of play: the API is not stable for the new additions, and GPU acceleration and certifiable optimization are still in flux. A patch release, 4.2.2 on 2026-06-30, is mostly repair work, including a cherry-picked hybrid compilation fix and several `ISAM2` fixes with a regression test to keep marginal-factor updates from growing the graph unexpectedly.
Smoothers, filters and the incremental solver
GTSAM spans the standard estimation spectrum, and the examples show how much of it is directly usable. `FixedLagSmootherExample.cpp` is the fixed-lag smoother, which keeps a moving window of states active and marginalizes older ones so the optimization cost does not grow with trajectory length. `GNCExample.cpp` is graduated non-convexity, a way to get a global-ish solution on a pose graph with bad initial guesses. `GEKF_Rot3Example.cpp` and the IEKF examples are filtering rather than smoothing, for the cases where you want the current state rather than the whole trajectory.
`ISAM2` is the piece people come for, and the 4.2.1 and 4.2.2 notes are an unusually honest account of its edge cases. They record fixes to several `ISAM2` issues and the addition of a regression test whose stated purpose is to ensure marginal-factor updates do not grow the graph unexpectedly. If you have ever watched memory climb in an incremental solve, that sentence is a direct hint about where to look.
`Point2` and `Point3` are Eigen vector aliases, and the documentation flags that their default constructors do not initialize their coefficients. This is the kind of note that saves an afternoon of chasing garbage poses, and it is a reminder that GTSAM leans on Eigen types rather than hiding them.
The IMU path has its own history. The library builds on the visual-inertial-aided navigation scheme from Lupton and Sukkarieh, and improves on it through integration on the manifold rather than in the ambient space. `CombinedImuFactorsExample.cpp` exercises the combination. If you cite the scheme in academic work the project asks for the Forster, Carlone, Dellaert and Scaramuzza RSS 2015 paper on IMU preintegration on manifolds, and if you cite GTSAM itself it asks for the Zenodo software DOI, which points at version 4.3.0.
Python, MATLAB and the documentation rebuild
The wrappers are the reason many people meet GTSAM at all, and the 4.3 release put real work into them. The repository labels itself as a Jupyter Notebook project in its language metadata, which reflects where the activity now sits: the Python side carries the examples and the teaching material, while C++ remains the core that everything binds to.
The Python documentation is a MyST site at borglab.github.io/gtsam, and 4.3 expanded it substantially with user guides, conceptual documentation and executable notebooks. The examples section now covers geometry, SLAM, structure from motion, navigation, filtering, discrete and hybrid inference, continuous-time estimation, certifiable estimation and CUDA optimization, with many notebooks runnable directly in Google Colab. That last detail matters more than it sounds, because it removes the local build from the first hour of evaluation entirely.
There is a separate package for people tracking the development branch: `gtsam-develop` on PyPI, built by its own workflow, with no Windows wheels. Wheels for the stable line are built across Python 3.11 through 3.14, with separate macOS arm64 and x86_64 jobs, and NumPy pinned below 2.0.0 for compatibility with the vendored `pybind11` stack. MATLAB has its own wrapper directory and README.
The ROS 2 relationship is worth noting as well. The Boost options default to OFF inside `colcon` builds, which tells you that a ROS 2 integration exists and that the library is built differently in that environment. The repository also contains `AGENTS.md`, `CLAUDE.md` and `GEMINI.md`, which is a fairly clear signal about how much of the modern contributor workflow has moved to coding agents.
Where the project actually stands
GTSAM has 3699 stars and 994 forks, an open issue count of 7, and its default branch is `develop`. That combination is telling. A low open issue count on a project with a thousand contributors and a decade of academic use means triage is working, or means issues are going somewhere else, but either way the ratio of forks to issues suggests most people arrived to use it or extend it rather than to file.
The `develop` branch warning is the most important operational fact for anyone not contributing. The documentation says it contains changes intended for the next GTSAM release and may include API changes, and that for production use you should choose the latest stable version from the releases page. Current development builds require C++17, and Boost support is optional under CMake options. A second switch, `GTSAM_ALLOW_DEPRECATED_SINCE_V43`, defaults to ON and governs APIs deprecated as of 4.3; setting it OFF while migrating is the intended way to find what is scheduled for removal.
The tree tells you the shape of the project: `gtsam/` for the library, `gtsam_unstable/` for everything not yet promoted, `examples/`, `python/`, `matlab/`, `wrap/` for the binding generator, `timing/` for benchmarks, `containers/` for images, plus `INSTALL.md`, `DEVELOP.md`, `USAGE.md` and `THANKS.md`. Having a documented `gtsam_unstable` directory is a good sign, since it means the boundary between experimental and supported is explicit rather than vibes.
The license field reads NOASSERTION in the repository metadata, and the tree contains both `LICENSE` and `LICENSE.BSD`. For a project that grew out of academic work and ships into robotics companies, that is worth resolving with the maintainers or your own legal reading before you commit to it, because the two files in the root suggest a mixed heritage. The CUDA linear solvers documentation lives in its own file under `doc/`, which suggests GPU solver work is documented separately from the main manual for good reason.
Editorial conclusion
GTSAM is the right choice when your estimation problem is genuinely a graph and you have the mathematics to own it: coupled landmarks, a camera rig, a loop closure that changes the whole trajectory, or an IMU stream fused with vision. It rewards you for reading Dellaert and Kaess, and the notebooks plus the certifiable optimization work mean a new user has a defensible path in rather than a stack of undocumented headers. The practical warning is the branch structure: `develop` carries API changes intended for the next release, so pin a released version such as 4.3.0 for anything you do not want to revisit. Build from source with the three CMake commands above, run the `check` target once so a toolchain problem shows up on a clean machine, and then decide early whether you want the nonlinear path or the constrained and certifiable one, since the two answer the same question with very different guarantees.
Frequently asked questions
How does Gtsam work?
GTSAM represents an estimation problem as a factor graph rather than as a matrix to factor. You create variable nodes for poses, landmarks and biases, add factor nodes for each measurement with its noise model, then run a solver such as Gauss-Newton, LM, a fixed-lag smoother or ISAM2 over that graph. Results come back as beliefs over variables and as marginals over selected ones, and the same structure extends to discrete and hybrid problems.
How are factor graphs used in SLAM?
In SLAM each pose and landmark becomes a variable and each sensor reading becomes a factor between the variables it observes. Odometry, IMU preintegration, visual reprojection and loop closures all enter the same graph, so adding a loop closure is a matter of attaching one factor rather than refactoring a dense system. GTSAM ships this as `examples/CertifiableLandmarkSLAM.cpp` and a pose graph SLAM example, plus iSAM2 for incremental updates as the robot moves.
What is a factor graph?
A factor graph is a bipartite graph with variable nodes and factor nodes. A variable holds an unknown to be estimated, such as a pose or a landmark, and a factor holds a measurement together with the probability density of that measurement given the variables it touches. The graph encodes the joint distribution, so marginalizing a variable, or asking what a change to one factor does to a distant one, falls out of message passing over the structure.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/borglab-gtsam)