Source code for tangent_py.core

"""
Core cppyy initialization and header loading.
"""
import cppyy
import os
from pathlib import Path

_initialized = False
_tangent_root = None


[docs] def get_tangent_root() -> Path: """Get the root directory of the Tangent project.""" global _tangent_root if _tangent_root is None: # Navigate from tangent_py package to project root # python/tangent_py/core.py -> python/tangent_py -> python -> Tangent _tangent_root = Path(__file__).parent.parent.parent return _tangent_root
[docs] def init(): """ Initialize cppyy with Tangent headers. This must be called before using any Tangent functionality. It loads Eigen, Sophus, and all Tangent headers. Safe to call multiple times (idempotent). """ global _initialized if _initialized: return root = get_tangent_root() # Enable -O3 optimization for LLVM auto-vectorization # This must be set before any code is compiled cppyy.gbl.gInterpreter.ProcessLine(".O3") # Add include paths cppyy.add_include_path(str(root / "include")) cppyy.add_include_path(str(root / "extern" / "eigen")) cppyy.add_include_path(str(root / "extern" / "sophus")) # Eigen configuration for cppyy compatibility # EIGEN_DONT_VECTORIZE disables Eigen's explicit SIMD intrinsics which cppyy's # Cling can't parse (especially ARM NEON intrinsics on aarch64). # With -O3, LLVM will still auto-vectorize the code. cppyy.cppdef(""" #define EIGEN_DONT_VECTORIZE #define EIGEN_DEFAULT_DENSE_INDEX_TYPE int #define EIGEN_NO_DEBUG """) # Include Eigen cppyy.include("Eigen/Dense") cppyy.include("Eigen/Sparse") # Include Sophus cppyy.include("sophus/se3.hpp") cppyy.include("sophus/so3.hpp") # Include Tangent core headers cppyy.include("tangent/Differentiation/Jet.h") cppyy.include("tangent/Differentiation/JetTraits.h") cppyy.include("tangent/Variables/OptimizableVariable.h") cppyy.include("tangent/Variables/SimpleScalar.h") cppyy.include("tangent/Variables/SE3.h") cppyy.include("tangent/Variables/SO3.h") cppyy.include("tangent/Variables/InverseDepth.h") cppyy.include("tangent/ErrorTerms/ErrorTermBase.h") cppyy.include("tangent/ErrorTerms/AutoDiffErrorTerm.h") cppyy.include("tangent/Containers/SlotMap.h") cppyy.include("tangent/Types/GaussianPrior.h") cppyy.include("tangent/Types/SparseBlockMatrix.h") cppyy.include("tangent/Optimization/OptimizerContainers.h") cppyy.include("tangent/Optimization/HuberLossFunction.h") cppyy.include("tangent/Optimization/PSDSchurSolver.h") cppyy.include("tangent/Optimization/Marginalizer.h") cppyy.include("tangent/Optimization/SSEOptimizer.h") _initialized = True
[docs] def define_error_term(cpp_code: str): """ JIT compile a C++ error term class. The code should define a class inheriting from AutoDiffErrorTerm. Args: cpp_code: C++ code string defining the error term class Example: >>> define_error_term(''' ... class DiffError : public Tangent::AutoDiffErrorTerm<DiffError, double, 1, ... Tangent::SimpleScalar, ... Tangent::SimpleScalar> { ... public: ... DiffError(Tangent::VariableKey<Tangent::SimpleScalar> k1, ... Tangent::VariableKey<Tangent::SimpleScalar> k2) { ... std::get<0>(variableKeys) = k1; ... std::get<1>(variableKeys) = k2; ... information.setIdentity(); ... } ... ... template <typename T, typename V1, typename V2> ... Eigen::Matrix<T, 1, 1> computeError(const V1& v1, const V2& v2) const { ... Eigen::Matrix<T, 1, 1> err; ... err(0) = v2 - v1; ... return err; ... } ... }; ... ''') """ init() cppyy.cppdef(cpp_code)
[docs] def is_initialized() -> bool: """Check if cppyy has been initialized.""" return _initialized