diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..9367bbe --- /dev/null +++ b/.clang-format @@ -0,0 +1,7 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +TabWidth: 4 +ColumnLimit: 120 +UseTab: Never +PointerAlignment: Left +AlwaysBreakTemplateDeclarations: Yes diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..626bdf9 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,121 @@ +{ + "name": "GroundGrid", + "privileged": true, + "build": { + "dockerfile": "../Dockerfile", + "args": { + "USER_UID": "1000", + "USER_GID": "1000" + } + }, + "containerEnv": { + "ROS_AUTOMATIC_DISCOVERY_RANGE": "LOCALHOST", + "ROS_DOMAIN_ID": "0" + }, + "runArgs": [ + "--net", + "host", + "--privileged", + "--env=DISPLAY", + "--volume=/tmp/.X11-unix:/tmp/.X11-unix:rw" + ], + "hostRequirements": { + "gpu": "optional" + }, + "remoteUser": "devuser", + "workspaceFolder": "/home/devuser/workspace/groundgrid", + "mounts": [ + { + "source": "${env:HOME}/workspace", + "target": "/home/devuser/workspace", + "type": "bind" + } + ], + "postCreateCommand": "bash -c 'source /opt/ros/noetic/setup.bash'", + "customizations": { + "vscode": { + "extensions": [ + "ms-iot.vscode-ros", + "ms-python.black-formatter", + "ms-python.vscode-pylance", + "ms-python.python", + "ms-python.debugpy", + "xaver.clang-format", + "eamodio.gitlens", + "twxs.cmake", + "ClemensPeters.format-json", + "DavidAnson.vscode-markdownlint", + "redhat.vscode-xml", + "redhat.vscode-yaml", + "mechatroner.rainbow-csv", + "llvm-vs-code-extensions.vscode-clangd" + ], + "settings": { + "terminal.integrated.defaultProfile.linux": "bash", + "terminal.integrated.env.linux": { + "CMAKE_PREFIX_PATH": "/opt/ros/noetic:$CMAKE_PREFIX_PATH", + "LD_LIBRARY_PATH": "/opt/ros/noetic/lib:$LD_LIBRARY_PATH" + }, + "search.exclude": { + "**/build": true, + "**/install": true, + "**/log": true + }, + "ros.rosSetupScript": "/opt/ros/noetic/setup.bash", + "python.autoComplete.extraPaths": [ + "/opt/ros/noetic/lib/python3/dist-packages/" + ], + "python.analysis.extraPaths": [ + "/opt/ros/noetic/lib/python3/dist-packages/" + ], + "clangd.path": "/usr/bin/clangd", + "clangd.checkUpdates": false, + "C_Cpp.clang_format_style": "file", + "C_Cpp.default.cppStandard": "c++17", + "C_Cpp.default.cStandard": "c11", + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", + "C_Cpp.default.browse.path": [ + "${workspaceFolder}" + ], + "C_Cpp.autocomplete": "disabled", + "C_Cpp.intelliSenseEngine": "disabled", + "C_Cpp.errorSquiggles": "disabled", + "C_Cpp.formatting": "disabled", + "C_Cpp.intelliSenseEngineFallback": "disabled", + "C_Cpp.configurationWarnings": "disabled", + "C_Cpp.vcpkg.enabled": false, + "C_Cpp.inlayHints.parameterNames.enabled": false, + "C_Cpp.autoAddFileAssociations": false, + "C_Cpp.codeAnalysis.runAutomatically": false, + "C_Cpp.default.enableConfigurationSquiggles": false, + "[c]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "xaver.clang-format" + }, + "[cpp]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "xaver.clang-format" + }, + "[python]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "ms-python.black-formatter" + }, + "[yaml]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "redhat.vscode-yaml" + }, + "[json]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "ClemensPeters.format-json" + }, + "[xml]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "redhat.vscode-xml" + }, + "files.trimTrailingWhitespace": true, + "files.insertFinalNewline": true, + "terminal.integrated.scrollback": 10000 + } + } + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0ca5ebc --- /dev/null +++ b/.gitignore @@ -0,0 +1,99 @@ +# Core dumps +core +core.* + +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Build directories +build/ +Build/ +bin/ +Bin/ +lib/ +Lib/ +lib64/ +Lib64/ +CMakeFiles/ +CMakeCache.txt +cmake_install.cmake +Makefile +*.cmake +*.ninja +.ninja_deps +.ninja_log +*.vcxproj +*.vcxproj.filters +*.vcxproj.user +*.DS_Store +*.ipynb_checkpoints + +# Python build artifacts +*.pyc +*.pyo +*.pyd +__pycache__/ +*.egg-info/ +dist/ +build/ +*.log + +# Clang-format index +.cache + +# ROS +.catkin_tools/ +devel/ +logs/ +install/ +*.launch~ +*.pyc + +# Ignore files generated by IDEs and editors +.vscode/ +.idea/ +*.swp +*.bak +*~ +*.tmp +*.temp +*.log +*.log.* + +# Ignore test results +test-output/ +test-results/ + +# Ignore dependency directories +node_modules/ +vendor/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8a787ae --- /dev/null +++ b/Dockerfile @@ -0,0 +1,68 @@ +# Use an official ROS1 environment as a parent image +FROM ros:noetic-robot + +# Set the default shell to bash +SHELL ["/bin/bash", "-c"] + +# Set a non-interactive shell to avoid stuck prompts during build +ARG DEBIAN_FRONTEND=noninteractive + +# Update package lists and install only necessary packages +RUN apt-get update && apt-get install -y \ + build-essential \ + cmake \ + git \ + sudo \ + lsb-release \ + gnupg2 \ + net-tools \ + clang-format \ + clangd \ + gdb \ + libpcl-dev \ + libopencv-dev \ + python3-pip \ + python3-catkin-tools \ + python3-rospkg \ + python3-rospy \ + ros-noetic-tf2-ros \ + ros-noetic-sensor-msgs \ + ros-noetic-catkin \ + ros-noetic-pcl-ros \ + ros-noetic-grid-map \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Set Python 3 as the default Python version +RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 1 + +# Copy requirements.txt and install Python packages using pip +COPY requirements.txt /tmp/requirements.txt +RUN pip3 install -r /tmp/requirements.txt + +# Add a user for the development environment +ARG USERNAME=devuser +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +# Create user with specified home directory +RUN groupadd --gid $USER_GID $USERNAME \ + && useradd --uid $USER_UID --gid $USER_GID --create-home --home-dir /home/$USERNAME $USERNAME \ + && echo "$USERNAME ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME + +# Ensure .bashrc exists and source it in the entrypoint script +RUN touch /home/$USERNAME/.bashrc + +# Set the working directory and change ownership +WORKDIR /home/$USERNAME/workspace +RUN chown -R $USERNAME:$USERNAME /home/$USERNAME/workspace + +# Setup ROS1 environment in the bashrc for interactive bash shells +RUN echo "source /opt/ros/noetic/setup.bash" >> /home/$USERNAME/.bashrc + +# Switch to the non-root user +USER $USERNAME + +# Command to run on container start +CMD ["/bin/bash"] diff --git a/README.md b/README.md index ba8ea78..1fb4488 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,13 @@ # Source code for the article "GroundGrid: LiDAR Point Cloud Ground Segmentation and Terrain Estimation" + This repository contains the source code for the article "GroundGrid: LiDAR Point Cloud Ground Segmentation and Terrain Estimation" published in the IEEE Robotics and Automation Letters ([DOI: 10.1109/LRA.2023.3333233](https://doi.org/10.1109/lra.2023.3333233)). +

Ground segmentation results

-# Dependencies +## Dependencies + - ROS Noetic Ninjemys - catkin - roscpp @@ -26,14 +29,50 @@ This repository contains the source code for the article "GroundGrid: LiDAR Poin - cv_bridge - pcl_ros -# Build +## Development Container + +To be able to use Nvidia GPU graphics within Docker follow container toolkit installation steps . + +Build Docker image: + +```bash +docker build -t groundgrid:latest . +``` + +Run Docker container: + +```bash +docker run --net host --privileged --env="DISPLAY=$DISPLAY" --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" -v "${HOME}/workspace:/home/devuser/workspace" -it groundgrid:latest /bin/bash +``` + +## Build + +Install required dependencies + +```bash +pip3 install -r requirements.txt ``` + +Build: + +```bash +cd /home/devuser/workspace/groundgrid/src +ln -s .. groundgrid catkin build -DCMAKE_BUILD_TYPE=Release groundgrid ``` -# Launch -## Playback +## Clean + +```bash +catkin clean ``` + +## Launch + +### Playback + +```bash +source devel/setup.bash roslaunch groundgrid KITTIPlayback.launch directory:=/path/to/the/SemanticKITTI/dataset sequence:=0 ``` @@ -42,14 +81,15 @@ The launch file opens a RViz window which displays the segmentation results: SemanticKitti playback Rviz window

- ## Ground Segmentation Evaluation -``` + +```bash roslaunch groundgrid KITTIEvaluate.launch directory:=/path/to/the/SemanticKITTI/dataset sequence:=0 ``` This launch file evaluates the ground segmentation performance of GroundGrid and displays the results every 500 processed clouds. The final results are displayed upon receiving Ctrl+C in the terminal: + ``` Stats Received 4540 point clouds. KITTI sequence 00. @@ -90,4 +130,3 @@ F1 97.35% 8607231 2761917 Accuracy 97.24% 400339747 411708895 IoUg 94.84% ``` - diff --git a/requirements.txt b/requirements.txt index 8887eb2..22a8b6c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,12 +1,9 @@ +cmake-format imageio>=2.19.2 rospkg>=1.4.0 numpy>=1.22.3 pandas>=1.4.1 pyntcloud>=0.3.0 -rospy>=1.15.14 -sensor_msgs>=1.13.1 -tf2_ros>=0.7.5 xmltodict>=0.13.0 pyyaml>=6.0 glfw==2.5.3 -tf>=1.13.2 diff --git a/src/groundgrid b/src/groundgrid new file mode 120000 index 0000000..a96aa0e --- /dev/null +++ b/src/groundgrid @@ -0,0 +1 @@ +.. \ No newline at end of file