RoboticsHow-to

Convert a waypoint pose relative to a feature without drift

Convert a waypoint pose relative to a feature, verify it against the move tab, trace the few-millimeter gap to feature and TCP teaching, and fix it.

LumaSpec Vision12 min read Share on LinkedIn

On this page 9 sections
  1. 01How do you read a pose relative to a feature into a variable?
  2. 02Why are the scripted values a few millimeters off the Move tab?
  3. 03Where do the few millimeters actually come from?
  4. 04How do you verify the transform before trusting it?
  5. 05What does the camera need when its field of view is taught to the feature?
  6. 06How do you send the X and Y to the vision system?
  7. 07When is the Move tab the wrong reference?
  8. 08What should you check before shipping the cell?
  9. 09Questions

You taught the camera's field of view to a feature, not to the robot base, and now the vision system needs the X and Y of a waypoint in that feature's frame. The pendant's Move tab shows the values, but a script reading get_actual_tcp_pose() returns base-frame meters, and the numbers you compute land a few millimeters off. Below is the exact script chain, the steps to expose both the live pose and taught waypoints as feature-frame variables, an error budget that explains the gap with arithmetic, and the camera-side numbers a field of view taught to the feature has to hit.

How do you read a pose relative to a feature into a variable?

Chain two script calls: pose_trans(pose_inv(FeaturePose), get_actual_tcp_pose()) returns the live TCP pose expressed in the feature's frame, and the same wrapper turns any stored waypoint pose into feature coordinates. On a Universal Robots controller both are plain URScript, callable from any program. get_actual_tcp_pose() returns the tool-center-point pose in the base frame as [x, y, z, rx, ry, rz]; pose_inv(FeaturePose) inverts the feature's base pose; pose_trans multiplies the two. Elements [0] and [1] of the result are the X and Y the Move tab displays, in meters.

pose_in_feature = pose_trans(pose_inv(FeaturePose), get_actual_tcp_pose()) x_mm = pose_in_feature[0] × 1000 y_mm = pose_in_feature[1] × 1000
  1. On the Features screen, teach the plane and tick Variable, so the controller exposes it as FeaturePose to every program. A feature that is not a variable cannot be referenced from script at all, so check this first.
  2. With the robot sitting at the waypoint, run the chain above and read elements [0] and [1], multiplied by 1000.
  3. For a taught waypoint rather than the live pose, set the waypoint itself to variable in the move command — call it wp — and wrap it identically: wp_in_feature = pose_trans(pose_inv(FeaturePose), wp). That is the whole trick for putting taught numbers into a variable.
  4. To move relative to the feature, compose in the other order: movel(pose_trans(FeaturePose, offset), a, v) drives the tool to offset written in feature coordinates, and reusing MOVEL waypoints with feature planes shows the pattern for waypoints shared across features.

Building the handoff inside a URCap instead of a program changes the plumbing, not the math: how URCaps get poses relative to a feature frame runs the same conversion through the API.

Why are the scripted values a few millimeters off the Move tab?

Because the two numbers are not the same measurement: the tab displays the taught waypoint's target in the feature you selected, while your script reads where the robot actually stopped, through a feature variable and a TCP that each carry teaching error. The transform itself is exact — pose composition in double precision does not manufacture millimeters — so separate the real sources before touching the math:

  • Target against actual. The tab shows the commanded target; get_actual_tcp_pose() reports where the arm really stopped. At rest the two sit within the pose repeatability a six-axis cobot datasheet quotes, 0.02 to 0.1 mm. Not your gap.
  • Typed constants. If the feature's numbers were copied into the script, every later re-teach changes the tab but not your script, by exactly the re-teach delta. Reference FeaturePose, never a copy.
  • Active tool. The tab transforms positions with whatever tool is selected on the pendant. A different tool shifts readings by the offset between the two TCP definitions — tens of millimeters, hard to miss. The same tool leaves only the residuals in the next section.

Where do the few millimeters actually come from?

Almost always from the plane's rotation error acting over the distance between the feature origin and your point: half a degree of rotation, normal for a hand-taught plane, moves a point 200 mm out by 1.7 mm even with a perfect origin. The origin error is a constant offset; rotation is a lever that grows with distance, which is why the discrepancy changes between waypoints.

position error ≈ distance × sin(rotation error) 200 mm × sin(0.5°) = 200 × 0.0087 ≈ 1.7 mm
Source Typical size At a point 200 mm from the origin
Plane rotation, 0.2-0.5° hand-taught lever × sin(angle) 0.7-1.7 mm
Plane origin touch 0.2-0.5 mm 0.2-0.5 mm
TCP taught from 3-4 touches 0.1-0.5 mm 0.1-0.5 mm
Actual against commanded at rest 0.02-0.1 mm negligible

Combine the mid-range values as a root sum of squares — 1.2 mm of lever, 0.3 mm of origin, 0.3 mm of TCP: √(1.2² + 0.3² + 0.3²) = √1.62 ≈ 1.3 mm. That is the few millimeters, and none of it lives in the transform.

Re-teach the plane with its three points as far apart as the fixture allows, using the sharpest tip you can jog accurately. Touched to 0.2 mm on points 200 mm apart, the rotation error falls to about 0.06° and the whole budget drops under 0.5 mm. When the residual appears only on rotated parts, chase the rotation term — vision pick error under rotation: diagnose position drift works that case end to end.

How do you verify the transform before trusting it?

Drive the TCP to the feature origin and read your script's X and Y: both should sit within 0.3 mm of zero, and a 100 mm jog along the feature's X axis should move X by 100.0 ± 0.3 mm while Y stays inside ± 0.3 mm. Five checks, ten minutes, and every failure mode above has a signature:

  1. Origin check. Jog to the feature origin; script X and Y within 0.3 mm of zero passes.
  2. Axis check. Jog 100 mm along the feature's X axis; ΔX = 100.0 ± 0.3 mm and ΔY within ± 0.3 mm passes. Y creeping as X grows is the rotation lever above.
  3. Round trip. pose_trans(FeaturePose, pose_in_feature) must return the base pose you started from, within 0.1 mm; if it does not, FeaturePose is not the feature the tab is showing.
  4. Units. Multiply script meters by 1000 before comparing anything to the tab's millimeters.
  5. Selections. Same tool and same feature active on the pendant as in the program, then compare at one shared point.

What does the camera need when its field of view is taught to the feature?

A camera whose field of view is taught to the feature works entirely in feature-frame millimeters, so it needs a pixel-to-millimeter scale calibrated at the feature plane, a field of view covering the feature with margin, and pixels enough that vision error stays far below the robot-side budget. Take a fixture with 200 × 150 mm of usable area at a 400 mm working distance:

How sensor width, working distance and field of view set the focal length Rays from the edges of the sensor pass through the lens and spread to the edges of the field of view. The ratio of sensor width to field of view is the magnification m.CameraField of view (FOV)Working distance (WD)≈ fsensor width slensm = s / FOVf = WD × m / (1 + m)
How sensor width, working distance and field of view set the focal length. Rays from the edges of the sensor pass through the lens and spread to the edges of the field of view. The ratio of sensor width to field of view is the magnification m.
m = sensor width / field of view f = WD × m / (1 + m)
  • Margin: 10 percent each side sets the required field of view at 220 × 165 mm.
  • Magnification: m = 7.2 / 220 = 0.033 with a 1/1.8-inch sensor, about 7.2 × 5.4 mm.
  • Focal length: f = 400 × 0.033 / 1.033 = 12.7 mm, so order a 12 mm lens.
  • Check: field of view = sensor × (WD − f) / f = 7.2 × 388 / 12 ≈ 233 mm wide and 5.4 × 388 / 12 ≈ 175 mm high, covering 220 × 165 with room to spare.
Lens focal length, field of view and working distance
Units
Solve for
Focal length
– mm
Field of view
– mm
Working distance
– mm
Magnification
– x
Angle of view
– °
Pixel on the part
– mm

Thin-lens model: m = sensor width / field of view, f = WD × m / (1 + m). Accurate to a few percent above about 150 mm; check the lens's minimum object distance.

Find lenses with this focal length Open the full calculator

A 6 MP sensor in this format is about 3072 × 2048 pixels, so the scale at the plane is 233 / 3072 ≈ 0.076 mm per pixel and a half-pixel edge error is 0.04 mm — roughly twenty to forty-five times finer than the 0.7-1.8 mm robot-side budget. The optics are not the problem; the feature teaching is. How much of the frame a fixture may occupy has its own rule: calibration target field of view and lens coverage margins gives those numbers. An overhead mount changes the geometry, not the method — hanging robot vision calibration: teach the work plane covers teaching the plane from a camera above the cell.

For a single-station cell, this class of camera on a C-mount covers the window with room to grow:

Area scan camerasHikrobot MV-CT0MG0060/R/NN/NN 6 MP Area Scan Camera, 3rd Gen., GigE, Mono, BASEMV-CT0MG0060/R/NN/NN
Sensor format
1/1.8"
Lens mount
C-mount
Interface
GigE
Resolution
6-10 MP
$909.00View partBuild a system with it

The camera above is a 6 MP GigE area scan camera with a 1/1.8-inch sensor, mono output and a C-mount. On a 12 mm lens it delivers the 233 mm field of view from the example. When the detection should stay on the device, smart cameras output feature-frame coordinates with no PC in the loop; smart camera hand-eye calibration when no wizard exists covers the vision side where no calibration wizard is available. The MV-SC5060XM-08M-WBN is a 6 MP mono smart camera with a fixed 8 mm lens on an M12 mount and a GigE interface.

Smart cameras & vision sensorsHikrobot MV-SC5060XM-08M-WBN SC5000X series Smart Camera, 6 MP, Mono, 8 mm focal length, M12-mountMV-SC5060XM-08M-WBN
Interface
GigE
Resolution
6-10 MP
Sensor format
1/2.4"
Shutter
Rolling
$1,629.00View part

Its 1/2.4-inch sensor frames a smaller field of view at the same working distance, so re-run the numbers above before swapping formats. Past one station, vision controllers host several cameras and the feature-frame bookkeeping in one box; the MV-VC5525-256G70-NN carries PoE camera ports and eight built-in light channels. For images that also feed review or archiving, area scan cameras remain the flexible pick.

How do you send the X and Y to the vision system?

Round to 0.01 mm and send one ASCII line per position over a network socket — X and Y in millimeters with fixed decimals — because a fixed-format line survives controller and vision-side upgrades better than raw floats or scaled registers. On the robot that is three URScript calls: socket_open, socket_send_line, socket_close. Two variants and the handshake matter more than the transport:

  • Modbus instead of sockets: write X and Y to two holding registers in 0.01 mm units; a 16-bit register covers ±327 mm, enough for any one feature.
  • Handshake at connect: have the vision side echo the pixel-to-millimeter scale it is using, so a stale calibration fails at link-up instead of at the first rejected part.
  • Pairing: when a vision result must be matched to the robot position that triggered it, timestamps do the matching — asynchronous vision result frame matching with timestamps sets that up.

When is the Move tab the wrong reference?

Whenever the script and the tab disagree by more than the 0.7-1.8 mm budget, trust neither and re-teach: the tab is only as good as the feature and tool currently selected on the pendant, and both sit one re-teach away from the copy your program holds. Read the pattern, then act:

  • Under about 2 mm and repeatable — teaching error. Re-teach the plane with points spread wide, then re-run the checks.
  • Different every run — the pendant's tool or feature selection differs from the program's. Align them.
  • Constant offset in one axis at every point — the origin touch. Re-touch the origin point only.
  • Offset grows with distance from the origin — rotation. Re-teach the plane, wider.
  • Camera or mount moved since the field of view was taught — the feature-frame shortcut is broken; run a full hand-eye calibration, starting from robot hand-eye calibration: how nine-point alignment works. The reverse direction, camera results into base-frame picks, is using eye-to-hand calibration results to compute robot-base picks.

The handoff exists on every controller and only the words change: on a Yaskawa robot it is user-frame assignment plus relative-job conversion, and converting a job to run in a user frame walks that version through.

What should you check before shipping the cell?

Run the checks below after any re-teach of the feature, the tool or the camera mount; they take under ten minutes and catch every failure mode in this guide, and each line says why it is on the list.

  • The feature is a variable and the script reads FeaturePose — typed constants silently diverge after the next re-teach.
  • Origin check passes — X and Y within 0.3 mm of zero at the feature origin.
  • Axis check passes — a 100 mm jog moves X by 100.0 ± 0.3 mm with Y inside ± 0.3 mm.
  • Units converted — meters to millimeters before any value leaves the robot.
  • Vision echoes its pixel-to-millimeter scale at handshake — catches a stale calibration at connect time.
  • Residual against the Move tab sits inside the 0.7-1.8 mm budget — otherwise the plane gets re-taught wide.
  • Field of view covers the feature with 10 percent margin and the scale was calibrated at the plane, not assumed from the lens.

Start the camera step below with your fixture's field of view and working distance, see the robotics topic page for the other robot-side calibration guides, and bring the feature-frame numbers of a cell already built to the contact page.

Build the whole station

The configurator matches a camera, lens, light, light controller and cables to each other, step by step, and lists only parts that fit what you already picked.

Start with the camera

Questions

Does the pose chain also give the orientation relative to the feature?

Yes. Elements three to five of the result are the TCP rotation vector expressed in the feature axes, in radians. Multiply elements zero and one by 1000 for millimeters, and leave the rotation vector in radians unless the receiving system wants a rotation matrix — convert before sending, because most vision interfaces expect degrees or a matrix, not a raw rotation vector.

Why does the pendant show millimeters when the script returns meters?

The pendant displays positions in millimeters and rotations in degrees for the operator; the script pose array stores meters and radians. Multiply x and y by 1000 before comparing, and convert the rotation vector if you compare angles. A mismatch that is almost exactly a factor of 1000 is this unit difference, not drift, and it is the first thing to rule out.

How far apart should the three plane-teaching points be?

As far apart as the fixture allows, because the taught plane angular error scales inversely with point spacing. Points 50 mm apart touched to 0.2 mm leave about 0.23° of rotation error, which is 0.8 mm at 200 mm from the origin; the same touches on points 200 mm apart leave 0.06°, which is 0.2 mm. Wider spacing beats more careful touching.

Should the robot or the vision system own the feature frame?

The robot owns it. The feature is taught where the parts physically sit, so the robot feature variable is the master and the vision system calibrates its pixel-to-millimeter scale against that same physical plane. If the camera moves or the fixture is rebuilt, re-teach the robot feature first and hand the new frame to vision — never edit the vision scale to absorb a robot-side change.

Can you skip hand-eye calibration when the camera is taught to the feature?

For picks inside that one taught field of view, yes: the camera reports feature-frame coordinates and the robot consumes them directly, so no camera-to-base transform is ever used. Add hand-eye calibration when parts arrive outside the window, when the camera or robot might move between runs, or when results must be reported in base coordinates for traceability.