diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 744dd41..abea273 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -20,21 +20,21 @@ jobs: run: ${SCCACHE_PATH} --show-stats - uses: actions-rs/toolchain@v1 with: - toolchain: nightly-2024-09-01 + toolchain: nightly + - uses: extractions/setup-just@v1 - name: cargo build env: SCCACHE_GHA_ENABLED: "true" RUSTC_WRAPPER: "sccache" run: | - rustup default nightly-2024-09-01 + rustup default nightly cargo build --release --all-targets --all-features - name: cargo test env: SCCACHE_GHA_ENABLED: "true" RUSTC_WRAPPER: "sccache" run: | - rustup default nightly-2024-09-01 - cargo test --release --all-features + just test - name: Run sccache stat for check after shell: bash run: ${SCCACHE_PATH} --show-stats diff --git a/.github/workflows/stable.yml b/.github/workflows/stable.yml index 05c3a9d..9b565b7 100644 --- a/.github/workflows/stable.yml +++ b/.github/workflows/stable.yml @@ -18,6 +18,7 @@ jobs: - name: Run sccache stat for check before shell: bash run: ${SCCACHE_PATH} --show-stats + - uses: extractions/setup-just@v1 - uses: actions-rs/toolchain@v1 with: toolchain: stable @@ -27,6 +28,7 @@ jobs: RUSTC_WRAPPER: "sccache" run: | cargo build --release --all-targets + just build-std - name: cargo test env: SCCACHE_GHA_ENABLED: "true" diff --git a/Cargo.toml b/Cargo.toml index d29f29d..6eeabbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,28 +34,20 @@ sophus_sensor = {path = "crates/sophus_sensor", version = "0.10.0"} approx = "0.5" as-any = "0.3" -assertables = "8.3" async-trait = "0.1" bytemuck = {version = "1.14", features = ["derive"]} concat-arrays = "0.1" dyn-clone = "1.0" env_logger = "0.11" faer = "0.19" -image = {version = "0.25", features = [ - "jpeg", - "png", - "tiff", -]} linked-hash-map = "0.5" log = "0.4" nalgebra = {version = "0.33", features = ["rand", "bytemuck"]} ndarray = {version = "0.15", features = ["approx-0_5"]} num-traits = "0.2" numpy = "0.21" -png = "0.17" rand = "0.8" -thiserror = "1.0" -tiff = "0.9.0" +snafu = "0.8.5" typenum = {version = "1.17", features = ["const-generics"]} winit = {version = "0.30", features = ["android-native-activity"]} diff --git a/crates/sophus/Cargo.toml b/crates/sophus/Cargo.toml index 65060e1..0222043 100644 --- a/crates/sophus/Cargo.toml +++ b/crates/sophus/Cargo.toml @@ -32,3 +32,4 @@ simd = [ "sophus_opt/simd", "sophus_sensor/simd", ] +std = [] diff --git a/crates/sophus_core/Cargo.toml b/crates/sophus_core/Cargo.toml index 491a539..226fcb2 100644 --- a/crates/sophus_core/Cargo.toml +++ b/crates/sophus_core/Cargo.toml @@ -12,16 +12,16 @@ version.workspace = true [dependencies] approx.workspace = true -assertables.workspace = true concat-arrays.workspace = true log.workspace = true nalgebra.workspace = true ndarray.workspace = true num-traits.workspace = true -thiserror.workspace = true +snafu.workspace = true typenum.workspace = true sleef = {version = "0.3", optional = true} [features] simd = ["sleef"] +std = [] diff --git a/crates/sophus_core/src/calculus/dual/dual_batch_matrix.rs b/crates/sophus_core/src/calculus/dual/dual_batch_matrix.rs index 4d95127..1a06a71 100644 --- a/crates/sophus_core/src/calculus/dual/dual_batch_matrix.rs +++ b/crates/sophus_core/src/calculus/dual/dual_batch_matrix.rs @@ -10,15 +10,15 @@ use crate::tensor::mut_tensor::MutTensorDDR; use crate::tensor::mut_tensor::MutTensorDDRC; use approx::AbsDiffEq; use approx::RelativeEq; +use core::fmt::Debug; +use core::ops::Add; +use core::ops::Mul; +use core::ops::Neg; +use core::ops::Sub; +use core::simd::LaneCount; +use core::simd::Mask; +use core::simd::SupportedLaneCount; use num_traits::Zero; -use std::fmt::Debug; -use std::ops::Add; -use std::ops::Mul; -use std::ops::Neg; -use std::ops::Sub; -use std::simd::LaneCount; -use std::simd::Mask; -use std::simd::SupportedLaneCount; use crate::calculus::dual::dual_matrix::DijPairM; @@ -686,7 +686,7 @@ impl Debug where LaneCount: SupportedLaneCount, { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if self.dij_part.is_some() { f.debug_struct("DualScalarLike") .field("val", &self.real_part) diff --git a/crates/sophus_core/src/calculus/dual/dual_batch_scalar.rs b/crates/sophus_core/src/calculus/dual/dual_batch_scalar.rs index c1403d9..8b1c4b4 100644 --- a/crates/sophus_core/src/calculus/dual/dual_batch_scalar.rs +++ b/crates/sophus_core/src/calculus/dual/dual_batch_scalar.rs @@ -9,22 +9,25 @@ use crate::linalg::EPS_F64; use crate::prelude::*; use crate::tensor::mut_tensor::InnerScalarToVec; use crate::tensor::mut_tensor::MutTensorDD; +use alloc::vec::Vec; use approx::assert_abs_diff_eq; use approx::AbsDiffEq; use approx::RelativeEq; +use core::fmt::Debug; +use core::ops::Add; +use core::ops::AddAssign; +use core::ops::Div; +use core::ops::Mul; +use core::ops::Neg; +use core::ops::Sub; +use core::ops::SubAssign; +use core::simd::LaneCount; +use core::simd::Mask; +use core::simd::SupportedLaneCount; use num_traits::One; use num_traits::Zero; -use std::fmt::Debug; -use std::ops::Add; -use std::ops::AddAssign; -use std::ops::Div; -use std::ops::Mul; -use std::ops::Neg; -use std::ops::Sub; -use std::ops::SubAssign; -use std::simd::LaneCount; -use std::simd::Mask; -use std::simd::SupportedLaneCount; + +extern crate alloc; /// Dual number - a real number and an infinitesimal number (batch version) #[derive(Clone)] @@ -267,7 +270,7 @@ where BatchScalarF64: IsCoreScalar, LaneCount: SupportedLaneCount, { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if self.dij_part.is_some() { f.debug_struct("DualScalar") .field("val", &self.real_part) diff --git a/crates/sophus_core/src/calculus/dual/dual_batch_vector.rs b/crates/sophus_core/src/calculus/dual/dual_batch_vector.rs index d3c0c7c..712dab1 100644 --- a/crates/sophus_core/src/calculus/dual/dual_batch_vector.rs +++ b/crates/sophus_core/src/calculus/dual/dual_batch_vector.rs @@ -9,13 +9,13 @@ use crate::tensor::mut_tensor::MutTensorDD; use crate::tensor::mut_tensor::MutTensorDDR; use approx::AbsDiffEq; use approx::RelativeEq; -use std::fmt::Debug; -use std::ops::Add; -use std::ops::Neg; -use std::ops::Sub; -use std::simd::LaneCount; -use std::simd::Mask; -use std::simd::SupportedLaneCount; +use core::fmt::Debug; +use core::ops::Add; +use core::ops::Neg; +use core::ops::Sub; +use core::simd::LaneCount; +use core::simd::Mask; +use core::simd::SupportedLaneCount; /// Dual vector (batch version) #[derive(Clone, Debug)] diff --git a/crates/sophus_core/src/calculus/dual/dual_matrix.rs b/crates/sophus_core/src/calculus/dual/dual_matrix.rs index b110f81..892c5f2 100644 --- a/crates/sophus_core/src/calculus/dual/dual_matrix.rs +++ b/crates/sophus_core/src/calculus/dual/dual_matrix.rs @@ -8,12 +8,12 @@ use crate::tensor::mut_tensor::MutTensorDDR; use crate::tensor::mut_tensor::MutTensorDDRC; use approx::AbsDiffEq; use approx::RelativeEq; +use core::fmt::Debug; +use core::ops::Add; +use core::ops::Mul; +use core::ops::Neg; +use core::ops::Sub; use num_traits::Zero; -use std::fmt::Debug; -use std::ops::Add; -use std::ops::Mul; -use std::ops::Neg; -use std::ops::Sub; /// DualScalarLike matrix #[derive(Clone)] @@ -25,7 +25,7 @@ pub struct DualMatrix { } impl Debug for DualMatrix { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if self.dij_part.is_some() { f.debug_struct("DualScalarLike") .field("val", &self.real_part) diff --git a/crates/sophus_core/src/calculus/dual/dual_scalar.rs b/crates/sophus_core/src/calculus/dual/dual_scalar.rs index 26df1cd..e029508 100644 --- a/crates/sophus_core/src/calculus/dual/dual_scalar.rs +++ b/crates/sophus_core/src/calculus/dual/dual_scalar.rs @@ -1,28 +1,26 @@ use super::dual_matrix::DualMatrix; use super::dual_vector::DualVector; - use crate::linalg::scalar::NumberCategory; - use crate::linalg::MatF64; use crate::linalg::VecF64; use crate::linalg::EPS_F64; use crate::prelude::*; use crate::tensor::mut_tensor::InnerScalarToVec; use crate::tensor::mut_tensor::MutTensorDD; - use approx::AbsDiffEq; use approx::RelativeEq; +use core::fmt::Debug; +use core::ops::Add; +use core::ops::AddAssign; +use core::ops::Div; +use core::ops::Mul; +use core::ops::Neg; +use core::ops::Sub; +use core::ops::SubAssign; use num_traits::One; use num_traits::Zero; -use std::fmt::Debug; -use std::ops::Add; -use std::ops::AddAssign; -use std::ops::Div; -use std::ops::Mul; -use std::ops::Neg; -use std::ops::Sub; -use std::ops::SubAssign; +extern crate alloc; /// Trait for dual numbers pub trait IsDual {} @@ -234,7 +232,7 @@ impl PartialEq for DualScalar { } impl PartialOrd for DualScalar { - fn partial_cmp(&self, other: &Self) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { self.real_part.partial_cmp(&other.real_part) } } @@ -246,7 +244,7 @@ impl From for DualScalar { } impl Debug for DualScalar { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if self.dij_part.is_some() { f.debug_struct("DualScalar") .field("val", &self.real_part) @@ -467,7 +465,7 @@ impl IsScalar<1> for DualScalar { } } - fn scalar_examples() -> Vec { + fn scalar_examples() -> alloc::vec::Vec { [1.0, 2.0, 3.0].iter().map(|&v| Self::from_f64(v)).collect() } diff --git a/crates/sophus_core/src/calculus/dual/dual_vector.rs b/crates/sophus_core/src/calculus/dual/dual_vector.rs index 243e5a2..005b35c 100644 --- a/crates/sophus_core/src/calculus/dual/dual_vector.rs +++ b/crates/sophus_core/src/calculus/dual/dual_vector.rs @@ -7,10 +7,10 @@ use crate::tensor::mut_tensor::MutTensorDD; use crate::tensor::mut_tensor::MutTensorDDR; use approx::AbsDiffEq; use approx::RelativeEq; -use std::fmt::Debug; -use std::ops::Add; -use std::ops::Neg; -use std::ops::Sub; +use core::fmt::Debug; +use core::ops::Add; +use core::ops::Neg; +use core::ops::Sub; /// Dual vector #[derive(Clone)] @@ -228,7 +228,7 @@ impl Add for DualVector { } impl Debug for DualVector { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if self.dij_part.is_some() { f.debug_struct("DualScalarLike") .field("val", &self.real_part) diff --git a/crates/sophus_core/src/calculus/maps/curves.rs b/crates/sophus_core/src/calculus/maps/curves.rs index 61f32a4..ea0209c 100644 --- a/crates/sophus_core/src/calculus/maps/curves.rs +++ b/crates/sophus_core/src/calculus/maps/curves.rs @@ -8,7 +8,7 @@ use nalgebra::SVector; /// /// f: ℝ -> ℝ pub struct ScalarValuedCurve, const BATCH: usize> { - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } impl, const BATCH: usize> ScalarValuedCurve { @@ -44,7 +44,7 @@ impl, const BATCH: usize> ScalarValuedCurve { /// /// f: ℝ -> ℝʳ pub struct VectorValuedCurve, const BATCH: usize> { - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } impl, const BATCH: usize> VectorValuedCurve { @@ -79,7 +79,7 @@ impl, const BATCH: usize> VectorValuedCurve { /// This is a function which takes a scalar and returns a matrix: /// f: ℝ -> ℝʳ x ℝᶜ pub struct MatrixValuedCurve, const BATCH: usize> { - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } impl, const BATCH: usize> MatrixValuedCurve { diff --git a/crates/sophus_core/src/calculus/maps/matrix_valued_maps.rs b/crates/sophus_core/src/calculus/maps/matrix_valued_maps.rs index 0760f11..e42efdc 100644 --- a/crates/sophus_core/src/calculus/maps/matrix_valued_maps.rs +++ b/crates/sophus_core/src/calculus/maps/matrix_valued_maps.rs @@ -2,8 +2,8 @@ use crate::linalg::SMat; use crate::prelude::*; use crate::tensor::mut_tensor::MutTensorDDRC; use crate::tensor::mut_tensor::MutTensorDRC; +use core::marker::PhantomData; use nalgebra::SMatrix; -use std::marker::PhantomData; /// Matrix-valued map on a vector space. /// @@ -12,7 +12,7 @@ use std::marker::PhantomData; /// f: ℝᵐ -> ℝʳ x ℝᶜ /// pub struct MatrixValuedMapFromVector, const BATCH: usize> { - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } impl, const BATCH: usize> @@ -82,7 +82,7 @@ impl, const BATCH: usize> /// f: ℝᵐ x ℝⁿ -> ℝʳ x ℝᶜ /// pub struct MatrixValuedMapFromMatrix, const BATCH: usize> { - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } impl, const BATCH: usize> diff --git a/crates/sophus_core/src/calculus/maps/scalar_valued_maps.rs b/crates/sophus_core/src/calculus/maps/scalar_valued_maps.rs index 4face75..f4e41c3 100644 --- a/crates/sophus_core/src/calculus/maps/scalar_valued_maps.rs +++ b/crates/sophus_core/src/calculus/maps/scalar_valued_maps.rs @@ -10,7 +10,7 @@ use crate::tensor::mut_tensor::MutTensorDD; /// These functions are also called a scalar fields (on vector spaces). /// pub struct ScalarValuedMapFromVector, const BATCH: usize> { - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } impl, const BATCH: usize> ScalarValuedMapFromVector { @@ -73,7 +73,7 @@ impl, const BATCH: usize> ScalarValuedMapFromVector ℝ pub struct ScalarValuedMapFromMatrix, const BATCH: usize> { - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } impl, const BATCH: usize> ScalarValuedMapFromMatrix { diff --git a/crates/sophus_core/src/calculus/maps/vector_valued_maps.rs b/crates/sophus_core/src/calculus/maps/vector_valued_maps.rs index bbfb8d6..476db2e 100644 --- a/crates/sophus_core/src/calculus/maps/vector_valued_maps.rs +++ b/crates/sophus_core/src/calculus/maps/vector_valued_maps.rs @@ -2,7 +2,7 @@ use crate::linalg::SVec; use crate::prelude::*; use crate::tensor::mut_tensor::MutTensorDDR; use crate::tensor::mut_tensor::MutTensorDR; -use std::marker::PhantomData; +use core::marker::PhantomData; /// Vector-valued map on a vector space. /// @@ -13,7 +13,7 @@ use std::marker::PhantomData; /// These functions are also called vector fields (on vector space). /// pub struct VectorValuedMapFromVector, const BATCH: usize> { - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } impl, const BATCH: usize> @@ -134,7 +134,7 @@ impl, const BATCH: usize> /// This type of function is also called a vector field (on product spaces). /// pub struct VectorValuedMapFromMatrix, const BATCH: usize> { - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } impl, const BATCH: usize> VectorValuedMapFromMatrix { diff --git a/crates/sophus_core/src/calculus/region.rs b/crates/sophus_core/src/calculus/region.rs index 3a12812..98e5206 100644 --- a/crates/sophus_core/src/calculus/region.rs +++ b/crates/sophus_core/src/calculus/region.rs @@ -45,7 +45,7 @@ impl IRegion { } /// Traits for regions -pub trait IsRegion>: std::marker::Sized { +pub trait IsRegion>: core::marker::Sized { /// create unbounded region fn unbounded() -> Self; diff --git a/crates/sophus_core/src/calculus/spline.rs b/crates/sophus_core/src/calculus/spline.rs index d8ee22c..b3f453f 100644 --- a/crates/sophus_core/src/calculus/spline.rs +++ b/crates/sophus_core/src/calculus/spline.rs @@ -1,23 +1,24 @@ /// Cubic B-Spline details pub mod spline_segment; -use log::debug; - use crate::calculus::spline::spline_segment::CubicBSplineSegment; use crate::calculus::spline::spline_segment::SegmentCase; use crate::prelude::*; +use log::debug; + +extern crate alloc; /// Cubic B-Spline implementation pub struct CubicBSplineImpl { /// Control points - pub control_points: Vec>, + pub control_points: alloc::vec::Vec>, /// delta between control points pub delta_t: S, } impl CubicBSplineImpl { /// indices involved - pub fn idx_involved(&self, segment_idx: usize) -> Vec { + pub fn idx_involved(&self, segment_idx: usize) -> alloc::vec::Vec { let num = self.num_segments(); assert!(segment_idx < num); @@ -25,7 +26,7 @@ impl CubicBSplineImpl { let idx_0 = segment_idx; let idx_1 = segment_idx + 1; let idx_2 = (segment_idx + 2).min(self.control_points.len() - 1); - vec![idx_prev, idx_0, idx_1, idx_2] + alloc::vec![idx_prev, idx_0, idx_1, idx_2] } /// Interpolate @@ -139,7 +140,10 @@ pub struct CubicBSplineParams { impl CubicBSpline { /// create a new cubic B-Spline - pub fn new(control_points: Vec>, params: CubicBSplineParams) -> Self { + pub fn new( + control_points: alloc::vec::Vec>, + params: CubicBSplineParams, + ) -> Self { Self { spline_impl: CubicBSplineImpl { control_points, @@ -164,7 +168,7 @@ impl CubicBSpline { } /// indices involved - pub fn idx_involved(&self, t: S) -> Vec { + pub fn idx_involved(&self, t: S) -> alloc::vec::Vec { let index_and_u = self.index_and_u(t); self.spline_impl.idx_involved(index_and_u.segment_idx) } diff --git a/crates/sophus_core/src/calculus/spline/spline_segment.rs b/crates/sophus_core/src/calculus/spline/spline_segment.rs index 188a621..4862f29 100644 --- a/crates/sophus_core/src/calculus/spline/spline_segment.rs +++ b/crates/sophus_core/src/calculus/spline/spline_segment.rs @@ -1,5 +1,5 @@ use crate::prelude::*; -use std::marker::PhantomData; +use core::marker::PhantomData; /// cubic basis function pub struct CubicBasisFunction { diff --git a/crates/sophus_core/src/lib.rs b/crates/sophus_core/src/lib.rs index 5265c38..5f19b1b 100644 --- a/crates/sophus_core/src/lib.rs +++ b/crates/sophus_core/src/lib.rs @@ -1,5 +1,6 @@ #![cfg_attr(feature = "simd", feature(portable_simd))] #![deny(missing_docs)] +#![no_std] #![allow(clippy::needless_range_loop)] //! Core math functionality including //! - linear algebra types @@ -22,6 +23,9 @@ //! * closed region: [calculus::region::Interval] //! - manifolds: [manifold::traits] +#[cfg(feature = "std")] +extern crate std; + /// calculus - differentiation, splines, and more pub mod calculus; /// floating point diff --git a/crates/sophus_core/src/linalg.rs b/crates/sophus_core/src/linalg.rs index 7e0678f..0012e6f 100644 --- a/crates/sophus_core/src/linalg.rs +++ b/crates/sophus_core/src/linalg.rs @@ -23,22 +23,22 @@ pub mod batch_vector; pub mod vector; #[cfg(feature = "simd")] -use std::ops::Add; +use core::ops::Add; #[cfg(feature = "simd")] -use std::simd::cmp::SimdPartialEq; +use core::simd::cmp::SimdPartialEq; #[cfg(feature = "simd")] -use std::simd::num::SimdFloat; +use core::simd::num::SimdFloat; #[cfg(feature = "simd")] -use std::simd::LaneCount; +use core::simd::LaneCount; #[cfg(feature = "simd")] -use std::simd::Mask; +use core::simd::Mask; #[cfg(feature = "simd")] -use std::simd::Simd; +use core::simd::Simd; #[cfg(feature = "simd")] -use std::simd::SimdElement; +use core::simd::SimdElement; #[cfg(feature = "simd")] -use std::simd::SupportedLaneCount; +use core::simd::SupportedLaneCount; /// Static vector pub type SVec = nalgebra::SVector; diff --git a/crates/sophus_core/src/linalg/batch_mask.rs b/crates/sophus_core/src/linalg/batch_mask.rs index 2862350..5cc7bf6 100644 --- a/crates/sophus_core/src/linalg/batch_mask.rs +++ b/crates/sophus_core/src/linalg/batch_mask.rs @@ -1,8 +1,8 @@ use crate::prelude::IsBoolMask; -use std::simd::LaneCount; -use std::simd::Mask; -use std::simd::MaskElement; -use std::simd::SupportedLaneCount; +use core::simd::LaneCount; +use core::simd::Mask; +use core::simd::MaskElement; +use core::simd::SupportedLaneCount; impl IsBoolMask for Mask where diff --git a/crates/sophus_core/src/linalg/batch_matrix.rs b/crates/sophus_core/src/linalg/batch_matrix.rs index d9a426e..fd6c7f1 100644 --- a/crates/sophus_core/src/linalg/batch_matrix.rs +++ b/crates/sophus_core/src/linalg/batch_matrix.rs @@ -1,14 +1,11 @@ use crate::calculus::dual::DualBatchMatrix; - use crate::linalg::BatchMatF64; use crate::linalg::BatchScalarF64; use crate::linalg::BatchVecF64; - use crate::prelude::*; - -use std::simd::LaneCount; -use std::simd::Mask; -use std::simd::SupportedLaneCount; +use core::simd::LaneCount; +use core::simd::Mask; +use core::simd::SupportedLaneCount; impl IsMatrix, ROWS, COLS, BATCH> for BatchMatF64 diff --git a/crates/sophus_core/src/linalg/batch_scalar.rs b/crates/sophus_core/src/linalg/batch_scalar.rs index 1fa6b3b..e58324d 100644 --- a/crates/sophus_core/src/linalg/batch_scalar.rs +++ b/crates/sophus_core/src/linalg/batch_scalar.rs @@ -10,24 +10,28 @@ use crate::linalg::BatchVecF64; use crate::linalg::EPS_F64; use crate::prelude::IsCoreScalar; use crate::prelude::*; +use alloc::vec; +use alloc::vec::Vec; use approx::AbsDiffEq; use approx::RelativeEq; -use std::fmt::Debug; -use std::ops::AddAssign; -use std::ops::Div; -use std::ops::Mul; -use std::ops::MulAssign; -use std::ops::Neg; -use std::ops::Sub; -use std::ops::SubAssign; -use std::simd::cmp::SimdPartialOrd; -use std::simd::num::SimdFloat; -use std::simd::LaneCount; -use std::simd::Mask; -use std::simd::Simd; -use std::simd::SimdElement; -use std::simd::StdFloat; -use std::simd::SupportedLaneCount; +use core::fmt::Debug; +use core::ops::AddAssign; +use core::ops::Div; +use core::ops::Mul; +use core::ops::MulAssign; +use core::ops::Neg; +use core::ops::Sub; +use core::ops::SubAssign; +use core::simd::cmp::SimdPartialOrd; +use core::simd::num::SimdFloat; +use core::simd::LaneCount; +use core::simd::Mask; +use core::simd::Simd; +use core::simd::SimdElement; +use core::simd::SupportedLaneCount; +use sleef::Sleef; + +extern crate alloc; impl IsCoreScalar for BatchScalar @@ -35,7 +39,7 @@ where LaneCount: SupportedLaneCount, Simd: SimdFloat, BatchScalar: - Clone + Debug + nalgebra::Scalar + num_traits::Zero + std::ops::AddAssign, + Clone + Debug + nalgebra::Scalar + num_traits::Zero + core::ops::AddAssign, { fn number_category() -> NumberCategory { NumberCategory::Real @@ -296,7 +300,9 @@ where } fn fract(self) -> Self { - BatchScalarF64 { 0: self.0.fract() } + BatchScalarF64 { + 0: self.0.frfrexp(), + } } fn floor(&self) -> BatchScalarF64 { diff --git a/crates/sophus_core/src/linalg/batch_vector.rs b/crates/sophus_core/src/linalg/batch_vector.rs index 8509356..1e674d6 100644 --- a/crates/sophus_core/src/linalg/batch_vector.rs +++ b/crates/sophus_core/src/linalg/batch_vector.rs @@ -3,9 +3,9 @@ use crate::linalg::BatchMatF64; use crate::linalg::BatchScalarF64; use crate::linalg::BatchVecF64; use crate::prelude::*; -use std::simd::LaneCount; -use std::simd::Mask; -use std::simd::SupportedLaneCount; +use core::simd::LaneCount; +use core::simd::Mask; +use core::simd::SupportedLaneCount; impl IsVector, ROWS, BATCH> for BatchVecF64 diff --git a/crates/sophus_core/src/linalg/matrix.rs b/crates/sophus_core/src/linalg/matrix.rs index 6e2dda8..4615262 100644 --- a/crates/sophus_core/src/linalg/matrix.rs +++ b/crates/sophus_core/src/linalg/matrix.rs @@ -4,13 +4,13 @@ use crate::linalg::VecF64; use crate::prelude::*; use approx::AbsDiffEq; use approx::RelativeEq; -use std::fmt::Debug; -use std::ops::Add; -use std::ops::Index; -use std::ops::IndexMut; -use std::ops::Mul; -use std::ops::Neg; -use std::ops::Sub; +use core::fmt::Debug; +use core::ops::Add; +use core::ops::Index; +use core::ops::IndexMut; +use core::ops::Mul; +use core::ops::Neg; +use core::ops::Sub; /// Matrix trait /// - either a real (f64) or a dual number matrix diff --git a/crates/sophus_core/src/linalg/scalar.rs b/crates/sophus_core/src/linalg/scalar.rs index b9761ab..3075856 100644 --- a/crates/sophus_core/src/linalg/scalar.rs +++ b/crates/sophus_core/src/linalg/scalar.rs @@ -8,15 +8,16 @@ use crate::prelude::*; use approx::assert_abs_diff_eq; use approx::AbsDiffEq; use approx::RelativeEq; +use core::fmt::Debug; +use core::ops::Add; +use core::ops::AddAssign; +use core::ops::Div; +use core::ops::Mul; +use core::ops::Neg; +use core::ops::Sub; +use core::ops::SubAssign; use nalgebra::SimdValue; -use std::fmt::Debug; -use std::ops::Add; -use std::ops::AddAssign; -use std::ops::Div; -use std::ops::Mul; -use std::ops::Neg; -use std::ops::Sub; -use std::ops::SubAssign; +extern crate alloc; /// Number category #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -31,7 +32,7 @@ pub enum NumberCategory { /// Trait for scalar and batch scalar linalg pub trait IsCoreScalar: - Clone + Debug + nalgebra::Scalar + num_traits::Zero + std::ops::AddAssign + Clone + Debug + nalgebra::Scalar + num_traits::Zero + core::ops::AddAssign { /// Get the number category fn number_category() -> NumberCategory; @@ -66,7 +67,7 @@ pub trait IsScalar: PartialEq + Debug + Clone - + std::ops::Div + + core::ops::Div + Add + Mul + Sub @@ -183,7 +184,7 @@ pub trait IsScalar: fn real_part(&self) -> Self::RealScalar; /// return examples of scalar values - fn scalar_examples() -> Vec; + fn scalar_examples() -> alloc::vec::Vec; /// Return the self if the mask is true, otherwise the other value /// @@ -286,8 +287,8 @@ impl IsScalar<1> for f64 { self >= rhs } - fn scalar_examples() -> Vec { - vec![1.0, 2.0, 3.0] + fn scalar_examples() -> alloc::vec::Vec { + alloc::vec![1.0, 2.0, 3.0] } fn abs(self) -> f64 { @@ -385,6 +386,28 @@ impl IsScalar<1> for f64 { other } } + + fn ones() -> Self { + Self::from_f64(1.0) + } + + fn zeros() -> Self { + Self::from_f64(0.0) + } + + fn test_suite() { + let examples = Self::scalar_examples(); + for a in &examples { + let sin_a = (*a).sin(); + let cos_a = (*a).cos(); + let val = sin_a * sin_a + cos_a * cos_a; + let one = Self::ones(); + + for i in 0..1 { + assert_abs_diff_eq!(val.extract_single(i), one.extract_single(i)); + } + } + } } impl IsSingleScalar for f64 { diff --git a/crates/sophus_core/src/linalg/vector.rs b/crates/sophus_core/src/linalg/vector.rs index de7cb38..f913af4 100644 --- a/crates/sophus_core/src/linalg/vector.rs +++ b/crates/sophus_core/src/linalg/vector.rs @@ -4,12 +4,12 @@ use crate::linalg::VecF64; use crate::prelude::*; use approx::AbsDiffEq; use approx::RelativeEq; -use std::fmt::Debug; -use std::ops::Add; -use std::ops::Index; -use std::ops::IndexMut; -use std::ops::Neg; -use std::ops::Sub; +use core::fmt::Debug; +use core::ops::Add; +use core::ops::Index; +use core::ops::IndexMut; +use core::ops::Neg; +use core::ops::Sub; /// Vector - either a real (f64) or a dual number vector pub trait IsVector, const ROWS: usize, const BATCH_SIZE: usize>: diff --git a/crates/sophus_core/src/manifold/traits.rs b/crates/sophus_core/src/manifold/traits.rs index 5cd72ee..be781b0 100644 --- a/crates/sophus_core/src/manifold/traits.rs +++ b/crates/sophus_core/src/manifold/traits.rs @@ -1,11 +1,12 @@ use crate::linalg::VecF64; use crate::params::ParamsImpl; use crate::prelude::*; +extern crate alloc; /// A tangent implementation. pub trait TangentImpl, const DOF: usize, const BATCH_SIZE: usize> { /// Examples of tangent vectors. - fn tangent_examples() -> Vec>; + fn tangent_examples() -> alloc::vec::Vec>; } /// A manifold implementation. @@ -28,7 +29,7 @@ pub trait IsManifold< const PARAMS: usize, const DOF: usize, const BATCH_SIZE: usize, ->: HasParams + std::fmt::Debug + Clone +>: HasParams + core::fmt::Debug + Clone { /// o-plus operation fn oplus(&self, tangent: &S::Vector) -> Self; diff --git a/crates/sophus_core/src/manifold/unit_vector.rs b/crates/sophus_core/src/manifold/unit_vector.rs index 90906e0..1da19f3 100644 --- a/crates/sophus_core/src/manifold/unit_vector.rs +++ b/crates/sophus_core/src/manifold/unit_vector.rs @@ -8,10 +8,9 @@ use crate::traits::ManifoldImpl; use crate::traits::TangentImpl; use crate::HasParams; use crate::ParamsImpl; -use assertables::assert_le; -use std::marker::PhantomData; -use std::ops::Neg; -use thiserror::Error; +use core::marker::PhantomData; +use core::ops::Neg; +extern crate alloc; #[derive(Clone, Debug, Copy)] struct UnitVectorImpl< @@ -27,14 +26,14 @@ impl, const DOF: usize, const DIM: usize, const BATCH_SI UnitVectorImpl { fn unit(i: usize) -> S::Vector { - assert_le!(i, DIM); + assert!(i < DIM, "{} < {}", i, DIM); let mut v = S::Vector::::zeros(); v.set_elem(i, S::from_f64(1.0)); v } fn unit_tangent(i: usize) -> S::Vector { - assert_le!(i, DOF); + assert!(i < DOF, "{} < {}", i, DOF); let mut v = S::Vector::::zeros(); v.set_elem(i, S::from_f64(1.0)); v @@ -89,7 +88,7 @@ impl, const DOF: usize, const DIM: usize, const BATCH_SI impl, const DOF: usize, const DIM: usize, const BATCH_SIZE: usize> TangentImpl for UnitVectorImpl { - fn tangent_examples() -> Vec> { + fn tangent_examples() -> alloc::vec::Vec> { todo!() } } @@ -104,11 +103,11 @@ impl, const DOF: usize, const DIM: usize, const BATCH_SI .less_equal(&eps) } - fn params_examples() -> Vec> { + fn params_examples() -> alloc::vec::Vec> { todo!() } - fn invalid_params_examples() -> Vec> { + fn invalid_params_examples() -> alloc::vec::Vec> { todo!() } } @@ -201,12 +200,12 @@ pub type UnitVector2 = UnitVector; pub type UnitVector3 = UnitVector; /// Vector is near zero. -#[derive(Clone, Debug, Error)] +#[derive(Clone, Debug)] pub struct NearZeroUnitVector; -impl std::fmt::Display for NearZeroUnitVector { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Display for NearZeroUnitVector { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "Vector is near zero") } } @@ -264,11 +263,11 @@ impl, const DOF: usize, const DIM: usize, const BATCH_SI UnitVectorImpl::::are_params_valid(params) } - fn params_examples() -> Vec> { + fn params_examples() -> alloc::vec::Vec> { UnitVectorImpl::::params_examples() } - fn invalid_params_examples() -> Vec> { + fn invalid_params_examples() -> alloc::vec::Vec> { UnitVectorImpl::::invalid_params_examples() } } diff --git a/crates/sophus_core/src/params.rs b/crates/sophus_core/src/params.rs index 9a34b3c..7ba3d16 100644 --- a/crates/sophus_core/src/params.rs +++ b/crates/sophus_core/src/params.rs @@ -1,15 +1,19 @@ use crate::linalg::VecF64; use crate::points::example_points; use crate::prelude::*; +use alloc::vec; +use alloc::vec::Vec; + +extern crate alloc; /// Parameter implementation. pub trait ParamsImpl, const PARAMS: usize, const BATCH_SIZE: usize> { /// Is the parameter vector valid? fn are_params_valid(params: &S::Vector) -> S::Mask; /// Examples of valid parameter vectors. - fn params_examples() -> Vec>; + fn params_examples() -> alloc::vec::Vec>; /// Examples of invalid parameter vectors. - fn invalid_params_examples() -> Vec>; + fn invalid_params_examples() -> alloc::vec::Vec>; } /// A trait for linalg that have parameters. diff --git a/crates/sophus_core/src/points.rs b/crates/sophus_core/src/points.rs index 870a891..4715554 100644 --- a/crates/sophus_core/src/points.rs +++ b/crates/sophus_core/src/points.rs @@ -1,6 +1,7 @@ use crate::prelude::*; use nalgebra::SVector; use num_traits::Bounded; +extern crate alloc; /// Traits for points pub trait IsPoint: Copy + Bounded { @@ -86,8 +87,8 @@ impl IsPoint for SVector { /// Example points pub fn example_points, const POINT: usize, const BATCH: usize>( -) -> Vec> { - let points4 = vec![ +) -> alloc::vec::Vec> { + let points4 = alloc::vec![ S::Vector::<4>::from_f64_array([0.1, 0.0, 0.0, 0.0]), S::Vector::<4>::from_f64_array([1.0, 4.0, 1.0, 0.5]), S::Vector::<4>::from_f64_array([0.7, 5.0, 1.1, (-5.0)]), @@ -98,7 +99,7 @@ pub fn example_points, const POINT: usize, const BATCH: usize S::Vector::<4>::from_f64_array([2.0, (-3.0), 1.0, 0.5]), ]; - let mut out: Vec> = vec![]; + let mut out: alloc::vec::Vec> = alloc::vec![]; for p4 in points4 { let mut v = S::Vector::::zeros(); for i in 0..POINT.min(4) { diff --git a/crates/sophus_core/src/tensor/arc_tensor.rs b/crates/sophus_core/src/tensor/arc_tensor.rs index 37ea1cd..5dbc599 100644 --- a/crates/sophus_core/src/tensor/arc_tensor.rs +++ b/crates/sophus_core/src/tensor/arc_tensor.rs @@ -5,10 +5,9 @@ use crate::tensor::mut_tensor::InnerScalarToVec; use crate::tensor::mut_tensor::InnerVecToMat; use crate::tensor::MutTensor; use crate::tensor::TensorView; +use core::marker::PhantomData; use ndarray::Dimension; -use std::marker::PhantomData; - /// Arc tensor - a tensor with shared ownership /// /// See TensorView for more details of the tensor structure @@ -422,7 +421,11 @@ fn arc_tensor_tests() { img2.view().elem_view().as_slice().unwrap().as_ptr() ); } +} +#[test] +#[cfg(feature = "std")] +fn arc_tensor_std_tests() { // multi_threading use crate::tensor::arc_tensor::ArcTensorDDRC; use crate::tensor::mut_tensor::MutTensorDDRC; diff --git a/crates/sophus_core/src/tensor/element.rs b/crates/sophus_core/src/tensor/element.rs index 4f22f6f..7ebd55d 100644 --- a/crates/sophus_core/src/tensor/element.rs +++ b/crates/sophus_core/src/tensor/element.rs @@ -2,7 +2,7 @@ use crate::linalg::scalar::NumberCategory; use crate::linalg::SMat; use crate::linalg::SVec; use crate::prelude::*; -use std::fmt::Debug; +use core::fmt::Debug; pub use typenum::generic_const_mappings::Const; /// Trait for static tensors @@ -137,7 +137,7 @@ impl STensorFormat { num_rows: ROWS, num_cols: COLS, batch_size: BATCH_SIZE, - num_bytes_per_scalar: std::mem::size_of::(), + num_bytes_per_scalar: core::mem::size_of::(), } } diff --git a/crates/sophus_core/src/tensor/mut_tensor.rs b/crates/sophus_core/src/tensor/mut_tensor.rs index 443bee4..6cd113d 100644 --- a/crates/sophus_core/src/tensor/mut_tensor.rs +++ b/crates/sophus_core/src/tensor/mut_tensor.rs @@ -4,10 +4,10 @@ use crate::prelude::*; use crate::tensor::ArcTensor; use crate::tensor::MutTensorView; use crate::tensor::TensorView; +use core::fmt::Debug; +use core::marker::PhantomData; use ndarray::Dim; use ndarray::Ix; -use std::fmt::Debug; -use std::marker::PhantomData; /// mutable tensor /// diff --git a/crates/sophus_core/src/tensor/mut_tensor_view.rs b/crates/sophus_core/src/tensor/mut_tensor_view.rs index ff4d374..5d05b63 100644 --- a/crates/sophus_core/src/tensor/mut_tensor_view.rs +++ b/crates/sophus_core/src/tensor/mut_tensor_view.rs @@ -2,7 +2,7 @@ use crate::prelude::*; use crate::tensor::MutTensor; use crate::tensor::TensorView; use concat_arrays::concat_arrays; -use std::marker::PhantomData; +use core::marker::PhantomData; /// Mutable tensor view /// @@ -52,7 +52,7 @@ pub trait IsMutTensorLike< ) -> ndarray::ArrayViewMut<'a, Scalar, ndarray::Dim<[ndarray::Ix; TOTAL_RANK]>>; /// mutable reference to the static tensor at index idx - fn get_mut(&'a mut self, idx: [usize; DRANK]) -> &mut STensor; + fn get_mut(&'a mut self, idx: [usize; DRANK]) -> &'a mut STensor; } macro_rules! mut_view_is_view { @@ -102,8 +102,8 @@ macro_rules! mut_view_is_view { let ptr = elem_view_mut.as_ptr() as *mut Scalar; use ndarray::ShapeBuilder; - assert_eq!(std::mem::size_of::(), - std::mem::size_of::() * ROWS * COLS + assert_eq!(core::mem::size_of::(), + core::mem::size_of::() * ROWS * COLS ); let scalar_view_mut = @@ -116,7 +116,7 @@ macro_rules! mut_view_is_view { } /// get mutable reference to scalar at index idx - pub fn mut_scalar(&'a mut self, idx: [usize; $scalar_rank]) -> &mut Scalar{ + pub fn mut_scalar(&'a mut self, idx: [usize; $scalar_rank]) -> &'a mut Scalar{ &mut self.scalar_view_mut[idx] } @@ -249,7 +249,7 @@ macro_rules! mut_view_is_view { self.scalar_view_mut.view_mut() } - fn get_mut(&'a mut self, idx: [usize; $drank]) -> &mut STensor{ + fn get_mut(&'a mut self, idx: [usize; $drank]) -> &'a mut STensor{ &mut self.elem_view_mut[idx] } diff --git a/crates/sophus_core/src/tensor/tensor_view.rs b/crates/sophus_core/src/tensor/tensor_view.rs index 5e824a4..630b212 100644 --- a/crates/sophus_core/src/tensor/tensor_view.rs +++ b/crates/sophus_core/src/tensor/tensor_view.rs @@ -3,7 +3,7 @@ use crate::linalg::SVec; use crate::prelude::*; use crate::tensor::MutTensor; use concat_arrays::concat_arrays; -use std::marker::PhantomData; +use core::marker::PhantomData; /// Tensor view /// @@ -193,8 +193,8 @@ macro_rules! tensor_view_is_view { use ndarray::ShapeBuilder; assert_eq!( - std::mem::size_of::(), - std::mem::size_of::() * ROWS * COLS + core::mem::size_of::(), + core::mem::size_of::() * ROWS * COLS ); let scalar_view = unsafe { ndarray::ArrayView::from_shape_ptr(shape.strides(strides), ptr) }; diff --git a/crates/sophus_core/src/time_series.rs b/crates/sophus_core/src/time_series.rs index 7ad2a37..d0cd86f 100644 --- a/crates/sophus_core/src/time_series.rs +++ b/crates/sophus_core/src/time_series.rs @@ -1,11 +1,9 @@ -use std::collections::VecDeque; -use std::ops::Index; -use std::time::Duration; - -use log::warn; - use crate::calculus::Interval; use crate::prelude::IsRegion; +use core::ops::Index; +use core::time::Duration; +use log::warn; +extern crate alloc; /// has time_stamp method pub trait HasTimeStamp: Clone { @@ -38,7 +36,7 @@ pub trait HasInterpolate: HasTimeStamp { /// - Finding the nearest item to a given time stamp. #[derive(Clone)] pub struct TimeSeries { - sorted_data: VecDeque, + sorted_data: alloc::collections::vec_deque::VecDeque, } /// item with index @@ -59,7 +57,7 @@ impl TimeSeries { /// Create a new empty time series. pub fn new() -> Self { TimeSeries { - sorted_data: VecDeque::new(), + sorted_data: alloc::collections::vec_deque::VecDeque::new(), } } @@ -216,7 +214,7 @@ impl TimeSeries { } /// removes specified range of elements - pub fn drain>(&mut self, range: R) { + pub fn drain>(&mut self, range: R) { self.sorted_data.drain(range); } @@ -265,7 +263,7 @@ impl TimeSeries { impl IntoIterator for TimeSeries { type Item = T; - type IntoIter = std::collections::vec_deque::IntoIter; + type IntoIter = alloc::collections::vec_deque::IntoIter; fn into_iter(self) -> Self::IntoIter { self.sorted_data.into_iter() @@ -274,7 +272,7 @@ impl IntoIterator for TimeSeries { impl<'a, T: HasTimeStamp> IntoIterator for &'a TimeSeries { type Item = &'a T; - type IntoIter = std::collections::vec_deque::Iter<'a, T>; + type IntoIter = alloc::collections::vec_deque::Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.sorted_data.iter() @@ -292,7 +290,7 @@ impl Index for TimeSeries { #[cfg(test)] mod tests { use super::*; - use std::time::Duration; + use core::time::Duration; // Mock struct implementing HasTimeStamp #[derive(Debug, PartialEq, Clone)] @@ -417,7 +415,7 @@ mod tests { #[test] fn test_insert_duplicate_timestamps() { let mut series = TimeSeries::new(); - let items = vec![ + let items = alloc::vec![ TestItem { timestamp: 1.0, value: 10.0, @@ -601,7 +599,7 @@ mod tests { #[test] fn test_find_nearest_within_multiple_items_left_closer() { let mut series = TimeSeries::new(); - let items = vec![ + let items = alloc::vec![ TestItem { timestamp: 1.0, value: 10.0, @@ -633,7 +631,7 @@ mod tests { #[test] fn test_find_nearest_within_multiple_items_right_closer() { let mut series = TimeSeries::new(); - let items = vec![ + let items = alloc::vec![ TestItem { timestamp: 1.0, value: 10.0, @@ -665,7 +663,7 @@ mod tests { #[test] fn test_find_nearest_within_exact_match() { let mut series = TimeSeries::new(); - let items = vec![ + let items = alloc::vec![ TestItem { timestamp: 1.0, value: 10.0, @@ -695,7 +693,7 @@ mod tests { #[test] fn test_find_nearest_within_ouserieside_max_dist() { let mut series = TimeSeries::new(); - let items = vec![ + let items = alloc::vec![ TestItem { timestamp: 1.0, value: 10.0, @@ -742,7 +740,7 @@ mod tests { #[test] fn test_prune_older_than_no_prune() { let mut series = TimeSeries::new(); - let items = vec![ + let items = alloc::vec![ TestItem { timestamp: 10.0, value: 100.0, @@ -772,7 +770,7 @@ mod tests { #[test] fn test_prune_older_than_some_prune() { let mut series = TimeSeries::new(); - let items = vec![ + let items = alloc::vec![ TestItem { timestamp: 10.0, value: 100.0, @@ -814,7 +812,7 @@ mod tests { #[test] fn test_time_interval_non_empty() { let mut series = TimeSeries::new(); - let items = vec![ + let items = alloc::vec![ TestItem { timestamp: 5.0, value: 50.0, diff --git a/crates/sophus_image/Cargo.toml b/crates/sophus_image/Cargo.toml index df37f82..1ff75b5 100644 --- a/crates/sophus_image/Cargo.toml +++ b/crates/sophus_image/Cargo.toml @@ -14,13 +14,14 @@ version.workspace = true sophus_core.workspace = true approx.workspace = true -assertables.workspace = true bytemuck.workspace = true nalgebra.workspace = true ndarray.workspace = true num-traits.workspace = true -png.workspace = true -tiff.workspace = true + +tiff = {version = "0.9.0", optional = true} +png = {version ="0.17", optional = true} [features] simd = ["sophus_core/simd"] +std = ["png", "tiff"] diff --git a/crates/sophus_image/src/arc_image.rs b/crates/sophus_image/src/arc_image.rs index a939ce0..d75d054 100644 --- a/crates/sophus_image/src/arc_image.rs +++ b/crates/sophus_image/src/arc_image.rs @@ -241,7 +241,7 @@ macro_rules! arc_image { fn image_view( &'b self, ) -> super::image_view::GenImageView< - '_, + 'b, $scalar_rank, $srank, Scalar, diff --git a/crates/sophus_image/src/intensity_image.rs b/crates/sophus_image/src/intensity_image.rs index 0397328..5ac92c4 100644 --- a/crates/sophus_image/src/intensity_image.rs +++ b/crates/sophus_image/src/intensity_image.rs @@ -3,6 +3,7 @@ pub mod dyn_intensity_image; /// intensity image pub mod intensity_arc_image; /// intensity view image +#[cfg(feature = "std")] pub mod intensity_image_view; /// mutable intensity image pub mod intensity_mut_image; diff --git a/crates/sophus_image/src/intensity_image/intensity_arc_image.rs b/crates/sophus_image/src/intensity_image/intensity_arc_image.rs index d574cdf..e750170 100644 --- a/crates/sophus_image/src/intensity_image/intensity_arc_image.rs +++ b/crates/sophus_image/src/intensity_image/intensity_arc_image.rs @@ -1,4 +1,4 @@ -use std::any::TypeId; +use core::any::TypeId; use crate::arc_image::ArcImageR; use crate::intensity_image::dyn_intensity_image::DynIntensityArcImage; @@ -28,7 +28,7 @@ use sophus_core::linalg::SVec; pub trait IsIntensityArcImage< Scalar: IsIntensityScalar + 'static, Pixel: IntensityPixel + 'static, ->: std::marker::Sized +>: core::marker::Sized { /// Pixel type type Pixel: IntensityPixel; @@ -97,7 +97,9 @@ impl IsIntensityArcImage fo // If the scalar type is the same, just return the image. // Safety: This is safe because the types are actually the same. - return unsafe { std::mem::transmute::, ArcImage>(self) }; + return unsafe { + core::mem::transmute::, ArcImage>(self) + }; } ArcImage::::from_map(&self.image_view(), |rgb: &Scalar| -> OtherScalar { OtherScalar::from(*rgb) @@ -153,7 +155,7 @@ impl IsIntensityArcImage, ArcImageR>(self) + core::mem::transmute::, ArcImageR>(self) }; } ArcImageR::::from_map( @@ -209,7 +211,7 @@ impl IsIntensityArcImage, ArcImageR>(self) + core::mem::transmute::, ArcImageR>(self) }; } ArcImageR::::from_map( @@ -269,7 +271,7 @@ impl IsIntensityArcImage, ArcImageR>(self) + core::mem::transmute::, ArcImageR>(self) }; } ArcImageR::::from_map( diff --git a/crates/sophus_image/src/intensity_image/intensity_mut_image.rs b/crates/sophus_image/src/intensity_image/intensity_mut_image.rs index 061fd8c..36aa6e5 100644 --- a/crates/sophus_image/src/intensity_image/intensity_mut_image.rs +++ b/crates/sophus_image/src/intensity_image/intensity_mut_image.rs @@ -26,7 +26,7 @@ use sophus_core::linalg::SVec; pub trait IsIntensityMutImage< Scalar: IsIntensityScalar + 'static, Pixel: IntensityPixel + 'static, ->: std::marker::Sized +>: core::marker::Sized { /// Pixel type type Pixel: IntensityPixel; diff --git a/crates/sophus_image/src/intensity_image/intensity_scalar.rs b/crates/sophus_image/src/intensity_image/intensity_scalar.rs index 1fbf827..00d9745 100644 --- a/crates/sophus_image/src/intensity_image/intensity_scalar.rs +++ b/crates/sophus_image/src/intensity_image/intensity_scalar.rs @@ -1,5 +1,5 @@ +use core::any::TypeId; use sophus_core::prelude::*; -use std::any::TypeId; /// either u8, u16, or f32 pub trait IsIntensityScalar: IsCoreScalar + Sized + Copy { diff --git a/crates/sophus_image/src/io.rs b/crates/sophus_image/src/io.rs index e9e91cf..b96520c 100644 --- a/crates/sophus_image/src/io.rs +++ b/crates/sophus_image/src/io.rs @@ -1,5 +1,7 @@ /// png io +#[cfg(feature = "std")] pub mod png; /// tiff io +#[cfg(feature = "std")] pub mod tiff; diff --git a/crates/sophus_image/src/io/png.rs b/crates/sophus_image/src/io/png.rs index 85d855d..e6fa5e5 100644 --- a/crates/sophus_image/src/io/png.rs +++ b/crates/sophus_image/src/io/png.rs @@ -9,8 +9,11 @@ use crate::mut_image::MutImage4U8; use crate::mut_image::MutImageU16; use crate::mut_image::MutImageU8; use crate::ImageSize; +use std::format; use std::fs::File; use std::io::BufWriter; +use std::string::ToString; +use std::vec; /// Save an image of unsigned integers as a PNG file pub fn save_as_png<'a, ImageView: IsIntensityViewImageU<'a>>( diff --git a/crates/sophus_image/src/io/tiff.rs b/crates/sophus_image/src/io/tiff.rs index b8fbbda..32103ee 100644 --- a/crates/sophus_image/src/io/tiff.rs +++ b/crates/sophus_image/src/io/tiff.rs @@ -11,10 +11,11 @@ use crate::mut_image::MutImage4U8; use crate::mut_image::MutImageF32; use crate::mut_image::MutImageU16; use crate::mut_image::MutImageU8; - use crate::prelude::DynIntensityMutImage; use crate::ImageSize; +use std::format; use std::fs::File; +use std::string::ToString; use tiff::decoder::Decoder; use tiff::decoder::DecodingResult; use tiff::encoder::colortype::ColorType; diff --git a/crates/sophus_image/src/lib.rs b/crates/sophus_image/src/lib.rs index ec426c2..368da8d 100644 --- a/crates/sophus_image/src/lib.rs +++ b/crates/sophus_image/src/lib.rs @@ -1,7 +1,11 @@ #![cfg_attr(feature = "simd", feature(portable_simd))] #![deny(missing_docs)] +#![no_std] //! image crate - part of the sophus-rs project +#[cfg(feature = "std")] +extern crate std; + /// image with shared ownership pub mod arc_image; /// color maps diff --git a/crates/sophus_image/src/mut_image.rs b/crates/sophus_image/src/mut_image.rs index eb2e163..c4fefdf 100644 --- a/crates/sophus_image/src/mut_image.rs +++ b/crates/sophus_image/src/mut_image.rs @@ -6,6 +6,8 @@ use sophus_core::linalg::SVec; use sophus_core::tensor::MutTensor; use sophus_core::tensor::TensorView; +extern crate alloc; + /// Mutable image of static tensors #[derive(Debug, Clone, Default)] pub struct GenMutImage< @@ -184,16 +186,16 @@ macro_rules! mut_image { pub fn try_make_copy_from_size_and_bytes( image_size: ImageSize, bytes: &'a [u8], - ) -> Result { + ) -> Result { let num_scalars_in_pixel = STensor::num_scalars(); let num_scalars_in_image = num_scalars_in_pixel * image_size.width * image_size.height; - let size_in_bytes = num_scalars_in_image * std::mem::size_of::(); + let size_in_bytes = num_scalars_in_image * core::mem::size_of::(); if(bytes.len() != size_in_bytes){ - return Err(format!("bytes.len() = {} != size_in_bytes = {}", + return Err(alloc::format!("bytes.len() = {} != size_in_bytes = {}", bytes.len(), size_in_bytes)); } let stensor_slice = unsafe { - std::slice::from_raw_parts( + core::slice::from_raw_parts( bytes.as_ptr() as *const Scalar, num_scalars_in_image) }; @@ -311,7 +313,7 @@ macro_rules! mut_image { } } - fn mut_pixel(&'a mut self, u: usize, v: usize) -> &mut STensor { + fn mut_pixel(&'a mut self, u: usize, v: usize) -> &'a mut STensor { self.mut_tensor.get_mut([v, u]) } } diff --git a/crates/sophus_image/src/mut_image_view.rs b/crates/sophus_image/src/mut_image_view.rs index 8c71770..f9fa7d5 100644 --- a/crates/sophus_image/src/mut_image_view.rs +++ b/crates/sophus_image/src/mut_image_view.rs @@ -87,7 +87,7 @@ macro_rules! mut_image_view { } } - fn mut_pixel(&'a mut self, u: usize, v: usize) -> &mut STensor { + fn mut_pixel(&'a mut self, u: usize, v: usize) -> &'a mut STensor { // NOTE: // We are converting from Image Indexing Convention (d0 = u = col_idx, d1 = v = row_idx) // to tensor (and matrix) convention (d0 = rows, d1 = cols). @@ -119,5 +119,5 @@ pub trait IsMutImageView< ) -> GenMutImageView<'a, TOTAL_RANK, SRANK, Scalar, STensor, ROWS, COLS>; /// returns mutable u,v pixel - fn mut_pixel(&'a mut self, u: usize, v: usize) -> &mut STensor; + fn mut_pixel(&'a mut self, u: usize, v: usize) -> &'a mut STensor; } diff --git a/crates/sophus_lie/Cargo.toml b/crates/sophus_lie/Cargo.toml index 00207ea..582f7c9 100644 --- a/crates/sophus_lie/Cargo.toml +++ b/crates/sophus_lie/Cargo.toml @@ -13,11 +13,10 @@ version.workspace = true [dependencies] approx.workspace = true -assertables.workspace = true log.workspace = true nalgebra.workspace = true num-traits.workspace = true -thiserror.workspace = true +snafu.workspace = true sophus_core = {workspace = true} diff --git a/crates/sophus_lie/src/average.rs b/crates/sophus_lie/src/average.rs index 30455b7..0ae441f 100644 --- a/crates/sophus_lie/src/average.rs +++ b/crates/sophus_lie/src/average.rs @@ -4,19 +4,19 @@ use crate::groups::rotation2::Rotation2F64; use crate::groups::rotation3::Rotation3F64; use crate::traits::IsLieGroupImpl; use crate::LieGroup; +use snafu::prelude::*; use sophus_core::linalg::EPS_F64; use sophus_core::prelude::IsSingleScalar; use sophus_core::prelude::IsVector; -use thiserror::Error; /// error of iterative_average -#[derive(Error, Debug)] +#[derive(Snafu, Debug)] pub enum IterativeAverageError { /// slice is empty - #[error("empty slice")] + #[snafu(display("empty slice"))] EmptySlice, /// not converged - #[error("no convergence after {max_iteration_count:?} iterations")] + #[snafu(display("no convergence after {max_iteration_count:?} iterations"))] NotConverged { /// max iteration count max_iteration_count: u32, diff --git a/crates/sophus_lie/src/groups/rotation2.rs b/crates/sophus_lie/src/groups/rotation2.rs index 6f92033..a568ca5 100644 --- a/crates/sophus_lie/src/groups/rotation2.rs +++ b/crates/sophus_lie/src/groups/rotation2.rs @@ -7,10 +7,12 @@ use crate::traits::IsLieFactorGroupImpl; use crate::traits::IsLieGroupImpl; use crate::traits::IsRealLieFactorGroupImpl; use crate::traits::IsRealLieGroupImpl; +use core::marker::PhantomData; use sophus_core::linalg::EPS_F64; use sophus_core::manifold::traits::TangentImpl; use sophus_core::params::ParamsImpl; -use std::marker::PhantomData; + +extern crate alloc; /// 2D rotation group implementation struct - SO(2) #[derive(Debug, Copy, Clone, Default)] @@ -28,10 +30,10 @@ impl, const BATCH_SIZE: usize> HasDisambiguate, const BATCH_SIZE: usize> ParamsImpl for Rotation2Impl { - fn params_examples() -> Vec> { - let mut params = vec![]; + fn params_examples() -> alloc::vec::Vec> { + let mut params = alloc::vec![]; for i in 0..10 { - let angle = S::from_f64(i as f64 * std::f64::consts::PI / 5.0); + let angle = S::from_f64(i as f64 * core::f64::consts::PI / 5.0); params.push( Rotation2::::exp(&S::Vector::<1>::from_array([angle])) .params() @@ -41,8 +43,8 @@ impl, const BATCH_SIZE: usize> ParamsImpl Vec> { - vec![ + fn invalid_params_examples() -> alloc::vec::Vec> { + alloc::vec![ S::Vector::<2>::from_array([S::from_f64(0.0), S::from_f64(0.0)]), S::Vector::<2>::from_array([S::from_f64(0.5), S::from_f64(0.5)]), S::Vector::<2>::from_array([S::from_f64(0.5), S::from_f64(-0.5)]), @@ -60,8 +62,8 @@ impl, const BATCH_SIZE: usize> ParamsImpl, const BATCH_SIZE: usize> TangentImpl for Rotation2Impl { - fn tangent_examples() -> Vec> { - vec![ + fn tangent_examples() -> alloc::vec::Vec> { + alloc::vec![ S::Vector::<1>::from_array([S::from_f64(0.0)]), S::Vector::<1>::from_array([S::from_f64(1.0)]), S::Vector::<1>::from_array([S::from_f64(-1.0)]), @@ -187,7 +189,7 @@ impl, const BATCH_SIZE: usize> } fn has_shortest_path_ambiguity(params: &S::Vector<2>) -> S::Mask { - (Self::log(params).get_elem(0).abs() - S::from_f64(std::f64::consts::PI)) + (Self::log(params).get_elem(0).abs() - S::from_f64(core::f64::consts::PI)) .abs() .less_equal(&S::from_f64(EPS_F64)) } diff --git a/crates/sophus_lie/src/groups/rotation3.rs b/crates/sophus_lie/src/groups/rotation3.rs index 77dbe1c..c8400bb 100644 --- a/crates/sophus_lie/src/groups/rotation3.rs +++ b/crates/sophus_lie/src/groups/rotation3.rs @@ -9,13 +9,15 @@ use crate::traits::IsLieGroupImpl; use crate::traits::IsRealLieFactorGroupImpl; use crate::traits::IsRealLieGroupImpl; use core::f64; +use core::marker::PhantomData; use log::warn; use sophus_core::linalg::vector::cross; use sophus_core::linalg::MatF64; use sophus_core::linalg::EPS_F64; use sophus_core::manifold::traits::TangentImpl; use sophus_core::params::ParamsImpl; -use std::marker::PhantomData; + +extern crate alloc; /// 3d rotation implementation - SO(3) #[derive(Debug, Copy, Clone, Default)] @@ -35,11 +37,11 @@ impl, const BATCH: usize> HasDisambiguate } impl, const BATCH: usize> ParamsImpl for Rotation3Impl { - fn params_examples() -> Vec> { + fn params_examples() -> alloc::vec::Vec> { const NEAR_PI: f64 = f64::consts::PI - 1e-6; const NEAR_MINUS_PI: f64 = f64::consts::PI - 1e-6; - vec![ + alloc::vec![ Rotation3::::exp(&S::Vector::<3>::from_f64_array([0.0, 0.0, 0.0])) .params() .clone(), @@ -161,8 +163,8 @@ impl, const BATCH: usize> ParamsImpl for Rotatio ] } - fn invalid_params_examples() -> Vec> { - vec![ + fn invalid_params_examples() -> alloc::vec::Vec> { + alloc::vec![ S::Vector::<4>::from_f64_array([0.0, 0.0, 0.0, 0.0]), S::Vector::<4>::from_f64_array([0.5, 0.5, 0.5, 0.0]), S::Vector::<4>::from_f64_array([0.5, -0.5, 0.5, 1.0]), @@ -178,8 +180,8 @@ impl, const BATCH: usize> ParamsImpl for Rotatio } impl, const BATCH: usize> TangentImpl for Rotation3Impl { - fn tangent_examples() -> Vec> { - vec![ + fn tangent_examples() -> alloc::vec::Vec> { + alloc::vec![ S::Vector::<3>::from_f64_array([0.0, 0.0, 0.0]), S::Vector::<3>::from_f64_array([1.0, 0.0, 0.0]), S::Vector::<3>::from_f64_array([0.0, 1.0, 0.0]), @@ -514,7 +516,7 @@ impl, const BATCH: usize> IsRealLieGroupImpl) -> S::Mask { let theta = Self::log(params).norm(); - (theta - S::from_f64(std::f64::consts::PI)) + (theta - S::from_f64(core::f64::consts::PI)) .abs() .less_equal(&S::from_f64(EPS_F64.sqrt())) } diff --git a/crates/sophus_lie/src/groups/translation_product_product.rs b/crates/sophus_lie/src/groups/translation_product_product.rs index 117fe71..2d4f535 100644 --- a/crates/sophus_lie/src/groups/translation_product_product.rs +++ b/crates/sophus_lie/src/groups/translation_product_product.rs @@ -9,6 +9,8 @@ use sophus_core::manifold::traits::TangentImpl; use sophus_core::params::ParamsImpl; use sophus_core::points::example_points; +extern crate alloc; + /// implementation of a translation product group /// /// It is a semi-direct product of the commutative translation group (Euclidean vector space) and a factor group. @@ -24,7 +26,7 @@ pub struct TranslationProductGroupImpl< const BATCH: usize, F: IsLieFactorGroupImpl, > { - phantom: std::marker::PhantomData<(S, F)>, + phantom: core::marker::PhantomData<(S, F)>, } impl< @@ -75,7 +77,7 @@ impl< S::Vector::block_vec2(translation.clone(), factor_tangent.clone()) } - fn translation_examples() -> Vec> { + fn translation_examples() -> alloc::vec::Vec> { example_points::() } } @@ -118,14 +120,14 @@ impl< F::are_params_valid(&Self::factor_params(params)) } - fn params_examples() -> Vec> { - let mut examples = vec![]; + fn params_examples() -> alloc::vec::Vec> { + let mut examples = alloc::vec![]; let factor_examples = F::params_examples(); let translation_examples = Self::translation_examples(); // Determine the maximum length of factor and translation examples - let max_len = std::cmp::max(factor_examples.len(), translation_examples.len()); + let max_len = core::cmp::max(factor_examples.len(), translation_examples.len()); for i in 0..max_len { // Wrap around indices if one vector is shorter than the other @@ -137,8 +139,8 @@ impl< examples } - fn invalid_params_examples() -> Vec> { - vec![Self::params_from( + fn invalid_params_examples() -> alloc::vec::Vec> { + alloc::vec![Self::params_from( &S::Vector::zeros(), &F::invalid_params_examples()[0], )] @@ -158,14 +160,14 @@ impl< > TangentImpl for TranslationProductGroupImpl { - fn tangent_examples() -> Vec> { - let mut examples = vec![]; + fn tangent_examples() -> alloc::vec::Vec> { + let mut examples = alloc::vec![]; let factor_examples = F::tangent_examples(); let translation_examples = Self::translation_examples(); // Determine the maximum length of factor and translation examples - let max_len = std::cmp::max(factor_examples.len(), translation_examples.len()); + let max_len = core::cmp::max(factor_examples.len(), translation_examples.len()); for i in 0..max_len { // Wrap around indices if one vector is shorter than the other diff --git a/crates/sophus_lie/src/lib.rs b/crates/sophus_lie/src/lib.rs index 6cd035a..33b835f 100644 --- a/crates/sophus_lie/src/lib.rs +++ b/crates/sophus_lie/src/lib.rs @@ -1,6 +1,7 @@ #![cfg_attr(feature = "simd", feature(portable_simd))] #![deny(missing_docs)] #![allow(clippy::needless_range_loop)] +#![no_std] //! Lie groups crate - part of the sophus-rs project /// Lie groups diff --git a/crates/sophus_lie/src/lie_group.rs b/crates/sophus_lie/src/lie_group.rs index 1c94012..ddb8de9 100644 --- a/crates/sophus_lie/src/lie_group.rs +++ b/crates/sophus_lie/src/lie_group.rs @@ -1,9 +1,11 @@ use super::traits::IsLieGroupImpl; use crate::prelude::*; use approx::assert_relative_eq; +use core::fmt::Debug; use sophus_core::manifold::traits::TangentImpl; use sophus_core::params::ParamsImpl; -use std::fmt::Debug; + +extern crate alloc; /// Lie group #[derive(Debug, Copy, Clone, Default)] @@ -17,7 +19,7 @@ pub struct LieGroup< G: IsLieGroupImpl, > { pub(crate) params: S::Vector, - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } impl< @@ -35,11 +37,11 @@ impl< G::are_params_valid(params) } - fn params_examples() -> Vec> { + fn params_examples() -> alloc::vec::Vec> { G::params_examples() } - fn invalid_params_examples() -> Vec> { + fn invalid_params_examples() -> alloc::vec::Vec> { G::invalid_params_examples() } } @@ -62,7 +64,7 @@ impl< ); Self { params: G::disambiguate(params.clone()), - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } } @@ -85,7 +87,7 @@ impl< G: IsLieGroupImpl, > TangentImpl for LieGroup { - fn tangent_examples() -> Vec<>::Vector> { + fn tangent_examples() -> alloc::vec::Vec<>::Vector> { G::tangent_examples() } } @@ -206,8 +208,8 @@ impl< } /// group element examples - pub fn element_examples() -> Vec { - let mut elements = vec![]; + pub fn element_examples() -> alloc::vec::Vec { + let mut elements = alloc::vec![]; for params in Self::params_examples() { elements.push(Self::from_params(¶ms)); } @@ -239,13 +241,13 @@ impl< num += S::Mask::all_true().count(); } let percentage = num_preserves as f64 / num as f64; - assertables::assert_le!(percentage, 0.75); + assert!(percentage <= 0.75, "{} <= 0.75", percentage); } } fn adjoint_tests() { - let group_examples: Vec<_> = Self::element_examples(); - let tangent_examples: Vec> = G::tangent_examples(); + let group_examples: alloc::vec::Vec<_> = Self::element_examples(); + let tangent_examples: alloc::vec::Vec> = G::tangent_examples(); for g in &group_examples { let mat: S::Matrix = g.matrix(); @@ -281,8 +283,8 @@ impl< } fn exp_tests() { - let group_examples: Vec<_> = Self::element_examples(); - let tangent_examples: Vec> = G::tangent_examples(); + let group_examples: alloc::vec::Vec<_> = Self::element_examples(); + let tangent_examples: alloc::vec::Vec> = G::tangent_examples(); for g in &group_examples { let matrix_before = *g.compact().real_matrix(); @@ -308,7 +310,7 @@ impl< } fn hat_tests() { - let tangent_examples: Vec> = G::tangent_examples(); + let tangent_examples: alloc::vec::Vec> = G::tangent_examples(); for omega in &tangent_examples { assert_relative_eq!( @@ -320,7 +322,7 @@ impl< } fn group_operation_tests() { - let group_examples: Vec<_> = Self::element_examples(); + let group_examples: alloc::vec::Vec<_> = Self::element_examples(); for g1 in &group_examples { for g2 in &group_examples { @@ -351,9 +353,9 @@ impl< /// run all tests pub fn test_suite() { // Most tests will trivially pass if there are no examples. So first we make sure we have at least three per group. - let group_examples: Vec<_> = Self::element_examples(); + let group_examples: alloc::vec::Vec<_> = Self::element_examples(); assert!(group_examples.len() >= 3); - let tangent_examples: Vec> = G::tangent_examples(); + let tangent_examples: alloc::vec::Vec> = G::tangent_examples(); assert!(tangent_examples.len() >= 3); Self::presentability_tests(); diff --git a/crates/sophus_lie/src/lie_group_manifold.rs b/crates/sophus_lie/src/lie_group_manifold.rs index 117a6ca..2e32eff 100644 --- a/crates/sophus_lie/src/lie_group_manifold.rs +++ b/crates/sophus_lie/src/lie_group_manifold.rs @@ -1,8 +1,10 @@ use crate::lie_group::LieGroup; use crate::prelude::*; use crate::traits::IsLieGroupImpl; +use core::fmt::Debug; use sophus_core::params::ParamsImpl; -use std::fmt::Debug; + +extern crate alloc; /// Left group manifold /// @@ -36,11 +38,11 @@ impl< G::are_params_valid(params) } - fn params_examples() -> Vec<>::Vector> { + fn params_examples() -> alloc::vec::Vec<>::Vector> { G::params_examples() } - fn invalid_params_examples() -> Vec<>::Vector> { + fn invalid_params_examples() -> alloc::vec::Vec<>::Vector> { G::invalid_params_examples() } } diff --git a/crates/sophus_lie/src/real_lie_group.rs b/crates/sophus_lie/src/real_lie_group.rs index b0d2203..9eb9a19 100644 --- a/crates/sophus_lie/src/real_lie_group.rs +++ b/crates/sophus_lie/src/real_lie_group.rs @@ -15,13 +15,15 @@ use sophus_core::calculus::maps::MatrixValuedMapFromVector; use sophus_core::calculus::maps::VectorValuedMapFromMatrix; use sophus_core::calculus::maps::VectorValuedMapFromVector; +extern crate alloc; + #[cfg(feature = "simd")] use sophus_core::calculus::dual::dual_batch_scalar::DualBatchScalar; #[cfg(feature = "simd")] use sophus_core::linalg::BatchScalarF64; -use std::fmt::Display; -use std::fmt::Formatter; +use core::fmt::Display; +use core::fmt::Formatter; impl< S: IsRealScalar, @@ -97,7 +99,7 @@ impl< G: IsLieGroupImpl, > Display for LieGroup { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { write!(f, "{:?}", self.compact()) } } @@ -139,7 +141,7 @@ macro_rules! def_real_group_test_template { const DOF: usize = <$group>::DOF; use sophus_core::manifold::traits::TangentImpl; - let tangent_examples: Vec<<$scalar as IsScalar<$batch>>::Vector> + let tangent_examples: alloc::vec::Vec<<$scalar as IsScalar<$batch>>::Vector> = <$group>::tangent_examples(); for a in &tangent_examples { @@ -385,8 +387,6 @@ macro_rules! def_real_group_test_template { ).log() }; - println!("a:{:?} - b: {:?}", a.params(), b.params()); - let analytic_diff = Self::dx_log_a_exp_x_b_at_0(&a, &b); let o = <$scalar as IsScalar<$batch>>::Vector::zeros(); let auto_diff = VectorValuedMapFromVector::<$dual_scalar, $batch> @@ -518,7 +518,7 @@ macro_rules! def_real_group_test_template { fn interpolation_test() { - let group_examples: Vec<_> = Self::element_examples(); + let group_examples: alloc::vec::Vec<_> = Self::element_examples(); for foo_from_bar in &group_examples { for foo_from_daz in &group_examples { diff --git a/crates/sophus_lie/src/traits.rs b/crates/sophus_lie/src/traits.rs index 41e23e2..28c70e4 100644 --- a/crates/sophus_lie/src/traits.rs +++ b/crates/sophus_lie/src/traits.rs @@ -1,7 +1,7 @@ use crate::prelude::*; +use core::fmt::Debug; use sophus_core::manifold::traits::TangentImpl; use sophus_core::params::ParamsImpl; -use std::fmt::Debug; /// Disambiguate the parameters. pub trait HasDisambiguate, const PARAMS: usize, const BATCH_SIZE: usize>: @@ -297,7 +297,7 @@ pub trait HasAverage< const PARAMS: usize, const POINT: usize, const AMBIENT: usize, ->: IsLieGroup + std::marker::Sized +>: IsLieGroup + core::marker::Sized { /// Lie group average fn average(parent_from_body_transforms: &[Self]) -> Result; diff --git a/crates/sophus_opt/Cargo.toml b/crates/sophus_opt/Cargo.toml index b2c4c1a..69519e6 100644 --- a/crates/sophus_opt/Cargo.toml +++ b/crates/sophus_opt/Cargo.toml @@ -18,7 +18,6 @@ sophus_sensor.workspace = true approx.workspace = true as-any.workspace = true -assertables.workspace = true dyn-clone.workspace = true faer.workspace = true log.workspace = true diff --git a/crates/sophus_opt/src/cost.rs b/crates/sophus_opt/src/cost.rs index 076edb6..2bf6408 100644 --- a/crates/sophus_opt/src/cost.rs +++ b/crates/sophus_opt/src/cost.rs @@ -1,9 +1,11 @@ use crate::term::Term; use crate::variables::VarKind; use crate::variables::VarPool; +use core::fmt::Debug; +use core::ops::AddAssign; use dyn_clone::DynClone; -use std::fmt::Debug; -use std::ops::AddAssign; + +extern crate alloc; /// Evaluated cost pub trait IsCost: Debug + DynClone { @@ -15,7 +17,7 @@ pub trait IsCost: Debug + DynClone { &self, variables: &VarPool, nu: f64, - upper_hessian_triplet: &mut Vec<(usize, usize, f64)>, + upper_hessian_triplet: &mut alloc::vec::Vec<(usize, usize, f64)>, neg_grad: &mut nalgebra::DVector, ); } @@ -24,19 +26,22 @@ pub trait IsCost: Debug + DynClone { #[derive(Debug, Clone)] pub struct Cost { /// one name (of the corresponding variable family) for each argument (of the cost function - pub family_names: [String; NUM_ARGS], + pub family_names: [alloc::string::String; NUM_ARGS], /// evaluated terms of the cost function - pub terms: Vec>, + pub terms: alloc::vec::Vec>, /// degrees of freedom for each argument pub dof_tuple: [i64; NUM_ARGS], } impl Cost { /// create a new evaluated cost - pub fn new(family_names: [String; NUM_ARGS], dof_tuple: [i64; NUM_ARGS]) -> Self { + pub fn new( + family_names: [alloc::string::String; NUM_ARGS], + dof_tuple: [i64; NUM_ARGS], + ) -> Self { Cost { family_names, - terms: Vec::new(), + terms: alloc::vec::Vec::new(), dof_tuple, } } @@ -69,14 +74,14 @@ impl IsCost for Cost { &self, variables: &VarPool, nu: f64, - upper_hessian_triplet: &mut Vec<(usize, usize, f64)>, + upper_hessian_triplet: &mut alloc::vec::Vec<(usize, usize, f64)>, neg_grad: &mut nalgebra::DVector, ) { let num_args = self.family_names.len(); - let mut start_indices_per_arg = Vec::new(); + let mut start_indices_per_arg = alloc::vec::Vec::new(); - let mut dof_per_arg = Vec::new(); + let mut dof_per_arg = alloc::vec::Vec::new(); for name in self.family_names.iter() { let family = variables.families.get(name).unwrap(); start_indices_per_arg.push(family.get_start_indices().clone()); diff --git a/crates/sophus_opt/src/cost_args.rs b/crates/sophus_opt/src/cost_args.rs index 139a28c..0cc4d67 100644 --- a/crates/sophus_opt/src/cost_args.rs +++ b/crates/sophus_opt/src/cost_args.rs @@ -1,5 +1,7 @@ use crate::variables::VarKind; +extern crate alloc; + /// Convert VarKind array to char array for comparison pub fn c_from_var_kind(var_kind_array: &[VarKind; N]) -> [char; N] { let mut c_array: [char; N] = ['0'; N]; @@ -82,7 +84,7 @@ where } /// Compare two cost argument id tuples - pub fn le_than(&self, lhs: [usize; N], rhs: [usize; N]) -> std::cmp::Ordering { + pub fn le_than(&self, lhs: [usize; N], rhs: [usize; N]) -> core::cmp::Ordering { let mut permuted_lhs: [usize; N] = [0; N]; let mut permuted_rhs: [usize; N] = [0; N]; @@ -102,12 +104,12 @@ where break; } match permuted_lhs[l].cmp(&permuted_rhs[l]) { - std::cmp::Ordering::Less => return std::cmp::Ordering::Less, - std::cmp::Ordering::Greater => return std::cmp::Ordering::Greater, - std::cmp::Ordering::Equal => l += 1, + core::cmp::Ordering::Less => return core::cmp::Ordering::Less, + core::cmp::Ordering::Greater => return core::cmp::Ordering::Greater, + core::cmp::Ordering::Equal => l += 1, } } - std::cmp::Ordering::Equal + core::cmp::Ordering::Equal } /// Return true if all non-conditioned variables are equal @@ -134,7 +136,7 @@ mod test { c: &[char; N], lhs: [usize; N], rhs: [usize; N], - ) -> std::cmp::Ordering { + ) -> core::cmp::Ordering { CompareIdx::new(c).le_than(lhs, rhs) } @@ -146,157 +148,157 @@ mod test { const CV: [char; 2] = ['c', 'f']; const CC: [char; 2] = ['c', 'c']; - assert_eq!(le_than(&VV, [0, 0], [1, 0]), std::cmp::Ordering::Less); - assert_eq!(le_than(&VV, [1, 0], [0, 0]), std::cmp::Ordering::Greater); - assert_eq!(le_than(&VC, [0, 0], [1, 0]), std::cmp::Ordering::Less); - assert_eq!(le_than(&VC, [1, 0], [0, 0]), std::cmp::Ordering::Greater); - assert_eq!(le_than(&CV, [0, 0], [1, 0]), std::cmp::Ordering::Less); - assert_eq!(le_than(&CV, [1, 0], [0, 0]), std::cmp::Ordering::Greater); - assert_eq!(le_than(&CC, [0, 0], [0, 0]), std::cmp::Ordering::Equal); + assert_eq!(le_than(&VV, [0, 0], [1, 0]), core::cmp::Ordering::Less); + assert_eq!(le_than(&VV, [1, 0], [0, 0]), core::cmp::Ordering::Greater); + assert_eq!(le_than(&VC, [0, 0], [1, 0]), core::cmp::Ordering::Less); + assert_eq!(le_than(&VC, [1, 0], [0, 0]), core::cmp::Ordering::Greater); + assert_eq!(le_than(&CV, [0, 0], [1, 0]), core::cmp::Ordering::Less); + assert_eq!(le_than(&CV, [1, 0], [0, 0]), core::cmp::Ordering::Greater); + assert_eq!(le_than(&CC, [0, 0], [0, 0]), core::cmp::Ordering::Equal); const MV: [char; 2] = ['m', 'f']; const VM: [char; 2] = ['f', 'm']; const MM: [char; 2] = ['m', 'm']; - assert_eq!(le_than(&MV, [0, 0], [1, 0]), std::cmp::Ordering::Less); - assert_eq!(le_than(&VM, [0, 0], [1, 0]), std::cmp::Ordering::Less); - assert_eq!(le_than(&MM, [0, 0], [0, 0]), std::cmp::Ordering::Equal); + assert_eq!(le_than(&MV, [0, 0], [1, 0]), core::cmp::Ordering::Less); + assert_eq!(le_than(&VM, [0, 0], [1, 0]), core::cmp::Ordering::Less); + assert_eq!(le_than(&MM, [0, 0], [0, 0]), core::cmp::Ordering::Equal); const VVV: [char; 3] = ['f', 'f', 'f']; assert_eq!( le_than(&VVV, [0, 0, 0], [1, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&VVV, [0, 2, 0], [1, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&VVV, [0, 1, 0], [1, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&VVV, [0, 0, 1], [1, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&VVV, [0, 1, 0], [0, 0, 1]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&VVV, [0, 0, 1], [0, 0, 2]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); const CVV: [char; 3] = ['c', 'f', 'f']; assert_eq!( le_than(&CVV, [0, 0, 0], [1, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&CVV, [0, 2, 0], [1, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CVV, [0, 1, 0], [1, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CVV, [0, 0, 1], [1, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CVV, [0, 1, 0], [0, 0, 1]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CVV, [0, 0, 1], [0, 0, 2]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); const CVC: [char; 3] = ['c', 'f', 'c']; assert_eq!( le_than(&CVC, [0, 0, 0], [1, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&CVC, [0, 2, 0], [1, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CVC, [0, 1, 0], [1, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CVC, [0, 0, 1], [1, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&CVC, [0, 1, 0], [0, 0, 1]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CVC, [0, 0, 1], [0, 0, 2]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); const CCV: [char; 3] = ['c', 'c', 'f']; assert_eq!( le_than(&CCV, [0, 0, 0], [0, 0, 0]), - std::cmp::Ordering::Equal + core::cmp::Ordering::Equal ); assert_eq!( le_than(&CCV, [0, 0, 0], [1, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&CCV, [0, 2, 0], [1, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&CCV, [0, 1, 0], [1, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&CCV, [0, 0, 1], [1, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CCV, [0, 1, 0], [0, 0, 1]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&CCV, [0, 0, 1], [0, 0, 2]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); const CVM: [char; 3] = ['c', 'f', 'm']; assert_eq!( le_than(&CVM, [0, 0, 0], [1, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&CVM, [0, 2, 0], [1, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CVM, [0, 1, 0], [1, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CVM, [0, 0, 1], [1, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CVM, [0, 1, 0], [0, 0, 1]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&CVM, [0, 0, 1], [0, 0, 2]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); // Length 4 @@ -310,59 +312,59 @@ mod test { assert_eq!( le_than(&VVVV, [0, 0, 0, 0], [1, 0, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&VVVV, [1, 0, 0, 0], [0, 0, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CVVV, [0, 0, 0, 0], [1, 0, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&CVVV, [1, 0, 0, 0], [0, 0, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CCVV, [0, 0, 0, 0], [0, 0, 0, 0]), - std::cmp::Ordering::Equal + core::cmp::Ordering::Equal ); assert_eq!( le_than(&CCVV, [0, 1, 0, 0], [0, 0, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CVCV, [0, 0, 0, 0], [1, 0, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&CVCV, [1, 0, 0, 0], [0, 0, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&VVCC, [0, 0, 0, 0], [0, 0, 0, 0]), - std::cmp::Ordering::Equal + core::cmp::Ordering::Equal ); assert_eq!( le_than(&VVCC, [0, 0, 0, 1], [0, 0, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&CCVC, [0, 0, 0, 0], [0, 1, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&CCVC, [0, 1, 0, 0], [0, 0, 0, 0]), - std::cmp::Ordering::Greater + core::cmp::Ordering::Greater ); assert_eq!( le_than(&VCCV, [0, 0, 0, 0], [1, 0, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&VCCV, [0, 0, 1, 0], [1, 0, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); const MVVM: [char; 4] = ['m', 'f', 'f', 'm']; @@ -372,23 +374,25 @@ mod test { assert_eq!( le_than(&MVVM, [0, 0, 0, 0], [1, 0, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&MMVV, [0, 0, 0, 0], [1, 0, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&VMMV, [0, 0, 0, 0], [1, 0, 0, 0]), - std::cmp::Ordering::Less + core::cmp::Ordering::Less ); assert_eq!( le_than(&MMMM, [0, 0, 0, 0], [0, 0, 0, 0]), - std::cmp::Ordering::Equal + core::cmp::Ordering::Equal ); + extern crate alloc; + let c: [char; 3] = ['f', 'f', 'c']; - let mut l: Vec<[usize; 3]> = vec![ + let mut l: alloc::vec::Vec<[usize; 3]> = alloc::vec![ [1, 2, 3], [4, 5, 6], [7, 8, 9], diff --git a/crates/sophus_opt/src/cost_fn.rs b/crates/sophus_opt/src/cost_fn.rs index 993a1c5..b62d0a3 100644 --- a/crates/sophus_opt/src/cost_fn.rs +++ b/crates/sophus_opt/src/cost_fn.rs @@ -6,9 +6,10 @@ use crate::term::Term; use crate::variables::IsVarTuple; use crate::variables::VarKind; use crate::variables::VarPool; -use std::marker::PhantomData; -use std::ops::Range; -use std::time::Instant; +use core::marker::PhantomData; +use core::ops::Range; + +extern crate alloc; /// Signature of a term of a cost function pub trait IsTermSignature: Send + Sync + 'static { @@ -33,10 +34,10 @@ pub struct CostSignature< TermSignature: IsTermSignature, > { /// one variable family name for each argument - pub family_names: [String; NUM_ARGS], + pub family_names: [alloc::string::String; NUM_ARGS], /// terms of the unevaluated cost function - pub terms: Vec, - pub(crate) reduction_ranges: Option>>, + pub terms: alloc::vec::Vec, + pub(crate) reduction_ranges: Option>>, } impl< @@ -46,7 +47,10 @@ impl< > CostSignature { /// Create a new cost signature - pub fn new(family_names: [String; NUM_ARGS], terms: Vec) -> Self { + pub fn new( + family_names: [alloc::string::String; NUM_ARGS], + terms: alloc::vec::Vec, + ) -> Self { CostSignature { family_names, terms, @@ -84,7 +88,7 @@ pub trait IsCostFn { var_pool: &VarPool, calc_derivatives: bool, parallelize: bool, - ) -> Box; + ) -> alloc::boxed::Box; /// sort the terms of the cost function (to ensure more efficient evaluation and reduction over /// conditioned variables) @@ -131,8 +135,8 @@ where global_constants: GlobalConstants, signature: CostSignature, residual_fn: ResidualFn, - ) -> Box { - Box::new(Self { + ) -> alloc::boxed::Box { + alloc::boxed::Box::new(Self { global_constants, signature, residual_fn, @@ -147,8 +151,8 @@ where signature: CostSignature, residual_fn: ResidualFn, robust_kernel: RobustKernel, - ) -> Box { - Box::new(Self { + ) -> alloc::boxed::Box { + alloc::boxed::Box::new(Self { global_constants, signature, residual_fn, @@ -176,7 +180,7 @@ where var_pool: &VarPool, calc_derivatives: bool, parallelize: bool, - ) -> Box { + ) -> alloc::boxed::Box { let mut var_kind_array = VarTuple::var_kind_array(var_pool, self.signature.family_names.clone()); @@ -345,12 +349,10 @@ where } } - Box::new(evaluated_terms) + alloc::boxed::Box::new(evaluated_terms) } fn sort(&mut self, variables: &VarPool) { - let now = Instant::now(); - let var_kind_array = &VarTuple::var_kind_array(variables, self.signature.family_names.clone()); use crate::cost_args::CompareIdx; @@ -365,24 +367,16 @@ where .terms .sort_by(|a, b| less.le_than(*a.idx_ref(), *b.idx_ref())); - println!("sorting took: {:.2?}", now.elapsed()); - - let now = Instant::now(); - for t in 0..self.signature.terms.len() - 1 { assert!( less.le_than( *self.signature.terms[t].idx_ref(), *self.signature.terms[t + 1].idx_ref() - ) != std::cmp::Ordering::Greater + ) != core::cmp::Ordering::Greater ); } - println!("sorting val took: {:.2?}", now.elapsed()); - - let now = Instant::now(); - - let mut reduction_ranges: Vec> = vec![]; + let mut reduction_ranges: alloc::vec::Vec> = alloc::vec![]; let mut i = 0; while i < self.signature.terms.len() { let outer_term_signature = &self.signature.terms[i]; @@ -399,8 +393,6 @@ where } self.signature.reduction_ranges = Some(reduction_ranges); - - println!("reduction_ranges took: {:.2?}", now.elapsed()); } fn robust_kernel(&self) -> Option { diff --git a/crates/sophus_opt/src/example_problems/cam_calib.rs b/crates/sophus_opt/src/example_problems/cam_calib.rs index 0a61306..2f5ede3 100644 --- a/crates/sophus_opt/src/example_problems/cam_calib.rs +++ b/crates/sophus_opt/src/example_problems/cam_calib.rs @@ -18,7 +18,8 @@ use sophus_lie::Isometry3; use sophus_lie::Isometry3F64; use sophus_lie::Rotation3; use sophus_sensor::PinholeCamera; -use std::collections::HashMap; + +extern crate alloc; /// Camera calibration problem #[derive(Clone)] @@ -26,24 +27,24 @@ pub struct CamCalibProblem { /// intrinsics pub intrinsics: PinholeCamera, /// world from camera isometries - pub world_from_cameras: Vec, + pub world_from_cameras: alloc::vec::Vec, /// points in world - pub points_in_world: Vec>, + pub points_in_world: alloc::vec::Vec>, /// observations - pub observations: Vec, + pub observations: alloc::vec::Vec, /// true intrinsics pub true_intrinsics: PinholeCamera, /// true world from camera isometries - pub true_world_from_cameras: Vec, + pub true_world_from_cameras: alloc::vec::Vec, /// true points in world - pub true_points_in_world: Vec>, + pub true_points_in_world: alloc::vec::Vec>, } impl CamCalibProblem { /// create new camera calibration problem pub fn new(spurious_matches: bool) -> Self { - let true_world_from_cameras = vec![ + let true_world_from_cameras = alloc::vec![ Isometry3::identity(), Isometry3::from_translation_and_factor( &VecF64::<3>::new(0.0, 1.0, 0.0), @@ -67,8 +68,8 @@ impl CamCalibProblem { image_size, ); - let mut observations = vec![]; - let mut true_points_in_world = vec![]; + let mut observations = alloc::vec![]; + let mut true_points_in_world = alloc::vec![]; for i in 0..40 { let u = rng.gen::() * (image_size.width as f64 - 1.0); @@ -119,7 +120,7 @@ impl CamCalibProblem { } Self { - world_from_cameras: vec![ + world_from_cameras: alloc::vec![ Isometry3::::identity(), true_world_from_cameras[1], true_world_from_cameras[1], @@ -142,9 +143,9 @@ impl CamCalibProblem { ); let cam_family: VarFamily> = - VarFamily::new(intrinsics_var_kind, vec![self.intrinsics]); + VarFamily::new(intrinsics_var_kind, alloc::vec![self.intrinsics]); - let mut id = HashMap::new(); + let mut id = alloc::collections::BTreeMap::new(); id.insert(0, ()); id.insert(1, ()); @@ -165,7 +166,7 @@ impl CamCalibProblem { let up_var_pool = optimize( var_pool, - vec![ + alloc::vec![ // robust kernel to deal with outliers CostFn::new_robust( (), @@ -195,7 +196,7 @@ impl CamCalibProblem { let priors = CostSignature::<1, (Isometry3F64, MatF64<6, 6>), Isometry3PriorTermSignature>::new( ["poses".into()], - vec![ + alloc::vec![ Isometry3PriorTermSignature { entity_indices: [0], isometry_prior: ( @@ -219,7 +220,7 @@ impl CamCalibProblem { ); let cam_family: VarFamily> = - VarFamily::new(VarKind::Conditioned, vec![self.intrinsics]); + VarFamily::new(VarKind::Conditioned, alloc::vec![self.intrinsics]); let pose_family: VarFamily = VarFamily::new(VarKind::Free, self.world_from_cameras.clone()); @@ -235,7 +236,7 @@ impl CamCalibProblem { let up_var_pool = optimize( var_pool, - vec![ + alloc::vec![ CostFn::new_box((), priors.clone(), Isometry3PriorCostFn {}), CostFn::new_box((), reproj_obs.clone(), ReprojectionCostFn {}), ], @@ -248,15 +249,6 @@ impl CamCalibProblem { let refined_world_from_robot = up_var_pool.get_members::("poses".into()); - println!( - "refined_world_from_robot[0].translation(): {:?}", - refined_world_from_robot[0].translation() - ); - println!( - "refined_world_from_robot[1].translation(): {:?}", - refined_world_from_robot[1].translation() - ); - approx::assert_abs_diff_eq!( refined_world_from_robot[2].translation(), self.true_world_from_cameras[2].translation(), @@ -272,8 +264,8 @@ mod tests { use crate::example_problems::cam_calib::CamCalibProblem; use crate::variables::VarKind; - // CamCalibProblem::new(true).optimize_with_two_poses_fixed(VarKind::Free); + CamCalibProblem::new(true).optimize_with_two_poses_fixed(VarKind::Free); CamCalibProblem::new(false).optimize_with_two_poses_fixed(VarKind::Conditioned); - // CamCalibProblem::new(false).optimize_with_priors(); + CamCalibProblem::new(false).optimize_with_priors(); } } diff --git a/crates/sophus_opt/src/example_problems/pose_circle.rs b/crates/sophus_opt/src/example_problems/pose_circle.rs index da8ede1..5496e6e 100644 --- a/crates/sophus_opt/src/example_problems/pose_circle.rs +++ b/crates/sophus_opt/src/example_problems/pose_circle.rs @@ -12,15 +12,16 @@ use crate::variables::VarPoolBuilder; use sophus_core::linalg::VecF64; use sophus_lie::Isometry2; use sophus_lie::Isometry2F64; -use std::collections::HashMap; + +extern crate alloc; /// Pose graph example problem #[derive(Debug, Clone)] pub struct PoseCircleProblem { /// true poses - pub true_world_from_robot: Vec, + pub true_world_from_robot: alloc::vec::Vec, /// estimated poses - pub est_world_from_robot: Vec, + pub est_world_from_robot: alloc::vec::Vec, /// pose-pose constraints pub obs_pose_a_from_pose_b_poses: CostSignature<2, Isometry2F64, PoseGraphCostTermSignature>, } @@ -34,19 +35,19 @@ impl Default for PoseCircleProblem { impl PoseCircleProblem { /// Create a new pose graph problem pub fn new(len: usize) -> Self { - let mut true_world_from_robot_poses = vec![]; - let mut est_world_from_robot_poses = vec![]; + let mut true_world_from_robot_poses = alloc::vec![]; + let mut est_world_from_robot_poses = alloc::vec![]; let mut obs_pose_a_from_pose_b_poses = CostSignature::<2, Isometry2F64, PoseGraphCostTermSignature>::new( ["poses".into(), "poses".into()], - vec![], + alloc::vec![], ); let radius = 10.0; for i in 0..len { let frac = i as f64 / len as f64; - let angle = frac * std::f64::consts::TAU; + let angle = frac * core::f64::consts::TAU; let x = radius * angle.cos(); let y = radius * angle.sin(); let p = VecF64::<3>::from_real_array([x, y, 0.1 * angle]); @@ -121,7 +122,7 @@ impl PoseCircleProblem { /// Optimize the problem pub fn optimize(&self) -> VarPool { - let mut constants = HashMap::new(); + let mut constants = alloc::collections::BTreeMap::new(); constants.insert(0, ()); let family: VarFamily = VarFamily::new_with_const_ids( @@ -134,7 +135,7 @@ impl PoseCircleProblem { optimize( var_pool, - vec![CostFn::new_box( + alloc::vec![CostFn::new_box( (), self.obs_pose_a_from_pose_b_poses.clone(), PoseGraphCostFn {}, diff --git a/crates/sophus_opt/src/example_problems/simple_prior.rs b/crates/sophus_opt/src/example_problems/simple_prior.rs index bcf8375..133d8c1 100644 --- a/crates/sophus_opt/src/example_problems/simple_prior.rs +++ b/crates/sophus_opt/src/example_problems/simple_prior.rs @@ -17,6 +17,8 @@ use sophus_lie::Isometry2F64; use sophus_lie::Isometry3; use sophus_lie::Isometry3F64; +extern crate alloc; + /// Simple 2D isometry prior problem pub struct SimpleIso2PriorProblem { /// True world from robot isometry @@ -44,7 +46,7 @@ impl SimpleIso2PriorProblem { /// Test the simple 2D isometry prior problem pub fn test(&self) { use sophus_core::linalg::EPS_F64; - let cost_signature = vec![Isometry2PriorTermSignature { + let cost_signature = alloc::vec![Isometry2PriorTermSignature { isometry_prior_mean: self.true_world_from_robot, entity_indices: [0], }]; @@ -56,7 +58,7 @@ impl SimpleIso2PriorProblem { >::new(["poses".into()], cost_signature); let family: VarFamily = - VarFamily::new(VarKind::Free, vec![self.est_world_from_robot]); + VarFamily::new(VarKind::Free, alloc::vec![self.est_world_from_robot]); let families = VarPoolBuilder::new().add_family("poses", family).build(); @@ -68,7 +70,7 @@ impl SimpleIso2PriorProblem { let up_families = optimize( families, - vec![CostFn::new_box( + alloc::vec![CostFn::new_box( (), obs_pose_a_from_pose_b_poses.clone(), Isometry2PriorCostFn {}, @@ -117,7 +119,7 @@ impl SimpleIso3PriorProblem { pub fn test(&self) { use sophus_core::linalg::EPS_F64; - let cost_signature = vec![Isometry3PriorTermSignature { + let cost_signature = alloc::vec![Isometry3PriorTermSignature { isometry_prior: (self.true_world_from_robot, MatF64::<6, 6>::identity()), entity_indices: [0], }]; @@ -129,7 +131,7 @@ impl SimpleIso3PriorProblem { >::new(["poses".into()], cost_signature); let family: VarFamily = - VarFamily::new(VarKind::Free, vec![self.est_world_from_robot]); + VarFamily::new(VarKind::Free, alloc::vec![self.est_world_from_robot]); let families = VarPoolBuilder::new().add_family("poses", family).build(); @@ -141,7 +143,7 @@ impl SimpleIso3PriorProblem { let up_families = optimize( families, - vec![CostFn::new_box( + alloc::vec![CostFn::new_box( (), obs_pose_a_from_pose_b_poses.clone(), Isometry3PriorCostFn {}, diff --git a/crates/sophus_opt/src/ldlt.rs b/crates/sophus_opt/src/ldlt.rs index e8f2a2e..58c4b0a 100644 --- a/crates/sophus_opt/src/ldlt.rs +++ b/crates/sophus_opt/src/ldlt.rs @@ -1,5 +1,7 @@ use nalgebra::DMatrix; +extern crate alloc; + /// A matrix in triplet format for sparse LDLT factorization / using faer crate pub struct SparseLdlt { upper_ccs: faer::sparse::SparseColMat, @@ -8,7 +10,7 @@ pub struct SparseLdlt { /// A matrix in triplet format pub struct SymmetricTripletMatrix { /// upper diagonal triplets - pub upper_triplets: Vec<(usize, usize, f64)>, + pub upper_triplets: alloc::vec::Vec<(usize, usize, f64)>, /// row count (== column count) pub size: usize, } @@ -17,7 +19,7 @@ impl SymmetricTripletMatrix { /// Create an example matrix pub fn example() -> Self { Self { - upper_triplets: vec![ + upper_triplets: alloc::vec![ (0, 0, 3.05631771), (1, 1, 60.05631771), (2, 2, 6.05631771), @@ -63,8 +65,8 @@ impl SymmetricTripletMatrix { } struct SparseLdltPerm { - perm: Vec, - perm_inv: Vec, + perm: alloc::vec::Vec, + perm_inv: alloc::vec::Vec, } impl SparseLdltPerm { @@ -76,9 +78,9 @@ impl SparseLdltPerm { let nnz = upper_ccs.compute_nnz(); let perm_ref = unsafe { faer::perm::PermRef::new_unchecked(&self.perm, &self.perm_inv) }; - let mut ccs_perm_col_ptrs = Vec::new(); - let mut ccs_perm_row_indices = Vec::new(); - let mut ccs_perm_values = Vec::new(); + let mut ccs_perm_col_ptrs = alloc::vec::Vec::new(); + let mut ccs_perm_row_indices = alloc::vec::Vec::new(); + let mut ccs_perm_values = alloc::vec::Vec::new(); ccs_perm_col_ptrs.try_reserve_exact(dim + 1).unwrap(); ccs_perm_col_ptrs.resize(dim + 1, 0usize); @@ -130,8 +132,8 @@ impl SparseLdlt { let nnz = self.upper_ccs.compute_nnz(); let (perm, perm_inv) = { - let mut perm = Vec::new(); - let mut perm_inv = Vec::new(); + let mut perm = alloc::vec::Vec::new(); + let mut perm_inv = alloc::vec::Vec::new(); perm.try_reserve_exact(dim).unwrap(); perm_inv.try_reserve_exact(dim).unwrap(); perm.resize(dim, 0usize); @@ -169,8 +171,8 @@ impl SparseLdlt { ).unwrap(); let mut stack = faer::dyn_stack::PodStack::new(&mut mem); - let mut etree = Vec::new(); - let mut col_counts = Vec::new(); + let mut etree = alloc::vec::Vec::new(); + let mut col_counts = alloc::vec::Vec::new(); etree.try_reserve_exact(dim).unwrap(); etree.resize(dim, 0isize); col_counts.try_reserve_exact(dim).unwrap(); @@ -223,7 +225,7 @@ impl SparseLdlt { ]).unwrap()).unwrap(); let mut stack = faer::dyn_stack::PodStack::new(&mut mem); - let mut l_values = Vec::new(); + let mut l_values = alloc::vec::Vec::new(); l_values.try_reserve_exact(symbolic.len_values()).unwrap(); l_values.resize(symbolic.len_values(), 0.0f64); let ccs_perm_upper = symbolic_perm.permutation.perm_upper_ccs(&self.upper_ccs); diff --git a/crates/sophus_opt/src/lib.rs b/crates/sophus_opt/src/lib.rs index a7b9a08..3f94732 100644 --- a/crates/sophus_opt/src/lib.rs +++ b/crates/sophus_opt/src/lib.rs @@ -1,6 +1,7 @@ #![cfg_attr(feature = "simd", feature(portable_simd))] #![deny(missing_docs)] #![allow(clippy::needless_range_loop)] +#![no_std] //! # Non-linear least squares optimization crate - part of the sophus-rs project diff --git a/crates/sophus_opt/src/nlls.rs b/crates/sophus_opt/src/nlls.rs index fbfde88..dfb6873 100644 --- a/crates/sophus_opt/src/nlls.rs +++ b/crates/sophus_opt/src/nlls.rs @@ -2,9 +2,11 @@ use crate::cost::IsCost; use crate::cost_fn::IsCostFn; use crate::solvers::solve; use crate::variables::VarPool; +use core::fmt::Debug; use log::debug; use log::info; -use std::fmt::Debug; + +extern crate alloc; /// Optimization parameters #[derive(Copy, Clone, Debug)] @@ -30,10 +32,10 @@ impl Default for OptParams { /// Non-linear least squares optimization pub fn optimize( mut variables: VarPool, - mut cost_fns: Vec>, + mut cost_fns: alloc::vec::Vec>, params: OptParams, ) -> VarPool { - let mut init_costs: Vec> = Vec::new(); + let mut init_costs: alloc::vec::Vec> = alloc::vec::Vec::new(); for cost_fn in cost_fns.iter_mut() { // sort to achieve more efficient evaluation and reduction @@ -49,18 +51,16 @@ pub fn optimize( } let initial_mse = mse; - use std::time::Instant; - let now = Instant::now(); - for i in 0..params.num_iter { - let mut evaluated_costs: Vec> = Vec::new(); + let mut evaluated_costs: alloc::vec::Vec> = + alloc::vec::Vec::new(); for cost_fn in cost_fns.iter_mut() { evaluated_costs.push(cost_fn.eval(&variables, true, params.parallelize)); } let updated_families = solve(&variables, evaluated_costs, nu); - let mut new_costs: Vec> = Vec::new(); + let mut new_costs: alloc::vec::Vec> = alloc::vec::Vec::new(); for cost_fn in cost_fns.iter_mut() { new_costs.push(cost_fn.eval(&updated_families, true, params.parallelize)); } @@ -83,7 +83,6 @@ pub fn optimize( ); } info!("e^2: {:?} -> {:?}", initial_mse, mse); - info!("{} iters took: {:.2?}", params.num_iter, now.elapsed()); variables } diff --git a/crates/sophus_opt/src/solvers.rs b/crates/sophus_opt/src/solvers.rs index 2a0a6bf..9c39c3b 100644 --- a/crates/sophus_opt/src/solvers.rs +++ b/crates/sophus_opt/src/solvers.rs @@ -4,6 +4,8 @@ use crate::ldlt::SymmetricTripletMatrix; use crate::variables::VarKind; use crate::variables::VarPool; +extern crate alloc; + /// Normal equation pub struct SparseNormalEquation { sparse_hessian: SymmetricTripletMatrix, @@ -13,7 +15,7 @@ pub struct SparseNormalEquation { impl SparseNormalEquation { fn from_families_and_cost( variables: &VarPool, - costs: Vec>, + costs: alloc::vec::Vec>, nu: f64, ) -> SparseNormalEquation { assert!(variables.num_of_kind(VarKind::Marginalized) == 0); @@ -24,7 +26,7 @@ impl SparseNormalEquation { // to implement VarKind::Marginalized > 1. // - Example, the the arrow-head sparsity uses a recursive application of the Schur-Complement. let num_var_params = variables.num_free_params(); - let mut upper_hessian_triplet = Vec::new(); + let mut upper_hessian_triplet = alloc::vec::Vec::new(); let mut neg_grad = nalgebra::DVector::::zeros(num_var_params); for cost in costs.iter() { @@ -48,7 +50,11 @@ impl SparseNormalEquation { } /// Solve the normal equation -pub fn solve(variables: &VarPool, costs: Vec>, nu: f64) -> VarPool { +pub fn solve( + variables: &VarPool, + costs: alloc::vec::Vec>, + nu: f64, +) -> VarPool { assert!(variables.num_of_kind(VarKind::Marginalized) <= 1); assert!(variables.num_of_kind(VarKind::Free) >= 1); diff --git a/crates/sophus_opt/src/term.rs b/crates/sophus_opt/src/term.rs index d4ed9a2..fb6f269 100644 --- a/crates/sophus_opt/src/term.rs +++ b/crates/sophus_opt/src/term.rs @@ -6,6 +6,8 @@ use crate::variables::VarKind; use sophus_core::linalg::MatF64; use sophus_core::linalg::VecF64; +extern crate alloc; + /// Evaluated cost term #[derive(Debug, Clone)] pub struct Term { @@ -248,7 +250,7 @@ where (), ); - let dims = vec![D0]; + let dims = alloc::vec![D0]; let mut hessian = BlockMatrix::new(&dims); let mut gradient = BlockVector::new(&[D0]); diff --git a/crates/sophus_opt/src/variables.rs b/crates/sophus_opt/src/variables.rs index b775cb0..4f0f679 100644 --- a/crates/sophus_opt/src/variables.rs +++ b/crates/sophus_opt/src/variables.rs @@ -1,4 +1,5 @@ use crate::prelude::*; +use core::fmt::Debug; use dyn_clone::DynClone; use sophus_core::linalg::VecF64; use sophus_lie::Isometry2; @@ -7,12 +8,10 @@ use sophus_lie::Isometry3; use sophus_lie::Isometry3F64; use sophus_sensor::camera_enum::perspective_camera::UnifiedCameraF64; use sophus_sensor::BrownConradyCamera; +use sophus_sensor::KannalaBrandtCamera; use sophus_sensor::PinholeCamera; -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::fmt::Debug; -use sophus_sensor::KannalaBrandtCamera; +extern crate alloc; /// Variable kind #[derive(PartialEq, Debug, Clone, Copy)] @@ -81,25 +80,31 @@ pub trait IsVarTuple: Send + Sync + 'static { /// reference to the variable family tuple fn ref_var_family_tuple( families: &VarPool, - names: [String; NUM_ARGS], + names: [alloc::string::String; NUM_ARGS], ) -> Self::VarFamilyTupleRef<'_>; /// extract the variables from the family tuple fn extract(family_tuple: &Self::VarFamilyTupleRef<'_>, ids: [usize; NUM_ARGS]) -> Self; /// return the variable kind for each variable (one for each argument of the cost function) - fn var_kind_array(families: &VarPool, names: [String; NUM_ARGS]) -> [VarKind; NUM_ARGS]; + fn var_kind_array( + families: &VarPool, + names: [alloc::string::String; NUM_ARGS], + ) -> [VarKind; NUM_ARGS]; } impl IsVarTuple<1> for M0 { const DOF_T: [usize; 1] = [M0::DOF]; type VarFamilyTupleRef<'a> = &'a VarFamily; - fn var_kind_array(families: &VarPool, names: [String; 1]) -> [VarKind; 1] { + fn var_kind_array(families: &VarPool, names: [alloc::string::String; 1]) -> [VarKind; 1] { [families.families.get(&names[0]).unwrap().get_var_kind()] } - fn ref_var_family_tuple(families: &VarPool, names: [String; 1]) -> Self::VarFamilyTupleRef<'_> { + fn ref_var_family_tuple( + families: &VarPool, + names: [alloc::string::String; 1], + ) -> Self::VarFamilyTupleRef<'_> { families.get::>(names[0].clone()) } @@ -114,14 +119,17 @@ impl = (&'a VarFamily, &'a VarFamily); - fn var_kind_array(families: &VarPool, names: [String; 2]) -> [VarKind; 2] { + fn var_kind_array(families: &VarPool, names: [alloc::string::String; 2]) -> [VarKind; 2] { [ families.families.get(&names[0]).unwrap().get_var_kind(), families.families.get(&names[1]).unwrap().get_var_kind(), ] } - fn ref_var_family_tuple(families: &VarPool, names: [String; 2]) -> Self::VarFamilyTupleRef<'_> { + fn ref_var_family_tuple( + families: &VarPool, + names: [alloc::string::String; 2], + ) -> Self::VarFamilyTupleRef<'_> { ( families.get::>(names[0].clone()), families.get::>(names[1].clone()), @@ -145,7 +153,7 @@ impl< const DOF_T: [usize; 3] = [M0::DOF, M1::DOF, M2::DOF]; type VarFamilyTupleRef<'a> = (&'a VarFamily, &'a VarFamily, &'a VarFamily); - fn var_kind_array(families: &VarPool, names: [String; 3]) -> [VarKind; 3] { + fn var_kind_array(families: &VarPool, names: [alloc::string::String; 3]) -> [VarKind; 3] { [ families.families.get(&names[0]).unwrap().get_var_kind(), families.families.get(&names[1]).unwrap().get_var_kind(), @@ -153,7 +161,10 @@ impl< ] } - fn ref_var_family_tuple(families: &VarPool, names: [String; 3]) -> Self::VarFamilyTupleRef<'_> { + fn ref_var_family_tuple( + families: &VarPool, + names: [alloc::string::String; 3], + ) -> Self::VarFamilyTupleRef<'_> { ( families.get::>(names[0].clone()), families.get::>(names[1].clone()), @@ -217,15 +228,15 @@ impl IsVariable for Isometry3F64 { pub struct VarFamily { kind: VarKind, /// members of the family - pub members: Vec, - constant_members: HashMap, - start_indices: Vec, + pub members: alloc::vec::Vec, + constant_members: alloc::collections::BTreeMap, + start_indices: alloc::vec::Vec, } impl VarFamily { /// create a new variable family a variable kind (free, conditioned, ...) and a list of members - pub fn new(kind: VarKind, members: Vec) -> Self { - Self::new_with_const_ids(kind, members, HashMap::new()) + pub fn new(kind: VarKind, members: alloc::vec::Vec) -> Self { + Self::new_with_const_ids(kind, members, alloc::collections::BTreeMap::new()) } /// Create a new variable family a variable kind (free, conditioned, ...), a list of members and a list of constant members @@ -233,14 +244,14 @@ impl VarFamily { /// The constant members are not updated during optimization (no matter the variable kind) pub fn new_with_const_ids( kind: VarKind, - members: Vec, - constant_members: HashMap, + members: alloc::vec::Vec, + constant_members: alloc::collections::BTreeMap, ) -> Self { VarFamily { kind, members, constant_members, - start_indices: vec![], + start_indices: alloc::vec![], } } @@ -267,7 +278,7 @@ pub trait IsVarFamily: as_any::AsAny + Debug + DynClone { fn num_marg_scalars(&self) -> usize; /// start indices in linear system of equations - fn get_start_indices(&self) -> &Vec; + fn get_start_indices(&self) -> &alloc::vec::Vec; /// number of members in the family fn len(&self) -> usize; @@ -330,7 +341,7 @@ impl IsVarFamily for VarFamily { match self.get_var_kind() { VarKind::Free => { - let mut indices = vec![]; + let mut indices = alloc::vec![]; let mut idx: usize = *inout_offset; for i in 0..self.members.len() { if self.constant_members.contains_key(&i) { @@ -346,7 +357,7 @@ impl IsVarFamily for VarFamily { self.start_indices = indices; } VarKind::Conditioned => { - let mut indices = vec![]; + let mut indices = alloc::vec![]; for _i in 0..self.members.len() { indices.push(-1); @@ -355,7 +366,7 @@ impl IsVarFamily for VarFamily { self.start_indices = indices; } VarKind::Marginalized => { - let mut indices = vec![]; + let mut indices = alloc::vec![]; for _i in 0..self.members.len() { indices.push(-2); @@ -378,7 +389,7 @@ impl IsVarFamily for VarFamily { self.c() } - fn get_start_indices(&self) -> &Vec { + fn get_start_indices(&self) -> &alloc::vec::Vec { &self.start_indices } @@ -392,7 +403,8 @@ dyn_clone::clone_trait_object!(IsVarFamily); /// Builder for the variable pool #[derive(Debug, Clone)] pub struct VarPoolBuilder { - families: std::collections::BTreeMap>, + families: + alloc::collections::BTreeMap>, } impl Default for VarPoolBuilder { @@ -405,17 +417,18 @@ impl VarPoolBuilder { /// create a new variable pool builder pub fn new() -> Self { Self { - families: BTreeMap::new(), + families: alloc::collections::btree_map::BTreeMap::new(), } } /// add a family of variables to the pool - pub fn add_family, Var: IsVariable + 'static>( + pub fn add_family, Var: IsVariable + 'static>( mut self, name: S, family: VarFamily, ) -> Self { - self.families.insert(name.into(), Box::new(family)); + self.families + .insert(name.into(), alloc::boxed::Box::new(family)); self } @@ -428,7 +441,8 @@ impl VarPoolBuilder { /// A pool of variable families #[derive(Debug, Clone)] pub struct VarPool { - pub(crate) families: std::collections::BTreeMap>, + pub(crate) families: + alloc::collections::BTreeMap>, } impl VarPool { @@ -479,14 +493,17 @@ impl VarPool { /// retrieve a variable family by name /// /// Panics if the family does not exist, or the specified type is not correct - pub fn get(&self, name: String) -> &T { + pub fn get(&self, name: alloc::string::String) -> &T { as_any::Downcast::downcast_ref::(self.families.get(&name).unwrap().as_ref()).unwrap() } /// retrieve family members by family name /// /// Panics if the family does not exist, or the specified type is not correct - pub fn get_members(&self, name: String) -> Vec { + pub fn get_members( + &self, + name: alloc::string::String, + ) -> alloc::vec::Vec { as_any::Downcast::downcast_ref::>(self.families.get(&name).unwrap().as_ref()) .unwrap() .members diff --git a/crates/sophus_sensor/Cargo.toml b/crates/sophus_sensor/Cargo.toml index 92cc2d4..c6ec9e8 100644 --- a/crates/sophus_sensor/Cargo.toml +++ b/crates/sophus_sensor/Cargo.toml @@ -15,7 +15,6 @@ sophus_core.workspace = true sophus_image.workspace = true approx.workspace = true -assertables.workspace = true log.workspace = true nalgebra.workspace = true ndarray.workspace = true diff --git a/crates/sophus_sensor/src/camera.rs b/crates/sophus_sensor/src/camera.rs index bd612b5..97dfdd8 100644 --- a/crates/sophus_sensor/src/camera.rs +++ b/crates/sophus_sensor/src/camera.rs @@ -2,6 +2,8 @@ use super::traits::IsCameraDistortionImpl; use crate::prelude::*; use sophus_image::ImageSize; +extern crate alloc; + /// A generic camera model #[derive(Debug, Copy, Clone)] pub struct Camera< @@ -13,7 +15,7 @@ pub struct Camera< Proj: IsProjection, > { params: S::Vector, - phantom: std::marker::PhantomData<(Distort, Proj)>, + phantom: core::marker::PhantomData<(Distort, Proj)>, image_size: ImageSize, } @@ -40,7 +42,7 @@ impl< ); Self { params: params.clone(), - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, image_size: size, } } @@ -104,12 +106,12 @@ impl< } /// Examples of valid parameters - pub fn params_examples() -> Vec> { + pub fn params_examples() -> alloc::vec::Vec> { Distort::params_examples() } /// Examples of invalid parameters - pub fn invalid_params_examples() -> Vec> { + pub fn invalid_params_examples() -> alloc::vec::Vec> { Distort::invalid_params_examples() } } diff --git a/crates/sophus_sensor/src/distortion_table.rs b/crates/sophus_sensor/src/distortion_table.rs index 01309fa..d1c2feb 100644 --- a/crates/sophus_sensor/src/distortion_table.rs +++ b/crates/sophus_sensor/src/distortion_table.rs @@ -9,6 +9,8 @@ use sophus_image::interpolation::interpolate; use sophus_image::mut_image::MutImage2F32; use sophus_image::mut_image_view::IsMutImageView; +extern crate alloc; + /// A table of distortion values. #[derive(Debug, Clone)] pub struct DistortTable { @@ -111,7 +113,7 @@ fn camera_distortion_table_tests() { type DynCameraF64 = DynCamera; { - let mut cameras: Vec = vec![]; + let mut cameras: alloc::vec::Vec = alloc::vec![]; cameras.push(DynCameraF64::new_pinhole( &VecF64::<4>::new(600.0, 600.0, 1.0, 0.5), ImageSize { @@ -121,7 +123,9 @@ fn camera_distortion_table_tests() { )); cameras.push(DynCamera::new_kannala_brandt( - &VecF64::<8>::from_vec(vec![1000.0, 1000.0, 320.0, 280.0, 0.1, 0.01, 0.001, 0.0001]), + &VecF64::<8>::from_vec(alloc::vec![ + 1000.0, 1000.0, 320.0, 280.0, 0.1, 0.01, 0.001, 0.0001 + ]), ImageSize { width: 640, height: 480, @@ -129,7 +133,7 @@ fn camera_distortion_table_tests() { )); for camera in cameras { - let pixels_in_image = vec![ + let pixels_in_image = alloc::vec![ VecF64::<2>::new(0.0, 0.0), VecF64::<2>::new(2.0, 1.0), VecF64::<2>::new(2.9, 1.9), diff --git a/crates/sophus_sensor/src/distortions/affine.rs b/crates/sophus_sensor/src/distortions/affine.rs index 55ad8a4..cc04003 100644 --- a/crates/sophus_sensor/src/distortions/affine.rs +++ b/crates/sophus_sensor/src/distortions/affine.rs @@ -1,7 +1,9 @@ use crate::prelude::*; use crate::traits::IsCameraDistortionImpl; +use core::marker::PhantomData; use sophus_core::params::ParamsImpl; -use std::marker::PhantomData; + +extern crate alloc; /// Affine "distortion" implementation /// @@ -18,12 +20,12 @@ impl, const BATCH: usize> ParamsImpl S::Mask::all_true() } - fn params_examples() -> Vec> { - vec![S::Vector::<4>::from_f64_array([1.0, 1.0, 0.0, 0.0])] + fn params_examples() -> alloc::vec::Vec> { + alloc::vec![S::Vector::<4>::from_f64_array([1.0, 1.0, 0.0, 0.0])] } - fn invalid_params_examples() -> Vec> { - vec![ + fn invalid_params_examples() -> alloc::vec::Vec> { + alloc::vec![ S::Vector::<4>::from_f64_array([0.0, 1.0, 0.0, 0.0]), S::Vector::<4>::from_f64_array([1.0, 0.0, 0.0, 0.0]), ] diff --git a/crates/sophus_sensor/src/distortions/brown_conrady.rs b/crates/sophus_sensor/src/distortions/brown_conrady.rs index ad1c4fa..5586d57 100644 --- a/crates/sophus_sensor/src/distortions/brown_conrady.rs +++ b/crates/sophus_sensor/src/distortions/brown_conrady.rs @@ -1,10 +1,12 @@ use crate::distortions::affine::AffineDistortionImpl; use crate::prelude::*; use crate::traits::IsCameraDistortionImpl; +use core::marker::PhantomData; use log::warn; use sophus_core::linalg::EPS_F64; use sophus_core::params::ParamsImpl; -use std::marker::PhantomData; + +extern crate alloc; /// Kannala-Brandt distortion implementation #[derive(Debug, Clone, Copy)] @@ -19,8 +21,8 @@ impl, const BATCH: usize> ParamsImpl S::Mask::all_true() } - fn params_examples() -> Vec> { - vec![S::Vector::<12>::from_f64_array([ + fn params_examples() -> alloc::vec::Vec> { + alloc::vec![S::Vector::<12>::from_f64_array([ 286.0, 286.0, 424.0, @@ -36,8 +38,8 @@ impl, const BATCH: usize> ParamsImpl ])] } - fn invalid_params_examples() -> Vec> { - vec![] + fn invalid_params_examples() -> alloc::vec::Vec> { + alloc::vec![] } } diff --git a/crates/sophus_sensor/src/distortions/kannala_brandt.rs b/crates/sophus_sensor/src/distortions/kannala_brandt.rs index a58612e..6b99cfa 100644 --- a/crates/sophus_sensor/src/distortions/kannala_brandt.rs +++ b/crates/sophus_sensor/src/distortions/kannala_brandt.rs @@ -1,8 +1,10 @@ use crate::prelude::*; use crate::traits::IsCameraDistortionImpl; +use core::marker::PhantomData; use sophus_core::linalg::EPS_F64; use sophus_core::params::ParamsImpl; -use std::marker::PhantomData; + +extern crate alloc; /// Kannala-Brandt distortion implementation #[derive(Debug, Clone, Copy)] @@ -17,14 +19,14 @@ impl, const BATCH: usize> ParamsImpl S::Mask::all_true() } - fn params_examples() -> Vec> { - vec![S::Vector::<8>::from_f64_array([ + fn params_examples() -> alloc::vec::Vec> { + alloc::vec![S::Vector::<8>::from_f64_array([ 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, ])] } - fn invalid_params_examples() -> Vec> { - vec![ + fn invalid_params_examples() -> alloc::vec::Vec> { + alloc::vec![ S::Vector::<8>::from_f64_array([0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), S::Vector::<8>::from_f64_array([1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), ] diff --git a/crates/sophus_sensor/src/distortions/unified.rs b/crates/sophus_sensor/src/distortions/unified.rs index 2819a21..5f2ea41 100644 --- a/crates/sophus_sensor/src/distortions/unified.rs +++ b/crates/sophus_sensor/src/distortions/unified.rs @@ -1,10 +1,12 @@ use crate::prelude::*; use crate::traits::IsCameraDistortionImpl; +use core::marker::PhantomData; use sophus_core::params::ParamsImpl; use sophus_core::prelude::IsMatrix; use sophus_core::prelude::IsScalar; use sophus_core::prelude::IsVector; -use std::marker::PhantomData; + +extern crate alloc; /// Unified Extended distortion implementation #[derive(Debug, Clone, Copy)] @@ -19,14 +21,14 @@ impl, const BATCH: usize> ParamsImpl S::Mask::all_true() } - fn params_examples() -> Vec> { - vec![S::Vector::<6>::from_f64_array([ + fn params_examples() -> alloc::vec::Vec> { + alloc::vec![S::Vector::<6>::from_f64_array([ 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, ])] } - fn invalid_params_examples() -> Vec> { - vec![ + fn invalid_params_examples() -> alloc::vec::Vec> { + alloc::vec![ S::Vector::<6>::from_f64_array([0.0, 1.0, 0.0, 0.0, 0.0, 0.0]), S::Vector::<6>::from_f64_array([1.0, 0.0, 0.0, 0.0, 0.0, 0.0]), ] diff --git a/crates/sophus_sensor/src/dyn_camera.rs b/crates/sophus_sensor/src/dyn_camera.rs index 32d0299..7aca225 100644 --- a/crates/sophus_sensor/src/dyn_camera.rs +++ b/crates/sophus_sensor/src/dyn_camera.rs @@ -7,6 +7,8 @@ use crate::KannalaBrandtCamera; use crate::PinholeCamera; use sophus_image::ImageSize; +extern crate alloc; + /// Dynamic camera facade #[derive(Debug, Clone)] pub struct DynCameraFacade< @@ -15,7 +17,7 @@ pub struct DynCameraFacade< CameraType: IsCameraEnum, > { camera_type: CameraType, - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } /// Dynamic generalized camera (perspective or orthographic) @@ -47,7 +49,7 @@ impl, const BATCH: usize, CameraType: IsCameraEnum> ]), image_size, ), - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } } @@ -71,7 +73,7 @@ impl, const BATCH: usize, CameraType: IsCameraEnum> ]), image_size, ), - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } } @@ -79,7 +81,7 @@ impl, const BATCH: usize, CameraType: IsCameraEnum> pub fn from_model(camera_type: CameraType) -> Self { Self { camera_type, - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } } @@ -187,7 +189,7 @@ fn dyn_camera_tests() { type DynCameraF64 = DynCamera; { - let mut cameras: Vec = vec![]; + let mut cameras: alloc::vec::Vec = alloc::vec![]; cameras.push(DynCameraF64::new_pinhole( &VecF64::<4>::new(600.0, 599.0, 1.0, 0.5), ImageSize { @@ -197,7 +199,7 @@ fn dyn_camera_tests() { )); cameras.push(DynCamera::new_unified( - &VecF64::<6>::from_vec(vec![998.0, 1000.0, 320.0, 280.0, 0.5, 1.2]), + &VecF64::<6>::from_vec(alloc::vec![998.0, 1000.0, 320.0, 280.0, 0.5, 1.2]), ImageSize { width: 640, height: 480, @@ -205,7 +207,9 @@ fn dyn_camera_tests() { )); cameras.push(DynCamera::new_kannala_brandt( - &VecF64::<8>::from_vec(vec![999.0, 1000.0, 320.0, 280.0, 0.1, 0.01, 0.001, 0.0001]), + &VecF64::<8>::from_vec(alloc::vec![ + 999.0, 1000.0, 320.0, 280.0, 0.1, 0.01, 0.001, 0.0001 + ]), ImageSize { width: 640, height: 480, @@ -213,7 +217,7 @@ fn dyn_camera_tests() { )); cameras.push(DynCamera::new_brown_conrady( - &VecF64::<12>::from_vec(vec![ + &VecF64::<12>::from_vec(alloc::vec![ 288.0, 284.0, 0.5 * (424.0 - 1.0), @@ -234,7 +238,7 @@ fn dyn_camera_tests() { )); for camera in cameras { - let pixels_in_image = vec![ + let pixels_in_image = alloc::vec![ VecF64::<2>::new(2.0, 1.0), VecF64::<2>::new(2.9, 1.9), VecF64::<2>::new(2.5, 1.5), @@ -275,8 +279,6 @@ fn dyn_camera_tests() { pixel, EPS_F64, ); - println!("dx: {:?}", dx); - println!("numeric_dx: {:?}", numeric_dx); assert_relative_eq!(dx, numeric_dx, epsilon = 1e-4); @@ -303,7 +305,6 @@ fn dyn_camera_tests() { params, EPS_F64, ); - println!("dx_params: {:?}", dx_params); assert_relative_eq!(dx_params, numeric_dx_params, epsilon = 1e-4); } PerspectiveCameraEnum::BrownConrady(_camera) => { diff --git a/crates/sophus_sensor/src/lib.rs b/crates/sophus_sensor/src/lib.rs index 86d9f4f..2b3d889 100644 --- a/crates/sophus_sensor/src/lib.rs +++ b/crates/sophus_sensor/src/lib.rs @@ -1,5 +1,6 @@ #![cfg_attr(feature = "simd", feature(portable_simd))] #![deny(missing_docs)] +#![no_std] //! Sensor (aka camera) crate - part of the sophus-rs project diff --git a/crates/sophus_sensor/src/projections/orthographic.rs b/crates/sophus_sensor/src/projections/orthographic.rs index 544b00f..9667fd5 100644 --- a/crates/sophus_sensor/src/projections/orthographic.rs +++ b/crates/sophus_sensor/src/projections/orthographic.rs @@ -1,9 +1,9 @@ use crate::camera::Camera; use crate::distortions::affine::AffineDistortionImpl; use crate::traits::IsProjection; +use core::marker::PhantomData; use sophus_core::linalg::scalar::IsScalar; use sophus_core::linalg::vector::IsVector; -use std::marker::PhantomData; /// Orthographic projection implementation #[derive(Debug, Clone)] diff --git a/crates/sophus_sensor/src/projections/perspective.rs b/crates/sophus_sensor/src/projections/perspective.rs index 1fb405b..97df136 100644 --- a/crates/sophus_sensor/src/projections/perspective.rs +++ b/crates/sophus_sensor/src/projections/perspective.rs @@ -9,7 +9,7 @@ use sophus_core::prelude::IsSingleScalar; /// Projects a 3D point in the camera frame to a 2D point in the z=1 plane #[derive(Debug, Clone, Copy)] pub struct PerspectiveProjectionImpl, const BATCH: usize> { - phantom: std::marker::PhantomData, + phantom: core::marker::PhantomData, } impl, const BATCH: usize> IsProjection diff --git a/justfile b/justfile index b12bc68..12a9980 100644 --- a/justfile +++ b/justfile @@ -5,4 +5,13 @@ clippy: cargo clippy build: - cargo build --release --all + cargo build --release --all-targets + +build-std: + cargo build --release --all-targets --features std + +build-simd: + cargo +nightly build --release --all-targets --features simd + +test: + cargo +nightly test --release