Skip to main content

g2o: A General Framework for Graph Optimization (Python bindings)

Project description

g2o - General Graph Optimization

Ubicoders g2opy edition

Static Badge Static Badge Static Badge Static Badge

Build and Publishing

For build instructions and maintainer guidelines, please refer to manual.md.

ubuntu install

sudo apt-get install -qq qtdeclarative5-dev qt5-qmake libqglviewer-dev-qt5 libsuitesparse-dev libeigen3-dev -y

For the new conda env

conda install -y -c conda-forge "libstdcxx-ng>=12" "libgcc-ng>=12" libgomp

Then, install this package

pip install ubicoders-g2opy

windows dependencies

just do

pip install ubicoders-g2opy

intro

This project is based on the original g2o maintainer as below.

This porject provide windows and linux off the shelf packge including the .dll and .so files as well as the types of the apis for intellisense.

Otherthan that, same as g2o's pymem branch

Latest Commit base:

  • 70f058fde4516505ecb3b392b25bd66b2f4fdf47 (Sep 21, 2025)

How it works

Built the .whl with the damn .dll and .so files for god xxxxing sake.

The pip packge name is pyg2o. But import with import g2opy as g2o

Intellisense Enhanced

sample1 sample2

Supported Python Versions

  • 3.10 ✅
  • 3.11 ✅
  • 3.12 ✅
  • 3.13 ✅

Supproted Numpy Version

  • numpy 1 ⬜
  • numpy 2 ✅

Tested OS and Python

  • Windows 11 ✅
  • Ubuntu 20 ⬜
  • Ubuntu 22 ⬜
  • Ubuntu 24 ✅
  • Ubuntu 25 ✅

Test the installaton

create below and run

python tester.py

tester.py

import numpy as np
import g2opy as g2o
np.set_printoptions(precision=3)
np.set_printoptions(suppress=True)
from collections import defaultdict

def showCameraPoses(optim, idx, N):
    for i in range(idx, idx + N):
        T = optim.vertex(i).estimate().matrix()
        trans = T[:3, 3]
        print('camera pose at ', i, ': ', trans)

def calcSSE(optim, idx, wPts):
    sse = 0
    N = wPts.shape[0]
    for i in range(idx, idx + N):
        guessedWpt = optim.vertex(i)
        error = guessedWpt.estimate() - wPts[i-idx]
        sse += np.sum(error ** 2)
    return sse

def showWpts(optim, idx, N):
    for i in range(idx, idx + N):
        T = optim.vertex(i).estimate()
        #T = np.round(T, 0)
        print('guessed wPt at ', i-idx, ': ', T)

def main():   
    optimizer = g2o.SparseOptimizer()
    solver = g2o.BlockSolverSE3(g2o.LinearSolverCSparseSE3())
    solver = g2o.OptimizationAlgorithmLevenberg(solver)
    optimizer.set_algorithm(solver)

    f, p = 200, 256
    baseline = 0.3
    K = np.array([[f, 0, p],
                  [0, f, p],
                  [0, 0, 1]])

    wPts = np.array([
        [0, 0, 10],
        [-1, 3, 30],
        [2, 2, 37.2],
    ])

    num_pose = 10
    for i in range(0, int(num_pose/2)):
        pose = g2o.Isometry3d(np.identity(3), [(i-2)*10, 0, 0])
        v_se3 = g2o.VertexSCam()
        v_se3.set_cam(f, f, p, p, baseline)
        v_se3.set_id(i)
        v_se3.set_estimate(pose)
        if i < 2:
            v_se3.set_fixed(True)
        v_se3.set_all() # sets transfrom, projection, dR (angle)
        optimizer.add_vertex(v_se3)

    for i in range(int(num_pose/2), num_pose):
        pose = g2o.Isometry3d(np.identity(3), [0, (i - int(num_pose/2)- 2) * 10, 0])
        v_se3 = g2o.VertexSCam()
        v_se3.set_cam(f, f, p, p, baseline)
        v_se3.set_id(i)
        v_se3.set_estimate(pose)
        v_se3.set_fixed(False)
        v_se3.set_all() # sets transfrom, projection, dR (angle)
        optimizer.add_vertex(v_se3)

    point_id = 0

    for i, wpt in enumerate(wPts):
        guessed_wPt = g2o.VertexPointXYZ()
        guessed_wPt.set_id(num_pose + point_id)
        guessed_wPt.set_marginalized(True)
        guessed_wPt.set_estimate(wpt + np.random.randn(3) )
        optimizer.add_vertex(guessed_wPt)

        for j in range(num_pose):
            z = optimizer.vertex(j).map_point(wpt)
            if i > 1:
                z +=  np.random.randn(3)
            edge = g2o.EdgeXyzVsc()
            edge.set_vertex(0, guessed_wPt)
            edge.set_vertex(1, optimizer.vertex(j))
            edge.set_measurement(z)
            edge.set_information(np.identity(3))
            optimizer.add_edge(edge)

        point_id += 1

    sse0 = calcSSE(optimizer, num_pose, wPts)
    print('\nRMSE (inliers only):')
    print('before optimization:', np.sqrt(sse0 / wPts.shape[0]))
    showCameraPoses(optimizer, 0, num_pose)
    showWpts(optimizer, num_pose, 3)


    print('Performing full BA:')
    optimizer.initialize_optimization()
    optimizer.set_verbose(False)
    optimizer.optimize(100)

    sse1 = calcSSE(optimizer, num_pose, wPts)

    print('\nRMSE (inliers only):')
    print('after  optimization:', np.sqrt(sse1 / wPts.shape[0]))
    showCameraPoses(optimizer, 0, num_pose)
    showWpts(optimizer, num_pose, 3)


if __name__ == '__main__':
    main()

see the orignal readme at https://github.com/RainerKuemmerle/g2o

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

ubicoders_g2opy-2.1.7-cp310-cp310-manylinux_2_38_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.38+ x86-64

ubicoders_g2opy-2.1.7-cp310-cp310-manylinux_2_34_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.34+ x86-64

ubicoders_g2opy-2.1.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

File details

Details for the file ubicoders_g2opy-2.1.7-cp310-cp310-manylinux_2_38_x86_64.whl.

File metadata

File hashes

Hashes for ubicoders_g2opy-2.1.7-cp310-cp310-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 5914473fe7865436eafebba3d75fd0bfa71fb870af492c897fa39c087db9cba9
MD5 3011bc4c26d24dcea5451bb21c3c68b0
BLAKE2b-256 f85cea41ac6a81ae854402d7e040188a481f6edd7ac8d95dbfce8a70a390a50f

See more details on using hashes here.

File details

Details for the file ubicoders_g2opy-2.1.7-cp310-cp310-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for ubicoders_g2opy-2.1.7-cp310-cp310-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 2f1e97298eefc152afdf376d637e84f707689501bcfe8ae7f0dd8f2ebc48f3ba
MD5 907c7387b35333e5994a5dc6382a31af
BLAKE2b-256 241addf3c13f78305de3c37ae6391075bd9561a76a13a5d1f0b12e9ab118991f

See more details on using hashes here.

File details

Details for the file ubicoders_g2opy-2.1.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for ubicoders_g2opy-2.1.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 a058163f991db6efecbbdaa5047ae505a33e5c2950591fd68751a79ab3f65801
MD5 99210a2ab911f6ed93090747183a698a
BLAKE2b-256 b6d4ece9a9779524c1c0a2772be1efa2b171c8dbfc802812cd094fc559769e4b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page