Advanced Metal Research
GitHub Contact AMR

Weld planning, verification and evidence

On this page
  1. The pipeline
  2. What the verifier checks
  3. Collisions
  4. Limits
  5. The tracking certificate, welds only
  6. Verdicts
  7. What admission requires
  8. What is not verified
  9. The plan result
  10. Related pages

The weld planner turns a CAD part and a program into joint trajectories that the robot can play. It then proves, against the cell model, that those trajectories are clear of collisions and inside the joint limits, and it only writes the playable file if that proof holds for every segment.

This is the only verification path in RosieOS. Nothing else in the system checks a motion against the cell geometry. Read What is verified before motion in the safety model first. This page explains what that check covers.

1 · AUTHOR (OLP + SEAM WORKER) STEP part imported, placed on the cell Seam worker weld joints, seams, torch angle search, trim or accept Program robot.v4.program.v2 weld nodes, taught moves .weldplan program, cell, tooling, STEP, fixtures, digests 2 · PLAN (WELD PLANNER :8796, CUDA) M4 seam search sampled poses, sphere model M5 + M6 trajopt weld curves, moves between Verifier exact meshes, limits, tracking certificate Admission + .rdt every segment PASS, or no trajectory is written 3 · LOAD AND RUN Simulate replays the exact bytes optional operator step OLP Load fetch by digest, identity, Home, no process outputs rt-control admission positions, velocities, steps, digest Play motion start gate in rosie-rt-core Not on this path, and not verified: jog, joint and Cartesian moves, Home, Go to plan start, direct rtctl or SDK commands.
The red box is the verifier: the only place RosieOS checks motion against the cell geometry. No .rdt exists unless every segment passes it.

The pipeline#

  1. Author. You import a STEP part in offline programming (OLP) and place it on the cell. The seam worker finds the weld joints, proposes seams and searches the torch work and travel angles along each one. You accept or trim each weld. Taught moves, dwells and Home can go in the same program. See Program a weld from CAD.
  2. Pack. OLP packs the program, the cell descriptor, the torch, the STEP file and any fixtures into one .weldplan container, with a SHA-256 digest for every member. See the weld program format.
  3. Plan. The weld planner runs three stages on an NVIDIA GPU:
    • M4, seam search. A dynamic program over a sampled lattice of robot poses, including positioner angles, finds the K best ways across each seam. It screens each sampled pose against a sphere model of the arm. The result is exact within the sampled lattice. It is not a continuous check.
    • M5, weld trajectory optimisation. Each seam's best candidates become a continuous curve (cubic Hermite knots and velocities) that keeps the tool on the seam.
    • M6, connecting moves. The approach from the cell's reset pose, the transits between welds, the retract, and any taught moves.
  4. Verify. Every M5 curve and every M6 move goes to the verifier, which judges it against the exact cell meshes.
  5. Admit and encode. Admission reads the verifier's reports. If every segment passed, the planner resamples the plan into a dense trajectory (.rdt) and files it by digest. If not, no .rdt exists.
  6. Load and run. OLP's Load fetches the .rdt by digest from the planner's store. It checks the plan's identity, the robot description and cell calibration and Home. rt-control then admits it against the live machine. See Connect to a cell and run a program.

The search stages use a fast, approximate collision model: the arm as spheres, and everything it must not hit as signed-distance fields. The verifier deliberately uses a different model, the real triangles, so that the approximation cannot certify itself.

What the verifier checks#

The verifier works on the real triangles, in 64-bit floating point on the CPU. It has its own forward kinematics and shares no code with the planner it judges.

Collisions#

The verifier does not sample waypoints. For each segment it bounds how fast any point of each link can move. It then asks whether each pair of bodies is further apart, at the middle of an interval, than that bound allows the gap to shrink across the interval. If so, no contact exists anywhere in the interval. If not, it halves the interval and asks again. It stops after 10 halvings, and reaching that depth is a refusal, never a pass.

BodiesChecked against
Every robot and positioner link that has a mesh in the robot descriptionEvery other link, except links joined by a joint, which touch by construction
The workpiece, tessellated from the request's STEP file and posed by the placementThe links
Fixtures from the request, in the cell's world frameThe moving arm links and the workpiece only

A pair counts as a collision when it comes closer than the verification margin: 2 mm by default, set by verify_margin_mm (0 to 50 mm). The margin exists because the cell meshes are the visual meshes and fixtures are measured by hand. The report counts collisions, and separately penetrating for pairs that actually touch or overlap.

The verifier refuses to judge a trajectory against a cell it cannot see. If the robot's meshes are missing, planning fails with an error rather than passing.

Limits#

  • Joint positions. Checked against each joint's limits in the cell descriptor. A joint with no position limit is reported as unverifiable.
  • Joint velocity and acceleration. Checked against the rate limits in the cell profile, which come from the robot description's config.json, narrowed by the cell. For connecting moves the check uses the exact extrema of the cubic Hermite curve that is emitted, not only the knots. A joint with no rate limit is reported as unverifiable.
  • Travel mobility, welds only. Whether the joints can deliver the programmed travel speed along the seam direction without exceeding their rate limits. This catches poses near a singularity, where a slow tool speed would need very fast joints.

The tracking certificate, welds only#

The verifier also bounds how far the tool point can be from where it belongs on the seam, at every instant between samples, not just at the samples. The tolerance is the seam's tolerance.position_mm, 0.5 mm by default. The certificate is exact for straight seam segments. For a curved seam segment the bound does not exist yet, so the certificate reports it as unverifiable, and the weld cannot pass.

"Tracking" here means this geometric certificate on the planned path. There is no seam tracking or sensing in RosieOS: nothing measures the real seam while welding. See Process I/O and sensing.

Verdicts#

Each report has one of three verdicts:

VerdictMeaning
PASSEvery check ran and passed, and nothing was unverifiable
REFUSEDNo failure was found, but at least one check could not run (it is listed in unverifiable), or the tracking search was undecided
FAILA collision, a limit violation or a tracking violation was found

The distinction the verifier keeps is between "checked and clear" and "not checked". A missing rate limit is not a passed rate check.

What admission requires#

Admission is the gate between the planner's result and the .rdt file. It is require_native_motion() in weldplan/native_admission.py, and it runs before any dense resampling. A plan gets a .rdt only if all of these hold:

  1. The connecting-move stage did not fail. Otherwise: motion_join_failed.
  2. seams and connecting_trajectories are lists of objects, and every seam has a non-empty, unique id. Otherwise: motion_result_invalid.
  3. Every seam was crossed by the search, with no error. Otherwise: seam_not_planned, with where the search stopped and why (poses outside joint travel, rejected by sphere screening, unreachable by inverse kinematics, or with no allowed step from the previous sample).
  4. Every seam has a continuous trajectory. Otherwise: motion_not_verified.
  5. Every seam trajectory's verdict is PASS, with collisions, penetrating and limit_violations all exactly 0 and unverifiable empty. Its limit_violations and limit_unverifiable lists are empty. Otherwise: motion_not_verified, with the measured numbers and up to the first few findings (which bodies, which joint, how far).
  6. Every seam's tracking certificate is PASS, with no segment out of tolerance, nothing undecided or unverifiable, and a finite bound between 0 and the declared tolerance. Otherwise: motion_not_verified.
  7. Every connecting move is an approach, transit or retract whose verdict is PASS, with collisions, penetrating and limit_violations all 0 and unverifiable empty. Otherwise: motion_result_invalid or motion_not_verified.

A separate candidate-only mode, used for saving authored welds that have not been planned, refuses any continuous motion with candidate_only_requires_m4, so it cannot be used to get around a failed report.

If you turn verification off (verify=false), the trajectories carry no verdict, admission refuses them, and no .rdt is written. The OLP server always asks for verification.

Admission reads the planner's own reports. It does not authenticate a result document, and it does not re-verify the resampled .rdt; see below.

What is not verified#

Be precise about the limits of this check:

  • Motion outside planned programs. Jog, joint and Cartesian moves, "All joints to 0°", Home, go-home, Go to plan start, and anything sent through rtctl, the SDKs or the dense trajectory daemon never pass through the verifier. They rely on rt-core's limit and readiness checks only. See the motion start gate.
  • Physics. The verifier is a geometric certificate, not a simulation. It does not model torques, payload, following error, drive behaviour or jerk.
  • Anything not in the model. People, cables, clamps you did not enter as fixtures, a part that differs from its CAD file, or a part placed somewhere other than its placement says. The result is only as good as the cell meshes, the robot description, the cell calibration and the placement.
  • The M4 screen. The seam search checks sampled poses against spheres. Its findings are reported as screening results, "not a continuous mesh collision certificate". Only the continuous M5 and M6 output is certified.
  • The exported representation. The .rdt is a resampling of the verified curves on a 0.01 s grid. The exporter slows the start and end of each weld pass with a 0.25 s ramp and adds a 3 s stationary dwell before and after each pass. Positions stay on the certified path, but the verifier does not re-judge the resampled file. The encoder checks its own rules instead: segments start and end at rest, consecutive segments meet within 0.001 rad, no sample-to-sample step is larger than the velocity ceiling allows (with 25 % interpolation slack), and no axis exceeds the cell's per-axis velocity ceiling (qd_limit_exceeded). See the .rdt format.
  • Plan speed. speed_scale (1 % to 100 %) slows the whole plan after planning. The path, and so the clearance and tracking certificates, are unchanged, and the original velocity and acceleration checks stay conservative for any scale up to 1.
  • The weld. Nothing checks bead quality, arc behaviour or process parameters. Torch outputs are refused everywhere, so no program can switch a torch on. See Process outputs are refused.

You can replay the exact .rdt bytes before Load, in the 3D viewer or on the local simulator. That replay is an operator step. The software does not require it.

The plan result#

The planner answers with a result document, schema amr-weld-planner-v1.motion-plan-result.v1. Angles are in degrees and lengths in mm on the wire. The document is the evidence for a plan:

BlockWhat it records
requestThe SHA-256 of the exact .weldplan bytes, the request, program and cell ids, the cell descriptor summary, the source STEP and its digest, every member's digest, and the placement
producermodule (amr-weld-planner/v1) and source_revision: the full 40-character Git commit of the planner code, or null with source_revision_state: "unavailable" when it was not supplied
candidate_searchHow M4 searched: dynamic_programming_over_discrete_redundancy_lattice, minimising the sum of absolute joint motion, exact_within_the_sampled_lattice
coverageWhat was and was not evaluated; see below
optionsEvery planning option actually used, flat, with verify_margin_mm in mm
timings_msWall time per stage, in pipeline order
seams[]Per seam: whether it was crossed, the K candidates, and the continuous trajectory with its verdict and tracking reports
connecting_trajectories[]The moves, each with kind, from, to, knots, clearance_mm and verdict
dense or dense_errorThe .rdt summary, or the reason none was written

The coverage block states the claim limits in the document itself:

KeyValues
candidate_collision_screeningsampled_lattice_nodes or not_evaluated
candidate_limit_checksreported_per_candidate
weld_trajectory_continuous_verification, connecting_trajectory_continuous_verificationevaluated_for_all_emitted_trajectories, partially_evaluated or not_evaluated
canonical_motion_serverAlways not_evaluated
physical_motionAlways not_evaluated
execution_authorityAlways none

A plan result grants no authority to move anything. Authority comes from the rt-control lease when you Load and Play. See One controller at a time.

When a plan comes back without a .rdt, the planner keeps the request and its full result under <dense store>/refused/, named by the request digest, so you can diagnose it without planning again. It keeps the newest 5.

The .rdt header carries the plan identity (plan_id, program_id, program_digest, revisions) and the robot description and cell calibration identities the plan was made against. program_digest is sha256: plus the digest of the .weldplan request, and plan_id is <program_id>:<first 12 hex characters of that digest>. OLP's Load refuses a plan made for another robot description or cell calibration. See Robot description and coordinate frames.