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
164 changes: 46 additions & 118 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,119 +1,78 @@
# BROS
<p align="center">
<img src="assets/logos/BROS2-logo-long.png" alt="BROS2 logo" width="440">
</p>

BROS (Block ROS) is an Electron desktop environment for building, simulating, and introspecting ROS 2 graphs with a drag-and-drop block interface. It streamlines going from idea to runnable robot behavior by generating ROS packages, launch files, and providing live insight into running nodes.
BROS2 (Block ROS2) is an Electron desktop environment for building, simulating, and introspecting ROS2 graphs with a drag-and-drop block interface. It streamlines going from idea to runnable robot behavior by generating ROS packages, launch files, and providing live insight into running nodes.

## Why BROS?
Basically, BROS2 (Block ROS2) is an Electron desktop app that lets you assemble ROS2 graphs visually and run them through a managed Docker workspace 🦾🤖

## Why BROS2?
- Visual composition of ROS 2 nodes, topics, and services without leaving the editor.
- Automatic generation of package scaffolding and launch files from the block graph.
- Integrated simulation hooks (Gazebo, Isaac) and telemetry panels for rapid iteration.
- Cross-platform desktop app distributed via Electron so teams share a single workflow.

## Prerequisites
- macOS (Apple Silicon or Intel) or Linux with Docker Desktop / Docker Engine installed and running.
- `nvm` for Node version management (installed automatically by the bootstrap script if missing).
- Node `20.19.x` and pnpm `10.x` (configured by the bootstrap script).
## Requirements
- macOS (Apple Silicon or Intel) or Linux with Docker Desktop / Docker Engine running.
- Git, curl, and bash (used by the bootstrap script).
- Internet access to download Node, pnpm, and Electron during setup.

Verify Docker CLI access before launching the app:
Verify Docker access before continuing:

```bash
which docker
docker ps
```

## Setup & Install

### 1. Bootstrap the workspace
## First-Time Setup

```bash
git clone https://github.com/nhathout/BROS.git
cd BROS
./apps/desktop-app/scripts/bootstrap.sh
cd apps/desktop-app/
node node_modules/electron/install.js
pnpm dev
```

What the script does:
- Ensures `nvm` is present and switches to Node `20.19.0`.
- Installs pnpm `10.17.1` via Corepack (or npm fallback).
- Runs `pnpm install -r` to hydrate all workspaces.
- Builds the Electron main process and renderer bundles.
- Launches the BROS desktop binary once the build finishes.
- Adds `nvm use` to your shell profile (optional prompt) so new terminals select the correct Node version.
The bootstrap script installs or activates:
- `nvm` (if missing) and Node `20.19.0`.
- pnpm `10.17.1` via Corepack (or npm fallback).
- Workspace dependencies with `pnpm install -r`.
- Electron binaries and a first build of the desktop app.

Restart the shell if you are prompted so `pnpm` is on the `PATH`.
It launches the packaged app once everything compiles. If the script adds an `nvm use` snippet to your shell profile, open a new terminal so `pnpm` is on your `PATH` next time.

### 2. Install / refresh dependencies manually
## Daily Development

Any time dependencies change (for example when pulling new workspace packages) run:
From a bootstrapped workspace, start the dev environment from the desktop app folder:

```bash
pnpm install
```

This command wires all local packages together (e.g. `@bros/ui`, `@bros/validation`) so TypeScript and the Electron main process can resolve them.

## Build & Development Workflow

### Full workspace build

Compiles every workspace package (shared → UI → runner → validation → desktop app) and packages the desktop app via Electron Builder:

```bash
pnpm -r build
cd apps/desktop-app
node node_modules/electron/install.js
pnpm dev
```

Use this when you need a production build or fresh type declarations everywhere. Artifacts end up in:
- `packages/**/dist/` for shared libraries.
- `apps/desktop-app/dist/` for the main process + preloads.
- `apps/desktop-app/release/` for packaged Electron binaries.
`pnpm dev` runs the Electron main process (`dev:main`) and the Vite renderer (`dev:renderer`) concurrently. Keep this terminal open while developing. You can also run the same command from the repo root with `pnpm --filter ./apps/desktop-app dev`.

### Faster iterative builds

For day-to-day development you can build only the pieces that change:
If you pull dependency changes later, refresh them with:

```bash
pnpm --filter @bros/shared build
pnpm --filter @bros/ui build
pnpm --filter @bros/runner build
pnpm --filter @bros/validation build
pnpm --filter ./apps/desktop-app build:main # one-off compile
# or keep it running:
pnpm --filter ./apps/desktop-app build:main:watch
pnpm install -r
```

The order above guarantees that the Electron main process sees fresh declaration files.

### Run the desktop app in dev mode
## ROS 2 Dev Notes

Start the renderer and Electron in separate terminals (after running `build:main` at least once):

```bash
# Terminal 1 – Vite dev server for renderer assets
pnpm --filter ./apps/desktop-app dev

# Terminal 2 – Electron, pointing at the dev server
pnpm --filter ./apps/desktop-app electron:dev
```

If you are not running `build:main:watch`, re-run `pnpm --filter ./apps/desktop-app build:main` whenever main-process or preload code changes, then restart `electron:dev`.

## Using the Preload Bridges

The preload script exposes two namespaces:
The preload bridge exposes `window.runner` for Docker-backed ROS 2 sessions and `window.ir` for graph validation.

```ts
window.runner.up(projectName: string): Promise<void>
window.runner.exec(command: string): Promise<{ stdout: string; stderr: string; code: number }>
window.runner.down(): Promise<void>
window.runner.up(projectName: string): Promise<void>;
window.runner.exec(command: string): Promise<{ stdout: string; stderr: string; code: number }>;
window.runner.down(): Promise<void>;

window.ir.build(graph: BlockGraph): Promise<{ ir: IR; issues: string[] }>
window.ir.validate(ir: IR): Promise<{ errors: Issue[]; warnings: Issue[] }>
window.ir.build(graph: BlockGraph): Promise<{ ir: IR; issues: string[] }>;
window.ir.validate(ir: IR): Promise<{ errors: Issue[]; warnings: Issue[] }>;
```

### Runner sanity check (DevTools)

With Docker running, open DevTools (`View → Toggle Developer Tools`) and run:
With Docker running and the app in dev mode, open DevTools (`View → Toggle Developer Tools`) and run:

```js
await window.runner.up("hello_ros");
Expand All @@ -122,7 +81,7 @@ await window.runner.exec("ros2 pkg list | head -n 5");
await window.runner.down();
```

You should see Docker bring up a container named `bros_hello_ros`, and new files appear under `~/BROS/Projects/hello_ros/`.
This spins up the `bros_hello_ros` container defined in `Projects/hello_ros` and exercises the ROS 2 CLI.

### IR build + validation example

Expand All @@ -139,56 +98,25 @@ const { errors, warnings } = await window.ir.validate(ir);
console.log({ issues, errors, warnings });
```

## Testing

- Validation rules (`@bros/validation`):

```bash
pnpm --filter @bros/validation test
```

Runs Vitest covering duplicate node detection, topic type mismatches, and orphan publishers/subscribers.

- UI + shared packages (when tests are added):

```bash
pnpm --filter @bros/ui test
pnpm --filter @bros/shared test
```
## Cleaning

- Execute every registered suite at once:

```bash
pnpm -r test
```

## Cleaning the Workspace

Remove compiled artifacts everywhere:
Wipe compiled artifacts across every workspace when you need a fresh build:

```bash
pnpm -r clean
```

This clears `dist/`, `release/`, `tsconfig.tsbuildinfo`, and similar outputs for every package. After cleaning run a build to regenerate declarations:

```bash
pnpm -r build
# or rebuild selectively, e.g.
pnpm --filter @bros/validation build
pnpm --filter ./apps/desktop-app build:main
```

To fully reset dependencies:
To reset dependencies as well:

```bash
pnpm store prune
rm -rf node_modules
pnpm install
pnpm install -r
```

## Notes & Tips
- Keep Docker running whenever you interact with `window.runner.*` APIs.
- Rerun `pnpm install` after pulling changes that add or rename workspace packages.
- The bootstrap script is idempotent; rerun it after upgrading your shell or Node toolchain.
- Electron Builder artifacts land in `apps/desktop-app/release/`; use `open` (macOS) or the file manager to launch packaged builds.
After cleaning, rerun `pnpm dev` (or `./apps/desktop-app/scripts/bootstrap.sh`) to rebuild the app.

## Tips
- Keep Docker running whenever you use `window.runner.*`; the runner manages containers in `Projects/`.
- If `pnpm dev` fails because Electron is missing, re-run `node node_modules/electron/install.js`.
- Rerun the bootstrap script after major Node/pnpm upgrades—it is idempotent and safe to run again.
Binary file added assets/logos/BROS2-logo-long.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/logos/BROS2-logo.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.