Skip to content

Commit a74eae6

Browse files
[ImuFactor] Add an on manifold Imu Factor
Unit testing is left to a follow up commit. The core use-facing api is found in - symforce/slam/imu_preintegration/preintegrated_imu_measurements.h - symforce/slam/imu_preintegration/imu_factor.h Unlike most other factors (/residual functions) in symforce, the ImuFactor is a functor so as to store the pre-integrated values with the function rather than in the `Values`. (There are a lot of parameters that are constant and unique to each factor). A python version of the `ImuFactor` class will come in a subsequent commit. Topic: on_manifold_imu_factor
1 parent 474f1bd commit a74eae6

15 files changed

Lines changed: 4127 additions & 0 deletions

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ install(DIRECTORY gen/cpp/ DESTINATION include FILES_MATCHING PATTERN "*.h" PATT
280280

281281
if(SYMFORCE_BUILD_OPT)
282282
add_subdirectory(symforce/opt)
283+
add_subdirectory(symforce/slam)
283284
endif()
284285

285286
if(SYMFORCE_BUILD_CC_SYM)

gen/cpp/sym/factors/imu_manifold_preintegration_update.h

Lines changed: 851 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gen/cpp/sym/factors/internal_imu_factor.h

Lines changed: 2373 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

symforce/geo/matrix.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,21 @@ def transpose(self) -> Matrix:
480480
"""
481481
return self.__class__(self.mat.transpose())
482482

483+
def lower_triangle(self: MatrixT) -> MatrixT:
484+
"""
485+
Returns the lower triangle of self
486+
487+
self must be square
488+
"""
489+
rows, cols = self.shape
490+
if rows != cols:
491+
raise ValueError(f"Attempted to take lower triangle of non-square matrix (found shape {self.shape})")
492+
493+
lt = self.__class__()
494+
for k in range(rows):
495+
lt[k, :k + 1] = self[k, :k + 1]
496+
return lt
497+
483498
def reshape(self, rows: int, cols: int) -> Matrix:
484499
return self.__class__(self.mat.reshape(rows, cols))
485500

symforce/pybind/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
# This source code is under the Apache 2.0 license found in the LICENSE file.
44
# ----------------------------------------------------------------------------
55

6+
# ==============================================================================
7+
# Third Party Dependencies
8+
# ==============================================================================
9+
610
include(FetchContent)
711

812
find_package(pybind11 QUIET)
@@ -21,6 +25,13 @@ else()
2125
message(STATUS "pybind11 found")
2226
endif()
2327

28+
# ==============================================================================
29+
# SymForce Targets
30+
# ==============================================================================
31+
32+
# ------------------------------------------------------------------------------
33+
# cc_sym
34+
2435
pybind11_add_module(
2536
cc_sym
2637
SHARED

symforce/slam/CMakeLists.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# ----------------------------------------------------------------------------
2+
# SymForce - Copyright 2022, Skydio, Inc.
3+
# This source code is under the Apache 2.0 license found in the LICENSE file.
4+
# ----------------------------------------------------------------------------
5+
6+
# ==============================================================================
7+
# SymForce Targets
8+
# ==============================================================================
9+
10+
file(GLOB_RECURSE SYMFORCE_SLAM_SOURCES CONFIGURE_DEPENDS *.cc **/*.cc)
11+
file(GLOB_RECURSE SYMFORCE_SLAM_HEADERS CONFIGURE_DEPENDS *.h **/*.h *.tcc **/*.tcc)
12+
13+
add_library(
14+
symforce_slam
15+
${SYMFORCE_LIBRARY_TYPE}
16+
${SYMFORCE_SLAM_SOURCES}
17+
${SYMFORCE_SLAM_HEADERS}
18+
)
19+
target_compile_options(symforce_slam PRIVATE ${SYMFORCE_COMPILE_OPTIONS})
20+
target_link_libraries(symforce_slam
21+
symforce_gen
22+
symforce_opt
23+
${SYMFORCE_EIGEN_TARGET}
24+
)

symforce/slam/__init__.py

Whitespace-only changes.

symforce/slam/imu_preintegration/__init__.py

Whitespace-only changes.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# ----------------------------------------------------------------------------
2+
# SymForce - Copyright 2022, Skydio, Inc.
3+
# This source code is under the Apache 2.0 license found in the LICENSE file.
4+
# ----------------------------------------------------------------------------
5+
6+
from symforce import codegen
7+
from symforce import typing as T
8+
from symforce.slam.imu_preintegration.manifold_symbolic import imu_manifold_preintegration_update
9+
from symforce.slam.imu_preintegration.manifold_symbolic import internal_imu_residual
10+
11+
12+
def generate_manifold_imu_preintegration(
13+
config: codegen.CodegenConfig, output_dir: T.Openable
14+
) -> None:
15+
"""
16+
Generate the on-manifold IMU preintegration update and residual functions.
17+
"""
18+
codegen_update = codegen.Codegen.function(
19+
imu_manifold_preintegration_update,
20+
config=config,
21+
output_names=[
22+
"new_DR",
23+
"new_Dv",
24+
"new_Dp",
25+
"new_covariance",
26+
"new_DR_D_gyro_bias",
27+
"new_Dp_D_gyro_bias",
28+
"new_Dp_D_accel_bias",
29+
"new_Dv_D_gyro_bias",
30+
"new_Dv_D_accel_bias",
31+
],
32+
)
33+
codegen_update.generate_function(output_dir=output_dir, skip_directory_nesting=True)
34+
35+
codegen_residual = codegen.Codegen.function(
36+
internal_imu_residual,
37+
config=config,
38+
).with_linearization(
39+
which_args=[
40+
"pose_i",
41+
"vel_i",
42+
"pose_j",
43+
"vel_j",
44+
"accel_bias_i",
45+
"gyro_bias_i",
46+
]
47+
)
48+
codegen_residual.generate_function(output_dir=output_dir, skip_directory_nesting=True)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* ----------------------------------------------------------------------------
2+
* SymForce - Copyright 2022, Skydio, Inc.
3+
* This source code is under the Apache 2.0 license found in the LICENSE file.
4+
* ---------------------------------------------------------------------------- */
5+
6+
#include "./imu_factor.h"
7+
8+
#include <Eigen/Cholesky>
9+
10+
#include <sym/factors/internal_imu_factor.h>
11+
12+
#include "preintegrated_imu_measurements.h"
13+
14+
namespace sym {
15+
16+
template <typename Scalar>
17+
ImuFactor<Scalar>::ImuFactor(const ImuPreintegrator<Scalar>& preintegrator)
18+
: preintegrated_measurements_{preintegrator.PreintegratedMeasurements()},
19+
// NOTE(brad, chao): llt then inverse is 2x faster than inverse then llt
20+
sqrt_info_{preintegrator.Covariance().llt().matrixL().solve(
21+
Eigen::Matrix<Scalar, 9, 9>::Identity())} {}
22+
23+
template <typename Scalar>
24+
sym::Factor<Scalar> ImuFactor<Scalar>::Factor(const std::vector<Key>& keys_to_func) {
25+
const auto begin = keys_to_func.begin();
26+
return sym::Factor<Scalar>::Hessian(*this, keys_to_func, std::vector<Key>(begin, begin + 6));
27+
}
28+
29+
template <typename Scalar>
30+
void ImuFactor<Scalar>::operator()(
31+
const sym::Pose3<Scalar>& pose_i, const Eigen::Matrix<Scalar, 3, 1>& vel_i,
32+
const sym::Pose3<Scalar>& pose_j, const Eigen::Matrix<Scalar, 3, 1>& vel_j,
33+
const Eigen::Matrix<Scalar, 3, 1>& accel_bias_i, const Eigen::Matrix<Scalar, 3, 1>& gyro_bias_i,
34+
const Eigen::Matrix<Scalar, 3, 1>& gravity, const Scalar epsilon,
35+
Eigen::Matrix<Scalar, 9, 1>* const res, Eigen::Matrix<Scalar, 9, 24>* const jacobian,
36+
Eigen::Matrix<Scalar, 24, 24>* const hessian, Eigen::Matrix<Scalar, 24, 1>* const rhs) const {
37+
InternalImuFactor(
38+
pose_i, vel_i, pose_j, vel_j, accel_bias_i, gyro_bias_i, preintegrated_measurements_.DR,
39+
preintegrated_measurements_.Dv, preintegrated_measurements_.Dp, sqrt_info_,
40+
preintegrated_measurements_.DR_D_gyro_bias, preintegrated_measurements_.Dp_D_accel_bias,
41+
preintegrated_measurements_.Dp_D_gyro_bias, preintegrated_measurements_.Dv_D_accel_bias,
42+
preintegrated_measurements_.Dv_D_gyro_bias, preintegrated_measurements_.accel_bias,
43+
preintegrated_measurements_.gyro_bias, gravity, preintegrated_measurements_.integrated_dt,
44+
epsilon,
45+
// outputs
46+
res, jacobian, hessian, rhs);
47+
}
48+
49+
} // namespace sym
50+
51+
template class sym::ImuFactor<double>;
52+
template class sym::ImuFactor<float>;

0 commit comments

Comments
 (0)