diff --git a/.env.example b/.env.example index 2e3a6f6..016ed6e 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,9 @@ DISPLAY=:1 HOST_DATA_PATH=./data +# Default base image avoids anonymous Docker Hub pull-rate limits. +BASE_IMAGE=public.ecr.aws/ubuntu/ubuntu:22.04 + # These versions mirror the upstream event-driven Dockerfile as a starting point. YCM_VERSION=v0.15.2 YARP_VERSION=v3.8.0 diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml new file mode 100644 index 0000000..d8a30c5 --- /dev/null +++ b/.github/workflows/publish-image.yml @@ -0,0 +1,58 @@ +name: Publish image to GHCR + +on: + workflow_dispatch: + push: + branches: + - main + - master + tags: + - "v*" + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract image metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=tag + type=sha,prefix=sha- + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: true + platforms: linux/amd64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/test-image-build.yml b/.github/workflows/test-image-build.yml new file mode 100644 index 0000000..23aa73c --- /dev/null +++ b/.github/workflows/test-image-build.yml @@ -0,0 +1,44 @@ +name: Test image build + +on: + workflow_dispatch: + pull_request: + +jobs: + build-and-smoke-test: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + load: true + tags: primi-iit-docker:test + platforms: linux/amd64 + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Smoke test installed tools + run: | + docker run --rm --entrypoint bash primi-iit-docker:test -lc ' + set -euo pipefail + command -v yarp >/dev/null + command -v yarpmanager >/dev/null + command -v yarpview >/dev/null + command -v yarpscope >/dev/null + command -v yarpdataplayer >/dev/null + command -v vFramer >/dev/null + command -v start-yarpserver >/dev/null + command -v container-entrypoint >/dev/null + yarp check + ' diff --git a/DEVELOPER_README.md b/DEVELOPER_README.md new file mode 100644 index 0000000..77907a2 --- /dev/null +++ b/DEVELOPER_README.md @@ -0,0 +1,438 @@ +# Developer README + +This guide is for maintainers and contributors. It covers the repository structure, the current launch model, image/build details, and the current GitHub Actions + GHCR distribution path. + +For a file-by-file inventory of scripts, env files, build files, `yarpmanager` configs, and automation, see [REPOSITORY_REFERENCE.md](REPOSITORY_REFERENCE.md). + +## Goals + +This repo intentionally allows multiple user-facing entrypoints: + +- menu +- direct CLI scripts +- `yarpmanager` +- manual shell / YARP + +The policy is: + +- redundancy in access methods is acceptable +- hidden implementation layers should not be duplicated unnecessarily +- `yarpmanager` applications should launch the applications themselves, not `bash` wrappers +- deprecated launch wrappers should be removed when they stop carrying their own behavior + +## Current Architecture + +### Runtime Layers + +- [Dockerfile](Dockerfile): builds the workstation image +- [compose.yaml](compose.yaml): runs the single `robotology` container +- [container-entrypoint.sh](container-scripts/container-entrypoint.sh): remaps the in-container user to the host UID/GID +- [start-yarpserver.sh](container-scripts/start-yarpserver.sh): starts `yarpserver` inside the container + +### Operator-Facing Layers + +- [workstation-menu.sh](scripts/workstation-menu.sh): guided operator menu +- [common.sh](scripts/common.sh): shared host-side Docker and launcher helpers +- public scripts under [scripts](scripts/): stable CLI entrypoints +- internal script launchers under [scripts/internal](scripts/internal/): shell-only orchestration that still carries meaningful behavior +- `yarpmanager` apps under [yarpmanager/applications](yarpmanager/applications/): direct application launches + +### Current Launch Engines + +There are two real launch engines now: + +1. `yarpmanager` XML apps + - generic tools and BallBalance demos launch the applications directly + - the BallBalance manager apps use native dependencies and connections + +2. script-based internal launchers + - [launch-ballbalance-demo.sh](scripts/internal/launch-ballbalance-demo.sh) + - [launch-ballbalance-tool.sh](scripts/internal/launch-ballbalance-tool.sh) + - [launch-vframer.sh](scripts/internal/launch-vframer.sh) + - these are still useful because they add cleanup, waiting, retries, or script-only configuration + +The old generic `yarpmanager/bin` wrapper layer was removed because it no longer added behavior. + +## How The Stack Works + +The runtime defined in [compose.yaml](compose.yaml) does five important things: + +1. builds and runs a single `robotology` container +2. shares the host network with `network_mode: host` +3. mounts the project at `/workspace/project` +4. mounts the user data folder at `/workspace/data` +5. forwards X11 so GUI programs from the container can open on the host desktop + +The helper layer in [common.sh](scripts/common.sh) standardizes: + +- Docker availability checks +- Compose calls with the current host `UID` and `GID` +- execution as the `robotology` user inside the container +- `yarpserver` startup and detection +- GUI launcher behavior + +## Important Configuration + +The main operator-facing configuration lives in: + +- [`.env.example`](.env.example) +- [`.env`](.env) + +The most important values are: + +- `DISPLAY` +- `HOST_DATA_PATH` +- `BASE_IMAGE` +- `YCM_VERSION` +- `YARP_VERSION` +- `ED_VERSION` + +### `BASE_IMAGE` + +[Dockerfile](Dockerfile) now uses a configurable base image: + +```dockerfile +ARG BASE_IMAGE=public.ecr.aws/ubuntu/ubuntu:22.04 +FROM ${BASE_IMAGE} +``` + +and [compose.yaml](compose.yaml) passes that through as a build arg. + +This keeps Ubuntu 22.04 compatibility while avoiding anonymous Docker Hub pull-rate limits by default. + +### `vFramer` Defaults + +There are intentionally two configuration points now, because there are still two real launch engines: + +- `yarpmanager` `VFramer` app: [04-vframer.xml](yarpmanager/applications/04-vframer.xml) +- script-based `vFramer` launcher: [defaults.env](yarpmanager/defaults.env) + +Keep them aligned when changing defaults. + +## Developer Workflows + +Build: + +```bash +./scripts/build.sh +``` + +Start workstation: + +```bash +./scripts/start-workstation.sh +``` + +Open shell: + +```bash +./scripts/shell.sh +``` + +Verify repo launch definitions: + +```bash +./scripts/verify-repo.sh +``` + +Useful manual checks inside the container: + +```bash +yarp check +yarp detect +yarp name list +``` + +## Launch-Model Notes + +### Generic Tools + +The generic `yarpmanager` applications are direct-launch only: + +- [01-yarp-data-player.xml](yarpmanager/applications/01-yarp-data-player.xml) +- [02-yarp-scope.xml](yarpmanager/applications/02-yarp-scope.xml) +- [03-yarp-view.xml](yarpmanager/applications/03-yarp-view.xml) +- [04-vframer.xml](yarpmanager/applications/04-vframer.xml) +- [05-all-tools.xml](yarpmanager/applications/05-all-tools.xml) + +### BallBalance + +BallBalance is intentionally available via two approaches: + +- script-based demos from the public CLI wrappers +- direct-launch `yarpmanager` demos + +Those duplicate some session metadata, but the duplication is currently justified because the script path still carries behavior that the manager path does not: + +- pre-cleanup of matching old GUI/demo tools +- explicit waits for ports +- retry logic for connections + +If this behavior ever gets unified elsewhere, that duplicated session metadata should be reduced. + +## GitHub Distribution + +This repository now includes two GitHub Actions workflows: + +- [.github/workflows/test-image-build.yml](.github/workflows/test-image-build.yml): build-only CI that verifies the image can be built and smoke-tested without publishing +- [.github/workflows/publish-image.yml](.github/workflows/publish-image.yml): publish workflow that pushes the built image to GitHub Container Registry + +### Goal + +Build the image in GitHub Actions and publish it to GitHub Container Registry so normal users can pull it instead of building locally. + +Target image naming: + +```text +ghcr.io//: +``` + +Examples: + +```text +ghcr.io/my-org/primi_iit_docker:latest +ghcr.io/my-org/primi_iit_docker:v1.0.0 +ghcr.io/my-org/primi_iit_docker:main +``` + +### Why This Helps + +- avoids asking every user to run a heavy local build +- reduces exposure to upstream registry rate limits during normal use +- makes GitHub the practical distribution point for the workstation +- still keeps the Dockerfile as the source of truth + +### Current Workflow Shape + +Build-only workflow: + +- name: `Test image build` +- triggers: `workflow_dispatch`, `pull_request` +- behavior: builds the image with Buildx, loads it into the runner, and smoke-tests the installed binaries without pushing anything + +Publish workflow: + +Current triggers: + +- `workflow_dispatch` while the repo is still evolving +- pushes to `main` and `master` +- tag pushes like `v*` for releases + +Current job permissions: + +- `contents: read` +- `packages: write` + +Current workflow steps: + +1. checkout the repository +2. set up Docker Buildx +3. log in to `ghcr.io` using `${{ secrets.GITHUB_TOKEN }}` +4. derive tags and labels +5. build from [Dockerfile](Dockerfile) +6. push to `ghcr.io/${{ github.repository }}` + +The workflow builds from the Dockerfile defaults, so changing the Dockerfile or build defaults in the repo affects both local builds and GitHub-published images. + +### Current Tagging Policy + +- `vX.Y.Z` on releases +- `latest` on the default branch +- branch tags such as `main` or `master` +- `sha-...` tags for exact workflow outputs + +Stable users should pull release tags. Maintainers and testers can use `latest` or `main`. + +### Runner Behavior + +GitHub-hosted runners are the intended build environment for this workflow. That is useful here because GitHub’s official Docker publishing guidance explicitly calls out GitHub-hosted runners as the supported publishing path, and they are not affected the same way as your local anonymous Docker Hub build path. + +### Current User Distribution Flow + +Today, users typically do: + +```bash +./scripts/build.sh +./scripts/start-workstation.sh +``` + +After GHCR publishing is in place, the preferred user path becomes: + +```bash +docker pull ghcr.io//:latest +./scripts/start-workstation.sh +``` + +or later, if Compose is updated to support pull-first distribution more explicitly: + +```bash +docker compose pull +./scripts/start-workstation.sh +``` + +### GitHub-Side Setup Still Required + +1. Push this repository to GitHub with Actions enabled. +2. Run the workflow once manually or push to `main` / `master` / a `v*` tag. +3. Confirm the GHCR package appears under the repository owner namespace. +4. Set the GHCR package visibility to public if you want anonymous pulls. + +### Workflow Files + +Build-only workflow: + +```yaml +name: Test image build + +on: + workflow_dispatch: + pull_request: + +jobs: + build-and-smoke-test: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Build image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + load: true + tags: primi-iit-docker:test + platforms: linux/amd64 + cache-from: type=gha + cache-to: type=gha,mode=max + - name: Smoke test installed tools + run: | + docker run --rm --entrypoint bash primi-iit-docker:test -lc ' + set -euo pipefail + command -v yarp >/dev/null + command -v yarpmanager >/dev/null + command -v yarpview >/dev/null + command -v yarpscope >/dev/null + command -v yarpdataplayer >/dev/null + command -v vFramer >/dev/null + command -v start-yarpserver >/dev/null + command -v container-entrypoint >/dev/null + yarp check + ' +``` + +Publish workflow: + +This is the current workflow: + +```yaml +name: Publish image to GHCR + +on: + workflow_dispatch: + push: + branches: + - main + - master + tags: + - "v*" + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Extract image metadata + uses: docker/metadata-action@v5 + id: meta + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=tag + type=sha,prefix=sha- + type=raw,value=latest,enable={{is_default_branch}} + - name: Build and push image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: true + platforms: linux/amd64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max +``` + +### What To Test + +Local repository checks: + +1. Run `./scripts/verify-repo.sh`. +2. Run `docker compose config` and confirm the build args and service config still resolve correctly. +3. Read [README.md](README.md), [USER_README.md](USER_README.md), and [DEVELOPER_README.md](DEVELOPER_README.md) on GitHub or in a Markdown preview and verify the links render correctly. + +GitHub workflow checks: + +1. Open the Actions tab and confirm both `Test image build` and `Publish image to GHCR` appear. +2. Run `Test image build` manually with `workflow_dispatch`. +3. Confirm the build-only workflow logs show successful checkout, Buildx setup, image build, and smoke test. +4. Confirm the build-only workflow does not create or update any GHCR package. +5. Run `Publish image to GHCR` manually with `workflow_dispatch` or trigger it from `main` / `master` / a `v*` tag. +6. Confirm the publish workflow logs show successful checkout, GHCR login, metadata generation, build, and push. +7. Confirm the package is created at `ghcr.io//`. +8. Confirm the expected tags exist: `latest` on the default branch, branch tags like `main`, release tags like `v1.0.0`, and `sha-...`. +9. Confirm both workflows use the Dockerfile in the repo root and build `linux/amd64`. +10. Confirm later runs reuse the GitHub Actions cache instead of rebuilding every layer from scratch. + +GHCR pull checks: + +1. If the package is public, run `docker pull ghcr.io//:latest` from a clean machine or a shell without prior local state. +2. Run `docker image inspect ghcr.io//:latest` and confirm the image exists locally afterward. +3. Optionally pull a release tag like `ghcr.io//:v1.0.0` and compare it to `latest`. + +Runtime checks after pulling: + +1. Decide whether you want to keep using the local build path or test a pull-first path manually. +2. If testing a pull-first path manually, tag the pulled image to the local Compose image name if needed, then run `./scripts/start-workstation.sh`. +3. Open `yarpmanager` and launch a BallBalance demo. +4. Open the script-based demo path and make sure it still behaves correctly. +5. Confirm the GUI tools open and `yarpserver` is detected. + +## References + +Official GitHub references for the GHCR workflow: + +- Publishing Docker images with GitHub Actions: https://docs.github.com/actions/guides/publishing-docker-images +- Working with the GitHub Container registry: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry +- Package access and visibility for GHCR: https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility + +## Known Limits + +- the current image still assumes the Prophesee / Metavision SDK path from the upstream `event-driven` Dockerfile +- the exact live camera vendor is still a hardware-specific unknown +- scripted BallBalance demos intentionally pre-clean matching GUI/demo tools before launch +- manager-launched BallBalance demos do not pre-clean matching GUI/demo tools before launch +- `All Tools` is generic and not dataset-aware diff --git a/Dockerfile b/Dockerfile index 3b95363..3646e24 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,10 @@ -FROM ubuntu:jammy +ARG BASE_IMAGE=public.ecr.aws/ubuntu/ubuntu:22.04 +FROM ${BASE_IMAGE} ENV DEBIAN_FRONTEND=noninteractive ARG CODE_DIR=/usr/local/src +ARG BASE_IMAGE ARG YCM_VERSION=v0.15.2 ARG YARP_VERSION=v3.8.0 ARG ED_VERSION=master diff --git a/README.md b/README.md index c03411a..c969d71 100644 --- a/README.md +++ b/README.md @@ -1,479 +1,17 @@ # PRIMI IIT Dockerized YARP + Event-Driven Workstation -This project provides a Dockerized `YARP` + `event-driven` workstation with: +This repository provides a Dockerized `YARP` + `event-driven` workstation with: - one reusable Ubuntu-based image - GUI tool support on the host desktop -- a fixed data mount inside the container - helper scripts for non-expert users - `yarpmanager` applications for the same tools and demos -On this machine, the current host dataset root is: +Choose the guide that matches your role: -```text -/home/bmaacaron-iit.local/Documents/Datasets/2026_PRIMI/ -``` +- [User README](USER_README.md) +- [Developer README](DEVELOPER_README.md) -Inside the container, that appears as: +If you just want to start the workstation and run a demo, go to the [User README](USER_README.md). -```text -/workspace/data -``` - -So the BallBalance dataset is currently available in the container at: - -```text -/workspace/data/BallBalance -``` - -## Using the Docker - -This section is the minimum you need to operate the workstation in its different modes. - -### Installation and Setup - -Another user does need a few host-side tools installed. - -Required on the host: - -- Docker Engine -- Docker Compose plugin -- a desktop session with X11 / XWayland available through `DISPLAY` -- the `xhost` command -- `git` if they still need to clone or update the repository - -Recommended Ubuntu Docker packages: - -- `docker-ce` -- `docker-ce-cli` -- `containerd.io` -- `docker-buildx-plugin` -- `docker-compose-plugin` - -If `xhost` is missing, install: - -- `x11-xserver-utils` - -Users do **not** need to install these on the host: - -- `YARP` -- `event-driven` -- `yarpmanager` -- `yarpview` -- `yarpscope` -- `yarpdataplayer` -- `vFramer` - -Those are installed inside the Docker image from [Dockerfile](Dockerfile). - -Official install references: - -- Docker Engine on Ubuntu: - - https://docs.docker.com/engine/install/ubuntu/ -- Docker Compose plugin on Linux: - - https://docs.docker.com/compose/install/linux/ - -Minimal Ubuntu install flow: - -```bash -sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -sudo usermod -aG docker $USER -newgrp docker -docker info -docker compose version -``` - -If `xhost` is missing: - -```bash -sudo apt install x11-xserver-utils -``` - -Before first use on a new machine: - -1. Copy [`.env.example`](.env.example) to `.env`. -2. Set `HOST_DATA_PATH` to the host folder that should appear in the container as `/workspace/data`. -3. Make sure `DISPLAY` matches the active desktop session. - -### Quickstart - -This is the shortest path from zero to a running demo. - -1. Open a terminal in the project root: - -```bash -cd ~/Documents/Dockers/PRIMI_IIT_Docker -``` - -2. Build the image once: - -```bash -./scripts/build.sh -``` - -3. Start the workstation: - -```bash -./scripts/start-workstation.sh -``` - -4. Open the operator menu: - -```bash -./scripts/workstation-menu.sh -``` - -5. In the menu, choose: - -- `Open yarpmanager` - -6. Inside `yarpmanager`, launch one of: - -- `BallBalance Moving Demo` -- `BallBalance Stationary Demo` - -What opens: - -- `yarpdataplayer` -- `yarpview` -- `yarpscope` -- `vFramer` - -### Current State - -The current implemented behavior is: - -- image build works through `./scripts/build.sh` -- workstation startup works through `./scripts/start-workstation.sh` -- `yarpserver` is automatically detected and started if needed -- GUI tools launch from the container onto the host desktop -- `yarpmanager` is configured with generic tools and BallBalance demos -- BallBalance `moving` and `stationary` demos both work -- user data is exposed read-only at `/workspace/data` - -Important operational behavior: - -- BallBalance demos use `yarpdataplayer` replay outputs under `/yarpdataplayer/...` -- starting a BallBalance demo stops existing `yarpdataplayer`, `yarpview`, `yarpscope`, and `vFramer` processes inside the container before launching the new session -- `All Tools` in `yarpmanager` opens the generic tools, but it does not auto-load a dataset -- the BallBalance demos are the auto-loaded workflows - -### Key Paths - -On the host: - -- project root: `/home/bmaacaron-iit.local/Documents/Dockers/YarpinatorDocker` -- current dataset root: `/home/bmaacaron-iit.local/Documents/Datasets/2026_PRIMI/` - -Inside the container: - -- project root: `/workspace/project` -- user data root: `/workspace/data` -- BallBalance dataset: `/workspace/data/BallBalance` - -### CLI Workflow - -Use this if you want script-based entrypoints without entering the container manually. - -Build: - -```bash -./scripts/build.sh -``` - -Start workstation: - -```bash -./scripts/start-workstation.sh -``` - -Check status: - -```bash -./scripts/status.sh -``` - -List mounted data: - -```bash -./scripts/list-data.sh -``` - -Open generic tools: - -```bash -./scripts/open-manager.sh -./scripts/open-yarpview.sh -./scripts/open-yarpscope.sh -./scripts/open-vframer.sh -./scripts/open-dataplayer.sh -``` - -Run the BallBalance demos: - -```bash -./scripts/demo-ballbalance-moving.sh -./scripts/demo-ballbalance-stationary.sh -``` - -Stop only the demo tools: - -```bash -./scripts/stop-demo.sh -``` - -Stop the whole workstation: - -```bash -./scripts/stop-workstation.sh -``` - -### yarpmanager Workflow - -Launch the manager with: - -```bash -./scripts/open-manager.sh -``` - -Configured applications: - -- `YARP Data Player` -- `YARP Scope` -- `YARP View` -- `VFramer` -- `All Tools` -- `BallBalance Moving Demo` -- `BallBalance Stationary Demo` - -What they mean: - -- `YARP Data Player` - - opens the generic `yarpdataplayer` GUI -- `YARP Scope` - - opens the generic `yarpscope` GUI -- `YARP View` - - opens the generic `yarpview` GUI -- `VFramer` - - opens `vFramer` using the default source in [`yarpmanager/defaults.env`](yarpmanager/defaults.env) -- `All Tools` - - opens the four generic tools together - - does not auto-load a dataset -- `BallBalance Moving Demo` - - auto-loads `test_moving` - - opens the three matching viewers - - uses a coordinated launcher so the viewers do not race each other during startup -- `BallBalance Stationary Demo` - - auto-loads `test_stationary` - - opens the three matching viewers - - uses a coordinated launcher so the viewers do not race each other during startup - -If you want to stop a manager-launched BallBalance session from the CLI, use: - -```bash -./scripts/stop-demo.sh -``` - -### Menu Workflow - -For the simplest interactive operator flow: - -```bash -./scripts/workstation-menu.sh -``` - -The menu exposes: - -- workstation start -- status -- `yarpmanager` -- BallBalance moving demo -- BallBalance stationary demo -- each individual GUI tool -- stop demo only -- list data -- shell -- stop workstation - -### Stopping Things - -There are three stop levels: - -Stop only the BallBalance / GUI demo tools: - -```bash -./scripts/stop-demo.sh -``` - -Stop the whole container: - -```bash -./scripts/stop-workstation.sh -``` - -Stop from inside `yarpmanager`: - -- use the manager’s stop controls for the running application - -### Task Options Table - -This table compares the available ways to do the same task. - -| Task | Simplest CLI | Menu | yarpmanager | Manual shell / YARP | -| --- | --- | --- | --- | --- | -| Build image | `./scripts/build.sh` | not exposed | not applicable | `docker compose build` | -| Start container + `yarpserver` | `./scripts/start-workstation.sh` | `Start workstation` | not the primary path | `docker compose up -d` then `yarpserver` | -| Check runtime status | `./scripts/status.sh` | `Show status` | visual only after launch | `docker compose ps` and `yarp detect` | -| Inspect mounted data | `./scripts/list-data.sh` | `List mounted data` | not applicable | `ls /workspace/data` | -| Open generic tool launcher | `./scripts/open-manager.sh` | `Open yarpmanager` | `yarpmanager` itself | `yarpmanager --from /workspace/project/yarpmanager/ymanager.ini` | -| Open generic `yarpdataplayer` | `./scripts/open-dataplayer.sh` | `Open yarpdataplayer` | `YARP Data Player` | `yarpdataplayer` | -| Open generic `yarpview` | `./scripts/open-yarpview.sh` | `Open yarpview` | `YARP View` | `yarpview` | -| Open generic `yarpscope` | `./scripts/open-yarpscope.sh` | `Open yarpscope` | `YARP Scope` | `yarpscope` | -| Open generic `vFramer` | `./scripts/open-vframer.sh` | `Open vFramer` | `VFramer` | `vFramer --src ...` | -| Open all generic tools | not exposed directly | not exposed directly | `All Tools` | start each tool manually | -| Run BallBalance moving demo | `./scripts/demo-ballbalance-moving.sh` | `Run BallBalance moving demo` | `BallBalance Moving Demo` | manual replay + manual viewer launch | -| Run BallBalance stationary demo | `./scripts/demo-ballbalance-stationary.sh` | `Run BallBalance stationary demo` | `BallBalance Stationary Demo` | manual replay + manual viewer launch | -| Stop demo tools only | `./scripts/stop-demo.sh` | `Stop demo tools only` | stop app in manager | `pkill ...` then `yarp clean --timeout 1` | -| Stop whole workstation | `./scripts/stop-workstation.sh` | `Stop workstation` | close tools, then stop container separately | `docker compose down` | - -## Reference and Extra Details - -This section is not required for normal day-to-day use, but it explains how the project is put together and how to work at a lower level. - -### Core Concepts - -`Docker image` -: the built environment defined by [Dockerfile](Dockerfile) - -`Docker container` -: the running instance of that image - -`docker compose` -: the runtime definition in [compose.yaml](compose.yaml) - -`bind mount` -: a host folder exposed directly inside the container without copying it into the image - -`yarpserver` -: the YARP name server; other YARP tools depend on it to find ports - -`YARP port` -: a named communication endpoint such as `/yarpdataplayer/grabber` - -`yarpmanager` -: a GUI launcher/orchestrator for named applications made of one or more modules - -### How This Stack Works - -The runtime defined in [compose.yaml](compose.yaml) does five important things: - -1. builds and runs a single `robotology` container -2. shares the host network with `network_mode: host` -3. mounts the project at `/workspace/project` -4. mounts the user data folder at `/workspace/data` -5. forwards X11 so GUI programs from the container can open on the host desktop - -The helper layer in [`scripts/common.sh`](scripts/common.sh) standardizes: - -- Docker availability checks -- Compose calls with the current host `UID` and `GID` -- execution as the `robotology` user inside the container -- `yarpserver` startup and detection -- GUI launcher behavior - -The container entrypoint in [`container-scripts/container-entrypoint.sh`](container-scripts/container-entrypoint.sh) remaps the internal `robotology` user to the current host user’s numeric `UID` and `GID` at container start. That helps avoid file ownership problems on bind-mounted folders. - -### Configuration - -The operator-facing configuration lives in: - -- [`.env.example`](.env.example) -- [`.env`](.env) - -The most important values are: - -- `DISPLAY` - - host display used for GUI forwarding -- `HOST_DATA_PATH` - - host folder mounted into the container as `/workspace/data` -- `YCM_VERSION` -- `YARP_VERSION` -- `ED_VERSION` - -### Shell / YARP Workflow - -Use this path if you want manual control. - -Open a shell inside the running container: - -```bash -./scripts/shell.sh -``` - -Useful commands inside the container: - -```bash -yarp check -yarp detect -yarp name list -``` - -What they do: - -- `yarp check` - - basic YARP sanity test -- `yarp detect` - - checks whether `yarpserver` is reachable -- `yarp name list` - - lists the registered YARP ports known to the name server - -### BallBalance Tool Associations - -The current BallBalance associations are: - -| Tool | Dataset / source | Purpose | -| --- | --- | --- | -| `yarpdataplayer` | `/workspace/data/BallBalance/test_moving` or `/workspace/data/BallBalance/test_stationary` | replays the recorded session | -| `yarpview` | `/yarpdataplayer/grabber` | shows the RGB camera stream | -| `yarpscope` | `/yarpdataplayer/icub/right_arm/state:o` | plots the right-arm encoder stream | -| `vFramer` | `/yarpdataplayer/zynqGrabber/left/AE:o` | visualizes the event-camera stream | - -### Troubleshooting - -Docker socket / daemon problems: - -```bash -docker info -``` - -If the daemon is down: - -```bash -sudo systemctl start docker -docker info -``` - -If no GUI window appears, check: - -- `DISPLAY` is set correctly in `.env` -- you are running from a desktop session -- the X11 socket mount exists at `/tmp/.X11-unix` - -If `vFramer` needs a different default source, edit [`yarpmanager/defaults.env`](yarpmanager/defaults.env): - -```bash -VFRAMER_SRC=/event_camera/events:o -``` - -If the host data folder changes, update [`.env`](.env) and re-apply the runtime: - -```bash -./scripts/start-workstation.sh -``` - -### Known Limits - -- the current image assumes the Prophesee / Metavision SDK path from the upstream `event-driven` Dockerfile -- the exact live camera vendor is still a hardware-specific unknown -- BallBalance demos are opinionated workflows; they intentionally clean old replay/viewer processes before starting a new session -- `All Tools` is generic and not dataset-aware +If you need to maintain the image, scripts, `yarpmanager` definitions, or the GitHub Actions / GHCR distribution flow, go to the [Developer README](DEVELOPER_README.md). diff --git a/REPOSITORY_REFERENCE.md b/REPOSITORY_REFERENCE.md new file mode 100644 index 0000000..5376a87 --- /dev/null +++ b/REPOSITORY_REFERENCE.md @@ -0,0 +1,116 @@ +# Repository Reference + +This document is the file-by-file operational reference for the repository. It explains what the runnable scripts, environment files, build files, `yarpmanager` definitions, and automation files do. + +Conventions used below: + +- `public script`: intended to be run directly by a user or operator +- `internal script`: called by another script; usually not the main entrypoint +- `container script`: copied into the Docker image and run inside the container +- `config file`: affects build/runtime behavior but is not itself executable + +## Documentation Files + +| Path | What it does | +| --- | --- | +| [README.md](README.md) | Front page for the repository. It routes readers to the user guide or developer guide. | +| [USER_README.md](USER_README.md) | Operator-facing guide: setup, quickstart, normal workflows, demos, troubleshooting. | +| [DEVELOPER_README.md](DEVELOPER_README.md) | Maintainer-facing guide: architecture, launch model, build/distribution details, and GHCR workflow notes. | +| [REPOSITORY_REFERENCE.md](REPOSITORY_REFERENCE.md) | This file. It is the inventory/reference for scripts, configs, and automation. | + +## Build And Runtime Files + +| Path | Type | What it does | +| --- | --- | --- | +| [Dockerfile](Dockerfile) | config file | Builds the Ubuntu-based workstation image. Installs system dependencies, Prophesee/Metavision SDK, YCM, YARP, `event-driven`, the `robotology` user, and the in-container helper scripts. | +| [compose.yaml](compose.yaml) | config file | Defines the single `robotology` container. Builds from the Dockerfile, uses host networking, mounts the project and data directories, forwards X11, and keeps the container alive with `sleep infinity`. | +| [`.env.example`](.env.example) | config file | Template for the local environment file. Sets the display, host data path, build versions, and default base image. | +| [`.env`](.env) | config file | Local machine-specific copy of `.env.example`. Docker Compose reads this automatically when scripts call `docker compose`. | + +## Public Host Scripts + +These are the main scripts people are expected to run from the host machine. + +| Path | What it does | +| --- | --- | +| [scripts/build.sh](scripts/build.sh) | Runs `docker compose build` after verifying Docker is reachable. This is the normal image-build entrypoint. | +| [scripts/start-workstation.sh](scripts/start-workstation.sh) | Starts the container if needed, ensures `yarpserver` is up, and exits once the workstation is ready. | +| [scripts/start-yarpserver.sh](scripts/start-yarpserver.sh) | Ensures `yarpserver` is running inside the already-started container. It is safe to call repeatedly. | +| [scripts/status.sh](scripts/status.sh) | Shows the Compose service status and reports whether the YARP name server is currently detectable inside the container. | +| [scripts/stop-workstation.sh](scripts/stop-workstation.sh) | Stops and removes the Compose-managed container with `docker compose down`. | +| [scripts/shell.sh](scripts/shell.sh) | Opens an interactive shell inside the running container as the `robotology` user. | +| [scripts/list-data.sh](scripts/list-data.sh) | Prints the mounted container data path and lists the contents of `/workspace/data`. Useful for checking that the host dataset mount is correct. | +| [scripts/open-manager.sh](scripts/open-manager.sh) | Launches `yarpmanager` from the container using the repo’s `ymanager.ini`. | +| [scripts/open-dataplayer.sh](scripts/open-dataplayer.sh) | Launches the generic `yarpdataplayer` GUI from the container. | +| [scripts/open-yarpview.sh](scripts/open-yarpview.sh) | Launches the generic `yarpview` GUI from the container. | +| [scripts/open-yarpscope.sh](scripts/open-yarpscope.sh) | Launches the generic `yarpscope` GUI from the container. | +| [scripts/open-vframer.sh](scripts/open-vframer.sh) | Launches `vFramer` through the script-based launcher so it can still read the default source from `yarpmanager/defaults.env`. | +| [scripts/demo-ballbalance.sh](scripts/demo-ballbalance.sh) | Shared BallBalance demo launcher. Accepts `moving` or `stationary`, ensures X11 and `yarpserver`, then starts the internal coordinated demo launcher. | +| [scripts/demo-ballbalance-moving.sh](scripts/demo-ballbalance-moving.sh) | Thin wrapper that runs `demo-ballbalance.sh moving`. | +| [scripts/demo-ballbalance-stationary.sh](scripts/demo-ballbalance-stationary.sh) | Thin wrapper that runs `demo-ballbalance.sh stationary`. | +| [scripts/stop-demo.sh](scripts/stop-demo.sh) | Stops matching GUI/demo processes inside the container (`yarpdataplayer`, `yarpview`, `yarpscope`, `vFramer`) and cleans stale YARP ports. | +| [scripts/workstation-menu.sh](scripts/workstation-menu.sh) | Text menu that exposes the main public scripts in a guided interactive form. | +| [scripts/verify-repo.sh](scripts/verify-repo.sh) | Developer consistency check. Validates `yarpmanager` XML, ensures the XML apps are not shelling out through `bash`, and checks that the `vFramer` default source stays aligned. | + +## Shared And Internal Host Scripts + +These scripts support the public entrypoints. Most are not intended as the first thing a normal user runs. + +| Path | What it does | +| --- | --- | +| [scripts/common.sh](scripts/common.sh) | Shared function library for the host scripts. Wraps `docker compose`, handles Docker checks, X11 access, exec modes, container startup, and `yarpserver` detection. | +| [scripts/require-docker.sh](scripts/require-docker.sh) | Checks whether Docker is reachable and prints tailored troubleshooting guidance for common failure modes such as socket permissions or a stopped daemon. | +| [scripts/internal/launch-ballbalance-demo.sh](scripts/internal/launch-ballbalance-demo.sh) | Coordinates the script-based BallBalance demo startup. Starts the dataplayer first, then launches the viewers, tracks child PIDs, and cleans them up on exit. | +| [scripts/internal/launch-ballbalance-tool.sh](scripts/internal/launch-ballbalance-tool.sh) | Implements the script-based BallBalance tool logic for one tool at a time. Chooses the dataset, waits for ports, performs YARP connections, and handles cleanup/retry behavior. | +| [scripts/internal/launch-vframer.sh](scripts/internal/launch-vframer.sh) | Reads `yarpmanager/defaults.env`, resolves `VFRAMER_SRC`, and starts `vFramer` with that source. | + +## Container Scripts + +These are copied into the image and used inside the container. + +| Path | What it does | +| --- | --- | +| [container-scripts/container-entrypoint.sh](container-scripts/container-entrypoint.sh) | Docker entrypoint. Remaps the in-container `robotology` user/group to the host UID/GID, sets the runtime user environment, and drops privileges with `gosu`. This avoids bind-mount ownership issues. | +| [container-scripts/start-yarpserver.sh](container-scripts/start-yarpserver.sh) | In-container helper that starts `yarpserver` and logs to `/tmp/yarpserver.log`. It is invoked by the host-side startup helpers. | + +## yarpmanager Files + +These files define what `yarpmanager` sees and how it behaves. + +| Path | What it does | +| --- | --- | +| [yarpmanager/ymanager.ini](yarpmanager/ymanager.ini) | Main `yarpmanager` configuration. Points to the applications/modules/resources folders and enables `auto_connect` so the BallBalance app-defined connections can happen automatically. | +| [yarpmanager/defaults.env](yarpmanager/defaults.env) | Script-only default source for the `vFramer` launcher. This does not drive the direct-launch `yarpmanager` XML by itself. | +| [yarpmanager/applications/01-yarp-data-player.xml](yarpmanager/applications/01-yarp-data-player.xml) | `yarpmanager` application definition for the generic `yarpdataplayer` GUI. | +| [yarpmanager/applications/02-yarp-scope.xml](yarpmanager/applications/02-yarp-scope.xml) | `yarpmanager` application definition for the generic `yarpscope` GUI. | +| [yarpmanager/applications/03-yarp-view.xml](yarpmanager/applications/03-yarp-view.xml) | `yarpmanager` application definition for the generic `yarpview` GUI. | +| [yarpmanager/applications/04-vframer.xml](yarpmanager/applications/04-vframer.xml) | `yarpmanager` application definition for the generic `vFramer` GUI, using the direct-launch default source `/zynqGrabber/left/AE:o`. | +| [yarpmanager/applications/05-all-tools.xml](yarpmanager/applications/05-all-tools.xml) | `yarpmanager` application that launches the four generic tools together. It does not auto-load a dataset. | +| [yarpmanager/applications/06-ballbalance-moving-demo.xml](yarpmanager/applications/06-ballbalance-moving-demo.xml) | Direct-launch `yarpmanager` application for the moving BallBalance demo. Loads `test_moving`, declares port dependencies, and connects the RGB stream to `yarpview`. | +| [yarpmanager/applications/07-ballbalance-stationary-demo.xml](yarpmanager/applications/07-ballbalance-stationary-demo.xml) | Direct-launch `yarpmanager` application for the stationary BallBalance demo. Loads `test_stationary`, declares port dependencies, and connects the RGB stream to `yarpview`. | +| [yarpmanager/modules/.gitkeep](yarpmanager/modules/.gitkeep) | Placeholder to keep the modules directory in Git even though this repo does not currently define custom module XML files. | +| [yarpmanager/resources/.gitkeep](yarpmanager/resources/.gitkeep) | Placeholder to keep the resources directory in Git even though this repo does not currently define custom resource files. | + +## GitHub Automation + +| Path | What it does | +| --- | --- | +| [.github/workflows/test-image-build.yml](.github/workflows/test-image-build.yml) | GitHub Actions build-only workflow. It builds the Docker image on GitHub-hosted runners, loads it locally on the runner, and runs a lightweight smoke test without pushing to GHCR. | +| [.github/workflows/publish-image.yml](.github/workflows/publish-image.yml) | GitHub Actions workflow that builds the Docker image on GitHub-hosted runners and pushes it to GitHub Container Registry (`ghcr.io`). It triggers on manual dispatch, pushes to `main`/`master`, and version tags like `v*`. | + +## How The Pieces Fit Together + +The typical operator flow is: + +1. Build the image with [scripts/build.sh](scripts/build.sh). +2. Start the workstation with [scripts/start-workstation.sh](scripts/start-workstation.sh). +3. Launch tools through either [scripts/workstation-menu.sh](scripts/workstation-menu.sh), the other public scripts in [scripts](scripts/), or the `yarpmanager` apps defined in [yarpmanager/applications](yarpmanager/applications/). +4. Stop demo tools with [scripts/stop-demo.sh](scripts/stop-demo.sh) or stop the full workstation with [scripts/stop-workstation.sh](scripts/stop-workstation.sh). + +The key implementation split is: + +- public entrypoints live in [scripts](scripts/) +- shared logic lives in [scripts/common.sh](scripts/common.sh) +- script-only orchestration lives in [scripts/internal](scripts/internal/) +- in-container runtime helpers live in [container-scripts](container-scripts/) +- direct-launch `yarpmanager` behavior lives in [yarpmanager/applications](yarpmanager/applications/) diff --git a/USER_README.md b/USER_README.md new file mode 100644 index 0000000..614b02c --- /dev/null +++ b/USER_README.md @@ -0,0 +1,297 @@ +# User README + +This guide is for operators and users who want to run the workstation, open the tools, and launch demos. + +## What This Project Provides + +- one Dockerized `YARP` + `event-driven` workstation +- GUI forwarding from the container to the host desktop +- helper scripts for common tasks +- `yarpmanager` applications for the generic tools and BallBalance demos + +Inside the container, user data is mounted at: + +```text +/workspace/data +``` + +The BallBalance dataset is expected at: + +```text +/workspace/data/BallBalance +``` + +## Requirements + +Required on the host: + +- Docker Engine +- Docker Compose plugin +- a desktop session with X11 or XWayland available through `DISPLAY` +- the `xhost` command +- `git` if you still need to clone or update the repository + +Recommended Ubuntu Docker packages: + +- `docker-ce` +- `docker-ce-cli` +- `containerd.io` +- `docker-buildx-plugin` +- `docker-compose-plugin` + +If `xhost` is missing, install: + +- `x11-xserver-utils` + +You do not need to install these on the host: + +- `YARP` +- `event-driven` +- `yarpmanager` +- `yarpview` +- `yarpscope` +- `yarpdataplayer` +- `vFramer` + +Those are installed inside the Docker image from [Dockerfile](Dockerfile). + +## First-Time Setup + +1. Copy [`.env.example`](.env.example) to [`.env`](.env). +2. Set `HOST_DATA_PATH` to the host folder that should appear in the container as `/workspace/data`. +3. Make sure `DISPLAY` matches the active desktop session. + +## Quickstart + +1. Open a terminal in the project root: + +```bash +cd ~/Documents/Dockers/PRIMI_IIT_Docker +``` + +2. Build the image once: + +```bash +./scripts/build.sh +``` + +If your repository owner has already published a GHCR image for this project, they may give you a pull-first path instead of a local build. This guide keeps the local build as the default operator workflow. + +Pull-first alternative: + +```bash +docker pull ghcr.io//:latest +``` + +If you use that path, make sure your maintainer also tells you how they want [compose.yaml](compose.yaml) to consume the pulled image on your machine. + +3. Start the workstation: + +```bash +./scripts/start-workstation.sh +``` + +4. Open the operator menu: + +```bash +./scripts/workstation-menu.sh +``` + +5. In the menu, choose `Open yarpmanager`. + +6. Inside `yarpmanager`, launch one of: + +- `BallBalance Moving Demo` +- `BallBalance Stationary Demo` + +What opens: + +- `yarpdataplayer` +- `yarpview` +- `yarpscope` +- `vFramer` + +## Main Ways To Use It + +### Menu Workflow + +For the simplest interactive operator flow: + +```bash +./scripts/workstation-menu.sh +``` + +The menu exposes: + +- workstation start +- status +- `yarpmanager` +- BallBalance moving demo +- BallBalance stationary demo +- each individual GUI tool +- stop demo only +- list data +- shell +- stop workstation + +### CLI Workflow + +Use this if you want script-based entrypoints without entering the container manually. + +Build: + +```bash +./scripts/build.sh +``` + +Start workstation: + +```bash +./scripts/start-workstation.sh +``` + +Check status: + +```bash +./scripts/status.sh +``` + +List mounted data: + +```bash +./scripts/list-data.sh +``` + +Open generic tools: + +```bash +./scripts/open-manager.sh +./scripts/open-yarpview.sh +./scripts/open-yarpscope.sh +./scripts/open-vframer.sh +./scripts/open-dataplayer.sh +``` + +Run the BallBalance demos: + +```bash +./scripts/demo-ballbalance-moving.sh +./scripts/demo-ballbalance-stationary.sh +``` + +Stop the matching GUI demo tools: + +```bash +./scripts/stop-demo.sh +``` + +Stop the whole workstation: + +```bash +./scripts/stop-workstation.sh +``` + +### yarpmanager Workflow + +Launch the manager with: + +```bash +./scripts/open-manager.sh +``` + +Configured applications: + +- `YARP Data Player` +- `YARP Scope` +- `YARP View` +- `VFramer` +- `All Tools` +- `BallBalance Moving Demo` +- `BallBalance Stationary Demo` + +What they mean: + +- `YARP Data Player`: opens the generic `yarpdataplayer` GUI +- `YARP Scope`: opens the generic `yarpscope` GUI +- `YARP View`: opens the generic `yarpview` GUI +- `VFramer`: opens `vFramer` using the default source configured in [04-vframer.xml](yarpmanager/applications/04-vframer.xml) +- `All Tools`: opens the four generic tools together and does not auto-load a dataset +- `BallBalance Moving Demo`: auto-loads `test_moving` and opens the three matching viewers directly in `yarpmanager` +- `BallBalance Stationary Demo`: auto-loads `test_stationary` and opens the three matching viewers directly in `yarpmanager` + +If you want to stop a manager-launched BallBalance session from the CLI, use: + +```bash +./scripts/stop-demo.sh +``` + +### Manual Shell / YARP Workflow + +Open a shell inside the running container: + +```bash +./scripts/shell.sh +``` + +Useful commands inside the container: + +```bash +yarp check +yarp detect +yarp name list +``` + +## Important Behavior + +- BallBalance demos use `yarpdataplayer` replay outputs under `/yarpdataplayer/...` +- scripted BallBalance demos clean up matching old GUI/demo tools before launching a new session +- manager-launched BallBalance demos run tools directly and do not pre-clean old GUI/demo tools +- `All Tools` is generic and does not auto-load a dataset + +## BallBalance Tool Associations + +| Tool | Dataset / source | Purpose | +| --- | --- | --- | +| `yarpdataplayer` | `/workspace/data/BallBalance/test_moving` or `/workspace/data/BallBalance/test_stationary` | replays the recorded session | +| `yarpview` | `/yarpdataplayer/grabber` | shows the RGB camera stream | +| `yarpscope` | `/yarpdataplayer/icub/right_arm/state:o` | plots the right-arm encoder stream | +| `vFramer` | `/yarpdataplayer/zynqGrabber/left/AE:o` | visualizes the event-camera stream | + +## Troubleshooting + +Docker socket / daemon problems: + +```bash +docker info +``` + +If the daemon is down: + +```bash +sudo systemctl start docker +docker info +``` + +If no GUI window appears, check: + +- `DISPLAY` is set correctly in [`.env`](.env) +- you are running from a desktop session +- the X11 socket mount exists at `/tmp/.X11-unix` + +If the `yarpmanager` `VFramer` application needs a different default source, edit [04-vframer.xml](yarpmanager/applications/04-vframer.xml): + +```xml +--src /zynqGrabber/left/AE:o +``` + +If the script-based `./scripts/open-vframer.sh` launcher needs a different default source, edit [defaults.env](yarpmanager/defaults.env): + +```bash +VFRAMER_SRC=/zynqGrabber/left/AE:o +``` + +If the host data folder changes, update [`.env`](.env) and re-apply the runtime: + +```bash +./scripts/start-workstation.sh +``` diff --git a/compose.yaml b/compose.yaml index cbb1416..456b3d9 100644 --- a/compose.yaml +++ b/compose.yaml @@ -4,6 +4,7 @@ services: context: . dockerfile: Dockerfile args: + BASE_IMAGE: ${BASE_IMAGE:-public.ecr.aws/ubuntu/ubuntu:22.04} YCM_VERSION: ${YCM_VERSION:-v0.15.2} YARP_VERSION: ${YARP_VERSION:-v3.8.0} ED_VERSION: ${ED_VERSION:-master} diff --git a/scripts/common.sh b/scripts/common.sh index 65284a0..769a3c7 100755 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -24,6 +24,17 @@ compose_cmd() { } compose_exec() { + compose_cmd exec \ + -T \ + -u "$CONTAINER_USER" \ + -e HOME="$CONTAINER_HOME" \ + -e USER="$CONTAINER_USER" \ + -e LOGNAME="$CONTAINER_USER" \ + "$COMPOSE_SERVICE" \ + "$@" +} + +compose_exec_tty() { compose_cmd exec \ -u "$CONTAINER_USER" \ -e HOME="$CONTAINER_HOME" \ @@ -67,17 +78,21 @@ ensure_container_running() { compose_cmd up -d } +yarpserver_detected() { + compose_exec bash -lc 'timeout 2 yarp detect >/dev/null 2>&1' +} + ensure_yarpserver() { ensure_container_running - if compose_exec yarp detect >/dev/null 2>&1; then + if yarpserver_detected; then return 0 fi compose_exec_detached start-yarpserver for _ in 1 2 3 4 5; do - if compose_exec yarp detect >/dev/null 2>&1; then + if yarpserver_detected; then return 0 fi sleep 1 diff --git a/scripts/demo-ballbalance.sh b/scripts/demo-ballbalance.sh index 2abf719..ad932dd 100755 --- a/scripts/demo-ballbalance.sh +++ b/scripts/demo-ballbalance.sh @@ -17,7 +17,7 @@ ensure_yarpserver launch_demo_tool() { local selected_session="$1" - compose_exec_detached bash -lc 'cd /workspace/project && exec ./yarpmanager/bin/launch-ballbalance-demo.sh "$@"' bash "$selected_session" + compose_exec_detached bash -lc 'cd /workspace/project && exec ./scripts/internal/launch-ballbalance-demo.sh "$@"' bash "$selected_session" } launch_demo_tool "$session" diff --git a/yarpmanager/bin/launch-ballbalance-demo.sh b/scripts/internal/launch-ballbalance-demo.sh similarity index 100% rename from yarpmanager/bin/launch-ballbalance-demo.sh rename to scripts/internal/launch-ballbalance-demo.sh diff --git a/yarpmanager/bin/launch-ballbalance-tool.sh b/scripts/internal/launch-ballbalance-tool.sh similarity index 100% rename from yarpmanager/bin/launch-ballbalance-tool.sh rename to scripts/internal/launch-ballbalance-tool.sh diff --git a/yarpmanager/bin/launch-vframer.sh b/scripts/internal/launch-vframer.sh similarity index 81% rename from yarpmanager/bin/launch-vframer.sh rename to scripts/internal/launch-vframer.sh index d476c56..0497ff6 100755 --- a/yarpmanager/bin/launch-vframer.sh +++ b/scripts/internal/launch-vframer.sh @@ -8,6 +8,6 @@ if [[ -f "$DEFAULTS_FILE" ]]; then source "$DEFAULTS_FILE" fi -VFRAMER_SRC="${VFRAMER_SRC:-/event_camera/events:o}" +VFRAMER_SRC="${VFRAMER_SRC:-/zynqGrabber/left/AE:o}" exec vFramer --src "$VFRAMER_SRC" "$@" diff --git a/scripts/open-vframer.sh b/scripts/open-vframer.sh index 3507744..3817e8a 100755 --- a/scripts/open-vframer.sh +++ b/scripts/open-vframer.sh @@ -4,4 +4,4 @@ set -euo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/common.sh" -open_gui_command 'cd /workspace/project && exec ./yarpmanager/bin/launch-vframer.sh "$@"' "$@" +open_gui_command 'cd /workspace/project && exec ./scripts/internal/launch-vframer.sh "$@"' "$@" diff --git a/scripts/run-gui.sh b/scripts/run-gui.sh deleted file mode 100755 index f9d4f81..0000000 --- a/scripts/run-gui.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" -source "$SCRIPT_DIR/common.sh" - -allow_local_x11 -reconcile_container diff --git a/scripts/shell.sh b/scripts/shell.sh index 094037e..c3748eb 100755 --- a/scripts/shell.sh +++ b/scripts/shell.sh @@ -5,4 +5,4 @@ SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/common.sh" ensure_container_running -compose_exec bash +compose_exec_tty bash diff --git a/scripts/start-yarpserver.sh b/scripts/start-yarpserver.sh index 2d4d4c7..993b1b6 100755 --- a/scripts/start-yarpserver.sh +++ b/scripts/start-yarpserver.sh @@ -4,5 +4,5 @@ set -euo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/common.sh" -ensure_container_running -compose_exec start-yarpserver +ensure_yarpserver +echo "yarpserver detected." diff --git a/scripts/status.sh b/scripts/status.sh index 97430ce..b5f36bc 100755 --- a/scripts/status.sh +++ b/scripts/status.sh @@ -12,7 +12,7 @@ echo if compose_cmd ps --status running --services | grep -qx "$COMPOSE_SERVICE"; then echo "YARP name server:" - if compose_exec yarp detect >/dev/null 2>&1; then + if yarpserver_detected; then echo " detected" else echo " not detected" diff --git a/scripts/verify-phase1.sh b/scripts/verify-phase1.sh deleted file mode 100755 index a5d0f48..0000000 --- a/scripts/verify-phase1.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" -source "$SCRIPT_DIR/common.sh" - -ensure_container_running -compose_cmd ps -compose_exec yarp check diff --git a/scripts/verify-repo.sh b/scripts/verify-repo.sh new file mode 100755 index 0000000..3f7b142 --- /dev/null +++ b/scripts/verify-repo.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd -- "$SCRIPT_DIR/.." && pwd)" + +cd "$PROJECT_ROOT" + +xmllint --noout yarpmanager/applications/*.xml + +search_pattern='bash|-lc ' + +if command -v rg >/dev/null 2>&1; then + search_cmd=(rg -n "$search_pattern" yarpmanager/applications) +else + search_cmd=(grep -R -n -E "$search_pattern" yarpmanager/applications) +fi + +if "${search_cmd[@]}" >/dev/null; then + echo "yarpmanager applications still contain bash-based launch definitions." >&2 + exit 1 +fi + +default_src="$(sed -n 's/^VFRAMER_SRC=//p' yarpmanager/defaults.env)" +manager_src="$(sed -n 's@.*--src \(.*\)@\1@p' yarpmanager/applications/04-vframer.xml)" +all_tools_src="$(sed -n 's@.*--src \(.*\)@\1@p' yarpmanager/applications/05-all-tools.xml)" + +if [[ -z "$default_src" || -z "$manager_src" || -z "$all_tools_src" ]]; then + echo "Failed to extract one or more vFramer defaults for verification." >&2 + exit 1 +fi + +if [[ "$default_src" != "$manager_src" || "$default_src" != "$all_tools_src" ]]; then + echo "vFramer defaults are out of sync:" >&2 + echo " defaults.env: $default_src" >&2 + echo " 04-vframer.xml: $manager_src" >&2 + echo " 05-all-tools.xml: $all_tools_src" >&2 + exit 1 +fi + +echo "Repo launch definitions look consistent." diff --git a/yarpmanager/applications/01-yarp-data-player.xml b/yarpmanager/applications/01-yarp-data-player.xml index 1cdad35..29f9064 100644 --- a/yarpmanager/applications/01-yarp-data-player.xml +++ b/yarpmanager/applications/01-yarp-data-player.xml @@ -7,8 +7,7 @@ Codex - bash - -lc "./yarpmanager/bin/launch-yarpdataplayer.sh" + yarpdataplayer localhost /workspace/project --visible_na diff --git a/yarpmanager/applications/02-yarp-scope.xml b/yarpmanager/applications/02-yarp-scope.xml index a3f59de..a197bb6 100644 --- a/yarpmanager/applications/02-yarp-scope.xml +++ b/yarpmanager/applications/02-yarp-scope.xml @@ -7,8 +7,7 @@ Codex - bash - -lc "./yarpmanager/bin/launch-yarpscope.sh" + yarpscope localhost /workspace/project --visible_na diff --git a/yarpmanager/applications/03-yarp-view.xml b/yarpmanager/applications/03-yarp-view.xml index 3e15d01..2d4496f 100644 --- a/yarpmanager/applications/03-yarp-view.xml +++ b/yarpmanager/applications/03-yarp-view.xml @@ -7,8 +7,7 @@ Codex - bash - -lc "./yarpmanager/bin/launch-yarpview.sh" + yarpview localhost /workspace/project --visible_na diff --git a/yarpmanager/applications/04-vframer.xml b/yarpmanager/applications/04-vframer.xml index bd47410..2553339 100644 --- a/yarpmanager/applications/04-vframer.xml +++ b/yarpmanager/applications/04-vframer.xml @@ -7,8 +7,8 @@ Codex - bash - -lc "./yarpmanager/bin/launch-vframer.sh" + vFramer + --src /zynqGrabber/left/AE:o localhost /workspace/project --visible_na diff --git a/yarpmanager/applications/05-all-tools.xml b/yarpmanager/applications/05-all-tools.xml index e3c8e0c..4923103 100644 --- a/yarpmanager/applications/05-all-tools.xml +++ b/yarpmanager/applications/05-all-tools.xml @@ -7,7 +7,7 @@ Codex - ./yarpmanager/bin/yarp-data-player + yarpdataplayer localhost /workspace/project --visible_na @@ -16,7 +16,7 @@ - ./yarpmanager/bin/yarp-scope + yarpscope localhost /workspace/project --visible_na @@ -25,7 +25,7 @@ - ./yarpmanager/bin/yarp-view + yarpview localhost /workspace/project --visible_na @@ -34,7 +34,8 @@ - ./yarpmanager/bin/vframer + vFramer + --src /zynqGrabber/left/AE:o localhost /workspace/project --visible_na diff --git a/yarpmanager/applications/06-ballbalance-moving-demo.xml b/yarpmanager/applications/06-ballbalance-moving-demo.xml index 1611137..8deb052 100644 --- a/yarpmanager/applications/06-ballbalance-moving-demo.xml +++ b/yarpmanager/applications/06-ballbalance-moving-demo.xml @@ -7,8 +7,8 @@ Codex - bash - -lc "./yarpmanager/bin/launch-ballbalance-demo.sh moving" + yarpdataplayer + --dataset /workspace/data/BallBalance/test_moving --add_prefix localhost /workspace/project --visible_na @@ -16,4 +16,48 @@ 2.0 + + yarpview + --name /ballbalance_moving/yarpview/img:i + localhost + /workspace/project + --visible_na + + /yarpdataplayer/grabber + + + 2.0 + + + + yarpscope + --remote /yarpdataplayer/icub/right_arm/state:o --carrier tcp + localhost + /workspace/project + --visible_na + + /yarpdataplayer/icub/right_arm/state:o + + + 2.0 + + + + vFramer + --name /ballbalance_moving/vframer --src /yarpdataplayer/zynqGrabber/left/AE:o + localhost + /workspace/project + --visible_na + + /yarpdataplayer/zynqGrabber/left/AE:o + + + 2.0 + + + + /yarpdataplayer/grabber + /ballbalance_moving/yarpview/img:i + tcp + diff --git a/yarpmanager/applications/07-ballbalance-stationary-demo.xml b/yarpmanager/applications/07-ballbalance-stationary-demo.xml index b2faae3..fbe351b 100644 --- a/yarpmanager/applications/07-ballbalance-stationary-demo.xml +++ b/yarpmanager/applications/07-ballbalance-stationary-demo.xml @@ -7,8 +7,8 @@ Codex - bash - -lc "./yarpmanager/bin/launch-ballbalance-demo.sh stationary" + yarpdataplayer + --dataset /workspace/data/BallBalance/test_stationary --add_prefix localhost /workspace/project --visible_na @@ -16,4 +16,48 @@ 2.0 + + yarpview + --name /ballbalance_stationary/yarpview/img:i + localhost + /workspace/project + --visible_na + + /yarpdataplayer/grabber + + + 2.0 + + + + yarpscope + --remote /yarpdataplayer/icub/right_arm/state:o --carrier tcp + localhost + /workspace/project + --visible_na + + /yarpdataplayer/icub/right_arm/state:o + + + 2.0 + + + + vFramer + --name /ballbalance_stationary/vframer --src /yarpdataplayer/zynqGrabber/left/AE:o + localhost + /workspace/project + --visible_na + + /yarpdataplayer/zynqGrabber/left/AE:o + + + 2.0 + + + + /yarpdataplayer/grabber + /ballbalance_stationary/yarpview/img:i + tcp + diff --git a/yarpmanager/bin/launch-yarpdataplayer.sh b/yarpmanager/bin/launch-yarpdataplayer.sh deleted file mode 100755 index c01a739..0000000 --- a/yarpmanager/bin/launch-yarpdataplayer.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -exec yarpdataplayer "$@" diff --git a/yarpmanager/bin/launch-yarpscope.sh b/yarpmanager/bin/launch-yarpscope.sh deleted file mode 100755 index 1c064c3..0000000 --- a/yarpmanager/bin/launch-yarpscope.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -exec yarpscope "$@" diff --git a/yarpmanager/bin/launch-yarpview.sh b/yarpmanager/bin/launch-yarpview.sh deleted file mode 100755 index 52327b3..0000000 --- a/yarpmanager/bin/launch-yarpview.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -exec yarpview "$@" diff --git a/yarpmanager/bin/vframer b/yarpmanager/bin/vframer deleted file mode 100755 index 46ed94d..0000000 --- a/yarpmanager/bin/vframer +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" - -exec "$SCRIPT_DIR/launch-vframer.sh" "$@" diff --git a/yarpmanager/bin/yarp-data-player b/yarpmanager/bin/yarp-data-player deleted file mode 100755 index 35008ac..0000000 --- a/yarpmanager/bin/yarp-data-player +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" - -exec "$SCRIPT_DIR/launch-yarpdataplayer.sh" "$@" diff --git a/yarpmanager/bin/yarp-scope b/yarpmanager/bin/yarp-scope deleted file mode 100755 index fdfb487..0000000 --- a/yarpmanager/bin/yarp-scope +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" - -exec "$SCRIPT_DIR/launch-yarpscope.sh" "$@" diff --git a/yarpmanager/bin/yarp-view b/yarpmanager/bin/yarp-view deleted file mode 100755 index fe80f6f..0000000 --- a/yarpmanager/bin/yarp-view +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" - -exec "$SCRIPT_DIR/launch-yarpview.sh" "$@" diff --git a/yarpmanager/defaults.env b/yarpmanager/defaults.env index 2433532..a5c2f3e 100644 --- a/yarpmanager/defaults.env +++ b/yarpmanager/defaults.env @@ -1,3 +1,3 @@ -# Default event-camera source for the yarpmanager vFramer application. -# Change this if your event stream is published on a different YARP port. +# Default event-camera source for the script-based vFramer launcher. +# The yarpmanager application definitions keep their own direct-launch value. VFRAMER_SRC=/zynqGrabber/left/AE:o diff --git a/yarpmanager/ymanager.ini b/yarpmanager/ymanager.ini index 950ef1e..f65f023 100644 --- a/yarpmanager/ymanager.ini +++ b/yarpmanager/ymanager.ini @@ -13,8 +13,9 @@ watchdog = no module_failure = prompt connection_failure = prompt -# Connections are left manual because the real robot/data port names vary. -auto_connect = no +# Automatically connect application-defined ports after launch. +# The generic tool apps have no fixed connections; the BallBalance demos do. +auto_connect = yes # Appearance color_theme = dark