Run the weld planner
On this page
The weld planner lives in weld_planner/v1. It has two halves with different needs:
- The seam worker (CAD topology, weld joints, torch angle search, packing
.weldplanfiles) runs on the CPU in thedefaultenvironment. OLP starts it as a subprocess for every request; you never run it as a server. - The motion planner (seam search, trajectory optimisation, the verifier and the dense trajectory encoder) needs an NVIDIA GPU and runs in the
motionenvironment, as an HTTP server on port 8796.
For what the planner does and what its verification proves, see Weld planning and verification.
Before you start#
- Linux on x86-64 for the
motionenvironment. For an NVIDIA Jetson Thor, see Environments. Thedefaultenvironment also runs on Windows and macOS. - An NVIDIA GPU and a driver that supports CUDA 12 or later. The CUDA runtime comes from the environment; only the driver is the system's.
- pixi. Nothing else: pixi installs Python, CadQuery, PyTorch and the rest.
- A clone of RosieOS with its Git LFS files, because the planner reads the robot meshes from
robot_description/.
Install#
cd weld_planner/v1
pixi install -e default # seam worker and authoring tools (CPU)
pixi install -e motion # motion planner (CUDA PyTorch, several GB)Always pass -e to pixi run for motion tasks. Some task names, such as motion-test, exist in both environments.
Environments#
| Environment | Platforms | Used for |
|---|---|---|
default | linux-64, linux-aarch64, win-64, osx-64, osx-arm64 | The seam worker, CAD inspection tools and the fast self-tests |
motion | linux-64 | The motion planner and its tests, with CUDA PyTorch |
motion-thor | linux-aarch64 | The motion planner on an NVIDIA Jetson Thor. pixi provides everything except PyTorch, which comes from NVIDIA's own image. |
bench | linux-64 | Benchmarks against reference libraries. Not needed to plan. |
The motion environment pins TORCH_ALLOW_TF32_CUBLAS_OVERRIDE=0, so matrix maths keeps full float32 precision on every GPU. The planner was qualified that way.
Check the GPU#
pixi run -e motion motion-gpu # the device, its capability, and whether this PyTorch has kernels for it
pixi run -e motion motion-self-test # every motion worker's smoke check
pixi run -e motion motion-verify # the verifier's self-testServe the motion planner#
cd weld_planner/v1
pixi run -e motion motion-servemotion-serve starts the FastAPI server on 0.0.0.0:8796 and sets AMR_WELD_PLANNER_SOURCE_REVISION to the checkout's git rev-parse HEAD, so every result names the code that planned it. The server logs one line per plan to stderr: MiB in, how many seams were crossed, moves, MiB out, time queued and time served.
Check it:
curl -s http://localhost:8796/api/motion/health
# {"cuda": true, "device": "…"}"cuda": false means PyTorch cannot see the GPU. Planning will not work until it can.
Bind it safely#
Warning
The planner listens on every interface by default, with no authentication. Anyone who can reach port 8796 can queue plans on your GPU and download every stored trajectory. Bind it to localhost when OLP runs on the same machine, or allow only the hosts that need it through a firewall.
When OLP runs on the same machine, bind to localhost:
cd weld_planner/v1
AMR_WELD_PLANNER_SOURCE_REVISION=$(git rev-parse HEAD) \
pixi run -e motion python -m weld_motion_planner.server.motion_planner_server --host 127.0.0.1A Steam Deck pendant plans through a workstation's planner, so there the planner must listen on the network. Firewall port 8796 so that only the Deck (and your own machine) can reach it. For example, with ufw, with the Deck's address in place of the placeholder:
sudo ufw allow from <deck-address> to any port 8796 proto tcp
sudo ufw deny 8796/tcpThe dev stack's motion service runs pixi run -e motion motion-serve, so it too listens on every interface. See Run everything in simulation.
Server options#
| Flag | Environment variable | Default | Description |
|---|---|---|---|
--host | 0.0.0.0 | Listen address | |
--port | 8796 | Listen port | |
--dense-store-dir | WELD_PLANNER_DENSE_STORE_DIR | ~/.cache/rosieos-olp/weld-planner-dense | Where verified .rdt files are stored, by digest. Refused requests are kept under refused/ in the same directory. |
AMR_WELD_PLANNER_SOURCE_REVISION | Set by motion-serve | A full 40-character lowercase Git commit, stamped into results. Any other non-empty value makes every plan fail. |
The store sits outside the checkout on purpose, so resetting the workspace does not delete a trajectory a program still plays. It is still a cache: OLP keeps its own copy of each trajectory, and a Load after the file is gone answers dense_blob_not_found. Plan again.
Connect OLP to it#
OLP reaches the planner through one variable, which the OLP launcher reads:
export OFFLINE_PROGRAMMING_WELD_PLANNER_MOTION_ORIGIN=http://127.0.0.1:8796
bash offline-programming/v1/start-offline-programming.shThe launcher prints a motion: line. motion: DISABLED means the variable is not set. Without it, Plan answers motion_origin_unavailable and Load answers dense_blob_source_unavailable. The dev stack sets it for you. See the OLP server's variables.
OLP also runs the seam worker from weld_planner/v1 for every seam request and every plan. By default it launches pixi run -e default python -m seam_worker.workers --stdin, so the default environment must be installed on the machine that runs the OLP server. Two variables change that:
| Variable | Default | Description |
|---|---|---|
SEAM_WORKER_PYTHON | unset (use pixi run) | A Python executable to run the worker directly |
SEAM_WORKER_SPARES | 2 | Workers started ahead of their request. 0 starts every request cold. |
Plan from the command line#
You can plan a .weldplan without the server. This is useful for looking at one part in detail:
cd weld_planner/v1
pixi run -e motion motion-plan data/motion/bracket_a_2x.weldplan --trajectories --output result.jsonIt prints a summary per seam and writes the full result document to --output. The command line never writes a .rdt. Only the server does, with dense=true.
| Flag | Default | Description |
|---|---|---|
request | required | Path to a .weldplan |
--k | 5 | Candidate paths per seam |
--samples-per-seam | by time | Space the lattice by sample count |
--no-collide | off | Skip collision screening and avoidance. The result says it is unscreened. |
--trajectories | off | Also run M5 and the connecting moves (minutes rather than seconds) |
--no-moves | off | With --trajectories, skip the connecting moves |
--no-verify | off | Skip the verifier. Nothing planned this way can become a .rdt. |
--output PATH | none | Write the result document as JSON |
--source-revision | AMR_WELD_PLANNER_SOURCE_REVISION | The full Git commit to record |
The stages also run alone: motion-seams (M4), motion-weld-trajopt (M5) and motion-link (M6), each with a .weldplan argument.
The committed example requests are in weld_planner/v1/data/motion/. pixi run -e default motion-fixtures rebuilds them from the STEP files in data/fixtures/.
Inspect inputs#
| Task | What it shows |
|---|---|
pixi run -e motion motion-request --read <file.weldplan> | A .weldplan as the planner sees it |
pixi run -e default plan-request --read <file.weldplan> | The container's manifest, with every digest verified |
pixi run -e default program-v2 <program.json> | Problems in a robot.v4.program.v2 document |
pixi run -e motion motion-cell | Which axes are the arm, which move the work, which belong to neither |
pixi run -e motion motion-profile | The cell profile: axis roles, rates, reset pose, and what is missing |
pixi run -e motion motion-spheres | The arm's sphere model and the torch built from tooling.json |
Run any task with --help for its arguments.
Run the tests#
cd weld_planner/v1
pixi run -e motion motion-test # the motion planner's tests, on the GPU
pixi run -e default test # the whole suite in the authoring environment
pixi run -e default self-test # fast smoke checks, no GPUCI runs only a subset of the planner's tests, on a CPU build of PyTorch. Run motion-test on a GPU before you rely on a change.
When something goes wrong#
| Symptom | Cause |
|---|---|
/api/motion/health says "cuda": false | PyTorch cannot see the GPU. Check the driver with nvidia-smi, then pixi run -e motion motion-gpu. |
A plan fails with no cell meshes at … | The robot's meshes are missing. Fetch the Git LFS files. The verifier refuses to judge a cell it cannot see. |
A plan fails at once with a source_revision error | AMR_WELD_PLANNER_SOURCE_REVISION is set to something other than a full commit hash. Unset it, or use motion-serve. |
| A plan answers but has no trajectory | Read dense_error. The request and result are kept under <dense store>/refused/. See A plan without a trajectory. |
| A second plan waits | Only one plan runs at a time. GET /api/motion/progress shows the running stage. |