You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<spanstyle="color:red"><b>WARNING: SymForce is strictly confidential until its public release.</b></span>
11
10
12
-
SymForce is a Python and C++ library for symbolic computation and code generation. It contains three independently useful systems:
11
+
SymForce is a fast symbolic computation and code generation library for robotics applications like computer vision, state estimation, motion planning, and controls. It combines the development speed and flexibility of symbolic mathematics with the performance of autogenerated, highly optimized code in C++ or any target runtime language. SymForce contains three independently useful systems:
13
12
14
-
+**Symbolic Toolkit** - builds on the SymPy API to provide rigorous geometric and camera types, lie group calculus, singularity handling, and tools to model large problems
13
+
+**Symbolic Toolkit** - builds on the SymPy API to provide rigorous geometric and camera types, lie group calculus, singularity handling, and tools to model complex problems
15
14
16
15
+**Code Generator** - transforms symbolic expressions into blazing-fast, branchless code with clean APIs and minimal dependencies, with a template system to target any language
17
16
18
-
+**Optimization Library** - performs on-manifold factor graph optimization with a highly optimized implementation for real-time robotics applications
17
+
+**Optimization Library** - a fast tangent-space optimization library based on factor graphs, with a highly optimized implementation for real-time robotics applications
19
18
20
-
SymForce accelerates robotics and computer vision tasks like visual odometry, bundle adjustment, calibration, sparse nonlinear MPC, and embedded motor control.
19
+
SymForce automatically computes tangent space Jacobians, eliminating the need for any bug-prone handwritten derivatives. Generated functions can be directly used as factors in our nonlinear optimizer. This workflow enables faster runtime functions, faster development time, and fewer lines of handwritten code versus alternative methods.
20
+
21
+
SymForce was developed at [Skydio](https://skydio.com/). It is used in production to accelerate tasks like SLAM, bundle adjustment, calibration, and sparse nonlinear MPC for autonomous robots at scale.
+ Rapidly prototype and analyze complex problems with symbolic math, with a seamless workflow into production use
31
-
+ Compute fast and correct tangent-space jacobians for any expression
32
-
+ Reduce duplication and minimize bugs by generating native runtime code in multiple languages from a canonical symbolic representation
33
-
+ Generate embedded-friendly C++ functions that depend only on Eigen, are templated on the scalar type, and require no dynamic allocation
34
-
+ Outperform automatic differentiation techniques, sometimes by 10x
35
-
+ Leverage high quality, battle-hardened, and performant APIs at all levels
29
+
#### Features:
36
30
37
-
# Note to early access participants
31
+
+ Symbolic implementations of geometry and camera types with Lie group operations
32
+
+ Code generation of fast native runtime code from symbolic expressions, reducing duplication and minimizing bugs
33
+
+ Novel tools to compute fast and correct tangent-space jacobians for any expression, avoiding all handwritten derivatives
34
+
+ Strategies for flattening computation and leveraging sparsity that can yield 10x speedups over standard autodiff
35
+
+ A fast tangent-space optimization library in C++ and Python based on factor graphs
36
+
+ Rapid prototyping and analysis of complex problems with symbolic math, with a seamless workflow into production use
37
+
+ Embedded-friendly C++ generation of templated Eigen code with zero dynamic memory allocation
38
+
+ Highly performant, modular, tested, and extensible code
38
39
39
-
Thank you for helping us develop SymForce! We value the time you're taking to provide feedback during this private beta program.
40
+
# Early Access Notes
40
41
41
-
You will be invited to a private Slack channel with the authors. Please file specific issues on Github, and then use Slack for discussion. Do not share any links or code without express permission from the authors.
42
+
Thank you for helping us develop SymForce! We value the time you're taking to provide feedback during this private beta program. We expect some rough edges and slow, missing, or confusing aspects of the library. Please file [issues](https://github.com/symforce-org/symforce/issues) on GitHub and we will work to address them.
42
43
43
44
Things to try:
44
45
@@ -52,16 +53,10 @@ Things to try:
52
53
* Use the C++ Factor and Optimizer to solve a problem
53
54
* Read and understand the SymForce codebase
54
55
55
-
[**Read the docs!**](https://symforce-6d87c842-22de-4727-863b-e556dcc9093b.vercel.app/docs/index.html)
56
-
57
-
We know that currently some things will be slow, missing, or confusing. We're working on it, but please let us know what you encounter.
58
-
59
-
In the future we will share a survey with specific questions, but more generally we are interested in all feedback you can provide about the value of the library, comparisons to alternatives, and any guidance to us.
56
+
[**Read the docs!**](https://symforce.org)
60
57
61
58
# Build from source
62
59
63
-
<spanstyle="color:blue">TODO: Create wheels for <codestyle="color:blue"><b>pip install symforce</b></code></span>
64
-
65
60
SymForce requires Python 3.8 or later. We suggest using conda or virtualenv:
66
61
67
62
```
@@ -114,6 +109,8 @@ Verify the installation in Python:
114
109
>>> geo.Rot3()
115
110
```
116
111
112
+
<spanstyle="color:blue">TODO: Create wheels for <codestyle="color:blue"><b>pip install symforce</b></code></span>
113
+
117
114
# Tutorial
118
115
119
116
Let's walk through a simple example of modeling and solving an optimization problem with SymForce. In this example a robot moves through a 2D plane and the goal is to estimate its pose at multiple time steps given noisy measurements.
Now we can create [`Factor`](https://symforce-6d87c842-22de-4727-863b-e556dcc9093b.vercel.app/docs/api/symforce.opt.factor.html) objects from the residual functions and a set of keys. The keys are named strings for the function arguments, which will be accessed by name from a [`Values`](https://symforce-6d87c842-22de-4727-863b-e556dcc9093b.vercel.app/docs/api/symforce.values.values.html) class we later instantiate with numerical quantities.
233
+
Now we can create [`Factor`](https://symforce.org/api/symforce.opt.factor.html?highlight=factor#module-symforce.opt.factor) objects from the residual functions and a set of keys. The keys are named strings for the function arguments, which will be accessed by name from a [`Values`](https://symforce.org/api/symforce.values.values.html) class we later instantiate with numerical quantities.
237
234
238
235
```python
239
236
from symforce.opt.factor import Factor
@@ -267,7 +264,7 @@ Here is a visualization of the structure of this factor graph:
267
264
268
265
Our goal is to find poses of the robot that minimize the residual of this factor graph, assuming the
269
266
landmark positions in the world are known. We create an
with these factors and tell it to only optimize the pose keys (the rest are held constant):
272
269
```python
273
270
from symforce.opt.optimizer import Optimizer
@@ -280,7 +277,7 @@ optimizer = Optimizer(
280
277
)
281
278
```
282
279
283
-
Now we need to instantiate numerical [`Values`](https://symforce-6d87c842-22de-4727-863b-e556dcc9093b.vercel.app/docs/api/symforce.values.values.html) for the problem, including an initial guess for our unknown poses (just set them to identity).
280
+
Now we need to instantiate numerical [`Values`](https://symforce.org/api/symforce.values.values.html?highlight=values#module-symforce.values.values) for the problem, including an initial guess for our unknown poses (just set them to identity).
284
281
285
282
```python
286
283
import numpy as np
@@ -295,7 +292,7 @@ initial_values = Values(
295
292
)
296
293
```
297
294
298
-
Now run the optimization! This returns an [`Optimizer.Result`](https://symforce-6d87c842-22de-4727-863b-e556dcc9093b.vercel.app/docs/api/symforce.opt.optimizer.html#symforce.opt.optimizer.Optimizer.Result) object that contains the optimized values, error statistics, and per-iteration debug stats (if enabled).
295
+
Now run the optimization! This returns an [`Optimizer.Result`](https://symforce.org/api/symforce.opt.optimizer.html?highlight=optimizer#symforce.opt.optimizer.Optimizer.Result) object that contains the optimized values, error statistics, and per-iteration debug stats (if enabled).
299
296
```python
300
297
result = optimizer.optimize(initial_values)
301
298
```
@@ -315,24 +312,24 @@ All of the code for this example can also be found in `symforce/examples/robot_2
315
312
316
313
SymForce provides `sym` packages with runtime code for geometry and camera types that are generated from its symbolic `geo` and `cam` packages. As such, there are multiple versions of a class like `Pose3` and it can be a common source of confusion.
317
314
318
-
The canonical symbolic class [`geo.Pose3`](https://symforce-6d87c842-22de-4727-863b-e556dcc9093b.vercel.app/docs/api/symforce.geo.pose3.html) lives in the `symforce` package:
315
+
The canonical symbolic class [`geo.Pose3`](https://symforce.org/api/symforce.geo.pose3.html) lives in the `symforce` package:
319
316
```python
320
317
from symforce import geo
321
318
geo.Pose3.identity()
322
319
```
323
320
324
-
The autogenerated Python runtime class [`sym.Pose3`](https://symforce-6d87c842-22de-4727-863b-e556dcc9093b.vercel.app/docs/api-gen-py/sym.pose3.html) lives in the `sym` package:
321
+
The autogenerated Python runtime class [`sym.Pose3`](https://symforce.org/api-gen-py/sym.pose3.html?highlight=pose3#module-sym.pose3) lives in the `sym` package:
325
322
```python
326
323
import sym
327
324
sym.Pose3.identity()
328
325
```
329
326
330
-
The autogenerated C++ runtime class [`sym::Pose3`](https://symforce-6d87c842-22de-4727-863b-e556dcc9093b.vercel.app/docs/api-gen-cpp/class/classsym_1_1Pose3.html) lives in the `sym::` namespace:
327
+
The autogenerated C++ runtime class [`sym::Pose3`](https://symforce.org/api-gen-cpp/class/classsym_1_1Pose3.html) lives in the `sym::` namespace:
331
328
```C++
332
329
sym::Pose3<double>::Identity()
333
330
```
334
331
335
-
The matrix type for symbolic code is [`geo.Matrix`](https://symforce-6d87c842-22de-4727-863b-e556dcc9093b.vercel.app/docs/api/symforce.geo.matrix.html), for generated Python is [`numpy.ndarray`](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html), and for C++ is [`Eigen::Matrix`](https://eigen.tuxfamily.org/dox/group__TutorialMatrixClass.html).
332
+
The matrix type for symbolic code is [`geo.Matrix`](https://symforce.org/api/symforce.geo.matrix.html?highlight=matrix#module-symforce.geo.matrix), for generated Python is [`numpy.ndarray`](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html), and for C++ is [`Eigen::Matrix`](https://eigen.tuxfamily.org/dox/group__TutorialMatrixClass.html).
336
333
337
334
The symbolic classes can also handle numerical values, but will be dramatically slower than the generated classes. The symbolic classes must be used when defining functions for codegen and optimization. Generated functions always accept the runtime types.
338
335
@@ -344,7 +341,7 @@ As a convenience, the Python `Optimizer` class can accept symbolic types in its
344
341
345
342
Let's look under the hood to understand how that optimization worked. For each factor, SymForce introspects the form of the symbolic function, passes through symbolic inputs to build an output expression, automatically computes tangent-space jacobians of those output expressions wrt the optimized variables, and generates fast runtime code for them.
346
343
347
-
The [`Codegen`](https://symforce-6d87c842-22de-4727-863b-e556dcc9093b.vercel.app/docs/api/symforce.codegen.codegen.html) class is the central tool for generating runtime code from symbolic expressions. In this case, we pass it the bearing residual function and configure it to generate C++ code:
344
+
The [`Codegen`](https://symforce.org/api/symforce.codegen.codegen.html?highlight=codegen#module-symforce.codegen.codegen) class is the central tool for generating runtime code from symbolic expressions. In this case, we pass it the bearing residual function and configure it to generate C++ code:
348
345
```python
349
346
from symforce.codegen import Codegen, CppConfig
350
347
@@ -540,17 +537,25 @@ $ -->
540
537
541
538
# Learn More
542
539
543
-
You can find more SymForce tutorials [here](https://symforce-6d87c842-22de-4727-863b-e556dcc9093b.vercel.app/docs/index.html#guides).
540
+
You can find more SymForce tutorials [here](https://symforce.org/#guides).
544
541
545
542
# License
546
543
547
-
SymForce is released under the [BSD-3](https://opensource.org/licenses/BSD-3-Clause) license.
544
+
SymForce is released under the [Apache 2.0](https://spdx.org/licenses/Apache-2.0.html) license.
548
545
549
546
See the LICENSE file for more information.
550
547
548
+
# Sponsors
549
+
550
+
SymForce is developed and maintained by [Skydio](https://skydio.com/). It is released as a free and open-source library for the robotics community. Contributors to the project are welcome!
0 commit comments