Skip to content

Commit

Permalink
Change road incline calculations to be stored in RawMap. Previously, the
Browse files Browse the repository at this point in the history
"rise / run" calculation used the trimmed road center-lines, which don't
match up with the elevation at each original intersection point.

Also handle infinity in the output and reduce the resolution of the
query from every 1m to every 5m.

Regenerate all maps due to the map format change. Try bringing in
elevation data for all of Seattle using the LIDAR source, since
the data quality assessed in eldang/elevation_lookups#12 seems to be
similar, and LIDAR is way faster than contours.
  • Loading branch information
dabreegster committed Mar 24, 2021
1 parent e672256 commit 4ef04f5
Show file tree
Hide file tree
Showing 17 changed files with 594 additions and 609 deletions.
40 changes: 35 additions & 5 deletions convert_osm/src/elevation.rs
Expand Up @@ -43,7 +43,7 @@ pub fn add_data(map: &mut RawMap, timer: &mut Timer) -> Result<()> {
))
.arg("-t")
// TODO Upload this to Docker Hub, so it's easier to distribute
.arg("elevation_lookups")
.arg("elevation_lookups_lidar")
.arg("python3")
.arg("main.py")
.arg("query"),
Expand Down Expand Up @@ -78,7 +78,8 @@ fn generate_input(map: &RawMap) -> Result<Vec<OriginalRoad>> {
while dist <= pl.length() {
let (pt, _) = pl.dist_along(dist).unwrap();
pts.push(pt);
dist += Distance::meters(1.0);
// Smaller gives more detail, but is slower.
dist += Distance::meters(5.0);

This comment has been minimized.

Copy link
@eldang

eldang Mar 24, 2021

I'm curious about comparing results with different spacings. The Puget Sound LIDAR data has 1m pixels, but when I look at it visually I only tend to see clear breaks at scales of 10m or more so I suspect they've applied some smoothing to avoid noise from things like vehicles on the roadway. There's a good chance that you'll see close to no difference at all with sample spacing anywhere between 1m and 10m. And if the smoothing wasn't applied, sampling too frequently might actually increase noise more than signal.

This comment has been minimized.

Copy link
@dabreegster

dabreegster Mar 25, 2021

Author Collaborator

Interesting -- increasing to 10m buys even more performance.

I'm not sure my current approach of eyeballing changes between maps incorporating different elevation data is scaling well. I'll make a quick tool to compare the values ultimately stored at the roads and intersections and color based on relatively higher/lower or steeper/flatter. Then we can more quickly compare different data sources and sample sizes. No promises on getting to this this week, though

This comment has been minimized.

Copy link
@eldang

eldang Mar 25, 2021

I don't think this is urgent at all, unless I'm stumped again when I go back to trying to parallelise lookups. In that case it might become useful to figure this out in order to decide how important parallel lookups really are. But let's first see if I can get them working after a mental break.

}
// Always ask for the intersection
if *pts.last().unwrap() != pl.last_pt() {
Expand All @@ -103,21 +104,50 @@ fn scrape_output(map: &mut RawMap, ids: Vec<OriginalRoad>) -> Result<()> {
.lines()
.zip(ids)
{
cnt += 1;
let line = line?;
let mut values = Vec::new();
for x in line.split('\t') {
values.push(Distance::meters(x.parse::<f64>()?));
let x = x.parse::<f64>()?;
if !x.is_finite() {
// TODO Warn
continue;
}
values.push(Distance::meters(x));
}
if values.len() != 4 {
bail!("Elevation output line \"{}\" doesn't have 4 numbers", line);
error!("Elevation output line \"{}\" doesn't have 4 numbers", line);
continue;
}
// TODO Also put total_climb and total_descent on the roads
map.intersections.get_mut(&id.i1).unwrap().elevation = values[0];
map.intersections.get_mut(&id.i2).unwrap().elevation = values[1];
cnt += 1;
}
if cnt != num_ids {
bail!("Output had {} lines, but we made {} queries", cnt, num_ids);
}

// Calculate the incline for each road here, before the road gets trimmed for intersection
// geometry. If we did this after trimming, we'd miss some of the horizontal distance.
for (id, road) in &mut map.roads {
let rise = map.intersections[&id.i2].elevation - map.intersections[&id.i1].elevation;
let run = PolyLine::unchecked_new(road.center_points.clone()).length();
if !(rise / run).is_finite() {
// TODO Warn?
continue;
}
road.percent_incline = rise / run;
// Per https://wiki.openstreetmap.org/wiki/Key:incline#Common_.26_extreme_inclines, we
// shouldn't often see values outside a certain range. Adjust this when we import
// somewhere exceeding this...
if road.percent_incline.abs() > 0.3 {
error!(
"{} is unexpectedly steep! Incline is {}%",
id,
road.percent_incline * 100.0
);
}
}

Ok(())
}
1 change: 1 addition & 0 deletions convert_osm/src/extract.rs
Expand Up @@ -108,6 +108,7 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
osm_tags: way.tags.clone(),
turn_restrictions: Vec::new(),
complicated_turn_restrictions: Vec::new(),
percent_incline: 0.0,
},
));
continue;
Expand Down
2 changes: 1 addition & 1 deletion convert_osm/src/lib.rs
Expand Up @@ -111,7 +111,7 @@ pub fn convert(opts: Options, timer: &mut abstutil::Timer) -> RawMap {
parking::apply_parking(&mut map, &opts, timer);

// TODO Enable for all when SRTM is ready.
if map.name.city == abstio::CityName::seattle() && false {
if map.name.city == abstio::CityName::seattle() && true {
// TODO Make this bail out on failure, after the new dependencies are clearly explained.
if let Err(err) = elevation::add_data(&mut map, timer) {
error!("No elevation data: {}", err);
Expand Down

0 comments on commit 4ef04f5

Please sign in to comment.