Robot Settings

The robots section defines the robots, grippers, coordinate transformations, and motion information required for robot interaction.

A physical robot can be represented by multiple configurations, for example when different grippers are used. Robot settings also describe the positions and motion segments required to approach and execute a grip.

Hand-Eye Calibration: Station-Mounted and Robot-Mounted Cameras

From v2.0.0.

Each robot entry declares where its cameras sit, with cameraMountType:

cameraMountType Meaning

STATIC (default)

No camera of this robot is carried. cameraToRobot holds one hand-eye transform per camera, from the camera to the robot base frame, and cameraToMove is not read. This is the behaviour of every project written before eye-in-hand support, and a project that does not set cameraMountType keeps it.

MOVING

The robot carries the cameras listed in cameraToMove. This map holds one hand-eye transform per camera, from the camera to the robot’s move frame (the link named by moveFrame, normally the flange), not to the TCP. These cameras need the robot’s current move-frame pose for every capture. cameraToMove must not be empty.

cameraMountType is the gate, not the whole answer. Which cameras a MOVING robot actually carries is decided per camera, by whether the camera is listed in cameraToMove. A camera of the same robot that is not listed there is taken to be fixed in the cell: it is still resolved through cameraToRobot and needs no pose. One robot entry can therefore serve a wrist camera and an overhead camera at the same time, and only the wrist camera has to be given a pose.

The move frame is used rather than the TCP for two reasons: it is the frame the robot already reports (IN_PoseMoveInRobot on the PLC interface, and the pose that GetBestResult returns over OPC UA), so the two combine without any further conversion; and it does not change when the TCP is re-taught, so re-teaching a gripper does not invalidate a camera calibration.

Supply the pose with:

  • PLC (PROFINET): write IN_PoseMoveInRobot. LumiScan VGR takes a snapshot of it when it handles IN_TriggerCameraRequest (see Camera Mounted on the Robot).

  • OPC UA: call CaptureImageWithPose, or SetCapturePose followed by CaptureImage. SetCapturePose may also be called after a capture and before ComputeObjects; results already computed from the previous pose are discarded, so they are recomputed with the new one. GetCapturePose reads back the pose currently in effect.

  • User interface: the Set Capture Pose…​ dialog (A15).

In each case the pose is expressed in the robot’s own pose format, the units and rotation convention configured in poseFormat, so it is exactly what the robot reports and what LumiScan VGR returns as a grip pose.

If a capture is attempted with a carried camera and no pose has been supplied, it fails with MISSING_ROBOT_POSE instead of falling back to a guess. A camera of the same robot that is not carried is unaffected and captures normally.

The Recorded Capture Pose

A capture from a carried camera can only be interpreted together with the pose the robot was at, so LumiScan VGR saves that pose with the capture and reads it back when the recording is replayed.

Whenever a capture is exported (exportPcl or exportCenterView) and the active camera is one the robot carries, a file named after the capture is written next to it:

data/<cameraId>/2026-09-22_14-03-51_123.png
data/<cameraId>/2026-09-22_14-03-51_123.ply
data/<cameraId>/2026-09-22_14-03-51_123.pose.json

It holds the move-frame pose in robot base coordinates twice:

  • moveToBase: the 4x4 transform in metres. A replay uses this one, so a recording stays readable even if the project’s poseFormat is changed afterwards.

  • robotFormat: the same pose in the robot’s own format, i.e. the numbers shown on the robot pendant. It is not read back as the pose; it is compared with moveToBase when the file is loaded, so a changed poseFormat shows up as a warning instead of silently changing what every recorded number means.

Replaying the folder with --simulate-camera picks the pose up automatically, so an eye-in-hand recording is reproduced without entering the pose again by hand. This applies only to a simulated camera; a real camera always takes its pose from the PLC, OPC UA or the user interface as described above.

LumiScan VGR cannot currently ask a simulated camera which frame it has just replayed. A dataset recorded from one robot position therefore replays exactly; a dataset recorded from several positions logs a warning naming the pose it used, and only the frames taken at that pose are correct. Split such a recording into one dataset per robot position.

A pose file that is missing, unreadable or does not contain a valid rigid transform is reported and ignored, and the capture then fails with MISSING_ROBOT_POSE, the same refusal as if no pose had been supplied.

What moveFrame Has To Name

moveFrame is the name of a link in the URDF file. The choice is not cosmetic: it is the one setting that three things depend on, and nothing else in LumiScan VGR uses it (inverse kinematics, trajectory planning, collision checking, waypoints and the 3D view are all independent of it):

  1. What LumiScan VGR reports. OUT_PoseMoveInRobot (PROFINET), GripPointPose (OPC UA) and the trajectory are the pose of this link in baseFrame, i.e. the pose the robot is commanded to reach. Pointing moveFrame at a different link shifts every commanded pose by the transform between the two links, with no error anywhere.

  2. What the robot reports. With cameraMountType MOVING, the pose written to IN_PoseMoveInRobot (or passed to SetCapturePose) must be the pose of this same link.

  3. What the camera was calibrated against. cameraToMove is measured from the camera to this same link.

moveFrame is optional. From v2.0.0, an absent moveFrame means the TCP: the end effector of the URDF (its one leaf link), which inverse kinematics places on each grip pose. Name the flange instead when the robot controller is commanded in flange coordinates (no tool configured on the controller). Before v2.0.0 an absent moveFrame fell back to baseFrame, and a separate tcpFrame named the TCP.

With cameraMountType MOVING, moveFrame must differ from baseFrame; the settings file is refused at load otherwise, because a camera cannot be mounted on a flange that is the robot base.

A URDF may attach the move frame through a floating joint, and the standard LumiScan VGR robot model does exactly that: robot_base --(floating)-→ flansch --(fixed)-→ tcp. Inverse kinematics then places a free-floating flange instead of modelling a real arm. This does not affect an eye-in-hand camera: the floating joint is above the move frame while the camera is rigidly below it, and the camera-to-base transform is computed from the supplied pose and cameraToMove alone, without the URDF.