Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Hybrid Inference

This notebook demonstrates hybrid inference — the joint estimation of continuous (e.g. robot poses) and discrete (e.g. semantic class) variables — using GTSAM’s HybridNonlinearFactorGraph machinery.

We work through three progressively richer examples:

  1. Discrete-only inference — finding the Most Probable Explanation (MPE) of a binary variable given a DecisionTreeFactor prior.

  2. Continuous-only SLAM — using DCSAM as a wrapper around iSAM2 for standard Pose2 odometry SLAM.

  3. True hybrid inference — a robot with an uncertain motion mode (normal vs. slippery surface) where DCSAM jointly estimates the pose trajectory and the active mode.

Open In Colab

Background

A hybrid factor graph contains three types of variables:

TypeExampleContainer
Continuous nonlinearPose xi∈SE(2)x_i \in SE(2)Values
Continuous linearIMU biasVectorValues
DiscreteMotion mode m∈{0,1}m \in \{0,1\}DiscreteValues

Factors can be purely continuous (NonlinearFactor), purely discrete (DecisionTreeFactor), or hybrid (HybridNonlinearFactor).

Discrete-Continuous Smoothing and Mapping (DCSAM)

We first demonstrate hybrid inference using the DCSAM solver proposed by Doherty et al. 2022).

DCSAM is an iterative optimizer which alternates between:

  1. Continuous solve — run iSAM2 with the discrete variables fixed at their current MPE.

  2. Discrete solve — compute a DiscreteBoundaryFactor for each hybrid factor and find the new MPE by maximizing over the discrete variables.


Example 1 — Discrete-only Inference

The simplest case: a single binary variable D1∈{0,1}D_1 \in \{0, 1\} with a prior that strongly prefers D1=1D_1 = 1. We expect DCSAM to return D^1=1\hat{D}_1 = 1.

MPE for D(1): 1  (expected 1)

Example 2 — Continuous-only SLAM

An 8-pose 2-D SLAM problem: a robot follows a roughly octagonal path with noisy odometry. There are no discrete variables — DCSAM acts as a thin wrapper around iSAM2.

Continuous-only SLAM result (first three poses):
  X(0): x=0.0000, y=0.0000, θ=-0.0000 rad
  X(1): x=1.0000, y=0.0141, θ=0.7954 rad
  X(2): x=1.6899, y=0.7382, θ=1.5908 rad
<Figure size 600x500 with 1 Axes>

Example 3 — Hybrid Inference: Uncertain Motion Mode

Problem description

A robot moves from x0x_0 to x1x_1 to x2x_2. The first odometry step has an uncertain mode D0∈{0,1}D_0 \in \{0, 1\}:

  • Mode 0 (normal): Reliable motion Δx=(1,0,0)\Delta x = (1, 0, 0) with small noise.

  • Mode 1 (slippery): Same nominal motion but with large noise.

The second odometry step is a known, pure-continuous BetweenFactorPose2.

A DecisionTreeFactor encodes a prior over the mode, and we also add a discrete observation factor that says mode 0 is very likely. After calling DCSAM.update(), we verify that:

  • The discrete estimate is D^0=0\hat{D}_0 = 0 (normal mode).

  • The continuous estimates are close to the ground truth.

Hybrid inference result
  Discrete mode D(0): 0  (expected 0 = normal)
  X(0): x=0.0000, y=0.0000, θ=0.0000 rad
  X(1): x=1.0000, y=0.0000, θ=0.0000 rad
  X(2): x=2.0000, y=0.0000, θ=0.0000 rad
<Figure size 700x300 with 1 Axes>

Details

DCSAM performed two rounds of alternating minimization:

  1. Round 1:

    • Continuous: given the initial discrete guess (mode 0), iSAM2 pulls all poses towards the odometry mean.

    • Discrete: the DiscreteBoundaryFactor computed from the tight-noise component has a smaller negative log-likelihood at the current poses than the loose-noise component, so mode 0 is retained.

  2. Round 2 (dcsam.update() with no new factors):

    • Both steps refine slightly; the result converges.

The key insight is that DCSAM jointly estimates where the robot is and which motion model was active — something that neither a pure-continuous nor a pure-discrete solver can do alone.


Summary

ExampleVariablesMethod
Discrete-onlyD1∈{0,1}D_1 \in \{0,1\}DCSAM.update(graph, DiscreteValues)
Continuous-onlyx0…x7∈SE(2)x_0 \ldots x_7 \in SE(2)DCSAM.update(graph, HybridValues)
Hybridx0,x1,x2∈SE(2)x_0, x_1, x_2 \in SE(2), D0∈{0,1}D_0 \in \{0,1\}DCSAM.update(graph, HybridValues)

Key classes used:

  • HybridNonlinearFactorGraph — container for all factor types.

  • HybridNonlinearFactor — selects a NoiseModelFactor for each mode.

  • DecisionTreeFactor — probability table over discrete variables.

  • DCSAM — alternating-minimization solver.

  • HybridValues — container for the joint estimate (nonlinear(), discrete(), continuous()).

Further reading

  • K. Doherty et al., “DCSAM: Discrete-Continuous Smoothing and Mapping”, IEEE RA-L, 2022. https://arxiv.org/abs/2204.11936

  • GTSAM gtsam/hybrid/ module documentation and C++ unit tests.