# Program a weld from CAD

> Create a program in offline programming, import and place a STEP part, define welds from its edges with the seam search, plan and verify them with the weld planner, replay the result in simulation, and read a refusal.

URL: https://advancedmetalresearch.com/docs/guides/offline-programming
Section: RosieOS docs / Guides
Last updated: 2026-10-10

This guide takes a STEP part to a verified, simulated weld program in the offline programming (OLP) app. You import the part, place it on the cell, pick welds from its edges, plan them with the weld planner and replay the result. Nothing here moves a robot. Running the program on a cell is the next guide, [Connect to a cell and run a program](https://advancedmetalresearch.com/docs/guides/connect-a-cell).

## Before you start

You need three things running:

- **The OLP server and UI.** The [quickstart](https://advancedmetalresearch.com/docs/get-started/quickstart) starts both. Open `http://127.0.0.1:5189/offline-programming/v1/ui/`.
- **The weld planner**, with an NVIDIA GPU, and OLP pointed at it with `OFFLINE_PROGRAMMING_WELD_PLANNER_MOTION_ORIGIN`. The OLP launcher prints `motion:` with the origin it uses. See [Run the weld planner](https://advancedmetalresearch.com/docs/guides/run-the-weld-planner).
- **The CAD environments.** STEP import runs in the `cadquery/v1` pixi environment, and seam detection in the `weld_planner/v1` `default` environment. Install both with `pixi install` in each directory.

Programs live in your browser's storage (IndexedDB) for the page's origin. A different host name or port is a different store. Use **Export .weldplan…** or the catalogue to keep a copy elsewhere.

## 1. Create a program

Open the **Program** menu (☰) and choose **New program…**. Give it a name and press **Create program**. Your current program is saved first.

Every new program is a rails program: once it has a part, the weld planner is its planner.

In the **WORKSPACE TREE**, select **Workspace** to see the robot model (**Rosie 1400 V3** or **Rosie 1420 V1**) and the cell settings. If you will run the program on a cell, choose that cell from the **Cells** menu now and use **Pull cell settings**, so the plan is made against the cell's own calibration. Offline, **Load machine_planning_calibration.json…** plans against a calibration file instead.

## 2. Import the part

On the toolbar, open **Import** and choose **Weld parts from files…**, then pick one or more `.step` or `.stp` files. Each part gets its own placement and welds. The same menu lists STEP files you imported before, kept in this browser, so you can import them again without the file browser.

Add anything else the robot must clear:

- **Import › Fixtures / obstacles from files…** adds STEP geometry as fixtures.
- Right-click in the tree and choose **Add a stand** for a simple stand under the part.

The weld planner plans around every fixture you add, and the verifier checks the arm and the part against them. It knows nothing about bodies you leave out.

## 3. Place the part

Turn on **Move part** (M) and drag an arrow to slide the part along one of its axes, or an arc to turn it. The placement updates when you release. The placement is measured from the robot's work frame, so it means something only on that robot model.

The planner moves the positioner itself. You do not set its joint angles.

## 4. Choose presets

- **Weld presets** hold the process defaults that new welds start from. The shipped preset is "GMAW · mild steel · 6 mm fillet": 6.5 mm/s travel, 0° work angle and 12° travel angle.
- **Plan presets** hold the torch angle search and the fitted torch. The search presets are **Steady** (±15° work, ±40° travel) and **Wide** (±30° work, ±60° travel). The torch presets describe the torch body the search casts against.

## 5. Define the welds

Turn on **Rails welds** (W). Click an edge of the part, or click near the line where two plates meet. OLP matches the click to a detected seam and searches its torch angles at once, in both directions. The result appears in the welds list:

| State | Meaning |
|---|---|
| searching | The seam worker is casting rays and searching angles |
| proposed | The search found a work and travel profile. Decide what to do with it. |
| failed | The search found nothing it could use; the note says why |
| accepted | The weld is in the program as searched |
| trimmed | The weld is in the program, narrowed to its longest clear stretch |

For a proposed weld, press **Accept**, or **Trim** to keep only the longest stretch the torch can reach. Click the row for the detail: the work and travel angle profiles, which you can edit; a coverage strip showing which parts of the seam the torch reaches; and **Trim to longest clear run**, **Accept** and **Remove weld**.

An accepted weld becomes a weld node in the program, with its approach and retract around it. From then on the node is what gets planned. Select it and press **EDIT** to change its span, direction, angle profiles, travel speed, standoff or weave. The field names and units are in the [program format](https://advancedmetalresearch.com/docs/reference/program-format#weld-nodes) and the [seam model](https://advancedmetalresearch.com/docs/reference/weld-program-format#seams).

For a weld that is not an edge of the part, place torch poses by hand instead:

- **Waypoint welds**: torch poses joined as C0, C1 or C2
- **Line welds**: a straight weld between two poses
- **Arc welds**: a circular weld through three poses

OLP turns hand-placed welds into seams before it plans them.

You can add taught moves, dwells, I/O events and Home to the same program. See [Teach waypoints and moves](https://advancedmetalresearch.com/docs/guides/teach-waypoints).

## 6. Plan

Press **Plan** (P). The **Plan** menu shows which planner runs: **Weld planner · B-spline free space** by default. The cuRobo and Catmull-Rom (deprecated) entries only change the solver for the moves between welds.

A progress dialog shows four stages:

1. Packing the program for the weld planner
2. Planning: seam search, weld and connecting trajectory optimisation, verify
3. Keeping the plan and its trajectory
4. Loading the simulation

Planning takes minutes. You can cancel it in the dialog until the result is being kept. When it finishes, the status line reads `Planned · <samples> samples, <seconds> s · press play to simulate`.

What happened: OLP packed a `.weldplan`, the planner planned every weld and move, and the verifier checked each one against the exact cell meshes, the part, your fixtures and the joint limits. The planner wrote a trajectory only because every segment passed. OLP keeps a copy of that trajectory with the program. See [Weld planning and verification](https://advancedmetalresearch.com/docs/concepts/weld-planning-and-verification).

The planner needs the part's STEP file in this session. After a reload, if the status says the STEP is not loaded, import the same file again.

## 7. Simulate

Open the **Simulate & deploy** panel on the right and choose **Simulate**. Press ▶ to replay the planned trajectory in the viewer. These are the exact bytes a cell would play. The transport has stop, step back and forward, a timeline and a playback rate from 1× to 16×. The playback rate does not change the trajectory.

The viewport says **PREVIEW · NO MOTION OUTPUT**. The TCP path overlay shows the planned route: blue for travel and green for welds.

**PLAN SPEED** scales the whole plan's motion from 1 % to 100 % without changing the path. Change it before you plan; after a change, plan and simulate again.

## When planning is refused

A refused plan shows a message and **Technical details** with the planner's own evidence. The common cases:

| Message | What to do |
|---|---|
| Robot settings have changed since this program was created | The robot description changed since you wrote the program. Press **Review robot settings**, then **Accept current settings** in Workspace, and plan again. |
| No candidate motion path was found for a seam (`seam_not_planned`) | The seam search could not cross the seam. The details say where it stopped and why: joint travel limits, sphere collision screening, poses the robot cannot reach, or no allowed step between samples. Move the part, widen the search preset, or trim the weld. |
| No verified motion path is available (`motion_not_verified`) | A continuous check failed or could not run. The details name the bodies in contact, the joint and limit, or the check that was unverifiable. Review the seam, torch pose, part placement, weld speed or fixtures. |
| The welds planned but the moves between them did not (`motion_plan_unjoined`) | Try another free-space solver in the **Plan** menu, or add clearance around the part. |
| Motion origin or seam worker unavailable | Start the weld planner, or install the seam worker's environment. See [Run the weld planner](https://advancedmetalresearch.com/docs/guides/run-the-weld-planner). |

The planner keeps the last 5 refused requests and their results in its store's `refused/` directory, so a refusal can be studied without planning again. The full list of codes is in the [weld planner HTTP API](https://advancedmetalresearch.com/docs/apis/weld-planner-http#a-plan-without-a-trajectory) and the [OLP HTTP API](https://advancedmetalresearch.com/docs/apis/olp-http#weld-plan).

## Export the request

**Program › Export .weldplan…** downloads the exact request the planner would receive. Use it to plan the same program on another machine with the [command line](https://advancedmetalresearch.com/docs/guides/run-the-weld-planner#plan-from-the-command-line), or to keep with the plan result as evidence. The file format is in the [weld program reference](https://advancedmetalresearch.com/docs/reference/weld-program-format#weldplan).

## Next: run it on a cell

> [!WARNING] **Energised motion.** This moves the robot. RosieOS has no software E-stop: keep the hardware E-stop within reach and clear the cell before you arm. Jog, moves and Home are checked against joint limits only, not against collisions. See the [safety model](https://advancedmetalresearch.com/docs/get-started/safety-model).

On a cell, **Deploy** in the same panel homes, arms, loads and plays the program. Load only accepts a trajectory from the planner's store, and it refuses one made for a different robot description or cell calibration. Choose **Dry run · process outputs off**: torch outputs are refused in this release, and there is no seam tracking or sensing, so the robot follows the planned path exactly and nothing corrects it against the real part. **Go to plan start** moves the robot to the plan's first pose with a joint move, which is not verified against collisions. Follow [Connect to a cell and run a program](https://advancedmetalresearch.com/docs/guides/connect-a-cell).

## Related pages

- [Weld planning and verification](https://advancedmetalresearch.com/docs/concepts/weld-planning-and-verification)
- [Teach waypoints and moves](https://advancedmetalresearch.com/docs/guides/teach-waypoints)
- [Weld program and `.weldplan` container](/docs/reference/weld-program-format)
- [Offline programming HTTP API](https://advancedmetalresearch.com/docs/apis/olp-http)
- [Process I/O and sensing](https://advancedmetalresearch.com/docs/concepts/process-io-and-sensing)

## Sources

Written from these files in the RosieOS repository (https://github.com/advanced-metal-research/RosieOS):

- `offline-programming/v1/ui/src/main.ts:446-488,496-560,708,722-812,968-1060,1650-1769,1930-1989,2004-2030,3098-3340,4330-4420,4691-4730`
- `offline-programming/v1/ui/src/rails/index.ts:1-18,80-100,930-1010,1150-1230,1700-1766`
- `offline-programming/v1/ui/src/authoring/programTree.ts:50-110`
- `offline-programming/v1/ui/src/ui/planning-failure.ts:1-73`
- `offline-programming/v1/ui/src/execution/densePanel.ts:541-553`
- `offline-programming/v1/ui/src/rails/parameters.ts:181-200`
- `weld_planner/v1/data/presets/search/steady.json`
- `weld_planner/v1/data/presets/search/wide.json`
- `weld_planner/v1/data/presets/weld/gmaw-steel-fillet.json`
- `weld_planner/v1/python/seam_worker/workers.py:277-316,395-498`
- `weld_planner/v1/python/weldplan/plan_request.py:170-190`
- `weld_planner/v1/python/weld_motion_planner/server/motion_planner_server.py:80-82,346-377`
- `offline-programming/v1/start-offline-programming.sh:499-515`
