diff --git a/.github/workflows/README.md b/.github/workflows/README.md
new file mode 100644
index 0000000..3386944
--- /dev/null
+++ b/.github/workflows/README.md
@@ -0,0 +1,153 @@
+# Understanding the CI/CD workflows
+
+> [!NOTE]
+> At the moment, this workflow does not build for the ARM architecture. Please build these locally until Microsoft releases the feature for private repositories. [source one](https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories), [source two](https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for--private-repositories). For now, Jetson builds done online will simply be skipped.
+
+## Desired behaviour
+1. The user creates a new branch for their changes.
+1. The user commits their changes to the branch, with a relevant tag.
+1. The user pushes the branch to the remote repository.
+1. The CI/CD system detects the new tag and starts building the image.
+1. If the build is successful, the image is pushed to the GitHub Container Registry.
+1. The user can then pull the image from the registry and use it.
+
+### Key features
+- Dependant images are built in the correct order.
+- Images are built with the correct tags.
+- The CI/CD system is triggered by tags, not pushes to branches or pull requests.
+- Upon any failure, the system will exit gracefully and not proceed with downstream dependant builds.
+
+## Overview of the main workflow
+This is a high-level understanding of the workflow described in [build.yaml](/.github/workflows/build.yaml).
+
+1. The workflow is triggered when a tag starting with `v` (or `dev`) is pushed to the repository.
+
+1. Firstly, the workflow checks out the code from the repository and looks for changes. At a time, a change may be present in a full directory only. We do not test for individual Dockerfiles because certain images depend on others, and we want to build them in the correct order.
+
+ Places tested for changes:
+ - `ROS2/AMD64x86/`: desktop images for AMD64x86 architecture
+ - `ROS2/Jetson`: edge-computing images for NVIDIA Jetson architecture (once implemented)
+ - `.github/workflows/`: GitHub Actions workflows
+
+1. Next, the workflow looks for the Git tag. If it finds a tag that starts with `v`/`dev`, records this to a variable, so that it may be used later in the workflow.
+
+1. If changes were detected, the workflow proceeds to build the images. If any GitHub Action changes were detected, everything is rebuilt; otherwise only the changed images are rebuilt.
+
+1. The remainder of the build is split into five sections, which run in three steps (some sections run in parallel):
+
+ | Step | Sections that run in parallel |
+ | --- | --- |
+ | 1 | - ROS2 base humble images (AMD64/x86)
- ROS2 base humble images (Jetson/ARM) |
+ | 2 | - ROS2 humble_harmonic (AMD64/x86) |
+ | 3 | - ROS2 wheelchair2_base images (AMD64/x86)
- ROS2 wheelchair2_base_jetson (depends on humble_jetson) |
+
+ By default, all of these sections are configured as [matrix strategies](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow). Although some sections have only one entry, this allows for easy expansion in the future.
+
+## Overview of the reusable workflow
+It quickly became evident that several steps in the workflow were repetitive, so the majority of the actual work was refactored into a [reusable workflow](https://docs.github.com/en/actions/sharing-automations/reusing-workflows). This is described in [build-workflow.yaml](/.github/workflows/build-workflow.yaml), and is briefly explained below.
+
+This workflow is triggered by the main workflow, and receives the following inputs:
+
+| Input | Description | Default |
+| --- | --- | --- |
+| `build_context` | The build context for the Dockerfile | - |
+| `image_name` | The target name of the image to build | - |
+| `image_version` | The version tag of the image to build | - |
+| `runs_on` | The GitHub runner to use for the build | `ubuntu-latest` |
+
+First, code is checked out, [buildx is setup](https://github.com/docker/setup-buildx-action/tree/v3/), and [GHCR is authenticated](https://github.com/docker/setup-buildx-action/tree/v3/).
+
+Finally, the actual image is built and (if successful) pushed to the GitHub Container Registry, using the [`docker/build-push-action`](https://github.com/docker/build-push-action/tree/v6/) action.
+
+
+## Deeper dive into the main workflow
+Here, we discuss only the potentially confusing parts of the main workflow, which is described in [build.yaml](/.github/workflows/build.yaml).
+
+You are encouraged to read the [GitHub Actions documentation](https://docs.github.com/en/actions) for more information on how GitHub Actions work, how to write workflows, and reference for syntax. If you use VS Code to write workflows, the [GitHub Actions extension](https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-github-actions) is useful.
+
+### Checking for changes
+We use the [`dorny/paths-filter`](https://github.com/dorny/paths-filter/tree/v2/) action to check for changes in the repository. This action allows us to specify paths to check for changes, and it will return a boolean value indicating whether any changes were detected.
+
+These are stored as outputs of the `changes` job:
+
+```yaml
+outputs:
+ ros2-amd64: ${{ steps.filter.outputs.ros2-amd64 }}
+ ros2-jetson: ${{ steps.filter.outputs.ros2-jetson }}
+ workflow: ${{ steps.filter.outputs.workflow }}
+ image_version: ${{ steps.set_version.outputs.image_version }}
+```
+
+As described earlier, we check for changes in the three main directories:
+
+```yaml
+- name: Check for changes
+ id: filter
+ uses: dorny/paths-filter@v2
+ with:
+ filters: |
+ ros2-amd64:
+ - 'ROS2/AMD64x86/**'
+ ros2-jetson:
+ - 'ROS2/Jetson/**'
+ workflow:
+ - '.github/workflows/**'
+```
+
+### Setting the image version
+This simply involves obtaining the Git tag and setting it as an environment variable for later use:
+
+```yaml
+- name: Set image version
+ id: set_version
+ run: |
+ echo "image_version=${{ github.ref_name }}" >> $GITHUB_OUTPUT
+```
+
+### Building the images
+While there are several sections as described earlier, we shall dive deeper into one of these as exposition. Consider the "Stage 3: ROS2 wheelchair2_base images (AMD64/x86)" section.
+
+```yaml
+# Stage 3: ROS2 wheelchair2_base images (AMD64/x86)
+ros2-wheelchair-base:
+ needs: [changes, ros2-humble-base-amd64, ros2-humble-harmonic]
+ if: ${{ needs.changes.outputs.ros2-amd64 == 'true' || needs.changes.outputs.workflow == 'true' }}
+ name: ROS2 Wheelchair2 Base Images
+ permissions:
+ packages: write
+ contents: read
+ strategy:
+ matrix:
+ config:
+ - { build_context: './ROS2/AMD64x86/wheelchair2_base', image_name: 'wheelchair2_base', image_version: "${{ needs.changes.outputs.image_version }}" }
+ - { build_context: './ROS2/AMD64x86/wheelchair2_base_gazebo', image_name: 'wheelchair2_base_gazebo', image_version: "${{ needs.changes.outputs.image_version }}" }
+ uses: ./.github/workflows/build-workflow.yaml
+ with:
+ build_context: ${{ matrix.config.build_context }}
+ image_name: ${{ matrix.config.image_name }}
+ image_version: ${{ matrix.config.image_version }}
+ runs_on: ubuntu-latest
+```
+
+Let's break this down:
+- `needs`: This job depends on the `changes` job and the `ros2-humble-base-amd64` and `ros2-humble-harmonic` jobs. It will only run if these jobs are successful. This ensures that dependant images are built in the correct order.
+- `if`: This condition checks if there are changes in the `ROS2/AMD64x86/` directory or if there are changes in the workflows. If either condition is true, this job will run.
+- `permissions`: This job requires write access to packages (to push the built images) and read access to contents (to read the repository).
+- `strategy`: This defines a matrix strategy for the job. In this case, we have two configurations:
+ - `wheelchair2_base`: The base image for the wheelchair2 project.
+ - `wheelchair2_base_gazebo`: The base image for the wheelchair2 project with Gazebo support.
+- `uses`: This specifies that the job will use the reusable workflow defined in [build-workflow.yaml](/.github/workflows/build-workflow.yaml).
+- `with`: This passes the necessary parameters to the reusable workflow, including the build context, image name, image version, and the runner to use.
+
+Note the matrix system:
+```yaml
+strategy:
+ matrix:
+ config:
+ - { build_context: './ROS2/AMD64x86/wheelchair2_base', image_name: 'wheelchair2_base', image_version: "${{ needs.changes.outputs.image_version }}" }
+ - { build_context: './ROS2/AMD64x86/wheelchair2_base_gazebo', image_name: 'wheelchair2_base_gazebo', image_version: "${{ needs.changes.outputs.image_version }}" }
+```
+
+In this system, we specify one or more configurations for the job. Each configuration corresponds to one resulting image. The reusable workflow will be run for each configuration, allowing us to build multiple images in parallel by just adding one more entry to the `config` list.
+
+Please consult the [GitHub Actions documentation](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow) for more information on matrix strategies and syntax.
\ No newline at end of file
diff --git a/.github/workflows/build-release.yaml b/.github/workflows/build-release.yaml
new file mode 100644
index 0000000..aa3de01
--- /dev/null
+++ b/.github/workflows/build-release.yaml
@@ -0,0 +1,142 @@
+name: Build Multi-Architecture ROS Containers
+
+on:
+ push:
+ tags:
+ - 'v*'
+ - 'latest'
+ branches:
+ - master
+jobs:
+ # Detect file changes
+ changes:
+ runs-on: ubuntu-latest
+ outputs:
+ ros2-amd64: ${{ steps.filter.outputs.ros2-amd64 }}
+ ros2-jetson: ${{ steps.filter.outputs.ros2-jetson }}
+ workflow: ${{ steps.filter.outputs.workflow }}
+ image_version: ${{ steps.set_version.outputs.image_version }}
+ permissions:
+ packages: write
+ contents: read
+ pull-requests: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # fetch all history to compare with previous commits
+
+ - name: Check for file changes
+ uses: dorny/paths-filter@v2
+ id: filter
+ with:
+ filters: |
+ ros2-amd64:
+ - 'ROS2/AMD64x86/**'
+ workflow:
+ - '.github/workflows/**'
+# ros2-jetson:
+# - 'ROS2/Jetson/**'
+
+ - name: Set image version
+ id: set_version
+ run: |
+ echo "image_version=${{ github.ref_name }}" >> $GITHUB_OUTPUT
+
+ # Stage 1: ROS2 base humble images (AMD64/x86)
+ ros2-humble-base-amd64:
+ needs: changes
+ if: ${{ needs.changes.outputs.ros2-amd64 == 'true' || needs.changes.outputs.workflow == 'true' }}
+ name: ROS2 Humble Base Images (AMD64)
+ permissions:
+ packages: write
+ contents: read
+ strategy:
+ matrix:
+ config:
+ - { build_context: './ROS2/AMD64x86/humble', image_name: 'humble', image_version: "${{ needs.changes.outputs.image_version }}" }
+ - { build_context: './ROS2/AMD64x86/humble_gpu', image_name: 'humble_gpu', image_version: "${{ needs.changes.outputs.image_version }}" }
+ uses: ./.github/workflows/build-workflow.yaml
+ with:
+ build_context: ${{ matrix.config.build_context }}
+ image_name: ${{ matrix.config.image_name }}
+ image_version: ${{ matrix.config.image_version }}
+ runs_on: ubuntu-latest
+
+ # Stage 1: ROS2 base humble images (Jetson/ARM)
+ # ros2-humble-jetson:
+ # needs: changes
+ # if: ${{ needs.changes.outputs.ros2-jetson == 'true' || needs.changes.outputs.workflow == 'true' }}
+ # name: ROS2 Humble Jetson Base
+ # permissions:
+ # packages: write
+ # contents: read
+ # strategy:
+ # matrix:
+ # config:
+ # - { build_context: './ROS2/Jetson/humble_jetson', image_name: 'humble_jetson', image_version: "${{ needs.changes.outputs.image_version }}" }
+ # uses: ./.github/workflows/build-workflow.yaml
+ # with:
+ # build_context: ${{ matrix.config.build_context }}
+ # image_name: ${{ matrix.config.image_name }}
+ # image_version: ${{ matrix.config.image_version }}
+ # runs_on: ubuntu-24.04-arm
+
+ # Stage 2: ROS2 humble_harmonic (depends on base humble)
+ ros2-humble-harmonic:
+ needs: [changes, ros2-humble-base-amd64]
+ if: ${{ needs.changes.outputs.ros2-amd64 == 'true' || needs.changes.outputs.workflow == 'true' }}
+ name: ROS2 Humble Harmonic
+ permissions:
+ packages: write
+ contents: read
+ strategy:
+ matrix:
+ config:
+ - { build_context: './ROS2/AMD64x86/humble_harmonic', image_name: 'humble_harmonic', image_version: "${{ needs.changes.outputs.image_version }}" }
+ uses: ./.github/workflows/build-workflow.yaml
+ with:
+ build_context: ${{ matrix.config.build_context }}
+ image_name: ${{ matrix.config.image_name }}
+ image_version: ${{ matrix.config.image_version }}
+ runs_on: ubuntu-latest
+
+ # Stage 3: ROS2 wheelchair2_base images (AMD64/x86)
+ ros2-wheelchair-base:
+ needs: [changes, ros2-humble-base-amd64, ros2-humble-harmonic]
+ if: ${{ needs.changes.outputs.ros2-amd64 == 'true' || needs.changes.outputs.workflow == 'true' }}
+ name: ROS2 Wheelchair2 Base Images
+ permissions:
+ packages: write
+ contents: read
+ strategy:
+ matrix:
+ config:
+ - { build_context: './ROS2/AMD64x86/wheelchair2_base', image_name: 'wheelchair2_base', image_version: "${{ needs.changes.outputs.image_version }}" }
+ - { build_context: './ROS2/AMD64x86/wheelchair2_base_gazebo', image_name: 'wheelchair2_base_gazebo', image_version: "${{ needs.changes.outputs.image_version }}" }
+ uses: ./.github/workflows/build-workflow.yaml
+ with:
+ build_context: ${{ matrix.config.build_context }}
+ image_name: ${{ matrix.config.image_name }}
+ image_version: ${{ matrix.config.image_version }}
+ runs_on: ubuntu-latest
+
+ # Stage 3: ROS2 wheelchair2_base_jetson (depends on humble_jetson)
+ # ros2-wheelchair-jetson:
+ # needs: [changes, ros2-humble-jetson]
+ # if: ${{ needs.changes.outputs.ros2-jetson == 'true' || needs.changes.outputs.workflow == 'true' }}
+ # name: ROS2 Wheelchair2 Jetson Images
+ # permissions:
+ # packages: write
+ # contents: read
+ # strategy:
+ # matrix:
+ # config:
+ # - { build_context: './ROS2/Jetson/wheelchair2_base_jetson', image_name: 'wheelchair2_base_jetson', image_version: "${{ needs.changes.outputs.image_version }}" }
+ # uses: ./.github/workflows/build-workflow.yaml
+ # with:
+ # build_context: ${{ matrix.config.build_context }}
+ # image_name: ${{ matrix.config.image_name }}
+ # image_version: ${{ matrix.config.image_version }}
+ # runs_on: ubuntu-24.04-arm
\ No newline at end of file
diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml
new file mode 100644
index 0000000..e218daa
--- /dev/null
+++ b/.github/workflows/build-test.yaml
@@ -0,0 +1,140 @@
+name: Build Multi-Architecture ROS Containers
+
+on:
+ push:
+ tags:
+ - 'dev*'
+
+jobs:
+ # Detect file changes
+ changes:
+ runs-on: ubuntu-latest
+ outputs:
+ ros2-amd64: ${{ steps.filter.outputs.ros2-amd64 }}
+ ros2-jetson: ${{ steps.filter.outputs.ros2-jetson }}
+ workflow: ${{ steps.filter.outputs.workflow }}
+ image_version: ${{ steps.set_version.outputs.image_version }}
+ permissions:
+ packages: write
+ contents: read
+ pull-requests: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # fetch all history to compare with previous commits
+
+ - name: Check for file changes
+ uses: dorny/paths-filter@v2
+ id: filter
+ with:
+ filters: |
+ ros2-amd64:
+ - 'ROS2/AMD64x86/**'
+ workflow:
+ - '.github/workflows/**'
+# ros2-jetson:
+# - 'ROS2/Jetson/**'
+
+ - name: Set image version
+ id: set_version
+ run: |
+ echo "image_version=${{ github.ref_name }}" >> $GITHUB_OUTPUT
+
+ # Stage 1: ROS2 base humble images (AMD64/x86)
+ ros2-humble-base-amd64:
+ needs: changes
+ if: ${{ needs.changes.outputs.ros2-amd64 == 'true' || needs.changes.outputs.workflow == 'true' }}
+ name: ROS2 Humble Base Images (AMD64)
+ permissions:
+ packages: write
+ contents: read
+ strategy:
+ matrix:
+ config:
+ - { build_context: './ROS2/AMD64x86/humble', image_name: 'humble', image_version: "${{ needs.changes.outputs.image_version }}" }
+ - { build_context: './ROS2/AMD64x86/humble_gpu', image_name: 'humble_gpu', image_version: "${{ needs.changes.outputs.image_version }}" }
+ uses: ./.github/workflows/build-workflow.yaml
+ with:
+ build_context: ${{ matrix.config.build_context }}
+ image_name: ${{ matrix.config.image_name }}
+ image_version: ${{ matrix.config.image_version }}
+ runs_on: ubuntu-latest
+
+ # Stage 1: ROS2 base humble images (Jetson/ARM)
+ # ros2-humble-jetson:
+ # needs: changes
+ # if: ${{ needs.changes.outputs.ros2-jetson == 'true' || needs.changes.outputs.workflow == 'true' }}
+ # name: ROS2 Humble Jetson Base
+ # permissions:
+ # packages: write
+ # contents: read
+ # strategy:
+ # matrix:
+ # config:
+ # - { build_context: './ROS2/Jetson/humble_jetson', image_name: 'humble_jetson', image_version: "${{ needs.changes.outputs.image_version }}" }
+ # uses: ./.github/workflows/build-workflow.yaml
+ # with:
+ # build_context: ${{ matrix.config.build_context }}
+ # image_name: ${{ matrix.config.image_name }}
+ # image_version: ${{ matrix.config.image_version }}
+ # runs_on: ubuntu-24.04-arm
+
+ # Stage 2: ROS2 humble_harmonic (depends on base humble)
+ ros2-humble-harmonic:
+ needs: [changes, ros2-humble-base-amd64]
+ if: ${{ needs.changes.outputs.ros2-amd64 == 'true' || needs.changes.outputs.workflow == 'true' }}
+ name: ROS2 Humble Harmonic
+ permissions:
+ packages: write
+ contents: read
+ strategy:
+ matrix:
+ config:
+ - { build_context: './ROS2/AMD64x86/humble_harmonic', image_name: 'humble_harmonic', image_version: "${{ needs.changes.outputs.image_version }}" }
+ uses: ./.github/workflows/build-workflow.yaml
+ with:
+ build_context: ${{ matrix.config.build_context }}
+ image_name: ${{ matrix.config.image_name }}
+ image_version: ${{ matrix.config.image_version }}
+ runs_on: ubuntu-latest
+
+ # Stage 3: ROS2 wheelchair2_base images (AMD64/x86)
+ ros2-wheelchair-base:
+ needs: [changes, ros2-humble-base-amd64, ros2-humble-harmonic]
+ if: ${{ needs.changes.outputs.ros2-amd64 == 'true' || needs.changes.outputs.workflow == 'true' }}
+ name: ROS2 Wheelchair2 Base Images
+ permissions:
+ packages: write
+ contents: read
+ strategy:
+ matrix:
+ config:
+ - { build_context: './ROS2/AMD64x86/wheelchair2_base', image_name: 'wheelchair2_base', image_version: "${{ needs.changes.outputs.image_version }}" }
+ - { build_context: './ROS2/AMD64x86/wheelchair2_base_gazebo', image_name: 'wheelchair2_base_gazebo', image_version: "${{ needs.changes.outputs.image_version }}" }
+ uses: ./.github/workflows/build-workflow.yaml
+ with:
+ build_context: ${{ matrix.config.build_context }}
+ image_name: ${{ matrix.config.image_name }}
+ image_version: ${{ matrix.config.image_version }}
+ runs_on: ubuntu-latest
+
+ # Stage 3: ROS2 wheelchair2_base_jetson (depends on humble_jetson)
+ # ros2-wheelchair-jetson:
+ # needs: [changes, ros2-humble-jetson]
+ # if: ${{ needs.changes.outputs.ros2-jetson == 'true' || needs.changes.outputs.workflow == 'true' }}
+ # name: ROS2 Wheelchair2 Jetson Images
+ # permissions:
+ # packages: write
+ # contents: read
+ # strategy:
+ # matrix:
+ # config:
+ # - { build_context: './ROS2/Jetson/wheelchair2_base_jetson', image_name: 'wheelchair2_base_jetson', image_version: "${{ needs.changes.outputs.image_version }}" }
+ # uses: ./.github/workflows/build-workflow.yaml
+ # with:
+ # build_context: ${{ matrix.config.build_context }}
+ # image_name: ${{ matrix.config.image_name }}
+ # image_version: ${{ matrix.config.image_version }}
+ # runs_on: ubuntu-24.04-arm
\ No newline at end of file
diff --git a/.github/workflows/build-workflow.yaml b/.github/workflows/build-workflow.yaml
new file mode 100644
index 0000000..1553a07
--- /dev/null
+++ b/.github/workflows/build-workflow.yaml
@@ -0,0 +1,56 @@
+name: Build and Push Docker Image
+
+on:
+ workflow_call:
+ inputs:
+ build_context:
+ description: 'Path to the build context'
+ required: true
+ type: string
+ image_name:
+ description: 'Name of the Docker image'
+ required: true
+ type: string
+ image_version:
+ description: 'Version/tag for the Docker image'
+ required: true
+ type: string
+ runs_on:
+ description: 'The type of runner to use'
+ required: false
+ type: string
+ default: 'ubuntu-latest'
+
+jobs:
+ build-and-push:
+ name: Build and Push Docker Image
+ runs-on: ${{ inputs.runs_on }}
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Set up GitHub Actions environment
+ run: echo "GITHUB_OWNER_LOWER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
+
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Log in to GitHub Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Build and push Docker image
+ uses: docker/build-push-action@v6
+ with:
+ context: ${{ inputs.build_context }}
+ push: true
+ tags: ghcr.io/${{ env.GITHUB_OWNER_LOWER }}/${{ inputs.image_name }}:${{ inputs.image_version }}
+ labels: |
+ org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
\ No newline at end of file
diff --git a/README.md b/README.md
index 7423041..d6b1408 100644
--- a/README.md
+++ b/README.md
@@ -1,85 +1,191 @@
-# Docker For ROS Development
-Docker images for Easy ROS1 and ROS2 development with the wheelchair.
+# Docker for ROS Development
-## Available Images
+This repository provides ROS1 and ROS2 Docker images for easy development with the wheelchair.
-The following Docker images are available:
+This documentation is split into four parts:
-- `humble`: Based on `ubuntu:jammy`, this image includes ROS 2 Humble Hawksbill packages and a non-root user for enhanced security.
-- `humble_gpu`: Based on `nvidia/cuda:12.2.2-devel-ubuntu22.04`, this image includes ROS 2 Humble Hawksbill packages, CUDA, CuDNN and a non-root user for enhanced security.
-- `humble_harmonic`: Extends the `humble_gpu` image and includes Gazebo Harmonic, which works better with `humble-gz_sim` related deps. Hence this is **Recommended** over `fortress`.
-- `wheelchair2_base`: Extends the `humble` image and includes Realsense and Livox SDK's
-- `humble_jetson`: Based on `ubuntu:jammy for ARM64`, this image includes ROS 2 Humble Hawksbill packages and a non-root user for enhanced security.
-- `wheelchair2_base_jetson`: Extends the `humble_jetson` image and includes Realsense and Livox SDK's
-- `wheelchair2_base_gazebo`: Extends `humble_harmonic` image and includes `ros2_control`, `RGLGazeboPlugin`, `Nvidia Optix` for gz-sim and Realsense and Livox SDK's for real-world runs.
+- [List of features and images](#list-of-ros2-features-and-images)
+- [Instructions for everyone (GHCR authentication)](#authenticating-to-github-container-registry)
+- [How to use an image](#pulling-an-image)
+- [How to build an image](#building-an-image)
-**Important Note:** The `ROS1` images are currently **under development** and have not been heavily tested. They may be unstable or contain significant bugs.
-
-## Usage
+> [!NOTE]
+> This repository uses GitHub Actions for CI/CD. Further documentation on how we have implemented this is available in the [CI/CD documentation](/.github/workflows/README.md).
-### 1. Pulling an Image
+## List of ROS2 Features and Images
+
+| Image name | Base image | Intended target | Features |
+| --- | --- | --- | --- |
+| `humble` | [`ubuntu:jammy`](https://hub.docker.com/_/ubuntu) | x86\_64 laptop | - ROS2 Humble Hawksbill packages
- non-root user |
+| `humble_gpu` | [`nvidia/cuda:12.2.2-devel-ubuntu22.04`](https://hub.docker.com/r/nvidia/cuda) | x86\_64 laptop | - ROS2 Humble Hawksbill packages
- CUDA
- CuDNN
- non-root user |
+| `humble_harmonic` | `humble_gpu` | x86\_64 laptop | - Gazebo Harmonic (recommended over fortress) |
+| `wheelchair2_base` | `humble` | x86\_64 laptop | - Realsense SDK
- Livox SDK |
+| `wheelchair_2_base_gazebo` | `humble_harmonic` | x86\_64 laptop | - ros2\_control
- RGLGazeboPlugin
- Nvidia Optix for gz-sim
- Realsense SDK
- Livox SDK |
+| `humble_jetson` | [`nvcr.io/nvidia/l4t-jetpack`](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/l4t-jetpack) | Jetson (ARM64) | - ROS2 Humble Hawksbill packages
- non-root user |
+| `wheelchair2_base_jetson` | `humble_jetson` | Jetson (ARM64) | - Realsense SDK
- Livox SDK |
+
+> [!CAUTION]
+> The ROS1 images are currently **under development** and have not been heavily tested. They may be unstable or contain significant bugs.
+
+## Authenticating to GitHub Container Registry
+To pull or push images to the GitHub Container Registry, you need to authenticate using a personal access token (PAT) with the `write:packages` and `repo` scopes.
+
+Brief steps are given below, but you can find more detailed instructions in the [GitHub documentation](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-with-a-personal-access-token-classic).
+1. Create a personal access token (PAT) with the required scopes.
+2. Log in to the GitHub Container Registry using the following command:
+
+ ```bash
+ echo | docker login ghcr.io -u --password-stdin
+ ```
+
+3. Verify that you are logged in by running:
+
+ ```bash
+ docker info
+ ```
+
+### Debugging
+If docker throws the error even after restarting the Docker daemon:
+
+```txt
+Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
+```
+
+You can try the following steps:
+
+1. Docker networking requires IP forwarding. Check if it's enabled:
+ ```bash
+ sysctl net.ipv4.ip_forward
+ ```
+
+1. If it returns `0`, enable it with:
+
+ ```bash
+ sudo sysctl -w net.ipv4.ip_forward=1
+ ```
+
+1. Then restart the Docker daemon:
+
+ ```bash
+ sudo systemctl restart docker
+ ```
+
+1. When we're building a package from a GitHub repository, we only need the latest commits. We achieve this using the `--depth=1` option in the `git clone` command. This option tells Git to clone only the latest commit, which is sufficient for building the package.
+
+ Moreover, Git usually doesn't print logs to stdout when run in a container, but these are very useful for debugging. We enable these using the `--progress --verbose` flags.
+
+ Therefore, a complete `git clone` command would look like this:
+
+ ```bash
+ git clone --depth=1 --progress --verbose
+ ```
+
+ As an example:
+
+ ```bash
+ git clone --depth=1 --progress --verbose https://github.com/rtarun1/Livox-SDK2.git
+ ```
+
+## Pulling an image
To download a pre-built image from GitHub Container Registry (ghcr.io), use the following command:
```bash
-docker pull ghcr.io/smart-wheelchair-rrc/:latest
+docker pull ghcr.io/smart-wheelchair-rrc/:
```
Replace `` with the desired image name (e.g., `humble`, `wheelchair2_base`). For example:
```bash
-docker pull ghcr.io/smart-wheelchair-rrc/humble:latest
+docker pull ghcr.io/smart-wheelchair-rrc/humble:v3.0
```
-### 2. Building an Image (Optional)
+> [!IMPORTANT]
+> Please be mindful of the tag you are pulling. The `latest` tag is not used in this repository, so you need to provide a specific version tag (e.g., `v3.0`).
-If you prefer to build the image locally from the Dockerfile, clone this repository and navigate to the root directory. Then, use the following command:
+## Building an image
+Since this repository uses CI/CD builds, certain considerations must be taken into account when building images:
-```bash
-docker build -t ghcr.io/smart-wheelchair-rrc/ -f /Dockerfile
-```
+1. **Dependant images**
-Again, replace `` with the appropriate image name. For example, to build the `humble` image:
+ Certain images depend on other images. For example, `wheelchair2_base_gazebo` depends on `humble_harmonic`. If you want to build `wheelchair2_base_gazebo`, you need to build `humble_harmonic` first.
-```bash
-docker build -t ghcr.io/smart-wheelchair-rrc/humble -f humble-garden/Dockerfile humble
-```
+ In the dependant image's Dockerfile, you can specify the base image as follows:
-**Explanation of the `docker build` command:**
+ ```dockerfile
+ FROM ghcr.io/smart-wheelchair-rrc/humble_harmonic:v3.0
+ ```
-* `docker build`: The command to build a Docker image.
-* `-t ghcr.io/smart-wheelchair-rrc/`: Tags the image with the specified name and registry path.
-* `-f /Dockerfile`: Specifies the path to the Dockerfile to use for building the image.
-* ``: The build context, which is the directory containing the Dockerfile and any other files needed for the build.
+ Again, please be mindful of the tag you are using. If you update a base image, and you want the changes to reflect in the dependant image, you need to rebuild the dependant image **with the correct tag of the base image**.
-### 3. Pushing an Image (For Contributors)
+1. **Online builds must be tagged**
-If you have made changes to the Dockerfile and want to contribute by pushing the updated image to the registry, use the following command:
+ The CI/CD system **will not initiate builds** if the image is not tagged. Moreover, your tag must follow the [SemVer](https://semver.org/spec/v2.0.0.html) format. For example: `v3`, `v3.0`, `v3.1.0`. So your tag names must start with `v` and be followed by a version number.
-```bash
-docker push ghcr.io/smart-wheelchair-rrc/:latest
-```
+ Once a commit has been tagged and pushed to the repository, the CI/CD system will automatically build the image and push it to the GitHub Container Registry. It will attempt to do this regardless of the branch you are on.
-**Note:** You need to be authenticated with `ghcr.io` and have the appropriate permissions to push images to the `smart-wheelchair-rrc` repository.
+1. **Building locally**
-### Debugging
+ If you want to build locally, you're free to use any tags you like, however you should be mindful of dependant images and their tags. You can build an image using the following command:
->The docker throws " Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? " error, even after restarting docker, do the following:
+ ```bash
+ docker build -t ghcr.io/smart-wheelchair-rrc/: -f
+ ```
+
+ Replace `` with the desired image name, `` with the version tag, and `` with the directory containing the Dockerfile. For example, to build the `humble` image:
-- Docker networking requires IP forwarding. Check if it's enabled:
```bash
- sysctl net.ipv4.ip_forward
+ docker build -t ghcr.io/smart-wheelchair-rrc/humble:v3.0 -f ROS2/AMD64x86/humble/Dockerfile ROS2/AMD64x86/humble
```
-- If it returns 0, enable it with:
+
+1. **Pushing the image**
+
+ After building the image, you can push it to the GitHub Container Registry using the following command:
+
```bash
- sudo sysctl -w net.ipv4.ip_forward=1
+ docker push ghcr.io/smart-wheelchair-rrc/:
```
-- Then restart Docker:
+
+ For example, to push the `humble` image:
+
```bash
- sudo systemctl restart docker
+ docker push ghcr.io/smart-wheelchair-rrc/humble:v3.0
```
-## Acknowledgements
+> [!IMPORTANT]
+> Avoid using the `latest` tag.
-This work is inspired by the work of [soham2560](https://github.com/soham2560/DockerForROS2Development).
+### Explanation of the `docker build` command
+
+The [`docker build` command](https://docs.docker.com/reference/cli/docker/buildx/build/) is used to create a Docker image from a Dockerfile. Here's a breakdown of the command and its arguments:
+
+```bash
+docker build -t ghcr.io/smart-wheelchair-rrc/: -f
+```
+
+| Argument | Value | Example | Description |
+| --- | --- | --- | --- |
+| `-t` | `ghcr.io/smart-wheelchair-rrc/:` | `ghcr.io/smart-wheelchair-rrc/humble:v3.0` | Tags the image with the specified name and version tag. |
+| `-f` | `` | `ROS2/AMD64x86/humble/Dockerfile` | Specifies the path to the Dockerfile to use for building the image. |
+| | `` | `ROS2/AMD64x86/humble` | The build context, which is the directory containing the Dockerfile and any other files needed for the build. |
+### Recommendations for tagging images
+Suggestions for filling in the SemVer version tag.
+
+Let us assume that the latest image before you start working is `v3.14`. Therefore, the next image you target to release will be `v3.15`.
+
+However, the CI/CD workflow requires that you tag every commit where you want to build an image AND GitHub requires commit tags to be unique. If you wish to use the online builds to test your changes, you can use the `dev*` tags. For example, you can tag your commit as `dev3.15.0` or `dev3.15.1`. This way, you can test your changes without affecting the main versioning scheme.
+
+When you are ready to release the next version (most likely a merge commit), you can tag it as `v3.15.0` or `v3.15`. This will trigger the CI/CD workflow to build the image with the correct version tag.
+
+> [!NOTE]
+> - `v*` tags only work on the `master` branch.
+> - `dev*` tags can be used on any branch (including `master`).
+> - While the `latest` tag is supported on the `master` branch, it is **not recommended** to use it. Instead, prefer specific version tags like `v3.15` or `v3.15.0`.
+>
+> Both tags will trigger the workflow and push the image to GHCR.
+
+
+
+## Acknowledgements
+This work is inspired by the work of [soham2560](https://github.com/soham2560/DockerForROS2Development).
diff --git a/ROS2/AMD64x86/humble/Dockerfile b/ROS2/AMD64x86/humble/Dockerfile
index dab8f9b..69f9880 100644
--- a/ROS2/AMD64x86/humble/Dockerfile
+++ b/ROS2/AMD64x86/humble/Dockerfile
@@ -2,7 +2,7 @@ FROM ubuntu:jammy
# basic args
ARG ROS_DISTRO=humble
-ARG USERNAME=wheelchair2
+ARG USERNAME=container_user
ARG USER_UID=1000
ARG USER_GID=$USER_UID
@@ -29,20 +29,17 @@ RUN echo 'Asia/Kolkata' > /etc/timezone && \
RUN apt-get update && apt-get install -q -y --no-install-recommends \
dirmngr \
gnupg2 \
+ curl \
+ ca-certificates \
&& rm -rf /var/lib/apt/lists/*
-# setup keys
-RUN set -eux; \
- key='C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654'; \
- export GNUPGHOME="$(mktemp -d)"; \
- gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
- mkdir -p /usr/share/keyrings; \
- gpg --batch --export "$key" > /usr/share/keyrings/ros2-latest-archive-keyring.gpg; \
- gpgconf --kill all; \
- rm -rf "$GNUPGHOME"
-
-# setup sources.list
-RUN echo "deb [ signed-by=/usr/share/keyrings/ros2-latest-archive-keyring.gpg ] http://packages.ros.org/ros2/ubuntu jammy main" > /etc/apt/sources.list.d/ros2-latest.list
+# Setup ROS Apt sources
+RUN curl -L -s -o /tmp/ros2-apt-source.deb https://github.com/ros-infrastructure/ros-apt-source/releases/download/1.1.0/ros2-apt-source_1.1.0.jammy_all.deb \
+ && echo "1600cb8cc28258a39bffc1736a75bcbf52d1f2db371a4d020c1b187d2a5a083b /tmp/ros2-apt-source.deb" | sha256sum --strict --check \
+ && apt-get update \
+ && apt-get install /tmp/ros2-apt-source.deb \
+ && rm -f /tmp/ros2-apt-source.deb \
+ && rm -rf /var/lib/apt/lists/*
# setup environment
ENV LANG=C.UTF-8
diff --git a/ROS2/AMD64x86/humble_gpu/Dockerfile b/ROS2/AMD64x86/humble_gpu/Dockerfile
index 876caec..9791eb2 100644
--- a/ROS2/AMD64x86/humble_gpu/Dockerfile
+++ b/ROS2/AMD64x86/humble_gpu/Dockerfile
@@ -2,7 +2,7 @@ FROM nvidia/cuda:12.2.2-base-ubuntu22.04
# basic args
ARG ROS_DISTRO=humble
-ARG USERNAME=wheelchair2
+ARG USERNAME=container_user
ARG USER_UID=1000
ARG USER_GID=$USER_UID
@@ -29,20 +29,17 @@ RUN echo 'Asia/Kolkata' > /etc/timezone && \
RUN apt-get update && apt-get install -q -y --no-install-recommends \
dirmngr \
gnupg2 \
+ curl \
+ ca-certificates \
&& rm -rf /var/lib/apt/lists/*
-# setup keys
-RUN set -eux; \
- key='C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654'; \
- export GNUPGHOME="$(mktemp -d)"; \
- gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
- mkdir -p /usr/share/keyrings; \
- gpg --batch --export "$key" > /usr/share/keyrings/ros2-latest-archive-keyring.gpg; \
- gpgconf --kill all; \
- rm -rf "$GNUPGHOME"
-
-# setup sources.list
-RUN echo "deb [ signed-by=/usr/share/keyrings/ros2-latest-archive-keyring.gpg ] http://packages.ros.org/ros2/ubuntu jammy main" > /etc/apt/sources.list.d/ros2-latest.list
+# Setup ROS Apt sources
+RUN curl -L -s -o /tmp/ros2-apt-source.deb https://github.com/ros-infrastructure/ros-apt-source/releases/download/1.1.0/ros2-apt-source_1.1.0.jammy_all.deb \
+ && echo "1600cb8cc28258a39bffc1736a75bcbf52d1f2db371a4d020c1b187d2a5a083b /tmp/ros2-apt-source.deb" | sha256sum --strict --check \
+ && apt-get update \
+ && apt-get install /tmp/ros2-apt-source.deb \
+ && rm -f /tmp/ros2-apt-source.deb \
+ && rm -rf /var/lib/apt/lists/*
# setup environment
ENV LANG=C.UTF-8
diff --git a/ROS2/AMD64x86/humble_harmonic/Dockerfile b/ROS2/AMD64x86/humble_harmonic/Dockerfile
index 7fae0ef..72e4776 100644
--- a/ROS2/AMD64x86/humble_harmonic/Dockerfile
+++ b/ROS2/AMD64x86/humble_harmonic/Dockerfile
@@ -1,5 +1,6 @@
+FROM ghcr.io/smart-wheelchair-rrc/humble_gpu:v3.1
-FROM ghcr.io/smart-wheelchair-rrc/humble_gpu:latest
+ARG USERNAME=container_user
# Environment setup
ENV GZ_VERSION=harmonic
@@ -19,4 +20,4 @@ RUN sudo curl https://packages.osrfoundation.org/gazebo.gpg --output /usr/share/
&& sudo apt-get install -y gz-harmonic \
&& sudo rm -rf /var/lib/apt/lists/*
-RUN sudo apt-get update && sudo apt-get install -y ros-humble-ros-gzharmonic
\ No newline at end of file
+RUN sudo apt-get update && sudo apt-get install -y ros-$ROS_DISTRO-ros-gzharmonic
\ No newline at end of file
diff --git a/ROS2/AMD64x86/wheelchair2_base/.tmux.conf b/ROS2/AMD64x86/wheelchair2_base/.tmux.conf
new file mode 100644
index 0000000..ef5c78d
--- /dev/null
+++ b/ROS2/AMD64x86/wheelchair2_base/.tmux.conf
@@ -0,0 +1,24 @@
+# Minimal tmux configuration for scrolling support
+# Save this as .tmux.conf
+
+# Enable mouse support (includes scrolling)
+set -g mouse on
+
+# Increase scrollback buffer size from default 2000 to 10000
+set -g history-limit 10000
+
+# Enable mouse wheel scrolling in copy mode and normal mode
+bind -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'select-pane -t=; copy-mode -e; send-keys -M'"
+bind -n WheelDownPane select-pane -t= \; send-keys -M
+
+# Vi-style copy mode (optional but recommended)
+setw -g mode-keys vi
+
+# Easy access to copy mode with Page Up
+bind -n Pageup copy-mode -u
+
+# Shift + Page Up for copy mode (alternative)
+bind -n S-Pageup copy-mode -u
+
+# Shift + Page Down to exit copy mode
+bind -n S-Pagedown send-keys Pagedown
\ No newline at end of file
diff --git a/ROS2/AMD64x86/wheelchair2_base/Dockerfile b/ROS2/AMD64x86/wheelchair2_base/Dockerfile
index d75468b..aae5d1a 100644
--- a/ROS2/AMD64x86/wheelchair2_base/Dockerfile
+++ b/ROS2/AMD64x86/wheelchair2_base/Dockerfile
@@ -1,4 +1,6 @@
-FROM ghcr.io/smart-wheelchair-rrc/humble:latest
+FROM ghcr.io/smart-wheelchair-rrc/humble:v3.1
+
+ARG USERNAME=container_user
# Add the following labels
LABEL org.opencontainers.image.description="Wheelchair2"
@@ -32,9 +34,9 @@ RUN sudo apt-get update \
&& sudo rm -rf /var/lib/apt/lists/*
# Build and install Realsense-SDK
-WORKDIR /home/wheelchair2
-RUN git clone --branch v2.56.2 https://github.com/IntelRealSense/librealsense.git
-WORKDIR /home/wheelchair2/librealsense
+WORKDIR /home/$USERNAME
+RUN git clone --depth=1 --progress --verbose --branch v2.56.2 https://github.com/IntelRealSense/librealsense.git
+WORKDIR /home/$USERNAME/librealsense
RUN sudo mkdir -p /etc/udev/rules.d && \
./scripts/setup_udev_rules.sh \
./scripts/patch-realsense-ubuntu-lts-hwe.sh
@@ -43,8 +45,8 @@ RUN mkdir build && cd build \
&& sudo make uninstall && make clean && make && sudo make install
# Build and install Livox-SDK2
-WORKDIR /home/wheelchair2
-RUN git clone https://github.com/rtarun1/Livox-SDK2.git
+WORKDIR /home/$USERNAME
+RUN git clone --depth=1 --progress --verbose https://github.com/rtarun1/Livox-SDK2.git
RUN cd Livox-SDK2 \
&& mkdir build \
&& cd build \
@@ -75,5 +77,7 @@ RUN sudo apt-get update \
RUN echo 'export TERM="xterm-256color"' | sudo tee -a ~/.bashrc > /dev/null && \
echo "export PS1='\\[\\033[01;32m\\]\\u@\\h:\\[\\033[01;34m\\]\\w\\$\\[\\033[00m\\] '" | sudo tee -a ~/.bashrc > /dev/null
+COPY .tmux.conf /home/wheelchair2/.tmux.conf
+
# Environment variable for map folder
-ENV MAP_DIR=/home/wheelchair2/wheelchair2/src/wheelchair2_navigation/maps
\ No newline at end of file
+ENV MAP_DIR=/home/$USERNAME/wheelchair2/src/wheelchair2_navigation/maps
\ No newline at end of file
diff --git a/ROS2/AMD64x86/wheelchair2_base_gazebo/.tmux.conf b/ROS2/AMD64x86/wheelchair2_base_gazebo/.tmux.conf
new file mode 100644
index 0000000..ef5c78d
--- /dev/null
+++ b/ROS2/AMD64x86/wheelchair2_base_gazebo/.tmux.conf
@@ -0,0 +1,24 @@
+# Minimal tmux configuration for scrolling support
+# Save this as .tmux.conf
+
+# Enable mouse support (includes scrolling)
+set -g mouse on
+
+# Increase scrollback buffer size from default 2000 to 10000
+set -g history-limit 10000
+
+# Enable mouse wheel scrolling in copy mode and normal mode
+bind -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'select-pane -t=; copy-mode -e; send-keys -M'"
+bind -n WheelDownPane select-pane -t= \; send-keys -M
+
+# Vi-style copy mode (optional but recommended)
+setw -g mode-keys vi
+
+# Easy access to copy mode with Page Up
+bind -n Pageup copy-mode -u
+
+# Shift + Page Up for copy mode (alternative)
+bind -n S-Pageup copy-mode -u
+
+# Shift + Page Down to exit copy mode
+bind -n S-Pagedown send-keys Pagedown
\ No newline at end of file
diff --git a/ROS2/AMD64x86/wheelchair2_base_gazebo/Dockerfile b/ROS2/AMD64x86/wheelchair2_base_gazebo/Dockerfile
index 8a5f8bb..56de6cb 100644
--- a/ROS2/AMD64x86/wheelchair2_base_gazebo/Dockerfile
+++ b/ROS2/AMD64x86/wheelchair2_base_gazebo/Dockerfile
@@ -1,4 +1,6 @@
-FROM ghcr.io/smart-wheelchair-rrc/humble_harmonic:latest
+FROM ghcr.io/smart-wheelchair-rrc/humble_harmonic:v3.1
+
+ARG USERNAME=container_user
# Add the following labels
LABEL org.opencontainers.image.description="Wheelchair2"
@@ -32,9 +34,9 @@ RUN sudo apt-get update \
&& sudo rm -rf /var/lib/apt/lists/*
# Build and install Realsense-SDK
-WORKDIR /home/wheelchair2
-RUN git clone --branch v2.56.2 https://github.com/IntelRealSense/librealsense.git
-WORKDIR /home/wheelchair2/librealsense
+WORKDIR /home/$USERNAME
+RUN git clone --depth=1 --progress --verbose --branch v2.56.2 https://github.com/IntelRealSense/librealsense.git
+WORKDIR /home/$USERNAME/librealsense
RUN sudo mkdir -p /etc/udev/rules.d && \
./scripts/setup_udev_rules.sh \
./scripts/patch-realsense-ubuntu-lts-hwe.sh
@@ -43,8 +45,8 @@ RUN mkdir build && cd build \
&& sudo make uninstall && make clean && make && sudo make install
# Build and install Livox-SDK2
-WORKDIR /home/wheelchair2
-RUN git clone https://github.com/rtarun1/Livox-SDK2.git
+WORKDIR /home/$USERNAME
+RUN git clone --depth=1 --progress --verbose https://github.com/rtarun1/Livox-SDK2.git
RUN cd Livox-SDK2 \
&& mkdir build \
&& cd build \
@@ -60,13 +62,13 @@ RUN sudo apt-get update \
&& sudo apt-get -y install --no-install-recommends $(cat /tmp/rosPkgs.list) \
&& sudo rm -rf /var/lib/apt/lists/*
-WORKDIR /home/wheelchair2/gz_ros2_control_ws/src
-RUN git clone https://github.com/ros-controls/gz_ros2_control -b humble . \
+WORKDIR /home/$USERNAME/gz_ros2_control_ws/src
+RUN git clone --depth=1 --progress --verbose https://github.com/ros-controls/gz_ros2_control -b $ROS_DISTRO . \
&& export GZ_VERSION=harmonic \
&& rosdep install -r --from-paths . --ignore-src --rosdistro $ROS_DISTRO -y --skip-keys="ros_gz_bridge ros_gz_sim"
-WORKDIR /home/wheelchair2/gz_ros2_control_ws
-RUN source /opt/ros/humble/setup.bash \
+WORKDIR /home/$USERNAME/gz_ros2_control_ws
+RUN source /opt/ros/$ROS_DISTRO/setup.bash \
&& colcon build \
&& echo "source ~/gz_ros2_control_ws/install/setup.bash" | sudo tee -a ~/.bashrc > /dev/null
@@ -74,16 +76,16 @@ RUN sudo mkdir -p /opt/nvidia/
COPY NVIDIA-OptiX-SDK-7.2.0-linux64-x86_64/ /opt/nvidia/NVIDIA-OptiX-SDK-7.2.0-linux64-x86_64/
ENV OptiX_INSTALL_DIR=/opt/nvidia/NVIDIA-OptiX-SDK-7.2.0-linux64-x86_64/
-WORKDIR /home/wheelchair2
-RUN git clone https://github.com/RobotecAI/RGLGazeboPlugin.git \
+WORKDIR /home/$USERNAME
+RUN git clone --depth=1 --progress --verbose https://github.com/RobotecAI/RGLGazeboPlugin.git \
&& cd RGLGazeboPlugin \
&& mkdir build && cd build \
&& cmake .. && sudo make -j && sudo make install
# Environment variable for RGLGazeboPlugin
-ENV GZ_GUI_PLUGIN_PATH=/home/wheelchair2/RGLGazeboPlugin/install/RGLVisualize
-ENV GZ_SIM_SYSTEM_PLUGIN_PATH=/home/wheelchair2/RGLGazeboPlugin/install/RGLServerPlugin
-ENV RGL_PATTERNS_DIR=/home/wheelchair2/RGLGazeboPlugin/lidar_patterns
+ENV GZ_GUI_PLUGIN_PATH=/home/$USERNAME/RGLGazeboPlugin/install/RGLVisualize
+ENV GZ_SIM_SYSTEM_PLUGIN_PATH=/home/$USERNAME/RGLGazeboPlugin/install/RGLServerPlugin
+ENV RGL_PATTERNS_DIR=/home/$USERNAME/RGLGazeboPlugin/lidar_patterns
COPY pythonPkgs.list /tmp/pythonPkgs.list
RUN sudo apt-get update \
@@ -104,5 +106,7 @@ RUN sudo apt-get update \
RUN echo 'export TERM="xterm-256color"' | sudo tee -a ~/.bashrc > /dev/null && \
echo "export PS1='\\[\\033[01;32m\\]\\u@\\h:\\[\\033[01;34m\\]\\w\\$\\[\\033[00m\\] '" | sudo tee -a ~/.bashrc > /dev/null
+COPY .tmux.conf /home/wheelchair2/.tmux.conf
+
# Environment variable for map folder
-ENV MAP_DIR=/home/wheelchair2/wheelchair2/src/wheelchair2_navigation/maps
\ No newline at end of file
+ENV MAP_DIR=/home/$USERNAME/wheelchair2/src/wheelchair2_navigation/maps
\ No newline at end of file
diff --git a/ROS2/Jetson/humble_jetson/Dockerfile b/ROS2/Jetson/humble_jetson/Dockerfile
index 8f65d65..14a4702 100644
--- a/ROS2/Jetson/humble_jetson/Dockerfile
+++ b/ROS2/Jetson/humble_jetson/Dockerfile
@@ -29,20 +29,17 @@ RUN echo 'Asia/Kolkata' > /etc/timezone && \
RUN apt-get update && apt-get install -q -y --no-install-recommends \
dirmngr \
gnupg2 \
+ curl \
+ ca-certificates \
&& rm -rf /var/lib/apt/lists/*
-# setup keys
-RUN set -eux; \
- key='C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654'; \
- export GNUPGHOME="$(mktemp -d)"; \
- gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
- mkdir -p /usr/share/keyrings; \
- gpg --batch --export "$key" > /usr/share/keyrings/ros2-latest-archive-keyring.gpg; \
- gpgconf --kill all; \
- rm -rf "$GNUPGHOME"
-
-# setup sources.list
-RUN echo "deb [ signed-by=/usr/share/keyrings/ros2-latest-archive-keyring.gpg ] http://packages.ros.org/ros2/ubuntu jammy main" > /etc/apt/sources.list.d/ros2-latest.list
+# Setup ROS Apt sources
+RUN curl -L -s -o /tmp/ros2-apt-source.deb https://github.com/ros-infrastructure/ros-apt-source/releases/download/1.1.0/ros2-apt-source_1.1.0.jammy_all.deb \
+ && echo "1600cb8cc28258a39bffc1736a75bcbf52d1f2db371a4d020c1b187d2a5a083b /tmp/ros2-apt-source.deb" | sha256sum --strict --check \
+ && apt-get update \
+ && apt-get install /tmp/ros2-apt-source.deb \
+ && rm -f /tmp/ros2-apt-source.deb \
+ && rm -rf /var/lib/apt/lists/*
# setup environment
ENV LANG=C.UTF-8
diff --git a/ROS2/Jetson/wheelchair2_base_jetson/.tmux.conf b/ROS2/Jetson/wheelchair2_base_jetson/.tmux.conf
new file mode 100644
index 0000000..ef5c78d
--- /dev/null
+++ b/ROS2/Jetson/wheelchair2_base_jetson/.tmux.conf
@@ -0,0 +1,24 @@
+# Minimal tmux configuration for scrolling support
+# Save this as .tmux.conf
+
+# Enable mouse support (includes scrolling)
+set -g mouse on
+
+# Increase scrollback buffer size from default 2000 to 10000
+set -g history-limit 10000
+
+# Enable mouse wheel scrolling in copy mode and normal mode
+bind -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'select-pane -t=; copy-mode -e; send-keys -M'"
+bind -n WheelDownPane select-pane -t= \; send-keys -M
+
+# Vi-style copy mode (optional but recommended)
+setw -g mode-keys vi
+
+# Easy access to copy mode with Page Up
+bind -n Pageup copy-mode -u
+
+# Shift + Page Up for copy mode (alternative)
+bind -n S-Pageup copy-mode -u
+
+# Shift + Page Down to exit copy mode
+bind -n S-Pagedown send-keys Pagedown
\ No newline at end of file
diff --git a/ROS2/Jetson/wheelchair2_base_jetson/Dockerfile b/ROS2/Jetson/wheelchair2_base_jetson/Dockerfile
index 1074809..d4916cb 100644
--- a/ROS2/Jetson/wheelchair2_base_jetson/Dockerfile
+++ b/ROS2/Jetson/wheelchair2_base_jetson/Dockerfile
@@ -1,4 +1,4 @@
-FROM ghcr.io/smart-wheelchair-rrc/humble_jetson:latest
+FROM ghcr.io/smart-wheelchair-rrc/humble_jetson:v3.0
ARG USERNAME=container_user
@@ -35,7 +35,7 @@ RUN sudo apt-get update \
# Build and install Realsense-SDK
WORKDIR /home/$USERNAME
-RUN git clone --branch v2.56.2 https://github.com/IntelRealSense/librealsense.git
+RUN git clone --depth=1 --progress --verbose --branch v2.56.2 https://github.com/IntelRealSense/librealsense.git
WORKDIR /home/$USERNAME/librealsense
RUN sudo mkdir -p /etc/udev/rules.d && \
./scripts/setup_udev_rules.sh \
@@ -46,7 +46,7 @@ RUN mkdir build && cd build \
# Build and install Livox-SDK2
WORKDIR /home/$USERNAME
-RUN git clone https://github.com/rtarun1/Livox-SDK2.git
+RUN git clone --depth=1 --progress --verbose https://github.com/rtarun1/Livox-SDK2.git
RUN cd Livox-SDK2 \
&& mkdir build \
&& cd build \
@@ -77,5 +77,7 @@ RUN sudo apt-get update \
RUN echo 'export TERM="xterm-256color"' | sudo tee -a ~/.bashrc > /dev/null && \
echo "export PS1='\\[\\033[01;32m\\]\\u@\\h:\\[\\033[01;34m\\]\\w\\$\\[\\033[00m\\] '" | sudo tee -a ~/.bashrc > /dev/null
+COPY .tmux.conf /home/wheelchair2/.tmux.conf
+
# Environment variable for map folder
ENV MAP_DIR=/home/$USERNAME/wheelchair2/src/wheelchair2_navigation/maps
\ No newline at end of file