UnderAutomation
Any question?

[email protected]

Contact us
UnderAutomation
⌘Q
ABB SDK documentation
I/O signals, devices & networks
Documentation home

Motion system, position & kinematics

Read the robot position as a robtarget or a jointtarget, jog the robot, compute forward and inverse kinematics, and manage mechanical units and calibration.

robot.Rws.MotionSystem covers everything about how the robot stands and how it moves: the mechanical units of the system and their axes, where the tool currently is, jogging, the kinematics calculations, the collision supervision and the calibration.

This is the service that moves a real robot. Reading is always safe. Writing needs the mastership of the Motion domain, and most of the time also a controller in manual mode with the motors on, which is read and changed through the control panel.

Geometry types

The positions of the SDK are built from a few small classes of the UnderAutomation.ABB.Common namespace. They are the same types everywhere, so a position read here can be written into a RAPID variable without conversion.

TypeHolds
PositionX, Y, Z
QuaternionQ1 to Q4, an orientation as a unit quaternion
Posea Position plus an Orientation
RobotConfigurationQuarter1, Quarter4, Quarter6 and QuarterX, which say in which turn the axes sit
RobotJointsAxis1 to Axis6, the six axes of the arm
ExternalJointsAxisA to AxisF, the six external axes
RobTargeta Pose plus a Configuration and the ExternalAxes
JointTargetRobotAxes plus ExternalAxes

A pose alone does not say how the robot reaches it. The same point in space is usually reachable in several ways, and RobotConfiguration is what tells them apart.

An external axis the system does not use is reported with a large value instead of a real one. Compare it with the constant ExternalJoints.NotInUse rather than with zero.

Units are not the same everywhere, and this is the convention of the controller, not a choice of the SDK:

WhereUnits
Positions, axis poses and base framesmillimetres, and degrees for the joints
The four kinematics calculationsmetres and radians
Members of Common.Position :
public class Position {
// Initializes a new position at the origin
public Position()
// Initializes a new position
public Position(double x, double y, double z)
// Returns a string representation of this position
public override string ToString()
// Coordinate along the X axis
public double X { get; set; }
// Coordinate along the Y axis
public double Y { get; set; }
// Coordinate along the Z axis
public double Z { get; set; }
}
Members of Common.Quaternion :
public class Quaternion {
// Initializes a new quaternion with no rotation at all (1, 0, 0, 0)
public Quaternion()
// Initializes a new quaternion
public Quaternion(double q1, double q2, double q3, double q4)
// Real component of the quaternion
public double Q1 { get; set; }
// First imaginary component of the quaternion
public double Q2 { get; set; }
// Second imaginary component of the quaternion
public double Q3 { get; set; }
// Third imaginary component of the quaternion
public double Q4 { get; set; }
// Returns a string representation of this orientation
public override string ToString()
}
Members of Common.Pose :
public class Pose : Position {
// Initializes a new pose at the origin, with no rotation
public Pose()
// Initializes a new pose
public Pose(double x, double y, double z, double q1, double q2, double q3, double q4)
// Initializes a new pose
public Pose(double x, double y, double z, Quaternion orientation)
// Orientation held at this position. Never null: a pose built without one carries the identity rotation.
public Quaternion Orientation { get; set; }
// Returns a string representation of this pose
public override string ToString()
}
Members of Common.RobotConfiguration :
public class RobotConfiguration {
// Initializes a new configuration with every quarter revolution set to zero
public RobotConfiguration()
// Initializes a new configuration
public RobotConfiguration(int quarter1, int quarter4, int quarter6, int quarterX)
// Quarter revolution axis 1 sits in
public int Quarter1 { get; set; }
// Quarter revolution axis 4 sits in
public int Quarter4 { get; set; }
// Quarter revolution axis 6 sits in
public int Quarter6 { get; set; }
// Index of the arm configuration, which tells the remaining joint combinations apart
public int QuarterX { get; set; }
// Returns a string representation of this configuration
public override string ToString()
}
Members of Common.RobotJoints :
public class RobotJoints {
// Initializes the six axes to zero
public RobotJoints()
// Initializes the six axes
public RobotJoints(double axis1, double axis2, double axis3, double axis4, double axis5, double axis6)
// Value of axis 1
public double Axis1 { get; set; }
// Value of axis 2
public double Axis2 { get; set; }
// Value of axis 3
public double Axis3 { get; set; }
// Value of axis 4
public double Axis4 { get; set; }
// Value of axis 5
public double Axis5 { get; set; }
// Value of axis 6
public double Axis6 { get; set; }
// Returns a string representation of these joint values
public override string ToString()
}
Members of Common.ExternalJoints :
public class ExternalJoints {
// Initializes the six external axes to zero
public ExternalJoints()
// Initializes the six external axes
public ExternalJoints(double axisA, double axisB, double axisC, double axisD, double axisE, double axisF)
// Value of external axis A
public double AxisA { get; set; }
// Value of external axis B
public double AxisB { get; set; }
// Value of external axis C
public double AxisC { get; set; }
// Value of external axis D
public double AxisD { get; set; }
// Value of external axis E
public double AxisE { get; set; }
// Value of external axis F
public double AxisF { get; set; }
// Value the controller reports for an external axis that is not in use
public const double NotInUse = 9000000000
// Returns a string representation of these external axis values
public override string ToString()
}
Members of Common.RobTarget :
public class RobTarget : Pose {
// Initializes a new target at the origin, with no rotation
public RobTarget()
// Initializes a new target
public RobTarget(double x, double y, double z, Quaternion orientation, RobotConfiguration configuration, ExternalJoints externalAxes)
// Axis configuration used to reach the pose. Never null.
public RobotConfiguration Configuration { get; set; }
// Values of the six external axes, null when the reading does not report them
public ExternalJoints ExternalAxes { get; set; }
// Returns a string representation of this target
public override string ToString()
}
Members of Common.JointTarget :
public class JointTarget {
// Initializes a new joint target with every axis at zero
public JointTarget()
// Initializes a new joint target
public JointTarget(RobotJoints robotAxes, ExternalJoints externalAxes)
// Values of the six external axes. Never null.
public ExternalJoints ExternalAxes { get; set; }
// Values of the six axes of the robot arm. Never null.
public RobotJoints RobotAxes { get; set; }
// Returns a string representation of this joint target
public override string ToString()
}

Mechanical units

AVAILABLE ON
RWS 1.0
RWS 2.0

A mechanical unit is anything the controller drives: the robot arm itself, a track, a positioner. GetMechanicalUnits lists them, GetMechanicalUnit describes one of them, and SetMechanicalUnit changes its properties.

// Every mechanical unit of the system, with its activation state
foreach (MechanicalUnitItem unit in robot.Rws.MotionSystem.GetMechanicalUnits())
{
Console.WriteLine($"{unit.Name} : {unit.Mode}, drive module {unit.DriveModule}");
}
// Everything the controller knows about one unit
MechanicalUnitInfo info = robot.Rws.MotionSystem.GetMechanicalUnit("ROB_1");
Console.WriteLine($"{info.Type}, task {info.TaskName}, status {info.Status}");
Console.WriteLine($"tool {info.ToolName}, work object {info.WorkObjectName}, payload {info.PayloadName}");
Console.WriteLine($"{info.Axes} axes, jog mode {info.JogMode}, frame {info.CoordinateSystem}");
// Axis by axis. Axes are numbered from 1.
int axisCount = robot.Rws.MotionSystem.GetAxisCount("ROB_1");
for (int axis = 1; axis <= axisCount; axis++)
{
AxisInfo axisInfo = robot.Rws.MotionSystem.GetAxis("ROB_1", axis);
Pose axisPose = robot.Rws.MotionSystem.GetAxisPose("ROB_1", axis);
Console.WriteLine($"axis {axisInfo.Number} : {axisInfo.Status}, at {axisPose}");
}
// Where the base of the unit stands, in millimetres
BaseFrame baseFrame = robot.Rws.MotionSystem.GetBaseFrame("ROB_1");
Console.WriteLine($"base frame {baseFrame}, type {baseFrame.Type}");
// Changing a property of a unit needs the mastership of the motion domain.
// Give only the properties you want to change, leave the others null.
robot.Rws.Mastership.Request(MastershipDomain.Motion);
try
{
robot.Rws.MotionSystem.SetMechanicalUnit("ROB_1",
tool: "tGripper",
jogMode: JogMode.Cartesian,
coordinateSystem: CoordinateSystem.Base);
}
finally
{
robot.Rws.Mastership.Release();
}
// The controller answers success even when it could not apply one of the properties.
// Read the unit back to see what it really did.
Console.WriteLine(robot.Rws.MotionSystem.GetMechanicalUnit("ROB_1").ToolName);

MechanicalUnitInfo.Status says whether the unit can move at all:

MechanicalUnitStatusMeaning
SynchronizedCalibrated and synchronized, the unit can be moved
NotCommutatedOne or several motors have not been commutated
NotCalibratedThe unit has never been calibrated
NotAbsoluteSynchronized, NotRelativeSynchronizedThe measurement of one or several axes is not synchronized
Locked, LockedShowThe unit is locked and refuses to move
Initiated, Undefined, UnknownThe unit is starting up, or the controller does not report its state

SetMechanicalUnit needs the mastership of the Motion domain. Give only the properties you want to change and leave the others null. The controller answers with a success status even when it could not apply one of them, so read the unit back to see what it really did.

SetBaseFrame and SetAxisPose declare where a unit or an axis sits in the cell. They do not move anything, they change the calibration of the cell, and the user account needs the matching UAS grant. The controller takes the request and applies the frame afterwards, so a success means the request was accepted, not that the new frame is already in use.

Methods of MotionSystemService :
// Gets the state of one axis of a mechanical unit (synchronous)
AxisInfo GetAxis(string mechanicalUnit, int axis);
// Gets how many axes a mechanical unit has (synchronous)
int GetAxisCount(string mechanicalUnit);
// Gets where one axis of a mechanical unit sits (synchronous) The position is expressed in millimetres.
Pose GetAxisPose(string mechanicalUnit, int axis);
// Gets where the base of a mechanical unit sits (synchronous) The position is expressed in millimetres.
BaseFrame GetBaseFrame(string mechanicalUnit);
// Gets everything the controller knows about one mechanical unit (synchronous)
MechanicalUnitInfo GetMechanicalUnit(string mechanicalUnit);
// Lists the mechanical units of the motion system (synchronous)
MechanicalUnitItem[] GetMechanicalUnits();
// Declares where one axis of a mechanical unit sits (synchronous) The position is expressed in millimetres.
void SetAxisPose(string mechanicalUnit, int axis, Pose pose);
// Declares where the base of a mechanical unit sits (synchronous) The position is expressed in millimetres.
void SetBaseFrame(string mechanicalUnit, Pose baseFrame);
// Changes one or several properties of a mechanical unit (synchronous) Every argument but the unit name is optional; leave the ones you do not want to touch null. At least one of them has to be given.
void SetMechanicalUnit(string mechanicalUnit, string tool = null, string workObject = null, string payload = null, string totalPayload = null, MechanicalUnitMode? mode = null, JogMode? jogMode = null, CoordinateSystem? coordinateSystem = null);
// Places a mechanical unit at the given joint values without moving it there (synchronous) Only a virtual controller accepts this: it teleports the simulated robot, which a real one cannot do.
void SetMechanicalUnitPosition(string mechanicalUnit, JointTarget position);

Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.

Members of Rws.Data.MechanicalUnitItem :
public class MechanicalUnitItem {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.MechanicalUnitItem" data-throw-if-not-resolved="false"></xref> class
public MechanicalUnitItem()
// Whether the unit can be activated, null when the controller did not report it
public bool? ActivationAllowed { get; set; }
// Number of the drive module the unit is connected to, null when the controller did not report it
public int? DriveModule { get; set; }
// Whether the unit is activated
public MechanicalUnitMode Mode { get; set; }
// Name of the mechanical unit, for example "ROB_1"
public string Name { get; set; }
// Returns a string representation of this mechanical unit
public override string ToString()
}
Members of Rws.Data.MechanicalUnitInfo :
public class MechanicalUnitInfo {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.MechanicalUnitInfo" data-throw-if-not-resolved="false"></xref> class
public MechanicalUnitInfo()
// Number of axes of the unit, null when the controller did not report it
public int? Axes { get; set; }
// Reference frame the cartesian positions of the unit are expressed in
public CoordinateSystem CoordinateSystem { get; set; }
// Name of the mechanical unit integrated into this one. A unit that integrates no other one is
// reported with a placeholder name rather than an empty value.
public string HasIntegratedUnit { get; set; }
// Name of the mechanical unit this one is integrated into. A unit that is integrated into no other
// one is reported with a placeholder name rather than an empty value.
public string IsIntegratedUnit { get; set; }
// How the jogging commands sent to the unit are interpreted
public JogMode JogMode { get; set; }
// Whether the unit is activated
public MechanicalUnitMode Mode { get; set; }
// Name of the mechanical unit, for example "ROB_1"
public string Name { get; set; }
// Name of the active payload
public string PayloadName { get; set; }
// Calibration and synchronization state of the unit
public MechanicalUnitStatus Status { get; set; }
// Name of the RAPID task that drives the unit
public string TaskName { get; set; }
// Returns a string representation of this mechanical unit
public override string ToString()
// Name of the active tool
public string ToolName { get; set; }
// Number of axes of the unit and of the units integrated with it,
// null when the controller did not report it
public int? TotalAxes { get; set; }
// Name of the active total payload, which is the payload plus the load of the tool
public string TotalPayloadName { get; set; }
// Kind of mechanical unit
public MechanicalUnitType Type { get; set; }
// Name of the active work object
public string WorkObjectName { get; set; }
}
Members of Rws.Data.MechanicalUnitMode :
public enum MechanicalUnitMode {
// The mechanical unit is activated and takes part in the motion
Activated = 1
// The mechanical unit is deactivated and stays where it is
Deactivated = 2
// The controller reported a mode this library does not know
Unknown = 0
}
Members of Rws.Data.MechanicalUnitType :
public enum MechanicalUnitType {
// No mechanical unit
None = 1
// A robot arm without a tool center point, which can only be moved axis by axis
Robot = 3
// A single external axis, such as a track or a positioner
Single = 4
// A robot arm holding a tool center point, which can be moved in cartesian coordinates
TcpRobot = 2
// The controller knows the unit but does not report what it is
Undefined = 5
// The controller reported a type this library does not know
Unknown = 0
}
Members of Rws.Data.MechanicalUnitStatus :
public enum MechanicalUnitStatus {
// The unit is starting up
Initiated = 1
// The unit is locked and refuses to move
Locked = 7
// The unit is locked, and the controller shows it as such
LockedShow = 8
// One or several absolute measurement axes are not synchronized
NotAbsoluteSynchronized = 4
// The unit has never been calibrated
NotCalibrated = 3
// One or several motors have not been commutated
NotCommutated = 2
// One or several relative measurement axes are not synchronized
NotRelativeSynchronized = 5
// The unit is calibrated and synchronized, and can be moved
Synchronized = 6
// The controller knows the unit but does not report its state
Undefined = 9
// The controller reported a state this library does not know
Unknown = 0
}
Members of Rws.Data.AxisInfo :
public class AxisInfo {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.AxisInfo" data-throw-if-not-resolved="false"></xref> class
public AxisInfo()
// Logical joint number of the axis, null when the controller did not report it
public int? LogicalAxis { get; set; }
// Number of the axis inside its mechanical unit, starting at 1
public int Number { get; set; }
// Calibration and synchronization state of the axis
public MechanicalUnitStatus Status { get; set; }
// Returns a string representation of this axis
public override string ToString()
}
Members of Rws.Data.BaseFrame :
public class BaseFrame : Pose {
// Initializes a new base frame at the origin, with no rotation
public BaseFrame()
// Returns a string representation of this base frame
public override string ToString()
// Kind of base frame the controller reports, for example "IRBRobot"
public string Type { get; set; }
}
Members of Rws.Data.CoordinateSystem :
public enum CoordinateSystem {
// The base frame of the mechanical unit
Base = 2
// The frame of the active tool
Tool = 3
// The controller reported a frame this library does not know
Unknown = 0
// The frame of the active work object
WorkObject = 4
// The world frame, shared by every mechanical unit of the system
World = 1
}
Members of Rws.Data.JogMode :
public enum JogMode {
// The tool is aligned with the closest axis of the active coordinate system
Align = 4
// Each command moves one axis of the first axis group
AxisGroup1 = 1
// Each command moves one axis of the second axis group
AxisGroup2 = 2
// The tool is moved along the axes of the active coordinate system
Cartesian = 3
// The robot changes axis configuration without moving the tool center point
ConfigurationJog = 6
// The robot moves to a given position
GoToPosition = 5
// The controller reported a mode this library does not know
Unknown = 0
}

Read the robot position

AVAILABLE ON
RWS 1.0
RWS 2.0

Four readings answer the same question in four ways. All of them are read only and need no mastership.

MethodReturns
GetRobTarget(unit)RobTarget, the Cartesian position with the axis configuration and the external axes
GetCartesianPosition(unit)RobTarget without the external axes, ExternalAxes is then null
GetJointTarget(unit)JointTarget, the joint values
GetPhysicalJoints(unit)RobotJoints, the raw values of the measurement system of the unit
// Where the tool is, in millimetres, with the axis configuration and the external axes
RobTarget target = robot.Rws.MotionSystem.GetRobTarget("ROB_1");
Console.WriteLine($"X={target.X} Y={target.Y} Z={target.Z}");
Console.WriteLine($"orientation {target.Orientation}");
Console.WriteLine($"configuration {target.Configuration}");
Console.WriteLine($"external axes {target.ExternalAxes}");
// The same reading in another frame, with a given tool and work object
RobTarget inWorld = robot.Rws.MotionSystem.GetRobTarget("ROB_1", CoordinateSystem.World,
tool: "tGripper", workObject: "wobj0");
Console.WriteLine(inWorld);
// The joint values, robot axes in degrees
JointTarget joints = robot.Rws.MotionSystem.GetJointTarget("ROB_1");
Console.WriteLine($"axis 1 = {joints.RobotAxes.Axis1} deg");
Console.WriteLine($"axis 2 = {joints.RobotAxes.Axis2} deg");
// An external axis the system does not define comes back as ExternalJoints.NotInUse
if (joints.ExternalAxes.AxisA != ExternalJoints.NotInUse)
{
Console.WriteLine($"external axis A = {joints.ExternalAxes.AxisA}");
}
// alwaysRead asks the controller to measure again instead of answering with the value it holds
JointTarget measured = robot.Rws.MotionSystem.GetJointTarget("ROB_1", alwaysRead: true);
Console.WriteLine(measured);
// Cartesian position without the external axes. ExternalAxes is null here.
RobTarget cartesian = robot.Rws.MotionSystem.GetCartesianPosition("ROB_1");
Console.WriteLine(cartesian);
// The raw values of the measurement system of the unit
RobotJoints physical = robot.Rws.MotionSystem.GetPhysicalJoints("ROB_1");
Console.WriteLine(physical);
// The same two positions seen from a RAPID task instead of a mechanical unit
RobTarget taskTarget = robot.Rws.Rapid.GetRobTarget("T_ROB1");
JointTarget taskJoints = robot.Rws.Rapid.GetJointTarget("T_ROB1");
// Which external joints of the task carry a real value
RapidExternalJointStates states = robot.Rws.Rapid.GetExternalJointStates("T_ROB1");
Console.WriteLine($"external joint 1 : {states.Joint1}");
// The units the task can move
foreach (RapidMechanicalUnitItem unit in robot.Rws.Rapid.GetMechanicalUnits("T_ROB1"))
{
Console.WriteLine($"{unit.Name} : {unit.Type}, {unit.Mode}");
}

GetRobTarget takes a CoordinateSystem, a tool and a work object. Without them it answers in the base frame of the unit, with the tool and the work object currently active on it. Passing a tool that does not exist is refused by the controller.

GetJointTarget has an alwaysRead parameter. By default the controller answers with the value it already holds. With alwaysRead: true it measures the position again, which costs more and is what you want when the robot has just moved.

Methods of MotionSystemService :
// Gets where the tool of a mechanical unit currently is, without the external axes (synchronous) The position is expressed in millimetres.
RobTarget GetCartesianPosition(string mechanicalUnit, CoordinateSystem coordinateSystem = CoordinateSystem.Base, string tool = null, string workObject = null, bool logErrors = false);
// Gets the joint values a mechanical unit currently stands at (synchronous) The robot axes are expressed in degrees.
JointTarget GetJointTarget(string mechanicalUnit, bool alwaysRead = false);
// Gets the physical joint values of a mechanical unit, as its measurement system reads them (synchronous)
RobotJoints GetPhysicalJoints(string mechanicalUnit);
// Gets where the tool of a mechanical unit currently is (synchronous) The position is expressed in millimetres.
RobTarget GetRobTarget(string mechanicalUnit, CoordinateSystem coordinateSystem = CoordinateSystem.Base, string tool = null, string workObject = null);

Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.

Position of a RAPID task

AVAILABLE ON
RWS 1.0
RWS 2.0

The same two positions can also be read from a RAPID task instead of a mechanical unit. Those methods are on robot.Rws.Rapid, and the last block of the snippet above shows them.

MethodReturns
robot.Rws.Rapid.GetRobTarget(task)RobTarget of the robot of that task
robot.Rws.Rapid.GetJointTarget(task)JointTarget of the robot of that task
robot.Rws.Rapid.GetExternalJointStates(task)What each external joint of the task is doing
robot.Rws.Rapid.GetMechanicalUnits(task)The units the positions of the task are expressed in

Which one to use:

  • Read from the motion system when you work with a mechanical unit by name, when you need another coordinate system, another tool or another work object, or when you want the raw measurement.
  • Read from the RAPID task when your code already works with tasks, or when you want the position exactly as the running program sees it.

GetExternalJointStates is what says how to read the external axis values of the task: a joint can be linear, rotating, inactive, or active without a position. A RobTarget read from a task reports an inactive external axis with the same large value as ExternalJoints.NotInUse.

Methods of RapidService :
// Gets what each of the six external joints of a task is doing (synchronous) This is what says how to read the corresponding value of GetJointTarget(System.String): a joint reported as not active carries no meaningful position.
RapidExternalJointStates GetExternalJointStates(string task);
// Gets the joint values of the robot of a task (synchronous)
JointTarget GetJointTarget(string task);
// Gets the mechanical units the positions of a task are expressed in (synchronous)
RapidMechanicalUnitItem[] GetMechanicalUnits(string task);
// Gets where the tool of a task currently stands, as a position and an orientation (synchronous)
RobTarget GetRobTarget(string task, string tool = null, string workObject = null);

Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.

Members of Rws.Data.RapidExternalJointStates :
public class RapidExternalJointStates {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidExternalJointStates" data-throw-if-not-resolved="false"></xref> class
public RapidExternalJointStates()
// State of the first external joint
public RapidJointState Joint1 { get; set; }
// State of the second external joint
public RapidJointState Joint2 { get; set; }
// State of the third external joint
public RapidJointState Joint3 { get; set; }
// State of the fourth external joint
public RapidJointState Joint4 { get; set; }
// State of the fifth external joint
public RapidJointState Joint5 { get; set; }
// State of the sixth external joint
public RapidJointState Joint6 { get; set; }
// Returns a string representation of these joint states
public override string ToString()
}
Members of Rws.Data.RapidJointState :
public enum RapidJointState {
// The joint moves along a line
Linear = 1
// The joint is active but has no position
NoPosition = 4
// The joint is not active
NotActive = 3
// The joint turns
Rotating = 2
// The controller reported a state this library does not know
Unknown = 0
}
Members of Rws.Data.RapidMechanicalUnitItem :
public class RapidMechanicalUnitItem {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidMechanicalUnitItem" data-throw-if-not-resolved="false"></xref> class
public RapidMechanicalUnitItem()
// Whether the unit is activated
public MechanicalUnitMode Mode { get; set; }
// Name of the unit, for example "ROB_1"
public string Name { get; set; }
// Returns a string representation of this unit
public override string ToString()
// Kind of unit
public MechanicalUnitType Type { get; set; }
}

Move to a target

AVAILABLE ON
RWS 1.0
RWS 2.0

SetPositionTarget sends the robot to a Cartesian target. It really moves the arm. The preconditions are the same as for jogging: the controller in manual mode, the motors on, this client as the local client of the controller, and the mastership of the Motion domain.

SetMechanicalUnitPosition does not move anything. It places the unit at the given joint values. Only a virtual controller accepts it, a real one refuses the call.

// SetPositionTarget really moves the robot to a cartesian target.
// Same preconditions as jogging: manual mode, motors on, local client, motion mastership.
RobTarget target = robot.Rws.MotionSystem.GetRobTarget("ROB_1");
target.Z += 10; // 10 mm up
robot.Rws.Mastership.Request(MastershipDomain.Motion);
try
{
robot.Rws.MotionSystem.SetPositionTarget(target);
}
finally
{
robot.Rws.Mastership.Release();
}
// SetMechanicalUnitPosition does not move anything: it places the unit at the given joint
// values. Only a virtual controller accepts it, a real one refuses the call.
JointTarget joints = new JointTarget(new RobotJoints(0, 0, 0, 0, 30, 0), new ExternalJoints());
robot.Rws.Mastership.Request(MastershipDomain.Motion);
try
{
robot.Rws.MotionSystem.SetMechanicalUnitPosition("ROB_1", joints);
}
finally
{
robot.Rws.Mastership.Release();
}
Methods of MotionSystemService :
// Places a mechanical unit at the given joint values without moving it there (synchronous) Only a virtual controller accepts this: it teleports the simulated robot, which a real one cannot do.
void SetMechanicalUnitPosition(string mechanicalUnit, JointTarget position);
// Sends the robot to a cartesian target (synchronous) The position is expressed in millimetres, in the coordinate system currently active for the mechanical unit selected for jogging.
void SetPositionTarget(RobTarget target);

Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.

Jog the robot

AVAILABLE ON
RWS 1.0
RWS 2.0

Jogging moves the robot step by step, the way the operator does from the FlexPendant. Four conditions have to be met, and none of them can be arranged by a request:

  1. The controller is in manual mode. In automatic mode the request is refused with the HTTP status code 403.
  2. The motors are on.
  3. This client is the local client of the controller.
  4. This connection holds the mastership of the Motion domain.
// Check the preconditions before asking the robot to move
OperationMode mode = robot.Rws.Panel.GetOperationMode();
ControllerState state = robot.Rws.Panel.GetControllerState();
if (mode == OperationMode.Automatic || state != ControllerState.MotorsOn)
{
Console.WriteLine("Jogging is refused in this state");
return;
}
robot.Rws.Mastership.Request(MastershipDomain.Motion);
try
{
// Which unit the jogging commands apply to
robot.Rws.MotionSystem.SetJoggingMechanicalUnit("ROB_1");
// How the six values are read depends on the jog mode of that unit
robot.Rws.MotionSystem.SetMechanicalUnit("ROB_1", jogMode: JogMode.AxisGroup1);
// The change count of the last reading. The controller refuses a command
// built on a state that has moved on since.
MotionSystemInfo info = robot.Rws.MotionSystem.GetInfo();
// One small step on axis 1, nothing on the other five
RobotJoints step = new RobotJoints(100, 0, 0, 0, 0, 0);
robot.Rws.MotionSystem.Jog(step, info.ChangeCount.Value, JogIncrementMode.Small);
}
finally
{
robot.Rws.Mastership.Release();
}
// With JogIncrementMode.None the robot moves for as long as the command is repeated,
// so the loop itself is what stops the motion.
MotionSystemInfo current = robot.Rws.MotionSystem.GetInfo();
RobotJoints speed = new RobotJoints(50, 0, 0, 0, 0, 0);
for (int i = 0; i < 20; i++)
{
robot.Rws.MotionSystem.Jog(speed, current.ChangeCount.Value, JogIncrementMode.None);
System.Threading.Thread.Sleep(100);
}
// Some jogging requests are accepted by the controller and still not honoured.
// The error state says what went wrong.
MotionSystemErrorState error = robot.Rws.MotionSystem.GetErrorState();
Console.WriteLine($"{error.State}, {error.Count} error(s)");

SetJoggingMechanicalUnit chooses which unit the following jogging commands apply to. Jog then sends six values. How they are read depends on the jog mode of that unit, which SetMechanicalUnit sets:

JogModeThe six values are
AxisGroup1, AxisGroup2One value per axis of the group
CartesianA motion of the tool along the axes of the active coordinate system
AlignAn alignment of the tool with the closest axis of the active coordinate system
GoToPositionA position to move to
ConfigurationJogA change of axis configuration that does not move the tool center point

Jog also takes the change count of the last reading of the motion system. The controller refuses a command built on a state that has moved on since, so read GetInfo().ChangeCount before jogging.

JogIncrementModeEffect
NoneThe robot moves for as long as the command is repeated. The loop is what stops the motion.
UserOne step of the size configured in the system parameters
Small, Medium, LargeOne step of the corresponding size

A jogging request can be accepted by the controller and still not honoured. GetErrorState then says why, see the last section of this page.

Methods of MotionSystemService :
// Moves the mechanical unit currently selected for jogging (synchronous) The unit is the one SetJoggingMechanicalUnit(System.String) chose, and how the six values are interpreted depends on its jog mode: axis by axis, along the axes of a coordinate system, and so on.
void Jog(RobotJoints axes, int changeCount, JogIncrementMode incrementMode = JogIncrementMode.None);
// Chooses which mechanical unit the jogging commands apply to (synchronous)
void SetJoggingMechanicalUnit(string mechanicalUnit);

Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.

Members of Rws.Data.JogIncrementMode :
public enum JogIncrementMode {
// One large step
Large = 4
// One medium step
Medium = 3
// The robot moves for as long as the command is repeated, with no fixed step
None = 0
// One small step
Small = 2
// One step of the size configured in the system parameters
User = 1
}

Kinematics

AVAILABLE ON
RWS 1.0
RWS 2.0

The controller can compute where the tool would be for a set of joint values, and which joint values put the tool at a given pose. Nothing moves, and no mastership is needed.

These four calculations work in metres and radians, unlike every other reading of the service. The values are passed and returned in the same classes, only the unit changes.

// These four calculations work in metres and radians, not in millimetres and degrees.
// Tool relative to the mounting flange. Here the flange itself, with no rotation.
Pose toolFrame = new Pose(0, 0, 0, new Quaternion(1, 0, 0, 0));
// Forward kinematics: where the tool would be for these joint values
JointTarget joints = new JointTarget(new RobotJoints(0, 0, 0, 0, 0.5, 0), new ExternalJoints());
RobTarget pose = robot.Rws.MotionSystem.GetPoseFromJoints("ROB_1", toolFrame, joints);
Console.WriteLine($"tool at {pose.X} {pose.Y} {pose.Z} metres, configuration {pose.Configuration}");
// Inverse kinematics: which joint values put the tool at that pose.
// previousJoints decides between the solutions the pose admits.
JointTarget solution = robot.Rws.MotionSystem.GetJointsFromPose("ROB_1", pose, new ExternalJoints(),
toolFrame, joints, pose.Configuration);
Console.WriteLine($"axis 5 = {solution.RobotAxes.Axis5} rad");
// The controller has a second calculation for the same question. It does not always
// pick the same solution.
JointTarget other = robot.Rws.MotionSystem.GetJointsFromCartesian("ROB_1", pose, new ExternalJoints(),
toolFrame, joints, pose.Configuration);
Console.WriteLine(other);
// Every way of reaching the pose. A six axis robot usually has eight.
JointSolution[] solutions = robot.Rws.MotionSystem.GetAllJointSolutions("ROB_1", pose, new ExternalJoints(),
toolFrame, pose.Configuration);
foreach (JointSolution s in solutions)
{
Console.WriteLine($"{s.Configuration} : {s.RobotAxes}");
}
MethodAnswers
GetPoseFromJointsForward kinematics: the pose for these joint values
GetJointsFromPoseInverse kinematics: the joint values for this pose
GetJointsFromCartesianThe same question, through a second calculation of the controller
GetAllJointSolutionsEvery joint combination that reaches the pose, one per axis configuration

GetJointsFromPose and GetJointsFromCartesian take the same arguments and do not always return the same solution. Both are exposed because a controller can accept one and refuse the other. Compare the pose they reach rather than the joint values themselves.

previousJoints is what decides between the solutions a pose admits. Pass the joint values the robot is currently in, so the answer is the closest one.

Set robotHoldsWorkObject to true when the tool is fixed in the cell and the robot carries the work object. Set logErrors to true to have the controller write an event log message when the calculation fails.

A pose that cannot be reached is refused by the controller and reported as an RwsException.

Methods of MotionSystemService :
// Asks the controller for every joint combination that puts the tool at the given pose (synchronous) A six axis robot usually reaches the same pose in eight different ways, each one in a different axis configuration.
JointSolution[] GetAllJointSolutions(string mechanicalUnit, Pose pose, ExternalJoints externalAxes, Pose toolFrame, RobotConfiguration configuration, bool robotHoldsWorkObject = false);
// Asks the controller which joint values put the tool at the given pose, staying close to the joint values the robot is already in (synchronous)
JointTarget GetJointsFromCartesian(string mechanicalUnit, Pose pose, ExternalJoints externalAxes, Pose toolFrame, JointTarget previousJoints, RobotConfiguration configuration, bool robotHoldsWorkObject = false, bool logErrors = false);
// Asks the controller which joint values put the tool at the given pose (synchronous)
JointTarget GetJointsFromPose(string mechanicalUnit, Pose pose, ExternalJoints externalAxes, Pose toolFrame, JointTarget previousJoints, RobotConfiguration configuration, bool robotHoldsWorkObject = false, bool logErrors = false);
// Asks the controller where the tool would be if the robot stood at the given joint values, without moving it there (synchronous)
RobTarget GetPoseFromJoints(string mechanicalUnit, Pose toolFrame, JointTarget joints, bool robotHoldsWorkObject = false, bool logErrors = false);

Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.

Members of Rws.Data.JointSolution :
public class JointSolution : JointTarget {
// Initializes a new solution with every axis at zero
public JointSolution()
// Axis configuration this solution corresponds to. Never null.
public RobotConfiguration Configuration { get; set; }
// Returns a string representation of this solution
public override string ToString()
}

Collision supervision

AVAILABLE ON
RWS 1.0
RWS 2.0

The controller watches the torque of the axes and stops the robot when it meets an unexpected resistance. There is one setting for jogging and one for a programmed path, per mechanical unit.

// Collision detection while the unit is jogged
MotionSupervision jogging = robot.Rws.MotionSystem.GetMotionSupervision("ROB_1");
Console.WriteLine($"jogging supervision {jogging.Enabled}, sensitivity {jogging.Level} %");
// Collision detection while the unit follows a programmed path
PathSupervision path = robot.Rws.MotionSystem.GetPathSupervision("ROB_1");
Console.WriteLine($"path supervision {path.Enabled}, sensitivity {path.Level} %");
// Writing these four values needs the mastership of the motion domain.
// The lower the percentage, the sooner the controller reports a collision.
robot.Rws.Mastership.Request(MastershipDomain.Motion);
try
{
robot.Rws.MotionSystem.SetMotionSupervisionMode("ROB_1", true);
robot.Rws.MotionSystem.SetMotionSupervisionLevel("ROB_1", 80);
robot.Rws.MotionSystem.SetPathSupervisionMode("ROB_1", true);
robot.Rws.MotionSystem.SetPathSupervisionLevel("ROB_1", 80);
}
finally
{
robot.Rws.Mastership.Release();
}
// Collision prediction stops the robot before it hits something the controller
// knows about. It is a separate setting, and it needs no mastership.
bool predicting = robot.Rws.MotionSystem.GetCollisionPredictionMode();
if (!predicting)
{
// Refused when the collision detection option is not installed.
// The error message then names the missing option.
robot.Rws.MotionSystem.SetCollisionPredictionMode(true);
}
SettingApplies while
MotionSupervisionThe unit is jogged
PathSupervisionThe unit follows a programmed path

The level is a percentage. The lower the value, the sooner the controller reports a collision. The four write methods need the mastership of the Motion domain.

Collision prediction is a different feature: it stops the robot before it hits something the controller already knows about, where the supervision only reacts once the arm meets a resistance. GetCollisionPredictionMode and SetCollisionPredictionMode need no mastership.

All of this belongs to the Collision Detection option. On a controller built without it, switching the feature on is refused with the HTTP status code 403 and the SDK reports an error naming the missing option. Writing back the value the controller already holds is accepted.

SetNonMotionExecutionMode is nearby but different: it runs the RAPID program while skipping every motion instruction, which is how a program is tested without the robot leaving its position. It belongs to the editing domain, not to the motion one, so take every domain before calling it.

Methods of MotionSystemService :
// Tells whether the controller predicts collisions before they happen (synchronous) Collision prediction stops the robot before it hits something it knows about, where the motion supervision only reacts once the arm meets an unexpected resistance.
bool GetCollisionPredictionMode();
// Gets the collision detection settings that apply while a mechanical unit is jogged (synchronous)
MotionSupervision GetMotionSupervision(string mechanicalUnit);
// Tells whether the controller runs RAPID programs without moving the robot (synchronous) In that mode the program executes normally but every motion instruction is skipped, which is how a program is tested without the robot leaving its position.
bool GetNonMotionExecutionMode();
// Gets the collision detection settings that apply while a mechanical unit follows a programmed path (synchronous)
PathSupervision GetPathSupervision(string mechanicalUnit);
// Switches collision prediction on or off (synchronous)
void SetCollisionPredictionMode(bool enabled);
// Sets how sensitive the jogging collision detection of a mechanical unit is (synchronous)
void SetMotionSupervisionLevel(string mechanicalUnit, int sensitivity);
// Switches the jogging collision detection of a mechanical unit on or off (synchronous)
void SetMotionSupervisionMode(string mechanicalUnit, bool enabled);
// Chooses whether the controller runs RAPID programs without moving the robot (synchronous)
void SetNonMotionExecutionMode(bool enabled);
// Sets how sensitive the path collision detection of a mechanical unit is (synchronous)
void SetPathSupervisionLevel(string mechanicalUnit, int level);
// Switches the path collision detection of a mechanical unit on or off (synchronous)
void SetPathSupervisionMode(string mechanicalUnit, bool enabled);

Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.

Members of Rws.Data.MotionSupervision :
public class MotionSupervision {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.MotionSupervision" data-throw-if-not-resolved="false"></xref> class
public MotionSupervision()
// Whether the supervision is switched on, null when the controller did not report it
public bool? Enabled { get; set; }
// Sensitivity of the supervision, as a percentage: the lower the value, the sooner a collision is
// reported. Null when the controller did not report it.
public int? Level { get; set; }
// Returns a string representation of these settings
public override string ToString()
}
Members of Rws.Data.PathSupervision :
public class PathSupervision {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.PathSupervision" data-throw-if-not-resolved="false"></xref> class
public PathSupervision()
// Whether the supervision is switched on, null when the controller did not report it
public bool? Enabled { get; set; }
// Sensitivity of the supervision, as a percentage: the lower the value, the sooner a collision is
// reported. Null when the controller did not report it.
public int? Level { get; set; }
// Returns a string representation of these settings
public override string ToString()
}

Lead through

AVAILABLE ON
RWS 1.0
RWS 2.0

Lead through releases the arm so an operator can push it around by hand. The motors have to be on and the robot has to support the feature. This is one of the two writes of the service that need no mastership.

// Is the arm free to be pushed by hand right now
LeadThroughStatus status = robot.Rws.MotionSystem.GetLeadThrough("ROB_1");
Console.WriteLine(status);
// Switching it on releases the arm: the motors have to be on, and the robot
// has to support lead through. This call needs no mastership.
robot.Rws.MotionSystem.SetLeadThrough("ROB_1", true);
// Switching it off makes the arm hold its position again
robot.Rws.MotionSystem.SetLeadThrough("ROB_1", false);

GetLeadThrough returns Active when the arm gives way when pushed, and Inactive when it holds its position.

Methods of MotionSystemService :
// Tells whether an operator can push the arm of a mechanical unit around by hand (synchronous)
LeadThroughStatus GetLeadThrough(string mechanicalUnit);
// Lets an operator push the arm of a mechanical unit around by hand, or stops letting them (synchronous)
void SetLeadThrough(string mechanicalUnit, bool active);

Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.

Members of Rws.Data.LeadThroughStatus :
public enum LeadThroughStatus {
// The arm gives way when pushed
Active = 1
// The arm holds its position
Inactive = 2
// The controller reported a state this library does not know
Unknown = 0
}

Calibration

AVAILABLE ON
RWS 1.0
RWS 2.0

The calibration says where each axis really is. Reading it is safe and tells you why a unit reports something else than Synchronized.

// How each joint of the unit was calibrated
CalibrationInfo calibration = robot.Rws.MotionSystem.GetCalibrationInfo("ROB_1");
Console.WriteLine($"method {calibration.CalibrationMethodUsed}, {calibration.ExistingJointCount} joint(s)");
// The controller always answers with more joint slots than the unit has.
// The extra ones carry no name and are marked as not existing.
foreach (CalibrationJointInfo joint in calibration.Joints)
{
if (!joint.Exists) continue;
Console.WriteLine($"{joint.JointName} : factory {joint.FactoryCalibrationMethod}, now {joint.CurrentCalibrationMethod}");
}
// The name each joint carries, and the name of its calibration data
foreach (MotorCalibrationName name in robot.Rws.MotionSystem.GetMotorCalibrationNames("ROB_1"))
{
Console.WriteLine($"joint {name.Number} : {name.JointName}, data {name.CalibrationName}");
}
// The calibration is stored twice: in the controller cabinet and in the robot itself.
// The two copies are meant to agree.
SmbData smb = robot.Rws.MotionSystem.GetSmbData("ROB_1");
Console.WriteLine($"cabinet calibration {smb.CabinetCalibrationStatus}");
Console.WriteLine($"robot calibration {smb.RobotCalibrationStatus}");
if (smb.CabinetCalibrationStatus == SmbDataStatus.ValidNotEqual)
{
Console.WriteLine("the two copies do not hold the same data");
}

GetCalibrationInfo always answers with a fixed number of joint slots, larger than the number of joints the unit really has. The extra ones carry no name and have Exists set to false. ExistingJointCount counts the real ones.

The calibration data is stored twice, once in the controller cabinet and once in the robot itself. GetSmbData returns both copies with a status per block of data. ValidNotEqual means the two copies are present but do not agree.

The write operations replace the calibration of an axis. RWS offers no way to put the previous one back, so a wrong calibration leaves the robot moving to the wrong place until somebody recalibrates it from the FlexPendant. They need the mastership of the Motion domain, and the measurement board operations also need the controller in manual mode with this client as its local client.

// These four operations replace the calibration of an axis. RWS has no way to
// put the previous one back, so read the state first and be sure of the position
// the axis is standing in.
MechanicalUnitInfo unit = robot.Rws.MotionSystem.GetMechanicalUnit("ROB_1");
if (unit.Status != MechanicalUnitStatus.Synchronized)
{
Console.WriteLine($"ROB_1 is {unit.Status}");
}
robot.Rws.Mastership.Request(MastershipDomain.Motion);
try
{
// Teaches the controller how the rotor of the motor is oriented.
// Needed once after a motor has been replaced.
robot.Rws.MotionSystem.Commutate("ROB_1", 1);
// Move the axis to its synchronization mark first: the controller stores
// the position the axis is in right now.
robot.Rws.MotionSystem.SynchronizeAxisRevolutionCounter("ROB_1", 1);
robot.Rws.MotionSystem.UpdateRevolutionCounter("ROB_1", 1);
// Takes the current position of the axis as its new calibration position
robot.Rws.MotionSystem.FineCalibrate("ROB_1", 1);
}
finally
{
robot.Rws.Mastership.Release();
}
// Copy one of the two calibration data stores over the other. The overwritten
// one is gone, so read both first and keep the good one.
robot.Rws.MotionSystem.SetSmbData("ROB_1", SmbDataTransfer.RobotToController);
// Erase one of them. The controller cannot recover it.
robot.Rws.MotionSystem.ClearSmbData("ROB_1", SmbDataMemory.Controller);
MethodEffect
CommutateTeaches the controller how the rotor of the motor is oriented. Needed once after a motor has been replaced.
SynchronizeAxisRevolutionCounterTells the controller the axis stands at its synchronization mark
UpdateRevolutionCounterUpdates the revolution counter of the axis
FineCalibrateTakes the current position of the axis as its new calibration position
SetSmbDataCopies one of the two data stores over the other
ClearSmbDataErases one of the two data stores

For the three operations that store a position, move the axis to its synchronization mark first. The controller stores the position the axis is in at the moment of the call.

Methods of MotionSystemService :
// Erases one of the two serial measurement board data stores (synchronous)
void ClearSmbData(string mechanicalUnit, SmbDataMemory memory);
// Commutates the motor of one axis, which teaches the controller how the rotor of that motor is oriented (synchronous) Needed once after a motor has been replaced, before the axis can be calibrated.
void Commutate(string mechanicalUnit, int axis);
// Fine calibrates one axis of a mechanical unit (synchronous)
void FineCalibrate(string mechanicalUnit, int axis);
// Gets how each joint of a mechanical unit was calibrated (synchronous)
CalibrationInfo GetCalibrationInfo(string mechanicalUnit);
// Gets the name each joint of a mechanical unit carries, and the name of its calibration data (synchronous)
MotorCalibrationName[] GetMotorCalibrationNames(string mechanicalUnit);
// Gets the serial measurement board data of a mechanical unit, as held by the controller cabinet and by the robot itself (synchronous) The two copies are meant to agree. When they do not, one of them is written over the other with Data.SmbDataTransfer).
SmbData GetSmbData(string mechanicalUnit);
// Copies one of the two serial measurement board data stores over the other (synchronous)
void SetSmbData(string mechanicalUnit, SmbDataTransfer direction);
// Synchronizes the revolution counter of one axis, telling the controller that the axis stands at its synchronization mark (synchronous)
void SynchronizeAxisRevolutionCounter(string mechanicalUnit, int axis);
// Updates the revolution counter of one axis of a mechanical unit (synchronous)
void UpdateRevolutionCounter(string mechanicalUnit, int axis);

Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.

Members of Rws.Data.CalibrationInfo :
public class CalibrationInfo {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.CalibrationInfo" data-throw-if-not-resolved="false"></xref> class
public CalibrationInfo()
// Number of joints of the unit that are in use, null when the controller did not report it
public int? ActiveJointCount { get; set; }
// Name of the calibration method the unit was last calibrated with, for example "AxisCalibration"
public string CalibrationMethodUsed { get; set; }
// Kind of calibration window the controller offers for this unit,
// null when the controller did not report it
public int? CalibrationWindowType { get; set; }
// Number of joints that exist on the unit, counted from <xref href="UnderAutomation.ABB.Rws.Data.CalibrationInfo.Joints" data-throw-if-not-resolved="false"></xref>
public int ExistingJointCount { get; }
// Number of entries in <xref href="UnderAutomation.ABB.Rws.Data.CalibrationInfo.Joints" data-throw-if-not-resolved="false"></xref>, which is fixed and larger than
// <xref href="UnderAutomation.ABB.Rws.Data.CalibrationInfo.ActiveJointCount" data-throw-if-not-resolved="false"></xref>. Null when the controller did not report it.
public int? JointCount { get; set; }
// One entry per joint slot of the unit, the unused ones marked as such. Never null.
public CalibrationJointInfo[] Joints { get; set; }
// Returns a string representation of this calibration
public override string ToString()
}
Members of Rws.Data.CalibrationJointInfo :
public class CalibrationJointInfo {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.CalibrationJointInfo" data-throw-if-not-resolved="false"></xref> class
public CalibrationJointInfo()
// Method the joint is currently calibrated with
public string CurrentCalibrationMethod { get; set; }
// Whether the joint exists on this mechanical unit. The controller always answers with a fixed
// number of entries and marks the unused ones, which carry no name at all.
public bool Exists { get; set; }
// Method the joint was calibrated with in the factory
public string FactoryCalibrationMethod { get; set; }
// Name of the joint, for example "rob1_1", empty for an entry that does not exist
public string JointName { get; set; }
// Returns a string representation of this joint
public override string ToString()
}
Members of Rws.Data.MotorCalibrationName :
public class MotorCalibrationName {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.MotorCalibrationName" data-throw-if-not-resolved="false"></xref> class
public MotorCalibrationName()
// Name of the calibration data of the joint, usually the same as <xref href="UnderAutomation.ABB.Rws.Data.MotorCalibrationName.JointName" data-throw-if-not-resolved="false"></xref>
public string CalibrationName { get; set; }
// Name of the joint, for example "rob1_1"
public string JointName { get; set; }
// Number of the joint inside its mechanical unit, starting at 1
public int Number { get; set; }
// Returns a string representation of these names
public override string ToString()
}
Members of Rws.Data.SmbData :
public class SmbData {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.SmbData" data-throw-if-not-resolved="false"></xref> class
public SmbData()
// State of the absolute accuracy data stored in the cabinet
public SmbDataStatus CabinetAbsoluteAccuracyStatus { get; set; }
// State of the axis calibration data stored in the cabinet
public SmbDataStatus CabinetAxisCalibrationStatus { get; set; }
// State of the calibration data stored in the cabinet
public SmbDataStatus CabinetCalibrationStatus { get; set; }
// High part of the serial number stored in the cabinet
public string CabinetSerialNumberHighPart { get; set; }
// Low part of the serial number stored in the cabinet
public string CabinetSerialNumberLowPart { get; set; }
// Whether the serial number stored in the cabinet is usable, null when the controller did not report it
public bool? CabinetSerialNumberValid { get; set; }
// State of the service information data stored in the cabinet
public SmbDataStatus CabinetServiceInformationStatus { get; set; }
// Number of the drive module the data belongs to, null when the controller did not report it
public int? DriveModule { get; set; }
// Number of the measurement board the data belongs to, null when the controller did not report it
public int? MeasurementBoard { get; set; }
// Number of the measurement link the data belongs to, null when the controller did not report it
public int? MeasurementLink { get; set; }
// State of the absolute accuracy data stored in the robot
public SmbDataStatus RobotAbsoluteAccuracyStatus { get; set; }
// State of the axis calibration data stored in the robot
public SmbDataStatus RobotAxisCalibrationStatus { get; set; }
// State of the calibration data stored in the robot
public SmbDataStatus RobotCalibrationStatus { get; set; }
// High part of the serial number stored in the robot
public string RobotSerialNumberHighPart { get; set; }
// Low part of the serial number stored in the robot
public string RobotSerialNumberLowPart { get; set; }
// Whether the serial number stored in the robot is usable, null when the controller did not report it
public bool? RobotSerialNumberValid { get; set; }
// State of the service information data stored in the robot
public SmbDataStatus RobotServiceInformationStatus { get; set; }
// Returns a string representation of this data
public override string ToString()
}
Members of Rws.Data.SmbDataStatus :
public enum SmbDataStatus {
// The robot system does not use this block of data
NotUsed = 4
// The data is missing or unusable
NotValid = 3
// The controller reported a state this library does not know
Unknown = 0
// The data is present and the two copies agree
Valid = 1
// The data is present on both sides, but the two copies differ
ValidNotEqual = 2
}
Members of Rws.Data.SmbDataTransfer :
public enum SmbDataTransfer {
// The copy held by the controller cabinet is written into the robot
ControllerToRobot = 1
// The copy held by the robot is written into the controller cabinet
RobotToController = 0
}
Members of Rws.Data.SmbDataMemory :
public enum SmbDataMemory {
// The copy held by the controller cabinet
Controller = 1
// The copy held by the robot itself
Robot = 0
}

State of the motion system

AVAILABLE ON
RWS 1.0
RWS 2.0

GetInfo gives the overview: which unit the jogging commands apply to, whether absolute accuracy is on, and the change count.

// Overview of the motion system: which unit the jogging commands apply to,
// and the counter the controller increments on every change
MotionSystemInfo info = robot.Rws.MotionSystem.GetInfo();
Console.WriteLine($"jogging applies to {info.MechanicalUnitName}");
Console.WriteLine($"change count {info.ChangeCount}, absolute accuracy {info.AbsoluteAccuracyActive}");
// Ask whether anything moved since that reading, instead of reading everything again
if (info.ChangeCount.HasValue && robot.Rws.MotionSystem.HasChanged(info.ChangeCount.Value))
{
Console.WriteLine("the motion system changed");
}
// The last error the motion system ran into. Most of them come from a jogging
// request the controller accepted and could not honour.
MotionSystemErrorState error = robot.Rws.MotionSystem.GetErrorState();
if (error.State != MotionErrorState.Ok)
{
Console.WriteLine($"{error.State} ({error.RawState}), {error.Count} error(s)");
}
// Run the RAPID program without moving the robot. The instructions execute,
// the motion ones are skipped.
bool skipped = robot.Rws.MotionSystem.GetNonMotionExecutionMode();
robot.Rws.Mastership.Request();
try
{
robot.Rws.MotionSystem.SetNonMotionExecutionMode(true);
}
finally
{
robot.Rws.Mastership.Release();
}

The change count is a counter the controller increments on every change of the motion system. Reading it once and asking HasChanged afterwards is cheaper than fetching the whole state again to find out that nothing moved. Only pass a count a previous reading gave: the controller does not track how two counts relate, so a count it never reported comes back as changed.

GetErrorState returns the last error the motion system ran into and how many it has counted. Most of them come from a jogging request the controller accepted and could not honour, and they stay reported until a new one replaces them.

MotionErrorStateMeaning
OkNo error
MechanicalUnitNotActiveA mechanical unit was jogged whose activation failed
UncalibratedJogMotionTypeAn uncalibrated robot was jogged in a mode that needs its calibration
UnnormalizedQuaternionA tool, a load or a work object carries an orientation that is not normalized
ErroneousToolMassA load definition carries a negative mass
RobotHoldMismatchThe tool and the work object disagree on which one the robot holds
WorkObjectMechanicalUnitNotFoundA unit used in coordinated jogging was not found
InvalidJogMotionTypeThe requested jogging mode is not valid
UnknownThe controller reported an error the library does not know, RawState then holds it
Methods of MotionSystemService :
// Gets the last error the motion system ran into, and how many errors it has counted (synchronous) Most of these errors are raised by a jogging request the controller could not honour, and stay reported until a new one replaces them.
MotionSystemErrorState GetErrorState();
// Gets an overview of the motion system: the mechanical unit jogging applies to, the change counter and the payload and accuracy settings (synchronous)
MotionSystemInfo GetInfo();
// Tells whether the motion system changed since it reported the given change count (synchronous) Reading MotionSystemInfo.ChangeCount once and asking this afterwards is cheaper than fetching the whole state again to find out that nothing moved.
bool HasChanged(int changeCount);

Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.

Members of Rws.Data.MotionSystemInfo :
public class MotionSystemInfo {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.MotionSystemInfo" data-throw-if-not-resolved="false"></xref> class
public MotionSystemInfo()
// Whether absolute accuracy is switched on, null when the controller did not report it
public bool? AbsoluteAccuracyActive { get; set; }
// Counter the controller increments on every change of the motion system.
//
// <p>Pass it to <code>MotionSystemService.HasChanged()</code> to find out whether anything moved
// since a previous reading, without fetching the whole state again.</p>
public int? ChangeCount { get; set; }
// Name of the mechanical unit the jogging commands currently apply to
public string MechanicalUnitName { get; set; }
// Whether the payload of the robot is set by the running program rather than by the mechanical unit,
// null when the controller did not report it
public bool? ModalPayloadMode { get; set; }
// Rate at which the controller refreshes the motion system state, null when it did not report it
public int? PollRate { get; set; }
// Returns a string representation of this motion system
public override string ToString()
}
Members of Rws.Data.MotionSystemErrorState :
public class MotionSystemErrorState {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.MotionSystemErrorState" data-throw-if-not-resolved="false"></xref> class
public MotionSystemErrorState()
// Number of errors counted since the controller started, incremented on every new error,
// null when the controller did not report it
public int? Count { get; set; }
// Error state exactly as the controller reported it, useful when <xref href="UnderAutomation.ABB.Rws.Data.MotionSystemErrorState.State" data-throw-if-not-resolved="false"></xref> is
// <xref href="UnderAutomation.ABB.Rws.Data.MotionErrorState.Unknown" data-throw-if-not-resolved="false"></xref>
public string RawState { get; set; }
// Last error the motion system ran into
public MotionErrorState State { get; set; }
// Returns a string representation of this error state
public override string ToString()
}
Members of Rws.Data.MotionErrorState :
public enum MotionErrorState {
// A load definition carries a negative mass
ErroneousToolMass = 5
// The requested jogging mode is not valid
InvalidJogMotionType = 8
// A mechanical unit was jogged whose activation failed
MechanicalUnitNotActive = 2
// No error
Ok = 1
// The tool and the work object disagree on which one the robot holds
RobotHoldMismatch = 6
// An uncalibrated robot was jogged in a mode that needs its calibration
UncalibratedJogMotionType = 3
// The controller reported an error this library does not know
Unknown = 0
// A quaternion that is not normalized reached the jogging task, from a tool, a load or a work object
UnnormalizedQuaternion = 4
// A mechanical unit used in coordinated jogging was not found
WorkObjectMechanicalUnitNotFound = 7
}
View as Markdown

Easily integrate Universal Robots, Fanuc, Yaskawa, ABB or Staubli robots into your .NET, Python, LabVIEW or Matlab applications

UnderAutomation
Contact usLegal

© All rights reserved.