| #!/bin/bash |
|
|
| |
| |
| |
| |
| |
|
|
| cd "$(dirname "$0")" |
|
|
| |
| BUILD_CUDAGL=false |
| FORCE_REBUILD=false |
|
|
| for arg in "$@"; do |
| case $arg in |
| --rebuild|-r) |
| FORCE_REBUILD=true |
| shift |
| ;; |
| --with-opengl|-gl) |
| BUILD_CUDAGL=true |
| shift |
| ;; |
| --help|-h) |
| echo "G1 Deploy Docker Environment Launcher" |
| echo "" |
| echo "Usage: ./run-ros2-dev.sh [OPTIONS]" |
| echo "" |
| echo "Options:" |
| echo " --rebuild, -r Force rebuild of Docker image" |
| echo " --with-opengl, -gl Build custom CUDA+OpenGL base image (for visualization/GUI)" |
| echo " Takes ~30 minutes first time, needs ~5GB download" |
| echo " --help, -h Show this help message" |
| echo "" |
| echo "Examples:" |
| echo " ./run-ros2-dev.sh # Quick start with standard CUDA" |
| echo " ./run-ros2-dev.sh --with-opengl # Include OpenGL for RViz/Gazebo" |
| echo " ./run-ros2-dev.sh --rebuild # Force rebuild" |
| exit 0 |
| ;; |
| esac |
| done |
|
|
| echo "π G1 Deploy - Smart ROS2 Development Environment" |
| echo "=================================================" |
| echo "ποΈ Host Architecture: $(uname -m)" |
| if [ "$BUILD_CUDAGL" = true ]; then |
| echo "π¨ Mode: CUDA + OpenGL (for visualization/rendering)" |
| else |
| echo "β‘ Mode: Standard CUDA (fast, for inference/control)" |
| fi |
|
|
| |
| if command -v nvidia-smi &> /dev/null; then |
| HOST_DRIVER=$(nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -n1) |
| HOST_CUDA=$(nvidia-smi | grep "CUDA Version:" | sed 's/.*CUDA Version: \([0-9]\+\.[0-9]\+\).*/\1/' | head -n1) |
| if [ -n "$HOST_CUDA" ]; then |
| echo "π Host NVIDIA Driver: $HOST_DRIVER (CUDA $HOST_CUDA)" |
| fi |
| fi |
|
|
| |
| SYSTEM_TYPE="generic" |
| IS_JETSON=false |
| JETSON_MODEL="" |
| DOCKERFILE="Dockerfile.ros2" |
| IMAGE_NAME="g1-deploy-dev" |
| CUDA_VERSION="12.4.1" |
|
|
| |
| if [[ "$(uname -m)" == "aarch64" ]]; then |
| |
| if [[ -f "/etc/nv_tegra_release" ]] || \ |
| [[ -d "/usr/src/jetson_multimedia_api" ]] || \ |
| ls /etc/apt/sources.list.d/ 2>/dev/null | grep -q jetson || \ |
| [[ -f "/proc/device-tree/model" && $(cat /proc/device-tree/model 2>/dev/null) =~ "Jetson" ]]; then |
| IS_JETSON=true |
| SYSTEM_TYPE="jetson" |
| |
| |
| |
| CUDA_VERSION="12.4.1" |
| |
| |
| if [[ -f "/proc/device-tree/model" ]]; then |
| JETSON_MODEL=$(cat /proc/device-tree/model 2>/dev/null | tr -d '\0' | sed 's/NVIDIA //') |
| echo "π€ Detected Jetson: $JETSON_MODEL" |
| else |
| echo "π€ Detected Jetson System" |
| fi |
| |
| |
| if command -v jetson_release &> /dev/null; then |
| JETPACK_VERSION=$(jetson_release -v 2>/dev/null | grep "JETPACK" | cut -d' ' -f2 || echo "unknown") |
| echo "π¦ JetPack Version: $JETPACK_VERSION" |
| fi |
| fi |
| fi |
|
|
| |
| case "$SYSTEM_TYPE" in |
| jetson) |
| echo "β
Jetson system detected - using CUDA ${CUDA_VERSION}" |
| if [ -n "$HOST_CUDA" ]; then |
| echo "βΉοΈ Host CUDA: $HOST_CUDA, Container CUDA: ${CUDA_VERSION}" |
| fi |
| echo "β
Unified Dockerfile with Jetson auto-detection" |
| echo "β
Deep Learning Accelerator (DLA) support enabled" |
| echo "β
TensorRT integration via host mount" |
| ;; |
| *) |
| echo "β
Unified multi-architecture support" |
| echo "β
Container CUDA version: ${CUDA_VERSION}" |
| |
| |
| if [ -n "$HOST_CUDA" ]; then |
| CUDA_MAJOR_HOST=$(echo "$HOST_CUDA" | cut -d. -f1) |
| CUDA_MAJOR_CONTAINER=$(echo "$CUDA_VERSION" | cut -d. -f1) |
| |
| if [ "$CUDA_MAJOR_CONTAINER" -gt "$CUDA_MAJOR_HOST" ]; then |
| echo "" |
| echo "β οΈ WARNING: Container CUDA ($CUDA_VERSION) > Host CUDA ($HOST_CUDA)" |
| echo " This may not work! Your driver might be too old." |
| echo " Recommended: Update NVIDIA driver to support CUDA $CUDA_VERSION" |
| echo "" |
| elif [ "$CUDA_VERSION" != "$HOST_CUDA" ]; then |
| echo "βΉοΈ Note: Container CUDA ($CUDA_VERSION) differs from host ($HOST_CUDA)" |
| echo " This is OK if your driver supports CUDA $CUDA_VERSION" |
| fi |
| fi |
| |
| case $(uname -m) in |
| x86_64) |
| echo "β
Full x86_64 support with CUDA and TensorRT" |
| ;; |
| aarch64) |
| echo "β
ARM64 support (non-Jetson)" |
| echo "β
CUDA support from official NVIDIA images" |
| ;; |
| *) |
| echo "β οΈ Architecture $(uname -m) - experimental support" |
| ;; |
| esac |
| ;; |
| esac |
| echo "" |
|
|
| |
| CUDA_BASE_IMAGE="nvidia/cuda" |
| if [ "$BUILD_CUDAGL" = true ]; then |
| echo "π¨ Building custom CUDA+OpenGL base image..." |
| echo " This is a one-time process (takes ~30 minutes)" |
| echo "" |
| |
| CUDAGL_IMAGE="g1-cuda-gl" |
| CUDAGL_TAG="${CUDA_VERSION}-devel-ubuntu22.04" |
| |
| |
| if docker image inspect "${CUDAGL_IMAGE}:${CUDAGL_TAG}" >/dev/null 2>&1 && [ "$FORCE_REBUILD" != true ]; then |
| echo "β
Custom CUDA+GL image already exists: ${CUDAGL_IMAGE}:${CUDAGL_TAG}" |
| else |
| |
| if [ ! -d "nvidia-cuda-build" ]; then |
| echo "π₯ Cloning NVIDIA CUDA repository (one-time, ~2GB)..." |
| git clone --depth 1 https://gitlab.com/nvidia/container-images/cuda.git nvidia-cuda-build |
| fi |
| |
| cd nvidia-cuda-build |
| |
| |
| BUILD_ARCH=$(uname -m) |
| if [ "$BUILD_ARCH" = "x86_64" ]; then |
| BUILD_ARCH_FLAG="x86_64" |
| elif [ "$BUILD_ARCH" = "aarch64" ]; then |
| BUILD_ARCH_FLAG="arm64" |
| else |
| echo "β οΈ Unknown architecture: $BUILD_ARCH, using x86_64" |
| BUILD_ARCH_FLAG="x86_64" |
| fi |
| |
| echo "π¨ Building CUDA ${CUDA_VERSION} + OpenGL for ${BUILD_ARCH_FLAG}..." |
| echo " This takes 20-30 minutes on first build..." |
| |
| |
| ./build.sh -d \ |
| --image-name "${CUDAGL_IMAGE}" \ |
| --cuda-version "${CUDA_VERSION}" \ |
| --os ubuntu \ |
| --os-version 22.04 \ |
| --arch "${BUILD_ARCH_FLAG}" \ |
| --cudagl |
| |
| if [ $? -eq 0 ]; then |
| echo "β
Custom CUDA+GL base image built successfully!" |
| else |
| echo "β Failed to build custom CUDA+GL image" |
| echo " Falling back to standard CUDA image" |
| BUILD_CUDAGL=false |
| fi |
| |
| cd .. |
| fi |
| |
| if [ "$BUILD_CUDAGL" = true ]; then |
| CUDA_BASE_IMAGE="${CUDAGL_IMAGE}" |
| echo "β
Will use custom CUDA+GL image: ${CUDA_BASE_IMAGE}:${CUDAGL_TAG}" |
| fi |
| |
| echo "" |
| fi |
|
|
| |
| docker rm -f g1-deploy-dev g1-ros2-dev g1-jetson-dev 2>/dev/null || true |
|
|
| |
| BUILD_IMAGE=false |
| if ! docker image inspect "$IMAGE_NAME" >/dev/null 2>&1; then |
| echo "π¦ Image $IMAGE_NAME not found - building..." |
| BUILD_IMAGE=true |
| elif [ "$FORCE_REBUILD" = true ]; then |
| echo "π¦ Forced rebuild requested..." |
| BUILD_IMAGE=true |
| else |
| echo "β
Using existing Docker image: $IMAGE_NAME" |
| echo " (Use --rebuild or -r to force rebuild)" |
| fi |
|
|
| if [ "$BUILD_IMAGE" = true ]; then |
| echo "π¦ Building Docker image: $IMAGE_NAME" |
| echo " Dockerfile: $DOCKERFILE (unified for all platforms)" |
| echo " CUDA Version: $CUDA_VERSION" |
| echo " Base Image: $CUDA_BASE_IMAGE" |
| echo " System Type: $SYSTEM_TYPE" |
| |
| |
| |
| |
| docker build --network host -f "$DOCKERFILE" -t "$IMAGE_NAME" .. \ |
| --build-arg CUDA_VERSION=$CUDA_VERSION \ |
| --build-arg CUDA_BASE_IMAGE=$CUDA_BASE_IMAGE |
| fi |
|
|
| |
| TENSORRT_MOUNT="" |
| ADDITIONAL_MOUNTS="" |
| DEVICE_MOUNTS="" |
|
|
| if [[ "$SYSTEM_TYPE" == "jetson" ]] && [ -f "/usr/lib/aarch64-linux-gnu/libnvinfer.so" ]; then |
| |
| |
| |
| TENSORRT_STAGING="/tmp/tensorrt-stage-$$" |
| rm -rf "$TENSORRT_STAGING" |
| mkdir -p "$TENSORRT_STAGING/lib" "$TENSORRT_STAGING/include" |
|
|
| |
| for pattern in libnvinfer libnvinfer_plugin libnvinfer_builder_resource \ |
| libnvinfer_dispatch libnvinfer_lean libnvinfer_vc_plugin \ |
| libnvonnxparser; do |
| for f in /usr/lib/aarch64-linux-gnu/${pattern}.so*; do |
| [ -f "$f" ] || continue |
| base=$(basename "$f") |
| if [ -L "$f" ]; then |
| |
| target=$(basename "$(readlink "$f")") |
| ln -sf "$target" "$TENSORRT_STAGING/lib/$base" |
| else |
| |
| ln "$f" "$TENSORRT_STAGING/lib/$base" 2>/dev/null || cp "$f" "$TENSORRT_STAGING/lib/$base" |
| fi |
| done |
| done |
|
|
| |
| TENSORRT_INCLUDE_DIR="/usr/include/aarch64-linux-gnu" |
| [ -f "$TENSORRT_INCLUDE_DIR/NvInfer.h" ] || TENSORRT_INCLUDE_DIR="/usr/include" |
| for hdr in "$TENSORRT_INCLUDE_DIR"/Nv*.h; do |
| [ -f "$hdr" ] && ln "$hdr" "$TENSORRT_STAGING/include/" 2>/dev/null || cp "$hdr" "$TENSORRT_STAGING/include/" |
| done |
|
|
| echo "β
Using system TensorRT from JetPack (staged to $TENSORRT_STAGING)" |
| TENSORRT_MOUNT="-v $TENSORRT_STAGING:/opt/TensorRT:ro" |
| elif [ -n "$TensorRT_ROOT" ] && [ -d "$TensorRT_ROOT" ]; then |
| echo "β
TensorRT found: $TensorRT_ROOT (mounting to container)" |
| TENSORRT_MOUNT="-v $TensorRT_ROOT:/opt/TensorRT:ro" |
| else |
| echo "β οΈ TensorRT not found - Set \$TensorRT_ROOT environment variable for GPU inference" |
| echo " Example: export TensorRT_ROOT=/path/to/TensorRT" |
| fi |
|
|
| if [[ "$SYSTEM_TYPE" == "jetson" ]]; then |
| |
| if [ -n "$TENSORRT_MOUNT" ]; then |
| |
| |
| |
| |
| |
| |
| |
| : |
|
|
| |
| |
| HOST_CUDA_TOOLKIT="" |
| if [ -d "/usr/local/cuda/targets/aarch64-linux/lib" ]; then |
| HOST_CUDA_TOOLKIT="/usr/local/cuda" |
| else |
| |
| for cuda_dir in $(ls -d /usr/local/cuda-[0-9]* 2>/dev/null | sort -V -r); do |
| if [ -d "$cuda_dir/targets/aarch64-linux/lib" ]; then |
| HOST_CUDA_TOOLKIT="$cuda_dir" |
| break |
| fi |
| done |
| fi |
|
|
| if [ -n "$HOST_CUDA_TOOLKIT" ]; then |
| echo "β
Host CUDA toolkit found: $HOST_CUDA_TOOLKIT (mounting to container)" |
| ADDITIONAL_MOUNTS="$ADDITIONAL_MOUNTS -v $HOST_CUDA_TOOLKIT:$HOST_CUDA_TOOLKIT:ro" |
| else |
| echo "β οΈ Host CUDA toolkit not found under /usr/local/cuda-*/targets/aarch64-linux/lib" |
| echo " If DLA (cudla) linking fails, install JetPack dev components on host" |
| fi |
| |
| |
| if [ -f "/etc/nv_tegra_release" ]; then |
| ADDITIONAL_MOUNTS="$ADDITIONAL_MOUNTS -v /etc/nv_tegra_release:/etc/nv_tegra_release:ro" |
| fi |
| |
| |
| DEVICE_MOUNTS="" |
| JETSON_DEVICES=( |
| "/dev/nvidia0" |
| "/dev/nvidiactl" |
| "/dev/nvidia-modeset" |
| "/dev/nvhost-ctrl" |
| "/dev/nvhost-ctrl-gpu" |
| "/dev/nvhost-prof-gpu" |
| "/dev/nvmap" |
| "/dev/nvhost-gpu" |
| "/dev/nvhost-as-gpu" |
| "/dev/nvhost-vic" |
| "/dev/tegra-crypto" |
| ) |
| |
| for device in "${JETSON_DEVICES[@]}"; do |
| if [ -e "$device" ]; then |
| DEVICE_MOUNTS="$DEVICE_MOUNTS --device $device:$device" |
| fi |
| done |
| |
| if [ -z "$DEVICE_MOUNTS" ]; then |
| echo "β οΈ Warning: No Jetson GPU devices found in /dev/" |
| fi |
| |
| |
| if ls /usr/lib/aarch64-linux-gnu/libcudnn* >/dev/null 2>&1; then |
| echo "β
cuDNN libraries found on host" |
| fi |
| fi |
| |
| |
| if [ -f "/usr/lib/aarch64-linux-gnu/nvidia/libnvcudla.so" ]; then |
| echo "β
Deep Learning Accelerator (DLA) libraries available" |
| else |
| echo "β οΈ DLA libraries not found - will run without DLA acceleration" |
| fi |
| fi |
|
|
| |
| if [ -f "../src/g1/g1_deploy_onnx_ref/config/fastrtps_profile.xml" ]; then |
| echo "β
FastRTPS production profile ready" |
| else |
| echo "β οΈ FastRTPS profile missing - using defaults" |
| fi |
|
|
| echo "" |
| echo "π³ Launching $SYSTEM_TYPE-optimized container..." |
|
|
| |
| GPU_SETTINGS="" |
| if docker info 2>/dev/null | grep -q "Runtimes.*nvidia"; then |
| |
| if [[ "$SYSTEM_TYPE" == "jetson" ]]; then |
| GPU_SETTINGS="--runtime nvidia --gpus all" |
| else |
| GPU_SETTINGS="--gpus all" |
| fi |
| else |
| |
| if command -v nvidia-smi &> /dev/null; then |
| echo "βΉοΈ Using --gpus all (nvidia runtime not configured)" |
| GPU_SETTINGS="--gpus all" |
| else |
| echo "β οΈ Warning: No NVIDIA GPU support detected" |
| GPU_SETTINGS="" |
| fi |
| fi |
|
|
| |
| docker run -it --rm \ |
| --name "$IMAGE_NAME" \ |
| --network host \ |
| --ipc host \ |
| $GPU_SETTINGS \ |
| -v "$(cd .. && pwd):/workspace/g1_deploy:rw" \ |
| -v "$(cd ../.. && pwd)/gear_sonic:/workspace/gear_sonic:rw" \ |
| $TENSORRT_MOUNT \ |
| $ADDITIONAL_MOUNTS \ |
| $DEVICE_MOUNTS \ |
| -e RMW_IMPLEMENTATION=rmw_fastrtps_cpp \ |
| -e ROS_DOMAIN_ID=0 \ |
| -e NVIDIA_VISIBLE_DEVICES=all \ |
| -e NVIDIA_DRIVER_CAPABILITIES=all \ |
| -e SYSTEM_TYPE="$SYSTEM_TYPE" \ |
| -e IS_JETSON="$IS_JETSON" \ |
| -e JETSON_MODEL="$JETSON_MODEL" \ |
| -w /workspace/g1_deploy \ |
| "$IMAGE_NAME" \ |
| bash -c " |
| echo '' |
| if [[ \"\$SYSTEM_TYPE\" == \"jetson\" ]]; then |
| echo 'π€ G1 Deploy Jetson Development Environment' |
| echo '============================================' |
| echo 'π¦ Jetson CUDA + DLA Integration' |
| |
| # Match bare-metal builds: if a host CUDA toolkit is mounted, prefer it. |
| # Choose /usr/local/cuda if it has targets/aarch64-linux; otherwise pick newest cuda-*. |
| if [ -d '/usr/local/cuda/targets/aarch64-linux/lib' ]; then |
| export CUDAToolkit_ROOT='/usr/local/cuda' |
| export CUDA_HOME='/usr/local/cuda' |
| else |
| BEST_CUDA=\$(ls -d /usr/local/cuda-[0-9]* 2>/dev/null | sort -V -r | head -n1) |
| if [ -n \"\$BEST_CUDA\" ] && [ -d \"\$BEST_CUDA/targets/aarch64-linux/lib\" ]; then |
| export CUDAToolkit_ROOT=\"\$BEST_CUDA\" |
| export CUDA_HOME=\"\$BEST_CUDA\" |
| fi |
| fi |
| |
| # Ensure NVIDIA library path is in linker configuration for DLA |
| if [ -d '/usr/lib/aarch64-linux-gnu/nvidia' ]; then |
| echo '/usr/lib/aarch64-linux-gnu/nvidia' > /etc/ld.so.conf.d/nvidia.conf |
| ldconfig |
| echo 'β
NVIDIA DLA libraries configured' |
| fi |
| else |
| echo 'π― G1 Deploy ROS2 Development Environment' |
| echo '=========================================' |
| echo 'π¦ NVIDIA CUDA Multi-Architecture' |
| fi |
| echo '' |
| |
| # Fix Git ownership issue for mounted directory |
| git config --global --add safe.directory /workspace/g1_deploy |
| |
| # Set up environment using the project's setup script |
| # This ensures consistency between Docker and bare-metal installations |
| if [ -f 'scripts/setup_env.sh' ]; then |
| echo 'π§ Running setup_env.sh for environment configuration...' |
| source scripts/setup_env.sh |
| else |
| # Fallback if setup script not found |
| echo 'β οΈ setup_env.sh not found, using basic environment' |
| source /opt/ros/humble/setup.bash |
| export RMW_IMPLEMENTATION=rmw_fastrtps_cpp |
| export LD_LIBRARY_PATH='/opt/onnxruntime/lib:\$LD_LIBRARY_PATH' |
| fi |
| |
| # Status check |
| echo 'π Environment Status:' |
| if [[ \"\$SYSTEM_TYPE\" == \"jetson\" ]]; then |
| echo \" π€ System: Jetson \$JETSON_MODEL\" |
| fi |
| echo \" ποΈ Architecture: $(uname -m)\" |
| command -v just >/dev/null && echo ' β
Just command runner' || echo ' β Just not found' |
| command -v cmake >/dev/null && echo ' β
CMake build system' || echo ' β CMake not found' |
| echo \" β
ROS2 Humble ($(ros2 --version 2>/dev/null || echo 'version unknown'))\" |
| echo ' β
ONNX Runtime 1.16.3' |
| command -v nvcc >/dev/null 2>&1 && echo \" β
CUDA \$(nvcc --version | grep release | cut -d' ' -f5 | cut -d',' -f1 2>/dev/null || echo 'Toolkit')\" || echo ' β οΈ CUDA Toolkit not found' |
| |
| # Check TensorRT (unified location for all platforms) |
| ls /opt/TensorRT >/dev/null 2>&1 && echo ' β
TensorRT (mounted from host)' || echo ' β οΈ TensorRT not mounted - set \$TensorRT_ROOT on host' |
| |
| # Jetson-specific checks |
| if [[ \"\$SYSTEM_TYPE\" == \"jetson\" ]]; then |
| [ -f '/usr/lib/aarch64-linux-gnu/nvidia/libnvcudla.so' ] && echo ' β
Deep Learning Accelerator (DLA) ready' || echo ' β οΈ DLA libraries not found' |
| nvidia-smi 2>/dev/null | grep -q 'GPU' && echo ' β
GPU acceleration available' || echo ' β οΈ GPU not detected (check device mounts)' |
| fi |
| |
| echo '' |
| echo 'π οΈ Quick Commands:' |
| if [[ \"\$SYSTEM_TYPE\" == \"jetson\" ]]; then |
| echo ' just build # Build with ARM64 + DLA optimizations' |
| echo ' just test-ros2 # Test ROS2 integration on Jetson' |
| echo ' just run freq_test model.onnx # Test inference with DLA' |
| else |
| echo ' just build # Build with ROS2 support' |
| echo ' just test-ros2 # Test ROS2 integration' |
| fi |
| echo ' just --list # Show all commands' |
| echo '' |
| echo 'Ready for development! π' |
| echo '' |
| |
| exec bash |
| " |
|
|