diff --git a/.devcontainer/.env b/.devcontainer/.env deleted file mode 100644 index 4feacc6..0000000 --- a/.devcontainer/.env +++ /dev/null @@ -1,4 +0,0 @@ -USER=eddy -USER_UID=1000 -USER_GID=1000 -ROS_DISTRO=humble diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index ca2d95c..3c51393 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,6 +1,41 @@ -# Multi-version ROS2 development container +# Multi-stage ROS2 development container (CPU/GPU compatible) ARG ROS_DISTRO=humble -FROM ros:${ROS_DISTRO}-ros-base +ARG CUDA_VERSION=12.4.0 +ARG UBUNTU_VERSION=22.04 + +# =============================================== +# CPU Base - Standard ROS2 image +# =============================================== +FROM ros:${ROS_DISTRO}-ros-base as cpu-base + +# =============================================== +# GPU Base - CUDA with manual ROS2 install +# =============================================== +FROM nvidia/cuda:${CUDA_VERSION}-runtime-ubuntu${UBUNTU_VERSION} as gpu-base +ARG ROS_DISTRO + +# Install ROS2 manually since we're not using the ros: base image +# Set non-interactive to avoid geographic area prompts +ENV DEBIAN_FRONTEND=noninteractive +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN apt-get update && apt-get install -y --no-install-recommends \ + curl \ + gnupg2 \ + lsb-release \ + tzdata \ + && ln -fs /usr/share/zoneinfo/Etc/UTC /etc/localtime \ + && dpkg-reconfigure --frontend noninteractive tzdata \ + && curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo "$UBUNTU_CODENAME") main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null \ + && apt-get update && apt-get install -y --no-install-recommends \ + ros-${ROS_DISTRO}-ros-base \ + && rm -rf /var/lib/apt/lists/* +ENV DEBIAN_FRONTEND=interactive + +# =============================================== +# Install Common Development Tools from Either Base +# =============================================== +FROM ${TARGETARCH:-cpu}-base as dev-tools # Install development tools not in base image RUN apt-get update && apt-get install -y --no-install-recommends \ @@ -8,6 +43,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python3-colcon-common-extensions \ python3-rosdep \ openssh-client \ + git \ curl \ && rm -rf /var/lib/apt/lists/* @@ -21,7 +57,8 @@ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ rm -rf /var/lib/apt/lists/* # Install Claude Code CLI via npm -RUN npm install -g @anthropic-ai/claude-code@1.0.0 +# hadolint ignore=DL3016 +RUN npm install -g @anthropic-ai/claude-code # Initialize rosdep RUN rosdep init || true @@ -29,9 +66,14 @@ RUN rosdep init || true # Set working dir (matches VSCode workspace) WORKDIR /deep_ros_ws -# Cater image to user +# =============================================== +# Add User Configuration +# =============================================== +FROM dev-tools as user-conf ARG USERNAME +ARG ROS_DISTRO +# Cater image to user SHELL ["/bin/bash", "-c"] COPY .env /tmp/.env # hadolint ignore=SC2086 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index aca1cee..0000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "deep_ros-dev", - "build": { - "dockerfile": "Dockerfile", - "args": { - "ROS_DISTRO": "${localEnv:ROS_DISTRO:humble}", - "USERNAME": "${localEnv:USER}" - } - }, - "containerEnv": { - "ROS_DISTRO": "${localEnv:ROS_DISTRO:humble}", - "SSH_AUTH_SOCK": "/ssh-agent" - }, - "mounts": [ - "source=${localEnv:SSH_AUTH_SOCK},target=/ssh-agent,type=bind", - ], - "customizations": { - "vscode": { - "extensions": [ - "ms-vscode.cpptools", - "ms-vscode.cmake-tools", - "ms-python.python", - "redhat.vscode-xml", - "anthropics.claude-for-vscode" - ] - } - }, - "workspaceFolder": "/deep_ros_ws", - "workspaceMount": "source=${localWorkspaceFolder},target=/deep_ros_ws,type=bind", - "containerName": "deep-ros-devcontainer", - "runArgs": [ - "--hostname=deep-devcontainer" - ] -} diff --git a/.devcontainer/gen_env.sh b/.devcontainer/gen_env.sh deleted file mode 100755 index 3cfa03c..0000000 --- a/.devcontainer/gen_env.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2025-present WATonomous. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -set -e - -# Check if ROS_DISTRO was provided as argument -if [ $# -eq 0 ]; then - echo "Usage: $0 " - exit 1 -fi - -ROS_DISTRO="$1" -ENV_FILE=".devcontainer/.env" - -echo "Generating $ENV_FILE ..." -{ - echo "USER=$(whoami)" - echo "USER_UID=$(id -u)" - echo "USER_GID=$(id -g)" - echo "ROS_DISTRO=$ROS_DISTRO" -} >> "$ENV_FILE" - -echo "Done. Contents:" -cat "$ENV_FILE" diff --git a/.devcontainer/generate_devcontainer.sh b/.devcontainer/generate_devcontainer.sh new file mode 100755 index 0000000..8920232 --- /dev/null +++ b/.devcontainer/generate_devcontainer.sh @@ -0,0 +1,102 @@ +#!/bin/bash + +# Copyright (c) 2025-present WATonomous. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# generate_devcontainer.sh +# Usage: +# ./generate_devcontainer.sh [cuda_version] [ubuntu_version] + +set -e + +ROS_DISTRO=${1:-humble} +CONTAINER_TYPE=${2:-cpu} +CUDA_VERSION=${3:-12.4.0} +UBUNTU_VERSION=${4:-22.04} +USERNAME=${USER:-vscode} + +echo "Generating devcontainer configuration..." +echo "ROS Distribution: $ROS_DISTRO" +echo "Container Type: $CONTAINER_TYPE" + +if [ "$CONTAINER_TYPE" = "gpu" ]; then + echo "CUDA Version: $CUDA_VERSION" + echo "Ubuntu Version: $UBUNTU_VERSION" +fi + +# Generate container name and build args based on type +if [ "$CONTAINER_TYPE" = "gpu" ]; then + CONTAINER_NAME="ROS2 Development Container (GPU)" + BUILD_ARGS='"ROS_DISTRO": "'$ROS_DISTRO'", + "USERNAME": "'$USERNAME'", + "TARGETARCH": "gpu", + "CUDA_VERSION": "'$CUDA_VERSION'", + "UBUNTU_VERSION": "'$UBUNTU_VERSION'", + "USER_UID": "'$(id -u)'", + "USER_GID": "'$(id -g)'"' + RUN_ARGS='"--network=host", + "--gpus=all"' +else + CONTAINER_NAME="ROS2 Development Container (CPU)" + BUILD_ARGS='"ROS_DISTRO": "'$ROS_DISTRO'", + "USERNAME": "'$USERNAME'", + "TARGETARCH": "cpu", + "USER_UID": "'$(id -u)'", + "USER_GID": "'$(id -g)'"' + RUN_ARGS='"--network=host"' +fi + +# Generate the devcontainer.json with shared structure +cat > .devcontainer/devcontainer.json << EOF +{ + "name": "$CONTAINER_NAME", + "build": { + "dockerfile": "Dockerfile", + "args": { + $BUILD_ARGS + } + }, + "runArgs": [ + $RUN_ARGS + ], + "mounts": [ + "source=\${localWorkspaceFolder},target=/deep_ros_ws,type=bind,consistency=cached" + ], + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.cpptools", + "ms-python.python", + "ms-vscode.cmake-tools", + "redhat.vscode-yaml", + "ms-iot.vscode-ros" + ], + "settings": { + "python.defaultInterpreterPath": "/usr/bin/python3", + "terminal.integrated.shell.linux": "/bin/bash" + } + } + }, + "remoteUser": "$USERNAME" +} +EOF + +echo "Devcontainer configuration generated successfully!" +echo "Files created:" +echo " - .devcontainer/devcontainer.json" +echo "" +echo "Environment variables set for this session" +echo "" +echo "You can now:" +echo " 1. Open the command palette (Ctrl+Shift+P)" +echo " 2. Run 'Dev Containers: Rebuild and Reopen in Container'" diff --git a/.gitignore b/.gitignore index f12d9be..24d1d9e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,12 @@ -.claude/ +# ROS2 build artifacts build/ install/ log/ + +# Autogenerated devcontainer files +.devcontainer/devcontainer.json +.devcontainer/.env + +# Claude helpers +.claude/ +CLAUDE.md diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..c7a3e2b --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,30 @@ +{ + "configurations": [ + { + "name": "ROS2 Humble", + "compileCommands": "${workspaceFolder}/build/compile_commands.json", + "includePath": [ + "${workspaceFolder}/**", + "${workspaceFolder}/onnx_example_node/include/**", + "${workspaceFolder}/onnx_example_node/third_party/onnxruntime-linux-x64-1.16.3/include/**", + "${workspaceFolder}/deep_core/include/**", + "${workspaceFolder}/deep_backends/**/include/**", + "/opt/ros/humble/include/**" + ], + "defines": [], + "compilerPath": "/usr/bin/g++", + "cStandard": "c99", + "cppStandard": "c++17", + "intelliSenseMode": "linux-gcc-x64", + "browse": { + "path": [ + "${workspaceFolder}", + "/opt/ros/humble/include" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "${workspaceFolder}/.vscode/browse.vc.db" + } + } + ], + "version": 4 +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9affefe --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,84 @@ +{ + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", + "C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json", + "C_Cpp.intelliSenseEngine": "default", + "C_Cpp.errorSquiggles": "enabled", + "C_Cpp.autocomplete": "default", + "files.associations": { + "*.hpp": "cpp", + "*.h": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "array": "cpp", + "atomic": "cpp", + "strstream": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "chrono": "cpp", + "compare": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdint": "cpp", + "deque": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "semaphore": "cpp", + "shared_mutex": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "variant": "cpp" + }, + "cmake.configureOnOpen": false, + "cmake.buildDirectory": "${workspaceFolder}/build", + "ros.distro": "humble" +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 61fed9c..d256d03 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,11 +2,44 @@ "version": "2.0.0", "tasks": [ { - "label": "Setup Devcontainer", + "label": "Setup Devcontainer (CPU Only)", "type": "shell", - "command": "./.devcontainer/gen_env.sh ${input:rosDistro}", + "command": "./.devcontainer/generate_devcontainer.sh", + "args": [ + "${input:rosDistro}", + "cpu" + ], + "problemMatcher": [], + "group": "build", + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared", + "showReuseMessage": true, + "clear": false + } + }, + { + "label": "Setup Devcontainer (GPU)", + "type": "shell", + "command": "./.devcontainer/generate_devcontainer.sh", + "args": [ + "${input:rosDistro}", + "gpu", + "${input:cudaVersion}", + "${input:ubuntuVersion}" + ], "problemMatcher": [], - "group": "build" + "group": "build", + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared", + "showReuseMessage": true, + "clear": false + } } ], "inputs": [ @@ -21,6 +54,55 @@ "rolling" ], "default": "humble" + }, + { + "id": "containerType", + "type": "pickString", + "description": "Select container type", + "options": [ + { + "label": "CPU Only", + "value": "cpu" + }, + { + "label": "GPU Enabled (NVIDIA)", + "value": "gpu" + } + ], + "default": "cpu" + }, + { + "id": "cudaVersion", + "type": "pickString", + "description": "Select CUDA version", + "options": [ + "12.6.2", + "12.4.0", + "12.2.2", + "12.1.1", + "11.8.0" + ], + "default": "12.4.0" + }, + { + "id": "ubuntuVersion", + "type": "pickString", + "description": "Select Ubuntu version", + "options": [ + { + "label": "Ubuntu 24.04 (Noble)", + "value": "24.04" + }, + { + "label": "Ubuntu 22.04 (Jammy)", + "value": "22.04" + }, + { + "label": "Ubuntu 20.04 (Focal)", + "value": "20.04" + } + ], + "default": "22.04" } ] }