A set of command line tools for processing ray clouds, together with an associated C++ library.
Ray clouds are point clouds with the sensor origin stored per point (currently encoded in the 'normal' field of .ply files). Ray clouds represent free space as well as surfaces. This allows processing that cannot be done on point cloud data alone.
This is an open-source research library, a place to release new techniques in ray cloud analysis and manipulation. So if you would like to contribute with a new or improved method, do suggest it in our discussions page: https://github.com/csiro-robotics/raycloudtools/discussions.
Follow instructions in the docker folder
sudo apt-get install libeigen3-dev
git clone https://github.com/ethz-asl/libnabo.git
cd libnabo
git checkout tags/1.0.7
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo
make
sudo make install
cd ../..
git clone https://github.com/csiro-robotics/raycloudtools.git
cd raycloudtools
mkdir build
cd build
cmake ..
make
To run the rayXXXX tools from anywhere either sudo make install, or place in your ~/bashrc:
export PATH=$PATH:'source code path'/raycloudtools/build/bin
Raycloud files are loaded and saved in binary .ply format, the header section is text and follows this format:
ply
format binary_little_endian 1.0
comment generated by raycloudtools library
element vertex 0000000000<number of points>
property <float/double> x
property <float/double> y
property <float/double> z
property <float/double> time
property <float/double> nx
property <float/double> ny
property <float/double> nz
property uchar red
property uchar green
property uchar blue
property uchar alpha
end_header
followed by the binary data. By default it uses floats for x,y,z,nx,ny,nz and doubles for time. nx,ny,nz is the vector from the end point x,y,z to the sensor's location at the time that the point was observed. It is not a surface normal, but the ray representing free space from point to source.
Imported .ply point cloud files have a similar format, but without the nx,ny,nz fields, and optionally an intensity field instead of the red,green,blue,alpha:
ply
format binary_little_endian 1.0
comment Any comment here
element vertex 0000000000<number of points>
property <float/double> x
property <float/double> y
property <float/double> z
property <float/double> time
property <float/double> intensity
end_header
The range of this intensity mapped onto the raycloud's 0-255 alpha value using rayimport's max_intensity optional parameter.
The imported .laz point cloud format is the 3D point, time and intensity fields. Plus the optional colour field.
This gives an example of how the command line tools could be sequenced to analyse (top down) and generate (bottom up) ray clouds.
rayimport forest.laz forest_traj.txt Import point cloud and trajectory to a single raycloud file forest.ply. forest_traj.txt is space separated 'time x y z' per line.
raycreate room 1 Generate a single room with a window and door, using random seed 1.
You can visualise the rays in meshlab with Render | Show Vertex Normals. The ray lengths need to be scaled: Tools | Options | NormalLength roughly 0.025 (smaller for larger clouds)raydecimate room.ply 10 cm Spatially decimate cloud to one point every cubic 10 cm.
raytranslate room.ply 3 0 0 Translate the ray cloud 3 metres along the x axis.
rayrotate room.ply 0 0 30 Rotate the ray cloud 30 degrees around the z axis.
raydenoise room.ply 10 cm Remove rays with isolated end points more than 10 cm from any other, not including unbounded rays.
raysmooth room.ply Move ray end points onto the nearest surface, to smooth the resulting cloud.
rayrender room.ply top density_rgb Render the cloud from the top, as a surface area density.
raytransients min room.ply 2 rays Segment out moving or moved objects during the scan, when matter has been re-observed as missing by 2 or more rays.
Leaving the minimum of geometry when transient.
In this raycloud the table and cupboard appear only after the empty room has been scanned for several seconds, so we can isolate these transient objects.
Left: original cloud. Middle: the fixed (untransient) raycloud. Right: the remaining transient rays are also saved.
raycombine room.ply room2.ply Combine room and its transformed version together, keeping all rays.
raycombine min room.ply room2.ply 1 rays Combine the two ray clouds keeping only the minimum of geometry where there is a difference.
This is a form of union of the two volumes.
rayalign room.ply room2.ply Aligns room onto room2, allowing for a small about of non-rigidity
rayextract terrain cloud.ply extracts a ground mesh based on a conical height condition.
rayextract trees forest.ply forest_mesh.ply extracts tree structures to text file, and segments forest.
Optional build dependencies:
For rayconvert to work from .laz files:
- git clone https://github.com/LASzip/LASzip.git, then git checkout tags/2.0.1, then mkdir build, cd build, cmake .., make, sudo make install.
- git clone https://github.com/libLAS/libLAS.git, then mkdir build, cd build, cmake .. -DWITH_LASZIP=ON, make, sudo make install (you'll need GEOTIFF to be off in libLAS, and to have installed boost)
- in raycloudtools/build: cmake .. -DWITH_LAS=ON (or ccmake .. to turn on/off WITH_LAS)
- note that you may need to add the liblas path into LD_LIBRARY path, normally this can be done with the following line in your ~/.bashrc: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
For raywrap:
- git clone http://github.com/qhull/qhull.git, git checkout tags/v7.3.2
- In qhull: mkdir build, cd build, cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=true, make, sudo make install.
- in raycloudtools/build: cmake .. -DWITH_QHULL=ON (or ccmake .. to turn on/off WITH_QHULL)
To render clouds to geotif (.tif) images:
- git clone https://github.com/OSGeo/libgeotiff.git
- follow the build instructions in its README.md, note that the "DCMAKE_C_FLAGS" parameter needs a preceeding "-"
- copy a FindGeoTIFF.cmake file to your cmake folder, such as from here: https://github.com/ufz/geotiff
- in raycloudtools/build: cmake .. -DWITH_TIFF=ON (or ccmake .. to turn on/off WITH_TIFF)
Unit tests must be enabled at build time before running. To build with unit tests, the CMake variable RAYCLOUD_BUILD_TESTS
must be ON
. This can be done in the initial project configuration by running the following command from the build
directory: cmake -DRAYCLOUD_BUILD_TESTS=ON ..
Unit tests may then be run directly or using CTest
.
To run using CTest:
- Change into the
build
directory - Run
ctest .
On some platforms it may be necessary to specify the build configuration to test. For example, the Release
build may be tested using the modified command ctest . -C Release
.
When directly invoking the unit tests, is important that the tests are run from the directory to which the raycloud tools executables are built. To invoke the tests directly:
- Change into the
build
directory - Change into the
bin/
directory - Run
./raytest
This research was supported by funding from CSIRO's Data61, Land and Water, Wine Australia, and the Department of Agriculture's Rural R&D for Profit program. The authors gratefully acknowledge the support of these groups, which has helped in making this library possible.
The paper describing this software is available here: https://ieeexplore.ieee.org/abstract/document/9444433
Citations:
Lowe, Thomas, and Kazys Stepanas. "RayCloudTools: A Concise Interface for Analysis and Manipulation of Ray Clouds." IEEE Access (2021).
Lowe, T, Moghadam, P, Edwards, E, Williams, J. Canopy density estimation in perennial horticulture crops using 3D spinning lidar SLAM. J Field Robotics. 2021; 1– 21. https://doi.org/10.1002/rob.22006