Skip to main content

franka/
duration.rs

1//! Millisecond duration used for robot time stamps (mirrors `franka::Duration`).
2
3/// A duration in whole milliseconds, as reported by the robot (`RobotState::time`).
4///
5/// With the `serde` feature it serialises as the bare millisecond count.
6#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct Duration(u64);
9
10impl Duration {
11    /// Creates a duration from milliseconds.
12    pub const fn from_millis(ms: u64) -> Self {
13        Duration(ms)
14    }
15
16    /// Whole milliseconds.
17    pub const fn as_millis(self) -> u64 {
18        self.0
19    }
20
21    /// Seconds as a floating-point number (mirrors `franka::Duration::toSec`).
22    pub fn as_secs_f64(self) -> f64 {
23        self.0 as f64 * 1e-3
24    }
25
26    /// Converts to a `std::time::Duration`.
27    pub const fn to_std(self) -> std::time::Duration {
28        std::time::Duration::from_millis(self.0)
29    }
30}
31
32impl std::ops::Add for Duration {
33    type Output = Duration;
34    fn add(self, rhs: Duration) -> Duration {
35        Duration(self.0 + rhs.0)
36    }
37}
38
39impl std::ops::AddAssign for Duration {
40    fn add_assign(&mut self, rhs: Duration) {
41        self.0 += rhs.0;
42    }
43}
44
45impl std::ops::Sub for Duration {
46    type Output = Duration;
47    /// Saturating like libfranka's unsigned arithmetic would wrap; we saturate at zero instead
48    /// so a reordered state can never produce an absurd time step.
49    fn sub(self, rhs: Duration) -> Duration {
50        Duration(self.0.saturating_sub(rhs.0))
51    }
52}
53
54impl From<Duration> for std::time::Duration {
55    fn from(d: Duration) -> Self {
56        d.to_std()
57    }
58}
59
60impl std::fmt::Display for Duration {
61    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62        write!(f, "{} ms", self.0)
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn arithmetic_and_conversion() {
72        let a = Duration::from_millis(1500);
73        let b = Duration::from_millis(500);
74        assert_eq!((a - b).as_millis(), 1000);
75        assert_eq!((b - a).as_millis(), 0);
76        assert_eq!((a + b).as_millis(), 2000);
77        assert!((a.as_secs_f64() - 1.5).abs() < 1e-12);
78        assert_eq!(
79            std::time::Duration::from(a),
80            std::time::Duration::from_millis(1500)
81        );
82    }
83}