Browse Source

maxspeed added

Johann Woelper 7 years ago
parent
commit
2c5909e58d
2 changed files with 87 additions and 40 deletions
  1. 77 33
      src/gps.rs
  2. 10 7
      src/main.rs

+ 77 - 33
src/gps.rs

@@ -1,4 +1,3 @@
-#![feature(extern_prelude)]
 extern crate chrono;
 extern crate quick_xml;
 
@@ -11,8 +10,8 @@ use quick_xml::Writer;
 use std::fs::File;
 use std::io::prelude::*;
 use std::io::Cursor;
-use std::time::Duration as stdDuration;
 use std::path::Path;
+use std::time::Duration as stdDuration;
 
 
 #[derive(Debug, Clone)]
@@ -34,7 +33,6 @@ impl Point {
     }
 }
 
-
 #[derive(Default, Debug)]
 pub struct Track {
     pub name: String,
@@ -56,48 +54,74 @@ impl Track {
         sum
     }
 
-    fn to_xml(&self) {
+    pub fn to_xml(&self) {
         let mut writer = Writer::new_with_indent(Cursor::new(Vec::new()), 32, 4); //32 is space character
 
         let mut gpx_elem = BytesStart::owned(b"gpx".to_vec(), "gpx".len());
-        gpx_elem.push_attribute(("creator", "Pothole"));
-        assert!(writer.write_event(Event::Start(gpx_elem)).is_ok());
+        gpx_elem.push_attribute(("creator", "rust gps module"));
+        writer.write_event(Event::Start(gpx_elem)).unwrap();
 
         let trk_elem = BytesStart::owned(b"trk".to_vec(), "trk".len());
+        
+        let name_elem = BytesStart::owned(b"name".to_vec(), "name".len());
+        writer.write_event(Event::Start(name_elem)).unwrap();
+        writer.write(self.name.as_bytes()).unwrap();
+        writer.write_event(Event::End(BytesEnd::borrowed(b"name"))).unwrap();
+
         assert!(writer.write_event(Event::Start(trk_elem)).is_ok());
 
         let mut prev_point = &self.points[0];
 
         let trkseg_elem = BytesStart::owned(b"trkseg".to_vec(), "trkseg".len());
-        assert!(writer.write_event(Event::Start(trkseg_elem)).is_ok());
+        
+        assert!(writer.write_event(Event::Start(trkseg_elem.clone())).is_ok());
 
+        let mut ptnum = 0;
         for pt in &self.points {
             //segment detection
             let d = dist(prev_point, pt);
             prev_point = pt;
-
+            // if there is a gap to the last point, consider this a new segment
             if d > 0.5 {
                 assert!(
                     writer
                         .write_event(Event::End(BytesEnd::borrowed(b"trkseg")))
                         .is_ok()
                 );
-                let trkseg_elem = BytesStart::owned(b"trkseg".to_vec(), "trkseg".len());
-                assert!(writer.write_event(Event::Start(trkseg_elem)).is_ok());
-            } else {
-
+                // let trkseg_elem = BytesStart::owned(b"trkseg".to_vec(), "trkseg".len());
+                assert!(writer.write_event(Event::Start(trkseg_elem.clone())).is_ok());
             }
 
+
             let mut pt_elem = BytesStart::owned(b"trkpt".to_vec(), "trkpt".len());
             pt_elem.push_attribute(("lat", pt.lat.to_string().as_str()));
             pt_elem.push_attribute(("lon", pt.long.to_string().as_str()));
-            pt_elem.push_attribute(("ele", pt.ele.to_string().as_str()));
             assert!(writer.write_event(Event::Start(pt_elem)).is_ok());
+
+            let ele_elem = BytesStart::owned(b"ele".to_vec(), "ele".len());
+            writer.write_event(Event::Start(ele_elem)).unwrap();
+            writer.write(pt.ele.to_string().as_bytes()).unwrap();
+            writer.write_event(Event::End(BytesEnd::borrowed(b"ele"))).unwrap();
+
+            let time_timem = BytesStart::owned(b"time".to_vec(), "time".len());
+            writer.write_event(Event::Start(time_timem)).unwrap();
+            writer.write(pt.time.format("%FT%H:%M:%S%.3fZ").to_string().as_bytes()).unwrap();
+            writer.write_event(Event::End(BytesEnd::borrowed(b"time"))).unwrap();
+
+
             assert!(
                 writer
                     .write_event(Event::End(BytesEnd::borrowed(b"trkpt")))
                     .is_ok()
             );
+            if ptnum >= self.points.len()-1 {
+                assert!(
+                    writer
+                        .write_event(Event::End(BytesEnd::borrowed(b"trkseg")))
+                        .is_ok()
+                );
+            }
+            ptnum+=1;
         }
 
         assert!(
@@ -114,7 +138,6 @@ impl Track {
         let result = writer.into_inner().into_inner();
         // println!("{:?}", str::from_utf8( &result).unwrap());
 
-
         let mut name: String = self.name.clone();
         name.push_str(".gpx");
         write_bytes(result, name);
@@ -143,7 +166,37 @@ impl Track {
         }
     }
 
-    pub fn parse(&mut self) {
+
+    pub fn get_maxspeed(&mut self) -> f64 {
+        // how far to average the track together
+        let sample_distance = 0.1;
+        let mut maxspeed: f64 = 0.0;
+
+        let mut fifo_track = Track {
+            ..Default::default()
+        };
+
+        let mut analyzed_track = Track {
+            name: "analyzed".to_string(),
+            ..Default::default()
+        };
+
+
+        for pt in &self.points {
+            fifo_track.points.push(pt.clone());
+            analyzed_track.points.push(pt.clone());
+            fifo_track.truncate_by_length(sample_distance);
+            let speed = fifo_track.speed();
+            if speed > maxspeed {
+                maxspeed = speed
+            }
+        }
+        maxspeed
+    }
+
+
+
+    pub fn get_bad_points(&mut self) -> Track {
         // how far to average the track together
         let sample_distance = 0.1;
         // This is where a track is considered bad = min_speed_factor * your average over sample_distance
@@ -161,12 +214,11 @@ impl Track {
         };
 
         let mut bad_track = Track {
-            name: "bad".to_string(),
+            name: format!("{}_{}", self.name, "bad"),
             ..Default::default()
         };
 
         for pt in &self.points {
-            // i = i + 1; if i > 30 {break};
             fifo_track.points.push(pt.clone());
             analyzed_track.points.push(pt.clone());
             fifo_track.truncate_by_length(sample_distance);
@@ -176,24 +228,20 @@ impl Track {
                 // println!("Track seems bad @ Km {:.1} {:.2} Km/h", analyzed_track.len(), speed);
             }
         }
-        bad_track.to_xml();
+        bad_track
     }
 
     pub fn from_xml(&mut self, filename: String) {
-        
-    
-
         // Records for the pull parser
         let mut current_point = Point::new();
         let mut current_data = "".to_string();
 
-        println!("XML parse start.");
+        // println!("XML parse start.");
 
         let mut reader = Reader::from_file(filename).unwrap();
         reader.trim_text(true);
         let mut buf = Vec::new();
 
-        // The `Reader` does not implement `Iterator` because it outputs borrowed data (`Cow`s)
         loop {
             match reader.read_event(&mut buf) {
                 Ok(Event::Start(ref e)) => {
@@ -247,20 +295,18 @@ impl Track {
                 }
                 Ok(Event::Eof) => break, // exits the loop when reaching end of file
                 Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e),
-                _ => (), // There are several other `Event`s we do not consider here
+                _ => (),
             }
 
             // if we don't keep a borrow elsewhere, we can clear the buffer to keep memory usage low
             buf.clear();
         }
-
-        println!("XML parse end.");
+        // println!("XML parse end.");
     }
 }
 
-
 fn dist(p1: &Point, p2: &Point) -> f64 {
-    let r = 6371.0;
+    let r = 6371.0; //earth rad in km
     let d_lat = (p1.lat - p2.lat).to_radians();
     let d_long = (p1.long - p2.long).to_radians();
     let a = (d_lat / 2.0).sin() * (d_lat / 2.0).sin()
@@ -276,20 +322,18 @@ fn write_bytes(bytes_to_write: Vec<u8>, filename: String) {
     let path = Path::new(filename.as_str());
     let display = path.display();
 
-    // Open a file in write-only mode, returns `io::Result<File>`
     let mut file = match File::create(&path) {
         Err(_why) => panic!("couldn't create {}", display),
         Ok(file) => file,
     };
 
-    // Write the `LOREM_IPSUM` string to `file`, returns `io::Result<()>`
     match file.write_all("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".as_bytes()) {
         Err(_why) => panic!("couldn't write to {}", display),
-        Ok(_) => (println!("Wrote header -> {}", display)),
+        Ok(_) => (),
     }
 
     match file.write_all(&bytes_to_write) {
         Err(_why) => panic!("couldn't write to {}", display),
-        Ok(_) => println!("Wrote data -> {}", display),
+        Ok(_) => println!("Wrote xml:    {}", display),
     }
-}
+}

+ 10 - 7
src/main.rs

@@ -3,7 +3,7 @@ extern crate clap;
 extern crate quick_xml;
 // extern crate gps;
 
-use clap::{App, Arg, SubCommand};
+use clap::{App, Arg};
 
 mod gps;
 
@@ -22,7 +22,6 @@ fn main() {
         )
         .get_matches();
 
-    // Gets a value for config if supplied by user, or defaults to "default.conf"
     let trackfile = matches.value_of("track").unwrap_or("data/Day1-1.gpx");
 
     let mut trk = Track {
@@ -31,9 +30,13 @@ fn main() {
 
     trk.from_xml(trackfile.to_string());
 
-    println!("Track name: {:?}", trk.name);
-    println!("Distance: {:?} km", trk.len());
-    println!("Duration: {:?} h", trk.time().num_minutes() as f32 / 60.0);
-    println!("Speed: {:?} Km/h", trk.speed());
-    trk.parse();
+    println!("Track name:   {:?}", trk.name);
+    println!("Distance:     {:.3} km", trk.len());
+    println!("Duration:     {:?} h", trk.time().num_minutes() as f32 / 60.0);
+    println!("Max Speed:    {:.1} Km/h", trk.get_maxspeed());
+    println!("Avg Speed:    {:.1} Km/h", trk.speed());
+    
+    //write bad segments
+    trk.get_bad_points().to_xml();
+
 }