trying some fixes for the various pb

master
frederic wagner 2022-07-22 13:50:53 +02:00
parent d3fcc943e6
commit f276e9e4f2
5 changed files with 68 additions and 76 deletions

View File

@ -30,3 +30,5 @@
* Waypoints information is embedded in file and extracted from comments on
points.
* Bugfix in map display (last segment was missing + wrong colors).
* Waypoint detections using OSM + sharp angles
* New algorith for direction detection

View File

@ -1,19 +1,22 @@
* bugs
- waypoints seem wrong
- direction is still shitty on gps
- we are always lost
- meters seem to be a bit too long
- direction is still shitty on gps ?
- we are always lost (done ?)
- waypoints seem wrong ?
* additional features
- display direction to nearest point
- turn off gps when moving to next waypoint
- display distance to next water/toilet
- display distance to next waypoint
- display average speed
- dynamic map rescale
- display scale (100m)
- get waypoints from osm
- compress path ?

View File

@ -541,16 +541,11 @@ function start(fn) {
}
}
if (old_points.length == 4) {
// let's just take average angle of 3 previous segments
let angles_sum = 0;
for (let i = 0; i < 3; i++) {
let p1 = old_points[i];
let p2 = old_points[i + 1];
let diff = p2.minus(p1);
let angle = Math.atan2(diff.lat, diff.lon);
angles_sum += angle;
}
status.update_position(position, angles_sum / 3.0);
// let's just take angle of segment between oldest and newest point
let oldest = old_points[0];
let diff = position.minus(oldest);
let angle = Math.atan2(diff.lat, diff.lon);
status.update_position(position, angle);
} else {
status.update_position(position, direction);
}

View File

@ -13,17 +13,26 @@ use osm::{parse_osm_data, InterestPoint};
const KEY: u16 = 47490;
const FILE_VERSION: u16 = 3;
#[derive(Debug, PartialEq, Clone, Copy)]
#[derive(Debug, Clone, Copy)]
pub struct Point {
x: f64,
y: f64,
}
impl PartialEq for Point {
fn eq(&self, other: &Self) -> bool {
(self.x - other.x).abs() < 0.0005 && (self.y - other.y).abs() < 0.0005
}
}
impl Eq for Point {}
impl std::hash::Hash for Point {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
unsafe { std::mem::transmute::<f64, u64>(self.x) }.hash(state);
unsafe { std::mem::transmute::<f64, u64>(self.y) }.hash(state);
let x = format!("{:.4}", self.x);
let y = format!("{:.4}", self.y);
x.hash(state);
y.hash(state);
// unsafe { std::mem::transmute::<f64, u64>(self.x) }.hash(state);
// unsafe { std::mem::transmute::<f64, u64>(self.y) }.hash(state);
}
}
@ -58,7 +67,7 @@ impl Point {
}
}
fn points(filename: &str) -> Vec<Vec<Point>> {
fn points(filename: &str) -> Vec<Point> {
let file = File::open(filename).unwrap();
let reader = BufReader::new(file);
@ -66,38 +75,15 @@ fn points(filename: &str) -> Vec<Vec<Point>> {
let mut gpx: Gpx = read(reader).unwrap();
eprintln!("we have {} tracks", gpx.tracks.len());
let mut points = Vec::new();
let mut iter = gpx
.tracks
gpx.tracks
.pop()
.unwrap()
.segments
.into_iter()
.flat_map(|segment| segment.points.into_iter())
.map(|p| {
let geop = p.point();
(
Point {
x: geop.x(),
y: geop.y(),
},
p.comment.is_some(),
)
})
.dedup();
let mut current_segment = iter.next().map(|(p, _)| p).into_iter().collect::<Vec<_>>();
for (p, is_waypoint) in iter {
if is_waypoint {
points.push(current_segment);
current_segment = Vec::new();
}
current_segment.push(p);
}
let last_point = current_segment.pop();
points.push(current_segment);
points.extend(last_point.map(|p| vec![p]));
points
.flat_map(|segment| segment.linestring())
.map(|c| c.x_y())
.map(|(x, y)| Point { x, y })
.collect()
}
// // NOTE: this angles idea could maybe be use to get dp from n^3 to n^2
@ -553,7 +539,7 @@ fn save_svg<'a, P: AsRef<Path>, I: IntoIterator<Item = &'a InterestPoint>>(
for point in interest_points {
writeln!(
&mut writer,
"<circle cx='{}' cy='{}' fill='{}' r='1%'/>",
"<circle cx='{}' cy='{}' fill='{}' r='0.8%'/>",
point.point.x,
point.point.y,
point.color(),
@ -563,7 +549,7 @@ fn save_svg<'a, P: AsRef<Path>, I: IntoIterator<Item = &'a InterestPoint>>(
waypoints.iter().try_for_each(|p| {
writeln!(
&mut writer,
"<circle cx='{}' cy='{}' fill='black' r='1%'/>",
"<circle cx='{}' cy='{}' fill='black' r='0.8%'/>",
p.x, p.y,
)
})?;
@ -572,11 +558,14 @@ fn save_svg<'a, P: AsRef<Path>, I: IntoIterator<Item = &'a InterestPoint>>(
Ok(())
}
fn detect_waypoints(points: &[Point]) -> HashSet<Point> {
fn detect_waypoints(points: &[Point], osm_waypoints: &HashSet<Point>) -> HashSet<Point> {
points
.first()
.into_iter()
.chain(points.iter().tuple_windows().filter_map(|(p1, p2, p3)| {
if !osm_waypoints.contains(&p2) {
return None;
}
let x1 = p2.x - p1.x;
let y1 = p2.y - p1.y;
let a1 = y1.atan2(x1);
@ -652,35 +641,21 @@ async fn main() {
let input_file = std::env::args().nth(1).unwrap_or("m.gpx".to_string());
let osm_file = std::env::args().nth(2);
eprintln!("input is {}", input_file);
let mut segmented_points = points(&input_file);
let p = segmented_points
.iter()
.flatten()
.copied()
.collect::<Vec<_>>();
let p = points(&input_file);
eprintln!("initialy we have {} points", p.len());
let rp = simplify_path(&p, 0.00015);
eprintln!("we now have {} points", rp.len());
eprintln!("we have {} waypoints", segmented_points.len());
let mut waypoints = HashSet::new();
let mut rp = Vec::new();
for (i1, i2) in (0..segmented_points.len()).tuple_windows() {
if let [s1, s2] = &mut segmented_points[i1..=i2] {
s1.extend(s2.first().copied());
waypoints.insert(s1.first().copied().unwrap());
let mut simplified = simplify_path(&s1, 0.00015);
rp.append(&mut simplified);
rp.pop();
}
}
rp.extend(segmented_points.last().and_then(|l| l.last()).copied());
let mut interests = if let Some(osm) = osm_file {
let (mut interests, osm_waypoints) = if let Some(osm) = osm_file {
parse_osm_data(osm)
} else {
Vec::new()
(Vec::new(), HashSet::new())
};
let waypoints = detect_waypoints(&rp, &osm_waypoints);
eprintln!("we found {} waypoints", waypoints.len());
// let mut interests = parse_osm_data("isere.osm.pbf");
let buckets = position_interests_along_path(&mut interests, &rp, 0.001, 5, 3);
// let i = get_openstreetmap_data(&rp).await;

View File

@ -5,8 +5,8 @@ use openstreetmap_api::{
types::{BoundingBox, Credentials},
Openstreetmap,
};
use osmio::prelude::*;
use osmio::OSMObjBase;
use osmio::{prelude::*, ObjId};
use std::collections::{HashMap, HashSet};
use std::path::Path;
@ -150,9 +150,11 @@ async fn get_openstreetmap_data(points: &[(f64, f64)]) -> HashSet<InterestPoint>
interest_points
}
pub fn parse_osm_data<P: AsRef<Path>>(path: P) -> Vec<InterestPoint> {
pub fn parse_osm_data<P: AsRef<Path>>(path: P) -> (Vec<InterestPoint>, HashSet<Point>) {
let reader = osmio::read_pbf(path).ok();
reader
let mut crossroads: HashMap<ObjId, usize> = HashMap::new();
let mut coordinates: HashMap<ObjId, Point> = HashMap::new();
let interests = reader
.map(|mut reader| {
let mut interests = Vec::new();
for obj in reader.objects() {
@ -167,13 +169,28 @@ pub fn parse_osm_data<P: AsRef<Path>>(path: P) -> Vec<InterestPoint> {
}) {
interests.push(p);
}
coordinates.insert(n.id(), Point { x: lon, y: lat });
});
}
osmio::obj_types::ArcOSMObj::Way(_) => {}
osmio::obj_types::ArcOSMObj::Way(w) => {
if !w.is_area() {
for node in w.nodes() {
*crossroads.entry(*node).or_default() += 1;
}
}
}
osmio::obj_types::ArcOSMObj::Relation(_) => {}
}
}
interests
})
.unwrap_or_default()
.unwrap_or_default();
(
interests,
crossroads
.iter()
.filter(|&(_, c)| *c >= 3)
.filter_map(|(id, _)| coordinates.get(&id).copied())
.collect(),
)
}