Skip to content

Commit

Permalink
flatten namespaces and more doc tweaks (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
strasdat authored Feb 17, 2025
1 parent b9f9dd1 commit 58da6ca
Show file tree
Hide file tree
Showing 151 changed files with 1,224 additions and 1,064 deletions.
68 changes: 42 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@

## Overview

sophus-rs is a Rust library for 2d and 3d geometry for Computer Vision and Robotics applications.
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).
sophus-rs is a Rust library for 2d and 3d geometry for Computer Vision and
Robotics applications. 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.
In addition to Lie groups, sophus-rs also includes other geometric/maths
concepts.

## Automatic differentiation

Expand Down Expand Up @@ -44,24 +46,30 @@ let finite_diff = VectorValuedVectorMap::<f64, 1>::sym_diff_quotient_jacobian(
0.0001,
);
// Automatic differentiation Jacobian
let auto_diff = proj_fn::<DualScalar<3, 1>, 3, 1>(DualVector::var(a)).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.
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).
* 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
Special Euclidean group SE(2), and
* the group of 3d isometries, [lie::Isometry3], also known as the
Spevial Euclidean group SE(3).


```
Expand All @@ -77,7 +85,9 @@ 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);
= 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);
Expand All @@ -89,11 +99,11 @@ let point_in_world = world_from_foo_isometry.transform(&point_in_foo);
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);
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);
approx::assert_abs_diff_eq!(
point_in_world, expected_point_in_world, epsilon = 1e-9);
// Map isometry to 6-dimensional tangent space.
let omega = world_from_foo_isometry.log();
Expand All @@ -105,13 +115,19 @@ approx::assert_abs_diff_eq!(roundtrip_world_from_foo_isometry.matrix(),
// 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;
let bar_from_foo_isometry
= world_from_bar_isometry.inverse() * world_from_foo_isometry;
```

## Sparse non-linear least squares optimization

sophus-rs also provides a sparse non-linear least squares optimization through
[crate::opt].

## 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.
such unit vector, splines, image classes, camera models, and some visualization
tools. Check out the [documentation](https://docs.rs/sophus) for more information.


## Building
Expand All @@ -123,16 +139,16 @@ sophus-rs builds on stable.
sophus = "0.13.0"
```

```toml
[dependencies]
sophus = { version = "0.13.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.13.0", features = ["simd"] }
```

## Crate Structure and Usage

sophus-rs is an **umbrella crate** that provides a single entry point to multiple
Expand Down
18 changes: 8 additions & 10 deletions crates/sophus/examples/camera_sim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,23 @@

use sophus::{
lie::Isometry3,
prelude::IsImageView,
prelude::*,
sim::camera_simulator::CameraSimulator,
};
use sophus_image::{
io::{
png::save_as_png,
tiff::save_as_tiff,
save_as_png,
save_as_tiff,
},
ImageSize,
};
use sophus_renderer::{
camera::properties::RenderCameraProperties,
camera::RenderCameraProperties,
renderables::{
color::Color,
scene_renderable::{
make_line3,
make_mesh3_at,
make_point3,
},
make_line3,
make_mesh3_at,
make_point3,
Color,
},
RenderContext,
};
Expand Down
46 changes: 19 additions & 27 deletions crates/sophus/examples/viewer_ex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,43 @@ use sophus::{
examples::viewer_example::make_distorted_frame,
lie::Isometry3,
prelude::*,
sensor::dyn_camera::DynCameraF64,
sensor::DynCameraF64,
};
use sophus_image::{
intensity_image::intensity_arc_image::IsIntensityArcImage,
mut_image::MutImageF32,
mut_image_view::IsMutImageView,
ImageSize,
MutImageF32,
};
use sophus_renderer::{
camera::{
clipping_planes::ClippingPlanes,
properties::RenderCameraProperties,
ClippingPlanes,
RenderCamera,
RenderCameraProperties,
},
renderables::{
color::Color,
frame::ImageFrame,
pixel_renderable::{
make_line2,
make_point2,
},
scene_renderable::{
make_line3,
make_mesh3_at,
make_point3,
},
make_line2,
make_line3,
make_mesh3_at,
make_point2,
make_point3,
Color,
ImageFrame,
},
RenderContext,
};
use sophus_viewer::{
packets::{
append_to_scene_packet,
create_scene_packet,
image_view_packet::ImageViewPacket,
plot_view_packet::{
curve_vec_with_conf::CurveVecWithConfStyle,
scalar_curve::ScalarCurveStyle,
vec_curve::CurveVecStyle,
ClearCondition,
LineType,
PlotViewPacket,
},
ClearCondition,
CurveVecStyle,
CurveVecWithConfStyle,
ImageViewPacket,
LineType,
Packet,
PlotViewPacket,
ScalarCurveStyle,
},
simple_viewer::SimpleViewer,
SimpleViewer,
};
use thingbuf::mpsc::blocking::channel;

Expand Down
12 changes: 6 additions & 6 deletions crates/sophus/src/examples/viewer_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ use sophus_autodiff::{
prelude::IsVector,
};
use sophus_image::{
arc_image::ArcImage4U8,
mut_image::MutImage4U8,
mut_image_view::IsMutImageView,
prelude::*,
ArcImage4U8,
ImageSize,
MutImage4U8,
};
use sophus_renderer::{
camera::properties::RenderCameraProperties,
renderables::frame::ImageFrame,
camera::RenderCameraProperties,
renderables::ImageFrame,
};
use sophus_sensor::dyn_camera::DynCameraF64;
use sophus_sensor::DynCameraF64;

/// Makes example image of image-size
pub fn make_example_image(image_size: ImageSize) -> ArcImage4U8 {
Expand Down
9 changes: 6 additions & 3 deletions crates/sophus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ 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
/// Non-comprehensive list of examples.
///
/// This is *not a comprehensive list* of examples for the *sophus umbrella crate*.
/// The current focus is on the sophus render and camera simulation modules. 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;
Expand All @@ -46,7 +49,7 @@ pub use thingbuf;
/// It is recommended to import this prelude when working with `sophus` types:
///
/// ```
/// use sophus_autodiff::prelude::*;
/// use sophus::prelude::*;
/// ```
pub mod prelude {
pub use crate::{
Expand Down
2 changes: 1 addition & 1 deletion crates/sophus_autodiff/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
description = "sophus - geometry for robotics and computer vision"
description = "automatic differentiation with optional SIMD acceleration"
name = "sophus_autodiff"
readme = "README.md"

Expand Down
60 changes: 37 additions & 23 deletions crates/sophus_autodiff/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
## Automatic differentiation with optional SIMD acceleration

This crate provides traits, structs, and helper functions to enable automatic
differentiation (AD) through the use of dual numbers. In particular, it defines
*dual scalar*, *dual vector*, and *dual matrix* types, along with their SIMD
"batch" counterparts, for forward-mode AD in both scalar and vector/matrix contexts.
"batch" counterparts, for forward-mode AD in both scalar and vector/matrix
contexts.

## Overview

Expand All @@ -16,29 +19,31 @@ The primary interfaces are defined by traits in [crate::linalg]:
- **Real types** are your basic floating-point types ([f64], etc.).
- **Dual types** extend these scalars, vectors, or matrices to store partial
derivatives (the “infinitesimal” part) in addition to the real value.
- **Batch real types** and **batch dual types** leverage Rust’s `portable_simd` to
process multiple derivatives or computations in parallel.
- **Batch real types** and **batch dual types** leverage Rust’s `portable_simd`
to process multiple derivatives or computations in parallel.

**Note:** Batch types such as [linalg::BatchScalarF64], [linalg::BatchVecF64], and
[linalg::BatchMatF64] require enabling the `"simd"` feature in your `Cargo.toml`.
**Note:** Batch types such as [linalg::BatchScalarF64], [linalg::BatchVecF64],
and [linalg::BatchMatF64] require enabling the `"simd"` feature in your
`Cargo.toml`.

## Numerical differentiation
In addition to forward-mode AD via dual numbers, this module also contains functionality
to compute numerical derivatives (finite differences) of your functions in various shapes:
In addition to forward-mode AD via dual numbers, this module also contains
functionality to compute numerical derivatives (finite differences) of your
functions in various shapes:

* **Curves,** functions which take a scalar input:
- f: ℝ -> ℝ, [maps::ScalarValuedCurve]
- f: ℝ -> ℝʳ, [maps::VectorValuedCurve]
- f: ℝ -> ℝʳˣᶜ, [maps::MatrixValuedCurve]
- `f: ℝ -> ℝ`, [maps::ScalarValuedCurve]
- `f: ℝ -> ℝʳ`, [maps::VectorValuedCurve]
- `f: ℝ -> ℝʳˣᶜ`, [maps::MatrixValuedCurve]
* **Scalar-valued maps**, functions which return a scalar:
- f: ℝᵐ -> ℝ, [maps::ScalarValuedVectorMap]
- f: ℝᵐˣⁿ -> ℝ, [maps::ScalarValuedMatrixMap]
- `f: ℝᵐ -> ℝ`, [maps::ScalarValuedVectorMap]
- `f: ℝᵐˣⁿ -> ℝ`, [maps::ScalarValuedMatrixMap]
* **Vector-valued maps**, functions which return a vector:
- f: ℝᵐ -> ℝᵖ, [maps::VectorValuedVectorMap]
- f: ℝᵐˣⁿ -> ℝᵖ, [maps::VectorValuedMatrixMap]
- `f: ℝᵐ -> ℝᵖ`, [maps::VectorValuedVectorMap]
- `f: ℝᵐˣⁿ -> ℝᵖ`, [maps::VectorValuedMatrixMap]
* **Matrix-valued maps**, functions which return a matrix:
- f: ℝᵐ -> ℝʳˣᶜ, [maps::MatrixValuedVectorMap]
- f: ℝᵐˣⁿ -> ℝʳˣᶜ, [maps::MatrixValuedMatrixMap]
- `f: ℝᵐ -> ℝʳˣᶜ`, [maps::MatrixValuedVectorMap]
- `f: ℝᵐˣⁿ -> ℝʳˣᶜ`, [maps::MatrixValuedMatrixMap]

You’ll find the associated functions for finite-difference computations in the
[maps submodule][crate::maps].
Expand All @@ -52,7 +57,7 @@ use sophus_autodiff::dual::{DualScalar, DualVector};
use sophus_autodiff::maps::VectorValuedVectorMap;
use sophus_autodiff::linalg::VecF64;

// Suppose we have a function f: ℝ³ → ℝ²
// Suppose we have a function `f: ℝ³ → ℝ²`
//
// [[ x ]] [[ x / z ]]
// f [[ y ]] = [[ ]]
Expand All @@ -76,15 +81,17 @@ let fd_jacobian = VectorValuedVectorMap::<f64, 1>::sym_diff_quotient_jacobian(
);

// (2) Forward-mode autodiff using dual numbers:
let auto_jacobian = proj_fn::<DualScalar<3, 1>, 3, 1>(DualVector::var(input)).jacobian();
let auto_jacobian =
proj_fn::<DualScalar<3, 1>, 3, 1>(DualVector::var(input)).jacobian();

// Compare the two results:
approx::assert_abs_diff_eq!(fd_jacobian, auto_jacobian, epsilon = 1e-5);
```

By using the [dual::DualScalar] (or [dual::DualVector], etc.) approach, we get the Jacobian
via forward-mode autodiff. Alternatively, we can use finite differences for
functions that might not be easily retrofitted with dual numbers.
By using the [dual::DualScalar] (or [dual::DualVector], etc.) approach, we get
the Jacobian via forward-mode autodiff. Alternatively, we can use finite
differences for functions that might not be easily retrofitted with dual
numbers.

## See Also

Expand All @@ -95,5 +102,12 @@ functions that might not be easily retrofitted with dual numbers.

## Feature Flags

- `"simd"`: Enables batch types like [dual::DualBatchScalar], [linalg::BatchVecF64], etc.
which require Rust’s nightly `portable_simd` feature.
- `"simd"`: Enables batch types like [dual::DualBatchScalar],
[linalg::BatchVecF64], etc. which require Rust’s nightly `portable_simd`
feature.

## Integration with sophus-rs

This crate is part of the [sophus umbrella crate](https://crates.io/crates/sophus).
It re-exports the relevant prelude types under [prelude], so you can
seamlessly interoperate with the rest of the sophus-rs types.
Loading

0 comments on commit 58da6ca

Please sign in to comment.