Skip to content

Commit

Permalink
sophus_{autodiff,geo,lie} docs
Browse files Browse the repository at this point in the history
  • Loading branch information
strasdat committed Feb 16, 2025
1 parent 079b512 commit e53446f
Show file tree
Hide file tree
Showing 96 changed files with 2,288 additions and 1,081 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
steps:
- name: Checkout workspace
uses: actions/checkout@v3
- uses: extractions/setup-just@v1
- name: Install pre-commit and install
run: |
pip install pre-commit
Expand All @@ -22,8 +23,13 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
- name: cargo fmt
run: |
rustup default nightly
rustup component add rustfmt
just format
- name: cargo doc
run: |
rustup default nightly
rustup component add rustfmt
cargo fmt
just doc
17 changes: 5 additions & 12 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,22 @@ jobs:
run: ${SCCACHE_PATH} --show-stats
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2024-12-01
toolchain: nightly
- uses: extractions/setup-just@v1
- name: cargo build
env:
SCCACHE_GHA_ENABLED: "true"
RUSTC_WRAPPER: "sccache"
run: |
rustup default nightly-2024-12-01
cargo build --release --all-targets --all-features
rustup default nightly
just build-simd
- name: cargo test
env:
SCCACHE_GHA_ENABLED: "true"
RUSTC_WRAPPER: "sccache"
run: |
rustup default nightly-2024-12-01
just test
- name: cargo docs
env:
SCCACHE_GHA_ENABLED: "true"
RUSTC_WRAPPER: "sccache"
run: |
rustup default nightly-2024-12-01
cargo doc --no-deps --all-features
rustup default nightly
just test-simd
- name: Run sccache stat for check after
shell: bash
run: ${SCCACHE_PATH} --show-stats
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ nalgebra = { version = "0.33.2", features = ["rand", "bytemuck"] }
ndarray = { version = "0.15", features = ["approx-0_5"] }
num-traits = "0.2"
rand = "0.8"
rustc_version = "0.4"
snafu = "0.8.5"
typenum = { version = "1.17", features = ["const-generics"] }
winit = { version = "0.30.5", features = ["android-native-activity"] }
Expand Down
144 changes: 133 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,108 @@ sophus-rs is a Rust library for 2d and 3d geometry for Computer Vision and Robot
It is a spin-off of the [Sophus](https://github.com/strasdat/Sophus) C++ library which
focuses on *Lie groups* (e.g. rotations and transformations in 2d and 3d).

In addition to Lie groups, sophus-rs also includes other geometric/maths concepts such unit vector,
splines, image classes, camera models as well as a other utilities such as a non-linear least
squares optimization.
In addition to Lie groups, sophus-rs also includes other geometric/maths concepts.

## Status
## Automatic differentiation

This library is in an early development stage - hence API is highly unstable. It is likely that
existing features will be removed or changed in the future.
sophus-rs provides an automatic differentiation using dual numbers such as
[autodiff::dual::DualScalar] and [autodiff::dual::DualVector].

```
use sophus::prelude::*;
use sophus::autodiff::dual::{DualScalar, DualVector};
use sophus::autodiff::linalg::VecF64;
use sophus::autodiff::maps::VectorValuedVectorMap;
// [[ x ]] [[ x / z ]]
// proj [[ y ]] = [[ ]]
// [[ z ]] [[ y / z ]]
fn proj_fn<S: IsSingleScalar<DM, DN>, const DM: usize, const DN: usize>(
v: S::Vector<3>,
) -> S::Vector<2> {
let x = v.elem(0);
let y = v.elem(1);
let z = v.elem(2);
S::Vector::<2>::from_array([x / z, y / z])
}
let a = VecF64::<3>::new(1.0, 2.0, 3.0);
// Finite difference Jacobian
let finite_diff = VectorValuedVectorMap::<f64, 1>::sym_diff_quotient_jacobian(
proj_fn::<f64, 0, 0>,
a,
0.0001,
);
// Automatic differentiation Jacobian
let auto_diff = proj_fn::<DualScalar<3, 1>, 3, 1>(DualVector::var(a)).jacobian();
approx::assert_abs_diff_eq!(finite_diff, auto_diff, epsilon = 0.0001);
```

Note that proj_fn is a function that takes a 3D vector and returns a 2D vector. The Jacobian of
proj_fn is 2x3 matrix. When a (three dimensional) dual vector is passed to proj_fn, then
a 2d dual vector is returned. Since we are expecting a 2x3 Jacobian, each element of the 2d dual
vector must represent 3x1 Jacobian. This is why we use DualScalar<3, 1> as the scalar type.

## Lie Groups

sophus-rs provides a number of Lie groups, including:

* The group of 2D rotations, [lie::Rotation2], also known as the special orthogonal group SO(2),
* the group of 3D rotations, [lie::Rotation3], also known as the special orthogonal group SO(3),
* the group of 2d isometries, [lie::Isometry2], also known as the Euclidean group SE(2), and
* the group of 3d isometries, [lie::Isometry3], also known as the Euclidean group SE(3).


```
use sophus::autodiff::linalg::VecF64;
use sophus::lie::{Rotation3F64, Isometry3F64};
use std::f64::consts::FRAC_PI_4;
// Create a rotation around the z-axis by 45 degrees.
let world_from_foo_rotation = Rotation3F64::rot_z(FRAC_PI_4);
// Create a translation in 3D.
let foo_in_world = VecF64::<3>::new(1.0, 2.0, 3.0);
// Combine them into an SE(3) transform.
let world_from_foo_isometry
= Isometry3F64::from_translation_and_rotation(foo_in_world, world_from_foo_rotation);
// Apply world_from_foo_isometry to a 3D point in the foo reference frame.
let point_in_foo = VecF64::<3>::new(10.0, 0.0, 0.0);
let point_in_world = world_from_foo_isometry.transform(&point_in_foo);
// Manually compute the expected transformation:
// - rotate (10, 0, 0) around z by 45°
// - then translate by (1, 2, 3)
let angle = FRAC_PI_4;
let cos = angle.cos();
let sin = angle.sin();
let expected_point_in_world = VecF64::<3>::new(1.0 + 10.0 * cos, 2.0 + 10.0 * sin, 3.0);
approx::assert_abs_diff_eq!(point_in_world[0], expected_point_in_world[0], epsilon = 1e-9);
approx::assert_abs_diff_eq!(point_in_world[1], expected_point_in_world[1], epsilon = 1e-9);
approx::assert_abs_diff_eq!(point_in_world[2], expected_point_in_world[2], epsilon = 1e-9);
// Map isometry to 6-dimensional tangent space.
let omega = world_from_foo_isometry.log();
// Map tangent space element back to the manifold.
let roundtrip_world_from_foo_isometry = Isometry3F64::exp(&omega);
approx::assert_abs_diff_eq!(roundtrip_world_from_foo_isometry.matrix(),
world_from_foo_isometry.matrix(),
epsilon = 1e-9);
// Compose with another isometry.
let world_from_bar_isometry = Isometry3F64::rot_y(std::f64::consts::FRAC_PI_6);
let bar_from_foo_isometry = world_from_bar_isometry.inverse() * world_from_foo_isometry;
```

## And more...

such unit vector, splines, image classes, camera models, non-linear least squares optimization and
some visualization tools. Check out the [documentation](https://docs.rs/sophus) for more information.

However, the intend is to stride for correctness, facilitated by a comprehensive test suite.

## Building

Expand All @@ -31,12 +123,42 @@ sophus-rs builds on stable.
sophus = "0.12.0"
```

```toml
[dependencies]
sophus = { version = "0.12.0", features = ["simd"] }
```

To allow for batch types, such as BatchScalarF64, the 'simd' feature is required. This feature
depends on [`portable-simd`](https://doc.rust-lang.org/std/simd/index.html), which is currently
only available on [nightly](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html). There
are no plans to rely on any other nightly features.

```toml
[dependencies]
sophus = { version = "0.12.0", features = ["simd"] }
```
## Crate Structure and Usage

sophus-rs is an **umbrella crate** that provides a single entry point to multiple
sub-crates (modules) under the `sophus::` namespace. For example, the automatic differentiation
sub-crate can be accessed via `use sophus::autodiff`, and the lie group sub-crate via
`use sophus::lie`, etc.

- If you want all of sophus’s functionalities at once (geometry, AD, manifolds, etc.),
simply add `sophus` in your `Cargo.toml`, and then in your Rust code:

```rust
use sophus::prelude::*;
use sophus::autodiff::dual::DualScalar;
// ...
```

- If you only need the autodiff functionalities in isolation, you can also depend on the
standalone crate underlying `sophus_autodiff`.

```rust
use sophus_autodiff::prelude::*;
use sophus_autodiff::dual::DualScalar;
// ...
```

## Status

This library is in an early development stage - hence API is highly unstable. It is likely that
existing features will be removed or changed in the future.
3 changes: 3 additions & 0 deletions crates/sophus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ thingbuf.workspace = true
tokio = { version = "1", features = ["full"] }
wgpu.workspace = true

[build-dependencies]
rustc_version.workspace = true


[features]
simd = [
Expand Down
10 changes: 10 additions & 0 deletions crates/sophus/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
fn main() {
println!("cargo:rustc-check-cfg=cfg(nightly)"); // Declares 'nightly' as a valid cfg condition

let is_nightly =
rustc_version::version_meta().unwrap().channel == rustc_version::Channel::Nightly;

if is_nightly {
println!("cargo:rustc-cfg=nightly");
}
}
15 changes: 15 additions & 0 deletions crates/sophus/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#![cfg_attr(feature = "simd", feature(portable_simd))]
#![allow(clippy::needless_range_loop)]
#![doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
#![cfg_attr(nightly, feature(doc_auto_cfg))]

#[doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
#[cfg(doctest)]
pub struct ReadmeDoctests;

#[doc(inline)]
pub use sophus_autodiff as autodiff;
Expand All @@ -27,12 +32,22 @@ pub use sophus_timeseries as timeseries;
#[doc(inline)]
pub use sophus_viewer as viewer;

/// Examples for the `sophus` umbrella crate. Note that this is not a comprehensive list of
/// examples, and most usage examples are found in the individual sub-crates. In particular, the
/// unit tests in each sub-crate are a good source of examples.
pub mod examples;
pub use eframe;
pub use nalgebra;
pub use ndarray;
pub use thingbuf;

/// sophus prelude.
///
/// It is recommended to import this prelude when working with `sophus` types:
///
/// ```
/// use sophus_autodiff::prelude::*;
/// ```
pub mod prelude {
pub use crate::{
autodiff::prelude::*,
Expand Down
5 changes: 4 additions & 1 deletion crates/sophus_autodiff/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
description = "sophus - geometry for robotics and computer vision"
name = "sophus_autodiff"
readme = "../../README.md"
readme = "../README.md"

edition.workspace = true
include.workspace = true
Expand All @@ -21,6 +21,9 @@ typenum.workspace = true

sleef = {version = "0.3", optional = true}

[build-dependencies]
rustc_version.workspace = true

[features]
simd = ["sleef"]
std = []
Expand Down
Loading

0 comments on commit e53446f

Please sign in to comment.