bcar 0.2.1

BCar is a Rust library with basic bicycle car computations.
Documentation
//! Basic properties of bicycle car.

/// Structure to hold car motion.
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Motion {
    pub speed: f64,
    pub steer: f64,
}

impl Motion {
    pub fn new(speed: f64, steer: f64) -> Motion {
        Motion {speed, steer}
    }

    /// Return default motion.
    ///
    ///
    /// Examples
    /// ========
    ///
    /// ```
    /// let m = bcar::Motion::default();
    /// assert_eq!(m, bcar::Motion::new(0.0, 0.0));
    /// ```
    pub fn default() -> Motion {
        Motion {speed: 0.0, steer: 0.0}
    }
}

/// Structure to hold car dimensions.
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Size {
    pub curb_to_curb: f64,
    pub width: f64, // width
    pub wheelbase: f64, // wheelbase
    pub distance_to_front: f64, // from the rear axle center
    pub length: f64,
}

impl Size {
    pub fn new(
        curb_to_curb: f64,
        width: f64,
        wheelbase: f64,
        distance_to_front: f64,
        length: f64,
    ) -> Size {
        Size {
            curb_to_curb,
            width,
            wheelbase,
            distance_to_front,
            length,
        }
    }

    /// Return default size of Porsche car.
    ///
    /// Default size is based on [Porsche Panamera 971 dimensions](https://www.porsche.com/international/models/panamera/panamera-turbo-models/panamera-turbo/featuresandspecs/).
    ///
    ///
    /// Examples
    /// ========
    ///
    /// ```
    /// let s = bcar::Size::default_porsche();
    /// assert_eq!(s, bcar::Size::new(11.8872, 2.165, 2.950, 3.9865, 5.049));
    /// ```
    pub fn default_porsche() -> Size {
        Size {
            curb_to_curb: 11.8872,
            width: 2.165,
            wheelbase: 2.950,
            distance_to_front: 3.9865,
            length: 5.049,
        }
    }

    /// Return default size of Fiat car.
    ///
    /// Default size is based on [Fiat Punto](https://en.wikipedia.org/wiki/Fiat_Punto).
    ///
    ///
    /// Examples
    /// ========
    ///
    /// ```
    /// let s = bcar::Size::default_fiat();
    /// assert_eq!(s, bcar::Size::new(10.820, 1.625, 2.450, 3.105, 3.760));
    /// ```
    pub fn default_fiat() -> Size {
        Size {
            curb_to_curb: 10.820,
            width: 1.625,
            wheelbase: 2.450,
            distance_to_front: 3.105,
            length: 3.760,
        }
    }
    pub fn default() -> Size {
        Size::default_fiat()
    }

    pub fn diagonal_length(&self) -> f64 {
        (self.width.powi(2) + self.length.powi(2)).sqrt()
    }

    /// Return maximum steering angle for the car properties.
    ///
    /// Examples
    /// ========
    ///
    ///     let s = bcar::Size::default_fiat();
    ///     assert!((s.max_steer() - 0.5483439469279819).abs() < 1e-10);
    ///     let s = bcar::Size::default_porsche();
    ///     assert!((s.max_steer() - 0.6263322191718842).abs() < 1e-10);
    pub fn max_steer(&self) -> f64 {
        // atan of wb / mtr, where mtr = ((ctc/2)^2 - wb^2)^0.5 - w/2
        self.wheelbase.atan2((
            (self.curb_to_curb/2.0).powi(2)
            - self.wheelbase.powi(2)
        ).sqrt() - self.width/2.0)
    }

    /// Return the length of the perfect parking slot.
    ///
    /// The width of the slot is the same as the width of the car.
    ///
    /// References
    /// ----------
    ///
    /// - Simon R. Blackburn *The Geometry of Perfect Parking*
    /// - https://www.ma.rhul.ac.uk/SRBparking
    pub fn perfect_parking_slot_length(&self) -> f64 {
        let r = self.curb_to_curb / 2.0;
        let l = self.wheelbase;
        let k = self.distance_to_front - self.wheelbase;
        let w = self.width;

        self.length
        + (
            (r * r - l * l)
            + (l + k).powi(2)
            - ((r * r - l * l).sqrt() - w).powi(2)
        ).sqrt()
        - l
        - k
    }
}