r-lidar-lab / ALSroads

Road corrections and measurements from ALS data
19 stars 4 forks source link

Issue: measure_roads() - Error in sf::st_distance(start_ori, start_new) : st_crs(x) == st_crs(y) is not TRUE #41

Closed ilythiamorley closed 2 years ago

ilythiamorley commented 2 years ago

Hi JR,

I am having an issue running the measure_roads() function on a new study area.

Most of the time the function finds new roads and runs without issue, but for some road segments I get the error:

res <- ALSroads::measure_roads(ctg = ctg, dtm = dtm, roads = roads)
#> Road 1 of 18  Progress: .....................
#> Road 2 of 18  Progress: .............................................
#> Error in sf::st_distance(start_ori, start_new) : 
#>  st_crs(x) == st_crs(y) is not TRUE

I have made sure that the CRS of all input data (ctg, dtm, roads) is the same.

I produced a subset of my data, with a new dtm, to test if the error was a result of my input data - but I get the same error.

My code is:

#---Input Data ---#
las_infolder <- "E:/example_data/subset_ctg/"
ctg <- readLAScatalog(las_infolder, filter = "-drop_withheld -keep_random_fraction 0.25")
dtm <- raster("E:/example_data/dtm/dtm.tif")
roads <- st_read("E:/example_data/roads/roads.shp")

roads <-  st_cast(roads, "LINESTRING") # multistring to linestring
roads <- tibble::rowid_to_column(roads, "ID") #add ID field 

#---All roads---#
res <- ALSroads::measure_roads(ctg = ctg, dtm = dtm, roads = roads)

#---Individal Road---# 
roads_subset <- roads %>%  dplyr::filter(ID %in% c(2))

res_individual_road <- ALSroads::measure_roads(ctg = ctg, dtm = dtm, road = roads_subset)

I would really appreciate your advice on this issue, I am unsure what I am doing to cause this.

Example data: https://drive.google.com/drive/folders/1qObZsuDXu9uG43xfDPpJ0PQTMYiQKIlf?usp=sharing

L

Jean-Romain commented 2 years ago

Road 1

For roads[1,] I get warnings.

res <- ALSroads::measure_road(ctg = ctg, centerline = roads[1,], dtm = dtm)
#> Warnings:
#> 1: EPSG code not found: header not updated. Try to provide the ESPG code instead of a crs 
#> 2: Impossible to travel to the end of the road. Road does not exist. 

Warning 2 is legit. The road is outside the collection. Actually I'm surprise it did not crash stronger. Warning 1 is not legit and must be fixed either in lidR or ALSroad. It is related to the fact it is a LAS 1.4 file. Minimal reproducible example

las_infolder <- "example_data/subset_ctg/"
ctg <- readLAScatalog(las_infolder, filter = "-drop_withheld -keep_random_fraction 0.001")
las = readLAS(ctg[1,])
data = round(data.frame(X = runif(100), Y = runif(100), Z = runif(100)), 2)
xy = LAS(data, LASheader(data))
lidR::st_crs(xy) <- sf::st_crs(ctg)
#> Message d'avis :
#> EPSG code not found: header not updated. Try to provide the ESPG code instead of a crs 

Road 2

For roads[2,] I get the error.

res <- ALSroads::measure_road(ctg = ctg, centerline = roads[2,], dtm = dtm)
#> Erreur dans sf::st_distance(start_ori, start_new) : 
#>  st_crs(x) == st_crs(y) n'est pas TRUE

It comes from a portion of code added by @jfbourdon . It is a shitty situation where the CRS of the centerline, the CRS of the point cloud and the CRS of the DTM are identical but have different representation due to the numerous way to represent CRS that are clashing. This is partly related to LAS 1.4

st_crs(roads) == st_crs(ctg)
#> FALSE

To solve this I must give precedence to one CRS. Do we want to get the output in the CRS of the point cloud or in the CRS of the roads? I think we want the road (despite being all the same actually).