Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 2 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
PORT_ROSBRIDGE=9090
PORT_CONTROL_PANEL=4004

# DDS discovery (scripts/dds_env.sh). macOS defaults to localhost-only unicast:
# tmux daemonizes to PPID 1, so the tmux server holds its own macOS Local Network
# permission, which Homebrew tmux never gets — multicast discovery is then dropped
# silently and nodes never find each other. Loopback is exempt. Linux keeps stock DDS.
# DDS discovery (scripts/dds_env.sh). macOS defaults to localhost-only unicast
# because multicast needs a Local Network permission tmux never gets.
# LUCY_DDS_LOCALHOST=0
# LUCY_DDS_INTERFACE=192.168.1.5
# LUCY_DDS_PEERS=hostA,hostB
10 changes: 5 additions & 5 deletions .github/workflows/install-and-launch.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# - DEV=false -> install.sh uses url_https from config/repos.json.
# - ./install.sh --skip-build clones sub-repos; colcon build runs via pixi run build.
# - DEV=false -> install.py uses url_https from config/repos.json.
# - python3 install.py --skip-build clones sub-repos; colcon build runs via pixi run build.

name: Install, Launch & Release

Expand Down Expand Up @@ -58,8 +58,8 @@ jobs:
- name: Clone sub-repositories (skip colcon)
shell: bash
run: |
chmod +x install.sh launch_lucy.sh
./install.sh --skip-build
chmod +x launch_lucy.sh
python3 install.py --skip-build

- name: Build workspace (colcon)
shell: bash
Expand All @@ -79,7 +79,7 @@ jobs:

- name: Launch smoke test (headless)
shell: bash
run: ./launch_lucy.sh --headless ros2 doctor --report
run: ./launch_lucy.sh --headless python scripts/ros_doctor.py

- name: Launcher tmux smoke (Linux)
if: matrix.pixi_platform == 'linux-64'
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Pixi
.pixi/

# Workspace (filled by install.sh)
# Workspace (filled by install.py)
src/

# Colcon
Expand Down
4 changes: 2 additions & 2 deletions Lucy.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def main_tui(stdscr):
set_dev_mode(is_dev_mode)
elif selected_option == "Update":
return {
"cmd": ["./install.sh"],
"cmd": [sys.executable, "install.py"],
"interactive": False,
"name": "Install",
"extra_env": INSTALL_ENV,
Expand Down Expand Up @@ -249,7 +249,7 @@ def check_initial_size():
sys.exit(1)
if not wants_install:
sys.exit(0)
rc = run_command(["./install.sh"], extra_env=INSTALL_ENV)
rc = run_command([sys.executable, "install.py"], extra_env=INSTALL_ENV)
if rc != 0:
print(f"\n--- Install finished with exit code {rc} ---")
print("Press Enter to exit.")
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ Run `Lucy.py` and the install scripts **from the repository root** — they read
### Linux / macOS

```bash
./install.sh # thin wrapper around install.py
python3 install.py
```

**NixOS:** enable [nix-ld](https://github.com/nix-community/nix-ld) so Pixi/RoboStack conda binaries can load the host dynamic linker (required before `./install.sh`):
**NixOS:** enable [nix-ld](https://github.com/nix-community/nix-ld) so Pixi/RoboStack conda binaries can load the host dynamic linker (required before `install.py`):

```nix
programs.nix-ld.enable = true;
Expand Down Expand Up @@ -80,7 +80,7 @@ pixi run control-panel # http://localhost:4004
pixi run rviz # optional viewer
```

`pixi run core` also starts a `/joint_states` stand-in, because ros2_control's controller_manager currently crashes on Windows. The robot renders and follows the panel's sliders, but is not driveable. See the [developer guide](docs/developer_lucy_packages.md).
`pixi run core` also starts a `/joint_states` stand-in, because ros2_control's controller_manager currently crashes on Windows. The model follows the panel's sliders, but nothing reaches the hardware. See the [developer guide](docs/developer_lucy_packages.md).

## Using the Lucy launcher

Expand Down Expand Up @@ -117,5 +117,5 @@ For developer mode, Pixi component tasks (`pixi run core`, `sim-headless`, …),

## More

- [`docs/developer_lucy_packages.md`](docs/developer_lucy_packages.md) — developer guide: per-repo docs, all `install.sh` / `launch_lucy.sh` flags, dev mode, ports, environment overrides, packages overview.
- [`docs/developer_lucy_packages.md`](docs/developer_lucy_packages.md) — developer guide: per-repo docs, all `install.py` / `launch_lucy.sh` flags, dev mode, ports, environment overrides, packages overview.
- [`docs/launcher_packages.md`](docs/launcher_packages.md) — launcher guide: how to add new packages to the launcher UI and understand the configuration fields.
4 changes: 2 additions & 2 deletions config/repos.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
},
{
"name": "lucy_ros_packages",
"branch": "feat-pixi",
"branch": "aes/fix-supervisor-orphaned-children",
"url_https": "https://github.com/Sentience-Robotics/lucy_ros_packages.git",
"url_ssh": "git@github.com:Sentience-Robotics/lucy_ros_packages.git"
},
{
"name": "lucy_control_panel",
"branch": "dev",
"branch": "aes/shorten-service-comment",
"url_https": "https://github.com/Sentience-Robotics/lucy_control_panel.git",
"url_ssh": "git@github.com:Sentience-Robotics/lucy_control_panel.git"
}
Expand Down
30 changes: 15 additions & 15 deletions docs/developer_lucy_packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ When enabled:

| Behavior | Effect |
|----------|--------|
| **SSH clones** | `install.sh` uses `url_ssh` from [`config/repos.json`](../config/repos.json) instead of HTTPS |
| **SSH clones** | `install.py` uses `url_ssh` from [`config/repos.json`](../config/repos.json) instead of HTTPS |
| **No auto-launch** | Core and Control Panel are not started automatically on Launch |

SSH keys must be configured for GitHub on your host before running `./install.sh` with `DEV=true`.
SSH keys must be configured for GitHub on your host before running `install.py` with `DEV=true`.

### Local overrides (gitignored)

Expand Down Expand Up @@ -44,7 +44,7 @@ For a multi-robot dev setup, copy [`config/launcher_config.json.local.example`](

### Linux

Standard path: `./install.sh` then `python3 Lucy.py`.
Standard path: `python3 install.py` then `python3 Lucy.py`.

**Wayland:** RViz/Gazebo may need `xhost +local:` or an X11 session.

Expand All @@ -66,28 +66,28 @@ Developer CLI equivalents:

| Windows | Linux/macOS |
|---------|-------------|
| `Lucy-Setup.exe` → Fresh install | `./install.sh` |
| `Lucy-Setup.exe` → Update | `./install.sh` |
| `Lucy-Setup.exe` → Repair | `./install.sh --repair` |
| `Lucy-Setup.exe` → Fresh install | `python3 install.py` |
| `Lucy-Setup.exe` → Update | `python3 install.py` |
| `Lucy-Setup.exe` → Repair | `python3 install.py --repair` |
| `Lucy.exe` | `./launch_lucy.sh` |
| `Lucy.exe --cli build-only` | `./install.sh --build-only` |
| `Lucy.exe --cli build-only` | `python3 install.py --build-only` |

Launch runs via Git Bash (`bash launch_lucy.sh`). Without tmux, the Control Center runs directly (`pixi run -- python -m launcher`).

### Workspace install (`install.sh`)
### Workspace install (`install.py`)

Pixi installs RoboStack Jazzy; `colcon build --symlink-install` builds `src/`; `yarn install` sets up the control panel.

| Command | What it does |
|---------|--------------|
| `./install.sh` | Clone missing repos, pull existing ones, `pixi install`, colcon build |
| `./install.sh --repair` | Wipe each repo under `src/` then re-clone and rebuild |
| `./install.sh --build-only` | Skip git; `pixi install` + colcon + panel yarn |
| `./install.sh --skip-build` | Clone/pull only (CI) |
| `python3 install.py` | Clone missing repos, pull existing ones, `pixi install`, colcon build |
| `python3 install.py --repair` | Wipe each repo under `src/` then re-clone and rebuild |
| `python3 install.py --build-only` | Skip git; `pixi install` + colcon + panel yarn |
| `python3 install.py --skip-build` | Clone/pull only (CI) |

**Do not use `rosdep`** — it bypasses Pixi/RoboStack. Add deps via `pixi.toml` or clone into `src/`. See [`docs/pixi_setup.md`](pixi_setup.md).

**RealSense** (optional, not in Pixi): after a normal build, run `./scripts/build_local_realsense.sh` or `LUCY_BUILD_REALSENSE=1 ./install.sh`. Primary target is Linux; see script for aarch64 notes.
**RealSense** (optional, not in Pixi): after a normal build, run `./scripts/build_local_realsense.sh` or `LUCY_BUILD_REALSENSE=1 python3 install.py`. Primary target is Linux; see script for aarch64 notes.

**Packages under `src/`** (from [`config/repos.json`](../config/repos.json)):

Expand Down Expand Up @@ -174,7 +174,7 @@ ros2 launch lucy_bringup lucy.launch.py gazebo:=true

| Action | Command |
|--------|---------|
| Install / update | `./install.sh` |
| Install / update | `python3 install.py` |
| Rebuild | `pixi run build` then `pixi run panel-install` |
| Launch | `./launch_lucy.sh` |
| Dev shell | `pixi run shell` |
Expand Down Expand Up @@ -205,7 +205,7 @@ From **Configuration → ACTIVATE**, enable **SIMULATION ONLY** to run **VALIDAT

| Env var | Default | Purpose |
|---------|---------|---------|
| `DEV` | unset | `true` → SSH clones during `install.sh` |
| `DEV` | unset | `true` → SSH clones during `install.py` |
| `PORT_CONTROL_PANEL` | auto | Host port for control panel URL |
| `PORT_CONTROL_PANEL_CONTAINER` | `VITE_PORT` from `src/lucy_control_panel/.env`, else `4004` | Port the Vite dev server listens on inside the container |
| `PORT_ROSBRIDGE` | `9090` | rosbridge WebSocket |
Expand Down
2 changes: 1 addition & 1 deletion docs/pixi_setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ When adding or changing workspace packages:
pixi install # updates pixi.lock for every platform in pixi.toml
```

`install.sh` runs `pixi lock` automatically if `pixi.lock` is missing, then `pixi install`.
`install.py` runs `pixi lock` automatically if `pixi.lock` is missing, then `pixi install`.

**Pixi ≥ 0.78** is recommended for multi-platform lock resolution (`curl -fsSL https://pixi.sh/install.sh | bash`).

Expand Down
26 changes: 15 additions & 11 deletions install.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
"""Lucy workspace setup: clone sub-repos, install RoboStack deps via Pixi, colcon build.

Single cross-platform implementation behind ./install.sh (Linux, macOS) and the
Single cross-platform implementation behind the Windows launcher and the
Windows flows in windows/install_ops.py. Keep behaviour changes here so no
platform drifts from the others.

Expand Down Expand Up @@ -443,7 +443,7 @@ def confirm_install(req_id: str, prompt: str, auto_env: str) -> None:
fail(req_id, f"{prompt} needs confirmation in non-interactive mode. "
f"Set {auto_env}=1 or run from an interactive terminal.")
if input(f"{prompt} [y/N] ").strip().lower() not in ("y", "yes"):
fail(req_id, f"Aborted install it manually or set {auto_env}=1.")
fail(req_id, f"Aborted - install it manually or set {auto_env}=1.")


def confirm_pixi_install() -> None:
Expand All @@ -461,8 +461,8 @@ def ensure_pixi(run_command: Callable = default_run_command, log: Log = print) -
if env_flag("LUCY_SKIP_PIXI_UPGRADE"):
fail("pixi", f"pixi {current} is older than required {minimum}" if current else "pixi not found")

log(f"install: pixi {current} is older than {minimum} installing latest ..." if current
else "install: pixi not found installing via pixi.sh ...")
log(f"install: pixi {current} is older than {minimum} - installing latest ..." if current
else "install: pixi not found - installing via pixi.sh ...")
log("install: (LUCY_SKIP_PIXI_UPGRADE=1 to abort; LUCY_PIXI_AUTO_UPGRADE=1 to skip prompt)")

confirm_pixi_install()
Expand Down Expand Up @@ -502,7 +502,7 @@ def ensure_msvc(run_command: Callable = default_run_command, log: Log = print) -
if shutil.which("winget") is None:
fail("msvc", "winget not found, so the build tools cannot be installed automatically.")

log("install: MSVC build tools not found installing via winget (roughly 1.5 GB) ...")
log("install: MSVC build tools not found - installing via winget (roughly 1.5 GB) ...")
log("install: (LUCY_SKIP_MSVC_INSTALL=1 to abort; LUCY_MSVC_AUTO_INSTALL=1 to skip prompt)")
confirm_install("msvc", "Install the Visual Studio Build Tools C++ compiler?", "LUCY_MSVC_AUTO_INSTALL")
run_command(msvc_install_command())
Expand Down Expand Up @@ -645,7 +645,7 @@ def install_repos(
effective = "zip"

if effective == "zip" and mode == "update":
log("NOTE: ZIP-based install local changes under src/ were replaced.")
log("NOTE: ZIP-based install - local changes under src/ were replaced.")

mark_optional_colcon_ignore(root, repos, log)
return effective
Expand Down Expand Up @@ -739,7 +739,7 @@ def pixi_install(
project_root: Path | str, run_command: Callable = default_run_command, log: Log = print
) -> None:
if not (Path(project_root) / "pixi.lock").is_file():
log("No pixi.lock running pixi lock (solves every platform in pixi.toml) ...")
log("No pixi.lock - running pixi lock (solves every platform in pixi.toml) ...")
pixi_run(project_root, ["lock"], run_command)
log("Pixi install (RoboStack Jazzy, all workspace platforms) ...")
pixi_run(project_root, ["install"], run_command)
Expand All @@ -752,12 +752,12 @@ def build_local_realsense_optional(
) -> None:
"""Optional local librealsense build (Linux-targeted shell script)."""
if not env_flag("LUCY_BUILD_REALSENSE"):
log("RealSense: local build when needed scripts/build_local_realsense.sh")
log("RealSense: local build when needed: scripts/build_local_realsense.sh")
return
if sys.platform == "win32":
log("RealSense: LUCY_BUILD_REALSENSE set but the local build is Linux-only; skipping.")
return
log("LUCY_BUILD_REALSENSE enabled building librealsense locally ...")
log("LUCY_BUILD_REALSENSE enabled - building librealsense locally ...")
script = Path(project_root) / "scripts" / "build_local_realsense.sh"
run_command(["bash", str(script)], cwd=str(project_root))

Expand Down Expand Up @@ -870,8 +870,12 @@ def main(argv: Optional[list[str]] = None) -> int:
print(f"Install failed: {exc}", file=sys.stderr)
return 1

print("Repos ready. Run 'pixi run build' or re-run without --skip-build." if args.skip_build
else "Install complete. Run './launch_lucy.sh' or Launch in Lucy.py")
if args.skip_build:
print("Repos ready. Run 'pixi run build' or re-run without --skip-build.")
elif sys.platform == "win32":
print("Install complete. Run 'pixi run core', then 'pixi run control-panel'.")
else:
print("Install complete. Run './launch_lucy.sh' or Launch in Lucy.py")
return 0


Expand Down
32 changes: 0 additions & 32 deletions install.sh

This file was deleted.

6 changes: 2 additions & 4 deletions launch_lucy.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# Start the Lucy stack (ROS 2 Jazzy + Control Center launcher) via Pixi.
#
# Prerequisite: ./install.sh
# Prerequisite: python3 install.py
#
# Usage:
# ./launch_lucy.sh tmux + Control Center launcher (default)
Expand All @@ -14,8 +14,6 @@
# Ports published on the host: rosbridge 9090, control panel PORT_CONTROL_PANEL (defaults to
# VITE_PORT from src/lucy_control_panel/.env, else 4004). Vite proxies /rosbridge to the bridge.
#
# Docker platform follows the last ./install.sh run (.lucy-docker-platform; override with LUCY_DOCKER_PLATFORM).
# GPU mode is auto-detected via docker/gpu_detect.sh (jetson / nvidia / dri / software).

set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
Expand Down Expand Up @@ -99,7 +97,7 @@ vite_scheme_from_envfile() {
check_cmd pixi

if [[ ! -f "$SCRIPT_DIR/install/setup.bash" && ! -f "$SCRIPT_DIR/install/setup.bat" ]]; then
echo "Workspace not built. Run ./install.sh or Install in Lucy.py" >&2
echo "Workspace not built. Run python3 install.py or Install in Lucy.py" >&2
exit 1
fi

Expand Down
4 changes: 2 additions & 2 deletions pixi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ ros-jazzy-simulation-interfaces = "*"
ros-jazzy-backward-ros = "*"

# RealSense is not a Pixi dependency — build locally when needed:
# ./scripts/build_local_realsense.sh (or LUCY_BUILD_REALSENSE=1 ./install.sh)
# ./scripts/build_local_realsense.sh (or LUCY_BUILD_REALSENSE=1 python3 install.py)

[feature.ros.target.osx-arm64.dependencies]
pygraphviz = "*"
Expand Down Expand Up @@ -108,7 +108,7 @@ panel-dev = { cmd = "yarn dev", cwd = "src/lucy_control_panel" }
panel-build = { cmd = "yarn build", cwd = "src/lucy_control_panel" }

[feature.dev.tasks]
doctor = "ros2 doctor --report"
doctor = "python scripts/ros_doctor.py"
workspace-test = { cmd = "PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 pytest tests -q -p pytester -p python -p terminal" }
shell = "bash scripts/pixi_dev_shell.sh"

Expand Down
2 changes: 1 addition & 1 deletion scripts/build_local_realsense.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#
# Run after a normal workspace build (install/setup.bash must exist). Does not
# replace pixi run build — it adds librealsense + realsense-ros to install/.
# install.sh runs this when LUCY_BUILD_REALSENSE=1 (after colcon + panel-install).
# install.py runs this when LUCY_BUILD_REALSENSE=1 (after colcon + panel-install).
#
# Uses a portable CPU count for cmake -j (nproc on Linux, sysctl on macOS).

Expand Down
Loading
Loading