r-lidar / lidR

Airborne LiDAR data manipulation and visualisation for forestry application
https://CRAN.R-project.org/package=lidR
GNU General Public License v3.0
587 stars 132 forks source link

NA values in the covariance matrix #666

Closed JinyiXia closed 1 year ago

JinyiXia commented 1 year ago

Hi all,

I'm attempting to calculate some custom metrics from a TLS las file. I've set the sphere radius to 0.15 m in order to identify neighboring points, but it's possible that this value is too small, resulting in some points not having any neighboring points within that range. As a result, NA values are generated when computing the covariance matrix, which produces the following error:

Error: Error in eigen(cov_m_3d) : infinite or missing values in 'x'

I've also attempted to eliminate the NA points within the custom metric function, but a new issue has arisen where there are more pointID items than metric items, as indicated in the following error:

Error in `[.data.table`(output, , `:=`(pointID, 1:npoints(las))) : =====] 100% (1 threads)
  Supplied 2340896 items to be assigned to 2340894 items of column 'pointID'. If you wish to 'recycle' the RHS please use rep() to make this intent clear to readers of your code._

Do you have any suggestions for resolving this situation? Thank you very much!

Jean-Romain commented 1 year ago

Maybe you could provide a minimal reproducible example. At least you can mention which function you are talking about. Thank you.

JinyiXia commented 1 year ago

Thank you for your prompt reply! And sorry for the previous unclear question. To clarify, I am using the function point_metrics and the custom metrics function as described in the manual.

plane_metrics1 = function(x,y,z, th1 = 25, th2 = 6) {
  xyz <- cbind(x,y,z)
  cov_m <- cov(xyz)
  eigen_m <- eigen(cov_m)$value
  is_planar <- eigen_m[2] > (th1*eigen_m[3]) && (th2*eigen_m[2]) > eigen_m[1]
  return(list(planar = is_planar))
}

M <- point_metrics(las, ~plane_metrics1(X,Y,Z), r = 0.15)

Here is a small portion of the data: demo.zip And it gives the same error as:

Error: Error in eigen(cov_m) : infinite or missing values in 'x'

It appears that some points do not have neighboring points when a sphere radius of 0.15 is set, which may explain the issue. While there may be potential solutions to eliminate these points before we compute the covariance matrix, I am currently uncertain about how to proceed. Thank you for your assistance!

Jean-Romain commented 1 year ago

The problem comes from you code. point_metrics() feed your function with the correct neighborhood i.e. a single point central point when there is no point in a .15 radius. You must handle this case yourself in your function. The simplest options is but you may chose something more clever.

if (length(x) < 3) return (NA_real_)