Source code for symforce.examples.bundle_adjustment_fixed_size.build_values
# ----------------------------------------------------------------------------
# SymForce - Copyright 2022, Skydio, Inc.
# This source code is under the Apache 2.0 license found in the LICENSE file.
# ----------------------------------------------------------------------------
"""
This file builds a Values with all symbols needed for the fixed-size example.
"""
import symforce.symbolic as sf
from symforce.values import Values
[docs]def define_view(index: int) -> Values:
"""
Creates a symbolic pose + calibration representing a single image
"""
values = Values()
values["calibration"] = sf.LinearCameraCal.symbolic(f"cal{index}")
values["pose"] = sf.Pose3.symbolic(f"pose{index}")
return values
[docs]def define_feature_match(index: int, match_num: int) -> Values:
"""
Create a symbolic correspondence definition with the given specs. This includes
every symbol specific to defining and optimizing a single 2D-2D match.
Args:
index (int): Camera index
match_num (int): Feature match number for this specific target camera
create_landmark (bool): Use landmark variable parameterization
"""
values = Values()
# Source pixel coordinate (camera 0)
values["source_coords"] = sf.V2.symbolic(f"source_coords_{index}{match_num}")
# Target pixel coordinate (specified camera index)
values["target_coords"] = sf.V2.symbolic(f"target_coords_{index}{match_num}")
# Weight of match
values["weight"] = sf.Symbol(f"weights_{index}{match_num}")
values["inverse_range_prior"] = sf.Symbol(f"inverse_range_priors_{index}{match_num}")
values["inverse_range_prior_sigma"] = sf.Symbol(
f"inverse_range_prior_sigmas_{index}{match_num}"
)
return values
[docs]def define_pose_prior(source_cam_index: int, target_cam_index: int) -> Values:
"""
Create symbols for a pose prior and uncertainty.
"""
values = Values()
values["target_T_src"] = sf.Pose3.symbolic(
f"target_T_src_{source_cam_index}_{target_cam_index}"
)
# Square root information matrix of pose estimate [rad, rad, rad, m, m, m]
values["sqrt_info"] = sf.M66.symbolic(f"pose_sqrt_info_{source_cam_index}_{target_cam_index}")
return values
[docs]def define_objective_costs() -> Values:
"""
Define parameters for objectives
"""
values = Values()
# Robust cost function transition point for reprojection error [px]
values["reprojection_error_gnc_scale"] = sf.Symbol("reprojection_error_gnc_scale")
# Robust cost function mu convexity parameter
values["reprojection_error_gnc_mu"] = sf.Symbol("reprojection_error_gnc_mu")
return values
[docs]def build_values(num_views: int, num_landmarks: int) -> Values:
"""
Create a Values object with all symbols needed for optimization of a set
of camera views with sparse feature matches.
Args:
num_views (int): Number of camera views
num_landmarks (int): Fixed number of landmarks
Returns:
(Values): Values to optimize + constants
"""
values = Values()
values["views"] = []
values["priors"] = []
values["matches"] = []
# Define camera views
for src_cam_inx in range(num_views):
values["views"].append(define_view(src_cam_inx))
priors = []
for target_cam_inx in range(num_views):
priors.append(define_pose_prior(src_cam_inx, target_cam_inx))
values["priors"].append(priors)
# Define landmarks
values["landmarks"] = []
for i in range(num_landmarks):
values["landmarks"].append(sf.Symbol(f"source_inverse_ranges{i}"))
# Define correspondences variables from camera 0 to all others
for v_i in range(num_views - 1):
matches = []
for l_i in range(num_landmarks):
matches.append(define_feature_match(index=v_i, match_num=l_i))
values["matches"].append(matches)
values["costs"] = define_objective_costs()
values["epsilon"] = sf.Symbol("epsilon")
return values