Skip to content

Commit 615a9a3

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 4c36881 commit 615a9a3

19 files changed

Lines changed: 5120 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/internal/imu_manifold_preintegration_update.h

Lines changed: 815 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_manifold_preintegration_update_auto_derivative.h

Lines changed: 937 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/internal_imu_factor.h

Lines changed: 2377 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: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,23 @@ def transpose(self) -> Matrix:
487487
"""
488488
return Matrix(self.mat.transpose())
489489

490+
def lower_triangle(self: MatrixT) -> MatrixT:
491+
"""
492+
Returns the lower triangle (including diagonal) of self
493+
494+
self must be square
495+
"""
496+
rows, cols = self.shape
497+
if rows != cols:
498+
raise ValueError(
499+
f"Attempted to take lower triangle of non-square matrix (found shape {self.shape})"
500+
)
501+
502+
lt = self.__class__()
503+
for k in range(rows):
504+
lt[k, : k + 1] = self[k, : k + 1]
505+
return lt
506+
490507
def reshape(self, rows: int, cols: int) -> Matrix:
491508
return Matrix(self.mat.reshape(rows, cols))
492509

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: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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+
import functools
7+
8+
from symforce import codegen
9+
from symforce import typing as T
10+
from symforce.slam.imu_preintegration.manifold_symbolic import imu_manifold_preintegration_update
11+
from symforce.slam.imu_preintegration.manifold_symbolic import internal_imu_residual
12+
13+
14+
def generate_manifold_imu_preintegration(
15+
config: codegen.CodegenConfig, output_dir: T.Openable
16+
) -> None:
17+
"""
18+
Generate the on-manifold IMU preintegration update and residual functions.
19+
"""
20+
21+
update_output_names = [
22+
"new_DR",
23+
"new_Dv",
24+
"new_Dp",
25+
"new_covariance",
26+
"new_DR_D_gyro_bias",
27+
"new_Dv_D_accel_bias",
28+
"new_Dv_D_gyro_bias",
29+
"new_Dp_D_accel_bias",
30+
"new_Dp_D_gyro_bias",
31+
]
32+
33+
codegen_update = codegen.Codegen.function(
34+
functools.partial(imu_manifold_preintegration_update, use_handwritten_derivatives=True),
35+
config=config,
36+
output_names=update_output_names,
37+
)
38+
codegen_update.generate_function(output_dir=output_dir, skip_directory_nesting=True)
39+
40+
codegen_update_auto_derivative = codegen.Codegen.function(
41+
functools.partial(imu_manifold_preintegration_update, use_handwritten_derivatives=False),
42+
name="imu_manifold_preintegration_update_auto_derivative",
43+
docstring="""
44+
Alternative to ImuManifoldPreintegrationUpdate that uses auto-derivatives. Exists only to
45+
help verify correctness of ImuManifoldPreintegrationUpdate. Should have the same output.
46+
Since this function is more expensive, there is no reason to use it instead.
47+
"""
48+
+ (
49+
imu_manifold_preintegration_update.__doc__
50+
if imu_manifold_preintegration_update.__doc__ is not None
51+
else ""
52+
),
53+
config=config,
54+
output_names=update_output_names,
55+
)
56+
codegen_update_auto_derivative.generate_function(
57+
output_dir=output_dir, skip_directory_nesting=True
58+
)
59+
60+
codegen_residual = codegen.Codegen.function(
61+
internal_imu_residual,
62+
config=config,
63+
).with_linearization(
64+
which_args=[
65+
"pose_i",
66+
"vel_i",
67+
"pose_j",
68+
"vel_j",
69+
"accel_bias_i",
70+
"gyro_bias_i",
71+
]
72+
)
73+
codegen_residual.generate_function(output_dir=output_dir, skip_directory_nesting=True)

0 commit comments

Comments
 (0)