diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/crates.js b/crates.js new file mode 100644 index 00000000..04ca6086 --- /dev/null +++ b/crates.js @@ -0,0 +1,2 @@ +window.ALL_CRATES = ["peng_quad"]; +//{"start":21,"fragment_lengths":[11]} \ No newline at end of file diff --git a/help.html b/help.html new file mode 100644 index 00000000..a414d19a --- /dev/null +++ b/help.html @@ -0,0 +1 @@ +Help

Rustdoc help

Back
\ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..54251167 --- /dev/null +++ b/index.html @@ -0,0 +1 @@ + diff --git a/peng_quad/all.html b/peng_quad/all.html new file mode 100644 index 00000000..e5de9910 --- /dev/null +++ b/peng_quad/all.html @@ -0,0 +1 @@ +List of all items in this crate

List of all items

Structs

Enums

Traits

Functions

\ No newline at end of file diff --git a/peng_quad/config/index.html b/peng_quad/config/index.html new file mode 100644 index 00000000..ba019929 --- /dev/null +++ b/peng_quad/config/index.html @@ -0,0 +1,5 @@ +peng_quad::config - Rust

Module peng_quad::config

source ·
Expand description

Configuration module +This module contains the configuration for the simulation, quadrotor, PID controller, IMU, maze, camera, mesh, and planner schedule. +The configuration is loaded from a YAML file using the serde library. +The configuration is then used to initialize the simulation, quadrotor, PID controller, IMU, maze, camera, mesh, and planner schedule.

+

Structs§

\ No newline at end of file diff --git a/peng_quad/config/sidebar-items.js b/peng_quad/config/sidebar-items.js new file mode 100644 index 00000000..cf898bb5 --- /dev/null +++ b/peng_quad/config/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["CameraConfig","Config","ImuConfig","MazeConfig","MeshConfig","PIDControllerConfig","PIDGains","PlannerStep","QuadrotorConfig","SimulationConfig"]}; \ No newline at end of file diff --git a/peng_quad/config/struct.CameraConfig.html b/peng_quad/config/struct.CameraConfig.html new file mode 100644 index 00000000..fb216d9a --- /dev/null +++ b/peng_quad/config/struct.CameraConfig.html @@ -0,0 +1,54 @@ +CameraConfig in peng_quad::config - Rust

Struct peng_quad::config::CameraConfig

source ·
pub struct CameraConfig {
+    pub resolution: (usize, usize),
+    pub fov: f32,
+    pub near: f32,
+    pub far: f32,
+    pub rotation_transform: [f32; 9],
+}
Expand description

Configuration for the camera

+

Fields§

§resolution: (usize, usize)

Camera resolution in pixels (width, height)

+
§fov: f32

Camera field of view in height in degrees

+
§near: f32

Camera near clipping plane in meters

+
§far: f32

Camera far clipping plane in meters

+
§rotation_transform: [f32; 9]

Camera transform matrix for depth

+

Trait Implementations§

source§

impl<'de> Deserialize<'de> for CameraConfig

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

\ No newline at end of file diff --git a/peng_quad/config/struct.Config.html b/peng_quad/config/struct.Config.html new file mode 100644 index 00000000..c61e3abf --- /dev/null +++ b/peng_quad/config/struct.Config.html @@ -0,0 +1,84 @@ +Config in peng_quad::config - Rust

Struct peng_quad::config::Config

source ·
pub struct Config {
Show 13 fields + pub simulation: SimulationConfig, + pub quadrotor: QuadrotorConfig, + pub pid_controller: PIDControllerConfig, + pub imu: ImuConfig, + pub maze: MazeConfig, + pub camera: CameraConfig, + pub mesh: MeshConfig, + pub planner_schedule: Vec<PlannerStep>, + pub use_rerun: bool, + pub render_depth: bool, + pub use_multithreading_depth_rendering: bool, + pub use_rk4_for_dynamics_control: bool, + pub use_rk4_for_dynamics_update: bool, +
}
Expand description

Configuration for the simulation

+

Fields§

§simulation: SimulationConfig

Simulation configuration

+
§quadrotor: QuadrotorConfig

Quadrotor configuration

+
§pid_controller: PIDControllerConfig

PID Controller configuration

+
§imu: ImuConfig

IMU configuration

+
§maze: MazeConfig

Maze configuration

+
§camera: CameraConfig

Camera configuration

+
§mesh: MeshConfig

Mesh configuration

+
§planner_schedule: Vec<PlannerStep>

Planner schedule configuration

+
§use_rerun: bool

Use rerun.io for recording

+
§render_depth: bool

Render depth

+
§use_multithreading_depth_rendering: bool

MultiThreading depth rendering

+
§use_rk4_for_dynamics_control: bool

Use RK4 for updating quadrotor dynamics_with_controls

+
§use_rk4_for_dynamics_update: bool

Use RK4 for updating quadrotor dynamics without controls

+

Implementations§

source§

impl Config

Implementation of the Config struct

+
source

pub fn from_yaml(filename: &str) -> Result<Self, Box<dyn Error>>

Load configuration from a YAML file.

+
§Arguments
+
    +
  • filename - The name of the file to load.
  • +
+
§Returns
+
    +
  • The configuration object.
  • +
+
§Errors
+
    +
  • If the file cannot be read or the YAML cannot be parsed.
  • +
+

Trait Implementations§

source§

impl<'de> Deserialize<'de> for Config

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

§

impl Freeze for Config

§

impl RefUnwindSafe for Config

§

impl Send for Config

§

impl Sync for Config

§

impl Unpin for Config

§

impl UnwindSafe for Config

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

\ No newline at end of file diff --git a/peng_quad/config/struct.ImuConfig.html b/peng_quad/config/struct.ImuConfig.html new file mode 100644 index 00000000..a562f3ae --- /dev/null +++ b/peng_quad/config/struct.ImuConfig.html @@ -0,0 +1,52 @@ +ImuConfig in peng_quad::config - Rust

Struct peng_quad::config::ImuConfig

source ·
pub struct ImuConfig {
+    pub accel_noise_std: f32,
+    pub gyro_noise_std: f32,
+    pub accel_bias_std: f32,
+    pub gyro_bias_std: f32,
+}
Expand description

Configuration for the IMU

+

Fields§

§accel_noise_std: f32

Accelerometer noise standard deviation

+
§gyro_noise_std: f32

Gyroscope noise standard deviation

+
§accel_bias_std: f32

Accelerometer bias drift standard deviation

+
§gyro_bias_std: f32

Gyroscope bias drift standard deviation

+

Trait Implementations§

source§

impl Default for ImuConfig

source§

fn default() -> ImuConfig

Returns the “default value” for a type. Read more
source§

impl<'de> Deserialize<'de> for ImuConfig

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

\ No newline at end of file diff --git a/peng_quad/config/struct.MazeConfig.html b/peng_quad/config/struct.MazeConfig.html new file mode 100644 index 00000000..efbb241f --- /dev/null +++ b/peng_quad/config/struct.MazeConfig.html @@ -0,0 +1,54 @@ +MazeConfig in peng_quad::config - Rust

Struct peng_quad::config::MazeConfig

source ·
pub struct MazeConfig {
+    pub upper_bounds: [f32; 3],
+    pub lower_bounds: [f32; 3],
+    pub num_obstacles: usize,
+    pub obstacles_velocity_bounds: [f32; 3],
+    pub obstacles_radius_bounds: [f32; 2],
+}
Expand description

Configuration for the maze

+

Fields§

§upper_bounds: [f32; 3]

Upper bounds of the maze in meters (x, y, z)

+
§lower_bounds: [f32; 3]

Lower bounds of the maze in meters (x, y, z)

+
§num_obstacles: usize

Number of obstacles in the maze

+
§obstacles_velocity_bounds: [f32; 3]

Obstacle velocity maximum bounds in m/s in (x, y, z) directions

+
§obstacles_radius_bounds: [f32; 2]

Obstacle radius bounds in meters (min, max)

+

Trait Implementations§

source§

impl<'de> Deserialize<'de> for MazeConfig

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

\ No newline at end of file diff --git a/peng_quad/config/struct.MeshConfig.html b/peng_quad/config/struct.MeshConfig.html new file mode 100644 index 00000000..180c0244 --- /dev/null +++ b/peng_quad/config/struct.MeshConfig.html @@ -0,0 +1,48 @@ +MeshConfig in peng_quad::config - Rust

Struct peng_quad::config::MeshConfig

source ·
pub struct MeshConfig {
+    pub division: usize,
+    pub spacing: f32,
+}
Expand description

Configuration for the mesh

+

Fields§

§division: usize

Division of the 2D mesh, the mesh will be division x division squares

+
§spacing: f32

Spacing between the squares in meters

+

Trait Implementations§

source§

impl<'de> Deserialize<'de> for MeshConfig

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

\ No newline at end of file diff --git a/peng_quad/config/struct.PIDControllerConfig.html b/peng_quad/config/struct.PIDControllerConfig.html new file mode 100644 index 00000000..a5875c97 --- /dev/null +++ b/peng_quad/config/struct.PIDControllerConfig.html @@ -0,0 +1,52 @@ +PIDControllerConfig in peng_quad::config - Rust

Struct peng_quad::config::PIDControllerConfig

source ·
pub struct PIDControllerConfig {
+    pub pos_gains: PIDGains,
+    pub att_gains: PIDGains,
+    pub pos_max_int: [f32; 3],
+    pub att_max_int: [f32; 3],
+}
Expand description

Configuration for the PID controller

+

Fields§

§pos_gains: PIDGains

Position gains

+
§att_gains: PIDGains

Attitude gains

+
§pos_max_int: [f32; 3]

Maximum integral error for position control

+
§att_max_int: [f32; 3]

Maximum integral error for attitude control

+

Trait Implementations§

source§

impl<'de> Deserialize<'de> for PIDControllerConfig

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

\ No newline at end of file diff --git a/peng_quad/config/struct.PIDGains.html b/peng_quad/config/struct.PIDGains.html new file mode 100644 index 00000000..ac5df8e0 --- /dev/null +++ b/peng_quad/config/struct.PIDGains.html @@ -0,0 +1,50 @@ +PIDGains in peng_quad::config - Rust

Struct peng_quad::config::PIDGains

source ·
pub struct PIDGains {
+    pub kp: [f32; 3],
+    pub ki: [f32; 3],
+    pub kd: [f32; 3],
+}
Expand description

Configuration for PID gains

+

Fields§

§kp: [f32; 3]

Proportional gains

+
§ki: [f32; 3]

Integral gains

+
§kd: [f32; 3]

Derivative gains

+

Trait Implementations§

source§

impl<'de> Deserialize<'de> for PIDGains

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

\ No newline at end of file diff --git a/peng_quad/config/struct.PlannerStep.html b/peng_quad/config/struct.PlannerStep.html new file mode 100644 index 00000000..9c788b72 --- /dev/null +++ b/peng_quad/config/struct.PlannerStep.html @@ -0,0 +1,50 @@ +PlannerStep in peng_quad::config - Rust

Struct peng_quad::config::PlannerStep

source ·
pub struct PlannerStep {
+    pub step: usize,
+    pub planner_type: String,
+    pub params: Value,
+}
Expand description

Configuration for a planner step

+

Fields§

§step: usize

Step number that the planner should be executed (Unit: ms)

+
§planner_type: String

Type of planner to use

+
§params: Value

Parameters for the planner

+

Trait Implementations§

source§

impl<'de> Deserialize<'de> for PlannerStep

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

\ No newline at end of file diff --git a/peng_quad/config/struct.QuadrotorConfig.html b/peng_quad/config/struct.QuadrotorConfig.html new file mode 100644 index 00000000..83837ac0 --- /dev/null +++ b/peng_quad/config/struct.QuadrotorConfig.html @@ -0,0 +1,52 @@ +QuadrotorConfig in peng_quad::config - Rust

Struct peng_quad::config::QuadrotorConfig

source ·
pub struct QuadrotorConfig {
+    pub mass: f32,
+    pub gravity: f32,
+    pub drag_coefficient: f32,
+    pub inertia_matrix: [f32; 9],
+}
Expand description

Configuration for the quadrotor

+

Fields§

§mass: f32

Mass of the quadrotor in kg

+
§gravity: f32

Gravity in m/s^2

+
§drag_coefficient: f32

Drag coefficient in Ns^2/m^2

+
§inertia_matrix: [f32; 9]

Inertia matrix in kg*m^2

+

Trait Implementations§

source§

impl<'de> Deserialize<'de> for QuadrotorConfig

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

\ No newline at end of file diff --git a/peng_quad/config/struct.SimulationConfig.html b/peng_quad/config/struct.SimulationConfig.html new file mode 100644 index 00000000..f0c5a354 --- /dev/null +++ b/peng_quad/config/struct.SimulationConfig.html @@ -0,0 +1,52 @@ +SimulationConfig in peng_quad::config - Rust

Struct peng_quad::config::SimulationConfig

source ·
pub struct SimulationConfig {
+    pub control_frequency: usize,
+    pub simulation_frequency: usize,
+    pub log_frequency: usize,
+    pub duration: f32,
+}
Expand description

Configuration for the simulation

+

Fields§

§control_frequency: usize

Control frequency in Hz

+
§simulation_frequency: usize

Simulation frequency in Hz

+
§log_frequency: usize

Log frequency in Hz

+
§duration: f32

Duration of the simulation in seconds

+

Trait Implementations§

source§

impl<'de> Deserialize<'de> for SimulationConfig

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

\ No newline at end of file diff --git a/peng_quad/enum.PlannerType.html b/peng_quad/enum.PlannerType.html new file mode 100644 index 00000000..9c7c45ad --- /dev/null +++ b/peng_quad/enum.PlannerType.html @@ -0,0 +1,114 @@ +PlannerType in peng_quad - Rust

Enum peng_quad::PlannerType

source ·
pub enum PlannerType {
+    Hover(HoverPlanner),
+    MinimumJerkLine(MinimumJerkLinePlanner),
+    Lissajous(LissajousPlanner),
+    Circle(CirclePlanner),
+    Landing(LandingPlanner),
+    ObstacleAvoidance(ObstacleAvoidancePlanner),
+    MinimumSnapWaypoint(MinimumSnapWaypointPlanner),
+}
Expand description

Enum representing different types of trajectory planners

+

§Example

+
use peng_quad::PlannerType;
+use peng_quad::HoverPlanner;
+let hover_planner : PlannerType = PlannerType::Hover(HoverPlanner{
+    target_position: nalgebra::Vector3::new(0.0, 0.0, 1.0),
+    target_yaw: 0.0,
+});
+

Variants§

§

Hover(HoverPlanner)

Hover planner

+
§

MinimumJerkLine(MinimumJerkLinePlanner)

Minimum jerk line planner

+
§

Lissajous(LissajousPlanner)

Minimum jerk circle planner

+
§

Circle(CirclePlanner)

Minimum jerk circle planner

+
§

Landing(LandingPlanner)

Minimum jerk landing planner

+
§

ObstacleAvoidance(ObstacleAvoidancePlanner)

Obstacle avoidance planner

+
§

MinimumSnapWaypoint(MinimumSnapWaypointPlanner)

Minimum snap waypoint planner

+

Implementations§

source§

impl PlannerType

Implementation of the planner type

+
source

pub fn plan( + &self, + current_position: Vector3<f32>, + current_velocity: Vector3<f32>, + time: f32, +) -> (Vector3<f32>, Vector3<f32>, f32)

Plans the trajectory based on the current planner type

+
§Arguments
+
    +
  • current_position - The current position of the quadrotor
  • +
  • current_velocity - The current velocity of the quadrotor
  • +
  • time - The current simulation time
  • +
+
§Returns
+
    +
  • A tuple containing the desired position, velocity, and yaw angle
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::PlannerType;
+use peng_quad::HoverPlanner;
+let hover_planner = HoverPlanner {
+    target_position: Vector3::new(0.0, 0.0, 1.0),
+    target_yaw: 0.0
+};
+let hover_planner_type = PlannerType::Hover(hover_planner);
+let (desired_position, desired_velocity, desired_yaw) = hover_planner_type.plan(Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 0.0);
+
source

pub fn is_finished( + &self, + current_position: Vector3<f32>, + time: f32, +) -> Result<bool, SimulationError>

Checks if the current trajectory is finished

+
§Arguments
+
    +
  • current_position - The current position of the quadrotor
  • +
  • time - The current simulation time
  • +
+
§Returns
+
    +
  • true if the trajectory is finished, false otherwise
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::PlannerType;
+use peng_quad::HoverPlanner;
+use peng_quad::Planner;
+let hover_planner = HoverPlanner{
+    target_position: Vector3::new(0.0, 0.0, 1.0),
+    target_yaw: 0.0,
+};
+let is_finished = hover_planner.is_finished(Vector3::new(0.0, 0.0, 0.0), 0.0);
+

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/enum.SimulationError.html b/peng_quad/enum.SimulationError.html new file mode 100644 index 00000000..6459d6f0 --- /dev/null +++ b/peng_quad/enum.SimulationError.html @@ -0,0 +1,56 @@ +SimulationError in peng_quad - Rust

Enum peng_quad::SimulationError

source ·
pub enum SimulationError {
+    RerunError(RecordingStreamError),
+    RerunSpawnError(SpawnError),
+    NalgebraError(String),
+    NormalError(NormalError),
+    OtherError(String),
+}
Expand description

Represents errors that can occur during simulation

+

§Example

+
use peng_quad::SimulationError;
+let error = SimulationError::NalgebraError("Matrix inversion failed".to_string());
+

Variants§

§

RerunError(RecordingStreamError)

Error related to Rerun visualization

+
§

RerunSpawnError(SpawnError)

Error related to Rerun spawn process

+
§

NalgebraError(String)

Error related to linear algebra operations

+
§

NormalError(NormalError)

Error related to normal distribution calculations

+
§

OtherError(String)

Other general errors

+

Trait Implementations§

source§

impl Debug for SimulationError

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for SimulationError

source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Error for SimulationError

source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
source§

impl From<Error> for SimulationError

source§

fn from(source: NormalError) -> Self

Converts to this type from the input type.
source§

impl From<RecordingStreamError> for SimulationError

source§

fn from(source: RecordingStreamError) -> Self

Converts to this type from the input type.
source§

impl From<SpawnError> for SimulationError

source§

fn from(source: SpawnError) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/fn.color_map_fn.html b/peng_quad/fn.color_map_fn.html new file mode 100644 index 00000000..1158f391 --- /dev/null +++ b/peng_quad/fn.color_map_fn.html @@ -0,0 +1,13 @@ +color_map_fn in peng_quad - Rust

Function peng_quad::color_map_fn

source ·
pub fn color_map_fn(gray: f32) -> (u8, u8, u8)
Expand description

turbo color map function

+

§Arguments

+
    +
  • gray - The gray value in the range [0, 255]
  • +
+

§Returns

+
    +
  • The RGB color value in the range [0, 255]
  • +
+

§Example

+
use peng_quad::color_map_fn;
+let color = color_map_fn(128.0);
+
\ No newline at end of file diff --git a/peng_quad/fn.create_planner.html b/peng_quad/fn.create_planner.html new file mode 100644 index 00000000..1f2d7c79 --- /dev/null +++ b/peng_quad/fn.create_planner.html @@ -0,0 +1,45 @@ +create_planner in peng_quad - Rust

Function peng_quad::create_planner

source ·
pub fn create_planner(
+    step: &PlannerStepConfig,
+    quad: &Quadrotor,
+    time: f32,
+    obstacles: &[Obstacle],
+) -> Result<PlannerType, SimulationError>
Expand description

Creates a planner based on the configuration

+

§Arguments

+
    +
  • step - The configuration for the planner step in ms unit
  • +
  • quad - The Quadrotor instance
  • +
  • time - The current simulation time
  • +
  • obstacles - The current obstacles in the simulation
  • +
+

§Returns

+
    +
  • PlannerType - The created planner
  • +
+

§Errors

+
    +
  • If the planner type is not recognized
  • +
+

§Example

+
use peng_quad::{PlannerType, Quadrotor, Obstacle, PlannerStepConfig, create_planner};
+use nalgebra::Vector3;
+let step = PlannerStepConfig {
+   step: 0,
+  planner_type: "MinimumJerkLine".to_string(),
+  params:
+      serde_yaml::from_str(r#"
+      end_position: [0.0, 0.0, 1.0]
+      end_yaw: 0.0
+      duration: 2.0
+      "#).unwrap(),
+};
+let time = 0.0;
+let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+let obstacles = vec![Obstacle::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 1.0)];
+let planner = create_planner(&step, &quadrotor, time, &obstacles).unwrap();
+match planner {
+   PlannerType::MinimumJerkLine(_) => log::info!("Created MinimumJerkLine planner"),
+  _ => log::info!("Created another planner"),
+}
+
\ No newline at end of file diff --git a/peng_quad/fn.log_data.html b/peng_quad/fn.log_data.html new file mode 100644 index 00000000..48cb7298 --- /dev/null +++ b/peng_quad/fn.log_data.html @@ -0,0 +1,33 @@ +log_data in peng_quad - Rust

Function peng_quad::log_data

source ·
pub fn log_data(
+    rec: &RecordingStream,
+    quad: &Quadrotor,
+    desired_position: &Vector3<f32>,
+    desired_velocity: &Vector3<f32>,
+    measured_accel: &Vector3<f32>,
+    measured_gyro: &Vector3<f32>,
+) -> Result<(), SimulationError>
Expand description

Logs simulation data to the rerun recording stream

+

§Arguments

+
    +
  • rec - The rerun::RecordingStream instance
  • +
  • quad - The Quadrotor instance
  • +
  • desired_position - The desired position vector
  • +
  • measured_accel - The measured acceleration vector
  • +
  • measured_gyro - The measured angular velocity vector
  • +
+

§Errors

+
    +
  • If the data cannot be logged to the recording stream
  • +
+

§Example

+
use peng_quad::{Quadrotor, log_data};
+use nalgebra::Vector3;
+let rec = rerun::RecordingStreamBuilder::new("peng").connect().unwrap();
+let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+let quad = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+let desired_position = Vector3::new(0.0, 0.0, 0.0);
+let desired_velocity = Vector3::new(0.0, 0.0, 0.0);
+let measured_accel = Vector3::new(0.0, 0.0, 0.0);
+let measured_gyro = Vector3::new(0.0, 0.0, 0.0);
+log_data(&rec, &quad, &desired_position, &desired_velocity, &measured_accel, &measured_gyro).unwrap();
+
\ No newline at end of file diff --git a/peng_quad/fn.log_depth_image.html b/peng_quad/fn.log_depth_image.html new file mode 100644 index 00000000..a5fe82a1 --- /dev/null +++ b/peng_quad/fn.log_depth_image.html @@ -0,0 +1,27 @@ +log_depth_image in peng_quad - Rust

Function peng_quad::log_depth_image

source ·
pub fn log_depth_image(
+    rec: &RecordingStream,
+    depth_image: &[f32],
+    width: usize,
+    height: usize,
+    min_depth: f32,
+    max_depth: f32,
+) -> Result<(), SimulationError>
Expand description

log depth image data to the rerun recording stream

+

§Arguments

+
    +
  • rec - The rerun::RecordingStream instance
  • +
  • depth_image - The depth image data
  • +
  • width - The width of the depth image
  • +
  • height - The height of the depth image
  • +
  • min_depth - The minimum depth value
  • +
  • max_depth - The maximum depth value
  • +
+

§Errors

+
    +
  • If the data cannot be logged to the recording stream
  • +
+

§Example

+
use peng_quad::log_depth_image;
+let rec = rerun::RecordingStreamBuilder::new("log.rerun").connect().unwrap();
+let depth_image = vec![0.0; 640 * 480];
+log_depth_image(&rec, &depth_image, 640, 480, 0.0, 1.0).unwrap();
+
\ No newline at end of file diff --git a/peng_quad/fn.log_maze_obstacles.html b/peng_quad/fn.log_maze_obstacles.html new file mode 100644 index 00000000..ed787498 --- /dev/null +++ b/peng_quad/fn.log_maze_obstacles.html @@ -0,0 +1,19 @@ +log_maze_obstacles in peng_quad - Rust

Function peng_quad::log_maze_obstacles

source ·
pub fn log_maze_obstacles(
+    rec: &RecordingStream,
+    maze: &Maze,
+) -> Result<(), SimulationError>
Expand description

Log the maze obstacles to the rerun recording stream

+

§Arguments

+
    +
  • rec - The rerun::RecordingStream instance
  • +
  • maze - The maze instance
  • +
+

§Errors

+
    +
  • If the data cannot be logged to the recording stream
  • +
+

§Example

+
use peng_quad::{Maze, log_maze_obstacles};
+let rec = rerun::RecordingStreamBuilder::new("log.rerun").connect().unwrap();
+let mut maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+log_maze_obstacles(&rec, &maze).unwrap();
+
\ No newline at end of file diff --git a/peng_quad/fn.log_maze_tube.html b/peng_quad/fn.log_maze_tube.html new file mode 100644 index 00000000..cb248488 --- /dev/null +++ b/peng_quad/fn.log_maze_tube.html @@ -0,0 +1,20 @@ +log_maze_tube in peng_quad - Rust

Function peng_quad::log_maze_tube

source ·
pub fn log_maze_tube(
+    rec: &RecordingStream,
+    maze: &Maze,
+) -> Result<(), SimulationError>
Expand description

Log the maze tube to the rerun recording stream

+

§Arguments

+
    +
  • rec - The rerun::RecordingStream instance
  • +
  • maze - The maze instance
  • +
+

§Errors

+
    +
  • If the data cannot be logged to the recording stream
  • +
+

§Example

+
use peng_quad::{Maze, log_maze_tube};
+use rerun::RecordingStreamBuilder;
+let rec = rerun::RecordingStreamBuilder::new("log.rerun").connect().unwrap();
+let mut maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+log_maze_tube(&rec, &maze).unwrap();
+
\ No newline at end of file diff --git a/peng_quad/fn.log_mesh.html b/peng_quad/fn.log_mesh.html new file mode 100644 index 00000000..b20975f4 --- /dev/null +++ b/peng_quad/fn.log_mesh.html @@ -0,0 +1,20 @@ +log_mesh in peng_quad - Rust

Function peng_quad::log_mesh

source ·
pub fn log_mesh(
+    rec: &RecordingStream,
+    division: usize,
+    spacing: f32,
+) -> Result<(), SimulationError>
Expand description

log mesh data to the rerun recording stream

+

§Arguments

+
    +
  • rec - The rerun::RecordingStream instance
  • +
  • division - The number of divisions in the mesh
  • +
  • spacing - The spacing between divisions
  • +
+

§Errors

+
    +
  • If the data cannot be logged to the recording stream
  • +
+

§Example

+
use peng_quad::log_mesh;
+let rec = rerun::RecordingStreamBuilder::new("log.rerun").connect().unwrap();
+log_mesh(&rec, 10, 0.1).unwrap();
+
\ No newline at end of file diff --git a/peng_quad/fn.log_trajectory.html b/peng_quad/fn.log_trajectory.html new file mode 100644 index 00000000..bcf62ac9 --- /dev/null +++ b/peng_quad/fn.log_trajectory.html @@ -0,0 +1,21 @@ +log_trajectory in peng_quad - Rust

Function peng_quad::log_trajectory

source ·
pub fn log_trajectory(
+    rec: &RecordingStream,
+    trajectory: &Trajectory,
+) -> Result<(), SimulationError>
Expand description

log trajectory data to the rerun recording stream

+

§Arguments

+
    +
  • rec - The rerun::RecordingStream instance
  • +
  • trajectory - The Trajectory instance
  • +
+

§Errors

+
    +
  • If the data cannot be logged to the recording stream
  • +
+

§Example

+
use peng_quad::{Trajectory, log_trajectory};
+use nalgebra::Vector3;
+let rec = rerun::RecordingStreamBuilder::new("log.rerun").connect().unwrap();
+let mut trajectory = Trajectory::new(nalgebra::Vector3::new(0.0, 0.0, 0.0));
+trajectory.add_point(nalgebra::Vector3::new(1.0, 0.0, 0.0));
+log_trajectory(&rec, &trajectory).unwrap();
+
\ No newline at end of file diff --git a/peng_quad/fn.parse_f32.html b/peng_quad/fn.parse_f32.html new file mode 100644 index 00000000..f77e7274 --- /dev/null +++ b/peng_quad/fn.parse_f32.html @@ -0,0 +1,20 @@ +parse_f32 in peng_quad - Rust

Function peng_quad::parse_f32

source ·
pub fn parse_f32(value: &Value, key: &str) -> Result<f32, SimulationError>
Expand description

Helper function to parse f32 from YAML

+

§Arguments

+
    +
  • value - YAML value
  • +
  • key - key to parse
  • +
+

§Returns

+
    +
  • f32 - parsed value
  • +
+

§Errors

+
    +
  • SimulationError - if the value is not a valid f32
  • +
+

§Example

+
use peng_quad::{parse_f32, SimulationError};
+let value = serde_yaml::from_str("key: 1.0").unwrap();
+let result = parse_f32(&value, "key").unwrap();
+assert_eq!(result, 1.0);
+
\ No newline at end of file diff --git a/peng_quad/fn.parse_vector3.html b/peng_quad/fn.parse_vector3.html new file mode 100644 index 00000000..1a334c52 --- /dev/null +++ b/peng_quad/fn.parse_vector3.html @@ -0,0 +1,23 @@ +parse_vector3 in peng_quad - Rust

Function peng_quad::parse_vector3

source ·
pub fn parse_vector3(
+    value: &Value,
+    key: &str,
+) -> Result<Vector3<f32>, SimulationError>
Expand description

Helper function to parse Vector3 from YAML

+

§Arguments

+
    +
  • value - YAML value
  • +
  • key - key to parse
  • +
+

§Returns

+
    +
  • Vector3<f32> - parsed vector
  • +
+

§Errors

+
    +
  • SimulationError - if the value is not a valid vector
  • +
+

§Example

+
use nalgebra::Vector3;
+use peng_quad::{parse_vector3, SimulationError};
+let value = serde_yaml::from_str("test: [1.0, 2.0, 3.0]").unwrap();
+assert_eq!(parse_vector3(&value, "test").unwrap(), Vector3::new(1.0, 2.0, 3.0));
+
\ No newline at end of file diff --git a/peng_quad/fn.pinhole_depth.html b/peng_quad/fn.pinhole_depth.html new file mode 100644 index 00000000..7905a4ac --- /dev/null +++ b/peng_quad/fn.pinhole_depth.html @@ -0,0 +1,35 @@ +pinhole_depth in peng_quad - Rust

Function peng_quad::pinhole_depth

source ·
pub fn pinhole_depth(
+    rec: &RecordingStream,
+    width: usize,
+    height: usize,
+    fov: f32,
+    cam_position: Vector3<f32>,
+    cam_orientation: UnitQuaternion<f32>,
+    cam_transform: [f32; 9],
+    depth_image: &[f32],
+) -> Result<(), SimulationError>
Expand description

creates pinhole camera

+

§Arguments

+
    +
  • rec - The rerun::RecordingStream instance
  • +
  • width - The width component of the camera resolution
  • +
  • height - The height component of the camera resolution
  • +
  • fov - The fov of the camera
  • +
  • cam_position - The position vector of the camera (aligns with the quad)
  • +
  • cam_orientation - The orientation quaternion of quad
  • +
  • cam_transform - The transform matrix between quad and camera alignment
  • +
  • depth_image - The depth image data
  • +
+

§Errors

+
    +
  • If the data cannot be logged to the recording stream
  • +
+

§Example

+
use peng_quad::pinhole_depth;
+use nalgebra::{Vector3, UnitQuaternion};
+let rec = rerun::RecordingStreamBuilder::new("log.rerun").connect().unwrap();
+let depth_image = vec![ 0.0f32 ; 640 * 480];
+let cam_position = Vector3::new(0.0,0.0,0.0);
+let cam_orientation = UnitQuaternion::identity();
+let cam_transform = [0.0, 0.0, 1.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0];
+pinhole_depth(&rec, 128usize, 96usize, 90.0, cam_position, cam_orientation, cam_transform, &depth_image).unwrap();
+
\ No newline at end of file diff --git a/peng_quad/fn.update_planner.html b/peng_quad/fn.update_planner.html new file mode 100644 index 00000000..a3e20608 --- /dev/null +++ b/peng_quad/fn.update_planner.html @@ -0,0 +1,48 @@ +update_planner in peng_quad - Rust

Function peng_quad::update_planner

source ·
pub fn update_planner(
+    planner_manager: &mut PlannerManager,
+    step: usize,
+    time: f32,
+    simulation_frequency: usize,
+    quad: &Quadrotor,
+    obstacles: &[Obstacle],
+    planner_config: &[PlannerStepConfig],
+) -> Result<(), SimulationError>
Expand description

Updates the planner based on the current simulation step and configuration

+

§Arguments

+
    +
  • planner_manager - The PlannerManager instance to update
  • +
  • step - The current simulation step in ms unit
  • +
  • time - The current simulation time
  • +
  • `simulation_frequency’ - The simulation frequency in Hz
  • +
  • quad - The Quadrotor instance
  • +
  • obstacles - The current obstacles in the simulation
  • +
  • planner_config - The planner configuration
  • +
+

§Errors

+
    +
  • If the planner could not be created
  • +
+

§Example

+
use peng_quad::{PlannerManager, Quadrotor, Obstacle, PlannerStepConfig, update_planner};
+use nalgebra::Vector3;
+let simulation_frequency = 1000;
+let initial_position = Vector3::new(0.0, 0.0, 0.0);
+let initial_yaw = 0.0;
+let mut planner_manager = PlannerManager::new(initial_position, initial_yaw);
+let step = 0;
+let time = 0.0;
+let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+let obstacles = vec![Obstacle::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 1.0)];
+let planner_config = vec![PlannerStepConfig {
+    step: 0,
+    planner_type: "MinimumJerkLine".to_string(),
+    params:
+       serde_yaml::from_str(r#"
+       end_position: [0.0, 0.0, 1.0]
+       end_yaw: 0.0
+       duration: 2.0
+       "#).unwrap(),
+}];
+update_planner(&mut planner_manager, step, time, simulation_frequency, &quadrotor, &obstacles, &planner_config).unwrap();
+
\ No newline at end of file diff --git a/peng_quad/index.html b/peng_quad/index.html new file mode 100644 index 00000000..20c4b1cc --- /dev/null +++ b/peng_quad/index.html @@ -0,0 +1,24 @@ +peng_quad - Rust

Crate peng_quad

source ·
Expand description

§Quadrotor Simulation

+

This crate provides a comprehensive simulation environment for quadrotor drones. +It includes models for quadrotor dynamics, IMU simulation, various trajectory planners, +and a PID controller for position and attitude control.

+

§Features

+
    +
  • Realistic quadrotor dynamics simulation
  • +
  • IMU sensor simulation with configurable noise parameters
  • +
  • Multiple trajectory planners including hover, minimum jerk, Lissajous curves, and circular paths
  • +
  • PID controller for position and attitude control
  • +
  • Integration with the rerun crate for visualization
  • +
+

§Example

+
use nalgebra::Vector3;
+use peng_quad::{Quadrotor, SimulationError};
+let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix);
+

Modules§

  • Configuration module +This module contains the configuration for the simulation, quadrotor, PID controller, IMU, maze, camera, mesh, and planner schedule. +The configuration is loaded from a YAML file using the serde library. +The configuration is then used to initialize the simulation, quadrotor, PID controller, IMU, maze, camera, mesh, and planner schedule.

Structs§

  • Represents a camera in the simulation which is used to render the depth of the scene
  • Planner for circular trajectories
  • Planner for hovering at a fixed position
  • Represents an Inertial Measurement Unit (IMU) with bias and noise characteristics
  • Planner for landing maneuvers
  • Planner for Lissajous curve trajectories
  • Represents a maze in the simulation
  • Planner for minimum jerk trajectories along a straight line
  • Waypoint planner that generates a minimum snap trajectory between waypoints
  • Represents an obstacle in the simulation
  • Obstacle avoidance planner that uses a potential field approach to avoid obstacles +The planner calculates a repulsive force for each obstacle and an attractive force towards the goal +The resulting force is then used to calculate the desired position and velocity
  • PID controller for quadrotor position and attitude control
  • Manages different trajectory planners and switches between them
  • Represents a step in the planner schedule.
  • Represents a quadrotor with its physical properties and state
  • A struct to hold trajectory data

Enums§

  • Enum representing different types of trajectory planners
  • Represents errors that can occur during simulation

Traits§

  • Trait defining the interface for trajectory planners

Functions§

\ No newline at end of file diff --git a/peng_quad/sidebar-items.js b/peng_quad/sidebar-items.js new file mode 100644 index 00000000..4fe28ac0 --- /dev/null +++ b/peng_quad/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["PlannerType","SimulationError"],"fn":["color_map_fn","create_planner","log_data","log_depth_image","log_maze_obstacles","log_maze_tube","log_mesh","log_trajectory","parse_f32","parse_vector3","pinhole_depth","update_planner"],"mod":["config"],"struct":["Camera","CirclePlanner","HoverPlanner","Imu","LandingPlanner","LissajousPlanner","Maze","MinimumJerkLinePlanner","MinimumSnapWaypointPlanner","Obstacle","ObstacleAvoidancePlanner","PIDController","PlannerManager","PlannerStepConfig","Quadrotor","Trajectory"],"trait":["Planner"]}; \ No newline at end of file diff --git a/peng_quad/struct.Camera.html b/peng_quad/struct.Camera.html new file mode 100644 index 00000000..3f3a6b16 --- /dev/null +++ b/peng_quad/struct.Camera.html @@ -0,0 +1,133 @@ +Camera in peng_quad - Rust

Struct peng_quad::Camera

source ·
pub struct Camera {
+    pub resolution: (usize, usize),
+    pub fov: f32,
+    pub near: f32,
+    pub far: f32,
+    pub aspect_ratio: f32,
+    pub ray_directions: Vec<Vector3<f32>>,
+}
Expand description

Represents a camera in the simulation which is used to render the depth of the scene

+

§Example

+
use peng_quad::Camera;
+let camera = Camera::new((800, 600), 60.0, 0.1, 100.0);
+

Fields§

§resolution: (usize, usize)

The resolution of the camera

+
§fov: f32

The field of view of the camera

+
§near: f32

The near clipping plane of the camera

+
§far: f32

The far clipping plane of the camera

+
§aspect_ratio: f32

The aspect ratio of the camera

+
§ray_directions: Vec<Vector3<f32>>

The ray directions of each pixel in the camera

+

Implementations§

source§

impl Camera

Implementation of the camera

+
source

pub fn new(resolution: (usize, usize), fov: f32, near: f32, far: f32) -> Self

Creates a new camera with the given resolution, field of view, near and far clipping planes

+
§Arguments
+
    +
  • resolution - The resolution of the camera
  • +
  • fov - The field of view of the camera
  • +
  • near - The near clipping plane of the camera
  • +
  • far - The far clipping plane of the camera
  • +
+
§Returns
+
    +
  • The new camera instance
  • +
+
§Example
+
use peng_quad::Camera;
+let camera = Camera::new((800, 600), 60.0, 0.1, 100.0);
+
source

pub fn render_depth( + &self, + quad_position: &Vector3<f32>, + quad_orientation: &UnitQuaternion<f32>, + maze: &Maze, + depth_buffer: &mut Vec<f32>, + use_multi_threading: bool, +) -> Result<(), SimulationError>

Renders the depth of the scene from the perspective of the quadrotor

+
§Arguments
+
    +
  • quad_position - The position of the quadrotor
  • +
  • quad_orientation - The orientation of the quadrotor
  • +
  • maze - The maze in the scene
  • +
  • depth_buffer - The depth buffer to store the depth values
  • +
+
§Errors
+
    +
  • If the depth buffer is not large enough to store the depth values
  • +
+
§Example
+
use peng_quad::{Camera, Maze};
+use nalgebra::{Vector3, UnitQuaternion};
+let camera = Camera::new((800, 600), 60.0, 0.1, 100.0);
+let quad_position = Vector3::new(0.0, 0.0, 0.0);
+let quad_orientation = UnitQuaternion::identity();
+let mut maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+let mut depth_buffer = vec![0.0; 800 * 600];
+let use_multithreading = true;
+camera.render_depth(&quad_position, &quad_orientation, &maze, &mut depth_buffer, use_multithreading);
+
source

pub fn ray_cast( + &self, + origin: &Vector3<f32>, + rotation_world_to_camera: &Matrix3<f32>, + direction: &Vector3<f32>, + maze: &Maze, +) -> Result<f32, SimulationError>

Casts a ray from the camera origin in the given direction

+
§Arguments
+
    +
  • origin - The origin of the ray
  • +
  • rotation_world_to_camera - The rotation matrix from world to camera coordinates
  • +
  • direction - The direction of the ray
  • +
  • maze - The maze in the scene
  • +
+
§Returns
+
    +
  • The distance to the closest obstacle hit by the ray
  • +
+
§Errors
+
    +
  • If the ray does not hit any obstacles
  • +
+
§Example
+
use peng_quad::{Camera, Maze};
+use nalgebra::{Vector3, Matrix3};
+let camera = Camera::new((800, 600), 60.0, 0.1, 100.0);
+let origin = Vector3::new(0.0, 0.0, 0.0);
+let rotation_world_to_camera = Matrix3::identity();
+let direction = Vector3::new(1.0, 0.0, 0.0);
+let mut maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+let distance = camera.ray_cast(&origin, &rotation_world_to_camera, &direction, &maze);
+

Auto Trait Implementations§

§

impl Freeze for Camera

§

impl RefUnwindSafe for Camera

§

impl Send for Camera

§

impl Sync for Camera

§

impl Unpin for Camera

§

impl UnwindSafe for Camera

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.CirclePlanner.html b/peng_quad/struct.CirclePlanner.html new file mode 100644 index 00000000..aefaa44f --- /dev/null +++ b/peng_quad/struct.CirclePlanner.html @@ -0,0 +1,84 @@ +CirclePlanner in peng_quad - Rust

Struct peng_quad::CirclePlanner

source ·
pub struct CirclePlanner {
+    pub center: Vector3<f32>,
+    pub radius: f32,
+    pub angular_velocity: f32,
+    pub start_position: Vector3<f32>,
+    pub start_time: f32,
+    pub duration: f32,
+    pub start_yaw: f32,
+    pub end_yaw: f32,
+    pub ramp_time: f32,
+}
Expand description

Planner for circular trajectories

+

§Example

+
use nalgebra::Vector3;
+use peng_quad::CirclePlanner;
+let circle_planner = CirclePlanner {
+    center: Vector3::new(1.0, 1.0, 1.0),
+    radius: 1.0,
+    angular_velocity: 1.0,
+    start_position: Vector3::new(0.0, 0.0, 0.0),
+    start_time: 0.0,
+    duration: 1.0,
+    start_yaw: 0.0,
+    end_yaw: 0.0,
+    ramp_time: 0.1,
+};
+

Fields§

§center: Vector3<f32>

Center of the circular trajectory

+
§radius: f32

Radius of the circular trajectory

+
§angular_velocity: f32

Angular velocity of the circular motion

+
§start_position: Vector3<f32>

Starting position of the trajectory

+
§start_time: f32

Start time of the trajectory

+
§duration: f32

Duration of the trajectory

+
§start_yaw: f32

Starting yaw angle

+
§end_yaw: f32

Ending yaw angle

+
§ramp_time: f32

Ramp-up time for smooth transitions

+

Trait Implementations§

source§

impl Planner for CirclePlanner

Implementation of the Planner trait for CirclePlanner

+
source§

fn plan( + &self, + _current_position: Vector3<f32>, + _current_velocity: Vector3<f32>, + time: f32, +) -> (Vector3<f32>, Vector3<f32>, f32)

Plans the trajectory based on the current state and time Read more
source§

fn is_finished( + &self, + _current_position: Vector3<f32>, + time: f32, +) -> Result<bool, SimulationError>

Checks if the current trajectory is finished Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.HoverPlanner.html b/peng_quad/struct.HoverPlanner.html new file mode 100644 index 00000000..10f7894b --- /dev/null +++ b/peng_quad/struct.HoverPlanner.html @@ -0,0 +1,63 @@ +HoverPlanner in peng_quad - Rust

Struct peng_quad::HoverPlanner

source ·
pub struct HoverPlanner {
+    pub target_position: Vector3<f32>,
+    pub target_yaw: f32,
+}
Expand description

Planner for hovering at a fixed position

+

§Example

+
use nalgebra::Vector3;
+use peng_quad::HoverPlanner;
+let hover_planner = HoverPlanner {
+    target_position: Vector3::new(0.0, 0.0, 0.0),
+    target_yaw: 0.0,
+};
+

Fields§

§target_position: Vector3<f32>

Target position for hovering

+
§target_yaw: f32

Target yaw angle for hovering

+

Trait Implementations§

source§

impl Planner for HoverPlanner

Implementation of the Planner trait for the HoverPlanner

+
source§

fn plan( + &self, + _current_position: Vector3<f32>, + _current_velocity: Vector3<f32>, + _time: f32, +) -> (Vector3<f32>, Vector3<f32>, f32)

Plans the trajectory based on the current state and time Read more
source§

fn is_finished( + &self, + _current_position: Vector3<f32>, + _time: f32, +) -> Result<bool, SimulationError>

Checks if the current trajectory is finished Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.Imu.html b/peng_quad/struct.Imu.html new file mode 100644 index 00000000..233f639a --- /dev/null +++ b/peng_quad/struct.Imu.html @@ -0,0 +1,125 @@ +Imu in peng_quad - Rust

Struct peng_quad::Imu

source ·
pub struct Imu {
+    pub accel_bias: Vector3<f32>,
+    pub gyro_bias: Vector3<f32>,
+    pub accel_noise_std: f32,
+    pub gyro_noise_std: f32,
+    pub accel_bias_std: f32,
+    pub gyro_bias_std: f32,
+    /* private fields */
+}
Expand description

Represents an Inertial Measurement Unit (IMU) with bias and noise characteristics

+

§Example

+
use nalgebra::Vector3;
+use peng_quad::Imu;
+let accel_noise_std = 0.0003;
+let gyro_noise_std = 0.02;
+let accel_bias_std = 0.0001;
+let gyro_bias_std = 0.001;
+let imu = Imu::new(accel_noise_std, gyro_noise_std, accel_bias_std, gyro_bias_std);
+

Fields§

§accel_bias: Vector3<f32>

Accelerometer bias

+
§gyro_bias: Vector3<f32>

Gyroscope bias

+
§accel_noise_std: f32

Standard deviation of accelerometer noise

+
§gyro_noise_std: f32

Standard deviation of gyroscope noise

+
§accel_bias_std: f32

Standard deviation of accelerometer bias drift

+
§gyro_bias_std: f32

Standard deviation of gyroscope bias drift

+

Implementations§

source§

impl Imu

Implements the IMU

+
source

pub fn new( + accel_noise_std: f32, + gyro_noise_std: f32, + accel_bias_std: f32, + gyro_bias_std: f32, +) -> Result<Self, SimulationError>

Creates a new IMU with default parameters

+
§Arguments
+
    +
  • accel_noise_std - Standard deviation of accelerometer noise
  • +
  • gyro_noise_std - Standard deviation of gyroscope noise
  • +
  • accel_bias_std - Standard deviation of accelerometer bias drift
  • +
  • gyro_bias_std - Standard deviation of gyroscope bias drift
  • +
+
§Returns
+
    +
  • A new Imu instance
  • +
+
§Example
+
use peng_quad::Imu;
+
+let imu = Imu::new(0.01, 0.01, 0.01, 0.01);
+
source

pub fn update(&mut self, dt: f32) -> Result<(), SimulationError>

Updates the IMU biases over time

+
§Arguments
+
    +
  • dt - Time step for the update
  • +
+
§Errors
+
    +
  • Returns a SimulationError if the bias drift cannot be calculated
  • +
+
§Example
+
use peng_quad::Imu;
+
+let mut imu = Imu::new(0.01, 0.01, 0.01, 0.01).unwrap();
+imu.update(0.01).unwrap();
+
source

pub fn read( + &mut self, + true_acceleration: Vector3<f32>, + true_angular_velocity: Vector3<f32>, +) -> Result<(Vector3<f32>, Vector3<f32>), SimulationError>

Simulates IMU readings with added bias and noise

+
§Arguments
+
    +
  • true_acceleration - The true acceleration vector
  • +
  • true_angular_velocity - The true angular velocity vector
  • +
+
§Returns
+
    +
  • A tuple containing the measured acceleration and angular velocity
  • +
+
§Errors
+
    +
  • Returns a SimulationError if the IMU readings cannot be calculated
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::Imu;
+
+let mut imu = Imu::new(0.01, 0.01, 0.01, 0.01).unwrap();
+let true_acceleration = Vector3::new(0.0, 0.0, 9.81);
+let true_angular_velocity = Vector3::new(0.0, 0.0, 0.0);
+let (measured_acceleration, measured_ang_velocity) = imu.read(true_acceleration, true_angular_velocity).unwrap();
+

Auto Trait Implementations§

§

impl Freeze for Imu

§

impl RefUnwindSafe for Imu

§

impl Send for Imu

§

impl Sync for Imu

§

impl Unpin for Imu

§

impl UnwindSafe for Imu

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.LandingPlanner.html b/peng_quad/struct.LandingPlanner.html new file mode 100644 index 00000000..52e36dab --- /dev/null +++ b/peng_quad/struct.LandingPlanner.html @@ -0,0 +1,69 @@ +LandingPlanner in peng_quad - Rust

Struct peng_quad::LandingPlanner

source ·
pub struct LandingPlanner {
+    pub start_position: Vector3<f32>,
+    pub start_time: f32,
+    pub duration: f32,
+    pub start_yaw: f32,
+}
Expand description

Planner for landing maneuvers

+

§Example

+
use nalgebra::Vector3;
+use peng_quad::LandingPlanner;
+let landing_planner = LandingPlanner {
+   start_position: Vector3::new(0.0, 0.0, 1.0),
+    start_time: 0.0,
+    duration: 1.0,
+    start_yaw: 0.0,
+};
+

Fields§

§start_position: Vector3<f32>

Starting position of the landing maneuver

+
§start_time: f32

Start time of the landing maneuver

+
§duration: f32

Duration of the landing maneuver

+
§start_yaw: f32

Starting yaw angle

+

Trait Implementations§

source§

impl Planner for LandingPlanner

Implementation of the Planner trait for LandingPlanner

+
source§

fn plan( + &self, + _current_position: Vector3<f32>, + _current_velocity: Vector3<f32>, + time: f32, +) -> (Vector3<f32>, Vector3<f32>, f32)

Plans the trajectory based on the current state and time Read more
source§

fn is_finished( + &self, + current_position: Vector3<f32>, + time: f32, +) -> Result<bool, SimulationError>

Checks if the current trajectory is finished Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.LissajousPlanner.html b/peng_quad/struct.LissajousPlanner.html new file mode 100644 index 00000000..7f8f9e24 --- /dev/null +++ b/peng_quad/struct.LissajousPlanner.html @@ -0,0 +1,87 @@ +LissajousPlanner in peng_quad - Rust

Struct peng_quad::LissajousPlanner

source ·
pub struct LissajousPlanner {
+    pub start_position: Vector3<f32>,
+    pub center: Vector3<f32>,
+    pub amplitude: Vector3<f32>,
+    pub frequency: Vector3<f32>,
+    pub phase: Vector3<f32>,
+    pub start_time: f32,
+    pub duration: f32,
+    pub start_yaw: f32,
+    pub end_yaw: f32,
+    pub ramp_time: f32,
+}
Expand description

Planner for Lissajous curve trajectories

+

§Example

+
use nalgebra::Vector3;
+use peng_quad::LissajousPlanner;
+let lissajous_planner = LissajousPlanner {
+    start_position: Vector3::new(0.0, 0.0, 0.0),
+    center: Vector3::new(1.0, 1.0, 1.0),
+    amplitude: Vector3::new(1.0, 1.0, 1.0),
+    frequency: Vector3::new(1.0, 1.0, 1.0),
+    phase: Vector3::new(0.0, 0.0, 0.0),
+    start_time: 0.0,
+    duration: 1.0,
+    start_yaw: 0.0,
+    end_yaw: 0.0,
+    ramp_time: 0.1,
+};
+

Fields§

§start_position: Vector3<f32>

Starting position of the trajectory

+
§center: Vector3<f32>

Center of the Lissajous curve

+
§amplitude: Vector3<f32>

Amplitude of the Lissajous curve

+
§frequency: Vector3<f32>

Frequency of the Lissajous curve

+
§phase: Vector3<f32>

Phase of the Lissajous curve

+
§start_time: f32

Start time of the trajectory

+
§duration: f32

Duration of the trajectory

+
§start_yaw: f32

Starting yaw angle

+
§end_yaw: f32

Ending yaw angle

+
§ramp_time: f32

Ramp-up time for smooth transitions

+

Trait Implementations§

source§

impl Planner for LissajousPlanner

Implementation of the planner trait for Lissajous curve trajectories

+
source§

fn plan( + &self, + _current_position: Vector3<f32>, + _current_velocity: Vector3<f32>, + time: f32, +) -> (Vector3<f32>, Vector3<f32>, f32)

Plans the trajectory based on the current state and time Read more
source§

fn is_finished( + &self, + _current_position: Vector3<f32>, + time: f32, +) -> Result<bool, SimulationError>

Checks if the current trajectory is finished Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.Maze.html b/peng_quad/struct.Maze.html new file mode 100644 index 00000000..c11ac0f3 --- /dev/null +++ b/peng_quad/struct.Maze.html @@ -0,0 +1,101 @@ +Maze in peng_quad - Rust

Struct peng_quad::Maze

source ·
pub struct Maze {
+    pub lower_bounds: [f32; 3],
+    pub upper_bounds: [f32; 3],
+    pub obstacles: Vec<Obstacle>,
+    pub obstacles_velocity_bounds: [f32; 3],
+    pub obstacles_radius_bounds: [f32; 2],
+}
Expand description

Represents a maze in the simulation

+

§Example

+
use peng_quad::{Maze, Obstacle};
+use nalgebra::Vector3;
+let maze = Maze {
+    lower_bounds: [0.0, 0.0, 0.0],
+    upper_bounds: [1.0, 1.0, 1.0],
+    obstacles: vec![Obstacle::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 1.0)],
+    obstacles_velocity_bounds: [0.0, 0.0, 0.0],
+    obstacles_radius_bounds: [0.0, 0.0],
+};
+

Fields§

§lower_bounds: [f32; 3]

The lower bounds of the maze in the x, y, and z directions

+
§upper_bounds: [f32; 3]

The upper bounds of the maze in the x, y, and z directions

+
§obstacles: Vec<Obstacle>

The obstacles in the maze

+
§obstacles_velocity_bounds: [f32; 3]

The bounds of the obstacles’ velocity

+
§obstacles_radius_bounds: [f32; 2]

The bounds of the obstacles’ radius

+

Implementations§

source§

impl Maze

Implementation of the maze

+
source

pub fn new( + lower_bounds: [f32; 3], + upper_bounds: [f32; 3], + num_obstacles: usize, + obstacles_velocity_bounds: [f32; 3], + obstacles_radius_bounds: [f32; 2], +) -> Self

Creates a new maze with the given bounds and number of obstacles

+
§Arguments
+
    +
  • lower_bounds - The lower bounds of the maze
  • +
  • upper_bounds - The upper bounds of the maze
  • +
  • num_obstacles - The number of obstacles in the maze
  • +
+
§Returns
+
    +
  • The new maze instance
  • +
+
§Example
+
use peng_quad::Maze;
+let maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+
source

pub fn generate_obstacles(&mut self, num_obstacles: usize)

Generates the obstacles in the maze

+
§Arguments
+
    +
  • num_obstacles - The number of obstacles to generate
  • +
+
§Example
+
use peng_quad::Maze;
+let mut maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+maze.generate_obstacles(5);
+
source

pub fn update_obstacles(&mut self, dt: f32)

Updates the obstacles in the maze, if an obstacle hits a boundary, it bounces off

+
§Arguments
+
    +
  • dt - The time step
  • +
+
§Example
+
use peng_quad::Maze;
+let mut maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+maze.update_obstacles(0.1);
+

Auto Trait Implementations§

§

impl Freeze for Maze

§

impl RefUnwindSafe for Maze

§

impl Send for Maze

§

impl Sync for Maze

§

impl Unpin for Maze

§

impl UnwindSafe for Maze

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.MinimumJerkLinePlanner.html b/peng_quad/struct.MinimumJerkLinePlanner.html new file mode 100644 index 00000000..e846b722 --- /dev/null +++ b/peng_quad/struct.MinimumJerkLinePlanner.html @@ -0,0 +1,75 @@ +MinimumJerkLinePlanner in peng_quad - Rust

Struct peng_quad::MinimumJerkLinePlanner

source ·
pub struct MinimumJerkLinePlanner {
+    pub start_position: Vector3<f32>,
+    pub end_position: Vector3<f32>,
+    pub start_yaw: f32,
+    pub end_yaw: f32,
+    pub start_time: f32,
+    pub duration: f32,
+}
Expand description

Planner for minimum jerk trajectories along a straight line

+

§Example

+
use nalgebra::Vector3;
+use peng_quad::MinimumJerkLinePlanner;
+let minimum_jerk_line_planner = MinimumJerkLinePlanner {
+    start_position: Vector3::new(0.0, 0.0, 0.0),
+    end_position: Vector3::new(1.0, 1.0, 1.0),
+    start_yaw: 0.0,
+    end_yaw: 0.0,
+    start_time: 0.0,
+    duration: 1.0,
+};
+

Fields§

§start_position: Vector3<f32>

Starting position of the trajectory

+
§end_position: Vector3<f32>

Ending position of the trajectory

+
§start_yaw: f32

Starting yaw angle

+
§end_yaw: f32

Ending yaw angle

+
§start_time: f32

Start time of the trajectory

+
§duration: f32

Duration of the trajectory

+

Trait Implementations§

source§

impl Planner for MinimumJerkLinePlanner

Implementation of the planner trait for minimum jerk line planner

+
source§

fn plan( + &self, + _current_position: Vector3<f32>, + _current_velocity: Vector3<f32>, + time: f32, +) -> (Vector3<f32>, Vector3<f32>, f32)

Plans the trajectory based on the current state and time Read more
source§

fn is_finished( + &self, + _current_position: Vector3<f32>, + _time: f32, +) -> Result<bool, SimulationError>

Checks if the current trajectory is finished Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.MinimumSnapWaypointPlanner.html b/peng_quad/struct.MinimumSnapWaypointPlanner.html new file mode 100644 index 00000000..a9c2c301 --- /dev/null +++ b/peng_quad/struct.MinimumSnapWaypointPlanner.html @@ -0,0 +1,167 @@ +MinimumSnapWaypointPlanner in peng_quad - Rust

Struct peng_quad::MinimumSnapWaypointPlanner

source ·
pub struct MinimumSnapWaypointPlanner {
+    pub waypoints: Vec<Vector3<f32>>,
+    pub yaws: Vec<f32>,
+    pub times: Vec<f32>,
+    pub coefficients: Vec<Vec<Vector3<f32>>>,
+    pub yaw_coefficients: Vec<Vec<f32>>,
+    pub start_time: f32,
+}
Expand description

Waypoint planner that generates a minimum snap trajectory between waypoints

+

§Example

+
use peng_quad::MinimumSnapWaypointPlanner;
+use nalgebra::Vector3;
+let planner = MinimumSnapWaypointPlanner::new(
+    vec![Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 0.0, 0.0)],
+    vec![0.0, 0.0],
+    vec![1.0],
+    0.0,
+);
+

Fields§

§waypoints: Vec<Vector3<f32>>

List of waypoints

+
§yaws: Vec<f32>

List of yaw angles

+
§times: Vec<f32>

List of segment times to reach each waypoint

+
§coefficients: Vec<Vec<Vector3<f32>>>

Coefficients for the x, y, and z components of the trajectory

+
§yaw_coefficients: Vec<Vec<f32>>

Coefficients for the yaw component of the trajectory

+
§start_time: f32

Start time of the trajectory

+

Implementations§

source§

impl MinimumSnapWaypointPlanner

Implementation of the MinimumSnapWaypointPlanner

+
source

pub fn new( + waypoints: Vec<Vector3<f32>>, + yaws: Vec<f32>, + segment_times: Vec<f32>, + start_time: f32, +) -> Result<Self, SimulationError>

Generate a new minimum snap waypoint planner

+
§Arguments
+
    +
  • waypoints - List of waypoints
  • +
  • yaws - List of yaw angles
  • +
  • segment_times - List of segment times to reach each waypoint
  • +
  • start_time - Start time of the trajectory
  • +
+
§Returns
+
    +
  • A new minimum snap waypoint planner
  • +
+
§Errors
+
    +
  • Returns an error if the number of waypoints, yaws, and segment times do not match
  • +
+
§Example
+
use peng_quad::MinimumSnapWaypointPlanner;
+use nalgebra::Vector3;
+let waypoints = vec![Vector3::zeros(), Vector3::new(1.0, 0.0, 0.0)];
+let yaws = vec![0.0, 0.0];
+let segment_times = vec![1.0];
+let start_time = 0.0;
+let planner = MinimumSnapWaypointPlanner::new(waypoints, yaws, segment_times, start_time);
+
source

pub fn compute_minimum_snap_trajectories( + &mut self, +) -> Result<(), SimulationError>

Compute the coefficients for the minimum snap trajectory, calculated for each segment between waypoints

+
§Errors
+
    +
  • Returns an error if the nalgebra solver fails to solve the linear system
  • +
+
§Example
+
use peng_quad::MinimumSnapWaypointPlanner;
+use nalgebra::Vector3;
+let waypoints = vec![Vector3::zeros(), Vector3::new(1.0, 0.0, 0.0)];
+let yaws = vec![0.0, 0.0];
+let segment_times = vec![1.0];
+let start_time = 0.0;
+let mut planner = MinimumSnapWaypointPlanner::new(waypoints, yaws, segment_times, start_time).unwrap();
+planner.compute_minimum_snap_trajectories();
+
source

pub fn compute_minimum_acceleration_yaw_trajectories( + &mut self, +) -> Result<(), SimulationError>

Compute the coefficients for yaw trajectories +The yaw trajectory is a cubic polynomial and interpolated between waypoints

+
§Errors
+
    +
  • Returns an error if nalgebra fails to solve for the coefficients
  • +
+
§Example
+
use peng_quad::MinimumSnapWaypointPlanner;
+use nalgebra::Vector3;
+let waypoints = vec![Vector3::zeros(), Vector3::new(1.0, 0.0, 0.0)];
+let yaws = vec![0.0, 0.0];
+let segment_times = vec![1.0];
+let start_time = 0.0;
+let mut planner = MinimumSnapWaypointPlanner::new(waypoints, yaws, segment_times, start_time).unwrap();
+planner.compute_minimum_snap_trajectories();
+planner.compute_minimum_acceleration_yaw_trajectories();
+
source

pub fn evaluate_polynomial( + &self, + t: f32, + coeffs: &[Vector3<f32>], + yaw_coeffs: &[f32], +) -> (Vector3<f32>, Vector3<f32>, f32, f32)

Evaluate the trajectory at a given time, returns the position, velocity, yaw, and yaw rate at the given time

+
§Arguments
+
    +
  • t - The time to evaluate the trajectory at
  • +
  • coeffs - The coefficients for the position trajectory
  • +
  • yaw_coeffs - The coefficients for the yaw trajectory
  • +
+
§Returns
+
    +
  • position - The position at the given time (meters)
  • +
  • velocity - The velocity at the given time (meters / second)
  • +
  • yaw - The yaw at the given time (radians)
  • +
  • yaw_rate - The yaw rate at the given time (radians / second)
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::MinimumSnapWaypointPlanner;
+let waypoints = vec![Vector3::zeros(), Vector3::new(1.0, 0.0, 0.0)];
+let yaws = vec![0.0, 0.0];
+let segment_times = vec![1.0];
+let start_time = 0.0;
+let mut planner = MinimumSnapWaypointPlanner::new(waypoints, yaws, segment_times, start_time).unwrap();
+planner.compute_minimum_snap_trajectories();
+planner.compute_minimum_acceleration_yaw_trajectories();
+let (position, velocity, yaw, yaw_rate) = planner.evaluate_polynomial(0.5, &planner.coefficients[0], &planner.yaw_coefficients[0]);
+

Trait Implementations§

source§

impl Planner for MinimumSnapWaypointPlanner

Implement the Planner trait for MinimumSnapWaypointPlanner

+
source§

fn plan( + &self, + _current_position: Vector3<f32>, + _current_velocity: Vector3<f32>, + time: f32, +) -> (Vector3<f32>, Vector3<f32>, f32)

Plans the trajectory based on the current state and time Read more
source§

fn is_finished( + &self, + current_position: Vector3<f32>, + time: f32, +) -> Result<bool, SimulationError>

Checks if the current trajectory is finished Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.Obstacle.html b/peng_quad/struct.Obstacle.html new file mode 100644 index 00000000..07cada86 --- /dev/null +++ b/peng_quad/struct.Obstacle.html @@ -0,0 +1,71 @@ +Obstacle in peng_quad - Rust

Struct peng_quad::Obstacle

source ·
pub struct Obstacle {
+    pub position: Vector3<f32>,
+    pub velocity: Vector3<f32>,
+    pub radius: f32,
+}
Expand description

Represents an obstacle in the simulation

+

§Example

+
use peng_quad::Obstacle;
+use nalgebra::Vector3;
+let obstacle = Obstacle::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 1.0);
+

Fields§

§position: Vector3<f32>

The position of the obstacle

+
§velocity: Vector3<f32>

The velocity of the obstacle

+
§radius: f32

The radius of the obstacle

+

Implementations§

source§

impl Obstacle

Implementation of the Obstacle

+
source

pub fn new(position: Vector3<f32>, velocity: Vector3<f32>, radius: f32) -> Self

Creates a new obstacle with the given position, velocity, and radius

+
§Arguments
+
    +
  • position - The position of the obstacle
  • +
  • velocity - The velocity of the obstacle
  • +
  • radius - The radius of the obstacle
  • +
+
§Returns
+
    +
  • The new obstacle instance
  • +
+
§Example
+
use peng_quad::Obstacle;
+use nalgebra::Vector3;
+let obstacle = Obstacle::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 1.0);
+

Trait Implementations§

source§

impl Clone for Obstacle

source§

fn clone(&self) -> Obstacle

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> DynClone for T
where + T: Clone,

source§

fn __clone_box(&self, _: Private) -> *mut ()

source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.ObstacleAvoidancePlanner.html b/peng_quad/struct.ObstacleAvoidancePlanner.html new file mode 100644 index 00000000..3a75adb3 --- /dev/null +++ b/peng_quad/struct.ObstacleAvoidancePlanner.html @@ -0,0 +1,129 @@ +ObstacleAvoidancePlanner in peng_quad - Rust

Struct peng_quad::ObstacleAvoidancePlanner

source ·
pub struct ObstacleAvoidancePlanner {
+    pub target_position: Vector3<f32>,
+    pub start_time: f32,
+    pub duration: f32,
+    pub start_yaw: f32,
+    pub end_yaw: f32,
+    pub obstacles: Vec<Obstacle>,
+    pub k_att: f32,
+    pub k_rep: f32,
+    pub k_vortex: f32,
+    pub d0: f32,
+    pub d_target: f32,
+    pub max_speed: f32,
+}
Expand description

Obstacle avoidance planner that uses a potential field approach to avoid obstacles +The planner calculates a repulsive force for each obstacle and an attractive force towards the goal +The resulting force is then used to calculate the desired position and velocity

+

§Example

+
use nalgebra::Vector3;
+use peng_quad::{ObstacleAvoidancePlanner, Obstacle};
+let planner = ObstacleAvoidancePlanner {
+    target_position: Vector3::new(0.0, 0.0, 1.0),
+    start_time: 0.0,
+    duration: 10.0,
+    start_yaw: 0.0,
+    end_yaw: 0.0,
+    obstacles: vec![Obstacle {
+        position: Vector3::new(1.0, 0.0, 1.0),
+        velocity: Vector3::new(0.0, 0.0, 0.0),
+        radius: 0.5,
+    }],
+    k_att: 1.0,
+    k_rep: 1.0,
+    k_vortex: 1.0,
+    d0: 1.0,
+    d_target: 1.0,
+    max_speed: 1.0,
+};
+

Fields§

§target_position: Vector3<f32>

Target position of the planner

+
§start_time: f32

Start time of the planner

+
§duration: f32

Duration of the planner

+
§start_yaw: f32

Starting yaw angle

+
§end_yaw: f32

Ending yaw angle

+
§obstacles: Vec<Obstacle>

List of obstacles

+
§k_att: f32

Attractive force gain

+
§k_rep: f32

Repulsive force gain

+
§k_vortex: f32

Vortex force gain

+
§d0: f32

Influence distance of obstacles

+
§d_target: f32

Influence distance of target

+
§max_speed: f32

Maximum speed of the quadrotor

+

Implementations§

source§

impl ObstacleAvoidancePlanner

Implementation of the ObstacleAvoidancePlanner

+
source

pub fn smooth_attractive_force(&self, distance: f32) -> f32

A smooth attractive force function that transitions from linear to exponential decay +When the distance to the target is less than the target distance, the force is linear +When the distance is greater, the force decays exponentially

+
§Arguments
+
    +
  • distance - The distance to the target
  • +
+
§Returns
+
    +
  • The attractive force
  • +
+
§Example
+
use peng_quad::ObstacleAvoidancePlanner;
+let planner = ObstacleAvoidancePlanner {
+   target_position: nalgebra::Vector3::new(0.0, 0.0, 1.0),
+    start_time: 0.0,
+    duration: 10.0,
+    start_yaw: 0.0,
+    end_yaw: 0.0,
+    obstacles: vec![],
+    k_att: 1.0,
+    k_rep: 1.0,
+    k_vortex: 1.0,
+    d0: 1.0,
+    d_target: 1.0,
+    max_speed: 1.0,
+};
+let distance = 1.0;
+let force = planner.smooth_attractive_force(distance);
+

Trait Implementations§

source§

impl Planner for ObstacleAvoidancePlanner

Implementation of the Planner trait for ObstacleAvoidancePlanner

+
source§

fn plan( + &self, + current_position: Vector3<f32>, + current_velocity: Vector3<f32>, + time: f32, +) -> (Vector3<f32>, Vector3<f32>, f32)

Plans the trajectory based on the current state and time Read more
source§

fn is_finished( + &self, + current_position: Vector3<f32>, + time: f32, +) -> Result<bool, SimulationError>

Checks if the current trajectory is finished Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.PIDController.html b/peng_quad/struct.PIDController.html new file mode 100644 index 00000000..95fa1325 --- /dev/null +++ b/peng_quad/struct.PIDController.html @@ -0,0 +1,183 @@ +PIDController in peng_quad - Rust

Struct peng_quad::PIDController

source ·
pub struct PIDController {
+    pub kpid_pos: [Vector3<f32>; 3],
+    pub kpid_att: [Vector3<f32>; 3],
+    pub integral_pos_error: Vector3<f32>,
+    pub integral_att_error: Vector3<f32>,
+    pub max_integral_pos: Vector3<f32>,
+    pub max_integral_att: Vector3<f32>,
+    pub mass: f32,
+    pub gravity: f32,
+}
Expand description

PID controller for quadrotor position and attitude control

+

§Example

+
use nalgebra::Vector3;
+use peng_quad::PIDController;
+let kpid_pos = [
+    [1.0, 1.0, 1.0],
+    [0.1, 0.1, 0.1],
+    [0.01, 0.01, 0.01],
+];
+let kpid_att = [
+    [1.0, 1.0, 1.0],
+    [0.1, 0.1, 0.1],
+    [0.01, 0.01, 0.01],
+];
+let max_integral_pos = [1.0, 1.0, 1.0];
+let max_integral_att = [1.0, 1.0, 1.0];
+let mass = 1.0;
+let gravity = 9.81;
+let pid_controller = PIDController::new(kpid_pos, kpid_att, max_integral_pos, max_integral_att, mass, gravity);
+

Fields§

§kpid_pos: [Vector3<f32>; 3]

PID gain for position control including proportional, derivative, and integral gains

+
§kpid_att: [Vector3<f32>; 3]

PID gain for attitude control including proportional, derivative, and integral gains

+
§integral_pos_error: Vector3<f32>

Accumulated integral error for position

+
§integral_att_error: Vector3<f32>

Accumulated integral error for attitude

+
§max_integral_pos: Vector3<f32>

Maximum allowed integral error for position

+
§max_integral_att: Vector3<f32>

Maximum allowed integral error for attitude

+
§mass: f32

Mass of the quadrotor

+
§gravity: f32

Gravity constant

+

Implementations§

source§

impl PIDController

Implementation of PIDController

+
source

pub fn new( + _kpid_pos: [[f32; 3]; 3], + _kpid_att: [[f32; 3]; 3], + _max_integral_pos: [f32; 3], + _max_integral_att: [f32; 3], + _mass: f32, + _gravity: f32, +) -> Self

Creates a new PIDController with default gains +gains are in the order of proportional, derivative, and integral

+
§Arguments
+
    +
  • _kpid_pos - PID gains for position control
  • +
  • _kpid_att - PID gains for attitude control
  • +
  • _max_integral_pos - Maximum allowed integral error for position
  • +
  • _max_integral_att - Maximum allowed integral error for attitude
  • +
+
§Returns
+
    +
  • A new PIDController instance
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::PIDController;
+let kpid_pos = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
+let kpid_att = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
+let max_integral_pos = [1.0, 1.0, 1.0];
+let max_integral_att = [1.0, 1.0, 1.0];
+let mass = 1.0;
+let gravity = 9.81;
+let pid = PIDController::new(kpid_pos, kpid_att, max_integral_pos, max_integral_att, mass, gravity);
+
source

pub fn compute_attitude_control( + &mut self, + desired_orientation: &UnitQuaternion<f32>, + current_orientation: &UnitQuaternion<f32>, + current_angular_velocity: &Vector3<f32>, + dt: f32, +) -> Vector3<f32>

Computes attitude control torques

+
§Arguments
+
    +
  • desired_orientation - The desired orientation quaternion
  • +
  • current_orientation - The current orientation quaternion
  • +
  • current_angular_velocity - The current angular velocity
  • +
  • dt - Time step
  • +
+
§Returns
+
    +
  • The computed attitude control torques
  • +
+
§Example
+
use nalgebra::{UnitQuaternion, Vector3};
+use peng_quad::PIDController;
+
+let kpid_pos = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
+let kpid_att = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
+let max_integral_pos = [1.0, 1.0, 1.0];
+let max_integral_att = [1.0, 1.0, 1.0];
+let mass = 1.0;
+let gravity = 9.81;
+let mut pid = PIDController::new(kpid_pos, kpid_att, max_integral_pos, max_integral_att, mass, gravity);
+let desired_orientation = UnitQuaternion::identity();
+let current_orientation = UnitQuaternion::identity();
+let current_angular_velocity = Vector3::zeros();
+let dt = 0.01;
+let control_torques = pid.compute_attitude_control(&desired_orientation, &current_orientation, &current_angular_velocity, dt);
+
source

pub fn compute_position_control( + &mut self, + desired_position: &Vector3<f32>, + desired_velocity: &Vector3<f32>, + desired_yaw: f32, + current_position: &Vector3<f32>, + current_velocity: &Vector3<f32>, + dt: f32, +) -> (f32, UnitQuaternion<f32>)

Computes position control thrust and desired orientation

+
§Arguments
+
    +
  • desired_position - The desired position
  • +
  • desired_velocity - The desired velocity
  • +
  • desired_yaw - The desired yaw angle
  • +
  • current_position - The current position
  • +
  • current_velocity - The current velocity
  • +
  • dt - Time step
  • +
  • mass - Mass of the quadrotor
  • +
  • gravity - Gravitational acceleration
  • +
+
§Returns
+
    +
  • A tuple containing the computed thrust and desired orientation quaternion
  • +
+
§Example
+
use nalgebra::{UnitQuaternion, Vector3};
+use peng_quad::PIDController;
+
+let kpid_pos = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
+let kpid_att = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
+let max_integral_pos = [1.0, 1.0, 1.0];
+let max_integral_att = [1.0, 1.0, 1.0];
+let mass = 1.0;
+let gravity = 9.81;
+let mut pid = PIDController::new(kpid_pos, kpid_att, max_integral_pos, max_integral_att, mass, gravity);
+let desired_position = Vector3::new(0.0, 0.0, 1.0);
+let desired_velocity = Vector3::zeros();
+let desired_yaw = 0.0;
+let current_position = Vector3::zeros();
+let current_velocity = Vector3::zeros();
+let dt = 0.01;
+let (thrust, desired_orientation) = pid.compute_position_control(&desired_position, &desired_velocity, desired_yaw, &current_position, &current_velocity, dt);
+

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.PlannerManager.html b/peng_quad/struct.PlannerManager.html new file mode 100644 index 00000000..5624290d --- /dev/null +++ b/peng_quad/struct.PlannerManager.html @@ -0,0 +1,135 @@ +PlannerManager in peng_quad - Rust

Struct peng_quad::PlannerManager

source ·
pub struct PlannerManager {
+    pub current_planner: PlannerType,
+}
Expand description

Manages different trajectory planners and switches between them

+

§Example

+
use nalgebra::Vector3;
+use peng_quad::PlannerManager;
+let initial_position = Vector3::new(0.0, 0.0, 1.0);
+let initial_yaw = 0.0;
+let planner_manager = PlannerManager::new(initial_position, initial_yaw);
+

Fields§

§current_planner: PlannerType

The current planner

+

Implementations§

source§

impl PlannerManager

Implementation of the PlannerManager

+
source

pub fn new(initial_position: Vector3<f32>, initial_yaw: f32) -> Self

Creates a new PlannerManager with an initial hover planner

+
§Arguments
+
    +
  • initial_position - The initial position for hovering
  • +
  • initial_yaw - The initial yaw angle for hovering
  • +
+
§Returns
+
    +
  • A new PlannerManager instance
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::PlannerManager;
+let initial_position = Vector3::new(0.0, 0.0, 1.0);
+let initial_yaw = 0.0;
+let planner_manager = PlannerManager::new(initial_position, initial_yaw);
+
source

pub fn set_planner(&mut self, new_planner: PlannerType)

Sets a new planner

+
§Arguments
+
    +
  • new_planner - The new planner to be set
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::{PlannerManager, CirclePlanner, PlannerType};
+let initial_position = Vector3::new(0.0, 0.0, 1.0);
+let initial_yaw = 0.0;
+let mut planner_manager = PlannerManager::new(initial_position, initial_yaw);
+let new_planner = CirclePlanner {
+    center: Vector3::new(0.0, 0.0, 1.0),
+    radius: 1.0,
+    angular_velocity: 1.0,
+    start_yaw: 0.0,
+    end_yaw: 0.0,
+    start_time: 0.0,
+    duration: 10.0,
+    ramp_time: 1.0,
+    start_position: Vector3::new(0.0, 0.0, 1.0),
+};
+planner_manager.set_planner(PlannerType::Circle(new_planner));
+
source

pub fn update( + &mut self, + current_position: Vector3<f32>, + current_orientation: UnitQuaternion<f32>, + current_velocity: Vector3<f32>, + time: f32, + obstacles: &[Obstacle], +) -> Result<(Vector3<f32>, Vector3<f32>, f32), SimulationError>

Updates the current planner and returns the desired position, velocity, and yaw

+
§Arguments
+
    +
  • current_position - The current position of the quadrotor
  • +
  • current_orientation - The current orientation of the quadrotor
  • +
  • current_velocity - The current velocity of the quadrotor
  • +
  • time - The current simulation time
  • +
+
§Returns
+
    +
  • A tuple containing the desired position, velocity, and yaw angle
  • +
+
§Errors
+
    +
  • Returns a SimulationError if the current planner is not finished
  • +
+
§Example
+
use nalgebra::{Vector3, UnitQuaternion};
+use peng_quad::{PlannerManager, SimulationError};
+let initial_position = Vector3::new(0.0, 0.0, 1.0);
+let initial_yaw = 0.0;
+let mut planner_manager = PlannerManager::new(initial_position, initial_yaw);
+let current_position = Vector3::new(0.0, 0.0, 1.0);
+let current_orientation = UnitQuaternion::from_euler_angles(0.0, 0.0, 0.0);
+let current_velocity = Vector3::new(0.0, 0.0, 0.0);
+let obstacles = vec![];
+let time = 0.0;
+let result = planner_manager.update(current_position, current_orientation, current_velocity, time, &obstacles);
+match result {
+    Ok((target_position, target_velocity, target_yaw)) => {
+        println!("Target Position: {:?}", target_position);
+        println!("Target Velocity: {:?}", target_velocity);
+        println!("Target Yaw: {:?}", target_yaw);
+    }
+    Err(SimulationError) => {
+        log::error!("Error: Planner is not finished");
+    }
+}
+

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.PlannerStepConfig.html b/peng_quad/struct.PlannerStepConfig.html new file mode 100644 index 00000000..b0b7e151 --- /dev/null +++ b/peng_quad/struct.PlannerStepConfig.html @@ -0,0 +1,55 @@ +PlannerStepConfig in peng_quad - Rust

Struct peng_quad::PlannerStepConfig

source ·
pub struct PlannerStepConfig {
+    pub step: usize,
+    pub planner_type: String,
+    pub params: Value,
+}
Expand description

Represents a step in the planner schedule.

+

§Example

+
use peng_quad::PlannerStepConfig;
+let step = PlannerStepConfig {
+    step: 0,
+    planner_type: "MinimumJerkLocalPlanner".to_string(),
+    params: serde_yaml::Value::Null,
+};
+

Fields§

§step: usize

The simulation step at which this planner should be activated (in ms unit).

+
§planner_type: String

The type of planner to use for this step.

+
§params: Value

Additional parameters for the planner, stored as a YAML value.

+

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.Quadrotor.html b/peng_quad/struct.Quadrotor.html new file mode 100644 index 00000000..be74dfc1 --- /dev/null +++ b/peng_quad/struct.Quadrotor.html @@ -0,0 +1,211 @@ +Quadrotor in peng_quad - Rust

Struct peng_quad::Quadrotor

source ·
pub struct Quadrotor {
+    pub position: Vector3<f32>,
+    pub velocity: Vector3<f32>,
+    pub orientation: UnitQuaternion<f32>,
+    pub angular_velocity: Vector3<f32>,
+    pub mass: f32,
+    pub gravity: f32,
+    pub time_step: f32,
+    pub drag_coefficient: f32,
+    pub inertia_matrix: Matrix3<f32>,
+    pub inertia_matrix_inv: Matrix3<f32>,
+}
Expand description

Represents a quadrotor with its physical properties and state

+

§Example

+
use nalgebra::Vector3;
+use peng_quad::Quadrotor;
+let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix);
+

Fields§

§position: Vector3<f32>

Current position of the quadrotor in 3D space

+
§velocity: Vector3<f32>

Current velocity of the quadrotor

+
§orientation: UnitQuaternion<f32>

Current orientation of the quadrotor

+
§angular_velocity: Vector3<f32>

Current angular velocity of the quadrotor

+
§mass: f32

Mass of the quadrotor in kg

+
§gravity: f32

Gravitational acceleration in m/s^2

+
§time_step: f32

Simulation time step in seconds

+
§drag_coefficient: f32

Drag coefficient

+
§inertia_matrix: Matrix3<f32>

Inertia matrix of the quadrotor

+
§inertia_matrix_inv: Matrix3<f32>

Inverse of the inertia matrix

+

Implementations§

source§

impl Quadrotor

Implementation of the Quadrotor struct

+
source

pub fn new( + time_step: f32, + mass: f32, + gravity: f32, + drag_coefficient: f32, + inertia_matrix: [f32; 9], +) -> Result<Self, SimulationError>

Creates a new Quadrotor with default parameters

+
§Arguments
+
    +
  • time_step - The simulation time step in seconds
  • +
  • mass - The mass of the quadrotor in kg
  • +
  • gravity - The gravitational acceleration in m/s^2
  • +
  • drag_coefficient - The drag coefficient
  • +
  • inertia_matrix - The inertia matrix of the quadrotor
  • +
+
§Returns
+
    +
  • A new Quadrotor instance
  • +
+
§Errors
+
    +
  • Returns a SimulationError if the inertia matrix cannot be inverted
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::Quadrotor;
+
+let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix);
+
source

pub fn update_dynamics_with_controls_euler( + &mut self, + control_thrust: f32, + control_torque: &Vector3<f32>, +)

Updates the quadrotor’s dynamics with control inputs

+
§Arguments
+
    +
  • control_thrust - The total thrust force applied to the quadrotor
  • +
  • control_torque - The 3D torque vector applied to the quadrotor
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::Quadrotor;
+
+let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+let mut quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+let control_thrust = mass * gravity;
+let control_torque = Vector3::new(0.0, 0.0, 0.0);
+quadrotor.update_dynamics_with_controls_euler(control_thrust, &control_torque);
+
source

pub fn update_dynamics_with_controls_rk4( + &mut self, + control_thrust: f32, + control_torque: &Vector3<f32>, +)

Updates the quadrotor’s dynamics with control inputs using the Runge-Kutta 4th order method

+
§Arguments
+
    +
  • control_thrust - The total thrust force applied to the quadrotor
  • +
  • control_torque - The 3D torque vector applied to the quadrotor
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::Quadrotor;
+let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+let mut quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+let control_thrust = mass * gravity;
+let control_torque = Vector3::new(0.0, 0.0, 0.0);
+quadrotor.update_dynamics_with_controls_rk4(control_thrust, &control_torque);
+
source

pub fn get_state(&self) -> [f32; 13]

Returns the state derivative of the quadrotor

+
§Arguments
+
    +
  • state - The state of the quadrotor
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::Quadrotor;
+use nalgebra::UnitQuaternion;
+let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+let state = quadrotor.get_state();
+
source

pub fn set_state(&mut self, state: &[f32; 13])

Sets the state of the quadrotor

+
§Arguments
+
    +
  • state - The state of the quadrotor
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::Quadrotor;
+use nalgebra::UnitQuaternion;
+let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+let mut quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+let state = [
+   0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
+];
+quadrotor.set_state(&state);
+
source

pub fn state_derivative( + &self, + state: &[f32], + control_thrust: f32, + control_torque: &Vector3<f32>, +) -> [f32; 13]

Calculates the derivative of the state of the quadrotor

+
§Arguments
+
    +
  • state - The current state of the quadrotor
  • +
  • control_thrust - The thrust applied to the quadrotor
  • +
  • control_torque - The torque applied to the quadrotor
  • +
+
§Returns
+

The derivative of the state

+
§Example
+
use nalgebra::Vector3;
+use peng_quad::Quadrotor;
+use nalgebra::UnitQuaternion;
+let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+let state = [
+  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
+];
+let control_thrust = 0.0;
+let control_torque = Vector3::new(0.0, 0.0, 0.0);
+let derivative = quadrotor.state_derivative(&state, control_thrust, &control_torque);
+
source

pub fn read_imu(&self) -> Result<(Vector3<f32>, Vector3<f32>), SimulationError>

Simulates IMU readings

+
§Returns
+
    +
  • A tuple containing the true acceleration and angular velocity of the quadrotor
  • +
+
§Errors
+
    +
  • Returns a SimulationError if the IMU readings cannot be calculated
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::Quadrotor;
+
+let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+let (true_acceleration, true_angular_velocity) = quadrotor.read_imu().unwrap();
+

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/struct.Trajectory.html b/peng_quad/struct.Trajectory.html new file mode 100644 index 00000000..86aa9d7d --- /dev/null +++ b/peng_quad/struct.Trajectory.html @@ -0,0 +1,81 @@ +Trajectory in peng_quad - Rust

Struct peng_quad::Trajectory

source ·
pub struct Trajectory {
+    pub points: Vec<Vector3<f32>>,
+    pub last_logged_point: Vector3<f32>,
+    pub min_distance_threadhold: f32,
+}
Expand description

A struct to hold trajectory data

+

§Example

+
use peng_quad::Trajectory;
+let initial_point = nalgebra::Vector3::new(0.0, 0.0, 0.0);
+let mut trajectory = Trajectory::new(initial_point);
+

Fields§

§points: Vec<Vector3<f32>>

A vector of 3D points

+
§last_logged_point: Vector3<f32>

The last point that was logged

+
§min_distance_threadhold: f32

The minimum distance between points to log

+

Implementations§

source§

impl Trajectory

Implement the Trajectory struct

+
source

pub fn new(initial_point: Vector3<f32>) -> Self

Create a new Trajectory instance

+
§Arguments
+
    +
  • initial_point - The initial point to add to the trajectory
  • +
+
§Returns
+
    +
  • A new Trajectory instance
  • +
+
§Example
+
use peng_quad::Trajectory;
+let initial_point = nalgebra::Vector3::new(0.0, 0.0, 0.0);
+let mut trajectory = Trajectory::new(initial_point);
+
source

pub fn add_point(&mut self, point: Vector3<f32>) -> bool

Add a point to the trajectory if it is further than the minimum distance threshold

+
§Arguments
+
    +
  • point - The point to add
  • +
+
§Returns
+
    +
  • true if the point was added, false otherwise
  • +
+
§Example
+
use peng_quad::Trajectory;
+let mut trajectory = Trajectory::new(nalgebra::Vector3::new(0.0, 0.0, 0.0));
+let point = nalgebra::Vector3::new(1.0, 0.0, 0.0);
+assert_eq!(trajectory.add_point(point), true);
+assert_eq!(trajectory.add_point(point), false);
+

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where + T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where + Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where + T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where + Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where + F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where + Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where + Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where + T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where + Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where + T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where + Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<SS, SP> SupersetOf<SS> for SP
where + SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its +superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where + T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where + Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where + T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where + Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
\ No newline at end of file diff --git a/peng_quad/trait.Planner.html b/peng_quad/trait.Planner.html new file mode 100644 index 00000000..bd22cf77 --- /dev/null +++ b/peng_quad/trait.Planner.html @@ -0,0 +1,115 @@ +Planner in peng_quad - Rust

Trait peng_quad::Planner

source ·
pub trait Planner {
+    // Required methods
+    fn plan(
+        &self,
+        current_position: Vector3<f32>,
+        current_velocity: Vector3<f32>,
+        time: f32,
+    ) -> (Vector3<f32>, Vector3<f32>, f32);
+    fn is_finished(
+        &self,
+        current_position: Vector3<f32>,
+        time: f32,
+    ) -> Result<bool, SimulationError>;
+}
Expand description

Trait defining the interface for trajectory planners

+

§Example

+
use nalgebra::Vector3;
+use peng_quad::{Planner, SimulationError};
+struct TestPlanner;
+impl Planner for TestPlanner {
+   fn plan(
+        &self,
+        current_position: Vector3<f32>,
+        current_velocity: Vector3<f32>,
+        time: f32,
+) -> (Vector3<f32>, Vector3<f32>, f32) {
+        (Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 0.0)
+    }
+    fn is_finished(
+        &self,
+        current_position: Vector3<f32>,
+        time: f32,
+    ) -> Result<bool, SimulationError> {
+        Ok(true)
+    }
+}
+

Required Methods§

source

fn plan( + &self, + current_position: Vector3<f32>, + current_velocity: Vector3<f32>, + time: f32, +) -> (Vector3<f32>, Vector3<f32>, f32)

Plans the trajectory based on the current state and time

+
§Arguments
+
    +
  • current_position - The current position of the quadrotor
  • +
  • current_velocity - The current velocity of the quadrotor
  • +
  • time - The current simulation time
  • +
+
§Returns
+
    +
  • A tuple containing the desired position, velocity, and yaw angle
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::{Planner, SimulationError};
+struct TestPlanner;
+impl Planner for TestPlanner {
+    fn plan(
+        &self,
+        current_position: Vector3<f32>,
+        current_velocity: Vector3<f32>,
+        time: f32,
+) -> (Vector3<f32>, Vector3<f32>, f32) {
+        (Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 0.0)
+    }
+    fn is_finished(
+        &self,
+        current_position: Vector3<f32>,
+        time: f32,
+    ) -> Result<bool, SimulationError> {
+        Ok(true)
+    }
+}
+
source

fn is_finished( + &self, + current_position: Vector3<f32>, + time: f32, +) -> Result<bool, SimulationError>

Checks if the current trajectory is finished

+
§Arguments
+
    +
  • current_position - The current position of the quadrotor
  • +
  • time - The current simulation time
  • +
+
§Returns
+
    +
  • true if the trajectory is finished, false otherwise
  • +
+
§Example
+
use nalgebra::Vector3;
+use peng_quad::{Planner, SimulationError};
+struct TestPlanner;
+impl Planner for TestPlanner {
+    fn plan(
+        &self,
+        current_position: Vector3<f32>,
+        current_velocity: Vector3<f32>,
+        time: f32,
+) -> (Vector3<f32>, Vector3<f32>, f32) {
+        (Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 0.0)
+    }
+    fn is_finished(
+        &self,
+        current_position: Vector3<f32>,
+        time: f32,
+    ) -> Result<bool, SimulationError> {
+        Ok(true)
+    }
+}
+

Implementors§

source§

impl Planner for CirclePlanner

Implementation of the Planner trait for CirclePlanner

+
source§

impl Planner for HoverPlanner

Implementation of the Planner trait for the HoverPlanner

+
source§

impl Planner for LandingPlanner

Implementation of the Planner trait for LandingPlanner

+
source§

impl Planner for LissajousPlanner

Implementation of the planner trait for Lissajous curve trajectories

+
source§

impl Planner for MinimumJerkLinePlanner

Implementation of the planner trait for minimum jerk line planner

+
source§

impl Planner for MinimumSnapWaypointPlanner

Implement the Planner trait for MinimumSnapWaypointPlanner

+
source§

impl Planner for ObstacleAvoidancePlanner

Implementation of the Planner trait for ObstacleAvoidancePlanner

+
\ No newline at end of file diff --git a/search-index.js b/search-index.js new file mode 100644 index 00000000..707b01c1 --- /dev/null +++ b/search-index.js @@ -0,0 +1,4 @@ +var searchIndex = new Map(JSON.parse('[["peng_quad",{"t":"FPFPFFPFPFFPFPFPPFPFPFKFFGFPPGFNOOONOOOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOHNNNNCHOOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNONNNNNNNNNNNNNNNNNNOOOOOOOOOONONNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOONNNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOHHHHHHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOOONNNNNNNNNOOOOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOHHOHMNNNNNNNNOOOOOOOONONNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOOOOOOOOOONOOOOOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNHOOONNNNNNNNNNNNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOFFFFFFFFFFOOOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOONNNNNNNNNNOOONNNNNNNNNNNNNNNNNNNNNOOOOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOONNNNNNNNNNNNNNNNNNNNOOOOOOOONNNNNNNNNNNNNNNNNNNNOOOOOOOOOONNNNNNNNNNNNNNNNNNNNOOOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNN","n":["Camera","Circle","CirclePlanner","Hover","HoverPlanner","Imu","Landing","LandingPlanner","Lissajous","LissajousPlanner","Maze","MinimumJerkLine","MinimumJerkLinePlanner","MinimumSnapWaypoint","MinimumSnapWaypointPlanner","NalgebraError","NormalError","Obstacle","ObstacleAvoidance","ObstacleAvoidancePlanner","OtherError","PIDController","Planner","PlannerManager","PlannerStepConfig","PlannerType","Quadrotor","RerunError","RerunSpawnError","SimulationError","Trajectory","__clone_box","accel_bias","accel_bias_std","accel_noise_std","add_point","amplitude","angular_velocity","","aspect_ratio","az","","","","","","","","","","","","","","","","","","borrow","","","","","","","","","","","","","","","","","","borrow_mut","","","","","","","","","","","","","","","","","","cast_from","","","","","","","","","","","","","","","","","","center","","checked_as","","","","","","","","","","","","","","","","","","checked_cast_from","","","","","","","","","","","","","","","","","","clone","clone_into","clone_to_uninit","coefficients","color_map_fn","compute_attitude_control","compute_minimum_acceleration_yaw_trajectories","compute_minimum_snap_trajectories","compute_position_control","config","create_planner","current_planner","d0","d_target","deref","","","","","","","","","","","","","","","","","","deref_mut","","","","","","","","","","","","","","","","","","drag_coefficient","drop","","","","","","","","","","","","","","","","","","duration","","","","","end_position","end_yaw","","","","evaluate_polynomial","far","fmt","","fov","frequency","from","","","","","","","","","","","","","","","","","","","","","from_subset","","","","","","","","","","","","","","","","","","generate_obstacles","get_state","gravity","","gyro_bias","gyro_bias_std","gyro_noise_std","inertia_matrix","inertia_matrix_inv","init","","","","","","","","","","","","","","","","","","integral_att_error","integral_pos_error","into","","","","","","","","","","","","","","","","","","is_finished","","","","","","","","","is_in_subset","","","","","","","","","","","","","","","","","","k_att","k_rep","k_vortex","kpid_att","kpid_pos","last_logged_point","log_data","log_depth_image","log_maze_obstacles","log_maze_tube","log_mesh","log_trajectory","lossless_try_into","","","","","","","","","","","","","","","","","","lossy_into","","","","","","","","","","","","","","","","","","lower_bounds","mass","","max_integral_att","max_integral_pos","max_speed","min_distance_threadhold","near","new","","","","","","","","","obstacles","","obstacles_radius_bounds","obstacles_velocity_bounds","orientation","overflowing_as","","","","","","","","","","","","","","","","","","overflowing_cast_from","","","","","","","","","","","","","","","","","","params","parse_f32","parse_vector3","phase","pinhole_depth","plan","","","","","","","","","planner_type","points","position","","radius","","ramp_time","","ray_cast","ray_directions","read","read_imu","render_depth","resolution","saturating_as","","","","","","","","","","","","","","","","","","saturating_cast_from","","","","","","","","","","","","","","","","","","set_planner","set_state","smooth_attractive_force","source","start_position","","","","start_time","","","","","","start_yaw","","","","","state_derivative","step","target_position","","target_yaw","time_step","times","to_owned","to_string","to_subset","","","","","","","","","","","","","","","","","","to_subset_unchecked","","","","","","","","","","","","","","","","","","try_from","","","","","","","","","","","","","","","","","","try_into","","","","","","","","","","","","","","","","","","type_id","","","","","","","","","","","","","","","","","","unwrapped_as","","","","","","","","","","","","","","","","","","unwrapped_cast_from","","","","","","","","","","","","","","","","","","update","","update_dynamics_with_controls_euler","update_dynamics_with_controls_rk4","update_obstacles","update_planner","upper_bounds","velocity","","vzip","","","","","","","","","","","","","","","","","","waypoints","wrapping_as","","","","","","","","","","","","","","","","","","wrapping_cast_from","","","","","","","","","","","","","","","","","","yaw_coefficients","yaws","CameraConfig","Config","ImuConfig","MazeConfig","MeshConfig","PIDControllerConfig","PIDGains","PlannerStep","QuadrotorConfig","SimulationConfig","accel_bias_std","accel_noise_std","att_gains","att_max_int","az","","","","","","","","","","borrow","","","","","","","","","","borrow_mut","","","","","","","","","","camera","cast_from","","","","","","","","","","checked_as","","","","","","","","","","checked_cast_from","","","","","","","","","","control_frequency","default","deref","","","","","","","","","","deref_mut","","","","","","","","","","deserialize","","","","","","","","","","division","drag_coefficient","drop","","","","","","","","","","duration","far","fov","from","","","","","","","","","","from_subset","","","","","","","","","","from_yaml","gravity","gyro_bias_std","gyro_noise_std","imu","inertia_matrix","init","","","","","","","","","","into","","","","","","","","","","is_in_subset","","","","","","","","","","kd","ki","kp","log_frequency","lossless_try_into","","","","","","","","","","lossy_into","","","","","","","","","","lower_bounds","mass","maze","mesh","near","num_obstacles","obstacles_radius_bounds","obstacles_velocity_bounds","overflowing_as","","","","","","","","","","overflowing_cast_from","","","","","","","","","","params","pid_controller","planner_schedule","planner_type","pos_gains","pos_max_int","quadrotor","render_depth","resolution","rotation_transform","saturating_as","","","","","","","","","","saturating_cast_from","","","","","","","","","","simulation","simulation_frequency","spacing","step","to_subset","","","","","","","","","","to_subset_unchecked","","","","","","","","","","try_from","","","","","","","","","","try_into","","","","","","","","","","type_id","","","","","","","","","","unwrapped_as","","","","","","","","","","unwrapped_cast_from","","","","","","","","","","upper_bounds","use_multithreading_depth_rendering","use_rerun","use_rk4_for_dynamics_control","use_rk4_for_dynamics_update","vzip","","","","","","","","","","wrapping_as","","","","","","","","","","wrapping_cast_from","","","","","","","","",""],"q":[[0,"peng_quad"],[738,"peng_quad::config"],[1107,"dyn_clone::sealed"],[1108,"nalgebra::base::alias"],[1109,"core::option"],[1110,"nalgebra::geometry::quaternion"],[1111,"core::result"],[1112,"core::fmt"],[1113,"re_sdk::recording_stream"],[1114,"rand_distr::normal"],[1115,"re_sdk::spawn"],[1116,"alloc::vec"],[1117,"serde_yaml::value"],[1118,"core::error"],[1119,"alloc::string"],[1120,"core::any"],[1121,"serde::de"],[1122,"alloc::boxed"]],"i":"`Bj`0``0`0``0`0`B`0`1`0``````00``AdDl00jDbBfDdEb25Aj9CnD`64DfDnDhAnBdCh9=B`Ad=Dl;Bj;:Db?:98765>j54Bf4?3>=2Dd=<;:98Eb38726Aj6CnD`74DfDnDhAnBdCh9j54Bf4?3>=2Dd=<;:98Eb387777;`Aj<<0``>==3706CnD`74DfDnDhAnBdCh9j54Bf04?3>=2Dd=<;:98Eb387?41>j546Bf0?4440004?3>=2Dd=<;:98Eb387Aj03706CnD`74DfDnDhAnBdCh9=2Dd=<;:98Ebj98===Aj01``````5407CnD`85DfDnDhAnBdCh:9B`Ad?>:Bj:9Db?987654>=324Bf===8>?0Dl>:86Ebj6;888332Aj6CnD`7DdDfDnDhAnBdCh;:B`Ad?>;Bj;:Db:987654?>325``0`Cl2=<1;:876?Bf4<422=<>2=<:9>2=<:08?:?09450DlAj5CnD`6DdDfDnDhAnBdCh===>3`3>0>==U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nChecks if the current trajectory is finished\nChecks if the current trajectory is finished\nAttractive force gain\nRepulsive force gain\nVortex force gain\nPID gain for attitude control including proportional, …\nPID gain for position control including proportional, …\nThe last point that was logged\nLogs simulation data to the rerun recording stream\nlog depth image data to the rerun recording stream\nLog the maze obstacles to the rerun recording stream\nLog the maze tube to the rerun recording stream\nlog mesh data to the rerun recording stream\nlog trajectory data to the rerun recording stream\nThe lower bounds of the maze in the x, y, and z directions\nMass of the quadrotor in kg\nMass of the quadrotor\nMaximum allowed integral error for attitude\nMaximum allowed integral error for position\nMaximum speed of the quadrotor\nThe minimum distance between points to log\nThe near clipping plane of the camera\nCreates a new Quadrotor with default parameters\nCreates a new IMU with default parameters\nCreates a new PIDController with default gains gains are …\nCreates a new PlannerManager with an initial hover planner\nGenerate a new minimum snap waypoint planner\nCreates a new maze with the given bounds and number of …\nCreates a new camera with the given resolution, field of …\nCreate a new Trajectory instance\nCreates a new obstacle with the given position, velocity, …\nList of obstacles\nThe obstacles in the maze\nThe bounds of the obstacles’ radius\nThe bounds of the obstacles’ velocity\nCurrent orientation of the quadrotor\nAdditional parameters for the planner, stored as a YAML …\nHelper function to parse f32 from YAML\nHelper function to parse Vector3 from YAML\nPhase of the Lissajous curve\ncreates pinhole camera\nPlans the trajectory based on the current state and time\nPlans the trajectory based on the current planner type\nThe type of planner to use for this step.\nA vector of 3D points\nCurrent position of the quadrotor in 3D space\nThe position of the obstacle\nRadius of the circular trajectory\nThe radius of the obstacle\nRamp-up time for smooth transitions\nRamp-up time for smooth transitions\nCasts a ray from the camera origin in the given direction\nThe ray directions of each pixel in the camera\nSimulates IMU readings with added bias and noise\nSimulates IMU readings\nRenders the depth of the scene from the perspective of the …\nThe resolution of the camera\nSets a new planner\nSets the state of the quadrotor\nA smooth attractive force function that transitions from …\nStarting position of the trajectory\nStarting position of the trajectory\nStarting position of the trajectory\nStarting position of the landing maneuver\nStart time of the trajectory\nStart time of the trajectory\nStart time of the trajectory\nStart time of the landing maneuver\nStart time of the planner\nStart time of the trajectory\nStarting yaw angle\nStarting yaw angle\nStarting yaw angle\nStarting yaw angle\nStarting yaw angle\nCalculates the derivative of the state of the quadrotor\nThe simulation step at which this planner should be …\nTarget position for hovering\nTarget position of the planner\nTarget yaw angle for hovering\nSimulation time step in seconds\nList of segment times to reach each waypoint\nUpdates the IMU biases over time\nUpdates the current planner and returns the desired …\nUpdates the quadrotor’s dynamics with control inputs\nUpdates the quadrotor’s dynamics with control inputs …\nUpdates the obstacles in the maze, if an obstacle hits a …\nUpdates the planner based on the current simulation step …\nThe upper bounds of the maze in the x, y, and z directions\nCurrent velocity of the quadrotor\nThe velocity of the obstacle\nList of waypoints\nCoefficients for the yaw component of the trajectory\nList of yaw angles\nConfiguration for the camera\nConfiguration for the simulation\nConfiguration for the IMU\nConfiguration for the maze\nConfiguration for the mesh\nConfiguration for the PID controller\nConfiguration for PID gains\nConfiguration for a planner step\nConfiguration for the quadrotor\nConfiguration for the simulation\nAccelerometer bias drift standard deviation\nAccelerometer noise standard deviation\nAttitude gains\nMaximum integral error for attitude control\nCamera configuration\nControl frequency in Hz\nDivision of the 2D mesh, the mesh will be division x …\nDrag coefficient in Ns^2/m^2\nDuration of the simulation in seconds\nCamera far clipping plane in meters\nCamera field of view in height in degrees\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nLoad configuration from a YAML file.\nGravity in m/s^2\nGyroscope bias drift standard deviation\nGyroscope noise standard deviation\nIMU configuration\nInertia matrix in kg*m^2\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nDerivative gains\nIntegral gains\nProportional gains\nLog frequency in Hz\nLower bounds of the maze in meters (x, y, z)\nMass of the quadrotor in kg\nMaze configuration\nMesh configuration\nCamera near clipping plane in meters\nNumber of obstacles in the maze\nObstacle radius bounds in meters (min, max)\nObstacle velocity maximum bounds in m/s in (x, y, z) …\nParameters for the planner\nPID Controller configuration\nPlanner schedule configuration\nType of planner to use\nPosition gains\nMaximum integral error for position control\nQuadrotor configuration\nRender depth\nCamera resolution in pixels (width, height)\nCamera transform matrix for depth\nSimulation configuration\nSimulation frequency in Hz\nSpacing between the squares in meters\nStep number that the planner should be executed (Unit: ms)\nUpper bounds of the maze in meters (x, y, z)\nMultiThreading depth rendering\nUse rerun.io for recording\nUse RK4 for updating quadrotor dynamics_with_controls\nUse RK4 for updating quadrotor dynamics without controls") \ No newline at end of file diff --git a/settings.html b/settings.html new file mode 100644 index 00000000..9a427dc5 --- /dev/null +++ b/settings.html @@ -0,0 +1 @@ +Settings

Rustdoc settings

Back
\ No newline at end of file diff --git a/src-files.js b/src-files.js new file mode 100644 index 00000000..2db8d25e --- /dev/null +++ b/src-files.js @@ -0,0 +1,3 @@ +var srcIndex = new Map(JSON.parse('[["peng_quad",["",[],["config.rs","lib.rs"]]]]')); +createSrcSidebar(); +//{"start":36,"fragment_lengths":[44]} \ No newline at end of file diff --git a/src/peng_quad/config.rs.html b/src/peng_quad/config.rs.html new file mode 100644 index 00000000..f0d65a3f --- /dev/null +++ b/src/peng_quad/config.rs.html @@ -0,0 +1,323 @@ +config.rs - source
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+
//! Configuration module
+//! This module contains the configuration for the simulation, quadrotor, PID controller, IMU, maze, camera, mesh, and planner schedule.
+//! The configuration is loaded from a YAML file using the serde library.
+//! The configuration is then used to initialize the simulation, quadrotor, PID controller, IMU, maze, camera, mesh, and planner schedule.
+#[derive(serde::Deserialize)]
+/// Configuration for the simulation
+pub struct Config {
+    /// Simulation configuration
+    pub simulation: SimulationConfig,
+    /// Quadrotor configuration
+    pub quadrotor: QuadrotorConfig,
+    /// PID Controller configuration
+    pub pid_controller: PIDControllerConfig,
+    /// IMU configuration
+    pub imu: ImuConfig,
+    /// Maze configuration
+    pub maze: MazeConfig,
+    /// Camera configuration
+    pub camera: CameraConfig,
+    /// Mesh configuration
+    pub mesh: MeshConfig,
+    /// Planner schedule configuration
+    pub planner_schedule: Vec<PlannerStep>,
+    /// Use rerun.io for recording
+    pub use_rerun: bool,
+    /// Render depth
+    pub render_depth: bool,
+    /// MultiThreading depth rendering
+    pub use_multithreading_depth_rendering: bool,
+    /// Use RK4 for updating quadrotor dynamics_with_controls
+    pub use_rk4_for_dynamics_control: bool,
+    /// Use RK4 for updating quadrotor dynamics without controls
+    pub use_rk4_for_dynamics_update: bool,
+}
+
+#[derive(serde::Deserialize)]
+/// Configuration for a planner step
+pub struct PlannerStep {
+    /// Step number that the planner should be executed (Unit: ms)
+    pub step: usize,
+    /// Type of planner to use
+    pub planner_type: String,
+    /// Parameters for the planner
+    pub params: serde_yaml::Value,
+}
+
+#[derive(serde::Deserialize)]
+/// Configuration for the simulation
+pub struct SimulationConfig {
+    /// Control frequency in Hz
+    pub control_frequency: usize,
+    /// Simulation frequency in Hz
+    pub simulation_frequency: usize,
+    /// Log frequency in Hz
+    pub log_frequency: usize,
+    /// Duration of the simulation in seconds
+    pub duration: f32,
+}
+
+#[derive(serde::Deserialize)]
+/// Configuration for the quadrotor
+pub struct QuadrotorConfig {
+    /// Mass of the quadrotor in kg
+    pub mass: f32,
+    /// Gravity in m/s^2
+    pub gravity: f32,
+    /// Drag coefficient in Ns^2/m^2
+    pub drag_coefficient: f32,
+    /// Inertia matrix in kg*m^2
+    pub inertia_matrix: [f32; 9],
+}
+
+#[derive(serde::Deserialize)]
+/// Configuration for the PID controller
+pub struct PIDControllerConfig {
+    /// Position gains
+    pub pos_gains: PIDGains,
+    /// Attitude gains
+    pub att_gains: PIDGains,
+    /// Maximum integral error for position control
+    pub pos_max_int: [f32; 3],
+    /// Maximum integral error for attitude control
+    pub att_max_int: [f32; 3],
+}
+
+#[derive(serde::Deserialize)]
+/// Configuration for PID gains
+pub struct PIDGains {
+    /// Proportional gains
+    pub kp: [f32; 3],
+    /// Integral gains
+    pub ki: [f32; 3],
+    /// Derivative gains
+    pub kd: [f32; 3],
+}
+
+#[derive(serde::Deserialize, Default)]
+/// Configuration for the IMU
+pub struct ImuConfig {
+    /// Accelerometer noise standard deviation
+    pub accel_noise_std: f32,
+    /// Gyroscope noise standard deviation
+    pub gyro_noise_std: f32,
+    /// Accelerometer bias drift standard deviation
+    pub accel_bias_std: f32,
+    /// Gyroscope bias drift standard deviation
+    pub gyro_bias_std: f32,
+}
+
+#[derive(serde::Deserialize)]
+/// Configuration for the maze
+pub struct MazeConfig {
+    /// Upper bounds of the maze in meters (x, y, z)
+    pub upper_bounds: [f32; 3],
+    /// Lower bounds of the maze in meters (x, y, z)
+    pub lower_bounds: [f32; 3],
+    /// Number of obstacles in the maze
+    pub num_obstacles: usize,
+    /// Obstacle velocity maximum bounds in m/s in (x, y, z) directions
+    pub obstacles_velocity_bounds: [f32; 3],
+    /// Obstacle radius bounds in meters (min, max)
+    pub obstacles_radius_bounds: [f32; 2],
+}
+
+#[derive(serde::Deserialize)]
+/// Configuration for the camera
+pub struct CameraConfig {
+    /// Camera resolution in pixels (width, height)
+    pub resolution: (usize, usize),
+    /// Camera field of view in height in degrees
+    pub fov: f32,
+    /// Camera near clipping plane in meters
+    pub near: f32,
+    /// Camera far clipping plane in meters
+    pub far: f32,
+    /// Camera transform matrix for depth
+    pub rotation_transform: [f32; 9]
+}
+
+#[derive(serde::Deserialize)]
+/// Configuration for the mesh
+pub struct MeshConfig {
+    /// Division of the 2D mesh, the mesh will be division x division squares
+    pub division: usize,
+    /// Spacing between the squares in meters
+    pub spacing: f32,
+}
+/// Implementation of the Config struct
+impl Config {
+    /// Load configuration from a YAML file.
+    /// # Arguments
+    /// * `filename` - The name of the file to load.
+    /// # Returns
+    /// * The configuration object.
+    /// # Errors
+    /// * If the file cannot be read or the YAML cannot be parsed.
+    pub fn from_yaml(filename: &str) -> Result<Self, Box<dyn std::error::Error>> {
+        let contents = std::fs::read_to_string(filename)?;
+        Ok(serde_yaml::from_str(&contents)?)
+    }
+}
+
\ No newline at end of file diff --git a/src/peng_quad/lib.rs.html b/src/peng_quad/lib.rs.html new file mode 100644 index 00000000..9f336432 --- /dev/null +++ b/src/peng_quad/lib.rs.html @@ -0,0 +1,5377 @@ +lib.rs - source
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
+967
+968
+969
+970
+971
+972
+973
+974
+975
+976
+977
+978
+979
+980
+981
+982
+983
+984
+985
+986
+987
+988
+989
+990
+991
+992
+993
+994
+995
+996
+997
+998
+999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
+1539
+1540
+1541
+1542
+1543
+1544
+1545
+1546
+1547
+1548
+1549
+1550
+1551
+1552
+1553
+1554
+1555
+1556
+1557
+1558
+1559
+1560
+1561
+1562
+1563
+1564
+1565
+1566
+1567
+1568
+1569
+1570
+1571
+1572
+1573
+1574
+1575
+1576
+1577
+1578
+1579
+1580
+1581
+1582
+1583
+1584
+1585
+1586
+1587
+1588
+1589
+1590
+1591
+1592
+1593
+1594
+1595
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+1801
+1802
+1803
+1804
+1805
+1806
+1807
+1808
+1809
+1810
+1811
+1812
+1813
+1814
+1815
+1816
+1817
+1818
+1819
+1820
+1821
+1822
+1823
+1824
+1825
+1826
+1827
+1828
+1829
+1830
+1831
+1832
+1833
+1834
+1835
+1836
+1837
+1838
+1839
+1840
+1841
+1842
+1843
+1844
+1845
+1846
+1847
+1848
+1849
+1850
+1851
+1852
+1853
+1854
+1855
+1856
+1857
+1858
+1859
+1860
+1861
+1862
+1863
+1864
+1865
+1866
+1867
+1868
+1869
+1870
+1871
+1872
+1873
+1874
+1875
+1876
+1877
+1878
+1879
+1880
+1881
+1882
+1883
+1884
+1885
+1886
+1887
+1888
+1889
+1890
+1891
+1892
+1893
+1894
+1895
+1896
+1897
+1898
+1899
+1900
+1901
+1902
+1903
+1904
+1905
+1906
+1907
+1908
+1909
+1910
+1911
+1912
+1913
+1914
+1915
+1916
+1917
+1918
+1919
+1920
+1921
+1922
+1923
+1924
+1925
+1926
+1927
+1928
+1929
+1930
+1931
+1932
+1933
+1934
+1935
+1936
+1937
+1938
+1939
+1940
+1941
+1942
+1943
+1944
+1945
+1946
+1947
+1948
+1949
+1950
+1951
+1952
+1953
+1954
+1955
+1956
+1957
+1958
+1959
+1960
+1961
+1962
+1963
+1964
+1965
+1966
+1967
+1968
+1969
+1970
+1971
+1972
+1973
+1974
+1975
+1976
+1977
+1978
+1979
+1980
+1981
+1982
+1983
+1984
+1985
+1986
+1987
+1988
+1989
+1990
+1991
+1992
+1993
+1994
+1995
+1996
+1997
+1998
+1999
+2000
+2001
+2002
+2003
+2004
+2005
+2006
+2007
+2008
+2009
+2010
+2011
+2012
+2013
+2014
+2015
+2016
+2017
+2018
+2019
+2020
+2021
+2022
+2023
+2024
+2025
+2026
+2027
+2028
+2029
+2030
+2031
+2032
+2033
+2034
+2035
+2036
+2037
+2038
+2039
+2040
+2041
+2042
+2043
+2044
+2045
+2046
+2047
+2048
+2049
+2050
+2051
+2052
+2053
+2054
+2055
+2056
+2057
+2058
+2059
+2060
+2061
+2062
+2063
+2064
+2065
+2066
+2067
+2068
+2069
+2070
+2071
+2072
+2073
+2074
+2075
+2076
+2077
+2078
+2079
+2080
+2081
+2082
+2083
+2084
+2085
+2086
+2087
+2088
+2089
+2090
+2091
+2092
+2093
+2094
+2095
+2096
+2097
+2098
+2099
+2100
+2101
+2102
+2103
+2104
+2105
+2106
+2107
+2108
+2109
+2110
+2111
+2112
+2113
+2114
+2115
+2116
+2117
+2118
+2119
+2120
+2121
+2122
+2123
+2124
+2125
+2126
+2127
+2128
+2129
+2130
+2131
+2132
+2133
+2134
+2135
+2136
+2137
+2138
+2139
+2140
+2141
+2142
+2143
+2144
+2145
+2146
+2147
+2148
+2149
+2150
+2151
+2152
+2153
+2154
+2155
+2156
+2157
+2158
+2159
+2160
+2161
+2162
+2163
+2164
+2165
+2166
+2167
+2168
+2169
+2170
+2171
+2172
+2173
+2174
+2175
+2176
+2177
+2178
+2179
+2180
+2181
+2182
+2183
+2184
+2185
+2186
+2187
+2188
+2189
+2190
+2191
+2192
+2193
+2194
+2195
+2196
+2197
+2198
+2199
+2200
+2201
+2202
+2203
+2204
+2205
+2206
+2207
+2208
+2209
+2210
+2211
+2212
+2213
+2214
+2215
+2216
+2217
+2218
+2219
+2220
+2221
+2222
+2223
+2224
+2225
+2226
+2227
+2228
+2229
+2230
+2231
+2232
+2233
+2234
+2235
+2236
+2237
+2238
+2239
+2240
+2241
+2242
+2243
+2244
+2245
+2246
+2247
+2248
+2249
+2250
+2251
+2252
+2253
+2254
+2255
+2256
+2257
+2258
+2259
+2260
+2261
+2262
+2263
+2264
+2265
+2266
+2267
+2268
+2269
+2270
+2271
+2272
+2273
+2274
+2275
+2276
+2277
+2278
+2279
+2280
+2281
+2282
+2283
+2284
+2285
+2286
+2287
+2288
+2289
+2290
+2291
+2292
+2293
+2294
+2295
+2296
+2297
+2298
+2299
+2300
+2301
+2302
+2303
+2304
+2305
+2306
+2307
+2308
+2309
+2310
+2311
+2312
+2313
+2314
+2315
+2316
+2317
+2318
+2319
+2320
+2321
+2322
+2323
+2324
+2325
+2326
+2327
+2328
+2329
+2330
+2331
+2332
+2333
+2334
+2335
+2336
+2337
+2338
+2339
+2340
+2341
+2342
+2343
+2344
+2345
+2346
+2347
+2348
+2349
+2350
+2351
+2352
+2353
+2354
+2355
+2356
+2357
+2358
+2359
+2360
+2361
+2362
+2363
+2364
+2365
+2366
+2367
+2368
+2369
+2370
+2371
+2372
+2373
+2374
+2375
+2376
+2377
+2378
+2379
+2380
+2381
+2382
+2383
+2384
+2385
+2386
+2387
+2388
+2389
+2390
+2391
+2392
+2393
+2394
+2395
+2396
+2397
+2398
+2399
+2400
+2401
+2402
+2403
+2404
+2405
+2406
+2407
+2408
+2409
+2410
+2411
+2412
+2413
+2414
+2415
+2416
+2417
+2418
+2419
+2420
+2421
+2422
+2423
+2424
+2425
+2426
+2427
+2428
+2429
+2430
+2431
+2432
+2433
+2434
+2435
+2436
+2437
+2438
+2439
+2440
+2441
+2442
+2443
+2444
+2445
+2446
+2447
+2448
+2449
+2450
+2451
+2452
+2453
+2454
+2455
+2456
+2457
+2458
+2459
+2460
+2461
+2462
+2463
+2464
+2465
+2466
+2467
+2468
+2469
+2470
+2471
+2472
+2473
+2474
+2475
+2476
+2477
+2478
+2479
+2480
+2481
+2482
+2483
+2484
+2485
+2486
+2487
+2488
+2489
+2490
+2491
+2492
+2493
+2494
+2495
+2496
+2497
+2498
+2499
+2500
+2501
+2502
+2503
+2504
+2505
+2506
+2507
+2508
+2509
+2510
+2511
+2512
+2513
+2514
+2515
+2516
+2517
+2518
+2519
+2520
+2521
+2522
+2523
+2524
+2525
+2526
+2527
+2528
+2529
+2530
+2531
+2532
+2533
+2534
+2535
+2536
+2537
+2538
+2539
+2540
+2541
+2542
+2543
+2544
+2545
+2546
+2547
+2548
+2549
+2550
+2551
+2552
+2553
+2554
+2555
+2556
+2557
+2558
+2559
+2560
+2561
+2562
+2563
+2564
+2565
+2566
+2567
+2568
+2569
+2570
+2571
+2572
+2573
+2574
+2575
+2576
+2577
+2578
+2579
+2580
+2581
+2582
+2583
+2584
+2585
+2586
+2587
+2588
+2589
+2590
+2591
+2592
+2593
+2594
+2595
+2596
+2597
+2598
+2599
+2600
+2601
+2602
+2603
+2604
+2605
+2606
+2607
+2608
+2609
+2610
+2611
+2612
+2613
+2614
+2615
+2616
+2617
+2618
+2619
+2620
+2621
+2622
+2623
+2624
+2625
+2626
+2627
+2628
+2629
+2630
+2631
+2632
+2633
+2634
+2635
+2636
+2637
+2638
+2639
+2640
+2641
+2642
+2643
+2644
+2645
+2646
+2647
+2648
+2649
+2650
+2651
+2652
+2653
+2654
+2655
+2656
+2657
+2658
+2659
+2660
+2661
+2662
+2663
+2664
+2665
+2666
+2667
+2668
+2669
+2670
+2671
+2672
+2673
+2674
+2675
+2676
+2677
+2678
+2679
+2680
+2681
+2682
+2683
+2684
+2685
+2686
+2687
+2688
+
//! # Quadrotor Simulation
+//! This crate provides a comprehensive simulation environment for quadrotor drones.
+//! It includes models for quadrotor dynamics, IMU simulation, various trajectory planners,
+//! and a PID controller for position and attitude control.
+//! ## Features
+//! - Realistic quadrotor dynamics simulation
+//! - IMU sensor simulation with configurable noise parameters
+//! - Multiple trajectory planners including hover, minimum jerk, Lissajous curves, and circular paths
+//! - PID controller for position and attitude control
+//! - Integration with the `rerun` crate for visualization
+//! ## Example
+//! ```
+//! use nalgebra::Vector3;
+//! use peng_quad::{Quadrotor, SimulationError};
+//! let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+//! let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+//! let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix);
+//! ```
+use rand::SeedableRng;
+use rayon::prelude::*;
+pub mod config;
+use nalgebra::{Matrix3, Quaternion, Rotation3, SMatrix, UnitQuaternion, Vector3};
+use rand_chacha::ChaCha8Rng;
+use rand_distr::{Distribution, Normal};
+use std::f32::consts::PI;
+#[derive(thiserror::Error, Debug)]
+/// Represents errors that can occur during simulation
+/// # Example
+/// ```
+/// use peng_quad::SimulationError;
+/// let error = SimulationError::NalgebraError("Matrix inversion failed".to_string());
+/// ```
+pub enum SimulationError {
+    /// Error related to Rerun visualization
+    #[error("Rerun error: {0}")]
+    RerunError(#[from] rerun::RecordingStreamError),
+    /// Error related to Rerun spawn process
+    #[error("Rerun spawn error: {0}")]
+    RerunSpawnError(#[from] rerun::SpawnError),
+    /// Error related to linear algebra operations
+    #[error("Nalgebra error: {0}")]
+    NalgebraError(String),
+    /// Error related to normal distribution calculations
+    #[error("Normal error: {0}")]
+    NormalError(#[from] rand_distr::NormalError),
+    /// Other general errors
+    #[error("Other error: {0}")]
+    OtherError(String),
+}
+/// Represents a quadrotor with its physical properties and state
+/// # Example
+/// ```
+/// use nalgebra::Vector3;
+/// use peng_quad::Quadrotor;
+/// let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+/// let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+/// let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix);
+/// ```
+pub struct Quadrotor {
+    /// Current position of the quadrotor in 3D space
+    pub position: Vector3<f32>,
+    /// Current velocity of the quadrotor
+    pub velocity: Vector3<f32>,
+    /// Current orientation of the quadrotor
+    pub orientation: UnitQuaternion<f32>,
+    /// Current angular velocity of the quadrotor
+    pub angular_velocity: Vector3<f32>,
+    /// Mass of the quadrotor in kg
+    pub mass: f32,
+    /// Gravitational acceleration in m/s^2
+    pub gravity: f32,
+    /// Simulation time step in seconds
+    pub time_step: f32,
+    /// Drag coefficient
+    pub drag_coefficient: f32,
+    /// Inertia matrix of the quadrotor
+    pub inertia_matrix: Matrix3<f32>,
+    /// Inverse of the inertia matrix
+    pub inertia_matrix_inv: Matrix3<f32>,
+}
+/// Implementation of the Quadrotor struct
+impl Quadrotor {
+    /// Creates a new Quadrotor with default parameters
+    /// # Arguments
+    /// * `time_step` - The simulation time step in seconds
+    /// * `mass` - The mass of the quadrotor in kg
+    /// * `gravity` - The gravitational acceleration in m/s^2
+    /// * `drag_coefficient` - The drag coefficient
+    /// * `inertia_matrix` - The inertia matrix of the quadrotor
+    /// # Returns
+    /// * A new Quadrotor instance
+    /// # Errors
+    /// * Returns a SimulationError if the inertia matrix cannot be inverted
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::Quadrotor;
+    ///
+    /// let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+    /// let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+    /// let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix);
+    /// ```
+    pub fn new(
+        time_step: f32,
+        mass: f32,
+        gravity: f32,
+        drag_coefficient: f32,
+        inertia_matrix: [f32; 9],
+    ) -> Result<Self, SimulationError> {
+        let inertia_matrix = Matrix3::from_row_slice(&inertia_matrix);
+        let inertia_matrix_inv =
+            inertia_matrix
+                .try_inverse()
+                .ok_or(SimulationError::NalgebraError(
+                    "Failed to invert inertia matrix".to_string(),
+                ))?;
+        Ok(Self {
+            position: Vector3::zeros(),
+            velocity: Vector3::zeros(),
+            orientation: UnitQuaternion::identity(),
+            angular_velocity: Vector3::zeros(),
+            mass,
+            gravity,
+            time_step,
+            drag_coefficient,
+            inertia_matrix,
+            inertia_matrix_inv,
+        })
+    }
+    /// Updates the quadrotor's dynamics with control inputs
+    /// # Arguments
+    /// * `control_thrust` - The total thrust force applied to the quadrotor
+    /// * `control_torque` - The 3D torque vector applied to the quadrotor
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::Quadrotor;
+    ///
+    /// let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+    /// let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+    /// let mut quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+    /// let control_thrust = mass * gravity;
+    /// let control_torque = Vector3::new(0.0, 0.0, 0.0);
+    /// quadrotor.update_dynamics_with_controls_euler(control_thrust, &control_torque);
+    /// ```
+    pub fn update_dynamics_with_controls_euler(
+        &mut self,
+        control_thrust: f32,
+        control_torque: &Vector3<f32>,
+    ) {
+        let gravity_force = Vector3::new(0.0, 0.0, -self.mass * self.gravity);
+        let drag_force = -self.drag_coefficient * self.velocity.norm() * self.velocity;
+        let thrust_world = self.orientation * Vector3::new(0.0, 0.0, control_thrust);
+        let acceleration = (thrust_world + gravity_force + drag_force) / self.mass;
+        self.velocity += acceleration * self.time_step;
+        self.position += self.velocity * self.time_step;
+        let inertia_angular_velocity = self.inertia_matrix * self.angular_velocity;
+        let gyroscopic_torque = self.angular_velocity.cross(&inertia_angular_velocity);
+        let angular_acceleration = self.inertia_matrix_inv * (control_torque - gyroscopic_torque);
+        self.angular_velocity += angular_acceleration * self.time_step;
+        self.orientation *=
+            UnitQuaternion::from_scaled_axis(self.angular_velocity * self.time_step);
+    }
+    /// Updates the quadrotor's dynamics with control inputs using the Runge-Kutta 4th order method
+    /// # Arguments
+    /// * `control_thrust` - The total thrust force applied to the quadrotor
+    /// * `control_torque` - The 3D torque vector applied to the quadrotor
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::Quadrotor;
+    /// let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+    /// let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+    /// let mut quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+    /// let control_thrust = mass * gravity;
+    /// let control_torque = Vector3::new(0.0, 0.0, 0.0);
+    /// quadrotor.update_dynamics_with_controls_rk4(control_thrust, &control_torque);
+    /// ```
+    pub fn update_dynamics_with_controls_rk4(
+        &mut self,
+        control_thrust: f32,
+        control_torque: &Vector3<f32>,
+    ) {
+        let h = self.time_step;
+        let state = self.get_state();
+
+        let k1 = self.state_derivative(&state, control_thrust, control_torque);
+        let mut temp_state = [0.0; 13];
+        for i in 0..13 {
+            temp_state[i] = state[i] + 0.5 * h * k1[i];
+        }
+        let k2 = self.state_derivative(&temp_state, control_thrust, control_torque);
+
+        for i in 0..13 {
+            temp_state[i] = state[i] + 0.5 * h * k2[i];
+        }
+        let k3 = self.state_derivative(&temp_state, control_thrust, control_torque);
+
+        for i in 0..13 {
+            temp_state[i] = state[i] + h * k3[i];
+        }
+        let k4 = self.state_derivative(&temp_state, control_thrust, control_torque);
+
+        let mut new_state = [0.0; 13];
+        for i in 0..13 {
+            new_state[i] = state[i] + (h / 6.0) * (k1[i] + 2.0 * k2[i] + 2.0 * k3[i] + k4[i]);
+        }
+
+        let mut q = Quaternion::new(new_state[9], new_state[6], new_state[7], new_state[8]);
+        q = q.normalize();
+        new_state[6..10].copy_from_slice(q.coords.as_slice());
+
+        self.set_state(&new_state);
+    }
+    /// Returns the state derivative of the quadrotor
+    /// # Arguments
+    /// * `state` - The state of the quadrotor
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::Quadrotor;
+    /// use nalgebra::UnitQuaternion;
+    /// let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+    /// let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+    /// let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+    /// let state = quadrotor.get_state();
+    /// ```
+    pub fn get_state(&self) -> [f32; 13] {
+        let mut state = [0.0; 13];
+        state[0..3].copy_from_slice(self.position.as_slice());
+        state[3..6].copy_from_slice(self.velocity.as_slice());
+        state[6..10].copy_from_slice(self.orientation.coords.as_slice());
+        state[10..13].copy_from_slice(self.angular_velocity.as_slice());
+        state
+    }
+    /// Sets the state of the quadrotor
+    /// # Arguments
+    /// * `state` - The state of the quadrotor
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::Quadrotor;
+    /// use nalgebra::UnitQuaternion;
+    /// let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+    /// let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+    /// let mut quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+    /// let state = [
+    ///    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
+    /// ];
+    /// quadrotor.set_state(&state);
+    /// ```
+    pub fn set_state(&mut self, state: &[f32; 13]) {
+        self.position = Vector3::from_column_slice(&state[0..3]);
+        self.velocity = Vector3::from_column_slice(&state[3..6]);
+        self.orientation = UnitQuaternion::from_quaternion(Quaternion::new(
+            state[9], state[6], state[7], state[8],
+        ));
+        self.angular_velocity = Vector3::from_column_slice(&state[10..13]);
+    }
+    /// Calculates the derivative of the state of the quadrotor
+    /// # Arguments
+    /// * `state` - The current state of the quadrotor
+    /// * `control_thrust` - The thrust applied to the quadrotor
+    /// * `control_torque` - The torque applied to the quadrotor
+    /// # Returns
+    /// The derivative of the state
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::Quadrotor;
+    /// use nalgebra::UnitQuaternion;
+    /// let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+    /// let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+    /// let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+    /// let state = [
+    ///   0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
+    /// ];
+    /// let control_thrust = 0.0;
+    /// let control_torque = Vector3::new(0.0, 0.0, 0.0);
+    /// let derivative = quadrotor.state_derivative(&state, control_thrust, &control_torque);
+    /// ```
+    pub fn state_derivative(
+        &self,
+        state: &[f32],
+        control_thrust: f32,
+        control_torque: &Vector3<f32>,
+    ) -> [f32; 13] {
+        let velocity = Vector3::from_column_slice(&state[3..6]);
+        let orientation = UnitQuaternion::from_quaternion(Quaternion::new(
+            state[9], state[6], state[7], state[8],
+        ));
+        // Quaternion deriviative
+        let omega_quat = Quaternion::new(0.0, state[10], state[11], state[12]);
+        let q_dot = orientation.into_inner() * omega_quat * 0.5;
+
+        let angular_velocity = Vector3::from_column_slice(&state[10..13]);
+
+        let gravity_force = Vector3::new(0.0, 0.0, -self.mass * self.gravity);
+        let drag_force = -self.drag_coefficient * velocity.norm() * velocity;
+        let thrust_world = orientation * Vector3::new(0.0, 0.0, control_thrust);
+        let acceleration = (thrust_world + gravity_force + drag_force) / self.mass;
+
+        let inertia_angular_velocity = self.inertia_matrix * angular_velocity;
+        let gyroscopic_torque = angular_velocity.cross(&inertia_angular_velocity);
+        let angular_acceleration = self.inertia_matrix_inv * (control_torque - gyroscopic_torque);
+
+        let mut derivative = [0.0; 13];
+        derivative[0..3].copy_from_slice(velocity.as_slice());
+        derivative[3..6].copy_from_slice(acceleration.as_slice());
+        derivative[6..10].copy_from_slice(q_dot.coords.as_slice());
+        derivative[10..13].copy_from_slice(angular_acceleration.as_slice());
+        derivative
+    }
+    /// Simulates IMU readings
+    /// # Returns
+    /// * A tuple containing the true acceleration and angular velocity of the quadrotor
+    /// # Errors
+    /// * Returns a SimulationError if the IMU readings cannot be calculated
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::Quadrotor;
+    ///
+    /// let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+    /// let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+    /// let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+    /// let (true_acceleration, true_angular_velocity) = quadrotor.read_imu().unwrap();
+    /// ```
+    pub fn read_imu(&self) -> Result<(Vector3<f32>, Vector3<f32>), SimulationError> {
+        let gravity_world = Vector3::new(0.0, 0.0, self.gravity);
+        let true_acceleration =
+            self.orientation.inverse() * (self.velocity / self.time_step - gravity_world);
+        Ok((true_acceleration, self.angular_velocity))
+    }
+}
+/// Represents an Inertial Measurement Unit (IMU) with bias and noise characteristics
+/// # Example
+/// ```
+/// use nalgebra::Vector3;
+/// use peng_quad::Imu;
+/// let accel_noise_std = 0.0003;
+/// let gyro_noise_std = 0.02;
+/// let accel_bias_std = 0.0001;
+/// let gyro_bias_std = 0.001;
+/// let imu = Imu::new(accel_noise_std, gyro_noise_std, accel_bias_std, gyro_bias_std);
+/// ```
+pub struct Imu {
+    /// Accelerometer bias
+    pub accel_bias: Vector3<f32>,
+    /// Gyroscope bias
+    pub gyro_bias: Vector3<f32>,
+    /// Standard deviation of accelerometer noise
+    pub accel_noise_std: f32,
+    /// Standard deviation of gyroscope noise
+    pub gyro_noise_std: f32,
+    /// Standard deviation of accelerometer bias drift
+    pub accel_bias_std: f32,
+    /// Standard deviation of gyroscope bias drift
+    pub gyro_bias_std: f32,
+    /// Accelerometer noise distribution
+    accel_noise: Normal<f32>,
+    /// Gyroscope noise distribution
+    gyro_noise: Normal<f32>,
+    /// Accelerometer bias drift distribution
+    accel_bias_drift: Normal<f32>,
+    /// Gyroscope bias drift distribution
+    gyro_bias_drift: Normal<f32>,
+    /// Random number generator
+    rng: ChaCha8Rng,
+}
+/// Implements the IMU
+impl Imu {
+    /// Creates a new IMU with default parameters
+    /// # Arguments
+    /// * `accel_noise_std` - Standard deviation of accelerometer noise
+    /// * `gyro_noise_std` - Standard deviation of gyroscope noise
+    /// * `accel_bias_std` - Standard deviation of accelerometer bias drift
+    /// * `gyro_bias_std` - Standard deviation of gyroscope bias drift
+    /// # Returns
+    /// * A new Imu instance
+    /// # Example
+    /// ```
+    /// use peng_quad::Imu;
+    ///
+    /// let imu = Imu::new(0.01, 0.01, 0.01, 0.01);
+    /// ```
+    pub fn new(
+        accel_noise_std: f32,
+        gyro_noise_std: f32,
+        accel_bias_std: f32,
+        gyro_bias_std: f32,
+    ) -> Result<Self, SimulationError> {
+        Ok(Self {
+            accel_bias: Vector3::zeros(),
+            gyro_bias: Vector3::zeros(),
+            accel_noise_std,
+            gyro_noise_std,
+            accel_bias_std,
+            gyro_bias_std,
+            accel_noise: Normal::new(0.0, accel_noise_std)?,
+            gyro_noise: Normal::new(0.0, gyro_noise_std)?,
+            accel_bias_drift: Normal::new(0.0, accel_bias_std)?,
+            gyro_bias_drift: Normal::new(0.0, gyro_bias_std)?,
+            rng: ChaCha8Rng::from_entropy(),
+        })
+    }
+    /// Updates the IMU biases over time
+    /// # Arguments
+    /// * `dt` - Time step for the update
+    /// # Errors
+    /// * Returns a SimulationError if the bias drift cannot be calculated
+    /// # Example
+    /// ```
+    /// use peng_quad::Imu;
+    ///
+    /// let mut imu = Imu::new(0.01, 0.01, 0.01, 0.01).unwrap();
+    /// imu.update(0.01).unwrap();
+    /// ```
+    pub fn update(&mut self, dt: f32) -> Result<(), SimulationError> {
+        let dt_sqrt = fast_sqrt(dt);
+        let accel_drift = self.accel_bias_drift.sample(&mut self.rng) * dt_sqrt;
+        let gyro_drift = self.gyro_bias_drift.sample(&mut self.rng) * dt_sqrt;
+        self.accel_bias += Vector3::from_iterator((0..3).map(|_| accel_drift));
+        self.gyro_bias += Vector3::from_iterator((0..3).map(|_| gyro_drift));
+        Ok(())
+    }
+    /// Simulates IMU readings with added bias and noise
+    /// # Arguments
+    /// * `true_acceleration` - The true acceleration vector
+    /// * `true_angular_velocity` - The true angular velocity vector
+    /// # Returns
+    /// * A tuple containing the measured acceleration and angular velocity
+    /// # Errors
+    /// * Returns a SimulationError if the IMU readings cannot be calculated
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::Imu;
+    ///
+    /// let mut imu = Imu::new(0.01, 0.01, 0.01, 0.01).unwrap();
+    /// let true_acceleration = Vector3::new(0.0, 0.0, 9.81);
+    /// let true_angular_velocity = Vector3::new(0.0, 0.0, 0.0);
+    /// let (measured_acceleration, measured_ang_velocity) = imu.read(true_acceleration, true_angular_velocity).unwrap();
+    /// ```
+    pub fn read(
+        &mut self,
+        true_acceleration: Vector3<f32>,
+        true_angular_velocity: Vector3<f32>,
+    ) -> Result<(Vector3<f32>, Vector3<f32>), SimulationError> {
+        let accel_noise_sample =
+            Vector3::from_iterator((0..3).map(|_| self.accel_noise.sample(&mut self.rng)));
+        let gyro_noise_sample =
+            Vector3::from_iterator((0..3).map(|_| self.gyro_noise.sample(&mut self.rng)));
+        let measured_acceleration = true_acceleration + self.accel_bias + accel_noise_sample;
+        let measured_ang_velocity = true_angular_velocity + self.gyro_bias + gyro_noise_sample;
+        Ok((measured_acceleration, measured_ang_velocity))
+    }
+}
+/// PID controller for quadrotor position and attitude control
+/// # Example
+/// ```
+/// use nalgebra::Vector3;
+/// use peng_quad::PIDController;
+/// let kpid_pos = [
+///     [1.0, 1.0, 1.0],
+///     [0.1, 0.1, 0.1],
+///     [0.01, 0.01, 0.01],
+/// ];
+/// let kpid_att = [
+///     [1.0, 1.0, 1.0],
+///     [0.1, 0.1, 0.1],
+///     [0.01, 0.01, 0.01],
+/// ];
+/// let max_integral_pos = [1.0, 1.0, 1.0];
+/// let max_integral_att = [1.0, 1.0, 1.0];
+/// let mass = 1.0;
+/// let gravity = 9.81;
+/// let pid_controller = PIDController::new(kpid_pos, kpid_att, max_integral_pos, max_integral_att, mass, gravity);
+/// ```
+pub struct PIDController {
+    /// PID gain for position control including proportional, derivative, and integral gains
+    pub kpid_pos: [Vector3<f32>; 3],
+    /// PID gain for attitude control including proportional, derivative, and integral gains
+    pub kpid_att: [Vector3<f32>; 3],
+    /// Accumulated integral error for position
+    pub integral_pos_error: Vector3<f32>,
+    /// Accumulated integral error for attitude
+    pub integral_att_error: Vector3<f32>,
+    /// Maximum allowed integral error for position
+    pub max_integral_pos: Vector3<f32>,
+    /// Maximum allowed integral error for attitude
+    pub max_integral_att: Vector3<f32>,
+    /// Mass of the quadrotor
+    pub mass: f32,
+    /// Gravity constant
+    pub gravity: f32,
+}
+/// Implementation of PIDController
+impl PIDController {
+    /// Creates a new PIDController with default gains
+    /// gains are in the order of proportional, derivative, and integral
+    /// # Arguments
+    /// * `_kpid_pos` - PID gains for position control
+    /// * `_kpid_att` - PID gains for attitude control
+    /// * `_max_integral_pos` - Maximum allowed integral error for position
+    /// * `_max_integral_att` - Maximum allowed integral error for attitude
+    /// # Returns
+    /// * A new PIDController instance
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::PIDController;
+    /// let kpid_pos = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
+    /// let kpid_att = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
+    /// let max_integral_pos = [1.0, 1.0, 1.0];
+    /// let max_integral_att = [1.0, 1.0, 1.0];
+    /// let mass = 1.0;
+    /// let gravity = 9.81;
+    /// let pid = PIDController::new(kpid_pos, kpid_att, max_integral_pos, max_integral_att, mass, gravity);
+    /// ```
+    pub fn new(
+        _kpid_pos: [[f32; 3]; 3],
+        _kpid_att: [[f32; 3]; 3],
+        _max_integral_pos: [f32; 3],
+        _max_integral_att: [f32; 3],
+        _mass: f32,
+        _gravity: f32,
+    ) -> Self {
+        Self {
+            kpid_pos: _kpid_pos.map(Vector3::from),
+            kpid_att: _kpid_att.map(Vector3::from),
+            integral_pos_error: Vector3::zeros(),
+            integral_att_error: Vector3::zeros(),
+            max_integral_pos: Vector3::from(_max_integral_pos),
+            max_integral_att: Vector3::from(_max_integral_att),
+            mass: _mass,
+            gravity: _gravity,
+        }
+    }
+    /// Computes attitude control torques
+    /// # Arguments
+    /// * `desired_orientation` - The desired orientation quaternion
+    /// * `current_orientation` - The current orientation quaternion
+    /// * `current_angular_velocity` - The current angular velocity
+    /// * `dt` - Time step
+    /// # Returns
+    /// * The computed attitude control torques
+    /// # Example
+    /// ```
+    /// use nalgebra::{UnitQuaternion, Vector3};
+    /// use peng_quad::PIDController;
+    ///
+    /// let kpid_pos = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
+    /// let kpid_att = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
+    /// let max_integral_pos = [1.0, 1.0, 1.0];
+    /// let max_integral_att = [1.0, 1.0, 1.0];
+    /// let mass = 1.0;
+    /// let gravity = 9.81;
+    /// let mut pid = PIDController::new(kpid_pos, kpid_att, max_integral_pos, max_integral_att, mass, gravity);
+    /// let desired_orientation = UnitQuaternion::identity();
+    /// let current_orientation = UnitQuaternion::identity();
+    /// let current_angular_velocity = Vector3::zeros();
+    /// let dt = 0.01;
+    /// let control_torques = pid.compute_attitude_control(&desired_orientation, &current_orientation, &current_angular_velocity, dt);
+    /// ```
+    pub fn compute_attitude_control(
+        &mut self,
+        desired_orientation: &UnitQuaternion<f32>,
+        current_orientation: &UnitQuaternion<f32>,
+        current_angular_velocity: &Vector3<f32>,
+        dt: f32,
+    ) -> Vector3<f32> {
+        let error_orientation = current_orientation.inverse() * desired_orientation;
+        let (roll_error, pitch_error, yaw_error) = error_orientation.euler_angles();
+        let error_angles = Vector3::new(roll_error, pitch_error, yaw_error);
+        self.integral_att_error += error_angles * dt;
+        self.integral_att_error = self
+            .integral_att_error
+            .zip_map(&self.max_integral_att, |int, max| int.clamp(-max, max));
+        let error_angular_velocity = -current_angular_velocity; // TODO: Add desired angular velocity
+        self.kpid_att[0].component_mul(&error_angles)
+            + self.kpid_att[1].component_mul(&error_angular_velocity)
+            + self.kpid_att[2].component_mul(&self.integral_att_error)
+    }
+    /// Computes position control thrust and desired orientation
+    /// # Arguments
+    /// * `desired_position` - The desired position
+    /// * `desired_velocity` - The desired velocity
+    /// * `desired_yaw` - The desired yaw angle
+    /// * `current_position` - The current position
+    /// * `current_velocity` - The current velocity
+    /// * `dt` - Time step
+    /// * `mass` - Mass of the quadrotor
+    /// * `gravity` - Gravitational acceleration
+    /// # Returns
+    /// * A tuple containing the computed thrust and desired orientation quaternion
+    /// # Example
+    /// ```
+    /// use nalgebra::{UnitQuaternion, Vector3};
+    /// use peng_quad::PIDController;
+    ///
+    /// let kpid_pos = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
+    /// let kpid_att = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
+    /// let max_integral_pos = [1.0, 1.0, 1.0];
+    /// let max_integral_att = [1.0, 1.0, 1.0];
+    /// let mass = 1.0;
+    /// let gravity = 9.81;
+    /// let mut pid = PIDController::new(kpid_pos, kpid_att, max_integral_pos, max_integral_att, mass, gravity);
+    /// let desired_position = Vector3::new(0.0, 0.0, 1.0);
+    /// let desired_velocity = Vector3::zeros();
+    /// let desired_yaw = 0.0;
+    /// let current_position = Vector3::zeros();
+    /// let current_velocity = Vector3::zeros();
+    /// let dt = 0.01;
+    /// let (thrust, desired_orientation) = pid.compute_position_control(&desired_position, &desired_velocity, desired_yaw, &current_position, &current_velocity, dt);
+    /// ```
+    pub fn compute_position_control(
+        &mut self,
+        desired_position: &Vector3<f32>,
+        desired_velocity: &Vector3<f32>,
+        desired_yaw: f32,
+        current_position: &Vector3<f32>,
+        current_velocity: &Vector3<f32>,
+        dt: f32,
+    ) -> (f32, UnitQuaternion<f32>) {
+        let error_position = desired_position - current_position;
+        let error_velocity = desired_velocity - current_velocity;
+        self.integral_pos_error += error_position * dt;
+        self.integral_pos_error = self
+            .integral_pos_error
+            .zip_map(&self.max_integral_pos, |int, max| int.clamp(-max, max));
+        let acceleration = self.kpid_pos[0].component_mul(&error_position)
+            + self.kpid_pos[1].component_mul(&error_velocity)
+            + self.kpid_pos[2].component_mul(&self.integral_pos_error);
+        let gravity_compensation = Vector3::new(0.0, 0.0, self.gravity);
+        let total_acceleration = acceleration + gravity_compensation;
+        let thrust = self.mass * total_acceleration.norm();
+        let desired_orientation = if total_acceleration.norm() > 1e-6 {
+            let z_body = total_acceleration.normalize();
+            let yaw_rotation = UnitQuaternion::from_euler_angles(0.0, 0.0, desired_yaw);
+            let x_body_horizontal = yaw_rotation * Vector3::new(1.0, 0.0, 0.0);
+            let y_body = z_body.cross(&x_body_horizontal).normalize();
+            let x_body = y_body.cross(&z_body);
+            UnitQuaternion::from_rotation_matrix(&Rotation3::from_matrix_unchecked(
+                Matrix3::from_columns(&[x_body, y_body, z_body]),
+            ))
+        } else {
+            UnitQuaternion::from_euler_angles(0.0, 0.0, desired_yaw)
+        };
+        (thrust, desired_orientation)
+    }
+}
+/// Enum representing different types of trajectory planners
+/// # Example
+/// ```
+/// use peng_quad::PlannerType;
+/// use peng_quad::HoverPlanner;
+/// let hover_planner : PlannerType = PlannerType::Hover(HoverPlanner{
+///     target_position: nalgebra::Vector3::new(0.0, 0.0, 1.0),
+///     target_yaw: 0.0,
+/// });
+/// ```
+pub enum PlannerType {
+    /// Hover planner
+    Hover(HoverPlanner),
+    /// Minimum jerk line planner
+    MinimumJerkLine(MinimumJerkLinePlanner),
+    /// Minimum jerk circle planner
+    Lissajous(LissajousPlanner),
+    /// Minimum jerk circle planner
+    Circle(CirclePlanner),
+    /// Minimum jerk landing planner
+    Landing(LandingPlanner),
+    /// Obstacle avoidance planner
+    ObstacleAvoidance(ObstacleAvoidancePlanner),
+    /// Minimum snap waypoint planner
+    MinimumSnapWaypoint(MinimumSnapWaypointPlanner),
+}
+/// Implementation of the planner type
+impl PlannerType {
+    /// Plans the trajectory based on the current planner type
+    /// # Arguments
+    /// * `current_position` - The current position of the quadrotor
+    /// * `current_velocity` - The current velocity of the quadrotor
+    /// * `time` - The current simulation time
+    /// # Returns
+    /// * A tuple containing the desired position, velocity, and yaw angle
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::PlannerType;
+    /// use peng_quad::HoverPlanner;
+    /// let hover_planner = HoverPlanner {
+    ///     target_position: Vector3::new(0.0, 0.0, 1.0),
+    ///     target_yaw: 0.0
+    /// };
+    /// let hover_planner_type = PlannerType::Hover(hover_planner);
+    /// let (desired_position, desired_velocity, desired_yaw) = hover_planner_type.plan(Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 0.0);
+    /// ```
+    pub fn plan(
+        &self,
+        current_position: Vector3<f32>,
+        current_velocity: Vector3<f32>,
+        time: f32,
+    ) -> (Vector3<f32>, Vector3<f32>, f32) {
+        match self {
+            PlannerType::Hover(p) => p.plan(current_position, current_velocity, time),
+            PlannerType::MinimumJerkLine(p) => p.plan(current_position, current_velocity, time),
+            PlannerType::Lissajous(p) => p.plan(current_position, current_velocity, time),
+            PlannerType::Circle(p) => p.plan(current_position, current_velocity, time),
+            PlannerType::Landing(p) => p.plan(current_position, current_velocity, time),
+            PlannerType::ObstacleAvoidance(p) => p.plan(current_position, current_velocity, time),
+            PlannerType::MinimumSnapWaypoint(p) => p.plan(current_position, current_velocity, time),
+        }
+    }
+    /// Checks if the current trajectory is finished
+    /// # Arguments
+    /// * `current_position` - The current position of the quadrotor
+    /// * `time` - The current simulation time
+    /// # Returns
+    /// * `true` if the trajectory is finished, `false` otherwise
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::PlannerType;
+    /// use peng_quad::HoverPlanner;
+    /// use peng_quad::Planner;
+    /// let hover_planner = HoverPlanner{
+    ///     target_position: Vector3::new(0.0, 0.0, 1.0),
+    ///     target_yaw: 0.0,
+    /// };
+    /// let is_finished = hover_planner.is_finished(Vector3::new(0.0, 0.0, 0.0), 0.0);
+    /// ```
+    pub fn is_finished(
+        &self,
+        current_position: Vector3<f32>,
+        time: f32,
+    ) -> Result<bool, SimulationError> {
+        match self {
+            PlannerType::Hover(p) => p.is_finished(current_position, time),
+            PlannerType::MinimumJerkLine(p) => p.is_finished(current_position, time),
+            PlannerType::Lissajous(p) => p.is_finished(current_position, time),
+            PlannerType::Circle(p) => p.is_finished(current_position, time),
+            PlannerType::Landing(p) => p.is_finished(current_position, time),
+            PlannerType::ObstacleAvoidance(p) => p.is_finished(current_position, time),
+            PlannerType::MinimumSnapWaypoint(p) => p.is_finished(current_position, time),
+        }
+    }
+}
+/// Trait defining the interface for trajectory planners
+/// # Example
+/// ```
+/// use nalgebra::Vector3;
+/// use peng_quad::{Planner, SimulationError};
+/// struct TestPlanner;
+/// impl Planner for TestPlanner {
+///    fn plan(
+///         &self,
+///         current_position: Vector3<f32>,
+///         current_velocity: Vector3<f32>,
+///         time: f32,
+/// ) -> (Vector3<f32>, Vector3<f32>, f32) {
+///         (Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 0.0)
+///     }
+///     fn is_finished(
+///         &self,
+///         current_position: Vector3<f32>,
+///         time: f32,
+///     ) -> Result<bool, SimulationError> {
+///         Ok(true)
+///     }
+/// }
+/// ```
+pub trait Planner {
+    /// Plans the trajectory based on the current state and time
+    /// # Arguments
+    /// * `current_position` - The current position of the quadrotor
+    /// * `current_velocity` - The current velocity of the quadrotor
+    /// * `time` - The current simulation time
+    /// # Returns
+    /// * A tuple containing the desired position, velocity, and yaw angle
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::{Planner, SimulationError};
+    /// struct TestPlanner;
+    /// impl Planner for TestPlanner {
+    ///     fn plan(
+    ///         &self,
+    ///         current_position: Vector3<f32>,
+    ///         current_velocity: Vector3<f32>,
+    ///         time: f32,
+    /// ) -> (Vector3<f32>, Vector3<f32>, f32) {
+    ///         (Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 0.0)
+    ///     }
+    ///     fn is_finished(
+    ///         &self,
+    ///         current_position: Vector3<f32>,
+    ///         time: f32,
+    ///     ) -> Result<bool, SimulationError> {
+    ///         Ok(true)
+    ///     }
+    /// }
+    /// ```
+    fn plan(
+        &self,
+        current_position: Vector3<f32>,
+        current_velocity: Vector3<f32>,
+        time: f32,
+    ) -> (Vector3<f32>, Vector3<f32>, f32);
+    /// Checks if the current trajectory is finished
+    /// # Arguments
+    /// * `current_position` - The current position of the quadrotor
+    /// * `time` - The current simulation time
+    /// # Returns
+    /// * `true` if the trajectory is finished, `false` otherwise
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::{Planner, SimulationError};
+    /// struct TestPlanner;
+    /// impl Planner for TestPlanner {
+    ///     fn plan(
+    ///         &self,
+    ///         current_position: Vector3<f32>,
+    ///         current_velocity: Vector3<f32>,
+    ///         time: f32,
+    /// ) -> (Vector3<f32>, Vector3<f32>, f32) {
+    ///         (Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 0.0)
+    ///     }
+    ///     fn is_finished(
+    ///         &self,
+    ///         current_position: Vector3<f32>,
+    ///         time: f32,
+    ///     ) -> Result<bool, SimulationError> {
+    ///         Ok(true)
+    ///     }
+    /// }
+    /// ```
+    fn is_finished(
+        &self,
+        current_position: Vector3<f32>,
+        time: f32,
+    ) -> Result<bool, SimulationError>;
+}
+/// Planner for hovering at a fixed position
+/// # Example
+/// ```
+/// use nalgebra::Vector3;
+/// use peng_quad::HoverPlanner;
+/// let hover_planner = HoverPlanner {
+///     target_position: Vector3::new(0.0, 0.0, 0.0),
+///     target_yaw: 0.0,
+/// };
+/// ```
+pub struct HoverPlanner {
+    /// Target position for hovering
+    pub target_position: Vector3<f32>,
+    /// Target yaw angle for hovering
+    pub target_yaw: f32,
+}
+/// Implementation of the `Planner` trait for the `HoverPlanner`
+impl Planner for HoverPlanner {
+    fn plan(
+        &self,
+        _current_position: Vector3<f32>,
+        _current_velocity: Vector3<f32>,
+        _time: f32,
+    ) -> (Vector3<f32>, Vector3<f32>, f32) {
+        (self.target_position, Vector3::zeros(), self.target_yaw)
+    }
+
+    fn is_finished(
+        &self,
+        _current_position: Vector3<f32>,
+        _time: f32,
+    ) -> Result<bool, SimulationError> {
+        Ok(false) // Hover planner never "finished"
+    }
+}
+/// Planner for minimum jerk trajectories along a straight line
+/// # Example
+/// ```
+/// use nalgebra::Vector3;
+/// use peng_quad::MinimumJerkLinePlanner;
+/// let minimum_jerk_line_planner = MinimumJerkLinePlanner {
+///     start_position: Vector3::new(0.0, 0.0, 0.0),
+///     end_position: Vector3::new(1.0, 1.0, 1.0),
+///     start_yaw: 0.0,
+///     end_yaw: 0.0,
+///     start_time: 0.0,
+///     duration: 1.0,
+/// };
+/// ```
+pub struct MinimumJerkLinePlanner {
+    /// Starting position of the trajectory
+    pub start_position: Vector3<f32>,
+    /// Ending position of the trajectory
+    pub end_position: Vector3<f32>,
+    /// Starting yaw angle
+    pub start_yaw: f32,
+    /// Ending yaw angle
+    pub end_yaw: f32,
+    /// Start time of the trajectory
+    pub start_time: f32,
+    /// Duration of the trajectory
+    pub duration: f32,
+}
+/// Implementation of the planner trait for minimum jerk line planner
+impl Planner for MinimumJerkLinePlanner {
+    fn plan(
+        &self,
+        _current_position: Vector3<f32>,
+        _current_velocity: Vector3<f32>,
+        time: f32,
+    ) -> (Vector3<f32>, Vector3<f32>, f32) {
+        let t = ((time - self.start_time) / self.duration).clamp(0.0, 1.0);
+        let s = 10.0 * t.powi(3) - 15.0 * t.powi(4) + 6.0 * t.powi(5);
+        let s_dot = (30.0 * t.powi(2) - 60.0 * t.powi(3) + 30.0 * t.powi(4)) / self.duration;
+        let position = self.start_position + (self.end_position - self.start_position) * s;
+        let velocity = (self.end_position - self.start_position) * s_dot;
+        let yaw = self.start_yaw + (self.end_yaw - self.start_yaw) * s;
+        (position, velocity, yaw)
+    }
+
+    fn is_finished(
+        &self,
+        _current_position: Vector3<f32>,
+        _time: f32,
+    ) -> Result<bool, SimulationError> {
+        Ok((_current_position - self.end_position).norm() < 0.01
+            && _time >= self.start_time + self.duration)
+    }
+}
+/// Planner for Lissajous curve trajectories
+/// # Example
+/// ```
+/// use nalgebra::Vector3;
+/// use peng_quad::LissajousPlanner;
+/// let lissajous_planner = LissajousPlanner {
+///     start_position: Vector3::new(0.0, 0.0, 0.0),
+///     center: Vector3::new(1.0, 1.0, 1.0),
+///     amplitude: Vector3::new(1.0, 1.0, 1.0),
+///     frequency: Vector3::new(1.0, 1.0, 1.0),
+///     phase: Vector3::new(0.0, 0.0, 0.0),
+///     start_time: 0.0,
+///     duration: 1.0,
+///     start_yaw: 0.0,
+///     end_yaw: 0.0,
+///     ramp_time: 0.1,
+/// };
+/// ```
+pub struct LissajousPlanner {
+    /// Starting position of the trajectory
+    pub start_position: Vector3<f32>,
+    /// Center of the Lissajous curve
+    pub center: Vector3<f32>,
+    /// Amplitude of the Lissajous curve
+    pub amplitude: Vector3<f32>,
+    /// Frequency of the Lissajous curve
+    pub frequency: Vector3<f32>,
+    /// Phase of the Lissajous curve
+    pub phase: Vector3<f32>,
+    /// Start time of the trajectory
+    pub start_time: f32,
+    /// Duration of the trajectory
+    pub duration: f32,
+    /// Starting yaw angle
+    pub start_yaw: f32,
+    /// Ending yaw angle
+    pub end_yaw: f32,
+    /// Ramp-up time for smooth transitions
+    pub ramp_time: f32,
+}
+/// Implementation of the planner trait for Lissajous curve trajectories
+impl Planner for LissajousPlanner {
+    fn plan(
+        &self,
+        _current_position: Vector3<f32>,
+        _current_velocity: Vector3<f32>,
+        time: f32,
+    ) -> (Vector3<f32>, Vector3<f32>, f32) {
+        let t = ((time - self.start_time) / self.duration).clamp(0.0, 1.0);
+        let smooth_start = if t < self.ramp_time / self.duration {
+            let t_ramp = t / (self.ramp_time / self.duration);
+            t_ramp * t_ramp * (3.0 - 2.0 * t_ramp)
+        } else {
+            1.0
+        };
+        let velocity_ramp = if t < self.ramp_time / self.duration {
+            smooth_start
+        } else if t > 1.0 - self.ramp_time / self.duration {
+            let t_down = (1.0 - t) / (self.ramp_time / self.duration);
+            t_down * t_down * (3.0 - 2.0 * t_down)
+        } else {
+            1.0
+        };
+        let ang_pos = self.frequency * t * 2.0 * PI + self.phase;
+        let lissajous = self.amplitude.component_mul(&ang_pos.map(f32::sin));
+        let position =
+            self.start_position + smooth_start * ((self.center + lissajous) - self.start_position);
+        let mut velocity = Vector3::new(
+            self.amplitude.x * self.frequency.x * 2.0 * PI * ang_pos.x.cos(),
+            self.amplitude.y * self.frequency.y * 2.0 * PI * ang_pos.y.cos(),
+            self.amplitude.z * self.frequency.z * 2.0 * PI * ang_pos.z.cos(),
+        ) * velocity_ramp
+            / self.duration;
+        if t < self.ramp_time / self.duration {
+            let transition_velocity = (self.center - self.start_position)
+                * (2.0 * t / self.ramp_time - 2.0 * t * t / (self.ramp_time * self.ramp_time))
+                / self.duration;
+            velocity += transition_velocity;
+        }
+        let yaw = self.start_yaw + (self.end_yaw - self.start_yaw) * t;
+        (position, velocity, yaw)
+    }
+
+    fn is_finished(
+        &self,
+        _current_position: Vector3<f32>,
+        time: f32,
+    ) -> Result<bool, SimulationError> {
+        Ok(time >= self.start_time + self.duration)
+    }
+}
+/// Planner for circular trajectories
+/// # Example
+/// ```
+/// use nalgebra::Vector3;
+/// use peng_quad::CirclePlanner;
+/// let circle_planner = CirclePlanner {
+///     center: Vector3::new(1.0, 1.0, 1.0),
+///     radius: 1.0,
+///     angular_velocity: 1.0,
+///     start_position: Vector3::new(0.0, 0.0, 0.0),
+///     start_time: 0.0,
+///     duration: 1.0,
+///     start_yaw: 0.0,
+///     end_yaw: 0.0,
+///     ramp_time: 0.1,
+/// };
+/// ```
+pub struct CirclePlanner {
+    /// Center of the circular trajectory
+    pub center: Vector3<f32>,
+    /// Radius of the circular trajectory
+    pub radius: f32,
+    /// Angular velocity of the circular motion
+    pub angular_velocity: f32,
+    /// Starting position of the trajectory
+    pub start_position: Vector3<f32>,
+    /// Start time of the trajectory
+    pub start_time: f32,
+    /// Duration of the trajectory
+    pub duration: f32,
+    /// Starting yaw angle
+    pub start_yaw: f32,
+    /// Ending yaw angle
+    pub end_yaw: f32,
+    /// Ramp-up time for smooth transitions
+    pub ramp_time: f32,
+}
+/// Implementation of the Planner trait for CirclePlanner
+impl Planner for CirclePlanner {
+    fn plan(
+        &self,
+        _current_position: Vector3<f32>,
+        _current_velocity: Vector3<f32>,
+        time: f32,
+    ) -> (Vector3<f32>, Vector3<f32>, f32) {
+        let t = (time - self.start_time) / self.duration;
+        let t = t.clamp(0.0, 1.0);
+        let smooth_start = if t < self.ramp_time / self.duration {
+            let t_ramp = t / (self.ramp_time / self.duration);
+            t_ramp * t_ramp * (3.0 - 2.0 * t_ramp)
+        } else {
+            1.0
+        };
+        let velocity_ramp = if t < self.ramp_time / self.duration {
+            smooth_start
+        } else if t > 1.0 - self.ramp_time / self.duration {
+            let t_down = (1.0 - t) / (self.ramp_time / self.duration);
+            t_down * t_down * (3.0 - 2.0 * t_down)
+        } else {
+            1.0
+        };
+        let angle = self.angular_velocity * t * self.duration;
+        let circle_offset = Vector3::new(self.radius * angle.cos(), self.radius * angle.sin(), 0.0);
+        let position = self.start_position
+            + smooth_start * ((self.center + circle_offset) - self.start_position);
+        let tangential_velocity = Vector3::new(
+            -self.radius * self.angular_velocity * angle.sin(),
+            self.radius * self.angular_velocity * angle.cos(),
+            0.0,
+        );
+        let velocity = tangential_velocity * velocity_ramp;
+        let yaw = self.start_yaw + (self.end_yaw - self.start_yaw) * t;
+        (position, velocity, yaw)
+    }
+
+    fn is_finished(
+        &self,
+        _current_position: Vector3<f32>,
+        time: f32,
+    ) -> Result<bool, SimulationError> {
+        Ok(time >= self.start_time + self.duration)
+    }
+}
+/// Planner for landing maneuvers
+/// # Example
+/// ```
+/// use nalgebra::Vector3;
+/// use peng_quad::LandingPlanner;
+/// let landing_planner = LandingPlanner {
+///    start_position: Vector3::new(0.0, 0.0, 1.0),
+///     start_time: 0.0,
+///     duration: 1.0,
+///     start_yaw: 0.0,
+/// };
+/// ```
+pub struct LandingPlanner {
+    /// Starting position of the landing maneuver
+    pub start_position: Vector3<f32>,
+    /// Start time of the landing maneuver
+    pub start_time: f32,
+    /// Duration of the landing maneuver
+    pub duration: f32,
+    /// Starting yaw angle
+    pub start_yaw: f32,
+}
+/// Implementation of the Planner trait for LandingPlanner
+impl Planner for LandingPlanner {
+    fn plan(
+        &self,
+        _current_position: Vector3<f32>,
+        _current_velocity: Vector3<f32>,
+        time: f32,
+    ) -> (Vector3<f32>, Vector3<f32>, f32) {
+        let t = ((time - self.start_time) / self.duration).clamp(0.0, 1.0);
+        let target_z = self.start_position.z * (1.0 - t);
+        let target_position = Vector3::new(self.start_position.x, self.start_position.y, target_z);
+        let target_velocity = Vector3::new(0.0, 0.0, -self.start_position.z / self.duration);
+        (target_position, target_velocity, self.start_yaw)
+    }
+
+    fn is_finished(
+        &self,
+        current_position: Vector3<f32>,
+        time: f32,
+    ) -> Result<bool, SimulationError> {
+        Ok(current_position.z < 0.05 || time >= self.start_time + self.duration)
+    }
+}
+/// Manages different trajectory planners and switches between them
+/// # Example
+/// ```
+/// use nalgebra::Vector3;
+/// use peng_quad::PlannerManager;
+/// let initial_position = Vector3::new(0.0, 0.0, 1.0);
+/// let initial_yaw = 0.0;
+/// let planner_manager = PlannerManager::new(initial_position, initial_yaw);
+/// ```
+pub struct PlannerManager {
+    /// The current planner
+    pub current_planner: PlannerType,
+}
+/// Implementation of the PlannerManager
+impl PlannerManager {
+    /// Creates a new PlannerManager with an initial hover planner
+    /// # Arguments
+    /// * `initial_position` - The initial position for hovering
+    /// * `initial_yaw` - The initial yaw angle for hovering
+    /// # Returns
+    /// * A new PlannerManager instance
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::PlannerManager;
+    /// let initial_position = Vector3::new(0.0, 0.0, 1.0);
+    /// let initial_yaw = 0.0;
+    /// let planner_manager = PlannerManager::new(initial_position, initial_yaw);
+    /// ```
+    pub fn new(initial_position: Vector3<f32>, initial_yaw: f32) -> Self {
+        let hover_planner = HoverPlanner {
+            target_position: initial_position,
+            target_yaw: initial_yaw,
+        };
+        Self {
+            current_planner: PlannerType::Hover(hover_planner),
+        }
+    }
+    /// Sets a new planner
+    /// # Arguments
+    /// * `new_planner` - The new planner to be set
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::{PlannerManager, CirclePlanner, PlannerType};
+    /// let initial_position = Vector3::new(0.0, 0.0, 1.0);
+    /// let initial_yaw = 0.0;
+    /// let mut planner_manager = PlannerManager::new(initial_position, initial_yaw);
+    /// let new_planner = CirclePlanner {
+    ///     center: Vector3::new(0.0, 0.0, 1.0),
+    ///     radius: 1.0,
+    ///     angular_velocity: 1.0,
+    ///     start_yaw: 0.0,
+    ///     end_yaw: 0.0,
+    ///     start_time: 0.0,
+    ///     duration: 10.0,
+    ///     ramp_time: 1.0,
+    ///     start_position: Vector3::new(0.0, 0.0, 1.0),
+    /// };
+    /// planner_manager.set_planner(PlannerType::Circle(new_planner));
+    /// ```
+    pub fn set_planner(&mut self, new_planner: PlannerType) {
+        self.current_planner = new_planner;
+    }
+    /// Updates the current planner and returns the desired position, velocity, and yaw
+    /// # Arguments
+    /// * `current_position` - The current position of the quadrotor
+    /// * `current_orientation` - The current orientation of the quadrotor
+    /// * `current_velocity` - The current velocity of the quadrotor
+    /// * `time` - The current simulation time
+    /// # Returns
+    /// * A tuple containing the desired position, velocity, and yaw angle
+    /// # Errors
+    /// * Returns a SimulationError if the current planner is not finished
+    /// # Example
+    /// ```
+    /// use nalgebra::{Vector3, UnitQuaternion};
+    /// use peng_quad::{PlannerManager, SimulationError};
+    /// let initial_position = Vector3::new(0.0, 0.0, 1.0);
+    /// let initial_yaw = 0.0;
+    /// let mut planner_manager = PlannerManager::new(initial_position, initial_yaw);
+    /// let current_position = Vector3::new(0.0, 0.0, 1.0);
+    /// let current_orientation = UnitQuaternion::from_euler_angles(0.0, 0.0, 0.0);
+    /// let current_velocity = Vector3::new(0.0, 0.0, 0.0);
+    /// let obstacles = vec![];
+    /// let time = 0.0;
+    /// let result = planner_manager.update(current_position, current_orientation, current_velocity, time, &obstacles);
+    /// match result {
+    ///     Ok((target_position, target_velocity, target_yaw)) => {
+    ///         println!("Target Position: {:?}", target_position);
+    ///         println!("Target Velocity: {:?}", target_velocity);
+    ///         println!("Target Yaw: {:?}", target_yaw);
+    ///     }
+    ///     Err(SimulationError) => {
+    ///         log::error!("Error: Planner is not finished");
+    ///     }
+    /// }
+    /// ```
+    pub fn update(
+        &mut self,
+        current_position: Vector3<f32>,
+        current_orientation: UnitQuaternion<f32>,
+        current_velocity: Vector3<f32>,
+        time: f32,
+        obstacles: &[Obstacle],
+    ) -> Result<(Vector3<f32>, Vector3<f32>, f32), SimulationError> {
+        if self.current_planner.is_finished(current_position, time)? {
+            log::info!("Time: {:.2} s,\tSwitch Hover", time);
+            self.current_planner = PlannerType::Hover(HoverPlanner {
+                target_position: current_position,
+                target_yaw: current_orientation.euler_angles().2,
+            });
+        }
+        // Update obstacles for ObstacleAvoidancePlanner if needed
+        if let PlannerType::ObstacleAvoidance(ref mut planner) = self.current_planner {
+            planner.obstacles = obstacles.to_owned();
+        }
+        Ok(self
+            .current_planner
+            .plan(current_position, current_velocity, time))
+    }
+}
+/// Obstacle avoidance planner that uses a potential field approach to avoid obstacles
+/// The planner calculates a repulsive force for each obstacle and an attractive force towards the goal
+/// The resulting force is then used to calculate the desired position and velocity
+/// # Example
+/// ```
+/// use nalgebra::Vector3;
+/// use peng_quad::{ObstacleAvoidancePlanner, Obstacle};
+/// let planner = ObstacleAvoidancePlanner {
+///     target_position: Vector3::new(0.0, 0.0, 1.0),
+///     start_time: 0.0,
+///     duration: 10.0,
+///     start_yaw: 0.0,
+///     end_yaw: 0.0,
+///     obstacles: vec![Obstacle {
+///         position: Vector3::new(1.0, 0.0, 1.0),
+///         velocity: Vector3::new(0.0, 0.0, 0.0),
+///         radius: 0.5,
+///     }],
+///     k_att: 1.0,
+///     k_rep: 1.0,
+///     k_vortex: 1.0,
+///     d0: 1.0,
+///     d_target: 1.0,
+///     max_speed: 1.0,
+/// };
+/// ```
+pub struct ObstacleAvoidancePlanner {
+    /// Target position of the planner
+    pub target_position: Vector3<f32>,
+    /// Start time of the planner
+    pub start_time: f32,
+    /// Duration of the planner
+    pub duration: f32,
+    /// Starting yaw angle
+    pub start_yaw: f32,
+    /// Ending yaw angle
+    pub end_yaw: f32,
+    /// List of obstacles
+    pub obstacles: Vec<Obstacle>,
+    /// Attractive force gain
+    pub k_att: f32,
+    /// Repulsive force gain
+    pub k_rep: f32,
+    /// Vortex force gain
+    pub k_vortex: f32,
+    /// Influence distance of obstacles
+    pub d0: f32,
+    /// Influence distance of target
+    pub d_target: f32,
+    /// Maximum speed of the quadrotor
+    pub max_speed: f32,
+}
+/// Implementation of the Planner trait for ObstacleAvoidancePlanner
+impl Planner for ObstacleAvoidancePlanner {
+    fn plan(
+        &self,
+        current_position: Vector3<f32>,
+        current_velocity: Vector3<f32>,
+        time: f32,
+    ) -> (Vector3<f32>, Vector3<f32>, f32) {
+        let t = ((time - self.start_time) / self.duration).clamp(0.0, 1.0);
+        let distance_to_target = (self.target_position - current_position).norm();
+        let f_att = self.k_att
+            * self.smooth_attractive_force(distance_to_target)
+            * (self.target_position - current_position).normalize();
+        // Repulsive force from obstacles
+        let mut f_rep = Vector3::zeros();
+        let mut f_vortex = Vector3::zeros();
+        for obstacle in &self.obstacles {
+            let diff = current_position - obstacle.position;
+            let distance = diff.norm();
+            if distance < self.d0 {
+                f_rep += self.k_rep
+                    * (1.0 / distance - 1.0 / self.d0)
+                    * (1.0 / distance.powi(2))
+                    * diff.normalize();
+                f_vortex +=
+                    self.k_vortex * current_velocity.cross(&diff).normalize() / distance.powi(2);
+            }
+        }
+        let f_total = f_att + f_rep + f_vortex;
+        let desired_velocity = f_total.normalize() * self.max_speed.min(f_total.norm());
+        let desired_position = current_position + desired_velocity * self.duration * (1.0 - t);
+        let desired_yaw = self.start_yaw + (self.end_yaw - self.start_yaw) * t;
+        (desired_position, desired_velocity, desired_yaw)
+    }
+
+    fn is_finished(
+        &self,
+        current_position: Vector3<f32>,
+        time: f32,
+    ) -> Result<bool, SimulationError> {
+        Ok((current_position - self.target_position).norm() < 0.1
+            && time >= self.start_time + self.duration)
+    }
+}
+/// Implementation of the ObstacleAvoidancePlanner
+impl ObstacleAvoidancePlanner {
+    /// A smooth attractive force function that transitions from linear to exponential decay
+    /// When the distance to the target is less than the target distance, the force is linear
+    /// When the distance is greater, the force decays exponentially
+    /// # Arguments
+    /// * `distance` - The distance to the target
+    /// # Returns
+    /// * The attractive force
+    /// # Example
+    /// ```
+    /// use peng_quad::ObstacleAvoidancePlanner;
+    /// let planner = ObstacleAvoidancePlanner {
+    ///    target_position: nalgebra::Vector3::new(0.0, 0.0, 1.0),
+    ///     start_time: 0.0,
+    ///     duration: 10.0,
+    ///     start_yaw: 0.0,
+    ///     end_yaw: 0.0,
+    ///     obstacles: vec![],
+    ///     k_att: 1.0,
+    ///     k_rep: 1.0,
+    ///     k_vortex: 1.0,
+    ///     d0: 1.0,
+    ///     d_target: 1.0,
+    ///     max_speed: 1.0,
+    /// };
+    /// let distance = 1.0;
+    /// let force = planner.smooth_attractive_force(distance);
+    /// ```
+    #[inline]
+    pub fn smooth_attractive_force(&self, distance: f32) -> f32 {
+        if distance <= self.d_target {
+            distance
+        } else {
+            self.d_target + (distance - self.d_target).tanh()
+        }
+    }
+}
+/// Waypoint planner that generates a minimum snap trajectory between waypoints
+/// # Example
+/// ```
+/// use peng_quad::MinimumSnapWaypointPlanner;
+/// use nalgebra::Vector3;
+/// let planner = MinimumSnapWaypointPlanner::new(
+///     vec![Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 0.0, 0.0)],
+///     vec![0.0, 0.0],
+///     vec![1.0],
+///     0.0,
+/// );
+/// ```
+pub struct MinimumSnapWaypointPlanner {
+    /// List of waypoints
+    pub waypoints: Vec<Vector3<f32>>,
+    /// List of yaw angles
+    pub yaws: Vec<f32>,
+    /// List of segment times to reach each waypoint
+    pub times: Vec<f32>,
+    /// Coefficients for the x, y, and z components of the trajectory
+    pub coefficients: Vec<Vec<Vector3<f32>>>,
+    /// Coefficients for the yaw component of the trajectory
+    pub yaw_coefficients: Vec<Vec<f32>>,
+    /// Start time of the trajectory
+    pub start_time: f32,
+}
+/// Implementation of the MinimumSnapWaypointPlanner
+impl MinimumSnapWaypointPlanner {
+    /// Generate a new minimum snap waypoint planner
+    /// # Arguments
+    /// * `waypoints` - List of waypoints
+    /// * `yaws` - List of yaw angles
+    /// * `segment_times` - List of segment times to reach each waypoint
+    /// * `start_time` - Start time of the trajectory
+    /// # Returns
+    /// * A new minimum snap waypoint planner
+    /// # Errors
+    /// * Returns an error if the number of waypoints, yaws, and segment times do not match
+    /// # Example
+    /// ```
+    /// use peng_quad::MinimumSnapWaypointPlanner;
+    /// use nalgebra::Vector3;
+    /// let waypoints = vec![Vector3::zeros(), Vector3::new(1.0, 0.0, 0.0)];
+    /// let yaws = vec![0.0, 0.0];
+    /// let segment_times = vec![1.0];
+    /// let start_time = 0.0;
+    /// let planner = MinimumSnapWaypointPlanner::new(waypoints, yaws, segment_times, start_time);
+    /// ```
+    pub fn new(
+        waypoints: Vec<Vector3<f32>>,
+        yaws: Vec<f32>,
+        segment_times: Vec<f32>,
+        start_time: f32,
+    ) -> Result<Self, SimulationError> {
+        if waypoints.len() < 2 {
+            return Err(SimulationError::OtherError(
+                "At least two waypoints are required".to_string(),
+            ));
+        }
+        if waypoints.len() != segment_times.len() + 1 || waypoints.len() != yaws.len() {
+            return Err(SimulationError::OtherError("Number of segment times must be one less than number of waypoints, and yaws must match waypoints".to_string()));
+        }
+        let mut planner = Self {
+            waypoints,
+            yaws,
+            times: segment_times,
+            coefficients: Vec::new(),
+            yaw_coefficients: Vec::new(),
+            start_time,
+        };
+        planner.compute_minimum_snap_trajectories()?;
+        planner.compute_minimum_acceleration_yaw_trajectories()?;
+        Ok(planner)
+    }
+    /// Compute the coefficients for the minimum snap trajectory, calculated for each segment between waypoints
+    /// # Errors
+    /// * Returns an error if the nalgebra solver fails to solve the linear system
+    /// # Example
+    /// ```
+    /// use peng_quad::MinimumSnapWaypointPlanner;
+    /// use nalgebra::Vector3;
+    /// let waypoints = vec![Vector3::zeros(), Vector3::new(1.0, 0.0, 0.0)];
+    /// let yaws = vec![0.0, 0.0];
+    /// let segment_times = vec![1.0];
+    /// let start_time = 0.0;
+    /// let mut planner = MinimumSnapWaypointPlanner::new(waypoints, yaws, segment_times, start_time).unwrap();
+    /// planner.compute_minimum_snap_trajectories();
+    /// ```
+    pub fn compute_minimum_snap_trajectories(&mut self) -> Result<(), SimulationError> {
+        let n = self.waypoints.len() - 1;
+        for i in 0..n {
+            let duration = self.times[i];
+            let (start, end) = (self.waypoints[i], self.waypoints[i + 1]);
+            let mut a = SMatrix::<f32, 8, 8>::zeros();
+            let mut b = SMatrix::<f32, 8, 3>::zeros();
+            a.fixed_view_mut::<4, 4>(0, 0).fill_with_identity();
+            b.fixed_view_mut::<1, 3>(0, 0).copy_from(&start.transpose());
+            b.fixed_view_mut::<1, 3>(4, 0).copy_from(&end.transpose());
+            // End point constraints
+            for j in 0..8 {
+                a[(4, j)] = duration.powi(j as i32);
+                if j > 0 {
+                    a[(5, j)] = j as f32 * duration.powi(j as i32 - 1);
+                }
+                if j > 1 {
+                    a[(6, j)] = j as f32 * (j - 1) as f32 * duration.powi(j as i32 - 2);
+                }
+                if j > 2 {
+                    a[(7, j)] =
+                        j as f32 * (j - 1) as f32 * (j - 2) as f32 * duration.powi(j as i32 - 3);
+                }
+            }
+            let coeffs = a.lu().solve(&b).ok_or(SimulationError::NalgebraError(
+                "Failed to solve for coefficients in MinimumSnapWaypointPlanner".to_string(),
+            ))?;
+            self.coefficients.push(
+                (0..8)
+                    .map(|j| Vector3::new(coeffs[(j, 0)], coeffs[(j, 1)], coeffs[(j, 2)]))
+                    .collect(),
+            );
+        }
+        Ok(())
+    }
+    /// Compute the coefficients for yaw trajectories
+    /// The yaw trajectory is a cubic polynomial and interpolated between waypoints
+    /// # Errors
+    /// * Returns an error if nalgebra fails to solve for the coefficients
+    /// # Example
+    /// ```
+    /// use peng_quad::MinimumSnapWaypointPlanner;
+    /// use nalgebra::Vector3;
+    /// let waypoints = vec![Vector3::zeros(), Vector3::new(1.0, 0.0, 0.0)];
+    /// let yaws = vec![0.0, 0.0];
+    /// let segment_times = vec![1.0];
+    /// let start_time = 0.0;
+    /// let mut planner = MinimumSnapWaypointPlanner::new(waypoints, yaws, segment_times, start_time).unwrap();
+    /// planner.compute_minimum_snap_trajectories();
+    /// planner.compute_minimum_acceleration_yaw_trajectories();
+    /// ```
+    pub fn compute_minimum_acceleration_yaw_trajectories(&mut self) -> Result<(), SimulationError> {
+        let n = self.yaws.len() - 1; // Number of segments
+        for i in 0..n {
+            let (duration, start_yaw, end_yaw) = (self.times[i], self.yaws[i], self.yaws[i + 1]);
+            let mut a = SMatrix::<f32, 4, 4>::zeros();
+            let mut b = SMatrix::<f32, 4, 1>::zeros();
+            (a[(0, 0)], a[(1, 1)]) = (1.0, 1.0);
+            (b[0], b[2]) = (start_yaw, end_yaw);
+            for j in 0..4 {
+                a[(2, j)] = duration.powi(j as i32);
+                if j > 0 {
+                    a[(3, j)] = j as f32 * duration.powi(j as i32 - 1);
+                }
+            }
+            let yaw_coeffs = a.lu().solve(&b).ok_or(SimulationError::NalgebraError(
+                "Failed to solve for yaw coefficients in MinimumSnapWaypointPlanner".to_string(),
+            ))?;
+            self.yaw_coefficients.push(yaw_coeffs.as_slice().to_vec());
+        }
+        Ok(())
+    }
+    /// Evaluate the trajectory at a given time, returns the position, velocity, yaw, and yaw rate at the given time
+    /// # Arguments
+    /// * `t` - The time to evaluate the trajectory at
+    /// * `coeffs` - The coefficients for the position trajectory
+    /// * `yaw_coeffs` - The coefficients for the yaw trajectory
+    /// # Returns
+    /// * `position` - The position at the given time (meters)
+    /// * `velocity` - The velocity at the given time (meters / second)
+    /// * `yaw` - The yaw at the given time (radians)
+    /// * `yaw_rate` - The yaw rate at the given time (radians / second)
+    /// # Example
+    /// ```
+    /// use nalgebra::Vector3;
+    /// use peng_quad::MinimumSnapWaypointPlanner;
+    /// let waypoints = vec![Vector3::zeros(), Vector3::new(1.0, 0.0, 0.0)];
+    /// let yaws = vec![0.0, 0.0];
+    /// let segment_times = vec![1.0];
+    /// let start_time = 0.0;
+    /// let mut planner = MinimumSnapWaypointPlanner::new(waypoints, yaws, segment_times, start_time).unwrap();
+    /// planner.compute_minimum_snap_trajectories();
+    /// planner.compute_minimum_acceleration_yaw_trajectories();
+    /// let (position, velocity, yaw, yaw_rate) = planner.evaluate_polynomial(0.5, &planner.coefficients[0], &planner.yaw_coefficients[0]);
+    /// ```
+    pub fn evaluate_polynomial(
+        &self,
+        t: f32,
+        coeffs: &[Vector3<f32>],
+        yaw_coeffs: &[f32],
+    ) -> (Vector3<f32>, Vector3<f32>, f32, f32) {
+        let mut position = Vector3::zeros();
+        let mut velocity = Vector3::zeros();
+        let mut yaw = 0.0;
+        let mut yaw_rate = 0.0;
+        for (i, coeff) in coeffs.iter().enumerate() {
+            let ti = t.powi(i as i32);
+            position += coeff * ti;
+            if i > 0 {
+                velocity += coeff * (i as f32) * t.powi(i as i32 - 1);
+            }
+        }
+        for (i, &coeff) in yaw_coeffs.iter().enumerate() {
+            let ti = t.powi(i as i32);
+            yaw += coeff * ti;
+            if i > 0 {
+                yaw_rate += coeff * (i as f32) * t.powi(i as i32 - 1);
+            }
+        }
+        (position, velocity, yaw, yaw_rate)
+    }
+}
+/// Implement the `Planner` trait for `MinimumSnapWaypointPlanner`
+impl Planner for MinimumSnapWaypointPlanner {
+    fn plan(
+        &self,
+        _current_position: Vector3<f32>,
+        _current_velocity: Vector3<f32>,
+        time: f32,
+    ) -> (Vector3<f32>, Vector3<f32>, f32) {
+        let relative_time = time - self.start_time;
+        // Find the current segment
+        let mut segment_start_time = 0.0;
+        let mut current_segment = 0;
+        for (i, &segment_duration) in self.times.iter().enumerate() {
+            if relative_time < segment_start_time + segment_duration {
+                current_segment = i;
+                break;
+            }
+            segment_start_time += segment_duration;
+        }
+        // Evaluate the polynomial for the current segment
+        let segment_time = relative_time - segment_start_time;
+        let (position, velocity, yaw, _yaw_rate) = self.evaluate_polynomial(
+            segment_time,
+            &self.coefficients[current_segment],
+            &self.yaw_coefficients[current_segment],
+        );
+        (position, velocity, yaw)
+    }
+
+    fn is_finished(
+        &self,
+        current_position: Vector3<f32>,
+        time: f32,
+    ) -> Result<bool, SimulationError> {
+        let last_waypoint = self.waypoints.last().ok_or(SimulationError::OtherError(
+            "No waypoints available".to_string(),
+        ))?;
+        Ok(time >= self.start_time + self.times.iter().sum::<f32>()
+            && (current_position - last_waypoint).norm() < 0.1)
+    }
+}
+/// Represents a step in the planner schedule.
+/// # Example
+/// ```
+/// use peng_quad::PlannerStepConfig;
+/// let step = PlannerStepConfig {
+///     step: 0,
+///     planner_type: "MinimumJerkLocalPlanner".to_string(),
+///     params: serde_yaml::Value::Null,
+/// };
+/// ```
+pub struct PlannerStepConfig {
+    /// The simulation step at which this planner should be activated (in ms unit).
+    pub step: usize,
+    /// The type of planner to use for this step.
+    pub planner_type: String,
+    /// Additional parameters for the planner, stored as a YAML value.
+    pub params: serde_yaml::Value,
+}
+/// Updates the planner based on the current simulation step and configuration
+/// # Arguments
+/// * `planner_manager` - The PlannerManager instance to update
+/// * `step` - The current simulation step in ms unit
+/// * `time` - The current simulation time
+/// * `simulation_frequency' - The simulation frequency in Hz
+/// * `quad` - The Quadrotor instance
+/// * `obstacles` - The current obstacles in the simulation
+/// * `planner_config` - The planner configuration
+/// # Errors
+/// * If the planner could not be created
+/// # Example
+/// ```
+/// use peng_quad::{PlannerManager, Quadrotor, Obstacle, PlannerStepConfig, update_planner};
+/// use nalgebra::Vector3;
+/// let simulation_frequency = 1000;
+/// let initial_position = Vector3::new(0.0, 0.0, 0.0);
+/// let initial_yaw = 0.0;
+/// let mut planner_manager = PlannerManager::new(initial_position, initial_yaw);
+/// let step = 0;
+/// let time = 0.0;
+/// let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+/// let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+/// let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+/// let obstacles = vec![Obstacle::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 1.0)];
+/// let planner_config = vec![PlannerStepConfig {
+///     step: 0,
+///     planner_type: "MinimumJerkLine".to_string(),
+///     params:
+///        serde_yaml::from_str(r#"
+///        end_position: [0.0, 0.0, 1.0]
+///        end_yaw: 0.0
+///        duration: 2.0
+///        "#).unwrap(),
+/// }];
+/// update_planner(&mut planner_manager, step, time, simulation_frequency, &quadrotor, &obstacles, &planner_config).unwrap();
+/// ```
+pub fn update_planner(
+    planner_manager: &mut PlannerManager,
+    step: usize,
+    time: f32,
+    simulation_frequency: usize,
+    quad: &Quadrotor,
+    obstacles: &[Obstacle],
+    planner_config: &[PlannerStepConfig],
+) -> Result<(), SimulationError> {
+    if let Some(planner_step) = planner_config
+        .iter()
+        .find(|s| s.step * simulation_frequency == step * 1000)
+    {
+        log::info!("Time: {:.2} s,\tSwitch {}", time, planner_step.planner_type);
+        planner_manager.set_planner(create_planner(planner_step, quad, time, obstacles)?);
+    }
+    Ok(())
+}
+/// Creates a planner based on the configuration
+/// # Arguments
+/// * `step` - The configuration for the planner step in ms unit
+/// * `quad` - The Quadrotor instance
+/// * `time` - The current simulation time
+/// * `obstacles` - The current obstacles in the simulation
+/// # Returns
+/// * `PlannerType` - The created planner
+/// # Errors
+/// * If the planner type is not recognized
+/// # Example
+/// ```
+/// use peng_quad::{PlannerType, Quadrotor, Obstacle, PlannerStepConfig, create_planner};
+/// use nalgebra::Vector3;
+/// let step = PlannerStepConfig {
+///    step: 0,
+///   planner_type: "MinimumJerkLine".to_string(),
+///   params:
+///       serde_yaml::from_str(r#"
+///       end_position: [0.0, 0.0, 1.0]
+///       end_yaw: 0.0
+///       duration: 2.0
+///       "#).unwrap(),
+/// };
+/// let time = 0.0;
+/// let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+/// let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+/// let quadrotor = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+/// let obstacles = vec![Obstacle::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 1.0)];
+/// let planner = create_planner(&step, &quadrotor, time, &obstacles).unwrap();
+/// match planner {
+///    PlannerType::MinimumJerkLine(_) => log::info!("Created MinimumJerkLine planner"),
+///   _ => log::info!("Created another planner"),
+/// }
+/// ```
+pub fn create_planner(
+    step: &PlannerStepConfig,
+    quad: &Quadrotor,
+    time: f32,
+    obstacles: &[Obstacle],
+) -> Result<PlannerType, SimulationError> {
+    let params = &step.params;
+    match step.planner_type.as_str() {
+        "MinimumJerkLine" => Ok(PlannerType::MinimumJerkLine(MinimumJerkLinePlanner {
+            start_position: quad.position,
+            end_position: parse_vector3(params, "end_position")?,
+            start_yaw: quad.orientation.euler_angles().2,
+            end_yaw: parse_f32(params, "end_yaw")?,
+            start_time: time,
+            duration: parse_f32(params, "duration")?,
+        })),
+        "Lissajous" => Ok(PlannerType::Lissajous(LissajousPlanner {
+            start_position: quad.position,
+            center: parse_vector3(params, "center")?,
+            amplitude: parse_vector3(params, "amplitude")?,
+            frequency: parse_vector3(params, "frequency")?,
+            phase: parse_vector3(params, "phase")?,
+            start_time: time,
+            duration: parse_f32(params, "duration")?,
+            start_yaw: quad.orientation.euler_angles().2,
+            end_yaw: parse_f32(params, "end_yaw")?,
+            ramp_time: parse_f32(params, "ramp_time")?,
+        })),
+        "Circle" => Ok(PlannerType::Circle(CirclePlanner {
+            center: parse_vector3(params, "center")?,
+            radius: parse_f32(params, "radius")?,
+            angular_velocity: parse_f32(params, "angular_velocity")?,
+            start_position: quad.position,
+            start_time: time,
+            duration: parse_f32(params, "duration")?,
+            start_yaw: quad.orientation.euler_angles().2,
+            end_yaw: quad.orientation.euler_angles().2,
+            ramp_time: parse_f32(params, "ramp_time")?,
+        })),
+        "ObstacleAvoidance" => Ok(PlannerType::ObstacleAvoidance(ObstacleAvoidancePlanner {
+            target_position: parse_vector3(params, "target_position")?,
+            start_time: time,
+            duration: parse_f32(params, "duration")?,
+            start_yaw: quad.orientation.euler_angles().2,
+            end_yaw: parse_f32(params, "end_yaw")?,
+            obstacles: obstacles.to_owned(),
+            k_att: parse_f32(params, "k_att")?,
+            k_rep: parse_f32(params, "k_rep")?,
+            k_vortex: parse_f32(params, "k_vortex")?,
+            d0: parse_f32(params, "d0")?,
+            d_target: parse_f32(params, "d_target")?,
+            max_speed: parse_f32(params, "max_speed")?,
+        })),
+        "MinimumSnapWaypoint" => {
+            let mut waypoints = vec![quad.position];
+            waypoints.extend(
+                params["waypoints"]
+                    .as_sequence()
+                    .ok_or_else(|| SimulationError::OtherError("Invalid waypoints".to_string()))?
+                    .iter()
+                    .map(|w| {
+                        w.as_sequence()
+                            .and_then(|coords| {
+                                Some(Vector3::new(
+                                    coords[0].as_f64()? as f32,
+                                    coords[1].as_f64()? as f32,
+                                    coords[2].as_f64()? as f32,
+                                ))
+                            })
+                            .ok_or(SimulationError::OtherError("Invalid waypoint".to_string()))
+                    })
+                    .collect::<Result<Vec<Vector3<f32>>, SimulationError>>()?,
+            );
+            let mut yaws = vec![quad.orientation.euler_angles().2];
+            yaws.extend(
+                params["yaws"]
+                    .as_sequence()
+                    .ok_or(SimulationError::OtherError("Invalid yaws".to_string()))?
+                    .iter()
+                    .map(|y| {
+                        y.as_f64()
+                            .map(|v| v as f32)
+                            .ok_or(SimulationError::OtherError("Invalid yaw".to_string()))
+                    })
+                    .collect::<Result<Vec<f32>, SimulationError>>()?,
+            );
+            let segment_times = params["segment_times"]
+                .as_sequence()
+                .ok_or_else(|| SimulationError::OtherError("Invalid segment_times".to_string()))?
+                .iter()
+                .map(|t| {
+                    t.as_f64().map(|v| v as f32).ok_or_else(|| {
+                        SimulationError::OtherError("Invalid segment time".to_string())
+                    })
+                })
+                .collect::<Result<Vec<f32>, SimulationError>>()?;
+            MinimumSnapWaypointPlanner::new(waypoints, yaws, segment_times, time)
+                .map(PlannerType::MinimumSnapWaypoint)
+        }
+        "Landing" => Ok(PlannerType::Landing(LandingPlanner {
+            start_position: quad.position,
+            start_time: time,
+            duration: parse_f32(params, "duration")?,
+            start_yaw: quad.orientation.euler_angles().2,
+        })),
+        _ => Err(SimulationError::OtherError(format!(
+            "Unknown planner type: {}",
+            step.planner_type
+        ))),
+    }
+}
+/// Helper function to parse Vector3 from YAML
+/// # Arguments
+/// * `value` - YAML value
+/// * `key` - key to parse
+/// # Returns
+/// * `Vector3<f32>` - parsed vector
+/// # Errors
+/// * `SimulationError` - if the value is not a valid vector
+/// # Example
+/// ```
+/// use nalgebra::Vector3;
+/// use peng_quad::{parse_vector3, SimulationError};
+/// let value = serde_yaml::from_str("test: [1.0, 2.0, 3.0]").unwrap();
+/// assert_eq!(parse_vector3(&value, "test").unwrap(), Vector3::new(1.0, 2.0, 3.0));
+/// ```
+pub fn parse_vector3(
+    value: &serde_yaml::Value,
+    key: &str,
+) -> Result<Vector3<f32>, SimulationError> {
+    value[key]
+        .as_sequence()
+        .and_then(|seq| {
+            if seq.len() == 3 {
+                Some(Vector3::new(
+                    seq[0].as_f64()? as f32,
+                    seq[1].as_f64()? as f32,
+                    seq[2].as_f64()? as f32,
+                ))
+            } else {
+                None
+            }
+        })
+        .ok_or_else(|| SimulationError::OtherError(format!("Invalid {} vector", key)))
+}
+/// Helper function to parse f32 from YAML
+/// # Arguments
+/// * `value` - YAML value
+/// * `key` - key to parse
+/// # Returns
+/// * `f32` - parsed value
+/// # Errors
+/// * `SimulationError` - if the value is not a valid f32
+/// # Example
+/// ```
+/// use peng_quad::{parse_f32, SimulationError};
+/// let value = serde_yaml::from_str("key: 1.0").unwrap();
+/// let result = parse_f32(&value, "key").unwrap();
+/// assert_eq!(result, 1.0);
+/// ```
+pub fn parse_f32(value: &serde_yaml::Value, key: &str) -> Result<f32, SimulationError> {
+    value[key]
+        .as_f64()
+        .map(|v| v as f32)
+        .ok_or_else(|| SimulationError::OtherError(format!("Invalid {}", key)))
+}
+/// Represents an obstacle in the simulation
+/// # Example
+/// ```
+/// use peng_quad::Obstacle;
+/// use nalgebra::Vector3;
+/// let obstacle = Obstacle::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 1.0);
+/// ```
+#[derive(Clone)]
+pub struct Obstacle {
+    /// The position of the obstacle
+    pub position: Vector3<f32>,
+    /// The velocity of the obstacle
+    pub velocity: Vector3<f32>,
+    /// The radius of the obstacle
+    pub radius: f32,
+}
+/// Implementation of the Obstacle
+impl Obstacle {
+    /// Creates a new obstacle with the given position, velocity, and radius
+    /// # Arguments
+    /// * `position` - The position of the obstacle
+    /// * `velocity` - The velocity of the obstacle
+    /// * `radius` - The radius of the obstacle
+    /// # Returns
+    /// * The new obstacle instance
+    /// # Example
+    /// ```
+    /// use peng_quad::Obstacle;
+    /// use nalgebra::Vector3;
+    /// let obstacle = Obstacle::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 1.0);
+    /// ```
+    pub fn new(position: Vector3<f32>, velocity: Vector3<f32>, radius: f32) -> Self {
+        Self {
+            position,
+            velocity,
+            radius,
+        }
+    }
+}
+/// Represents a maze in the simulation
+/// # Example
+/// ```
+/// use peng_quad::{Maze, Obstacle};
+/// use nalgebra::Vector3;
+/// let maze = Maze {
+///     lower_bounds: [0.0, 0.0, 0.0],
+///     upper_bounds: [1.0, 1.0, 1.0],
+///     obstacles: vec![Obstacle::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 0.0), 1.0)],
+///     obstacles_velocity_bounds: [0.0, 0.0, 0.0],
+///     obstacles_radius_bounds: [0.0, 0.0],
+/// };
+/// ```
+pub struct Maze {
+    /// The lower bounds of the maze in the x, y, and z directions
+    pub lower_bounds: [f32; 3],
+    /// The upper bounds of the maze in the x, y, and z directions
+    pub upper_bounds: [f32; 3],
+    /// The obstacles in the maze
+    pub obstacles: Vec<Obstacle>,
+    /// The bounds of the obstacles' velocity
+    pub obstacles_velocity_bounds: [f32; 3],
+    /// The bounds of the obstacles' radius
+    pub obstacles_radius_bounds: [f32; 2],
+}
+/// Implementation of the maze
+impl Maze {
+    /// Creates a new maze with the given bounds and number of obstacles
+    /// # Arguments
+    /// * `lower_bounds` - The lower bounds of the maze
+    /// * `upper_bounds` - The upper bounds of the maze
+    /// * `num_obstacles` - The number of obstacles in the maze
+    /// # Returns
+    /// * The new maze instance
+    /// # Example
+    /// ```
+    /// use peng_quad::Maze;
+    /// let maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+    /// ```
+    pub fn new(
+        lower_bounds: [f32; 3],
+        upper_bounds: [f32; 3],
+        num_obstacles: usize,
+        obstacles_velocity_bounds: [f32; 3],
+        obstacles_radius_bounds: [f32; 2],
+    ) -> Self {
+        let mut maze = Maze {
+            lower_bounds,
+            upper_bounds,
+            obstacles: Vec::new(),
+            obstacles_velocity_bounds,
+            obstacles_radius_bounds,
+        };
+        maze.generate_obstacles(num_obstacles);
+        maze
+    }
+    /// Generates the obstacles in the maze
+    /// # Arguments
+    /// * `num_obstacles` - The number of obstacles to generate
+    /// # Example
+    /// ```
+    /// use peng_quad::Maze;
+    /// let mut maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+    /// maze.generate_obstacles(5);
+    /// ```
+    pub fn generate_obstacles(&mut self, num_obstacles: usize) {
+        let mut rng = ChaCha8Rng::from_entropy();
+        self.obstacles = (0..num_obstacles)
+            .map(|_| {
+                let position = Vector3::new(
+                    rand::Rng::gen_range(&mut rng, self.lower_bounds[0]..self.upper_bounds[0]),
+                    rand::Rng::gen_range(&mut rng, self.lower_bounds[1]..self.upper_bounds[1]),
+                    rand::Rng::gen_range(&mut rng, self.lower_bounds[2]..self.upper_bounds[2]),
+                );
+                let v_bounds = self.obstacles_velocity_bounds;
+                let r_bounds = self.obstacles_radius_bounds;
+                let velocity = Vector3::new(
+                    rand::Rng::gen_range(&mut rng, -v_bounds[0]..v_bounds[0]),
+                    rand::Rng::gen_range(&mut rng, -v_bounds[1]..v_bounds[1]),
+                    rand::Rng::gen_range(&mut rng, -v_bounds[2]..v_bounds[2]),
+                );
+                let radius = rand::Rng::gen_range(&mut rng, r_bounds[0]..r_bounds[1]);
+                Obstacle::new(position, velocity, radius)
+            })
+            .collect();
+    }
+    /// Updates the obstacles in the maze, if an obstacle hits a boundary, it bounces off
+    /// # Arguments
+    /// * `dt` - The time step
+    /// # Example
+    /// ```
+    /// use peng_quad::Maze;
+    /// let mut maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+    /// maze.update_obstacles(0.1);
+    /// ```
+    pub fn update_obstacles(&mut self, dt: f32) {
+        self.obstacles.iter_mut().for_each(|obstacle| {
+            obstacle.position += obstacle.velocity * dt;
+            for i in 0..3 {
+                if obstacle.position[i] - obstacle.radius < self.lower_bounds[i]
+                    || obstacle.position[i] + obstacle.radius > self.upper_bounds[i]
+                {
+                    obstacle.velocity[i] *= -1.0;
+                }
+            }
+        });
+    }
+}
+/// Represents a camera in the simulation which is used to render the depth of the scene
+/// # Example
+/// ```
+/// use peng_quad::Camera;
+/// let camera = Camera::new((800, 600), 60.0, 0.1, 100.0);
+/// ```
+pub struct Camera {
+    /// The resolution of the camera
+    pub resolution: (usize, usize),
+    /// The field of view of the camera
+    pub fov: f32,
+    /// The near clipping plane of the camera
+    pub near: f32,
+    /// The far clipping plane of the camera
+    pub far: f32,
+    /// The aspect ratio of the camera
+    pub aspect_ratio: f32,
+    /// The ray directions of each pixel in the camera
+    pub ray_directions: Vec<Vector3<f32>>,
+}
+/// Implementation of the camera
+impl Camera {
+    /// Creates a new camera with the given resolution, field of view, near and far clipping planes
+    /// # Arguments
+    /// * `resolution` - The resolution of the camera
+    /// * `fov` - The field of view of the camera
+    /// * `near` - The near clipping plane of the camera
+    /// * `far` - The far clipping plane of the camera
+    /// # Returns
+    /// * The new camera instance
+    /// # Example
+    /// ```
+    /// use peng_quad::Camera;
+    /// let camera = Camera::new((800, 600), 60.0, 0.1, 100.0);
+    /// ```
+    pub fn new(resolution: (usize, usize), fov: f32, near: f32, far: f32) -> Self {
+        let (width, height) = resolution;
+        let (aspect_ratio, tan_half_fov) = (width as f32 / height as f32, (fov / 2.0).tan());
+        let mut ray_directions = Vec::with_capacity(width * height);
+        for y in 0..height {
+            for x in 0..width {
+                let x_ndc = (2.0 * x as f32 / width as f32 - 1.0) * aspect_ratio * tan_half_fov;
+                let y_ndc = (1.0 - 2.0 * y as f32 / height as f32) * tan_half_fov;
+                ray_directions.push(Vector3::new(1.0, x_ndc, y_ndc).normalize());
+            }
+        }
+        Self {
+            resolution,
+            fov,
+            near,
+            far,
+            aspect_ratio,
+            ray_directions,
+        }
+    }
+    /// Renders the depth of the scene from the perspective of the quadrotor
+    /// # Arguments
+    /// * `quad_position` - The position of the quadrotor
+    /// * `quad_orientation` - The orientation of the quadrotor
+    /// * `maze` - The maze in the scene
+    /// * `depth_buffer` - The depth buffer to store the depth values
+    /// # Errors
+    /// * If the depth buffer is not large enough to store the depth values
+    /// # Example
+    /// ```
+    /// use peng_quad::{Camera, Maze};
+    /// use nalgebra::{Vector3, UnitQuaternion};
+    /// let camera = Camera::new((800, 600), 60.0, 0.1, 100.0);
+    /// let quad_position = Vector3::new(0.0, 0.0, 0.0);
+    /// let quad_orientation = UnitQuaternion::identity();
+    /// let mut maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+    /// let mut depth_buffer = vec![0.0; 800 * 600];
+    /// let use_multithreading = true;
+    /// camera.render_depth(&quad_position, &quad_orientation, &maze, &mut depth_buffer, use_multithreading);
+    /// ```
+    pub fn render_depth(
+        &self,
+        quad_position: &Vector3<f32>,
+        quad_orientation: &UnitQuaternion<f32>,
+        maze: &Maze,
+        depth_buffer: &mut Vec<f32>,
+        use_multi_threading: bool,
+    ) -> Result<(), SimulationError> {
+        let (width, height) = self.resolution;
+        let total_pixels = width * height;
+        let rotation_camera_to_world = quad_orientation.to_rotation_matrix().matrix()
+            * Matrix3::new(1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0);
+        let rotation_world_to_camera = rotation_camera_to_world.transpose();
+        if use_multi_threading {
+            depth_buffer.reserve((total_pixels - depth_buffer.capacity()).max(0));
+            depth_buffer
+                .par_iter_mut()
+                .enumerate()
+                .try_for_each(|(i, depth)| {
+                    let direction = rotation_camera_to_world * self.ray_directions[i];
+                    *depth =
+                        self.ray_cast(quad_position, &rotation_world_to_camera, &direction, maze)?;
+                    Ok::<(), SimulationError>(())
+                })?;
+        } else {
+            depth_buffer.clear();
+            depth_buffer.reserve((total_pixels - depth_buffer.capacity()).max(0));
+            for i in 0..total_pixels {
+                depth_buffer.push(self.ray_cast(
+                    quad_position,
+                    &rotation_world_to_camera,
+                    &(rotation_camera_to_world * self.ray_directions[i]),
+                    maze,
+                )?);
+            }
+        }
+        Ok(())
+    }
+    /// Casts a ray from the camera origin in the given direction
+    /// # Arguments
+    /// * `origin` - The origin of the ray
+    /// * `rotation_world_to_camera` - The rotation matrix from world to camera coordinates
+    /// * `direction` - The direction of the ray
+    /// * `maze` - The maze in the scene
+    /// # Returns
+    /// * The distance to the closest obstacle hit by the ray
+    /// # Errors
+    /// * If the ray does not hit any obstacles
+    /// # Example
+    /// ```
+    /// use peng_quad::{Camera, Maze};
+    /// use nalgebra::{Vector3, Matrix3};
+    /// let camera = Camera::new((800, 600), 60.0, 0.1, 100.0);
+    /// let origin = Vector3::new(0.0, 0.0, 0.0);
+    /// let rotation_world_to_camera = Matrix3::identity();
+    /// let direction = Vector3::new(1.0, 0.0, 0.0);
+    /// let mut maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+    /// let distance = camera.ray_cast(&origin, &rotation_world_to_camera, &direction, &maze);
+    /// ```
+    pub fn ray_cast(
+        &self,
+        origin: &Vector3<f32>,
+        rotation_world_to_camera: &Matrix3<f32>,
+        direction: &Vector3<f32>,
+        maze: &Maze,
+    ) -> Result<f32, SimulationError> {
+        let mut closest_hit = self.far;
+        // Inline tube intersection
+        for axis in 0..3 {
+            if direction[axis].abs() > f32::EPSILON {
+                for &bound in &[maze.lower_bounds[axis], maze.upper_bounds[axis]] {
+                    let t = (bound - origin[axis]) / direction[axis];
+                    if t > self.near && t < closest_hit {
+                        let intersection_point = origin + direction * t;
+                        if (0..3).all(|i| {
+                            i == axis
+                                || (intersection_point[i] >= maze.lower_bounds[i]
+                                    && intersection_point[i] <= maze.upper_bounds[i])
+                        }) {
+                            closest_hit = t;
+                        }
+                    }
+                }
+            }
+        }
+        // Early exit if we've hit a wall closer than any possible obstacle
+        if closest_hit <= self.near {
+            return Ok(f32::INFINITY);
+        }
+        // Inline sphere intersection
+        for obstacle in &maze.obstacles {
+            let oc = origin - obstacle.position;
+            let b = oc.dot(direction);
+            let c = oc.dot(&oc) - obstacle.radius * obstacle.radius;
+            let discriminant = b * b - c;
+            if discriminant >= 0.0 {
+                // let t = -b - discriminant.sqrt();
+                let t = -b - fast_sqrt(discriminant);
+                if t > self.near && t < closest_hit {
+                    closest_hit = t;
+                }
+            }
+        }
+        if closest_hit < self.far {
+            Ok((rotation_world_to_camera * direction * closest_hit).x)
+        } else {
+            Ok(f32::INFINITY)
+        }
+    }
+}
+/// Logs simulation data to the rerun recording stream
+/// # Arguments
+/// * `rec` - The rerun::RecordingStream instance
+/// * `quad` - The Quadrotor instance
+/// * `desired_position` - The desired position vector
+/// * `measured_accel` - The measured acceleration vector
+/// * `measured_gyro` - The measured angular velocity vector
+/// # Errors
+/// * If the data cannot be logged to the recording stream
+/// # Example
+/// ```no_run
+/// use peng_quad::{Quadrotor, log_data};
+/// use nalgebra::Vector3;
+/// let rec = rerun::RecordingStreamBuilder::new("peng").connect().unwrap();
+/// let (time_step, mass, gravity, drag_coefficient) = (0.01, 1.3, 9.81, 0.01);
+/// let inertia_matrix = [0.0347563, 0.0, 0.0, 0.0, 0.0458929, 0.0, 0.0, 0.0, 0.0977];
+/// let quad = Quadrotor::new(time_step, mass, gravity, drag_coefficient, inertia_matrix).unwrap();
+/// let desired_position = Vector3::new(0.0, 0.0, 0.0);
+/// let desired_velocity = Vector3::new(0.0, 0.0, 0.0);
+/// let measured_accel = Vector3::new(0.0, 0.0, 0.0);
+/// let measured_gyro = Vector3::new(0.0, 0.0, 0.0);
+/// log_data(&rec, &quad, &desired_position, &desired_velocity, &measured_accel, &measured_gyro).unwrap();
+/// ```
+pub fn log_data(
+    rec: &rerun::RecordingStream,
+    quad: &Quadrotor,
+    desired_position: &Vector3<f32>,
+    desired_velocity: &Vector3<f32>,
+    measured_accel: &Vector3<f32>,
+    measured_gyro: &Vector3<f32>,
+) -> Result<(), SimulationError> {
+    rec.log(
+        "world/quad/desired_position",
+        &rerun::Points3D::new([(desired_position.x, desired_position.y, desired_position.z)])
+            .with_radii([0.1])
+            .with_colors([rerun::Color::from_rgb(255, 255, 255)]),
+    )?;
+    rec.log(
+        "world/quad/base_link",
+        &rerun::Transform3D::from_translation_rotation(
+            rerun::Vec3D::new(quad.position.x, quad.position.y, quad.position.z),
+            rerun::Quaternion::from_xyzw([
+                quad.orientation.i,
+                quad.orientation.j,
+                quad.orientation.k,
+                quad.orientation.w,
+            ]),
+        )
+        .with_axis_length(0.7),
+    )?;
+    let (quad_roll, quad_pitch, quad_yaw) = quad.orientation.euler_angles();
+    let quad_euler_angles: Vector3<f32> = Vector3::new(quad_roll, quad_pitch, quad_yaw);
+    for (pre, vec) in [
+        ("position", &quad.position),
+        ("velocity", &quad.velocity),
+        ("accel", measured_accel),
+        ("orientation", &quad_euler_angles),
+        ("gyro", measured_gyro),
+        ("desired_position", desired_position),
+        ("desired_velocity", desired_velocity),
+    ] {
+        for (i, a) in ["x", "y", "z"].iter().enumerate() {
+            rec.log(format!("{}/{}", pre, a), &rerun::Scalar::new(vec[i] as f64))?;
+        }
+    }
+    Ok(())
+}
+/// Log the maze tube to the rerun recording stream
+/// # Arguments
+/// * `rec` - The rerun::RecordingStream instance
+/// * `maze` - The maze instance
+/// # Errors
+/// * If the data cannot be logged to the recording stream
+/// # Example
+/// ```no_run
+/// use peng_quad::{Maze, log_maze_tube};
+/// use rerun::RecordingStreamBuilder;
+/// let rec = rerun::RecordingStreamBuilder::new("log.rerun").connect().unwrap();
+/// let mut maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+/// log_maze_tube(&rec, &maze).unwrap();
+/// ```
+pub fn log_maze_tube(rec: &rerun::RecordingStream, maze: &Maze) -> Result<(), SimulationError> {
+    let (lower_bounds, upper_bounds) = (maze.lower_bounds, maze.upper_bounds);
+    let center_position = rerun::external::glam::Vec3::new(
+        (lower_bounds[0] + upper_bounds[0]) / 2.0,
+        (lower_bounds[1] + upper_bounds[1]) / 2.0,
+        (lower_bounds[2] + upper_bounds[2]) / 2.0,
+    );
+    let half_sizes = rerun::external::glam::Vec3::new(
+        (upper_bounds[0] - lower_bounds[0]) / 2.0,
+        (upper_bounds[1] - lower_bounds[1]) / 2.0,
+        (upper_bounds[2] - lower_bounds[2]) / 2.0,
+    );
+    rec.log(
+        "world/maze/tube",
+        &rerun::Boxes3D::from_centers_and_half_sizes([center_position], [half_sizes])
+            .with_colors([rerun::Color::from_rgb(128, 128, 255)]),
+    )?;
+    Ok(())
+}
+/// Log the maze obstacles to the rerun recording stream
+/// # Arguments
+/// * `rec` - The rerun::RecordingStream instance
+/// * `maze` - The maze instance
+/// # Errors
+/// * If the data cannot be logged to the recording stream
+/// # Example
+/// ```no_run
+/// use peng_quad::{Maze, log_maze_obstacles};
+/// let rec = rerun::RecordingStreamBuilder::new("log.rerun").connect().unwrap();
+/// let mut maze = Maze::new([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0], 5, [0.1, 0.1, 0.1], [0.1, 0.5]);
+/// log_maze_obstacles(&rec, &maze).unwrap();
+/// ```
+pub fn log_maze_obstacles(
+    rec: &rerun::RecordingStream,
+    maze: &Maze,
+) -> Result<(), SimulationError> {
+    let (positions, radii): (Vec<(f32, f32, f32)>, Vec<f32>) = maze
+        .obstacles
+        .iter()
+        .map(|obstacle| {
+            let pos = obstacle.position;
+            ((pos.x, pos.y, pos.z), obstacle.radius)
+        })
+        .unzip();
+    rec.log(
+        "world/maze/obstacles",
+        &rerun::Points3D::new(positions)
+            .with_radii(radii)
+            .with_colors([rerun::Color::from_rgb(255, 128, 128)]),
+    )?;
+    Ok(())
+}
+/// A struct to hold trajectory data
+/// # Example
+/// ```
+/// use peng_quad::Trajectory;
+/// let initial_point = nalgebra::Vector3::new(0.0, 0.0, 0.0);
+/// let mut trajectory = Trajectory::new(initial_point);
+/// ```
+pub struct Trajectory {
+    /// A vector of 3D points
+    pub points: Vec<Vector3<f32>>,
+    /// The last point that was logged
+    pub last_logged_point: Vector3<f32>,
+    /// The minimum distance between points to log
+    pub min_distance_threadhold: f32,
+}
+/// Implement the Trajectory struct
+impl Trajectory {
+    /// Create a new Trajectory instance
+    /// # Arguments
+    /// * `initial_point` - The initial point to add to the trajectory
+    /// # Returns
+    /// * A new Trajectory instance
+    /// # Example
+    /// ```
+    /// use peng_quad::Trajectory;
+    /// let initial_point = nalgebra::Vector3::new(0.0, 0.0, 0.0);
+    /// let mut trajectory = Trajectory::new(initial_point);
+    /// ```
+    pub fn new(initial_point: Vector3<f32>) -> Self {
+        Self {
+            points: vec![initial_point],
+            last_logged_point: initial_point,
+            min_distance_threadhold: 0.05,
+        }
+    }
+    /// Add a point to the trajectory if it is further than the minimum distance threshold
+    /// # Arguments
+    /// * `point` - The point to add
+    /// # Returns
+    /// * `true` if the point was added, `false` otherwise
+    /// # Example
+    /// ```
+    /// use peng_quad::Trajectory;
+    /// let mut trajectory = Trajectory::new(nalgebra::Vector3::new(0.0, 0.0, 0.0));
+    /// let point = nalgebra::Vector3::new(1.0, 0.0, 0.0);
+    /// assert_eq!(trajectory.add_point(point), true);
+    /// assert_eq!(trajectory.add_point(point), false);
+    /// ```
+    pub fn add_point(&mut self, point: Vector3<f32>) -> bool {
+        if (point - self.last_logged_point).norm() > self.min_distance_threadhold {
+            self.points.push(point);
+            self.last_logged_point = point;
+            true
+        } else {
+            false
+        }
+    }
+}
+/// log trajectory data to the rerun recording stream
+/// # Arguments
+/// * `rec` - The rerun::RecordingStream instance
+/// * `trajectory` - The Trajectory instance
+/// # Errors
+/// * If the data cannot be logged to the recording stream
+/// # Example
+/// ```no_run
+/// use peng_quad::{Trajectory, log_trajectory};
+/// use nalgebra::Vector3;
+/// let rec = rerun::RecordingStreamBuilder::new("log.rerun").connect().unwrap();
+/// let mut trajectory = Trajectory::new(nalgebra::Vector3::new(0.0, 0.0, 0.0));
+/// trajectory.add_point(nalgebra::Vector3::new(1.0, 0.0, 0.0));
+/// log_trajectory(&rec, &trajectory).unwrap();
+/// ```
+pub fn log_trajectory(
+    rec: &rerun::RecordingStream,
+    trajectory: &Trajectory,
+) -> Result<(), SimulationError> {
+    let path = trajectory
+        .points
+        .iter()
+        .map(|p| (p.x, p.y, p.z))
+        .collect::<Vec<(f32, f32, f32)>>();
+    rec.log(
+        "world/quad/path",
+        &rerun::LineStrips3D::new([path]).with_colors([rerun::Color::from_rgb(0, 255, 255)]),
+    )?;
+    Ok(())
+}
+/// log mesh data to the rerun recording stream
+/// # Arguments
+/// * `rec` - The rerun::RecordingStream instance
+/// * `division` - The number of divisions in the mesh
+/// * `spacing` - The spacing between divisions
+/// # Errors
+/// * If the data cannot be logged to the recording stream
+/// # Example
+/// ```no_run
+/// use peng_quad::log_mesh;
+/// let rec = rerun::RecordingStreamBuilder::new("log.rerun").connect().unwrap();
+/// log_mesh(&rec, 10, 0.1).unwrap();
+/// ```
+pub fn log_mesh(
+    rec: &rerun::RecordingStream,
+    division: usize,
+    spacing: f32,
+) -> Result<(), SimulationError> {
+    let grid_size: usize = division + 1;
+    let half_grid_size: f32 = (division as f32 * spacing) / 2.0;
+    let points: Vec<rerun::external::glam::Vec3> = (0..grid_size)
+        .flat_map(|i| {
+            (0..grid_size).map(move |j| {
+                rerun::external::glam::Vec3::new(
+                    j as f32 * spacing - half_grid_size,
+                    i as f32 * spacing - half_grid_size,
+                    0.0,
+                )
+            })
+        })
+        .collect();
+    let horizontal_lines: Vec<Vec<rerun::external::glam::Vec3>> = (0..grid_size)
+        .map(|i| points[i * grid_size..(i + 1) * grid_size].to_vec())
+        .collect();
+    let vertical_lines: Vec<Vec<rerun::external::glam::Vec3>> = (0..grid_size)
+        .map(|j| (0..grid_size).map(|i| points[i * grid_size + j]).collect())
+        .collect();
+    let line_strips: Vec<Vec<rerun::external::glam::Vec3>> =
+        horizontal_lines.into_iter().chain(vertical_lines).collect();
+    rec.log(
+        "world/mesh",
+        &rerun::LineStrips3D::new(line_strips)
+            .with_colors([rerun::Color::from_rgb(255, 255, 255)])
+            .with_radii([0.02]),
+    )?;
+    Ok(())
+}
+/// log depth image data to the rerun recording stream
+/// # Arguments
+/// * `rec` - The rerun::RecordingStream instance
+/// * `depth_image` - The depth image data
+/// * `width` - The width of the depth image
+/// * `height` - The height of the depth image
+/// * `min_depth` - The minimum depth value
+/// * `max_depth` - The maximum depth value
+/// # Errors
+/// * If the data cannot be logged to the recording stream
+/// # Example
+/// ```no_run
+/// use peng_quad::log_depth_image;
+/// let rec = rerun::RecordingStreamBuilder::new("log.rerun").connect().unwrap();
+/// let depth_image = vec![0.0; 640 * 480];
+/// log_depth_image(&rec, &depth_image, 640, 480, 0.0, 1.0).unwrap();
+/// ```
+pub fn log_depth_image(
+    rec: &rerun::RecordingStream,
+    depth_image: &[f32],
+    width: usize,
+    height: usize,
+    min_depth: f32,
+    max_depth: f32,
+) -> Result<(), SimulationError> {
+    let mut image = rerun::external::ndarray::Array::zeros((height, width, 3));
+    let depth_range = max_depth - min_depth;
+    image
+        .axis_iter_mut(rerun::external::ndarray::Axis(0))
+        .enumerate()
+        .for_each(|(y, mut row)| {
+            for (x, mut pixel) in row
+                .axis_iter_mut(rerun::external::ndarray::Axis(0))
+                .enumerate()
+            {
+                let depth = depth_image[y * width + x];
+                let color = if depth.is_finite() {
+                    let normalized_depth = ((depth - min_depth) / depth_range).clamp(0.0, 1.0);
+                    color_map_fn(normalized_depth * 255.0)
+                } else {
+                    (0, 0, 0)
+                };
+                (pixel[0], pixel[1], pixel[2]) = color;
+            }
+        });
+    let rerun_image = rerun::Image::from_color_model_and_tensor(rerun::ColorModel::RGB, image)
+        .map_err(|e| SimulationError::OtherError(format!("Failed to create rerun image: {}", e)))?;
+    rec.log("world/quad/cam/depth", &rerun_image)?;
+    Ok(())
+}
+/// creates pinhole camera
+/// # Arguments
+/// * `rec` - The rerun::RecordingStream instance
+/// * `width` - The width component of the camera resolution
+/// * `height` - The height component of the camera resolution
+/// * `fov` - The fov of the camera
+/// * `cam_position` - The position vector of the camera (aligns with the quad)
+/// * `cam_orientation` - The orientation quaternion of quad
+/// * `cam_transform` - The transform matrix between quad and camera alignment
+/// * `depth_image` - The depth image data
+/// # Errors
+/// * If the data cannot be logged to the recording stream
+/// # Example
+/// ```no_run
+/// use peng_quad::pinhole_depth;
+/// use nalgebra::{Vector3, UnitQuaternion};
+/// let rec = rerun::RecordingStreamBuilder::new("log.rerun").connect().unwrap();
+/// let depth_image = vec![ 0.0f32 ; 640 * 480];
+/// let cam_position = Vector3::new(0.0,0.0,0.0);
+/// let cam_orientation = UnitQuaternion::identity();
+/// let cam_transform = [0.0, 0.0, 1.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0];
+/// pinhole_depth(&rec, 128usize, 96usize, 90.0, cam_position, cam_orientation, cam_transform, &depth_image).unwrap();
+
+pub fn pinhole_depth(
+    rec: &rerun::RecordingStream,
+    width: usize,
+    height: usize,
+    fov: f32,
+    cam_position: Vector3<f32>,
+    cam_orientation: UnitQuaternion<f32>,
+    cam_transform: [f32; 9],
+    depth_image: &[f32],
+) -> Result<(), SimulationError> {
+    let fov_x = (width as f32 / height as f32 * (fov / 2.0).tan()).atan() * 2.0;
+    let horizontal_focal_length = (width as f32 / 2.0) / ((fov_x/ 2.0).tan());
+    let vertical_focal_length = (height as f32 / 2.0) / ((fov / 2.0).tan());
+    let pinhole_camera = rerun::Pinhole::from_focal_length_and_resolution(
+        (horizontal_focal_length, vertical_focal_length),
+        (width as f32, height as f32),
+    )
+        .with_camera_xyz(rerun::components::ViewCoordinates::RDF)
+        .with_resolution((width as f32, height as f32))
+        .with_principal_point((width as f32 / 2.0, height as f32 / 2.0));
+    let rotated_camera_orientation = UnitQuaternion::from_rotation_matrix(
+        &(cam_orientation.to_rotation_matrix()
+            * Rotation3::from_matrix_unchecked(Matrix3::from_row_slice(&cam_transform))),
+    );
+    let cam_transform = rerun::Transform3D::from_translation_rotation(
+        rerun::Vec3D::new(cam_position.x, cam_position.y, cam_position.z),
+        rerun::Quaternion::from_xyzw([
+            rotated_camera_orientation.i,
+            rotated_camera_orientation.j,
+            rotated_camera_orientation.k,
+            rotated_camera_orientation.w,
+        ]),
+    );
+    rec.log("world/quad/cam", &cam_transform)?;
+    rec.log("world/quad/cam", &pinhole_camera)?;
+    let depth_image_rerun =
+        rerun::external::ndarray::Array::from_shape_vec((height, width), depth_image.to_vec())
+            .unwrap();
+    rec.log(
+        "world/quad/cam/rerun_depth",
+        &rerun::DepthImage::try_from(depth_image_rerun)
+            .unwrap()
+            .with_meter(1.0),
+    )?;
+
+    Ok(())
+}
+/// turbo color map function
+/// # Arguments
+/// * `gray` - The gray value in the range [0, 255]
+/// # Returns
+/// * The RGB color value in the range [0, 255]
+/// # Example
+/// ```
+/// use peng_quad::color_map_fn;
+/// let color = color_map_fn(128.0);
+/// ```
+#[inline]
+pub fn color_map_fn(gray: f32) -> (u8, u8, u8) {
+    let x = gray / 255.0;
+    let r = (34.61
+        + x * (1172.33 - x * (10793.56 - x * (33300.12 - x * (38394.49 - x * 14825.05)))))
+        .clamp(0.0, 255.0) as u8;
+    let g = (23.31 + x * (557.33 + x * (1225.33 - x * (3574.96 - x * (1073.77 + x * 707.56)))))
+        .clamp(0.0, 255.0) as u8;
+    let b = (27.2 + x * (3211.1 - x * (15327.97 - x * (27814.0 - x * (22569.18 - x * 6838.66)))))
+        .clamp(0.0, 255.0) as u8;
+    (r, g, b)
+}
+
+/// Fast square root function
+/// # Arguments
+/// * `x` - The input value
+/// # Returns
+/// * The square root of the input value
+#[inline(always)]
+fn fast_sqrt(x: f32) -> f32 {
+    let i = x.to_bits();
+    let i = 0x1fbd1df5 + (i >> 1);
+    f32::from_bits(i)
+}
+
\ No newline at end of file diff --git a/static.files/COPYRIGHT-23e9bde6c69aea69.txt b/static.files/COPYRIGHT-23e9bde6c69aea69.txt new file mode 100644 index 00000000..1447df79 --- /dev/null +++ b/static.files/COPYRIGHT-23e9bde6c69aea69.txt @@ -0,0 +1,50 @@ +# REUSE-IgnoreStart + +These documentation pages include resources by third parties. This copyright +file applies only to those resources. The following third party resources are +included, and carry their own copyright notices and license terms: + +* Fira Sans (FiraSans-Regular.woff2, FiraSans-Medium.woff2): + + Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ + with Reserved Font Name Fira Sans. + + Copyright (c) 2014, Telefonica S.A. + + Licensed under the SIL Open Font License, Version 1.1. + See FiraSans-LICENSE.txt. + +* rustdoc.css, main.js, and playpen.js: + + Copyright 2015 The Rust Developers. + Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or + the MIT license (LICENSE-MIT.txt) at your option. + +* normalize.css: + + Copyright (c) Nicolas Gallagher and Jonathan Neal. + Licensed under the MIT license (see LICENSE-MIT.txt). + +* Source Code Pro (SourceCodePro-Regular.ttf.woff2, + SourceCodePro-Semibold.ttf.woff2, SourceCodePro-It.ttf.woff2): + + Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), + with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark + of Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceCodePro-LICENSE.txt. + +* Source Serif 4 (SourceSerif4-Regular.ttf.woff2, SourceSerif4-Bold.ttf.woff2, + SourceSerif4-It.ttf.woff2): + + Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name + 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United + States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceSerif4-LICENSE.md. + +This copyright file is intended to be distributed with rustdoc output. + +# REUSE-IgnoreEnd diff --git a/static.files/FiraSans-LICENSE-db4b642586e02d97.txt b/static.files/FiraSans-LICENSE-db4b642586e02d97.txt new file mode 100644 index 00000000..d7e9c149 --- /dev/null +++ b/static.files/FiraSans-LICENSE-db4b642586e02d97.txt @@ -0,0 +1,98 @@ +// REUSE-IgnoreStart + +Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. +with Reserved Font Name < Fira >, + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +// REUSE-IgnoreEnd diff --git a/static.files/FiraSans-Medium-8f9a781e4970d388.woff2 b/static.files/FiraSans-Medium-8f9a781e4970d388.woff2 new file mode 100644 index 00000000..7a1e5fc5 Binary files /dev/null and b/static.files/FiraSans-Medium-8f9a781e4970d388.woff2 differ diff --git a/static.files/FiraSans-Regular-018c141bf0843ffd.woff2 b/static.files/FiraSans-Regular-018c141bf0843ffd.woff2 new file mode 100644 index 00000000..e766e06c Binary files /dev/null and b/static.files/FiraSans-Regular-018c141bf0843ffd.woff2 differ diff --git a/static.files/LICENSE-APACHE-b91fa81cba47b86a.txt b/static.files/LICENSE-APACHE-b91fa81cba47b86a.txt new file mode 100644 index 00000000..16fe87b0 --- /dev/null +++ b/static.files/LICENSE-APACHE-b91fa81cba47b86a.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/static.files/LICENSE-MIT-65090b722b3f6c56.txt b/static.files/LICENSE-MIT-65090b722b3f6c56.txt new file mode 100644 index 00000000..31aa7938 --- /dev/null +++ b/static.files/LICENSE-MIT-65090b722b3f6c56.txt @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/static.files/NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2 b/static.files/NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2 new file mode 100644 index 00000000..1866ad4b Binary files /dev/null and b/static.files/NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2 differ diff --git a/static.files/NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt b/static.files/NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt new file mode 100644 index 00000000..4b3edc29 --- /dev/null +++ b/static.files/NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt @@ -0,0 +1,103 @@ +// REUSE-IgnoreStart + +Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/), + +with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, +NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, +Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, +NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic, +Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +// REUSE-IgnoreEnd diff --git a/static.files/SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 b/static.files/SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 new file mode 100644 index 00000000..462c34ef Binary files /dev/null and b/static.files/SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 differ diff --git a/static.files/SourceCodePro-LICENSE-d180d465a756484a.txt b/static.files/SourceCodePro-LICENSE-d180d465a756484a.txt new file mode 100644 index 00000000..0d2941e1 --- /dev/null +++ b/static.files/SourceCodePro-LICENSE-d180d465a756484a.txt @@ -0,0 +1,97 @@ +// REUSE-IgnoreStart + +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +// REUSE-IgnoreEnd diff --git a/static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2 b/static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2 new file mode 100644 index 00000000..10b558e0 Binary files /dev/null and b/static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2 differ diff --git a/static.files/SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2 b/static.files/SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2 new file mode 100644 index 00000000..5ec64eef Binary files /dev/null and b/static.files/SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2 differ diff --git a/static.files/SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2 b/static.files/SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2 new file mode 100644 index 00000000..181a07f6 Binary files /dev/null and b/static.files/SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2 differ diff --git a/static.files/SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2 b/static.files/SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2 new file mode 100644 index 00000000..2ae08a7b Binary files /dev/null and b/static.files/SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2 differ diff --git a/static.files/SourceSerif4-LICENSE-3bb119e13b1258b7.md b/static.files/SourceSerif4-LICENSE-3bb119e13b1258b7.md new file mode 100644 index 00000000..175fa4f4 --- /dev/null +++ b/static.files/SourceSerif4-LICENSE-3bb119e13b1258b7.md @@ -0,0 +1,98 @@ + + +Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. +Copyright 2014 - 2023 Adobe (http://www.adobe.com/), with Reserved Font Name ‘Source’. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + + diff --git a/static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2 b/static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2 new file mode 100644 index 00000000..0263fc30 Binary files /dev/null and b/static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2 differ diff --git a/static.files/favicon-2c020d218678b618.svg b/static.files/favicon-2c020d218678b618.svg new file mode 100644 index 00000000..8b34b511 --- /dev/null +++ b/static.files/favicon-2c020d218678b618.svg @@ -0,0 +1,24 @@ + + + + + diff --git a/static.files/favicon-32x32-422f7d1d52889060.png b/static.files/favicon-32x32-422f7d1d52889060.png new file mode 100644 index 00000000..69b8613c Binary files /dev/null and b/static.files/favicon-32x32-422f7d1d52889060.png differ diff --git a/static.files/main-921df33f47b8780c.js b/static.files/main-921df33f47b8780c.js new file mode 100644 index 00000000..c3155548 --- /dev/null +++ b/static.files/main-921df33f47b8780c.js @@ -0,0 +1,11 @@ +"use strict";window.RUSTDOC_TOOLTIP_HOVER_MS=300;window.RUSTDOC_TOOLTIP_HOVER_EXIT_MS=450;function resourcePath(basename,extension){return getVar("root-path")+basename+getVar("resource-suffix")+extension}function hideMain(){addClass(document.getElementById(MAIN_ID),"hidden")}function showMain(){removeClass(document.getElementById(MAIN_ID),"hidden")}function blurHandler(event,parentElem,hideCallback){if(!parentElem.contains(document.activeElement)&&!parentElem.contains(event.relatedTarget)){hideCallback()}}window.rootPath=getVar("root-path");window.currentCrate=getVar("current-crate");function setMobileTopbar(){const mobileTopbar=document.querySelector(".mobile-topbar");const locationTitle=document.querySelector(".sidebar h2.location");if(mobileTopbar){const mobileTitle=document.createElement("h2");mobileTitle.className="location";if(hasClass(document.querySelector(".rustdoc"),"crate")){mobileTitle.innerHTML=`Crate ${window.currentCrate}`}else if(locationTitle){mobileTitle.innerHTML=locationTitle.innerHTML}mobileTopbar.appendChild(mobileTitle)}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!=="undefined"){return ev.key}const c=ev.charCode||ev.keyCode;if(c===27){return"Escape"}return String.fromCharCode(c)}const MAIN_ID="main-content";const SETTINGS_BUTTON_ID="settings-menu";const ALTERNATIVE_DISPLAY_ID="alternative-display";const NOT_DISPLAYED_ID="not-displayed";const HELP_BUTTON_ID="help-button";function getSettingsButton(){return document.getElementById(SETTINGS_BUTTON_ID)}function getHelpButton(){return document.getElementById(HELP_BUTTON_ID)}function getNakedUrl(){return window.location.href.split("?")[0].split("#")[0]}function insertAfter(newNode,referenceNode){referenceNode.parentNode.insertBefore(newNode,referenceNode.nextSibling)}function getOrCreateSection(id,classes){let el=document.getElementById(id);if(!el){el=document.createElement("section");el.id=id;el.className=classes;insertAfter(el,document.getElementById(MAIN_ID))}return el}function getAlternativeDisplayElem(){return getOrCreateSection(ALTERNATIVE_DISPLAY_ID,"content hidden")}function getNotDisplayedElem(){return getOrCreateSection(NOT_DISPLAYED_ID,"hidden")}function switchDisplayedElement(elemToDisplay){const el=getAlternativeDisplayElem();if(el.children.length>0){getNotDisplayedElem().appendChild(el.firstElementChild)}if(elemToDisplay===null){addClass(el,"hidden");showMain();return}el.appendChild(elemToDisplay);hideMain();removeClass(el,"hidden")}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function preLoadCss(cssUrl){const link=document.createElement("link");link.href=cssUrl;link.rel="preload";link.as="style";document.getElementsByTagName("head")[0].appendChild(link)}(function(){const isHelpPage=window.location.pathname.endsWith("/help.html");function loadScript(url,errorCallback){const script=document.createElement("script");script.src=url;if(errorCallback!==undefined){script.onerror=errorCallback}document.head.append(script)}getSettingsButton().onclick=event=>{if(event.ctrlKey||event.altKey||event.metaKey){return}window.hideAllModals(false);addClass(getSettingsButton(),"rotate");event.preventDefault();loadScript(getVar("static-root-path")+getVar("settings-js"));setTimeout(()=>{const themes=getVar("themes").split(",");for(const theme of themes){if(theme!==""){preLoadCss(getVar("root-path")+theme+".css")}}},0)};window.searchState={loadingText:"Loading search results...",input:document.getElementsByClassName("search-input")[0],outputElement:()=>{let el=document.getElementById("search");if(!el){el=document.createElement("section");el.id="search";getNotDisplayedElem().appendChild(el)}return el},title:document.title,titleBeforeSearch:document.title,timeout:null,currentTab:0,focusedByTab:[null,null,null],clearInputTimeout:()=>{if(searchState.timeout!==null){clearTimeout(searchState.timeout);searchState.timeout=null}},isDisplayed:()=>searchState.outputElement().parentElement.id===ALTERNATIVE_DISPLAY_ID,focus:()=>{searchState.input.focus()},defocus:()=>{searchState.input.blur()},showResults:search=>{if(search===null||typeof search==="undefined"){search=searchState.outputElement()}switchDisplayedElement(search);searchState.mouseMovedAfterSearch=false;document.title=searchState.title},removeQueryParameters:()=>{document.title=searchState.titleBeforeSearch;if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.hash)}},hideResults:()=>{switchDisplayedElement(null);searchState.removeQueryParameters()},getQueryStringParams:()=>{const params={};window.location.search.substring(1).split("&").map(s=>{const pair=s.split("=").map(x=>x.replace(/\+/g," "));params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params},setup:()=>{const search_input=searchState.input;if(!searchState.input){return}let searchLoaded=false;function sendSearchForm(){document.getElementsByClassName("search-form")[0].submit()}function loadSearch(){if(!searchLoaded){searchLoaded=true;loadScript(getVar("static-root-path")+getVar("search-js"),sendSearchForm);loadScript(resourcePath("search-index",".js"),sendSearchForm)}}search_input.addEventListener("focus",()=>{search_input.origPlaceholder=search_input.placeholder;search_input.placeholder="Type your search here.";loadSearch()});if(search_input.value!==""){loadSearch()}const params=searchState.getQueryStringParams();if(params.search!==undefined){searchState.setLoadingSearch();loadSearch()}},setLoadingSearch:()=>{const search=searchState.outputElement();search.innerHTML="

"+searchState.loadingText+"

";searchState.showResults(search)},descShards:new Map(),loadDesc:async function({descShard,descIndex}){if(descShard.promise===null){descShard.promise=new Promise((resolve,reject)=>{descShard.resolve=resolve;const ds=descShard;const fname=`${ds.crate}-desc-${ds.shard}-`;const url=resourcePath(`search.desc/${descShard.crate}/${fname}`,".js",);loadScript(url,reject)})}const list=await descShard.promise;return list[descIndex]},loadedDescShard:function(crate,shard,data){this.descShards.get(crate)[shard].resolve(data.split("\n"))},};const toggleAllDocsId="toggle-all-docs";let savedHash="";function handleHashes(ev){if(ev!==null&&searchState.isDisplayed()&&ev.newURL){switchDisplayedElement(null);const hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.search+"#"+hash)}const elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}const pageId=window.location.hash.replace(/^#/,"");if(savedHash!==pageId){savedHash=pageId;if(pageId!==""){expandSection(pageId)}}if(savedHash.startsWith("impl-")){const splitAt=savedHash.indexOf("/");if(splitAt!==-1){const implId=savedHash.slice(0,splitAt);const assocId=savedHash.slice(splitAt+1);const implElems=document.querySelectorAll(`details > summary > section[id^="${implId}"]`,);onEachLazy(implElems,implElem=>{const numbered=/^(.+?)-([0-9]+)$/.exec(implElem.id);if(implElem.id!==implId&&(!numbered||numbered[1]!==implId)){return false}return onEachLazy(implElem.parentElement.parentElement.querySelectorAll(`[id^="${assocId}"]`),item=>{const numbered=/^(.+?)-([0-9]+)$/.exec(item.id);if(item.id===assocId||(numbered&&numbered[1]===assocId)){openParentDetails(item);item.scrollIntoView();setTimeout(()=>{window.location.replace("#"+item.id)},0);return true}},)})}}}function onHashChange(ev){hideSidebar();handleHashes(ev)}function openParentDetails(elem){while(elem){if(elem.tagName==="DETAILS"){elem.open=true}elem=elem.parentNode}}function expandSection(id){openParentDetails(document.getElementById(id))}function handleEscape(ev){searchState.clearInputTimeout();searchState.hideResults();ev.preventDefault();searchState.defocus();window.hideAllModals(true)}function handleShortcut(ev){const disableShortcuts=getSettingValue("disable-shortcuts")==="true";if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts){return}if(document.activeElement.tagName==="INPUT"&&document.activeElement.type!=="checkbox"&&document.activeElement.type!=="radio"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":case"/":ev.preventDefault();searchState.focus();break;case"+":ev.preventDefault();expandAllDocs();break;case"-":ev.preventDefault();collapseAllDocs();break;case"?":showHelp();break;default:break}}}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function addSidebarItems(){if(!window.SIDEBAR_ITEMS){return}const sidebar=document.getElementsByClassName("sidebar-elems")[0];function block(shortty,id,longty){const filtered=window.SIDEBAR_ITEMS[shortty];if(!filtered){return}const modpath=hasClass(document.querySelector(".rustdoc"),"mod")?"../":"";const h3=document.createElement("h3");h3.innerHTML=`${longty}`;const ul=document.createElement("ul");ul.className="block "+shortty;for(const name of filtered){let path;if(shortty==="mod"){path=`${modpath}${name}/index.html`}else{path=`${modpath}${shortty}.${name}.html`}let current_page=document.location.href.toString();if(current_page.endsWith("/")){current_page+="index.html"}const link=document.createElement("a");link.href=path;link.textContent=name;const li=document.createElement("li");if(link.href===current_page){li.classList.add("current")}li.appendChild(link);ul.appendChild(li)}sidebar.appendChild(h3);sidebar.appendChild(ul)}if(sidebar){block("primitive","primitives","Primitive Types");block("mod","modules","Modules");block("macro","macros","Macros");block("struct","structs","Structs");block("enum","enums","Enums");block("constant","constants","Constants");block("static","static","Statics");block("trait","traits","Traits");block("fn","functions","Functions");block("type","types","Type Aliases");block("union","unions","Unions");block("foreigntype","foreign-types","Foreign Types");block("keyword","keywords","Keywords");block("attr","attributes","Attribute Macros");block("derive","derives","Derive Macros");block("traitalias","trait-aliases","Trait Aliases")}}window.register_implementors=imp=>{const implementors=document.getElementById("implementors-list");const synthetic_implementors=document.getElementById("synthetic-implementors-list");const inlined_types=new Set();const TEXT_IDX=0;const SYNTHETIC_IDX=1;const TYPES_IDX=2;if(synthetic_implementors){onEachLazy(synthetic_implementors.getElementsByClassName("impl"),el=>{const aliases=el.getAttribute("data-aliases");if(!aliases){return}aliases.split(",").forEach(alias=>{inlined_types.add(alias)})})}let currentNbImpls=implementors.getElementsByClassName("impl").length;const traitName=document.querySelector(".main-heading h1 > .trait").textContent;const baseIdName="impl-"+traitName+"-";const libs=Object.getOwnPropertyNames(imp);const script=document.querySelector("script[data-ignore-extern-crates]");const ignoreExternCrates=new Set((script?script.getAttribute("data-ignore-extern-crates"):"").split(","),);for(const lib of libs){if(lib===window.currentCrate||ignoreExternCrates.has(lib)){continue}const structs=imp[lib];struct_loop:for(const struct of structs){const list=struct[SYNTHETIC_IDX]?synthetic_implementors:implementors;if(struct[SYNTHETIC_IDX]){for(const struct_type of struct[TYPES_IDX]){if(inlined_types.has(struct_type)){continue struct_loop}inlined_types.add(struct_type)}}const code=document.createElement("h3");code.innerHTML=struct[TEXT_IDX];addClass(code,"code-header");onEachLazy(code.getElementsByTagName("a"),elem=>{const href=elem.getAttribute("href");if(href&&!href.startsWith("#")&&!/^(?:[a-z+]+:)?\/\//.test(href)){elem.setAttribute("href",window.rootPath+href)}});const currentId=baseIdName+currentNbImpls;const anchor=document.createElement("a");anchor.href="#"+currentId;addClass(anchor,"anchor");const display=document.createElement("div");display.id=currentId;addClass(display,"impl");display.appendChild(anchor);display.appendChild(code);list.appendChild(display);currentNbImpls+=1}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}window.register_type_impls=imp=>{if(!imp||!imp[window.currentCrate]){return}window.pending_type_impls=null;const idMap=new Map();let implementations=document.getElementById("implementations-list");let trait_implementations=document.getElementById("trait-implementations-list");let trait_implementations_header=document.getElementById("trait-implementations");const script=document.querySelector("script[data-self-path]");const selfPath=script?script.getAttribute("data-self-path"):null;const mainContent=document.querySelector("#main-content");const sidebarSection=document.querySelector(".sidebar section");let methods=document.querySelector(".sidebar .block.method");let associatedTypes=document.querySelector(".sidebar .block.associatedtype");let associatedConstants=document.querySelector(".sidebar .block.associatedconstant");let sidebarTraitList=document.querySelector(".sidebar .block.trait-implementation");for(const impList of imp[window.currentCrate]){const types=impList.slice(2);const text=impList[0];const isTrait=impList[1]!==0;const traitName=impList[1];if(types.indexOf(selfPath)===-1){continue}let outputList=isTrait?trait_implementations:implementations;if(outputList===null){const outputListName=isTrait?"Trait Implementations":"Implementations";const outputListId=isTrait?"trait-implementations-list":"implementations-list";const outputListHeaderId=isTrait?"trait-implementations":"implementations";const outputListHeader=document.createElement("h2");outputListHeader.id=outputListHeaderId;outputListHeader.innerText=outputListName;outputList=document.createElement("div");outputList.id=outputListId;if(isTrait){const link=document.createElement("a");link.href=`#${outputListHeaderId}`;link.innerText="Trait Implementations";const h=document.createElement("h3");h.appendChild(link);trait_implementations=outputList;trait_implementations_header=outputListHeader;sidebarSection.appendChild(h);sidebarTraitList=document.createElement("ul");sidebarTraitList.className="block trait-implementation";sidebarSection.appendChild(sidebarTraitList);mainContent.appendChild(outputListHeader);mainContent.appendChild(outputList)}else{implementations=outputList;if(trait_implementations){mainContent.insertBefore(outputListHeader,trait_implementations_header);mainContent.insertBefore(outputList,trait_implementations_header)}else{const mainContent=document.querySelector("#main-content");mainContent.appendChild(outputListHeader);mainContent.appendChild(outputList)}}}const template=document.createElement("template");template.innerHTML=text;onEachLazy(template.content.querySelectorAll("a"),elem=>{const href=elem.getAttribute("href");if(href&&!href.startsWith("#")&&!/^(?:[a-z+]+:)?\/\//.test(href)){elem.setAttribute("href",window.rootPath+href)}});onEachLazy(template.content.querySelectorAll("[id]"),el=>{let i=0;if(idMap.has(el.id)){i=idMap.get(el.id)}else if(document.getElementById(el.id)){i=1;while(document.getElementById(`${el.id}-${2 * i}`)){i=2*i}while(document.getElementById(`${el.id}-${i}`)){i+=1}}if(i!==0){const oldHref=`#${el.id}`;const newHref=`#${el.id}-${i}`;el.id=`${el.id}-${i}`;onEachLazy(template.content.querySelectorAll("a[href]"),link=>{if(link.getAttribute("href")===oldHref){link.href=newHref}})}idMap.set(el.id,i+1)});const templateAssocItems=template.content.querySelectorAll("section.tymethod, "+"section.method, section.associatedtype, section.associatedconstant");if(isTrait){const li=document.createElement("li");const a=document.createElement("a");a.href=`#${template.content.querySelector(".impl").id}`;a.textContent=traitName;li.appendChild(a);sidebarTraitList.append(li)}else{onEachLazy(templateAssocItems,item=>{let block=hasClass(item,"associatedtype")?associatedTypes:(hasClass(item,"associatedconstant")?associatedConstants:(methods));if(!block){const blockTitle=hasClass(item,"associatedtype")?"Associated Types":(hasClass(item,"associatedconstant")?"Associated Constants":("Methods"));const blockClass=hasClass(item,"associatedtype")?"associatedtype":(hasClass(item,"associatedconstant")?"associatedconstant":("method"));const blockHeader=document.createElement("h3");const blockLink=document.createElement("a");blockLink.href="#implementations";blockLink.innerText=blockTitle;blockHeader.appendChild(blockLink);block=document.createElement("ul");block.className=`block ${blockClass}`;const insertionReference=methods||sidebarTraitList;if(insertionReference){const insertionReferenceH=insertionReference.previousElementSibling;sidebarSection.insertBefore(blockHeader,insertionReferenceH);sidebarSection.insertBefore(block,insertionReferenceH)}else{sidebarSection.appendChild(blockHeader);sidebarSection.appendChild(block)}if(hasClass(item,"associatedtype")){associatedTypes=block}else if(hasClass(item,"associatedconstant")){associatedConstants=block}else{methods=block}}const li=document.createElement("li");const a=document.createElement("a");a.innerText=item.id.split("-")[0].split(".")[1];a.href=`#${item.id}`;li.appendChild(a);block.appendChild(li)})}outputList.appendChild(template.content)}for(const list of[methods,associatedTypes,associatedConstants,sidebarTraitList]){if(!list){continue}const newChildren=Array.prototype.slice.call(list.children);newChildren.sort((a,b)=>{const aI=a.innerText;const bI=b.innerText;return aIbI?1:0});list.replaceChildren(...newChildren)}};if(window.pending_type_impls){window.register_type_impls(window.pending_type_impls)}function addSidebarCrates(){if(!window.ALL_CRATES){return}const sidebarElems=document.getElementsByClassName("sidebar-elems")[0];if(!sidebarElems){return}const h3=document.createElement("h3");h3.innerHTML="Crates";const ul=document.createElement("ul");ul.className="block crate";for(const crate of window.ALL_CRATES){const link=document.createElement("a");link.href=window.rootPath+crate+"/index.html";link.textContent=crate;const li=document.createElement("li");if(window.rootPath!=="./"&&crate===window.currentCrate){li.className="current"}li.appendChild(link);ul.appendChild(li)}sidebarElems.appendChild(h3);sidebarElems.appendChild(ul)}function expandAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);removeClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hasClass(e,"type-contents-toggle")&&!hasClass(e,"more-examples-toggle")){e.open=true}});innerToggle.title="collapse all docs";innerToggle.children[0].innerText="\u2212"}function collapseAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);addClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(e.parentNode.id!=="implementations-list"||(!hasClass(e,"implementors-toggle")&&!hasClass(e,"type-contents-toggle"))){e.open=false}});innerToggle.title="expand all docs";innerToggle.children[0].innerText="+"}function toggleAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);if(!innerToggle){return}if(hasClass(innerToggle,"will-expand")){expandAllDocs()}else{collapseAllDocs()}}(function(){const toggles=document.getElementById(toggleAllDocsId);if(toggles){toggles.onclick=toggleAllDocs}const hideMethodDocs=getSettingValue("auto-hide-method-docs")==="true";const hideImplementations=getSettingValue("auto-hide-trait-implementations")==="true";const hideLargeItemContents=getSettingValue("auto-hide-large-items")!=="false";function setImplementorsTogglesOpen(id,open){const list=document.getElementById(id);if(list!==null){onEachLazy(list.getElementsByClassName("implementors-toggle"),e=>{e.open=open})}}if(hideImplementations){setImplementorsTogglesOpen("trait-implementations-list",false);setImplementorsTogglesOpen("blanket-implementations-list",false)}onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hideLargeItemContents&&hasClass(e,"type-contents-toggle")){e.open=true}if(hideMethodDocs&&hasClass(e,"method-toggle")){e.open=false}})}());window.rustdoc_add_line_numbers_to_examples=()=>{onEachLazy(document.getElementsByClassName("rust-example-rendered"),x=>{const parent=x.parentNode;const line_numbers=parent.querySelectorAll(".example-line-numbers");if(line_numbers.length>0){return}const count=x.textContent.split("\n").length;const elems=[];for(let i=0;i{onEachLazy(document.getElementsByClassName("rust-example-rendered"),x=>{const parent=x.parentNode;const line_numbers=parent.querySelectorAll(".example-line-numbers");for(const node of line_numbers){parent.removeChild(node)}})};if(getSettingValue("line-numbers")==="true"){window.rustdoc_add_line_numbers_to_examples()}function showSidebar(){window.hideAllModals(false);const sidebar=document.getElementsByClassName("sidebar")[0];addClass(sidebar,"shown")}function hideSidebar(){const sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"shown")}window.addEventListener("resize",()=>{if(window.CURRENT_TOOLTIP_ELEMENT){const base=window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE;const force_visible=base.TOOLTIP_FORCE_VISIBLE;hideTooltip(false);if(force_visible){showTooltip(base);base.TOOLTIP_FORCE_VISIBLE=true}}});const mainElem=document.getElementById(MAIN_ID);if(mainElem){mainElem.addEventListener("click",hideSidebar)}onEachLazy(document.querySelectorAll("a[href^='#']"),el=>{el.addEventListener("click",()=>{expandSection(el.hash.slice(1));hideSidebar()})});onEachLazy(document.querySelectorAll(".toggle > summary:not(.hideme)"),el=>{el.addEventListener("click",e=>{if(e.target.tagName!=="SUMMARY"&&e.target.tagName!=="A"){e.preventDefault()}})});function showTooltip(e){const notable_ty=e.getAttribute("data-notable-ty");if(!window.NOTABLE_TRAITS&¬able_ty){const data=document.getElementById("notable-traits-data");if(data){window.NOTABLE_TRAITS=JSON.parse(data.innerText)}else{throw new Error("showTooltip() called with notable without any notable traits!")}}if(window.CURRENT_TOOLTIP_ELEMENT&&window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE===e){clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);return}window.hideAllModals(false);const wrapper=document.createElement("div");if(notable_ty){wrapper.innerHTML="
"+window.NOTABLE_TRAITS[notable_ty]+"
"}else{if(e.getAttribute("title")!==null){e.setAttribute("data-title",e.getAttribute("title"));e.removeAttribute("title")}if(e.getAttribute("data-title")!==null){const titleContent=document.createElement("div");titleContent.className="content";titleContent.appendChild(document.createTextNode(e.getAttribute("data-title")));wrapper.appendChild(titleContent)}}wrapper.className="tooltip popover";const focusCatcher=document.createElement("div");focusCatcher.setAttribute("tabindex","0");focusCatcher.onfocus=hideTooltip;wrapper.appendChild(focusCatcher);const pos=e.getBoundingClientRect();wrapper.style.top=(pos.top+window.scrollY+pos.height)+"px";wrapper.style.left=0;wrapper.style.right="auto";wrapper.style.visibility="hidden";document.body.appendChild(wrapper);const wrapperPos=wrapper.getBoundingClientRect();const finalPos=pos.left+window.scrollX-wrapperPos.width+24;if(finalPos>0){wrapper.style.left=finalPos+"px"}else{wrapper.style.setProperty("--popover-arrow-offset",(wrapperPos.right-pos.right+4)+"px",)}wrapper.style.visibility="";window.CURRENT_TOOLTIP_ELEMENT=wrapper;window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE=e;clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);wrapper.onpointerenter=ev=>{if(ev.pointerType!=="mouse"){return}clearTooltipHoverTimeout(e)};wrapper.onpointerleave=ev=>{if(ev.pointerType!=="mouse"){return}if(!e.TOOLTIP_FORCE_VISIBLE&&!e.contains(ev.relatedTarget)){setTooltipHoverTimeout(e,false);addClass(wrapper,"fade-out")}}}function setTooltipHoverTimeout(element,show){clearTooltipHoverTimeout(element);if(!show&&!window.CURRENT_TOOLTIP_ELEMENT){return}if(show&&window.CURRENT_TOOLTIP_ELEMENT){return}if(window.CURRENT_TOOLTIP_ELEMENT&&window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE!==element){return}element.TOOLTIP_HOVER_TIMEOUT=setTimeout(()=>{if(show){showTooltip(element)}else if(!element.TOOLTIP_FORCE_VISIBLE){hideTooltip(false)}},show?window.RUSTDOC_TOOLTIP_HOVER_MS:window.RUSTDOC_TOOLTIP_HOVER_EXIT_MS)}function clearTooltipHoverTimeout(element){if(element.TOOLTIP_HOVER_TIMEOUT!==undefined){removeClass(window.CURRENT_TOOLTIP_ELEMENT,"fade-out");clearTimeout(element.TOOLTIP_HOVER_TIMEOUT);delete element.TOOLTIP_HOVER_TIMEOUT}}function tooltipBlurHandler(event){if(window.CURRENT_TOOLTIP_ELEMENT&&!window.CURRENT_TOOLTIP_ELEMENT.contains(document.activeElement)&&!window.CURRENT_TOOLTIP_ELEMENT.contains(event.relatedTarget)&&!window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.contains(document.activeElement)&&!window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.contains(event.relatedTarget)){setTimeout(()=>hideTooltip(false),0)}}function hideTooltip(focus){if(window.CURRENT_TOOLTIP_ELEMENT){if(window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE){if(focus){window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.focus()}window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE=false}document.body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);window.CURRENT_TOOLTIP_ELEMENT=null}}onEachLazy(document.getElementsByClassName("tooltip"),e=>{e.onclick=()=>{e.TOOLTIP_FORCE_VISIBLE=e.TOOLTIP_FORCE_VISIBLE?false:true;if(window.CURRENT_TOOLTIP_ELEMENT&&!e.TOOLTIP_FORCE_VISIBLE){hideTooltip(true)}else{showTooltip(e);window.CURRENT_TOOLTIP_ELEMENT.setAttribute("tabindex","0");window.CURRENT_TOOLTIP_ELEMENT.focus();window.CURRENT_TOOLTIP_ELEMENT.onblur=tooltipBlurHandler}return false};e.onpointerenter=ev=>{if(ev.pointerType!=="mouse"){return}setTooltipHoverTimeout(e,true)};e.onpointermove=ev=>{if(ev.pointerType!=="mouse"){return}setTooltipHoverTimeout(e,true)};e.onpointerleave=ev=>{if(ev.pointerType!=="mouse"){return}if(!e.TOOLTIP_FORCE_VISIBLE&&window.CURRENT_TOOLTIP_ELEMENT&&!window.CURRENT_TOOLTIP_ELEMENT.contains(ev.relatedTarget)){setTooltipHoverTimeout(e,false);addClass(window.CURRENT_TOOLTIP_ELEMENT,"fade-out")}}});const sidebar_menu_toggle=document.getElementsByClassName("sidebar-menu-toggle")[0];if(sidebar_menu_toggle){sidebar_menu_toggle.addEventListener("click",()=>{const sidebar=document.getElementsByClassName("sidebar")[0];if(!hasClass(sidebar,"shown")){showSidebar()}else{hideSidebar()}})}function helpBlurHandler(event){blurHandler(event,getHelpButton(),window.hidePopoverMenus)}function buildHelpMenu(){const book_info=document.createElement("span");const channel=getVar("channel");book_info.className="top";book_info.innerHTML=`You can find more information in \ +the rustdoc book.`;const shortcuts=[["?","Show this help dialog"],["S / /","Focus the search field"],["↑","Move up in search results"],["↓","Move down in search results"],["← / →","Switch result tab (when results focused)"],["⏎","Go to active search result"],["+","Expand all sections"],["-","Collapse all sections"],].map(x=>"
"+x[0].split(" ").map((y,index)=>((index&1)===0?""+y+"":" "+y+" ")).join("")+"
"+x[1]+"
").join("");const div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

Keyboard Shortcuts

"+shortcuts+"
";const infos=[`For a full list of all search features, take a look here.`,"Prefix searches with a type followed by a colon (e.g., fn:) to \ + restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \ + enum, trait, type, macro, \ + and const.","Search functions by type signature (e.g., vec -> usize or \ + -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \ + your request: \"string\"","Look for functions that accept or return \ + slices and \ + arrays by writing \ + square brackets (e.g., -> [u8] or [] -> Option)","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

"+x+"

").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

Search Tricks

"+infos;const rustdoc_version=document.createElement("span");rustdoc_version.className="bottom";const rustdoc_version_code=document.createElement("code");rustdoc_version_code.innerText="rustdoc "+getVar("rustdoc-version");rustdoc_version.appendChild(rustdoc_version_code);const container=document.createElement("div");if(!isHelpPage){container.className="popover"}container.id="help";container.style.display="none";const side_by_side=document.createElement("div");side_by_side.className="side-by-side";side_by_side.appendChild(div_shortcuts);side_by_side.appendChild(div_infos);container.appendChild(book_info);container.appendChild(side_by_side);container.appendChild(rustdoc_version);if(isHelpPage){const help_section=document.createElement("section");help_section.appendChild(container);document.getElementById("main-content").appendChild(help_section);container.style.display="block"}else{const help_button=getHelpButton();help_button.appendChild(container);container.onblur=helpBlurHandler;help_button.onblur=helpBlurHandler;help_button.children[0].onblur=helpBlurHandler}return container}window.hideAllModals=switchFocus=>{hideSidebar();window.hidePopoverMenus();hideTooltip(switchFocus)};window.hidePopoverMenus=()=>{onEachLazy(document.querySelectorAll(".search-form .popover"),elem=>{elem.style.display="none"})};function getHelpMenu(buildNeeded){let menu=getHelpButton().querySelector(".popover");if(!menu&&buildNeeded){menu=buildHelpMenu()}return menu}function showHelp(){getHelpButton().querySelector("a").focus();const menu=getHelpMenu(true);if(menu.style.display==="none"){window.hideAllModals();menu.style.display=""}}if(isHelpPage){showHelp();document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click",event=>{const target=event.target;if(target.tagName!=="A"||target.parentElement.id!==HELP_BUTTON_ID||event.ctrlKey||event.altKey||event.metaKey){return}event.preventDefault()})}else{document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click",event=>{const target=event.target;if(target.tagName!=="A"||target.parentElement.id!==HELP_BUTTON_ID||event.ctrlKey||event.altKey||event.metaKey){return}event.preventDefault();const menu=getHelpMenu(true);const shouldShowHelp=menu.style.display==="none";if(shouldShowHelp){showHelp()}else{window.hidePopoverMenus()}})}setMobileTopbar();addSidebarItems();addSidebarCrates();onHashChange(null);window.addEventListener("hashchange",onHashChange);searchState.setup()}());(function(){const SIDEBAR_MIN=100;const SIDEBAR_MAX=500;const RUSTDOC_MOBILE_BREAKPOINT=700;const BODY_MIN=400;const SIDEBAR_VANISH_THRESHOLD=SIDEBAR_MIN/2;const sidebarButton=document.getElementById("sidebar-button");if(sidebarButton){sidebarButton.addEventListener("click",e=>{removeClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","false");if(document.querySelector(".rustdoc.src")){window.rustdocToggleSrcSidebar()}e.preventDefault()})}let currentPointerId=null;let desiredSidebarSize=null;let pendingSidebarResizingFrame=false;const resizer=document.querySelector(".sidebar-resizer");const sidebar=document.querySelector(".sidebar");if(!resizer||!sidebar){return}const isSrcPage=hasClass(document.body,"src");function hideSidebar(){if(isSrcPage){window.rustdocCloseSourceSidebar();updateLocalStorage("src-sidebar-width",null);document.documentElement.style.removeProperty("--src-sidebar-width");sidebar.style.removeProperty("--src-sidebar-width");resizer.style.removeProperty("--src-sidebar-width")}else{addClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","true");updateLocalStorage("desktop-sidebar-width",null);document.documentElement.style.removeProperty("--desktop-sidebar-width");sidebar.style.removeProperty("--desktop-sidebar-width");resizer.style.removeProperty("--desktop-sidebar-width")}}function showSidebar(){if(isSrcPage){window.rustdocShowSourceSidebar()}else{removeClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","false")}}function changeSidebarSize(size){if(isSrcPage){updateLocalStorage("src-sidebar-width",size);sidebar.style.setProperty("--src-sidebar-width",size+"px");resizer.style.setProperty("--src-sidebar-width",size+"px")}else{updateLocalStorage("desktop-sidebar-width",size);sidebar.style.setProperty("--desktop-sidebar-width",size+"px");resizer.style.setProperty("--desktop-sidebar-width",size+"px")}}function isSidebarHidden(){return isSrcPage?!hasClass(document.documentElement,"src-sidebar-expanded"):hasClass(document.documentElement,"hide-sidebar")}function resize(e){if(currentPointerId===null||currentPointerId!==e.pointerId){return}e.preventDefault();const pos=e.clientX-3;if(pos=SIDEBAR_MIN){if(isSidebarHidden()){showSidebar()}const constrainedPos=Math.min(pos,window.innerWidth-BODY_MIN,SIDEBAR_MAX);changeSidebarSize(constrainedPos);desiredSidebarSize=constrainedPos;if(pendingSidebarResizingFrame!==false){clearTimeout(pendingSidebarResizingFrame)}pendingSidebarResizingFrame=setTimeout(()=>{if(currentPointerId===null||pendingSidebarResizingFrame===false){return}pendingSidebarResizingFrame=false;document.documentElement.style.setProperty("--resizing-sidebar-width",desiredSidebarSize+"px",)},100)}}window.addEventListener("resize",()=>{if(window.innerWidth=(window.innerWidth-BODY_MIN)){changeSidebarSize(window.innerWidth-BODY_MIN)}else if(desiredSidebarSize!==null&&desiredSidebarSize>SIDEBAR_MIN){changeSidebarSize(desiredSidebarSize)}});function stopResize(e){if(currentPointerId===null){return}if(e){e.preventDefault()}desiredSidebarSize=sidebar.getBoundingClientRect().width;removeClass(resizer,"active");window.removeEventListener("pointermove",resize,false);window.removeEventListener("pointerup",stopResize,false);removeClass(document.documentElement,"sidebar-resizing");document.documentElement.style.removeProperty("--resizing-sidebar-width");if(resizer.releasePointerCapture){resizer.releasePointerCapture(currentPointerId);currentPointerId=null}}function initResize(e){if(currentPointerId!==null||e.altKey||e.ctrlKey||e.metaKey||e.button!==0){return}if(resizer.setPointerCapture){resizer.setPointerCapture(e.pointerId);if(!resizer.hasPointerCapture(e.pointerId)){resizer.releasePointerCapture(e.pointerId);return}currentPointerId=e.pointerId}window.hideAllModals(false);e.preventDefault();window.addEventListener("pointermove",resize,false);window.addEventListener("pointercancel",stopResize,false);window.addEventListener("pointerup",stopResize,false);addClass(resizer,"active");addClass(document.documentElement,"sidebar-resizing");const pos=e.clientX-sidebar.offsetLeft-3;document.documentElement.style.setProperty("--resizing-sidebar-width",pos+"px");desiredSidebarSize=null}resizer.addEventListener("pointerdown",initResize,false)}());(function(){function copyContentToClipboard(content){const el=document.createElement("textarea");el.value=content;el.setAttribute("readonly","");el.style.position="absolute";el.style.left="-9999px";document.body.appendChild(el);el.select();document.execCommand("copy");document.body.removeChild(el)}function copyButtonAnimation(button){button.classList.add("clicked");if(button.reset_button_timeout!==undefined){window.clearTimeout(button.reset_button_timeout)}button.reset_button_timeout=window.setTimeout(()=>{button.reset_button_timeout=undefined;button.classList.remove("clicked")},1000)}const but=document.getElementById("copy-path");if(!but){return}but.onclick=()=>{const parent=but.parentElement;const path=[];onEach(parent.childNodes,child=>{if(child.tagName==="A"){path.push(child.textContent)}});copyContentToClipboard(path.join("::"));copyButtonAnimation(but)};function copyCode(codeElem){if(!codeElem){return}copyContentToClipboard(codeElem.textContent)}function getExampleWrap(event){let elem=event.target;while(!hasClass(elem,"example-wrap")){if(elem===document.body||elem.tagName==="A"||elem.tagName==="BUTTON"||hasClass(elem,"docblock")){return null}elem=elem.parentElement}return elem}function addCopyButton(event){const elem=getExampleWrap(event);if(elem===null){return}elem.removeEventListener("mouseover",addCopyButton);const parent=document.createElement("div");parent.className="button-holder";const runButton=elem.querySelector(".test-arrow");if(runButton!==null){parent.appendChild(runButton)}elem.appendChild(parent);const copyButton=document.createElement("button");copyButton.className="copy-button";copyButton.title="Copy code to clipboard";copyButton.addEventListener("click",()=>{copyCode(elem.querySelector("pre > code"));copyButtonAnimation(copyButton)});parent.appendChild(copyButton)}function showHideCodeExampleButtons(event){const elem=getExampleWrap(event);if(elem===null){return}let buttons=elem.querySelector(".button-holder");if(buttons===null){addCopyButton(event);buttons=elem.querySelector(".button-holder");if(buttons===null){return}}buttons.classList.toggle("keep-visible")}onEachLazy(document.querySelectorAll(".docblock .example-wrap"),elem=>{elem.addEventListener("mouseover",addCopyButton);elem.addEventListener("click",showHideCodeExampleButtons)})}()) \ No newline at end of file diff --git a/static.files/normalize-76eba96aa4d2e634.css b/static.files/normalize-76eba96aa4d2e634.css new file mode 100644 index 00000000..469959f1 --- /dev/null +++ b/static.files/normalize-76eba96aa4d2e634.css @@ -0,0 +1,2 @@ + /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ +html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none} \ No newline at end of file diff --git a/static.files/noscript-3b12f09e550e0385.css b/static.files/noscript-3b12f09e550e0385.css new file mode 100644 index 00000000..befe4163 --- /dev/null +++ b/static.files/noscript-3b12f09e550e0385.css @@ -0,0 +1 @@ + #main-content .attributes{margin-left:0 !important;}#copy-path,#sidebar-button,.sidebar-resizer{display:none !important;}nav.sub{display:none;}.src .sidebar{display:none;}.notable-traits{display:none;}:root,:root:not([data-theme]){--main-background-color:white;--main-color:black;--settings-input-color:#2196f3;--settings-input-border-color:#717171;--settings-button-color:#000;--settings-button-border-focus:#717171;--sidebar-background-color:#f5f5f5;--sidebar-background-color-hover:#e0e0e0;--code-block-background-color:#f5f5f5;--scrollbar-track-background-color:#dcdcdc;--scrollbar-thumb-background-color:rgba(36,37,39,0.6);--scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;--headings-border-bottom-color:#ddd;--border-color:#e0e0e0;--button-background-color:#fff;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:none;--mobile-sidebar-menu-filter:none;--search-input-focused-border-color:#66afe9;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(35%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ad378a;--trait-link-color:#6e4fc9;--assoc-item-link-color:#3873ad;--function-link-color:#ad7c37;--macro-link-color:#068000;--keyword-link-color:#3873ad;--mod-link-color:#3873ad;--link-color:#3873ad;--sidebar-link-color:#356da4;--sidebar-current-link-background-color:#fff;--search-result-link-focus-background-color:#ccc;--search-result-border-color:#aaa3;--search-color:#000;--search-error-code-background-color:#d0cccc;--search-results-alias-color:#000;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#e6e6e6;--search-tab-button-not-selected-background:#e6e6e6;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#fff;--settings-menu-filter:none;--stab-background-color:#fff5d6;--stab-code-color:#000;--code-highlight-kw-color:#8959a8;--code-highlight-kw-2-color:#4271ae;--code-highlight-lifetime-color:#b76514;--code-highlight-prelude-color:#4271ae;--code-highlight-prelude-val-color:#c82829;--code-highlight-number-color:#718c00;--code-highlight-string-color:#718c00;--code-highlight-literal-color:#c82829;--code-highlight-attribute-color:#c82829;--code-highlight-self-color:#c82829;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8e908c;--code-highlight-doc-comment-color:#4d4d4c;--src-line-numbers-span-color:#c67e2d;--src-line-number-highlighted-background-color:#fdffd3;--target-background-color:#fdffd3;--target-border-color:#ad7c37;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:initial;--crate-search-div-filter:invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);--crate-search-div-hover-filter:invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);--crate-search-hover-border:#717171;--src-sidebar-background-selected:#fff;--src-sidebar-background-hover:#e0e0e0;--table-alt-row-background-color:#f5f5f5;--codeblock-link-background:#eee;--scrape-example-toggle-line-background:#ccc;--scrape-example-toggle-line-hover-background:#999;--scrape-example-code-line-highlight:#fcffd6;--scrape-example-code-line-highlight-focus:#f6fdb0;--scrape-example-help-border-color:#555;--scrape-example-help-color:#333;--scrape-example-help-hover-border-color:#000;--scrape-example-help-hover-color:#000;--scrape-example-code-wrapper-background-start:rgba(255,255,255,1);--scrape-example-code-wrapper-background-end:rgba(255,255,255,0);--sidebar-resizer-hover:hsl(207,90%,66%);--sidebar-resizer-active:hsl(207,90%,54%);}@media (prefers-color-scheme:dark){:root,:root:not([data-theme]){--main-background-color:#353535;--main-color:#ddd;--settings-input-color:#2196f3;--settings-input-border-color:#999;--settings-button-color:#000;--settings-button-border-focus:#ffb900;--sidebar-background-color:#505050;--sidebar-background-color-hover:#676767;--code-block-background-color:#2A2A2A;--scrollbar-track-background-color:#717171;--scrollbar-thumb-background-color:rgba(32,34,37,.6);--scrollbar-color:rgba(32,34,37,.6) #5a5a5a;--headings-border-bottom-color:#d2d2d2;--border-color:#e0e0e0;--button-background-color:#f0f0f0;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#008dfd;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(65%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#2dbfb8;--trait-link-color:#b78cf2;--assoc-item-link-color:#d2991d;--function-link-color:#2bab63;--macro-link-color:#09bd00;--keyword-link-color:#d2991d;--mod-link-color:#d2991d;--link-color:#d2991d;--sidebar-link-color:#fdbf35;--sidebar-current-link-background-color:#444;--search-result-link-focus-background-color:#616161;--search-result-border-color:#aaa3;--search-color:#111;--search-error-code-background-color:#484848;--search-results-alias-color:#fff;--search-results-grey-color:#ccc;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#252525;--search-tab-button-not-selected-background:#252525;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#353535;--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ab8ac1;--code-highlight-kw-2-color:#769acb;--code-highlight-lifetime-color:#d97f26;--code-highlight-prelude-color:#769acb;--code-highlight-prelude-val-color:#ee6868;--code-highlight-number-color:#83a300;--code-highlight-string-color:#83a300;--code-highlight-literal-color:#ee6868;--code-highlight-attribute-color:#ee6868;--code-highlight-self-color:#ee6868;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8d8d8b;--code-highlight-doc-comment-color:#8ca375;--src-line-numbers-span-color:#3b91e2;--src-line-number-highlighted-background-color:#0a042f;--target-background-color:#494a3d;--target-border-color:#bb7410;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%);--crate-search-div-hover-filter:invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);--crate-search-hover-border:#2196f3;--src-sidebar-background-selected:#333;--src-sidebar-background-hover:#444;--table-alt-row-background-color:#2a2a2a;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(53,53,53,1);--scrape-example-code-wrapper-background-end:rgba(53,53,53,0);--sidebar-resizer-hover:hsl(207,30%,54%);--sidebar-resizer-active:hsl(207,90%,54%);}} \ No newline at end of file diff --git a/static.files/rust-logo-151179464ae7ed46.svg b/static.files/rust-logo-151179464ae7ed46.svg new file mode 100644 index 00000000..62424d8f --- /dev/null +++ b/static.files/rust-logo-151179464ae7ed46.svg @@ -0,0 +1,61 @@ + + + diff --git a/static.files/rustdoc-492a78a4a87dcc01.css b/static.files/rustdoc-492a78a4a87dcc01.css new file mode 100644 index 00000000..e9199f95 --- /dev/null +++ b/static.files/rustdoc-492a78a4a87dcc01.css @@ -0,0 +1,47 @@ + :root{--nav-sub-mobile-padding:8px;--search-typename-width:6.75rem;--desktop-sidebar-width:200px;--src-sidebar-width:300px;--desktop-sidebar-z-index:100;--sidebar-elems-left-padding:24px;--clipboard-image:url('data:image/svg+xml,\ +\ +\ +');--copy-path-height:34px;--copy-path-width:33px;--checkmark-image:url('data:image/svg+xml,\ +\ +');--button-left-margin:4px;--button-border-radius:2px;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular-018c141bf0843ffd.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium-8f9a781e4970d388.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:400;src:local('Source Serif 4'),url("SourceSerif4-Regular-46f98efaafac5295.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:italic;font-weight:400;src:local('Source Serif 4 Italic'),url("SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:700;src:local('Source Serif 4 Bold'),url("SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:italic;font-weight:400;src:url("SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'NanumBarunGothic';src:url("NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2") format("woff2");font-display:swap;unicode-range:U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF;}*{box-sizing:border-box;}body{font:1rem/1.5 "Source Serif 4",NanumBarunGothic,serif;margin:0;position:relative;overflow-wrap:break-word;overflow-wrap:anywhere;font-feature-settings:"kern","liga";background-color:var(--main-background-color);color:var(--main-color);}h1{font-size:1.5rem;}h2{font-size:1.375rem;}h3{font-size:1.25rem;}h1,h2,h3,h4,h5,h6{font-weight:500;}h1,h2,h3,h4{margin:25px 0 15px 0;padding-bottom:6px;}.docblock h3,.docblock h4,h5,h6{margin:15px 0 5px 0;}.docblock>h2:first-child,.docblock>h3:first-child,.docblock>h4:first-child,.docblock>h5:first-child,.docblock>h6:first-child{margin-top:0;}.main-heading h1{margin:0;padding:0;flex-grow:1;overflow-wrap:break-word;overflow-wrap:anywhere;}.main-heading{display:flex;flex-wrap:wrap;padding-bottom:6px;margin-bottom:15px;}.content h2,.top-doc .docblock>h3,.top-doc .docblock>h4{border-bottom:1px solid var(--headings-border-bottom-color);}h1,h2{line-height:1.25;padding-top:3px;padding-bottom:9px;}h3.code-header{font-size:1.125rem;}h4.code-header{font-size:1rem;}.code-header{font-weight:600;margin:0;padding:0;white-space:pre-wrap;}#crate-search,h1,h2,h3,h4,h5,h6,.sidebar,.mobile-topbar,.search-input,.search-results .result-name,.item-name>a,.out-of-band,span.since,a.src,#help-button>a,summary.hideme,.scraped-example-list,ul.all-items{font-family:"Fira Sans",Arial,NanumBarunGothic,sans-serif;}#toggle-all-docs,a.anchor,.section-header a,#src-sidebar a,.rust a,.sidebar h2 a,.sidebar h3 a,.mobile-topbar h2 a,h1 a,.search-results a,.stab,.result-name i{color:var(--main-color);}span.enum,a.enum,span.struct,a.struct,span.union,a.union,span.primitive,a.primitive,span.type,a.type,span.foreigntype,a.foreigntype{color:var(--type-link-color);}span.trait,a.trait,span.traitalias,a.traitalias{color:var(--trait-link-color);}span.associatedtype,a.associatedtype,span.constant,a.constant,span.static,a.static{color:var(--assoc-item-link-color);}span.fn,a.fn,span.method,a.method,span.tymethod,a.tymethod{color:var(--function-link-color);}span.attr,a.attr,span.derive,a.derive,span.macro,a.macro{color:var(--macro-link-color);}span.mod,a.mod{color:var(--mod-link-color);}span.keyword,a.keyword{color:var(--keyword-link-color);}a{color:var(--link-color);text-decoration:none;}ol,ul{padding-left:24px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.625em;}p,.docblock>.warning{margin:0 0 .75em 0;}p:last-child,.docblock>.warning:last-child{margin:0;}button{padding:1px 6px;cursor:pointer;}button#toggle-all-docs{padding:0;background:none;border:none;-webkit-appearance:none;opacity:1;}.rustdoc{display:flex;flex-direction:row;flex-wrap:nowrap;}main{position:relative;flex-grow:1;padding:10px 15px 40px 45px;min-width:0;}.src main{padding:15px;}.width-limiter{max-width:960px;margin-right:auto;}details:not(.toggle) summary{margin-bottom:.6em;}code,pre,.code-header{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.125em;}.docblock pre code,.docblock-short pre code{padding:0;}pre{padding:14px;line-height:1.5;}pre.item-decl{overflow-x:auto;}.item-decl .type-contents-toggle{contain:initial;}.src .content pre{padding:20px;}.rustdoc.src .example-wrap pre.src-line-numbers{padding:20px 0 20px 4px;}img{max-width:100%;}.logo-container{line-height:0;display:block;}.rust-logo{filter:var(--rust-logo-filter);}.sidebar{font-size:0.875rem;flex:0 0 var(--desktop-sidebar-width);width:var(--desktop-sidebar-width);overflow-y:scroll;overscroll-behavior:contain;position:sticky;height:100vh;top:0;left:0;z-index:var(--desktop-sidebar-z-index);}.rustdoc.src .sidebar{flex-basis:50px;width:50px;border-right:1px solid;overflow-x:hidden;overflow-y:hidden;}.hide-sidebar .sidebar,.hide-sidebar .sidebar-resizer{display:none;}.sidebar-resizer{touch-action:none;width:9px;cursor:col-resize;z-index:calc(var(--desktop-sidebar-z-index) + 1);position:fixed;height:100%;left:calc(var(--desktop-sidebar-width) + 1px);}.rustdoc.src .sidebar-resizer{left:49px;}.src-sidebar-expanded .src .sidebar-resizer{left:var(--src-sidebar-width);}.sidebar-resizing{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;}.sidebar-resizing*{cursor:col-resize !important;}.sidebar-resizing .sidebar{position:fixed;}.sidebar-resizing>body{padding-left:var(--resizing-sidebar-width);}.sidebar-resizer:hover,.sidebar-resizer:active,.sidebar-resizer:focus,.sidebar-resizer.active{width:10px;margin:0;left:var(--desktop-sidebar-width);border-left:solid 1px var(--sidebar-resizer-hover);}.src-sidebar-expanded .rustdoc.src .sidebar-resizer:hover,.src-sidebar-expanded .rustdoc.src .sidebar-resizer:active,.src-sidebar-expanded .rustdoc.src .sidebar-resizer:focus,.src-sidebar-expanded .rustdoc.src .sidebar-resizer.active{left:calc(var(--src-sidebar-width) - 1px);}@media (pointer:coarse){.sidebar-resizer{display:none !important;}}.sidebar-resizer.active{padding:0 140px;width:2px;margin-left:-140px;border-left:none;}.sidebar-resizer.active:before{border-left:solid 2px var(--sidebar-resizer-active);display:block;height:100%;content:"";}.sidebar,.mobile-topbar,.sidebar-menu-toggle,#src-sidebar{background-color:var(--sidebar-background-color);}.src .sidebar>*{visibility:hidden;}.src-sidebar-expanded .src .sidebar{overflow-y:auto;flex-basis:var(--src-sidebar-width);width:var(--src-sidebar-width);}.src-sidebar-expanded .src .sidebar>*{visibility:visible;}#all-types{margin-top:1em;}*{scrollbar-width:initial;scrollbar-color:var(--scrollbar-color);}.sidebar{scrollbar-width:thin;scrollbar-color:var(--scrollbar-color);}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;background-color:var(--scrollbar-track-background-color);}.sidebar::-webkit-scrollbar-track{background-color:var(--scrollbar-track-background-color);}::-webkit-scrollbar-thumb,.sidebar::-webkit-scrollbar-thumb{background-color:var(--scrollbar-thumb-background-color);}.hidden{display:none !important;}.logo-container>img{height:48px;width:48px;}ul.block,.block li{padding:0;margin:0;list-style:none;}.sidebar-elems a,.sidebar>h2 a{display:block;padding:0.25rem;margin-right:0.25rem;border-left:solid var(--sidebar-elems-left-padding) transparent;margin-left:calc(-0.25rem - var(--sidebar-elems-left-padding));background-clip:border-box;}.sidebar h2{text-wrap:balance;overflow-wrap:anywhere;padding:0;margin:0.7rem 0;}.sidebar h3{text-wrap:balance;overflow-wrap:anywhere;font-size:1.125rem;padding:0;margin:0;}.sidebar-elems,.sidebar>.version,.sidebar>h2{padding-left:var(--sidebar-elems-left-padding);}.sidebar a{color:var(--sidebar-link-color);}.sidebar .current,.sidebar .current a,.sidebar-crate a.logo-container:hover+h2 a,.sidebar a:hover:not(.logo-container){background-color:var(--sidebar-current-link-background-color);}.sidebar-elems .block{margin-bottom:2em;}.sidebar-elems .block li a{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;}.sidebar-crate{display:flex;align-items:center;justify-content:center;margin:14px 32px 1rem;row-gap:10px;column-gap:32px;flex-wrap:wrap;}.sidebar-crate h2{flex-grow:1;margin:0 -8px;align-self:start;}.sidebar-crate .logo-container{margin:0 calc(-16px - var(--sidebar-elems-left-padding));padding:0 var(--sidebar-elems-left-padding);text-align:center;}.sidebar-crate .logo-container img{margin-top:-16px;border-top:solid 16px transparent;box-sizing:content-box;position:relative;background-clip:border-box;z-index:1;}.sidebar-crate h2 a{display:block;border-left:solid var(--sidebar-elems-left-padding) transparent;background-clip:border-box;margin:0 calc(-24px + 0.25rem) 0 calc(-0.2rem - var(--sidebar-elems-left-padding));padding:calc((16px - 0.57rem ) / 2 ) 0.25rem;padding-left:0.2rem;}.sidebar-crate h2 .version{display:block;font-weight:normal;font-size:1rem;overflow-wrap:break-word;}.sidebar-crate+.version{margin-top:-1rem;margin-bottom:1rem;}.mobile-topbar{display:none;}.rustdoc .example-wrap{display:flex;position:relative;margin-bottom:10px;}.rustdoc .example-wrap>pre{border-radius:6px;}.rustdoc .example-wrap:last-child{margin-bottom:0px;}.rustdoc .example-wrap pre{margin:0;flex-grow:1;}.rustdoc:not(.src) .example-wrap pre{overflow:auto hidden;}.rustdoc .example-wrap pre.example-line-numbers,.rustdoc .example-wrap pre.src-line-numbers{flex-grow:0;min-width:fit-content;overflow:initial;text-align:right;-webkit-user-select:none;user-select:none;padding:14px 8px;color:var(--src-line-numbers-span-color);}.rustdoc .example-wrap pre.src-line-numbers{padding:14px 0;}.src-line-numbers a,.src-line-numbers span{color:var(--src-line-numbers-span-color);padding:0 8px;}.src-line-numbers :target{background-color:transparent;border-right:none;padding:0 8px;}.src-line-numbers .line-highlighted{background-color:var(--src-line-number-highlighted-background-color);}.search-loading{text-align:center;}.docblock-short{overflow-wrap:break-word;overflow-wrap:anywhere;}.docblock :not(pre)>code,.docblock-short code{white-space:pre-wrap;}.top-doc .docblock h2{font-size:1.375rem;}.top-doc .docblock h3{font-size:1.25rem;}.top-doc .docblock h4,.top-doc .docblock h5{font-size:1.125rem;}.top-doc .docblock h6{font-size:1rem;}.docblock h5{font-size:1rem;}.docblock h6{font-size:0.875rem;}.docblock{margin-left:24px;position:relative;}.docblock>:not(.more-examples-toggle):not(.example-wrap){max-width:100%;overflow-x:auto;}.out-of-band{flex-grow:0;font-size:1.125rem;}.docblock code,.docblock-short code,pre,.rustdoc.src .example-wrap{background-color:var(--code-block-background-color);}#main-content{position:relative;}.docblock table{margin:.5em 0;border-collapse:collapse;}.docblock table td,.docblock table th{padding:.5em;border:1px solid var(--border-color);}.docblock table tbody tr:nth-child(2n){background:var(--table-alt-row-background-color);}.docblock .stab,.docblock-short .stab{display:inline-block;}div.where{white-space:pre-wrap;font-size:0.875rem;}.item-info{display:block;margin-left:24px;}.item-info code{font-size:0.875rem;}#main-content>.item-info{margin-left:0;}nav.sub{flex-grow:1;flex-flow:row nowrap;margin:4px 0 25px 0;display:flex;align-items:center;}.search-form{position:relative;display:flex;height:34px;flex-grow:1;}.src nav.sub{margin:0 0 15px 0;}.section-header{display:block;position:relative;}.section-header:hover>.anchor,.impl:hover>.anchor,.trait-impl:hover>.anchor,.variant:hover>.anchor{display:initial;}.anchor{display:none;position:absolute;left:-0.5em;background:none !important;}.anchor.field{left:-5px;}.section-header>.anchor{left:-15px;padding-right:8px;}h2.section-header>.anchor{padding-right:6px;}a.doc-anchor{color:var(--main-color);display:none;position:absolute;left:-17px;padding-right:10px;padding-left:3px;}*:hover>.doc-anchor{display:block;}.top-doc>.docblock>*:first-child>.doc-anchor{display:none !important;}.main-heading a:hover,.example-wrap .rust a:hover,.all-items a:hover,.docblock a:not(.scrape-help):not(.tooltip):hover:not(.doc-anchor),.docblock-short a:not(.scrape-help):not(.tooltip):hover,.item-info a{text-decoration:underline;}.crate.block li.current a{font-weight:500;}table,.item-table{overflow-wrap:break-word;}.item-table{display:table;padding:0;margin:0;width:100%;}.item-table>li{display:table-row;}.item-table>li>div{display:table-cell;}.item-table>li>.item-name{padding-right:1.25rem;}.search-results-title{margin-top:0;white-space:nowrap;display:flex;align-items:baseline;}#crate-search-div{position:relative;min-width:5em;}#crate-search{min-width:115px;padding:0 23px 0 4px;max-width:100%;text-overflow:ellipsis;border:1px solid var(--border-color);border-radius:4px;outline:none;cursor:pointer;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;background-color:var(--main-background-color);color:inherit;line-height:1.5;font-weight:500;}#crate-search:hover,#crate-search:focus{border-color:var(--crate-search-hover-border);}#crate-search-div::after{pointer-events:none;width:100%;height:100%;position:absolute;top:0;left:0;content:"";background-repeat:no-repeat;background-size:20px;background-position:calc(100% - 2px) 56%;background-image:url('data:image/svg+xml, \ + ');filter:var(--crate-search-div-filter);}#crate-search-div:hover::after,#crate-search-div:focus-within::after{filter:var(--crate-search-div-hover-filter);}#crate-search>option{font-size:1rem;}.search-input{-webkit-appearance:none;outline:none;border:1px solid var(--border-color);border-radius:2px;padding:8px;font-size:1rem;flex-grow:1;background-color:var(--button-background-color);color:var(--search-color);}.search-input:focus{border-color:var(--search-input-focused-border-color);}.search-results{display:none;}.search-results.active{display:block;}.search-results>a{display:flex;margin-left:2px;margin-right:2px;border-bottom:1px solid var(--search-result-border-color);gap:1em;}.search-results>a>div.desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex:2;}.search-results a:hover,.search-results a:focus{background-color:var(--search-result-link-focus-background-color);}.search-results .result-name{display:flex;align-items:center;justify-content:start;flex:3;}.search-results .result-name .alias{color:var(--search-results-alias-color);}.search-results .result-name .grey{color:var(--search-results-grey-color);}.search-results .result-name .typename{color:var(--search-results-grey-color);font-size:0.875rem;width:var(--search-typename-width);}.search-results .result-name .path{word-break:break-all;max-width:calc(100% - var(--search-typename-width));display:inline-block;}.search-results .result-name .path>*{display:inline;}.popover{position:absolute;top:100%;right:0;z-index:calc(var(--desktop-sidebar-z-index) + 1);margin-top:7px;border-radius:3px;border:1px solid var(--border-color);background-color:var(--main-background-color);color:var(--main-color);--popover-arrow-offset:11px;}.popover::before{content:'';position:absolute;right:var(--popover-arrow-offset);border:solid var(--border-color);border-width:1px 1px 0 0;background-color:var(--main-background-color);padding:4px;transform:rotate(-45deg);top:-5px;}.setting-line{margin:1.2em 0.6em;}.setting-radio input,.setting-check input{margin-right:0.3em;height:1.2rem;width:1.2rem;border:2px solid var(--settings-input-border-color);outline:none;-webkit-appearance:none;cursor:pointer;}.setting-radio input{border-radius:50%;}.setting-radio span,.setting-check span{padding-bottom:1px;}.setting-radio{margin-top:0.1em;margin-bottom:0.1em;min-width:3.8em;padding:0.3em;display:inline-flex;align-items:center;cursor:pointer;}.setting-radio+.setting-radio{margin-left:0.5em;}.setting-check{margin-right:20px;display:flex;align-items:center;cursor:pointer;}.setting-radio input:checked{box-shadow:inset 0 0 0 3px var(--main-background-color);background-color:var(--settings-input-color);}.setting-check input:checked{background-color:var(--settings-input-color);border-width:1px;content:url('data:image/svg+xml,\ + \ + ');}.setting-radio input:focus,.setting-check input:focus{box-shadow:0 0 1px 1px var(--settings-input-color);}.setting-radio input:checked:focus{box-shadow:inset 0 0 0 3px var(--main-background-color),0 0 2px 2px var(--settings-input-color);}.setting-radio input:hover,.setting-check input:hover{border-color:var(--settings-input-color) !important;}#help.popover{max-width:600px;--popover-arrow-offset:48px;}#help dt{float:left;clear:left;margin-right:0.5rem;}#help span.top,#help span.bottom{text-align:center;display:block;font-size:1.125rem;}#help span.top{margin:10px 0;border-bottom:1px solid var(--border-color);padding-bottom:4px;margin-bottom:6px;}#help span.bottom{clear:both;border-top:1px solid var(--border-color);}.side-by-side>div{width:50%;float:left;padding:0 20px 20px 17px;}.item-info .stab{display:block;padding:3px;margin-bottom:5px;}.item-name .stab{margin-left:0.3125em;}.stab{padding:0 2px;font-size:0.875rem;font-weight:normal;color:var(--main-color);background-color:var(--stab-background-color);width:fit-content;white-space:pre-wrap;border-radius:3px;display:inline;vertical-align:baseline;}.stab.portability>code{background:none;color:var(--stab-code-color);}.stab .emoji,.item-info .stab::before{font-size:1.25rem;}.stab .emoji{margin-right:0.3rem;}.item-info .stab::before{content:"\0";width:0;display:inline-block;color:transparent;}.emoji{text-shadow:1px 0 0 black,-1px 0 0 black,0 1px 0 black,0 -1px 0 black;}.since{font-weight:normal;font-size:initial;}.rightside{padding-left:12px;float:right;}.rightside:not(a),.out-of-band{color:var(--right-side-color);}pre.rust{tab-size:4;-moz-tab-size:4;}pre.rust .kw{color:var(--code-highlight-kw-color);}pre.rust .kw-2{color:var(--code-highlight-kw-2-color);}pre.rust .lifetime{color:var(--code-highlight-lifetime-color);}pre.rust .prelude-ty{color:var(--code-highlight-prelude-color);}pre.rust .prelude-val{color:var(--code-highlight-prelude-val-color);}pre.rust .string{color:var(--code-highlight-string-color);}pre.rust .number{color:var(--code-highlight-number-color);}pre.rust .bool-val{color:var(--code-highlight-literal-color);}pre.rust .self{color:var(--code-highlight-self-color);}pre.rust .attr{color:var(--code-highlight-attribute-color);}pre.rust .macro,pre.rust .macro-nonterminal{color:var(--code-highlight-macro-color);}pre.rust .question-mark{font-weight:bold;color:var(--code-highlight-question-mark-color);}pre.rust .comment{color:var(--code-highlight-comment-color);}pre.rust .doccomment{color:var(--code-highlight-doc-comment-color);}.rustdoc.src .example-wrap pre.rust a{background:var(--codeblock-link-background);}.example-wrap.compile_fail,.example-wrap.should_panic{border-left:2px solid var(--codeblock-error-color);}.ignore.example-wrap{border-left:2px solid var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover,.example-wrap.should_panic:hover{border-left:2px solid var(--codeblock-error-hover-color);}.example-wrap.ignore:hover{border-left:2px solid var(--codeblock-ignore-hover-color);}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip{color:var(--codeblock-error-color);}.example-wrap.ignore .tooltip{color:var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover .tooltip,.example-wrap.should_panic:hover .tooltip{color:var(--codeblock-error-hover-color);}.example-wrap.ignore:hover .tooltip{color:var(--codeblock-ignore-hover-color);}.example-wrap .tooltip{position:absolute;display:block;left:-25px;top:5px;margin:0;line-height:1;}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip,.example-wrap.ignore .tooltip{font-weight:bold;font-size:1.25rem;}.content .docblock .warning{border-left:2px solid var(--warning-border-color);padding:14px;position:relative;overflow-x:visible !important;}.content .docblock .warning::before{color:var(--warning-border-color);content:"ⓘ";position:absolute;left:-25px;top:5px;font-weight:bold;font-size:1.25rem;}.top-doc>.docblock>.warning:first-child::before{top:20px;}.example-wrap>a.test-arrow,.example-wrap .button-holder{visibility:hidden;position:absolute;top:4px;right:4px;z-index:1;}a.test-arrow{height:var(--copy-path-height);padding:6px 4px 0 11px;}a.test-arrow::before{content:url('data:image/svg+xml,');}.example-wrap .button-holder{display:flex;}@media not (pointer:coarse){.example-wrap:hover>a.test-arrow,.example-wrap:hover>.button-holder{visibility:visible;}}.example-wrap .button-holder.keep-visible{visibility:visible;}.example-wrap .button-holder .copy-button,.example-wrap .test-arrow{background:var(--main-background-color);cursor:pointer;border-radius:var(--button-border-radius);height:var(--copy-path-height);width:var(--copy-path-width);}.example-wrap .button-holder .copy-button{margin-left:var(--button-left-margin);padding:2px 0 0 4px;border:0;}.example-wrap .button-holder .copy-button::before,.example-wrap .test-arrow::before{filter:var(--copy-path-img-filter);}.example-wrap .button-holder .copy-button::before{content:var(--clipboard-image);}.example-wrap .button-holder .copy-button:hover::before,.example-wrap .test-arrow:hover::before{filter:var(--copy-path-img-hover-filter);}.example-wrap .button-holder .copy-button.clicked::before{content:var(--checkmark-image);padding-right:5px;}.code-attribute{font-weight:300;color:var(--code-attribute-color);}.item-spacer{width:100%;height:12px;display:block;}.out-of-band>span.since{font-size:1.25rem;}.sub-variant h4{font-size:1rem;font-weight:400;margin-top:0;margin-bottom:0;}.sub-variant{margin-left:24px;margin-bottom:40px;}.sub-variant>.sub-variant-field{margin-left:24px;}@keyframes targetfadein{from{background-color:var(--main-background-color);}10%{background-color:var(--target-border-color);}to{background-color:var(--target-background-color);}}:target{padding-right:3px;background-color:var(--target-background-color);border-right:3px solid var(--target-border-color);animation:0.65s cubic-bezier(0,0,0.1,1.0) 0.1s targetfadein;}.code-header a.tooltip{color:inherit;margin-right:15px;position:relative;}.code-header a.tooltip:hover{color:var(--link-color);}a.tooltip:hover::after{position:absolute;top:calc(100% - 10px);left:-15px;right:-15px;height:20px;content:"\00a0";}.fade-out{opacity:0;transition:opacity 0.45s cubic-bezier(0,0,0.1,1.0);}.popover.tooltip .content{margin:0.25em 0.5em;}.popover.tooltip .content pre,.popover.tooltip .content code{background:transparent;margin:0;padding:0;font-size:1.25rem;white-space:pre-wrap;}.popover.tooltip .content>h3:first-child{margin:0 0 5px 0;}.search-failed{text-align:center;margin-top:20px;display:none;}.search-failed.active{display:block;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#search-tabs{display:flex;flex-direction:row;gap:1px;margin-bottom:4px;}#search-tabs button{text-align:center;font-size:1.125rem;border:0;border-top:2px solid;flex:1;line-height:1.5;color:inherit;}#search-tabs button:not(.selected){background-color:var(--search-tab-button-not-selected-background);border-top-color:var(--search-tab-button-not-selected-border-top-color);}#search-tabs button:hover,#search-tabs button.selected{background-color:var(--search-tab-button-selected-background);border-top-color:var(--search-tab-button-selected-border-top-color);}#search-tabs .count{font-size:1rem;font-variant-numeric:tabular-nums;color:var(--search-tab-title-count-color);}#search .error code{border-radius:3px;background-color:var(--search-error-code-background-color);}.search-corrections{font-weight:normal;}#src-sidebar{width:100%;overflow:auto;}#src-sidebar div.files>a:hover,details.dir-entry summary:hover,#src-sidebar div.files>a:focus,details.dir-entry summary:focus{background-color:var(--src-sidebar-background-hover);}#src-sidebar div.files>a.selected{background-color:var(--src-sidebar-background-selected);}.src-sidebar-title{position:sticky;top:0;display:flex;padding:8px 8px 0 48px;margin-bottom:7px;background:var(--sidebar-background-color);border-bottom:1px solid var(--border-color);}#settings-menu,#help-button{margin-left:var(--button-left-margin);display:flex;}#sidebar-button{display:none;line-height:0;}.hide-sidebar #sidebar-button,.src #sidebar-button{display:flex;margin-right:4px;position:fixed;left:6px;height:34px;width:34px;background-color:var(--main-background-color);z-index:1;}.src #sidebar-button{left:8px;z-index:calc(var(--desktop-sidebar-z-index) + 1);}.hide-sidebar .src #sidebar-button{position:static;}#settings-menu>a,#help-button>a,#sidebar-button>a{display:flex;align-items:center;justify-content:center;background-color:var(--button-background-color);border:1px solid var(--border-color);border-radius:var(--button-border-radius);color:var(--settings-button-color);font-size:20px;width:33px;}#settings-menu>a:hover,#settings-menu>a:focus,#help-button>a:hover,#help-button>a:focus,#sidebar-button>a:hover,#sidebar-button>a:focus{border-color:var(--settings-button-border-focus);}#settings-menu>a{line-height:0;font-size:0;}#settings-menu>a:before{content:url('data:image/svg+xml,\ + ');width:22px;height:22px;filter:var(--settings-menu-filter);}#sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');width:22px;height:22px;}#copy-path{color:var(--copy-path-button-color);background:var(--main-background-color);height:var(--copy-path-height);width:var(--copy-path-width);margin-left:10px;padding:0;padding-left:2px;border:0;font-size:0;}#copy-path::before{filter:var(--copy-path-img-filter);content:var(--clipboard-image);}#copy-path:hover::before{filter:var(--copy-path-img-hover-filter);}#copy-path.clicked::before{content:var(--checkmark-image);}@keyframes rotating{from{transform:rotate(0deg);}to{transform:rotate(360deg);}}#settings-menu.rotate>a img{animation:rotating 2s linear infinite;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px var(--border-color);border-radius:3px;color:var(--kbd-color);background-color:var(--kbd-background);box-shadow:inset 0 -1px 0 var(--kbd-box-shadow-color);}ul.all-items>li{list-style:none;}details.dir-entry{padding-left:4px;}details.dir-entry>summary{margin:0 0 0 -4px;padding:0 0 0 4px;cursor:pointer;}details.dir-entry div.folders,details.dir-entry div.files{padding-left:23px;}details.dir-entry a{display:block;}details.toggle{contain:layout;position:relative;}details.toggle>summary.hideme{cursor:pointer;font-size:1rem;}details.toggle>summary{list-style:none;outline:none;}details.toggle>summary::-webkit-details-marker,details.toggle>summary::marker{display:none;}details.toggle>summary.hideme>span{margin-left:9px;}details.toggle>summary::before{background:url('data:image/svg+xml,') no-repeat top left;content:"";cursor:pointer;width:16px;height:16px;display:inline-block;vertical-align:middle;opacity:.5;filter:var(--toggle-filter);}details.toggle>summary.hideme>span,.more-examples-toggle summary,.more-examples-toggle .hide-more{color:var(--toggles-color);}details.toggle>summary::after{content:"Expand";overflow:hidden;width:0;height:0;position:absolute;}details.toggle>summary.hideme::after{content:"";}details.toggle>summary:focus::before,details.toggle>summary:hover::before{opacity:1;}details.toggle>summary:focus-visible::before{outline:1px dotted #000;outline-offset:1px;}details.non-exhaustive{margin-bottom:8px;}details.toggle>summary.hideme::before{position:relative;}details.toggle>summary:not(.hideme)::before{position:absolute;left:-24px;top:4px;}.impl-items>details.toggle>summary:not(.hideme)::before{position:absolute;left:-24px;}details.toggle[open] >summary.hideme{position:absolute;}details.toggle[open] >summary.hideme>span{display:none;}details.toggle[open] >summary::before{background:url('data:image/svg+xml,') no-repeat top left;}details.toggle[open] >summary::after{content:"Collapse";}.docblock summary>*{display:inline-block;}.docblock>.example-wrap:first-child .tooltip{margin-top:16px;}.src #sidebar-button>a:before,.sidebar-menu-toggle:before{content:url('data:image/svg+xml,\ + ');opacity:0.75;}.sidebar-menu-toggle:hover:before,.sidebar-menu-toggle:active:before,.sidebar-menu-toggle:focus:before{opacity:1;}.src #sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');opacity:0.75;}@media (max-width:850px){#search-tabs .count{display:block;}}@media (max-width:700px){*[id]{scroll-margin-top:45px;}.rustdoc{display:block;}main{padding-left:15px;padding-top:0px;}.main-heading{flex-direction:column;}.out-of-band{text-align:left;margin-left:initial;padding:initial;}.out-of-band .since::before{content:"Since ";}.sidebar .logo-container,.sidebar .location,.sidebar-resizer{display:none;}.sidebar{position:fixed;top:45px;left:-1000px;z-index:11;height:calc(100vh - 45px);width:200px;}.src main,.rustdoc.src .sidebar{top:0;padding:0;height:100vh;border:0;}.src .search-form{margin-left:40px;}.hide-sidebar .search-form{margin-left:32px;}.hide-sidebar .src .search-form{margin-left:0;}.sidebar.shown,.src-sidebar-expanded .src .sidebar,.rustdoc:not(.src) .sidebar:focus-within{left:0;}.mobile-topbar h2{padding-bottom:0;margin:auto 0.5em auto auto;overflow:hidden;font-size:24px;white-space:nowrap;text-overflow:ellipsis;}.mobile-topbar .logo-container>img{max-width:35px;max-height:35px;margin:5px 0 5px 20px;}.mobile-topbar{display:flex;flex-direction:row;position:sticky;z-index:10;font-size:2rem;height:45px;width:100%;left:0;top:0;}.hide-sidebar .mobile-topbar{display:none;}.sidebar-menu-toggle{width:45px;border:none;line-height:0;}.hide-sidebar .sidebar-menu-toggle{display:none;}.sidebar-elems{margin-top:1em;}.anchor{display:none !important;}#main-content>details.toggle>summary::before,#main-content>div>details.toggle>summary::before{left:-11px;}#copy-path,#help-button{display:none;}#sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');width:22px;height:22px;}.sidebar-menu-toggle:before{filter:var(--mobile-sidebar-menu-filter);}.sidebar-menu-toggle:hover{background:var(--main-background-color);}.item-table,.item-row,.item-table>li,.item-table>li>div,.search-results>a,.search-results>a>div{display:block;}.search-results>a{padding:5px 0px;}.search-results>a>div.desc,.item-table>li>div.desc{padding-left:2em;}.search-results .result-name{display:block;}.search-results .result-name .typename{width:initial;margin-right:0;}.search-results .result-name .typename,.search-results .result-name .path{display:inline;}.src-sidebar-expanded .src .sidebar{position:fixed;max-width:100vw;width:100vw;}.src .src-sidebar-title{padding-top:0;}details.toggle:not(.top-doc)>summary{margin-left:10px;}.impl-items>details.toggle>summary:not(.hideme)::before,#main-content>details.toggle:not(.top-doc)>summary::before,#main-content>div>details.toggle>summary::before{left:-11px;}.impl-items>.item-info{margin-left:34px;}.src nav.sub{margin:0;padding:var(--nav-sub-mobile-padding);}}@media (min-width:701px){.scraped-example-title{position:absolute;z-index:10;background:var(--main-background-color);bottom:8px;right:5px;padding:2px 4px;box-shadow:0 0 4px var(--main-background-color);}.item-table>li>.item-name{width:33%;}.item-table>li>div{overflow-wrap:anywhere;}}@media print{nav.sidebar,nav.sub,.out-of-band,a.src,#copy-path,details.toggle[open] >summary::before,details.toggle>summary::before,details.toggle.top-doc>summary{display:none;}.docblock{margin-left:0;}main{padding:10px;}}@media (max-width:464px){.docblock{margin-left:12px;}.docblock code{overflow-wrap:break-word;overflow-wrap:anywhere;}nav.sub{flex-direction:column;}.search-form{align-self:stretch;}}.variant,.implementors-toggle>summary,.impl,#implementors-list>.docblock,.impl-items>section,.impl-items>.toggle>summary,.methods>section,.methods>.toggle>summary{margin-bottom:0.75em;}.variants>.docblock,.implementors-toggle>.docblock,.impl-items>.toggle[open]:not(:last-child),.methods>.toggle[open]:not(:last-child),.implementors-toggle[open]:not(:last-child){margin-bottom:2em;}#trait-implementations-list .impl-items>.toggle:not(:last-child),#synthetic-implementations-list .impl-items>.toggle:not(:last-child),#blanket-implementations-list .impl-items>.toggle:not(:last-child){margin-bottom:1em;}.scraped-example-list .scrape-help{margin-left:10px;padding:0 4px;font-weight:normal;font-size:12px;position:relative;bottom:1px;border:1px solid var(--scrape-example-help-border-color);border-radius:50px;color:var(--scrape-example-help-color);}.scraped-example-list .scrape-help:hover{border-color:var(--scrape-example-help-hover-border-color);color:var(--scrape-example-help-hover-color);}.scraped-example{position:relative;}.scraped-example .code-wrapper{position:relative;display:flex;flex-direction:row;flex-wrap:wrap;width:100%;}.scraped-example:not(.expanded) .code-wrapper{max-height:calc(1.5em * 5 + 10px);}.scraped-example:not(.expanded) .code-wrapper pre{overflow-y:hidden;padding-bottom:0;max-height:calc(1.5em * 5 + 10px);}.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper,.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper pre{max-height:calc(1.5em * 10 + 10px);}.scraped-example .code-wrapper .next,.scraped-example .code-wrapper .prev,.scraped-example .code-wrapper .expand{color:var(--main-color);position:absolute;top:0.25em;z-index:1;padding:0;background:none;border:none;-webkit-appearance:none;opacity:1;}.scraped-example .code-wrapper .prev{right:2.25em;}.scraped-example .code-wrapper .next{right:1.25em;}.scraped-example .code-wrapper .expand{right:0.25em;}.scraped-example:not(.expanded) .code-wrapper::before,.scraped-example:not(.expanded) .code-wrapper::after{content:" ";width:100%;height:5px;position:absolute;z-index:1;}.scraped-example:not(.expanded) .code-wrapper::before{top:0;background:linear-gradient(to bottom,var(--scrape-example-code-wrapper-background-start),var(--scrape-example-code-wrapper-background-end));}.scraped-example:not(.expanded) .code-wrapper::after{bottom:0;background:linear-gradient(to top,var(--scrape-example-code-wrapper-background-start),var(--scrape-example-code-wrapper-background-end));}.scraped-example .code-wrapper .example-wrap{width:100%;overflow-y:hidden;margin-bottom:0;}.scraped-example:not(.expanded) .code-wrapper .example-wrap{overflow-x:hidden;}.scraped-example .example-wrap .rust span.highlight{background:var(--scrape-example-code-line-highlight);}.scraped-example .example-wrap .rust span.highlight.focus{background:var(--scrape-example-code-line-highlight-focus);}.more-examples-toggle{max-width:calc(100% + 25px);margin-top:10px;margin-left:-25px;}.more-examples-toggle .hide-more{margin-left:25px;cursor:pointer;}.more-scraped-examples{margin-left:25px;position:relative;}.toggle-line{position:absolute;top:5px;bottom:0;right:calc(100% + 10px);padding:0 4px;cursor:pointer;}.toggle-line-inner{min-width:2px;height:100%;background:var(--scrape-example-toggle-line-background);}.toggle-line:hover .toggle-line-inner{background:var(--scrape-example-toggle-line-hover-background);}.more-scraped-examples .scraped-example,.example-links{margin-top:20px;}.more-scraped-examples .scraped-example:first-child{margin-top:5px;}.example-links ul{margin-bottom:0;}:root[data-theme="light"],:root:not([data-theme]){--main-background-color:white;--main-color:black;--settings-input-color:#2196f3;--settings-input-border-color:#717171;--settings-button-color:#000;--settings-button-border-focus:#717171;--sidebar-background-color:#f5f5f5;--sidebar-background-color-hover:#e0e0e0;--code-block-background-color:#f5f5f5;--scrollbar-track-background-color:#dcdcdc;--scrollbar-thumb-background-color:rgba(36,37,39,0.6);--scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;--headings-border-bottom-color:#ddd;--border-color:#e0e0e0;--button-background-color:#fff;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:none;--mobile-sidebar-menu-filter:none;--search-input-focused-border-color:#66afe9;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(35%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ad378a;--trait-link-color:#6e4fc9;--assoc-item-link-color:#3873ad;--function-link-color:#ad7c37;--macro-link-color:#068000;--keyword-link-color:#3873ad;--mod-link-color:#3873ad;--link-color:#3873ad;--sidebar-link-color:#356da4;--sidebar-current-link-background-color:#fff;--search-result-link-focus-background-color:#ccc;--search-result-border-color:#aaa3;--search-color:#000;--search-error-code-background-color:#d0cccc;--search-results-alias-color:#000;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#e6e6e6;--search-tab-button-not-selected-background:#e6e6e6;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#fff;--settings-menu-filter:none;--stab-background-color:#fff5d6;--stab-code-color:#000;--code-highlight-kw-color:#8959a8;--code-highlight-kw-2-color:#4271ae;--code-highlight-lifetime-color:#b76514;--code-highlight-prelude-color:#4271ae;--code-highlight-prelude-val-color:#c82829;--code-highlight-number-color:#718c00;--code-highlight-string-color:#718c00;--code-highlight-literal-color:#c82829;--code-highlight-attribute-color:#c82829;--code-highlight-self-color:#c82829;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8e908c;--code-highlight-doc-comment-color:#4d4d4c;--src-line-numbers-span-color:#c67e2d;--src-line-number-highlighted-background-color:#fdffd3;--target-background-color:#fdffd3;--target-border-color:#ad7c37;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:initial;--crate-search-div-filter:invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);--crate-search-div-hover-filter:invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);--crate-search-hover-border:#717171;--src-sidebar-background-selected:#fff;--src-sidebar-background-hover:#e0e0e0;--table-alt-row-background-color:#f5f5f5;--codeblock-link-background:#eee;--scrape-example-toggle-line-background:#ccc;--scrape-example-toggle-line-hover-background:#999;--scrape-example-code-line-highlight:#fcffd6;--scrape-example-code-line-highlight-focus:#f6fdb0;--scrape-example-help-border-color:#555;--scrape-example-help-color:#333;--scrape-example-help-hover-border-color:#000;--scrape-example-help-hover-color:#000;--scrape-example-code-wrapper-background-start:rgba(255,255,255,1);--scrape-example-code-wrapper-background-end:rgba(255,255,255,0);--sidebar-resizer-hover:hsl(207,90%,66%);--sidebar-resizer-active:hsl(207,90%,54%);}:root[data-theme="dark"]{--main-background-color:#353535;--main-color:#ddd;--settings-input-color:#2196f3;--settings-input-border-color:#999;--settings-button-color:#000;--settings-button-border-focus:#ffb900;--sidebar-background-color:#505050;--sidebar-background-color-hover:#676767;--code-block-background-color:#2A2A2A;--scrollbar-track-background-color:#717171;--scrollbar-thumb-background-color:rgba(32,34,37,.6);--scrollbar-color:rgba(32,34,37,.6) #5a5a5a;--headings-border-bottom-color:#d2d2d2;--border-color:#e0e0e0;--button-background-color:#f0f0f0;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#008dfd;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(65%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#2dbfb8;--trait-link-color:#b78cf2;--assoc-item-link-color:#d2991d;--function-link-color:#2bab63;--macro-link-color:#09bd00;--keyword-link-color:#d2991d;--mod-link-color:#d2991d;--link-color:#d2991d;--sidebar-link-color:#fdbf35;--sidebar-current-link-background-color:#444;--search-result-link-focus-background-color:#616161;--search-result-border-color:#aaa3;--search-color:#111;--search-error-code-background-color:#484848;--search-results-alias-color:#fff;--search-results-grey-color:#ccc;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#252525;--search-tab-button-not-selected-background:#252525;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#353535;--settings-menu-filter:none;--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ab8ac1;--code-highlight-kw-2-color:#769acb;--code-highlight-lifetime-color:#d97f26;--code-highlight-prelude-color:#769acb;--code-highlight-prelude-val-color:#ee6868;--code-highlight-number-color:#83a300;--code-highlight-string-color:#83a300;--code-highlight-literal-color:#ee6868;--code-highlight-attribute-color:#ee6868;--code-highlight-self-color:#ee6868;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8d8d8b;--code-highlight-doc-comment-color:#8ca375;--src-line-numbers-span-color:#3b91e2;--src-line-number-highlighted-background-color:#0a042f;--target-background-color:#494a3d;--target-border-color:#bb7410;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%);--crate-search-div-hover-filter:invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);--crate-search-hover-border:#2196f3;--src-sidebar-background-selected:#333;--src-sidebar-background-hover:#444;--table-alt-row-background-color:#2a2a2a;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(53,53,53,1);--scrape-example-code-wrapper-background-end:rgba(53,53,53,0);--sidebar-resizer-hover:hsl(207,30%,54%);--sidebar-resizer-active:hsl(207,90%,54%);}:root[data-theme="ayu"]{--main-background-color:#0f1419;--main-color:#c5c5c5;--settings-input-color:#ffb454;--settings-input-border-color:#999;--settings-button-color:#fff;--settings-button-border-focus:#e0e0e0;--sidebar-background-color:#14191f;--sidebar-background-color-hover:rgba(70,70,70,0.33);--code-block-background-color:#191f26;--scrollbar-track-background-color:transparent;--scrollbar-thumb-background-color:#5c6773;--scrollbar-color:#5c6773 #24292f;--headings-border-bottom-color:#5c6773;--border-color:#5c6773;--button-background-color:#141920;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#5c6773;--copy-path-button-color:#fff;--copy-path-img-filter:invert(70%);--copy-path-img-hover-filter:invert(100%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ffa0a5;--trait-link-color:#39afd7;--assoc-item-link-color:#39afd7;--function-link-color:#fdd687;--macro-link-color:#a37acc;--keyword-link-color:#39afd7;--mod-link-color:#39afd7;--link-color:#39afd7;--sidebar-link-color:#53b1db;--sidebar-current-link-background-color:transparent;--search-result-link-focus-background-color:#3c3c3c;--search-result-border-color:#aaa3;--search-color:#fff;--search-error-code-background-color:#4f4c4c;--search-results-alias-color:#c5c5c5;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:none;--search-tab-button-not-selected-background:transparent !important;--search-tab-button-selected-border-top-color:none;--search-tab-button-selected-background:#141920 !important;--settings-menu-filter:invert(100%);--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ff7733;--code-highlight-kw-2-color:#ff7733;--code-highlight-lifetime-color:#ff7733;--code-highlight-prelude-color:#69f2df;--code-highlight-prelude-val-color:#ff7733;--code-highlight-number-color:#b8cc52;--code-highlight-string-color:#b8cc52;--code-highlight-literal-color:#ff7733;--code-highlight-attribute-color:#e6e1cf;--code-highlight-self-color:#36a3d9;--code-highlight-macro-color:#a37acc;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#788797;--code-highlight-doc-comment-color:#a1ac88;--src-line-numbers-span-color:#5c6773;--src-line-number-highlighted-background-color:rgba(255,236,164,0.06);--target-background-color:rgba(255,236,164,0.06);--target-border-color:rgba(255,180,76,0.85);--kbd-color:#c5c5c5;--kbd-background:#314559;--kbd-box-shadow-color:#5c6773;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(41%) sepia(12%) saturate(487%) hue-rotate(171deg) brightness(94%) contrast(94%);--crate-search-div-hover-filter:invert(98%) sepia(12%) saturate(81%) hue-rotate(343deg) brightness(113%) contrast(76%);--crate-search-hover-border:#e0e0e0;--src-sidebar-background-selected:#14191f;--src-sidebar-background-hover:#14191f;--table-alt-row-background-color:#191f26;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(15,20,25,1);--scrape-example-code-wrapper-background-end:rgba(15,20,25,0);--sidebar-resizer-hover:hsl(34,50%,33%);--sidebar-resizer-active:hsl(34,100%,66%);}:root[data-theme="ayu"] h1,:root[data-theme="ayu"] h2,:root[data-theme="ayu"] h3,:root[data-theme="ayu"] h4,:where(:root[data-theme="ayu"]) h1 a,:root[data-theme="ayu"] .sidebar h2 a,:root[data-theme="ayu"] .sidebar h3 a{color:#fff;}:root[data-theme="ayu"] .docblock code{color:#ffb454;}:root[data-theme="ayu"] .docblock a>code{color:#39AFD7 !important;}:root[data-theme="ayu"] .code-header,:root[data-theme="ayu"] .docblock pre>code,:root[data-theme="ayu"] pre,:root[data-theme="ayu"] pre>code,:root[data-theme="ayu"] .item-info code,:root[data-theme="ayu"] .rustdoc.source .example-wrap{color:#e6e1cf;}:root[data-theme="ayu"] .sidebar .current,:root[data-theme="ayu"] .sidebar .current a,:root[data-theme="ayu"] .sidebar a:hover,:root[data-theme="ayu"] #src-sidebar div.files>a:hover,:root[data-theme="ayu"] details.dir-entry summary:hover,:root[data-theme="ayu"] #src-sidebar div.files>a:focus,:root[data-theme="ayu"] details.dir-entry summary:focus,:root[data-theme="ayu"] #src-sidebar div.files>a.selected{color:#ffb44c;}:root[data-theme="ayu"] .sidebar-elems .location{color:#ff7733;}:root[data-theme="ayu"] .src-line-numbers .line-highlighted{color:#708090;padding-right:7px;border-right:1px solid #ffb44c;}:root[data-theme="ayu"] .search-results a:hover,:root[data-theme="ayu"] .search-results a:focus{color:#fff !important;background-color:#3c3c3c;}:root[data-theme="ayu"] .search-results a{color:#0096cf;}:root[data-theme="ayu"] .search-results a div.desc{color:#c5c5c5;}:root[data-theme="ayu"] .result-name .primitive>i,:root[data-theme="ayu"] .result-name .keyword>i{color:#788797;}:root[data-theme="ayu"] #search-tabs>button.selected{border-bottom:1px solid #ffb44c !important;border-top:none;}:root[data-theme="ayu"] #search-tabs>button:not(.selected){border:none;background-color:transparent !important;}:root[data-theme="ayu"] #search-tabs>button:hover{border-bottom:1px solid rgba(242,151,24,0.3);}:root[data-theme="ayu"] #settings-menu>a img,:root[data-theme="ayu"] #sidebar-button>a:before{filter:invert(100);} \ No newline at end of file diff --git a/static.files/scrape-examples-ef1e698c1d417c0c.js b/static.files/scrape-examples-ef1e698c1d417c0c.js new file mode 100644 index 00000000..ba830e37 --- /dev/null +++ b/static.files/scrape-examples-ef1e698c1d417c0c.js @@ -0,0 +1 @@ +"use strict";(function(){const DEFAULT_MAX_LINES=5;const HIDDEN_MAX_LINES=10;function scrollToLoc(elt,loc,isHidden){const lines=elt.querySelector(".src-line-numbers");let scrollOffset;const maxLines=isHidden?HIDDEN_MAX_LINES:DEFAULT_MAX_LINES;if(loc[1]-loc[0]>maxLines){const line=Math.max(0,loc[0]-1);scrollOffset=lines.children[line].offsetTop}else{const wrapper=elt.querySelector(".code-wrapper");const halfHeight=wrapper.offsetHeight/2;const offsetTop=lines.children[loc[0]].offsetTop;const lastLine=lines.children[loc[1]];const offsetBot=lastLine.offsetTop+lastLine.offsetHeight;const offsetMid=(offsetTop+offsetBot)/2;scrollOffset=offsetMid-halfHeight}lines.scrollTo(0,scrollOffset);elt.querySelector(".rust").scrollTo(0,scrollOffset)}function updateScrapedExample(example,isHidden){const locs=JSON.parse(example.attributes.getNamedItem("data-locs").textContent);let locIndex=0;const highlights=Array.prototype.slice.call(example.querySelectorAll(".highlight"));const link=example.querySelector(".scraped-example-title a");if(locs.length>1){const onChangeLoc=changeIndex=>{removeClass(highlights[locIndex],"focus");changeIndex();scrollToLoc(example,locs[locIndex][0],isHidden);addClass(highlights[locIndex],"focus");const url=locs[locIndex][1];const title=locs[locIndex][2];link.href=url;link.innerHTML=title};example.querySelector(".prev").addEventListener("click",()=>{onChangeLoc(()=>{locIndex=(locIndex-1+locs.length)%locs.length})});example.querySelector(".next").addEventListener("click",()=>{onChangeLoc(()=>{locIndex=(locIndex+1)%locs.length})})}const expandButton=example.querySelector(".expand");if(expandButton){expandButton.addEventListener("click",()=>{if(hasClass(example,"expanded")){removeClass(example,"expanded");scrollToLoc(example,locs[0][0],isHidden)}else{addClass(example,"expanded")}})}scrollToLoc(example,locs[0][0],isHidden)}const firstExamples=document.querySelectorAll(".scraped-example-list > .scraped-example");onEachLazy(firstExamples,el=>updateScrapedExample(el,false));onEachLazy(document.querySelectorAll(".more-examples-toggle"),toggle=>{onEachLazy(toggle.querySelectorAll(".toggle-line, .hide-more"),button=>{button.addEventListener("click",()=>{toggle.open=false})});const moreExamples=toggle.querySelectorAll(".scraped-example");toggle.querySelector("summary").addEventListener("click",()=>{setTimeout(()=>{onEachLazy(moreExamples,el=>updateScrapedExample(el,true))})},{once:true})})})() \ No newline at end of file diff --git a/static.files/search-a99f1315e7cc5121.js b/static.files/search-a99f1315e7cc5121.js new file mode 100644 index 00000000..aee0fc77 --- /dev/null +++ b/static.files/search-a99f1315e7cc5121.js @@ -0,0 +1,5 @@ +"use strict";if(!Array.prototype.toSpliced){Array.prototype.toSpliced=function(){const me=this.slice();Array.prototype.splice.apply(me,arguments);return me}}(function(){const itemTypes=["keyword","primitive","mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","associatedtype","constant","associatedconstant","union","foreigntype","existential","attr","derive","traitalias","generic",];const TY_GENERIC=itemTypes.indexOf("generic");const TY_IMPORT=itemTypes.indexOf("import");const ROOT_PATH=typeof window!=="undefined"?window.rootPath:"../";const UNBOXING_LIMIT=5;const REGEX_IDENT=/\p{ID_Start}\p{ID_Continue}*|_\p{ID_Continue}+/uy;const REGEX_INVALID_TYPE_FILTER=/[^a-z]/ui;const MAX_RESULTS=200;const NO_TYPE_FILTER=-1;const editDistanceState={current:[],prev:[],prevPrev:[],calculate:function calculate(a,b,limit){if(a.lengthlimit){return limit+1}while(b.length>0&&b[0]===a[0]){a=a.substring(1);b=b.substring(1)}while(b.length>0&&b[b.length-1]===a[a.length-1]){a=a.substring(0,a.length-1);b=b.substring(0,b.length-1)}if(b.length===0){return minDist}const aLength=a.length;const bLength=b.length;for(let i=0;i<=bLength;++i){this.current[i]=0;this.prev[i]=i;this.prevPrev[i]=Number.MAX_VALUE}for(let i=1;i<=aLength;++i){this.current[0]=i;const aIdx=i-1;for(let j=1;j<=bLength;++j){const bIdx=j-1;const substitutionCost=a[aIdx]===b[bIdx]?0:1;this.current[j]=Math.min(this.prev[j]+1,this.current[j-1]+1,this.prev[j-1]+substitutionCost,);if((i>1)&&(j>1)&&(a[aIdx]===b[bIdx-1])&&(a[aIdx-1]===b[bIdx])){this.current[j]=Math.min(this.current[j],this.prevPrev[j-2]+1,)}}const prevPrevTmp=this.prevPrev;this.prevPrev=this.prev;this.prev=this.current;this.current=prevPrevTmp}const distance=this.prev[bLength];return distance<=limit?distance:(limit+1)},};function editDistance(a,b,limit){return editDistanceState.calculate(a,b,limit)}function isEndCharacter(c){return"=,>-])".indexOf(c)!==-1}function isSeparatorCharacter(c){return c===","||c==="="}function isReturnArrow(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="->"}function skipWhitespace(parserState){while(parserState.pos0){const c=parserState.userQuery[pos-1];if(c===lookingFor){return true}else if(c!==" "){break}pos-=1}return false}function isLastElemGeneric(elems,parserState){return(elems.length>0&&elems[elems.length-1].generics.length>0)||prevIs(parserState,">")}function getFilteredNextElem(query,parserState,elems,isInGenerics){const start=parserState.pos;if(parserState.userQuery[parserState.pos]===":"&&!isPathStart(parserState)){throw["Expected type filter before ",":"]}getNextElem(query,parserState,elems,isInGenerics);if(parserState.userQuery[parserState.pos]===":"&&!isPathStart(parserState)){if(parserState.typeFilter!==null){throw["Unexpected ",":"," (expected path after type filter ",parserState.typeFilter+":",")",]}if(elems.length===0){throw["Expected type filter before ",":"]}else if(query.literalSearch){throw["Cannot use quotes on type filter"]}const typeFilterElem=elems.pop();checkExtraTypeFilterCharacters(start,parserState);parserState.typeFilter=typeFilterElem.name;parserState.pos+=1;parserState.totalElems-=1;query.literalSearch=false;getNextElem(query,parserState,elems,isInGenerics)}}function getItemsBefore(query,parserState,elems,endChar){let foundStopChar=true;let foundSeparator=false;const oldTypeFilter=parserState.typeFilter;parserState.typeFilter=null;const oldIsInBinding=parserState.isInBinding;parserState.isInBinding=null;let hofParameters=null;let extra="";if(endChar===">"){extra="<"}else if(endChar==="]"){extra="["}else if(endChar===")"){extra="("}else if(endChar===""){extra="->"}else{extra=endChar}while(parserState.pos"," after ","="]}hofParameters=[...elems];elems.length=0;parserState.pos+=2;foundStopChar=true;foundSeparator=false;continue}else if(c===" "){parserState.pos+=1;continue}else if(isSeparatorCharacter(c)){parserState.pos+=1;foundStopChar=true;foundSeparator=true;continue}else if(c===":"&&isPathStart(parserState)){throw["Unexpected ","::",": paths cannot start with ","::"]}else if(isEndCharacter(c)){throw["Unexpected ",c," after ",extra]}if(!foundStopChar){let extra=[];if(isLastElemGeneric(query.elems,parserState)){extra=[" after ",">"]}else if(prevIs(parserState,"\"")){throw["Cannot have more than one element if you use quotes"]}if(endChar!==""){throw["Expected ",",",", ","=",", or ",endChar,...extra,", found ",c,]}throw["Expected ",","," or ","=",...extra,", found ",c,]}const posBefore=parserState.pos;getFilteredNextElem(query,parserState,elems,endChar!=="");if(endChar!==""&&parserState.pos>=parserState.length){throw["Unclosed ",extra]}if(posBefore===parserState.pos){parserState.pos+=1}foundStopChar=false}if(parserState.pos>=parserState.length&&endChar!==""){throw["Unclosed ",extra]}parserState.pos+=1;if(hofParameters){foundSeparator=false;if([...elems,...hofParameters].some(x=>x.bindingName)||parserState.isInBinding){throw["Unexpected ","="," within ","->"]}const hofElem=makePrimitiveElement("->",{generics:hofParameters,bindings:new Map([["output",[...elems]]]),typeFilter:null,});elems.length=0;elems[0]=hofElem}parserState.typeFilter=oldTypeFilter;parserState.isInBinding=oldIsInBinding;return{foundSeparator}}function getNextElem(query,parserState,elems,isInGenerics){const generics=[];skipWhitespace(parserState);let start=parserState.pos;let end;if("[(".indexOf(parserState.userQuery[parserState.pos])!==-1){let endChar=")";let name="()";let friendlyName="tuple";if(parserState.userQuery[parserState.pos]==="["){endChar="]";name="[]";friendlyName="slice"}parserState.pos+=1;const{foundSeparator}=getItemsBefore(query,parserState,generics,endChar);const typeFilter=parserState.typeFilter;const bindingName=parserState.isInBinding;parserState.typeFilter=null;parserState.isInBinding=null;for(const gen of generics){if(gen.bindingName!==null){throw["Type parameter ","=",` cannot be within ${friendlyName} `,name]}}if(name==="()"&&!foundSeparator&&generics.length===1&&typeFilter===null){elems.push(generics[0])}else if(name==="()"&&generics.length===1&&generics[0].name==="->"){generics[0].typeFilter=typeFilter;elems.push(generics[0])}else{if(typeFilter!==null&&typeFilter!=="primitive"){throw["Invalid search type: primitive ",name," and ",typeFilter," both specified",]}parserState.totalElems+=1;if(isInGenerics){parserState.genericsElems+=1}elems.push(makePrimitiveElement(name,{bindingName,generics}))}}else if(parserState.userQuery[parserState.pos]==="&"){if(parserState.typeFilter!==null&&parserState.typeFilter!=="primitive"){throw["Invalid search type: primitive ","&"," and ",parserState.typeFilter," both specified",]}parserState.typeFilter=null;parserState.pos+=1;let c=parserState.userQuery[parserState.pos];while(c===" "&&parserState.pos=end){throw["Found generics without a path"]}parserState.pos+=1;getItemsBefore(query,parserState,generics,">")}else if(parserState.pos=end){throw["Found generics without a path"]}if(parserState.isInBinding){throw["Unexpected ","("," after ","="]}parserState.pos+=1;const typeFilter=parserState.typeFilter;parserState.typeFilter=null;getItemsBefore(query,parserState,generics,")");skipWhitespace(parserState);if(isReturnArrow(parserState)){parserState.pos+=2;skipWhitespace(parserState);getFilteredNextElem(query,parserState,generics,isInGenerics);generics[generics.length-1].bindingName=makePrimitiveElement("output")}else{generics.push(makePrimitiveElement(null,{bindingName:makePrimitiveElement("output"),typeFilter:null,}))}parserState.typeFilter=typeFilter}if(isStringElem){skipWhitespace(parserState)}if(start>=end&&generics.length===0){return}if(parserState.userQuery[parserState.pos]==="="){if(parserState.isInBinding){throw["Cannot write ","="," twice in a binding"]}if(!isInGenerics){throw["Type parameter ","="," must be within generics list"]}const name=parserState.userQuery.slice(start,end).trim();if(name==="!"){throw["Type parameter ","="," key cannot be ","!"," never type"]}if(name.includes("!")){throw["Type parameter ","="," key cannot be ","!"," macro"]}if(name.includes("::")){throw["Type parameter ","="," key cannot contain ","::"," path"]}if(name.includes(":")){throw["Type parameter ","="," key cannot contain ",":"," type"]}parserState.isInBinding={name,generics}}else{elems.push(createQueryElement(query,parserState,parserState.userQuery.slice(start,end),generics,isInGenerics,),)}}}function checkExtraTypeFilterCharacters(start,parserState){const query=parserState.userQuery.slice(start,parserState.pos).trim();const match=query.match(REGEX_INVALID_TYPE_FILTER);if(match){throw["Unexpected ",match[0]," in type filter (before ",":",")",]}}function createQueryElement(query,parserState,name,generics,isInGenerics){const path=name.trim();if(path.length===0&&generics.length===0){throw["Unexpected ",parserState.userQuery[parserState.pos]]}if(query.literalSearch&&parserState.totalElems-parserState.genericsElems>0){throw["Cannot have more than one element if you use quotes"]}const typeFilter=parserState.typeFilter;parserState.typeFilter=null;if(name==="!"){if(typeFilter!==null&&typeFilter!=="primitive"){throw["Invalid search type: primitive never type ","!"," and ",typeFilter," both specified",]}if(generics.length!==0){throw["Never type ","!"," does not accept generic parameters",]}const bindingName=parserState.isInBinding;parserState.isInBinding=null;return makePrimitiveElement("never",{bindingName})}const quadcolon=/::\s*::/.exec(path);if(path.startsWith("::")){throw["Paths cannot start with ","::"]}else if(path.endsWith("::")){throw["Paths cannot end with ","::"]}else if(quadcolon!==null){throw["Unexpected ",quadcolon[0]]}const pathSegments=path.split(/(?:::\s*)|(?:\s+(?:::\s*)?)/);if(pathSegments.length===0||(pathSegments.length===1&&pathSegments[0]==="")){if(generics.length>0||prevIs(parserState,">")){throw["Found generics without a path"]}else{throw["Unexpected ",parserState.userQuery[parserState.pos]]}}for(const[i,pathSegment]of pathSegments.entries()){if(pathSegment==="!"){if(i!==0){throw["Never type ","!"," is not associated item"]}pathSegments[i]="never"}}parserState.totalElems+=1;if(isInGenerics){parserState.genericsElems+=1}const bindingName=parserState.isInBinding;parserState.isInBinding=null;const bindings=new Map();const pathLast=pathSegments[pathSegments.length-1];return{name:name.trim(),id:null,fullPath:pathSegments,pathWithoutLast:pathSegments.slice(0,pathSegments.length-1),pathLast,normalizedPathLast:pathLast.replace(/_/g,""),generics:generics.filter(gen=>{if(gen.bindingName!==null){if(gen.name!==null){gen.bindingName.generics.unshift(gen)}bindings.set(gen.bindingName.name,gen.bindingName.generics);return false}return true}),bindings,typeFilter,bindingName,}}function makePrimitiveElement(name,extra){return Object.assign({name,id:null,fullPath:[name],pathWithoutLast:[],pathLast:name,normalizedPathLast:name,generics:[],bindings:new Map(),typeFilter:"primitive",bindingName:null,},extra)}function getStringElem(query,parserState,isInGenerics){if(isInGenerics){throw["Unexpected ","\""," in generics"]}else if(query.literalSearch){throw["Cannot have more than one literal search element"]}else if(parserState.totalElems-parserState.genericsElems>0){throw["Cannot use literal search when there is more than one element"]}parserState.pos+=1;const start=parserState.pos;const end=getIdentEndPosition(parserState);if(parserState.pos>=parserState.length){throw["Unclosed ","\""]}else if(parserState.userQuery[end]!=="\""){throw["Unexpected ",parserState.userQuery[end]," in a string element"]}else if(start===end){throw["Cannot have empty string element"]}parserState.pos+=1;query.literalSearch=true}function getIdentEndPosition(parserState){let afterIdent=consumeIdent(parserState);let end=parserState.pos;let macroExclamation=-1;while(parserState.pos0){throw["Unexpected ",c," after ",parserState.userQuery[parserState.pos-1]," (not a valid identifier)"]}else{throw["Unexpected ",c," (not a valid identifier)"]}parserState.pos+=1;afterIdent=consumeIdent(parserState);end=parserState.pos}if(macroExclamation!==-1){if(parserState.typeFilter===null){parserState.typeFilter="macro"}else if(parserState.typeFilter!=="macro"){throw["Invalid search type: macro ","!"," and ",parserState.typeFilter," both specified",]}end=macroExclamation}return end}function isSpecialStartCharacter(c){return"<\"".indexOf(c)!==-1}function isPathStart(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="::"}function consumeIdent(parserState){REGEX_IDENT.lastIndex=parserState.pos;const match=parserState.userQuery.match(REGEX_IDENT);if(match){parserState.pos+=match[0].length;return true}return false}function isPathSeparator(c){return c===":"||c===" "}class VlqHexDecoder{constructor(string,cons){this.string=string;this.cons=cons;this.offset=0;this.backrefQueue=[]}decodeList(){let c=this.string.charCodeAt(this.offset);const ret=[];while(c!==125){ret.push(this.decode());c=this.string.charCodeAt(this.offset)}this.offset+=1;return ret}decode(){let n=0;let c=this.string.charCodeAt(this.offset);if(c===123){this.offset+=1;return this.decodeList()}while(c<96){n=(n<<4)|(c&0xF);this.offset+=1;c=this.string.charCodeAt(this.offset)}n=(n<<4)|(c&0xF);const[sign,value]=[n&1,n>>1];this.offset+=1;return sign?-value:value}next(){const c=this.string.charCodeAt(this.offset);if(c>=48&&c<64){this.offset+=1;return this.backrefQueue[c-48]}if(c===96){this.offset+=1;return this.cons(0)}const result=this.cons(this.decode());this.backrefQueue.unshift(result);if(this.backrefQueue.length>16){this.backrefQueue.pop()}return result}}class RoaringBitmap{constructor(str){const strdecoded=atob(str);const u8array=new Uint8Array(strdecoded.length);for(let j=0;j=4){offsets=[];for(let j=0;j>3]&(1<<(j&0x7))){const runcount=(u8array[i]|(u8array[i+1]<<8));i+=2;this.containers.push(new RoaringBitmapRun(runcount,u8array.slice(i,i+(runcount*4)),));i+=runcount*4}else if(this.cardinalities[j]>=4096){this.containers.push(new RoaringBitmapBits(u8array.slice(i,i+8192)));i+=8192}else{const end=this.cardinalities[j]*2;this.containers.push(new RoaringBitmapArray(this.cardinalities[j],u8array.slice(i,i+end),));i+=end}}}contains(keyvalue){const key=keyvalue>>16;const value=keyvalue&0xFFFF;for(let i=0;i=start&&value<=(start+lenm1)){return true}}return false}}class RoaringBitmapArray{constructor(cardinality,array){this.cardinality=cardinality;this.array=array}contains(value){const l=this.cardinality*2;for(let i=0;i>3]&(1<<(value&7)))}}class DocSearch{constructor(rawSearchIndex,rootPath,searchState){this.searchIndexDeprecated=new Map();this.searchIndexEmptyDesc=new Map();this.functionTypeFingerprint=null;this.typeNameIdMap=new Map();this.ALIASES=new Map();this.rootPath=rootPath;this.searchState=searchState;this.typeNameIdOfArray=this.buildTypeMapIndex("array");this.typeNameIdOfSlice=this.buildTypeMapIndex("slice");this.typeNameIdOfArrayOrSlice=this.buildTypeMapIndex("[]");this.typeNameIdOfTuple=this.buildTypeMapIndex("tuple");this.typeNameIdOfUnit=this.buildTypeMapIndex("unit");this.typeNameIdOfTupleOrUnit=this.buildTypeMapIndex("()");this.typeNameIdOfFn=this.buildTypeMapIndex("fn");this.typeNameIdOfFnMut=this.buildTypeMapIndex("fnmut");this.typeNameIdOfFnOnce=this.buildTypeMapIndex("fnonce");this.typeNameIdOfHof=this.buildTypeMapIndex("->");this.EMPTY_BINDINGS_MAP=new Map();this.EMPTY_GENERICS_ARRAY=[];this.TYPES_POOL=new Map();this.searchIndex=this.buildIndex(rawSearchIndex)}buildTypeMapIndex(name,isAssocType){if(name===""||name===null){return null}if(this.typeNameIdMap.has(name)){const obj=this.typeNameIdMap.get(name);obj.assocOnly=isAssocType&&obj.assocOnly;return obj.id}else{const id=this.typeNameIdMap.size;this.typeNameIdMap.set(name,{id,assocOnly:isAssocType});return id}}buildItemSearchTypeAll(types,lowercasePaths){return types.length>0?types.map(type=>this.buildItemSearchType(type,lowercasePaths)):this.EMPTY_GENERICS_ARRAY}buildItemSearchType(type,lowercasePaths,isAssocType){const PATH_INDEX_DATA=0;const GENERICS_DATA=1;const BINDINGS_DATA=2;let pathIndex,generics,bindings;if(typeof type==="number"){pathIndex=type;generics=this.EMPTY_GENERICS_ARRAY;bindings=this.EMPTY_BINDINGS_MAP}else{pathIndex=type[PATH_INDEX_DATA];generics=this.buildItemSearchTypeAll(type[GENERICS_DATA],lowercasePaths,);if(type.length>BINDINGS_DATA&&type[BINDINGS_DATA].length>0){bindings=new Map(type[BINDINGS_DATA].map(binding=>{const[assocType,constraints]=binding;return[this.buildItemSearchType(assocType,lowercasePaths,true).id,this.buildItemSearchTypeAll(constraints,lowercasePaths),]}))}else{bindings=this.EMPTY_BINDINGS_MAP}}let result;if(pathIndex<0){result={id:pathIndex,ty:TY_GENERIC,path:null,exactPath:null,generics,bindings,}}else if(pathIndex===0){result={id:null,ty:null,path:null,exactPath:null,generics,bindings,}}else{const item=lowercasePaths[pathIndex-1];result={id:this.buildTypeMapIndex(item.name,isAssocType),ty:item.ty,path:item.path,exactPath:item.exactPath,generics,bindings,}}const cr=this.TYPES_POOL.get(result.id);if(cr){if(cr.generics.length===result.generics.length&&cr.generics!==result.generics&&cr.generics.every((x,i)=>result.generics[i]===x)){result.generics=cr.generics}if(cr.bindings.size===result.bindings.size&&cr.bindings!==result.bindings){let ok=true;for(const[k,v]of cr.bindings.entries()){const v2=result.bindings.get(v);if(!v2){ok=false;break}if(v!==v2&&v.length===v2.length&&v.every((x,i)=>v2[i]===x)){result.bindings.set(k,v)}else if(v!==v2){ok=false;break}}if(ok){result.bindings=cr.bindings}}if(cr.ty===result.ty&&cr.path===result.path&&cr.bindings===result.bindings&&cr.generics===result.generics&&cr.ty===result.ty){return cr}}this.TYPES_POOL.set(result.id,result);return result}buildFunctionTypeFingerprint(type,output,fps){let input=type.id;if(input===this.typeNameIdOfArray||input===this.typeNameIdOfSlice){input=this.typeNameIdOfArrayOrSlice}if(input===this.typeNameIdOfTuple||input===this.typeNameIdOfUnit){input=this.typeNameIdOfTupleOrUnit}if(input===this.typeNameIdOfFn||input===this.typeNameIdOfFnMut||input===this.typeNameIdOfFnOnce){input=this.typeNameIdOfHof}const hashint1=k=>{k=(~~k+0x7ed55d16)+(k<<12);k=(k ^ 0xc761c23c)^(k>>>19);k=(~~k+0x165667b1)+(k<<5);k=(~~k+0xd3a2646c)^(k<<9);k=(~~k+0xfd7046c5)+(k<<3);return(k ^ 0xb55a4f09)^(k>>>16)};const hashint2=k=>{k=~k+(k<<15);k ^=k>>>12;k+=k<<2;k ^=k>>>4;k=Math.imul(k,2057);return k ^(k>>16)};if(input!==null){const h0a=hashint1(input);const h0b=hashint2(input);const h1a=~~(h0a+Math.imul(h0b,2));const h1b=~~(h0a+Math.imul(h0b,3));const h2a=~~(h0a+Math.imul(h0b,4));const h2b=~~(h0a+Math.imul(h0b,5));output[0]|=(1<<(h0a%32))|(1<<(h1b%32));output[1]|=(1<<(h1a%32))|(1<<(h2b%32));output[2]|=(1<<(h2a%32))|(1<<(h0b%32));fps.add(input)}for(const g of type.generics){this.buildFunctionTypeFingerprint(g,output,fps)}const fb={id:null,ty:0,generics:this.EMPTY_GENERICS_ARRAY,bindings:this.EMPTY_BINDINGS_MAP,};for(const[k,v]of type.bindings.entries()){fb.id=k;fb.generics=v;this.buildFunctionTypeFingerprint(fb,output,fps)}output[3]=fps.size}buildIndex(rawSearchIndex){const buildFunctionSearchTypeCallback=lowercasePaths=>{return functionSearchType=>{if(functionSearchType===0){return null}const INPUTS_DATA=0;const OUTPUT_DATA=1;let inputs,output;if(typeof functionSearchType[INPUTS_DATA]==="number"){inputs=[this.buildItemSearchType(functionSearchType[INPUTS_DATA],lowercasePaths),]}else{inputs=this.buildItemSearchTypeAll(functionSearchType[INPUTS_DATA],lowercasePaths,)}if(functionSearchType.length>1){if(typeof functionSearchType[OUTPUT_DATA]==="number"){output=[this.buildItemSearchType(functionSearchType[OUTPUT_DATA],lowercasePaths,),]}else{output=this.buildItemSearchTypeAll(functionSearchType[OUTPUT_DATA],lowercasePaths,)}}else{output=[]}const where_clause=[];const l=functionSearchType.length;for(let i=2;inoop);let descShard={crate,shard:0,start:0,len:itemDescShardDecoder.next(),promise:null,resolve:null,};const descShardList=[descShard];this.searchIndexDeprecated.set(crate,new RoaringBitmap(crateCorpus.c));this.searchIndexEmptyDesc.set(crate,new RoaringBitmap(crateCorpus.e));let descIndex=0;const crateRow={crate,ty:3,name:crate,path:"",descShard,descIndex,exactPath:"",desc:crateCorpus.doc,parent:undefined,type:null,id,word:crate,normalizedName:crate.indexOf("_")===-1?crate:crate.replace(/_/g,""),bitIndex:0,implDisambiguator:null,};id+=1;searchIndex.push(crateRow);currentIndex+=1;if(!this.searchIndexEmptyDesc.get(crate).contains(0)){descIndex+=1}const itemTypes=crateCorpus.t;const itemNames=crateCorpus.n;const itemPaths=new Map(crateCorpus.q);const itemReexports=new Map(crateCorpus.r);const itemParentIdxDecoder=new VlqHexDecoder(crateCorpus.i,noop=>noop);const implDisambiguator=new Map(crateCorpus.b);const paths=crateCorpus.p;const aliases=crateCorpus.a;const lowercasePaths=[];const itemFunctionDecoder=new VlqHexDecoder(crateCorpus.f,buildFunctionSearchTypeCallback(lowercasePaths),);let len=paths.length;let lastPath=itemPaths.get(0);for(let i=0;i2){path=itemPaths.has(elem[2])?itemPaths.get(elem[2]):lastPath;lastPath=path}const exactPath=elem.length>3?itemPaths.get(elem[3]):path;lowercasePaths.push({ty,name:name.toLowerCase(),path,exactPath});paths[i]={ty,name,path,exactPath}}lastPath="";len=itemTypes.length;let lastName="";let lastWord="";for(let i=0;i=descShard.len&&!this.searchIndexEmptyDesc.get(crate).contains(bitIndex)){descShard={crate,shard:descShard.shard+1,start:descShard.start+descShard.len,len:itemDescShardDecoder.next(),promise:null,resolve:null,};descIndex=0;descShardList.push(descShard)}const name=itemNames[i]===""?lastName:itemNames[i];const word=itemNames[i]===""?lastWord:itemNames[i].toLowerCase();const path=itemPaths.has(i)?itemPaths.get(i):lastPath;const type=itemFunctionDecoder.next();if(type!==null){if(type){const fp=this.functionTypeFingerprint.subarray(id*4,(id+1)*4);const fps=new Set();for(const t of type.inputs){this.buildFunctionTypeFingerprint(t,fp,fps)}for(const t of type.output){this.buildFunctionTypeFingerprint(t,fp,fps)}for(const w of type.where_clause){for(const t of w){this.buildFunctionTypeFingerprint(t,fp,fps)}}}}const itemParentIdx=itemParentIdxDecoder.next();const row={crate,ty:itemTypes.charCodeAt(i)-65,name,path,descShard,descIndex,exactPath:itemReexports.has(i)?itemPaths.get(itemReexports.get(i)):path,parent:itemParentIdx>0?paths[itemParentIdx-1]:undefined,type,id,word,normalizedName:word.indexOf("_")===-1?word:word.replace(/_/g,""),bitIndex,implDisambiguator:implDisambiguator.has(i)?implDisambiguator.get(i):null,};id+=1;searchIndex.push(row);lastPath=row.path;if(!this.searchIndexEmptyDesc.get(crate).contains(bitIndex)){descIndex+=1}lastName=name;lastWord=word}if(aliases){const currentCrateAliases=new Map();this.ALIASES.set(crate,currentCrateAliases);for(const alias_name in aliases){if(!Object.prototype.hasOwnProperty.call(aliases,alias_name)){continue}let currentNameAliases;if(currentCrateAliases.has(alias_name)){currentNameAliases=currentCrateAliases.get(alias_name)}else{currentNameAliases=[];currentCrateAliases.set(alias_name,currentNameAliases)}for(const local_alias of aliases[alias_name]){currentNameAliases.push(local_alias+currentIndex)}}}currentIndex+=itemTypes.length;this.searchState.descShards.set(crate,descShardList)}this.TYPES_POOL=new Map();return searchIndex}static parseQuery(userQuery){function itemTypeFromName(typename){const index=itemTypes.findIndex(i=>i===typename);if(index<0){throw["Unknown type filter ",typename]}return index}function convertTypeFilterOnElem(elem){if(elem.typeFilter!==null){let typeFilter=elem.typeFilter;if(typeFilter==="const"){typeFilter="constant"}elem.typeFilter=itemTypeFromName(typeFilter)}else{elem.typeFilter=NO_TYPE_FILTER}for(const elem2 of elem.generics){convertTypeFilterOnElem(elem2)}for(const constraints of elem.bindings.values()){for(const constraint of constraints){convertTypeFilterOnElem(constraint)}}}function newParsedQuery(userQuery){return{original:userQuery,userQuery:userQuery.toLowerCase(),elems:[],returned:[],foundElems:0,totalElems:0,literalSearch:false,error:null,correction:null,proposeCorrectionFrom:null,proposeCorrectionTo:null,typeFingerprint:new Uint32Array(4),}}function parseInput(query,parserState){let foundStopChar=true;while(parserState.pos"){if(isReturnArrow(parserState)){break}throw["Unexpected ",c," (did you mean ","->","?)"]}else if(parserState.pos>0){throw["Unexpected ",c," after ",parserState.userQuery[parserState.pos-1]]}throw["Unexpected ",c]}else if(c===" "){skipWhitespace(parserState);continue}if(!foundStopChar){let extra="";if(isLastElemGeneric(query.elems,parserState)){extra=[" after ",">"]}else if(prevIs(parserState,"\"")){throw["Cannot have more than one element if you use quotes"]}if(parserState.typeFilter!==null){throw["Expected ",","," or ","->",...extra,", found ",c,]}throw["Expected ",",",", ",":"," or ","->",...extra,", found ",c,]}const before=query.elems.length;getFilteredNextElem(query,parserState,query.elems,false);if(query.elems.length===before){parserState.pos+=1}foundStopChar=false}if(parserState.typeFilter!==null){throw["Unexpected ",":"," (expected path after type filter ",parserState.typeFilter+":",")",]}while(parserState.pos"]}break}else{parserState.pos+=1}}}userQuery=userQuery.trim().replace(/\r|\n|\t/g," ");const parserState={length:userQuery.length,pos:0,totalElems:0,genericsElems:0,typeFilter:null,isInBinding:null,userQuery:userQuery.toLowerCase(),};let query=newParsedQuery(userQuery);try{parseInput(query,parserState);for(const elem of query.elems){convertTypeFilterOnElem(elem)}for(const elem of query.returned){convertTypeFilterOnElem(elem)}}catch(err){query=newParsedQuery(userQuery);query.error=err;return query}if(!query.literalSearch){query.literalSearch=parserState.totalElems>1}query.foundElems=query.elems.length+query.returned.length;query.totalElems=parserState.totalElems;return query}async execQuery(parsedQuery,filterCrates,currentCrate){const results_others=new Map(),results_in_args=new Map(),results_returned=new Map();function createQueryResults(results_in_args,results_returned,results_others,parsedQuery){return{"in_args":results_in_args,"returned":results_returned,"others":results_others,"query":parsedQuery,}}const buildHrefAndPath=item=>{let displayPath;let href;const type=itemTypes[item.ty];const name=item.name;let path=item.path;let exactPath=item.exactPath;if(type==="mod"){displayPath=path+"::";href=this.rootPath+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="import"){displayPath=item.path+"::";href=this.rootPath+item.path.replace(/::/g,"/")+"/index.html#reexport."+name}else if(type==="primitive"||type==="keyword"){displayPath="";href=this.rootPath+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=this.rootPath+name+"/index.html"}else if(item.parent!==undefined){const myparent=item.parent;let anchor=type+"."+name;const parentType=itemTypes[myparent.ty];let pageType=parentType;let pageName=myparent.name;exactPath=`${myparent.exactPath}::${myparent.name}`;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){const enumNameIdx=item.path.lastIndexOf("::");const enumName=item.path.substr(enumNameIdx+2);path=item.path.substr(0,enumNameIdx);displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}if(item.implDisambiguator!==null){anchor=item.implDisambiguator+"/"+anchor}href=this.rootPath+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html#"+anchor}else{displayPath=item.path+"::";href=this.rootPath+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href,`${exactPath}::${name}`]};function pathSplitter(path){const tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}const transformResults=results=>{const duplicates=new Set();const out=[];for(const result of results){if(result.id!==-1){const obj=this.searchIndex[result.id];obj.dist=result.dist;const res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=res[2]+"|"+obj.ty;if(duplicates.has(obj.fullPath)){continue}if(obj.ty===TY_IMPORT&&duplicates.has(res[2])){continue}if(duplicates.has(res[2]+"|"+TY_IMPORT)){continue}duplicates.add(obj.fullPath);duplicates.add(res[2]);obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}return out};const sortResults=async(results,isType,preferredCrate)=>{const userQuery=parsedQuery.userQuery;const casedUserQuery=parsedQuery.original;const result_list=[];for(const result of results.values()){result.item=this.searchIndex[result.id];result.word=this.searchIndex[result.id].word;result_list.push(result)}result_list.sort((aaa,bbb)=>{let a,b;a=(aaa.item.name!==casedUserQuery);b=(bbb.item.name!==casedUserQuery);if(a!==b){return a-b}a=(aaa.word!==userQuery);b=(bbb.word!==userQuery);if(a!==b){return a-b}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.path_dist;b=bbb.path_dist;if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}a=(aaa.dist);b=(bbb.dist);if(a!==b){return a-b}a=this.searchIndexDeprecated.get(aaa.item.crate).contains(aaa.item.bitIndex);b=this.searchIndexDeprecated.get(bbb.item.crate).contains(bbb.item.bitIndex);if(a!==b){return a-b}a=(aaa.item.crate!==preferredCrate);b=(bbb.item.crate!==preferredCrate);if(a!==b){return a-b}a=aaa.word.length;b=bbb.word.length;if(a!==b){return a-b}a=aaa.word;b=bbb.word;if(a!==b){return(a>b?+1:-1)}a=this.searchIndexEmptyDesc.get(aaa.item.crate).contains(aaa.item.bitIndex);b=this.searchIndexEmptyDesc.get(bbb.item.crate).contains(bbb.item.bitIndex);if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});return transformResults(result_list)};function unifyFunctionTypes(fnTypesIn,queryElems,whereClause,mgensIn,solutionCb,unboxingDepth,){if(unboxingDepth>=UNBOXING_LIMIT){return false}const mgens=mgensIn===null?null:new Map(mgensIn);if(queryElems.length===0){return!solutionCb||solutionCb(mgens)}if(!fnTypesIn||fnTypesIn.length===0){return false}const ql=queryElems.length;const fl=fnTypesIn.length;if(ql===1&&queryElems[0].generics.length===0&&queryElems[0].bindings.size===0){const queryElem=queryElems[0];for(const fnType of fnTypesIn){if(!unifyFunctionTypeIsMatchCandidate(fnType,queryElem,mgens)){continue}if(fnType.id<0&&queryElem.id<0){if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==queryElem.id){continue}const mgensScratch=new Map(mgens);mgensScratch.set(fnType.id,queryElem.id);if(!solutionCb||solutionCb(mgensScratch)){return true}}else if(!solutionCb||solutionCb(mgens?new Map(mgens):null)){return true}}for(const fnType of fnTypesIn){if(!unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth+1,)){continue}if(fnType.id<0){if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==0){continue}const mgensScratch=new Map(mgens);mgensScratch.set(fnType.id,0);if(unifyFunctionTypes(whereClause[(-fnType.id)-1],queryElems,whereClause,mgensScratch,solutionCb,unboxingDepth+1,)){return true}}else if(unifyFunctionTypes([...fnType.generics,...Array.from(fnType.bindings.values()).flat()],queryElems,whereClause,mgens?new Map(mgens):null,solutionCb,unboxingDepth+1,)){return true}}return false}const fnTypes=fnTypesIn.slice();const flast=fl-1;const qlast=ql-1;const queryElem=queryElems[qlast];let queryElemsTmp=null;for(let i=flast;i>=0;i-=1){const fnType=fnTypes[i];if(!unifyFunctionTypeIsMatchCandidate(fnType,queryElem,mgens)){continue}let mgensScratch;if(fnType.id<0){mgensScratch=new Map(mgens);if(mgensScratch.has(fnType.id)&&mgensScratch.get(fnType.id)!==queryElem.id){continue}mgensScratch.set(fnType.id,queryElem.id)}else{mgensScratch=mgens}fnTypes[i]=fnTypes[flast];fnTypes.length=flast;if(!queryElemsTmp){queryElemsTmp=queryElems.slice(0,qlast)}const passesUnification=unifyFunctionTypes(fnTypes,queryElemsTmp,whereClause,mgensScratch,mgensScratch=>{if(fnType.generics.length===0&&queryElem.generics.length===0&&fnType.bindings.size===0&&queryElem.bindings.size===0){return!solutionCb||solutionCb(mgensScratch)}const solution=unifyFunctionTypeCheckBindings(fnType,queryElem,whereClause,mgensScratch,unboxingDepth,);if(!solution){return false}const simplifiedGenerics=solution.simplifiedGenerics;for(const simplifiedMgens of solution.mgens){const passesUnification=unifyFunctionTypes(simplifiedGenerics,queryElem.generics,whereClause,simplifiedMgens,solutionCb,unboxingDepth,);if(passesUnification){return true}}return false},unboxingDepth,);if(passesUnification){return true}fnTypes[flast]=fnTypes[i];fnTypes[i]=fnType;fnTypes.length=fl}for(let i=flast;i>=0;i-=1){const fnType=fnTypes[i];if(!unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth+1,)){continue}let mgensScratch;if(fnType.id<0){mgensScratch=new Map(mgens);if(mgensScratch.has(fnType.id)&&mgensScratch.get(fnType.id)!==0){continue}mgensScratch.set(fnType.id,0)}else{mgensScratch=mgens}const generics=fnType.id<0?whereClause[(-fnType.id)-1]:fnType.generics;const bindings=fnType.bindings?Array.from(fnType.bindings.values()).flat():[];const passesUnification=unifyFunctionTypes(fnTypes.toSpliced(i,1,...generics,...bindings),queryElems,whereClause,mgensScratch,solutionCb,unboxingDepth+1,);if(passesUnification){return true}}return false}const unifyFunctionTypeIsMatchCandidate=(fnType,queryElem,mgensIn)=>{if(!typePassesFilter(queryElem.typeFilter,fnType.ty)){return false}if(fnType.id<0&&queryElem.id<0){if(mgensIn){if(mgensIn.has(fnType.id)&&mgensIn.get(fnType.id)!==queryElem.id){return false}for(const[fid,qid]of mgensIn.entries()){if(fnType.id!==fid&&queryElem.id===qid){return false}if(fnType.id===fid&&queryElem.id!==qid){return false}}}return true}else{if(queryElem.id===this.typeNameIdOfArrayOrSlice&&(fnType.id===this.typeNameIdOfSlice||fnType.id===this.typeNameIdOfArray)){}else if(queryElem.id===this.typeNameIdOfTupleOrUnit&&(fnType.id===this.typeNameIdOfTuple||fnType.id===this.typeNameIdOfUnit)){}else if(queryElem.id===this.typeNameIdOfHof&&(fnType.id===this.typeNameIdOfFn||fnType.id===this.typeNameIdOfFnMut||fnType.id===this.typeNameIdOfFnOnce)){}else if(fnType.id!==queryElem.id||queryElem.id===null){return false}if((fnType.generics.length+fnType.bindings.size)===0&&queryElem.generics.length!==0){return false}if(fnType.bindings.size0){const fnTypePath=fnType.path!==undefined&&fnType.path!==null?fnType.path.split("::"):[];if(queryElemPathLength>fnTypePath.length){return false}let i=0;for(const path of fnTypePath){if(path===queryElem.pathWithoutLast[i]){i+=1;if(i>=queryElemPathLength){break}}}if(i0){let mgensSolutionSet=[mgensIn];for(const[name,constraints]of queryElem.bindings.entries()){if(mgensSolutionSet.length===0){return false}if(!fnType.bindings.has(name)){return false}const fnTypeBindings=fnType.bindings.get(name);mgensSolutionSet=mgensSolutionSet.flatMap(mgens=>{const newSolutions=[];unifyFunctionTypes(fnTypeBindings,constraints,whereClause,mgens,newMgens=>{newSolutions.push(newMgens);return false},unboxingDepth,);return newSolutions})}if(mgensSolutionSet.length===0){return false}const binds=Array.from(fnType.bindings.entries()).flatMap(entry=>{const[name,constraints]=entry;if(queryElem.bindings.has(name)){return[]}else{return constraints}});if(simplifiedGenerics.length>0){simplifiedGenerics=[...simplifiedGenerics,...binds]}else{simplifiedGenerics=binds}return{simplifiedGenerics,mgens:mgensSolutionSet}}return{simplifiedGenerics,mgens:[mgensIn]}}function unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth,){if(unboxingDepth>=UNBOXING_LIMIT){return false}if(fnType.id<0&&queryElem.id>=0){if(!whereClause){return false}if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==0){return false}const mgensTmp=new Map(mgens);mgensTmp.set(fnType.id,null);return checkIfInList(whereClause[(-fnType.id)-1],queryElem,whereClause,mgensTmp,unboxingDepth,)}else if(fnType.generics.length>0||fnType.bindings.size>0){const simplifiedGenerics=[...fnType.generics,...Array.from(fnType.bindings.values()).flat(),];return checkIfInList(simplifiedGenerics,queryElem,whereClause,mgens,unboxingDepth,)}return false}function checkIfInList(list,elem,whereClause,mgens,unboxingDepth){for(const entry of list){if(checkType(entry,elem,whereClause,mgens,unboxingDepth)){return true}}return false}const checkType=(row,elem,whereClause,mgens,unboxingDepth)=>{if(unboxingDepth>=UNBOXING_LIMIT){return false}if(row.bindings.size===0&&elem.bindings.size===0){if(elem.id<0&&mgens===null){return row.id<0||checkIfInList(row.generics,elem,whereClause,mgens,unboxingDepth+1,)}if(row.id>0&&elem.id>0&&elem.pathWithoutLast.length===0&&typePassesFilter(elem.typeFilter,row.ty)&&elem.generics.length===0&&elem.id!==this.typeNameIdOfArrayOrSlice&&elem.id!==this.typeNameIdOfTupleOrUnit&&elem.id!==this.typeNameIdOfHof){return row.id===elem.id||checkIfInList(row.generics,elem,whereClause,mgens,unboxingDepth,)}}return unifyFunctionTypes([row],[elem],whereClause,mgens,null,unboxingDepth)};function checkPath(contains,ty){if(contains.length===0){return 0}const maxPathEditDistance=Math.floor(contains.reduce((acc,next)=>acc+next.length,0)/3,);let ret_dist=maxPathEditDistance+1;const path=ty.path.split("::");if(ty.parent&&ty.parent.name){path.push(ty.parent.name.toLowerCase())}const length=path.length;const clength=contains.length;pathiter:for(let i=length-clength;i>=0;i-=1){let dist_total=0;for(let x=0;xmaxPathEditDistance){continue pathiter}dist_total+=dist}}ret_dist=Math.min(ret_dist,Math.round(dist_total/clength))}return ret_dist>maxPathEditDistance?null:ret_dist}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER||filter===type)return true;const name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,descShard:item.descShard,descIndex:item.descIndex,exactPath:item.exactPath,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,bitIndex:item.bitIndex,implDisambiguator:item.implDisambiguator,}}const handleAliases=async(ret,query,filterCrates,currentCrate)=>{const lowerQuery=query.toLowerCase();const aliases=[];const crateAliases=[];if(filterCrates!==null){if(this.ALIASES.has(filterCrates)&&this.ALIASES.get(filterCrates).has(lowerQuery)){const query_aliases=this.ALIASES.get(filterCrates).get(lowerQuery);for(const alias of query_aliases){aliases.push(createAliasFromItem(this.searchIndex[alias]))}}}else{for(const[crate,crateAliasesIndex]of this.ALIASES){if(crateAliasesIndex.has(lowerQuery)){const pushTo=crate===currentCrate?crateAliases:aliases;const query_aliases=crateAliasesIndex.get(lowerQuery);for(const alias of query_aliases){pushTo.push(createAliasFromItem(this.searchIndex[alias]))}}}}const sortFunc=(aaa,bbb)=>{if(aaa.path{return this.searchIndexEmptyDesc.get(alias.crate).contains(alias.bitIndex)?"":this.searchState.loadDesc(alias)};const[crateDescs,descs]=await Promise.all([Promise.all(crateAliases.map(fetchDesc)),Promise.all(aliases.map(fetchDesc)),]);const pushFunc=alias=>{alias.alias=query;const res=buildHrefAndPath(alias);alias.displayPath=pathSplitter(res[0]);alias.fullPath=alias.displayPath+alias.name;alias.href=res[1];ret.others.unshift(alias);if(ret.others.length>MAX_RESULTS){ret.others.pop()}};aliases.forEach((alias,i)=>{alias.desc=descs[i]});aliases.forEach(pushFunc);crateAliases.forEach((alias,i)=>{alias.desc=crateDescs[i]});crateAliases.forEach(pushFunc)};function addIntoResults(results,fullId,id,index,dist,path_dist,maxEditDistance){if(dist<=maxEditDistance||index!==-1){if(results.has(fullId)){const result=results.get(fullId);if(result.dontValidate||result.dist<=dist){return}}results.set(fullId,{id:id,index:index,dontValidate:parsedQuery.literalSearch,dist:dist,path_dist:path_dist,})}}function handleSingleArg(row,pos,elem,results_others,results_in_args,results_returned,maxEditDistance,){if(!row||(filterCrates!==null&&row.crate!==filterCrates)){return}let path_dist=0;const fullId=row.id;const tfpDist=compareTypeFingerprints(fullId,parsedQuery.typeFingerprint,);if(tfpDist!==null){const in_args=row.type&&row.type.inputs&&checkIfInList(row.type.inputs,elem,row.type.where_clause,null,0);const returned=row.type&&row.type.output&&checkIfInList(row.type.output,elem,row.type.where_clause,null,0);if(in_args){results_in_args.max_dist=Math.max(results_in_args.max_dist||0,tfpDist);const maxDist=results_in_args.sizenormalizedIndex&&normalizedIndex!==-1)){index=normalizedIndex}if(elem.fullPath.length>1){path_dist=checkPath(elem.pathWithoutLast,row);if(path_dist===null){return}}if(parsedQuery.literalSearch){if(row.word===elem.pathLast){addIntoResults(results_others,fullId,pos,index,0,path_dist)}return}const dist=editDistance(row.normalizedName,elem.normalizedPathLast,maxEditDistance);if(index===-1&&dist>maxEditDistance){return}addIntoResults(results_others,fullId,pos,index,dist,path_dist,maxEditDistance)}function handleArgs(row,pos,results){if(!row||(filterCrates!==null&&row.crate!==filterCrates)||!row.type){return}const tfpDist=compareTypeFingerprints(row.id,parsedQuery.typeFingerprint,);if(tfpDist===null){return}if(results.size>=MAX_RESULTS&&tfpDist>results.max_dist){return}if(!unifyFunctionTypes(row.type.inputs,parsedQuery.elems,row.type.where_clause,null,mgens=>{return unifyFunctionTypes(row.type.output,parsedQuery.returned,row.type.where_clause,mgens,null,0,)},0,)){return}results.max_dist=Math.max(results.max_dist||0,tfpDist);addIntoResults(results,row.id,pos,0,tfpDist,0,Number.MAX_VALUE)}const compareTypeFingerprints=(fullId,queryFingerprint)=>{const fh0=this.functionTypeFingerprint[fullId*4];const fh1=this.functionTypeFingerprint[(fullId*4)+1];const fh2=this.functionTypeFingerprint[(fullId*4)+2];const[qh0,qh1,qh2]=queryFingerprint;const[in0,in1,in2]=[fh0&qh0,fh1&qh1,fh2&qh2];if((in0 ^ qh0)||(in1 ^ qh1)||(in2 ^ qh2)){return null}return this.functionTypeFingerprint[(fullId*4)+3]};const innerRunQuery=()=>{const queryLen=parsedQuery.elems.reduce((acc,next)=>acc+next.pathLast.length,0)+parsedQuery.returned.reduce((acc,next)=>acc+next.pathLast.length,0);const maxEditDistance=Math.floor(queryLen/3);const genericSymbols=new Map();const convertNameToId=(elem,isAssocType)=>{const loweredName=elem.pathLast.toLowerCase();if(this.typeNameIdMap.has(loweredName)&&(isAssocType||!this.typeNameIdMap.get(loweredName).assocOnly)){elem.id=this.typeNameIdMap.get(loweredName).id}else if(!parsedQuery.literalSearch){let match=null;let matchDist=maxEditDistance+1;let matchName="";for(const[name,{id,assocOnly}]of this.typeNameIdMap){const dist=Math.min(editDistance(name,loweredName,maxEditDistance),editDistance(name,elem.normalizedPathLast,maxEditDistance),);if(dist<=matchDist&&dist<=maxEditDistance&&(isAssocType||!assocOnly)){if(dist===matchDist&&matchName>name){continue}match=id;matchDist=dist;matchName=name}}if(match!==null){parsedQuery.correction=matchName}elem.id=match}if((elem.id===null&&parsedQuery.totalElems>1&&elem.typeFilter===-1&&elem.generics.length===0&&elem.bindings.size===0)||elem.typeFilter===TY_GENERIC){if(genericSymbols.has(elem.name)){elem.id=genericSymbols.get(elem.name)}else{elem.id=-(genericSymbols.size+1);genericSymbols.set(elem.name,elem.id)}if(elem.typeFilter===-1&&elem.name.length>=3){const maxPartDistance=Math.floor(elem.name.length/3);let matchDist=maxPartDistance+1;let matchName="";for(const name of this.typeNameIdMap.keys()){const dist=editDistance(name,elem.name,maxPartDistance);if(dist<=matchDist&&dist<=maxPartDistance){if(dist===matchDist&&matchName>name){continue}matchDist=dist;matchName=name}}if(matchName!==""){parsedQuery.proposeCorrectionFrom=elem.name;parsedQuery.proposeCorrectionTo=matchName}}elem.typeFilter=TY_GENERIC}if(elem.generics.length>0&&elem.typeFilter===TY_GENERIC){parsedQuery.error=["Generic type parameter ",elem.name," does not accept generic parameters",]}for(const elem2 of elem.generics){convertNameToId(elem2)}elem.bindings=new Map(Array.from(elem.bindings.entries()).map(entry=>{const[name,constraints]=entry;if(!this.typeNameIdMap.has(name)){parsedQuery.error=["Type parameter ",name," does not exist",];return[null,[]]}for(const elem2 of constraints){convertNameToId(elem2)}return[this.typeNameIdMap.get(name).id,constraints]}),)};const fps=new Set();for(const elem of parsedQuery.elems){convertNameToId(elem);this.buildFunctionTypeFingerprint(elem,parsedQuery.typeFingerprint,fps)}for(const elem of parsedQuery.returned){convertNameToId(elem);this.buildFunctionTypeFingerprint(elem,parsedQuery.typeFingerprint,fps)}if(parsedQuery.foundElems===1&&parsedQuery.returned.length===0){if(parsedQuery.elems.length===1){const elem=parsedQuery.elems[0];const length=this.searchIndex.length;for(let i=0,nSearchIndex=length;i0){const sortQ=(a,b)=>{const ag=a.generics.length===0&&a.bindings.size===0;const bg=b.generics.length===0&&b.bindings.size===0;if(ag!==bg){return ag-bg}const ai=a.id>0;const bi=b.id>0;return ai-bi};parsedQuery.elems.sort(sortQ);parsedQuery.returned.sort(sortQ);for(let i=0,nSearchIndex=this.searchIndex.length;i{const descs=await Promise.all(list.map(result=>{return this.searchIndexEmptyDesc.get(result.crate).contains(result.bitIndex)?"":this.searchState.loadDesc(result)}));for(const[i,result]of list.entries()){result.desc=descs[i]}}));if(parsedQuery.error!==null&&ret.others.length!==0){ret.query.error=null}return ret}}let rawSearchIndex;let docSearch;const longItemTypes=["keyword","primitive type","module","extern crate","re-export","struct","enum","function","type alias","static","trait","","trait method","method","struct field","enum variant","macro","assoc type","constant","assoc const","union","foreign type","existential type","attribute macro","derive macro","trait alias",];let currentResults;function printTab(nb){let iter=0;let foundCurrentTab=false;let foundCurrentResultSet=false;onEachLazy(document.getElementById("search-tabs").childNodes,elem=>{if(nb===iter){addClass(elem,"selected");foundCurrentTab=true}else{removeClass(elem,"selected")}iter+=1});const isTypeSearch=(nb>0||iter===1);iter=0;onEachLazy(document.getElementById("results").childNodes,elem=>{if(nb===iter){addClass(elem,"active");foundCurrentResultSet=true}else{removeClass(elem,"active")}iter+=1});if(foundCurrentTab&&foundCurrentResultSet){searchState.currentTab=nb;const correctionsElem=document.getElementsByClassName("search-corrections");if(isTypeSearch){removeClass(correctionsElem[0],"hidden")}else{addClass(correctionsElem[0],"hidden")}}else if(nb!==0){printTab(0)}}function buildUrl(search,filterCrates){let extra="?search="+encodeURIComponent(search);if(filterCrates!==null){extra+="&filter-crate="+encodeURIComponent(filterCrates)}return getNakedUrl()+extra+window.location.hash}function getFilterCrates(){const elem=document.getElementById("crate-search");if(elem&&elem.value!=="all crates"&&window.searchIndex.has(elem.value)){return elem.value}return null}function nextTab(direction){const next=(searchState.currentTab+direction+3)%searchState.focusedByTab.length;searchState.focusedByTab[searchState.currentTab]=document.activeElement;printTab(next);focusSearchResult()}function focusSearchResult(){const target=searchState.focusedByTab[searchState.currentTab]||document.querySelectorAll(".search-results.active a").item(0)||document.querySelectorAll("#search-tabs button").item(searchState.currentTab);searchState.focusedByTab[searchState.currentTab]=null;if(target){target.focus()}}async function addTab(array,query,display){const extraClass=display?" active":"";const output=document.createElement("div");if(array.length>0){output.className="search-results "+extraClass;for(const item of array){const name=item.name;const type=itemTypes[item.ty];const longType=longItemTypes[item.ty];const typeName=longType.length!==0?`${longType}`:"?";const link=document.createElement("a");link.className="result-"+type;link.href=item.href;const resultName=document.createElement("div");resultName.className="result-name";resultName.insertAdjacentHTML("beforeend",`${typeName}`);link.appendChild(resultName);let alias=" ";if(item.is_alias){alias=`
\ +${item.alias} - see \ +
`}resultName.insertAdjacentHTML("beforeend",`
${alias}\ +${item.displayPath}${name}\ +
`);const description=document.createElement("div");description.className="desc";description.insertAdjacentHTML("beforeend",item.desc);link.appendChild(description);output.appendChild(link)}}else if(query.error===null){output.className="search-failed"+extraClass;output.innerHTML="No results :(
"+"Try on DuckDuckGo?

"+"Or try looking in one of these:"}return[output,array.length]}function makeTabHeader(tabNb,text,nbElems){const fmtNbElems=nbElems<10?`\u{2007}(${nbElems})\u{2007}\u{2007}`:nbElems<100?`\u{2007}(${nbElems})\u{2007}`:`\u{2007}(${nbElems})`;if(searchState.currentTab===tabNb){return""}return""}async function showResults(results,go_to_first,filterCrates){const search=searchState.outputElement();if(go_to_first||(results.others.length===1&&getSettingValue("go-to-only-result")==="true")){window.onunload=()=>{};searchState.removeQueryParameters();const elem=document.createElement("a");elem.href=results.others[0].href;removeClass(elem,"active");document.body.appendChild(elem);elem.click();return}if(results.query===undefined){results.query=DocSearch.parseQuery(searchState.input.value)}currentResults=results.query.userQuery;const[ret_others,ret_in_args,ret_returned]=await Promise.all([addTab(results.others,results.query,true),addTab(results.in_args,results.query,false),addTab(results.returned,results.query,false),]);let currentTab=searchState.currentTab;if((currentTab===0&&ret_others[1]===0)||(currentTab===1&&ret_in_args[1]===0)||(currentTab===2&&ret_returned[1]===0)){if(ret_others[1]!==0){currentTab=0}else if(ret_in_args[1]!==0){currentTab=1}else if(ret_returned[1]!==0){currentTab=2}}let crates="";if(rawSearchIndex.size>1){crates=" in 
"}let output=`

Results${crates}

`;if(results.query.error!==null){const error=results.query.error;error.forEach((value,index)=>{value=value.split("<").join("<").split(">").join(">");if(index%2!==0){error[index]=`${value.replaceAll(" ", " ")}`}else{error[index]=value}});output+=`

Query parser error: "${error.join("")}".

`;output+="
"+makeTabHeader(0,"In Names",ret_others[1])+"
";currentTab=0}else if(results.query.foundElems<=1&&results.query.returned.length===0){output+="
"+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
"}else{const signatureTabTitle=results.query.elems.length===0?"In Function Return Types":results.query.returned.length===0?"In Function Parameters":"In Function Signatures";output+="
"+makeTabHeader(0,signatureTabTitle,ret_others[1])+"
";currentTab=0}if(results.query.correction!==null){const orig=results.query.returned.length>0?results.query.returned[0].name:results.query.elems[0].name;output+="

"+`Type "${orig}" not found. `+"Showing results for closest type name "+`"${results.query.correction}" instead.

`}if(results.query.proposeCorrectionFrom!==null){const orig=results.query.proposeCorrectionFrom;const targ=results.query.proposeCorrectionTo;output+="

"+`Type "${orig}" not found and used as generic parameter. `+`Consider searching for "${targ}" instead.

`}const resultsElem=document.createElement("div");resultsElem.id="results";resultsElem.appendChild(ret_others[0]);resultsElem.appendChild(ret_in_args[0]);resultsElem.appendChild(ret_returned[0]);search.innerHTML=output;const crateSearch=document.getElementById("crate-search");if(crateSearch){crateSearch.addEventListener("input",updateCrate)}search.appendChild(resultsElem);searchState.showResults(search);const elems=document.getElementById("search-tabs").childNodes;searchState.focusedByTab=[];let i=0;for(const elem of elems){const j=i;elem.onclick=()=>printTab(j);searchState.focusedByTab.push(null);i+=1}printTab(currentTab)}function updateSearchHistory(url){if(!browserSupportsHistoryApi()){return}const params=searchState.getQueryStringParams();if(!history.state&&!params.search){history.pushState(null,"",url)}else{history.replaceState(null,"",url)}}async function search(forced){const query=DocSearch.parseQuery(searchState.input.value.trim());let filterCrates=getFilterCrates();if(!forced&&query.userQuery===currentResults){if(query.userQuery.length>0){putBackSearch()}return}searchState.setLoadingSearch();const params=searchState.getQueryStringParams();if(filterCrates===null&¶ms["filter-crate"]!==undefined){filterCrates=params["filter-crate"]}searchState.title="\""+query.original+"\" Search - Rust";updateSearchHistory(buildUrl(query.original,filterCrates));await showResults(await docSearch.execQuery(query,filterCrates,window.currentCrate),params.go_to_first,filterCrates)}function onSearchSubmit(e){e.preventDefault();searchState.clearInputTimeout();search()}function putBackSearch(){const search_input=searchState.input;if(!searchState.input){return}if(search_input.value!==""&&!searchState.isDisplayed()){searchState.showResults();if(browserSupportsHistoryApi()){history.replaceState(null,"",buildUrl(search_input.value,getFilterCrates()))}document.title=searchState.title}}function registerSearchEvents(){const params=searchState.getQueryStringParams();if(searchState.input.value===""){searchState.input.value=params.search||""}const searchAfter500ms=()=>{searchState.clearInputTimeout();if(searchState.input.value.length===0){searchState.hideResults()}else{searchState.timeout=setTimeout(search,500)}};searchState.input.onkeyup=searchAfter500ms;searchState.input.oninput=searchAfter500ms;document.getElementsByClassName("search-form")[0].onsubmit=onSearchSubmit;searchState.input.onchange=e=>{if(e.target!==document.activeElement){return}searchState.clearInputTimeout();setTimeout(search,0)};searchState.input.onpaste=searchState.input.onchange;searchState.outputElement().addEventListener("keydown",e=>{if(e.altKey||e.ctrlKey||e.shiftKey||e.metaKey){return}if(e.which===38){const previous=document.activeElement.previousElementSibling;if(previous){previous.focus()}else{searchState.focus()}e.preventDefault()}else if(e.which===40){const next=document.activeElement.nextElementSibling;if(next){next.focus()}const rect=document.activeElement.getBoundingClientRect();if(window.innerHeight-rect.bottom{if(e.which===40){focusSearchResult();e.preventDefault()}});searchState.input.addEventListener("focus",()=>{putBackSearch()});searchState.input.addEventListener("blur",()=>{searchState.input.placeholder=searchState.input.origPlaceholder});if(browserSupportsHistoryApi()){const previousTitle=document.title;window.addEventListener("popstate",e=>{const params=searchState.getQueryStringParams();document.title=previousTitle;currentResults=null;if(params.search&¶ms.search.length>0){searchState.input.value=params.search;e.preventDefault();search()}else{searchState.input.value="";searchState.hideResults()}})}window.onpageshow=()=>{const qSearch=searchState.getQueryStringParams().search;if(searchState.input.value===""&&qSearch){searchState.input.value=qSearch}search()}}function updateCrate(ev){if(ev.target.value==="all crates"){const query=searchState.input.value.trim();updateSearchHistory(buildUrl(query,null))}currentResults=null;search(true)}function initSearch(searchIndx){rawSearchIndex=searchIndx;if(typeof window!=="undefined"){docSearch=new DocSearch(rawSearchIndex,ROOT_PATH,searchState);registerSearchEvents();if(window.searchState.getQueryStringParams().search){search()}}else if(typeof exports!=="undefined"){docSearch=new DocSearch(rawSearchIndex,ROOT_PATH,searchState);exports.docSearch=docSearch;exports.parseQuery=DocSearch.parseQuery}}if(typeof exports!=="undefined"){exports.initSearch=initSearch}if(typeof window!=="undefined"){window.initSearch=initSearch;if(window.searchIndex!==undefined){initSearch(window.searchIndex)}}else{initSearch(new Map())}})() \ No newline at end of file diff --git a/static.files/settings-4313503d2e1961c2.js b/static.files/settings-4313503d2e1961c2.js new file mode 100644 index 00000000..ab425fe4 --- /dev/null +++ b/static.files/settings-4313503d2e1961c2.js @@ -0,0 +1,17 @@ +"use strict";(function(){const isSettingsPage=window.location.pathname.endsWith("/settings.html");function changeSetting(settingName,value){if(settingName==="theme"){const useSystem=value==="system preference"?"true":"false";updateLocalStorage("use-system-theme",useSystem)}updateLocalStorage(settingName,value);switch(settingName){case"theme":case"preferred-dark-theme":case"preferred-light-theme":updateTheme();updateLightAndDark();break;case"line-numbers":if(value===true){window.rustdoc_add_line_numbers_to_examples()}else{window.rustdoc_remove_line_numbers_from_examples()}break;case"hide-sidebar":if(value===true){addClass(document.documentElement,"hide-sidebar")}else{removeClass(document.documentElement,"hide-sidebar")}break}}function showLightAndDark(){removeClass(document.getElementById("preferred-light-theme"),"hidden");removeClass(document.getElementById("preferred-dark-theme"),"hidden")}function hideLightAndDark(){addClass(document.getElementById("preferred-light-theme"),"hidden");addClass(document.getElementById("preferred-dark-theme"),"hidden")}function updateLightAndDark(){const useSystem=getSettingValue("use-system-theme");if(useSystem==="true"||(useSystem===null&&getSettingValue("theme")===null)){showLightAndDark()}else{hideLightAndDark()}}function setEvents(settingsElement){updateLightAndDark();onEachLazy(settingsElement.querySelectorAll("input[type=\"checkbox\"]"),toggle=>{const settingId=toggle.id;const settingValue=getSettingValue(settingId);if(settingValue!==null){toggle.checked=settingValue==="true"}toggle.onchange=()=>{changeSetting(toggle.id,toggle.checked)}});onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"),elem=>{const settingId=elem.name;let settingValue=getSettingValue(settingId);if(settingId==="theme"){const useSystem=getSettingValue("use-system-theme");if(useSystem==="true"||settingValue===null){settingValue=useSystem==="false"?"light":"system preference"}}if(settingValue!==null&&settingValue!=="null"){elem.checked=settingValue===elem.value}elem.addEventListener("change",ev=>{changeSetting(ev.target.name,ev.target.value)})})}function buildSettingsPageSections(settings){let output="";for(const setting of settings){const js_data_name=setting["js_name"];const setting_name=setting["name"];if(setting["options"]!==undefined){output+=`\ +
+
${setting_name}
+
`;onEach(setting["options"],option=>{const checked=option===setting["default"]?" checked":"";const full=`${js_data_name}-${option.replace(/ /g,"-")}`;output+=`\ + `});output+=`\ +
+
`}else{const checked=setting["default"]===true?" checked":"";output+=`\ +
\ + \ +
`}}return output}function buildSettingsPage(){const theme_names=getVar("themes").split(",").filter(t=>t);theme_names.push("light","dark","ayu");const settings=[{"name":"Theme","js_name":"theme","default":"system preference","options":theme_names.concat("system preference"),},{"name":"Preferred light theme","js_name":"preferred-light-theme","default":"light","options":theme_names,},{"name":"Preferred dark theme","js_name":"preferred-dark-theme","default":"dark","options":theme_names,},{"name":"Auto-hide item contents for large items","js_name":"auto-hide-large-items","default":true,},{"name":"Auto-hide item methods' documentation","js_name":"auto-hide-method-docs","default":false,},{"name":"Auto-hide trait implementation documentation","js_name":"auto-hide-trait-implementations","default":false,},{"name":"Directly go to item in search if there is only one result","js_name":"go-to-only-result","default":false,},{"name":"Show line numbers on code examples","js_name":"line-numbers","default":false,},{"name":"Hide persistent navigation bar","js_name":"hide-sidebar","default":false,},{"name":"Disable keyboard shortcuts","js_name":"disable-shortcuts","default":false,},];const elementKind=isSettingsPage?"section":"div";const innerHTML=`
${buildSettingsPageSections(settings)}
`;const el=document.createElement(elementKind);el.id="settings";if(!isSettingsPage){el.className="popover"}el.innerHTML=innerHTML;if(isSettingsPage){document.getElementById(MAIN_ID).appendChild(el)}else{el.setAttribute("tabindex","-1");getSettingsButton().appendChild(el)}return el}const settingsMenu=buildSettingsPage();function displaySettings(){settingsMenu.style.display="";onEachLazy(settingsMenu.querySelectorAll("input[type='checkbox']"),el=>{const val=getSettingValue(el.id);const checked=val==="true";if(checked!==el.checked&&val!==null){el.checked=checked}})}function settingsBlurHandler(event){blurHandler(event,getSettingsButton(),window.hidePopoverMenus)}if(isSettingsPage){getSettingsButton().onclick=event=>{event.preventDefault()}}else{const settingsButton=getSettingsButton();const settingsMenu=document.getElementById("settings");settingsButton.onclick=event=>{if(settingsMenu.contains(event.target)){return}event.preventDefault();const shouldDisplaySettings=settingsMenu.style.display==="none";window.hideAllModals();if(shouldDisplaySettings){displaySettings()}};settingsButton.onblur=settingsBlurHandler;settingsButton.querySelector("a").onblur=settingsBlurHandler;onEachLazy(settingsMenu.querySelectorAll("input"),el=>{el.onblur=settingsBlurHandler});settingsMenu.onblur=settingsBlurHandler}setTimeout(()=>{setEvents(settingsMenu);if(!isSettingsPage){displaySettings()}removeClass(getSettingsButton(),"rotate")},0)})() \ No newline at end of file diff --git a/static.files/src-script-e66d777a5a92e9b2.js b/static.files/src-script-e66d777a5a92e9b2.js new file mode 100644 index 00000000..d0aebb85 --- /dev/null +++ b/static.files/src-script-e66d777a5a92e9b2.js @@ -0,0 +1 @@ +"use strict";(function(){const rootPath=getVar("root-path");const NAME_OFFSET=0;const DIRS_OFFSET=1;const FILES_OFFSET=2;const RUSTDOC_MOBILE_BREAKPOINT=700;function closeSidebarIfMobile(){if(window.innerWidth{removeClass(document.documentElement,"src-sidebar-expanded");updateLocalStorage("source-sidebar-show","false")};window.rustdocShowSourceSidebar=()=>{addClass(document.documentElement,"src-sidebar-expanded");updateLocalStorage("source-sidebar-show","true")};window.rustdocToggleSrcSidebar=()=>{if(document.documentElement.classList.contains("src-sidebar-expanded")){window.rustdocCloseSourceSidebar()}else{window.rustdocShowSourceSidebar()}};function createSrcSidebar(){const container=document.querySelector("nav.sidebar");const sidebar=document.createElement("div");sidebar.id="src-sidebar";let hasFoundFile=false;for(const[key,source]of srcIndex){source[NAME_OFFSET]=key;hasFoundFile=createDirEntry(source,sidebar,"",hasFoundFile)}container.appendChild(sidebar);const selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}}function highlightSrcLines(){const match=window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);if(!match){return}let from=parseInt(match[1],10);let to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to{onEachLazy(e.getElementsByTagName("a"),i_e=>{removeClass(i_e,"line-highlighted")})});for(let i=from;i<=to;++i){elem=document.getElementById(i);if(!elem){break}addClass(elem,"line-highlighted")}}const handleSrcHighlight=(function(){let prev_line_id=0;const set_fragment=name=>{const x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSrcLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return ev=>{let cur_line_id=parseInt(ev.target.id,10);if(isNaN(cur_line_id)||ev.ctrlKey||ev.altKey||ev.metaKey){return}ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){const tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());window.addEventListener("hashchange",highlightSrcLines);onEachLazy(document.getElementsByClassName("src-line-numbers"),el=>{el.addEventListener("click",handleSrcHighlight)});highlightSrcLines();window.createSrcSidebar=createSrcSidebar})() \ No newline at end of file diff --git a/static.files/storage-118b08c4c78b968e.js b/static.files/storage-118b08c4c78b968e.js new file mode 100644 index 00000000..98189467 --- /dev/null +++ b/static.files/storage-118b08c4c78b968e.js @@ -0,0 +1,24 @@ +"use strict";const builtinThemes=["light","dark","ayu"];const darkThemes=["dark","ayu"];window.currentTheme=document.getElementById("themeStyle");const settingsDataset=(function(){const settingsElement=document.getElementById("default-settings");return settingsElement&&settingsElement.dataset?settingsElement.dataset:null})();function getSettingValue(settingName){const current=getCurrentValue(settingName);if(current===null&&settingsDataset!==null){const def=settingsDataset[settingName.replace(/-/g,"_")];if(def!==undefined){return def}}return current}const localStoredTheme=getSettingValue("theme");function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(elem&&elem.classList){elem.classList.add(className)}}function removeClass(elem,className){if(elem&&elem.classList){elem.classList.remove(className)}}function onEach(arr,func){for(const elem of arr){if(func(elem)){return true}}return false}function onEachLazy(lazyArray,func){return onEach(Array.prototype.slice.call(lazyArray),func)}function updateLocalStorage(name,value){try{window.localStorage.setItem("rustdoc-"+name,value)}catch(e){}}function getCurrentValue(name){try{return window.localStorage.getItem("rustdoc-"+name)}catch(e){return null}}const getVar=(function getVar(name){const el=document.querySelector("head > meta[name='rustdoc-vars']");return el?el.attributes["data-"+name].value:null});function switchTheme(newThemeName,saveTheme){const themeNames=getVar("themes").split(",").filter(t=>t);themeNames.push(...builtinThemes);if(themeNames.indexOf(newThemeName)===-1){return}if(saveTheme){updateLocalStorage("theme",newThemeName)}document.documentElement.setAttribute("data-theme",newThemeName);if(builtinThemes.indexOf(newThemeName)!==-1){if(window.currentTheme){window.currentTheme.parentNode.removeChild(window.currentTheme);window.currentTheme=null}}else{const newHref=getVar("root-path")+encodeURIComponent(newThemeName)+getVar("resource-suffix")+".css";if(!window.currentTheme){if(document.readyState==="loading"){document.write(``);window.currentTheme=document.getElementById("themeStyle")}else{window.currentTheme=document.createElement("link");window.currentTheme.rel="stylesheet";window.currentTheme.id="themeStyle";window.currentTheme.href=newHref;document.documentElement.appendChild(window.currentTheme)}}else if(newHref!==window.currentTheme.href){window.currentTheme.href=newHref}}}const updateTheme=(function(){const mql=window.matchMedia("(prefers-color-scheme: dark)");function updateTheme(){if(getSettingValue("use-system-theme")!=="false"){const lightTheme=getSettingValue("preferred-light-theme")||"light";const darkTheme=getSettingValue("preferred-dark-theme")||"dark";updateLocalStorage("use-system-theme","true");switchTheme(mql.matches?darkTheme:lightTheme,true)}else{switchTheme(getSettingValue("theme"),false)}}mql.addEventListener("change",updateTheme);return updateTheme})();if(getSettingValue("use-system-theme")!=="false"&&window.matchMedia){if(getSettingValue("use-system-theme")===null&&getSettingValue("preferred-dark-theme")===null&&darkThemes.indexOf(localStoredTheme)>=0){updateLocalStorage("preferred-dark-theme",localStoredTheme)}}updateTheme();if(getSettingValue("source-sidebar-show")==="true"){addClass(document.documentElement,"src-sidebar-expanded")}if(getSettingValue("hide-sidebar")==="true"){addClass(document.documentElement,"hide-sidebar")}function updateSidebarWidth(){const desktopSidebarWidth=getSettingValue("desktop-sidebar-width");if(desktopSidebarWidth&&desktopSidebarWidth!=="null"){document.documentElement.style.setProperty("--desktop-sidebar-width",desktopSidebarWidth+"px",)}const srcSidebarWidth=getSettingValue("src-sidebar-width");if(srcSidebarWidth&&srcSidebarWidth!=="null"){document.documentElement.style.setProperty("--src-sidebar-width",srcSidebarWidth+"px",)}}updateSidebarWidth();window.addEventListener("pageshow",ev=>{if(ev.persisted){setTimeout(updateTheme,0);setTimeout(updateSidebarWidth,0)}});class RustdocSearchElement extends HTMLElement{constructor(){super()}connectedCallback(){const rootPath=getVar("root-path");const currentCrate=getVar("current-crate");this.innerHTML=``}}window.customElements.define("rustdoc-search",RustdocSearchElement) \ No newline at end of file diff --git a/trait.impl/core/clone/trait.Clone.js b/trait.impl/core/clone/trait.Clone.js new file mode 100644 index 00000000..64339625 --- /dev/null +++ b/trait.impl/core/clone/trait.Clone.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[["impl Clone for Obstacle"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[272]} \ No newline at end of file diff --git a/trait.impl/core/convert/trait.From.js b/trait.impl/core/convert/trait.From.js new file mode 100644 index 00000000..3a8d00da --- /dev/null +++ b/trait.impl/core/convert/trait.From.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[["impl From<Error> for SimulationError"],["impl From<RecordingStreamError> for SimulationError"],["impl From<SpawnError> for SimulationError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1034]} \ No newline at end of file diff --git a/trait.impl/core/default/trait.Default.js b/trait.impl/core/default/trait.Default.js new file mode 100644 index 00000000..58acd1e8 --- /dev/null +++ b/trait.impl/core/default/trait.Default.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[["impl Default for ImuConfig"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[300]} \ No newline at end of file diff --git a/trait.impl/core/error/trait.Error.js b/trait.impl/core/error/trait.Error.js new file mode 100644 index 00000000..9f0e8fd7 --- /dev/null +++ b/trait.impl/core/error/trait.Error.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[["impl Error for SimulationError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[287]} \ No newline at end of file diff --git a/trait.impl/core/fmt/trait.Debug.js b/trait.impl/core/fmt/trait.Debug.js new file mode 100644 index 00000000..0e19f8d5 --- /dev/null +++ b/trait.impl/core/fmt/trait.Debug.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[["impl Debug for SimulationError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[283]} \ No newline at end of file diff --git a/trait.impl/core/fmt/trait.Display.js b/trait.impl/core/fmt/trait.Display.js new file mode 100644 index 00000000..2e40f87c --- /dev/null +++ b/trait.impl/core/fmt/trait.Display.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[["impl Display for SimulationError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[289]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Freeze.js b/trait.impl/core/marker/trait.Freeze.js new file mode 100644 index 00000000..f4cde155 --- /dev/null +++ b/trait.impl/core/marker/trait.Freeze.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[["impl Freeze for PlannerType",1,["peng_quad::PlannerType"]],["impl Freeze for SimulationError",1,["peng_quad::SimulationError"]],["impl Freeze for CameraConfig",1,["peng_quad::config::CameraConfig"]],["impl Freeze for Config",1,["peng_quad::config::Config"]],["impl Freeze for ImuConfig",1,["peng_quad::config::ImuConfig"]],["impl Freeze for MazeConfig",1,["peng_quad::config::MazeConfig"]],["impl Freeze for MeshConfig",1,["peng_quad::config::MeshConfig"]],["impl Freeze for PIDControllerConfig",1,["peng_quad::config::PIDControllerConfig"]],["impl Freeze for PIDGains",1,["peng_quad::config::PIDGains"]],["impl Freeze for PlannerStep",1,["peng_quad::config::PlannerStep"]],["impl Freeze for QuadrotorConfig",1,["peng_quad::config::QuadrotorConfig"]],["impl Freeze for SimulationConfig",1,["peng_quad::config::SimulationConfig"]],["impl Freeze for Camera",1,["peng_quad::Camera"]],["impl Freeze for CirclePlanner",1,["peng_quad::CirclePlanner"]],["impl Freeze for HoverPlanner",1,["peng_quad::HoverPlanner"]],["impl Freeze for Imu",1,["peng_quad::Imu"]],["impl Freeze for LandingPlanner",1,["peng_quad::LandingPlanner"]],["impl Freeze for LissajousPlanner",1,["peng_quad::LissajousPlanner"]],["impl Freeze for Maze",1,["peng_quad::Maze"]],["impl Freeze for MinimumJerkLinePlanner",1,["peng_quad::MinimumJerkLinePlanner"]],["impl Freeze for MinimumSnapWaypointPlanner",1,["peng_quad::MinimumSnapWaypointPlanner"]],["impl Freeze for Obstacle",1,["peng_quad::Obstacle"]],["impl Freeze for ObstacleAvoidancePlanner",1,["peng_quad::ObstacleAvoidancePlanner"]],["impl Freeze for PIDController",1,["peng_quad::PIDController"]],["impl Freeze for PlannerManager",1,["peng_quad::PlannerManager"]],["impl Freeze for PlannerStepConfig",1,["peng_quad::PlannerStepConfig"]],["impl Freeze for Quadrotor",1,["peng_quad::Quadrotor"]],["impl Freeze for Trajectory",1,["peng_quad::Trajectory"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[8813]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Send.js b/trait.impl/core/marker/trait.Send.js new file mode 100644 index 00000000..237296ef --- /dev/null +++ b/trait.impl/core/marker/trait.Send.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[["impl Send for PlannerType",1,["peng_quad::PlannerType"]],["impl Send for SimulationError",1,["peng_quad::SimulationError"]],["impl Send for CameraConfig",1,["peng_quad::config::CameraConfig"]],["impl Send for Config",1,["peng_quad::config::Config"]],["impl Send for ImuConfig",1,["peng_quad::config::ImuConfig"]],["impl Send for MazeConfig",1,["peng_quad::config::MazeConfig"]],["impl Send for MeshConfig",1,["peng_quad::config::MeshConfig"]],["impl Send for PIDControllerConfig",1,["peng_quad::config::PIDControllerConfig"]],["impl Send for PIDGains",1,["peng_quad::config::PIDGains"]],["impl Send for PlannerStep",1,["peng_quad::config::PlannerStep"]],["impl Send for QuadrotorConfig",1,["peng_quad::config::QuadrotorConfig"]],["impl Send for SimulationConfig",1,["peng_quad::config::SimulationConfig"]],["impl Send for Camera",1,["peng_quad::Camera"]],["impl Send for CirclePlanner",1,["peng_quad::CirclePlanner"]],["impl Send for HoverPlanner",1,["peng_quad::HoverPlanner"]],["impl Send for Imu",1,["peng_quad::Imu"]],["impl Send for LandingPlanner",1,["peng_quad::LandingPlanner"]],["impl Send for LissajousPlanner",1,["peng_quad::LissajousPlanner"]],["impl Send for Maze",1,["peng_quad::Maze"]],["impl Send for MinimumJerkLinePlanner",1,["peng_quad::MinimumJerkLinePlanner"]],["impl Send for MinimumSnapWaypointPlanner",1,["peng_quad::MinimumSnapWaypointPlanner"]],["impl Send for Obstacle",1,["peng_quad::Obstacle"]],["impl Send for ObstacleAvoidancePlanner",1,["peng_quad::ObstacleAvoidancePlanner"]],["impl Send for PIDController",1,["peng_quad::PIDController"]],["impl Send for PlannerManager",1,["peng_quad::PlannerManager"]],["impl Send for PlannerStepConfig",1,["peng_quad::PlannerStepConfig"]],["impl Send for Quadrotor",1,["peng_quad::Quadrotor"]],["impl Send for Trajectory",1,["peng_quad::Trajectory"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[8645]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Sync.js b/trait.impl/core/marker/trait.Sync.js new file mode 100644 index 00000000..654931e1 --- /dev/null +++ b/trait.impl/core/marker/trait.Sync.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[["impl Sync for PlannerType",1,["peng_quad::PlannerType"]],["impl Sync for SimulationError",1,["peng_quad::SimulationError"]],["impl Sync for CameraConfig",1,["peng_quad::config::CameraConfig"]],["impl Sync for Config",1,["peng_quad::config::Config"]],["impl Sync for ImuConfig",1,["peng_quad::config::ImuConfig"]],["impl Sync for MazeConfig",1,["peng_quad::config::MazeConfig"]],["impl Sync for MeshConfig",1,["peng_quad::config::MeshConfig"]],["impl Sync for PIDControllerConfig",1,["peng_quad::config::PIDControllerConfig"]],["impl Sync for PIDGains",1,["peng_quad::config::PIDGains"]],["impl Sync for PlannerStep",1,["peng_quad::config::PlannerStep"]],["impl Sync for QuadrotorConfig",1,["peng_quad::config::QuadrotorConfig"]],["impl Sync for SimulationConfig",1,["peng_quad::config::SimulationConfig"]],["impl Sync for Camera",1,["peng_quad::Camera"]],["impl Sync for CirclePlanner",1,["peng_quad::CirclePlanner"]],["impl Sync for HoverPlanner",1,["peng_quad::HoverPlanner"]],["impl Sync for Imu",1,["peng_quad::Imu"]],["impl Sync for LandingPlanner",1,["peng_quad::LandingPlanner"]],["impl Sync for LissajousPlanner",1,["peng_quad::LissajousPlanner"]],["impl Sync for Maze",1,["peng_quad::Maze"]],["impl Sync for MinimumJerkLinePlanner",1,["peng_quad::MinimumJerkLinePlanner"]],["impl Sync for MinimumSnapWaypointPlanner",1,["peng_quad::MinimumSnapWaypointPlanner"]],["impl Sync for Obstacle",1,["peng_quad::Obstacle"]],["impl Sync for ObstacleAvoidancePlanner",1,["peng_quad::ObstacleAvoidancePlanner"]],["impl Sync for PIDController",1,["peng_quad::PIDController"]],["impl Sync for PlannerManager",1,["peng_quad::PlannerManager"]],["impl Sync for PlannerStepConfig",1,["peng_quad::PlannerStepConfig"]],["impl Sync for Quadrotor",1,["peng_quad::Quadrotor"]],["impl Sync for Trajectory",1,["peng_quad::Trajectory"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[8645]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Unpin.js b/trait.impl/core/marker/trait.Unpin.js new file mode 100644 index 00000000..1f4669e3 --- /dev/null +++ b/trait.impl/core/marker/trait.Unpin.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[["impl Unpin for PlannerType",1,["peng_quad::PlannerType"]],["impl Unpin for SimulationError",1,["peng_quad::SimulationError"]],["impl Unpin for CameraConfig",1,["peng_quad::config::CameraConfig"]],["impl Unpin for Config",1,["peng_quad::config::Config"]],["impl Unpin for ImuConfig",1,["peng_quad::config::ImuConfig"]],["impl Unpin for MazeConfig",1,["peng_quad::config::MazeConfig"]],["impl Unpin for MeshConfig",1,["peng_quad::config::MeshConfig"]],["impl Unpin for PIDControllerConfig",1,["peng_quad::config::PIDControllerConfig"]],["impl Unpin for PIDGains",1,["peng_quad::config::PIDGains"]],["impl Unpin for PlannerStep",1,["peng_quad::config::PlannerStep"]],["impl Unpin for QuadrotorConfig",1,["peng_quad::config::QuadrotorConfig"]],["impl Unpin for SimulationConfig",1,["peng_quad::config::SimulationConfig"]],["impl Unpin for Camera",1,["peng_quad::Camera"]],["impl Unpin for CirclePlanner",1,["peng_quad::CirclePlanner"]],["impl Unpin for HoverPlanner",1,["peng_quad::HoverPlanner"]],["impl Unpin for Imu",1,["peng_quad::Imu"]],["impl Unpin for LandingPlanner",1,["peng_quad::LandingPlanner"]],["impl Unpin for LissajousPlanner",1,["peng_quad::LissajousPlanner"]],["impl Unpin for Maze",1,["peng_quad::Maze"]],["impl Unpin for MinimumJerkLinePlanner",1,["peng_quad::MinimumJerkLinePlanner"]],["impl Unpin for MinimumSnapWaypointPlanner",1,["peng_quad::MinimumSnapWaypointPlanner"]],["impl Unpin for Obstacle",1,["peng_quad::Obstacle"]],["impl Unpin for ObstacleAvoidancePlanner",1,["peng_quad::ObstacleAvoidancePlanner"]],["impl Unpin for PIDController",1,["peng_quad::PIDController"]],["impl Unpin for PlannerManager",1,["peng_quad::PlannerManager"]],["impl Unpin for PlannerStepConfig",1,["peng_quad::PlannerStepConfig"]],["impl Unpin for Quadrotor",1,["peng_quad::Quadrotor"]],["impl Unpin for Trajectory",1,["peng_quad::Trajectory"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[8729]} \ No newline at end of file diff --git a/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js b/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js new file mode 100644 index 00000000..644309e9 --- /dev/null +++ b/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[["impl !RefUnwindSafe for SimulationError",1,["peng_quad::SimulationError"]],["impl RefUnwindSafe for PlannerType",1,["peng_quad::PlannerType"]],["impl RefUnwindSafe for CameraConfig",1,["peng_quad::config::CameraConfig"]],["impl RefUnwindSafe for Config",1,["peng_quad::config::Config"]],["impl RefUnwindSafe for ImuConfig",1,["peng_quad::config::ImuConfig"]],["impl RefUnwindSafe for MazeConfig",1,["peng_quad::config::MazeConfig"]],["impl RefUnwindSafe for MeshConfig",1,["peng_quad::config::MeshConfig"]],["impl RefUnwindSafe for PIDControllerConfig",1,["peng_quad::config::PIDControllerConfig"]],["impl RefUnwindSafe for PIDGains",1,["peng_quad::config::PIDGains"]],["impl RefUnwindSafe for PlannerStep",1,["peng_quad::config::PlannerStep"]],["impl RefUnwindSafe for QuadrotorConfig",1,["peng_quad::config::QuadrotorConfig"]],["impl RefUnwindSafe for SimulationConfig",1,["peng_quad::config::SimulationConfig"]],["impl RefUnwindSafe for Camera",1,["peng_quad::Camera"]],["impl RefUnwindSafe for CirclePlanner",1,["peng_quad::CirclePlanner"]],["impl RefUnwindSafe for HoverPlanner",1,["peng_quad::HoverPlanner"]],["impl RefUnwindSafe for Imu",1,["peng_quad::Imu"]],["impl RefUnwindSafe for LandingPlanner",1,["peng_quad::LandingPlanner"]],["impl RefUnwindSafe for LissajousPlanner",1,["peng_quad::LissajousPlanner"]],["impl RefUnwindSafe for Maze",1,["peng_quad::Maze"]],["impl RefUnwindSafe for MinimumJerkLinePlanner",1,["peng_quad::MinimumJerkLinePlanner"]],["impl RefUnwindSafe for MinimumSnapWaypointPlanner",1,["peng_quad::MinimumSnapWaypointPlanner"]],["impl RefUnwindSafe for Obstacle",1,["peng_quad::Obstacle"]],["impl RefUnwindSafe for ObstacleAvoidancePlanner",1,["peng_quad::ObstacleAvoidancePlanner"]],["impl RefUnwindSafe for PIDController",1,["peng_quad::PIDController"]],["impl RefUnwindSafe for PlannerManager",1,["peng_quad::PlannerManager"]],["impl RefUnwindSafe for PlannerStepConfig",1,["peng_quad::PlannerStepConfig"]],["impl RefUnwindSafe for Quadrotor",1,["peng_quad::Quadrotor"]],["impl RefUnwindSafe for Trajectory",1,["peng_quad::Trajectory"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[10046]} \ No newline at end of file diff --git a/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js b/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js new file mode 100644 index 00000000..12774467 --- /dev/null +++ b/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[["impl !UnwindSafe for SimulationError",1,["peng_quad::SimulationError"]],["impl UnwindSafe for PlannerType",1,["peng_quad::PlannerType"]],["impl UnwindSafe for CameraConfig",1,["peng_quad::config::CameraConfig"]],["impl UnwindSafe for Config",1,["peng_quad::config::Config"]],["impl UnwindSafe for ImuConfig",1,["peng_quad::config::ImuConfig"]],["impl UnwindSafe for MazeConfig",1,["peng_quad::config::MazeConfig"]],["impl UnwindSafe for MeshConfig",1,["peng_quad::config::MeshConfig"]],["impl UnwindSafe for PIDControllerConfig",1,["peng_quad::config::PIDControllerConfig"]],["impl UnwindSafe for PIDGains",1,["peng_quad::config::PIDGains"]],["impl UnwindSafe for PlannerStep",1,["peng_quad::config::PlannerStep"]],["impl UnwindSafe for QuadrotorConfig",1,["peng_quad::config::QuadrotorConfig"]],["impl UnwindSafe for SimulationConfig",1,["peng_quad::config::SimulationConfig"]],["impl UnwindSafe for Camera",1,["peng_quad::Camera"]],["impl UnwindSafe for CirclePlanner",1,["peng_quad::CirclePlanner"]],["impl UnwindSafe for HoverPlanner",1,["peng_quad::HoverPlanner"]],["impl UnwindSafe for Imu",1,["peng_quad::Imu"]],["impl UnwindSafe for LandingPlanner",1,["peng_quad::LandingPlanner"]],["impl UnwindSafe for LissajousPlanner",1,["peng_quad::LissajousPlanner"]],["impl UnwindSafe for Maze",1,["peng_quad::Maze"]],["impl UnwindSafe for MinimumJerkLinePlanner",1,["peng_quad::MinimumJerkLinePlanner"]],["impl UnwindSafe for MinimumSnapWaypointPlanner",1,["peng_quad::MinimumSnapWaypointPlanner"]],["impl UnwindSafe for Obstacle",1,["peng_quad::Obstacle"]],["impl UnwindSafe for ObstacleAvoidancePlanner",1,["peng_quad::ObstacleAvoidancePlanner"]],["impl UnwindSafe for PIDController",1,["peng_quad::PIDController"]],["impl UnwindSafe for PlannerManager",1,["peng_quad::PlannerManager"]],["impl UnwindSafe for PlannerStepConfig",1,["peng_quad::PlannerStepConfig"]],["impl UnwindSafe for Quadrotor",1,["peng_quad::Quadrotor"]],["impl UnwindSafe for Trajectory",1,["peng_quad::Trajectory"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[9794]} \ No newline at end of file diff --git a/trait.impl/peng_quad/trait.Planner.js b/trait.impl/peng_quad/trait.Planner.js new file mode 100644 index 00000000..1d84d3c4 --- /dev/null +++ b/trait.impl/peng_quad/trait.Planner.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[16]} \ No newline at end of file diff --git a/trait.impl/serde/de/trait.Deserialize.js b/trait.impl/serde/de/trait.Deserialize.js new file mode 100644 index 00000000..c553c4a1 --- /dev/null +++ b/trait.impl/serde/de/trait.Deserialize.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["peng_quad",[["impl<'de> Deserialize<'de> for CameraConfig"],["impl<'de> Deserialize<'de> for Config"],["impl<'de> Deserialize<'de> for ImuConfig"],["impl<'de> Deserialize<'de> for MazeConfig"],["impl<'de> Deserialize<'de> for MeshConfig"],["impl<'de> Deserialize<'de> for PIDControllerConfig"],["impl<'de> Deserialize<'de> for PIDGains"],["impl<'de> Deserialize<'de> for PlannerStep"],["impl<'de> Deserialize<'de> for QuadrotorConfig"],["impl<'de> Deserialize<'de> for SimulationConfig"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[3173]} \ No newline at end of file