diff --git a/Chapter03/Cargo.toml b/Chapter03/Cargo.toml index a79cb18..eca4514 100644 --- a/Chapter03/Cargo.toml +++ b/Chapter03/Cargo.toml @@ -6,3 +6,6 @@ version = "1.0.0" floating-duration = "0.1.2" termion = "1.0" timebomb = "0.1" +serde = "1.0" +serde_json = "1.0" +serde_derive = "1.0" diff --git a/Chapter03/src/lib.rs b/Chapter03/src/lib.rs index 2a4dcca..1e7fc06 100644 --- a/Chapter03/src/lib.rs +++ b/Chapter03/src/lib.rs @@ -4,6 +4,9 @@ mod motor; use physics::{ElevatorSpecification, ElevatorState, MotorInput, simulate_elevator, DataRecorder, MotorController, MotorVoltage}; use motor::{SmoothMotorController}; +#[macro_use] extern crate serde_derive; +extern crate serde; +extern crate serde_json; extern crate floating_duration; use std::time::Instant; use std::env; @@ -53,6 +56,7 @@ struct SimpleDataRecorder<'a, W: 'a + Write> termwidth: u64, termheight: u64, stdout: &'a mut raw::RawTerminal, + log: File, record_location: Vec, record_velocity: Vec, record_acceleration: Vec, @@ -62,10 +66,14 @@ impl<'a, W: Write> DataRecorder for SimpleDataRecorder<'a, W> { fn init(&mut self, esp: ElevatorSpecification, est: ElevatorState) { - self.esp = esp; + self.esp = esp.clone(); + self.log.write_all(serde_json::to_string(&esp.clone()).unwrap().as_bytes()).expect("write spec to log"); } fn poll(&mut self, est: ElevatorState, dst: u64) { + let datum = (est.clone(), dst); + self.log.write_all(serde_json::to_string(&datum).unwrap().as_bytes()).expect("write state to log"); + //5.4. Print realtime statistics print!("{}{}{}", clear::All, cursor::Goto(1, 1), cursor::Hide); let carriage_floor = (est.location / self.esp.floor_height).floor(); @@ -123,7 +131,7 @@ pub fn run_simulation() //1. Store location, velocity, and acceleration state //2. Store motor input voltage let mut est = ElevatorState { - timestamp: Instant::now(), + timestamp: 0.0, location: 0.0, velocity: 0.0, acceleration: 0.0, @@ -198,13 +206,14 @@ pub fn run_simulation() termwidth: termsize.map(|(w,_)| w-2).expect("termwidth") as u64, termheight: termsize.map(|(_,h)| h-2).expect("termheight") as u64, stdout: &mut io::stdout().into_raw_mode().unwrap(), + log: File::create("simulation.log").expect("log file"), record_location: Vec::new(), record_velocity: Vec::new(), record_acceleration: Vec::new(), record_voltage: Vec::new() }; let mut mc = SmoothMotorController { - timestamp: Instant::now(), + timestamp: 0.0, esp: esp.clone() }; diff --git a/Chapter03/src/motor.rs b/Chapter03/src/motor.rs index 23eac07..2ab7509 100644 --- a/Chapter03/src/motor.rs +++ b/Chapter03/src/motor.rs @@ -76,7 +76,7 @@ impl MotorController for SimpleMotorController pub struct SmoothMotorController { pub esp: ElevatorSpecification, - pub timestamp: Instant + pub timestamp: f64 } impl MotorController for SmoothMotorController @@ -130,8 +130,8 @@ impl MotorController for SmoothMotorController let going_up = est.location < (dst as f64)*self.esp.floor_height; //time elapsed since last poll - let dt = est.timestamp.duration_since(self.timestamp) - .as_fractional_secs(); + let dt = est.timestamp - self.timestamp; + self.timestamp = est.timestamp; //Do not exceed maximum velocity if est.velocity.abs() >= MAX_VELOCITY { diff --git a/Chapter03/src/physics.rs b/Chapter03/src/physics.rs index 1080a11..0e0cff5 100644 --- a/Chapter03/src/physics.rs +++ b/Chapter03/src/physics.rs @@ -3,14 +3,14 @@ use std::time::Instant; use floating_duration::{TimeAsFloat, TimeFormat}; use std::{thread, time}; -#[derive(Clone)] +#[derive(Clone,Serialize,Deserialize)] pub enum MotorInput { Up { voltage: f64 }, Down { voltage: f64 } } -#[derive(Clone)] +#[derive(Clone,Serialize,Deserialize)] pub struct ElevatorSpecification { pub floor_count: u64, @@ -18,10 +18,10 @@ pub struct ElevatorSpecification pub carriage_weight: f64 } -#[derive(Clone)] +#[derive(Clone,Serialize,Deserialize)] pub struct ElevatorState { - pub timestamp: Instant, + pub timestamp: f64, pub location: f64, pub velocity: f64, pub acceleration: f64, @@ -81,13 +81,15 @@ pub fn simulate_elevator(esp: ElevatorSpe dr.init(esp.clone(), est.clone()); //5. Loop while there are remaining floor requests + let original_ts = Instant::now(); while req.len() > 0 { //5.1. Update location, velocity, and acceleration let now = Instant::now(); - let dt = now.duration_since(est.timestamp) + let ts = now.duration_since(original_ts) .as_fractional_secs(); - est.timestamp = now; + let dt = ts - est.timestamp; + est.timestamp = ts; est.location = est.location + est.velocity * dt; est.velocity = est.velocity + est.acceleration * dt;