Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d655441
Add vendor-agnostic wgpu compute backend
naitikpahwa18 Mar 16, 2026
bbf0a1e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 16, 2026
e812a99
add CUDA backend with runtime selection, rustfft migration
naitikpahwa18 Mar 18, 2026
4f9ad66
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 18, 2026
494b0df
Add Zero-Padding & Remove CPU Fallback
naitikpahwa18 Apr 13, 2026
e74f7f5
Merge branch 'ros2' into wgpu_integration
woensug-choi Apr 21, 2026
b15574d
Add Demo Guide to run Multi-Backend
naitikpahwa18 May 20, 2026
7402f0c
working update for macosx
woensug-choi May 22, 2026
6aef91c
debugFlag wgpu + Fix formatting
naitikpahwa18 May 25, 2026
9a08fa9
fix: preserve range axis after padded WGPU FFT
yeseorizi Sep 8, 2026
050244d
docs: record WGPU range-axis validation
yeseorizi Sep 8, 2026
8d103cd
Merge ros2 into WGPU integration for Lyrical and Jetty
yeseorizi Sep 18, 2026
14558f1
Make WGPU sonar runtime portable on macOS
yeseorizi Sep 18, 2026
720eb3d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 18, 2026
a9be805
fix: resolve multibeam sonar CMake lint failures
woensug-choi Sep 23, 2026
6908e81
ci: run Docker builds for all ros2 pull requests
woensug-choi Sep 23, 2026
272d8a0
fix: order sonar builds and export the installed WGPU library
woensug-choi Sep 23, 2026
5253159
ci: use Ubuntu 26.04 and publish PR-number Docker images
woensug-choi Sep 23, 2026
997c83f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 23, 2026
c4139b5
fix: make ROS bootstrap downloads deterministic in Docker builds
woensug-choi Sep 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .docker/lyrical.arm64v8.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# setup below is the adapted version of what that base image contained, plus the xrdp
# group-permission fix required by the verified Apple Silicon build.
# - ROS_DISTRO=lyrical; ros-lyrical-ros-gz supplies the Gazebo Jetty vendor packages.
# - The current CUDA sonar remains disabled on ARM64; the open WGPU PR is intentionally excluded.
# - The sonar uses the portable WGPU backend when CUDA is unavailable on ARM64.
# - ArduSub SITL includes the Python 3.14 compatibility shims validated on Ubuntu 26.04
# (imp/pipes modules, python-argparse removal, and PEP 668 handling).

Expand Down Expand Up @@ -96,13 +96,15 @@ EXPOSE 22/tcp

# --- ROS 2 Lyrical + Gazebo Jetty ---
ARG ROS_DISTRO="lyrical"
ARG ROS_APT_SOURCE_VERSION="1.3.0"
ENV GZ_VERSION=jetty

RUN apt update && apt full-upgrade -y && apt autoremove -y

# Gazebo Jetty is vendored by ros-lyrical-ros-gz on apt already — no separate Gazebo source build
RUN export ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F\" '{print $4}') && \
curl -L -o /tmp/ros2-apt-source.deb \
# Pin the bootstrap package to avoid unauthenticated GitHub API rate limits.
RUN curl --fail --show-error --location --retry 5 --retry-delay 2 \
-o /tmp/ros2-apt-source.deb \
"https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb" && \
dpkg -i /tmp/ros2-apt-source.deb && \
apt update && \
Expand Down
36 changes: 19 additions & 17 deletions .github/workflows/docker-amd64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,6 @@ on:
workflow_dispatch:
pull_request:
branches: [ros2]
paths:
- ".docker/**"
- ".dockerignore"
- ".github/workflows/docker-amd64.yml"
- "dave_interfaces/**"
- "examples/**"
- "extras/**"
- "gazebo/**"
- "models/**"
- "README.md"
push:
tags: ["*"]
branches: [ros2, dockertest]
Expand All @@ -30,15 +20,14 @@ concurrency:

jobs:
build-and-push-to-docker-hub:
# Never execute untrusted fork code on a self-hosted runner.
if: >-
github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository
runs-on: [self-hosted, x64]
timeout-minutes: 1440
# Validate all PRs on disposable hosted runners, including fork PRs.
# Keep publishing builds on the existing self-hosted runner.
runs-on: >-
${{ fromJSON(github.event_name == 'pull_request'
&& '["ubuntu-26.04"]' || '["self-hosted", "x64"]') }}
timeout-minutes: ${{ github.event_name == 'pull_request' && 360 || 1440 }}
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
Expand Down Expand Up @@ -70,9 +59,22 @@ jobs:
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
outputs: >-
${{ github.event_name == 'pull_request'
&& format('type=oci,dest={0}/pr-image.tar', runner.temp) || '' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
file: .docker/lyrical.amd64.dockerfile
platforms: linux/amd64
build-args: |
ROS_DISTRO=${{ env.ROS_DISTRO }}

- name: Upload PR image for trusted publishing
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: dave-pr-image-amd64
path: ${{ runner.temp }}/pr-image.tar
if-no-files-found: error
compression-level: 0
retention-days: 3
38 changes: 20 additions & 18 deletions .github/workflows/docker-arm64v8.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,6 @@ on:
workflow_dispatch:
pull_request:
branches: [ros2]
paths:
- ".docker/**"
- ".dockerignore"
- ".github/workflows/docker-arm64v8.yml"
- "dave_interfaces/**"
- "examples/**"
- "extras/**"
- "gazebo/**"
- "models/**"
- "README.md"
push:
tags: ["*"]
branches: [ros2, dockertest]
Expand All @@ -30,15 +20,14 @@ concurrency:

jobs:
build-and-push-to-docker-hub:
# Never execute untrusted fork code on a self-hosted runner.
if: >-
github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository
runs-on: [self-hosted, ARM64]
timeout-minutes: 1440
# Validate all PRs on disposable hosted runners, including fork PRs.
# Keep publishing builds on the existing self-hosted runner.
runs-on: >-
${{ fromJSON(github.event_name == 'pull_request'
&& '["ubuntu-26.04-arm"]' || '["self-hosted", "ARM64"]') }}
timeout-minutes: ${{ github.event_name == 'pull_request' && 360 || 1440 }}
permissions:
contents: read
packages: write
steps:
- name: Configure non-interactive Docker credentials
run: |
Expand All @@ -57,7 +46,7 @@ jobs:
# open Docker Desktop's interactive Keychain credential helper.
# The native driver avoids that dependency for this single-platform
# ARM64 build and works with Docker Desktop's containerd image store.
driver: docker
driver: ${{ github.event_name == 'pull_request' && 'docker-container' || 'docker' }}

- name: Configure Docker Hub authentication
if: github.event_name != 'pull_request'
Expand Down Expand Up @@ -95,13 +84,26 @@ jobs:
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
outputs: >-
${{ github.event_name == 'pull_request'
&& format('type=oci,dest={0}/pr-image.tar', runner.temp) || '' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
file: .docker/lyrical.arm64v8.dockerfile
platforms: linux/arm64/v8
build-args: |
ROS_DISTRO=${{ env.ROS_DISTRO }}

- name: Upload PR image for trusted publishing
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: dave-pr-image-arm64
path: ${{ runner.temp }}/pr-image.tar
if-no-files-found: error
compression-level: 0
retention-days: 3

- name: Clear Docker Hub credentials
if: always() && github.event_name != 'pull_request'
run: printf '{}\n' > "$DOCKER_CONFIG/config.json"
173 changes: 173 additions & 0 deletions .github/workflows/docker-pr-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
---
name: Publish PR Docker images

# This workflow must be on ros2 (the default branch) to receive workflow_run.
# Never check out or execute PR code here: only copy completed image archives.
# yamllint disable-line rule:truthy
on:
workflow_run:
workflows:
- Build Lyrical / Jetty Docker image (AMD64)
- Build Lyrical / Jetty Docker image (ARM64)
types: [completed]
workflow_dispatch:
inputs:
run_id:
description: Successful PR Docker build run ID to publish
required: true
type: string

permissions:
actions: read
contents: read
pull-requests: read

concurrency:
group: publish-pr-docker-images
cancel-in-progress: false

jobs:
identify:
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success')
runs-on: ubuntu-26.04
outputs:
ready: ${{ steps.builds.outputs.ready }}
pr: ${{ steps.builds.outputs.pr }}
sha: ${{ steps.builds.outputs.sha }}
amd64_run: ${{ steps.builds.outputs.amd64_run }}
arm64_run: ${{ steps.builds.outputs.arm64_run }}
steps:
- name: Verify current PR and successful builds for both architectures
id: builds
uses: actions/github-script@v7
with:
script: |
const repo = context.repo;
const id = String(context.payload.workflow_run?.id || context.payload.inputs?.run_id || '');
if (!/^\d+$/.test(id)) throw new Error('Invalid build run ID');
const {data: source} = await github.rest.actions.getWorkflowRun({...repo, run_id: Number(id)});
const files = {amd64: 'docker-amd64.yml', arm64: 'docker-arm64v8.yml'};
if (source.event !== 'pull_request' || source.conclusion !== 'success' ||
!Object.values(files).some(file => source.path === `.github/workflows/${file}`)) {
throw new Error('Expected a successful PR Docker build in this repository');
}
// Fork runs can have an empty pull_requests array. Resolve the PR via the API.
const prs = await github.paginate(github.rest.pulls.list, {
...repo, state: 'open', base: 'ros2',
head: `${source.head_repository.owner.login}:${source.head_branch}`, per_page: 100
});
const matches = prs.filter(pr => pr.head.sha === source.head_sha &&
pr.head.repo?.full_name === source.head_repository.full_name);
if (matches.length !== 1) {
core.notice('Build is no longer the current head of an open ros2 PR');
return;
}
const selected = {};
for (const [arch, workflow_id] of Object.entries(files)) {
const {data} = await github.rest.actions.listWorkflowRuns({
...repo, workflow_id, event: 'pull_request', head_sha: source.head_sha,
status: 'success', per_page: 100
});
const run = data.workflow_runs.find(candidate =>
candidate.head_repository?.full_name === source.head_repository.full_name);
if (!run) {
core.notice(`Waiting for a successful ${arch} build of this revision`);
return;
}
const artifacts = await github.paginate(github.rest.actions.listWorkflowRunArtifacts, {
...repo, run_id: run.id, per_page: 100
});
if (!artifacts.some(item => item.name === `dave-pr-image-${arch}` && !item.expired)) {
throw new Error(`Missing ${arch} image artifact in run ${run.id}`);
}
selected[arch] = run.id;
}
core.setOutput('pr', matches[0].number);
core.setOutput('sha', source.head_sha);
core.setOutput('amd64_run', selected.amd64);
core.setOutput('arm64_run', selected.arm64);
core.setOutput('ready', 'true');

publish:
needs: identify
if: needs.identify.outputs.ready == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 120
env:
IMAGE_NAME: ioeslab/dave
PR_NUMBER: ${{ needs.identify.outputs.pr }}
SOURCE_SHA: ${{ needs.identify.outputs.sha }}
steps:
- name: Install image-copy tool
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends skopeo

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Download AMD64 image from its verified build
uses: actions/download-artifact@v4
with:
name: dave-pr-image-amd64
path: ${{ runner.temp }}/amd64
run-id: ${{ needs.identify.outputs.amd64_run }}
github-token: ${{ github.token }}

- name: Publish AMD64 image without running it
run: |
archive="$RUNNER_TEMP/amd64/pr-image.tar"
skopeo inspect --config "oci-archive:$archive" | \
jq -e '.os == "linux" and .architecture == "amd64"'
skopeo copy --all --authfile "$HOME/.docker/config.json" \
"oci-archive:$archive" "docker://$IMAGE_NAME:pr-$PR_NUMBER-amd64-$SOURCE_SHA"
rm -- "$archive"

- name: Download ARM64 image from its verified build
uses: actions/download-artifact@v4
with:
name: dave-pr-image-arm64
path: ${{ runner.temp }}/arm64
run-id: ${{ needs.identify.outputs.arm64_run }}
github-token: ${{ github.token }}

- name: Publish ARM64 image without running it
run: |
archive="$RUNNER_TEMP/arm64/pr-image.tar"
skopeo inspect --override-arch arm64 --config "oci-archive:$archive" | \
jq -e '.os == "linux" and .architecture == "arm64"'
skopeo copy --all --authfile "$HOME/.docker/config.json" \
"oci-archive:$archive" "docker://$IMAGE_NAME:pr-$PR_NUMBER-arm64-$SOURCE_SHA"
rm -- "$archive"

- name: Check that the PR still points to this revision
uses: actions/github-script@v7
with:
script: |
const {data: pr} = await github.rest.pulls.get({
...context.repo, pull_number: Number(process.env.PR_NUMBER)
});
if (pr.state !== 'open' || pr.base.ref !== 'ros2' || pr.head.sha !== process.env.SOURCE_SHA) {
throw new Error('PR changed during publishing; leaving its current tags unchanged');
}

- name: Publish PR-number tags and multi-platform manifest
run: |
docker buildx imagetools create --tag "$IMAGE_NAME:pr-$PR_NUMBER-amd64" \
"$IMAGE_NAME:pr-$PR_NUMBER-amd64-$SOURCE_SHA"
docker buildx imagetools create --tag "$IMAGE_NAME:pr-$PR_NUMBER-arm64" \
"$IMAGE_NAME:pr-$PR_NUMBER-arm64-$SOURCE_SHA"
docker buildx imagetools create --tag "$IMAGE_NAME:pr-$PR_NUMBER" \
"$IMAGE_NAME:pr-$PR_NUMBER-amd64-$SOURCE_SHA" \
"$IMAGE_NAME:pr-$PR_NUMBER-arm64-$SOURCE_SHA"
printf 'Published %s:pr-%s for %s (AMD64 + ARM64).\n' \
"$IMAGE_NAME" "$PR_NUMBER" "$SOURCE_SHA" >> "$GITHUB_STEP_SUMMARY"
6 changes: 4 additions & 2 deletions extras/ros-lyrical-gz-jetty-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ sudo apt update && sudo apt install -y jq
# shellcheck disable=SC1091
. /etc/os-release
UBUNTU_CODENAME="${UBUNTU_CODENAME:-${VERSION_CODENAME}}"
ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | jq -r '.tag_name') && \
curl -L -o /tmp/ros2-apt-source.deb \
# Use a known release instead of a rate-limited unauthenticated API lookup.
ROS_APT_SOURCE_VERSION="${ROS_APT_SOURCE_VERSION:-1.3.0}"
curl --fail --show-error --location --retry 5 --retry-delay 2 \
-o /tmp/ros2-apt-source.deb \
"https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.${UBUNTU_CODENAME}_all.deb" && \
sudo apt-get install -y /tmp/ros2-apt-source.deb && \
rm -f /tmp/ros2-apt-source.deb
Expand Down
Loading
Loading