RAPID tasks & program execution
List RAPID tasks, start and stop program execution, follow the execution state, move the program pointer, load and unload modules.
robot.Rws.Rapid is the service of the program the robot runs. This page covers the tasks the program is split into, starting and stopping the execution, and moving the program pointer. The variables of the program are on RAPID variables & symbols, the source of the modules on RAPID modules & program files.
Reading never needs anything special. Every write of this page needs the Rapid mastership, and most of them also need the controller to be in the right operation mode. None of these resources answers while the controller runs in boot mode.
Tasks
A controller runs one RAPID task per robot, plus the background tasks the system needs. GetTasks lists them all, GetTask returns everything the controller knows about one of them.
// Every RAPID task of the controllerforeach (RapidTaskItem task in robot.Rws.Rapid.GetTasks()){Console.WriteLine(task.Name); // T_ROB1Console.WriteLine(task.Type); // Normal, Static or SemiStaticConsole.WriteLine(task.TaskState); // Linked when the program is ready to runConsole.WriteLine(task.ExecutionState); // Started, Stopped, ReadyConsole.WriteLine(task.Active); // null when the controller did not report itConsole.WriteLine(task.MotionTask); // true for the task that drives the robot}// Everything the controller knows about one taskRapidTaskInfo info = robot.Rws.Rapid.GetTask("T_ROB1");Console.WriteLine(info.ExecutionLevel); // Normal, Trap, User, NoneConsole.WriteLine(info.ExecutionCycle); // Forever, Once, OnceDoneConsole.WriteLine(info.ExecutionMode); // Continuous, StepIn, StepOver, ...Console.WriteLine(info.ProductionEntryPoint);Console.WriteLine(info.Trust);
RapidTaskType | What the task is |
|---|---|
Normal | A task holding a program an operator starts and stops |
Static | A task started with the controller and never stopped |
SemiStatic | A task started with the controller and restarted at every program reset |
Unknown | The controller reported a type the SDK does not know |
TaskState says whether the task can run. Only Linked means that the modules of the task were turned into a runnable program. Empty means the task holds nothing, Loaded that the modules are there but not linked yet.
RapidTaskExecutionState | Meaning |
|---|---|
Ready | The task is ready to run but is not running |
Started | The task is running |
Stopped | The task was stopped before its end |
Uninitialized | The task is not usable yet |
Activate and deactivate a task
A deactivated task is not started when the program starts. The selection panel of the FlexPendant shows the same thing, GetTaskSelection reads it. UserModify says whether an operator is allowed to change the selection of that task from the pendant.
// Which tasks the operator panel has selected, and which of them an operator may changeforeach (RapidTaskSelectionItem item in robot.Rws.Rapid.GetTaskSelection()){Console.WriteLine(item.Name + " selected=" + item.Selected + " userModify=" + item.UserModify);}// Activating or deactivating a task is a write, so it needs the mastershiprobot.Rws.Mastership.Request(MastershipDomain.Rapid);try{robot.Rws.Rapid.ActivateTask("T_ROB1");robot.Rws.Rapid.DeactivateTask("T_ROB2");// Same thing for every task at oncerobot.Rws.Rapid.ActivateTasks();robot.Rws.Rapid.DeactivateTasks();}finally{robot.Rws.Mastership.Release(MastershipDomain.Rapid);}
GetTaskProgramPointerSyncState and GetTaskMotionPointerSyncState, listed below, are described in the program pointer section of this page.
// Activates one task (synchronous)void ActivateTask(string task);// Activates every task of the controller (synchronous)void ActivateTasks();// Deactivates one task (synchronous)void DeactivateTask(string task);// Deactivates every task of the controller (synchronous)void DeactivateTasks();// Gets everything the controller reports about one task (synchronous)RapidTaskInfo GetTask(string task);// Gets whether the motion pointer of one task is synchronized with the others (synchronous)RapidPointerSyncState GetTaskMotionPointerSyncState(string task);// Gets whether the program pointer of one task is synchronized with the others (synchronous)RapidPointerSyncState GetTaskProgramPointerSyncState(string task);// Gets the task selection panel: which tasks are selected, and which of them an operator is allowed to change the selection of (synchronous)RapidTaskSelectionItem[] GetTaskSelection();// Gets every RAPID task of the controller and what each of them is doing (synchronous)RapidTaskItem[] GetTasks();
Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.
public class RapidTaskItem {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidTaskItem" data-throw-if-not-resolved="false"></xref> classpublic RapidTaskItem()// Whether the task is active, null when the controller did not report itpublic bool? Active { get; set; }// Whether the task is running, and whether it could bepublic RapidTaskExecutionState ExecutionState { get; set; }// Whether the task can move a mechanical unit, null when the controller did not report itpublic bool? MotionTask { get; set; }// Name of the task, for example "T_ROB1"public string Name { get; set; }// How far the controller has got in preparing the program of the taskpublic RapidTaskState TaskState { get; set; }// Returns a string representation of this taskpublic override string ToString()// Kind of task, which decides when the controller runs itpublic RapidTaskType Type { get; set; }}
public class RapidTaskInfo : RapidTaskItem {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidTaskInfo" data-throw-if-not-resolved="false"></xref> classpublic RapidTaskInfo()// Whether the task is bound to a configured task number, null when the controller did not report itpublic bool? BindReference { get; set; }// Number of cycles the task is set to run.//// <p>Only reported over a connection established with version 2, and left to// <xref href="UnderAutomation.ABB.Rws.Data.RapidExecutionCycle.Unknown" data-throw-if-not-resolved="false"></xref> otherwise.</p>public RapidExecutionCycle ExecutionCycle { get; set; }// Level at which the code of the task is currently executingpublic RapidExecutionLevel ExecutionLevel { get; set; }// Stepping mode the task was last started withpublic RapidTaskExecutionMode ExecutionMode { get; set; }// What kind of code the task is currently runningpublic RapidExecutionType ExecutionType { get; set; }// Routine the program pointer moves to when it is reset, for example "main"public string ProductionEntryPoint { get; set; }// Identifier of the task, null when the controller did not report itpublic int? TaskId { get; set; }// Name of the task running in the foreground, empty when there is nonepublic string TaskInForeground { get; set; }// What the controller does to the system when this task stops unexpectedlypublic RapidTaskTrustLevel Trust { get; set; }}
public class RapidTaskSelectionItem {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidTaskSelectionItem" data-throw-if-not-resolved="false"></xref> classpublic RapidTaskSelectionItem()// Whether the task can move a mechanical unit, null when the controller did not report itpublic bool? MotionTask { get; set; }// Name of the task, for example "T_ROB1"public string Name { get; set; }// Whether the task is selected, null when the controller did not report itpublic bool? Selected { get; set; }// Returns a string representation of this task selectionpublic override string ToString()// Whether an operator is allowed to change the selection of this task, null when the// controller did not report itpublic bool? UserModify { get; set; }}
public enum RapidTaskType {// A task started and stopped together with the programNormal = 1// A task restarted from its beginning every time the controller startsSemiStatic = 3// A task that keeps its program pointer where it was when the controller was switched offStatic = 2// The controller reported a type this library does not knowUnknown = 0}
public enum RapidTaskState {// The task holds no programEmpty = 1// The task has been created but its program is not linked yetInitiated = 2// The program of the task is linked and ready to runLinked = 3// A program is loaded into the task but not linked yetLoaded = 4// The task is not initializedUninitialized = 5// The controller reported a state this library does not knowUnknown = 0}
public enum RapidTaskExecutionState {// The task is ready to be startedReady = 1// The task is runningStarted = 3// The task was running and has been stoppedStopped = 2// The task is not initializedUninitialized = 4// The controller reported a state this library does not knowUnknown = 0}
public enum RapidTaskExecutionMode {// The task runs without steppingContinuous = 1// The task steps backwardsStepBack = 5// The task steps into the routine callsStepIn = 3// The task steps to the last instructionStepLast = 6// The task steps out of the current routineStepOutOf = 4// The task steps over the routine callsStepOver = 2// The task advances one instruction at a timeStepWise = 7// The controller reported a mode this library does not knowUnknown = 0}
public enum RapidTaskTrustLevel {// The system carries onNone = 1// The whole system failsSystemFailure = 2// The system haltsSystemHalt = 3// The system stopsSystemStop = 4// The controller reported a level this library does not knowUnknown = 0}
Build a task
BuildTask links the modules a task holds into a runnable program. The controller accepts the request even when the program does not compile, so read GetBuildErrors afterwards and check that the task state became Linked.
robot.Rws.Mastership.Request(MastershipDomain.Rapid);try{// Link the modules of the task into a runnable programrobot.Rws.Rapid.BuildTask("T_ROB1");}finally{robot.Rws.Mastership.Release(MastershipDomain.Rapid);}// The controller does not fail the build request, it reports what it refused afterwardsforeach (RapidBuildError error in robot.Rws.Rapid.GetBuildErrors("T_ROB1")){Console.WriteLine(error.ModuleName + " " + error.Row + "," + error.Column + ": " + error.Error);}// The task is runnable when its state is LinkedConsole.WriteLine(robot.Rws.Rapid.GetTask("T_ROB1").TaskState);
The build errors are described in RAPID modules & program files.
Methods of RapidService :// Links the program of a task, which is what turns the modules it holds into something runnable (synchronous) Read GetBuildErrors() afterwards to find out what the controller refused.void BuildTask(string task);
Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.
Load a module
LoadModule loads one module file into a task. The file has to be on the file system of the controller already, so upload it first with the file system service. Set replace to true when a module of the same name is already loaded, otherwise the controller refuses the request.
robot.Rws.Mastership.Request(MastershipDomain.Rapid);try{// The file has to be on the controller already. Upload it first with robot.Rws.File.// On OmniCore the call answers the name of what was loaded, on IRC5 it answers null.string loaded = robot.Rws.Rapid.LoadModule("T_ROB1", "$HOME/mymodule.mod", true);Console.WriteLine(loaded);robot.Rws.Rapid.UnloadModule("T_ROB1", "mymodule");}finally{robot.Rws.Mastership.Release(MastershipDomain.Rapid);}
UnloadModule takes the name of the module, not the name of the file. A module that was never saved is lost when it is unloaded.
Loading a whole program instead of one module is done with LoadProgram, see RAPID modules & program files.
// Loads a module file into a task (synchronous)string LoadModule(string task, string modulePath, bool replace = false);// Unloads a module from a task (synchronous)void UnloadModule(string task, string module);
Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.
Start and stop the program
Starting a program from your application fails when one of these conditions is not met:
- The controller is in automatic mode, or in manual mode with the enabling device held. The mode is read with the control panel service.
- The motors are on,
Panel.SetControllerState(ControllerState.MotorsOn). - The task is active and its state is
Linked. - The program pointer is set, which
ResetProgramPointerdoes for every task. - Your connection holds the
Rapidmastership.
// 1. The controller has to be in automatic modeif (robot.Rws.Panel.GetOperationMode() != OperationMode.Automatic)throw new Exception("Turn the key of the controller to automatic mode");robot.Rws.Mastership.Request(MastershipDomain.Rapid);try{// 2. Motors onrobot.Rws.Panel.SetControllerState(ControllerState.MotorsOn);// 3. Program pointer back to the entry point of every taskrobot.Rws.Rapid.ResetProgramPointer();// 4. Startrobot.Rws.Rapid.Start(RapidRegainMode.Continue,RapidExecutionMode.Continue,RapidExecutionCycle.Forever,RapidStartCondition.None,false, // do not stop at breakpointsfalse); // normal tasks only}finally{robot.Rws.Mastership.Release(MastershipDomain.Rapid);}// 5. Check that it really started, the call above only means the request was acceptedRapidExecutionInfo execution = robot.Rws.Rapid.GetExecutionState();Console.WriteLine(execution.State); // Running or StoppedConsole.WriteLine(execution.Cycle); // Forever, Once, OnceDone
Start returns as soon as the controller accepts the request, not when the robot moves. Read GetExecutionState afterwards to know what really happened.
RapidRegainMode | What the robot does when execution resumes |
|---|---|
Continue | Resume from the current position, without going back to the path |
Regain | Move back onto the path first |
Clear | Drop the path and resume from the current position |
EnterConsume | Resume by entering the path already computed |
RapidExecutionMode | How far the program advances |
|---|---|
Continue | Run until something stops it |
StepIn | Enter the routine called by the current instruction |
StepOver | Run the current instruction whole, without entering the routine it calls |
StepOut | Run until the current routine returns |
StepBack | Step one instruction backwards |
StepLast | Step to the last instruction |
StepMotion | Step to the next motion instruction |
RapidStartCondition.CallChain asks the controller to start only when the call chain of the program pointer is still valid, which is a way to refuse a start after the source was edited.
Cycles and entry point
SetExecutionCycle takes Once or Forever, the other values of the enum are only reported by the controller. StartFromProductionEntry starts at the production entry point of the task instead of the current program pointer.
AbortExecutionLevel leaves the routine running now and goes back to the level under it. This is how a trap or a service routine started by hand is abandoned without stopping the program below it.
robot.Rws.Mastership.Request(MastershipDomain.Rapid);try{// Only Once and Forever are accepted hererobot.Rws.Rapid.SetExecutionCycle(RapidExecutionCycle.Once);// Start from the production entry point instead of the current program pointerrobot.Rws.Rapid.StartFromProductionEntry();// Leave the routine that is running now and go back to the level below it.// This is how a trap or a service routine is abandoned without stopping the program under it.robot.Rws.Rapid.AbortExecutionLevel("T_ROB1");}finally{robot.Rws.Mastership.Release(MastershipDomain.Rapid);}
Stop
// Stop at the end of the current instruction, normal tasks onlyrobot.Rws.Rapid.Stop(RapidStopMode.Stop, RapidTaskScope.Normal);// Let the robot finish the cycle it is in, then stoprobot.Rws.Rapid.Stop(RapidStopMode.Cycle, RapidTaskScope.Normal);// Stop everything at once, including the static and semi static tasksrobot.Rws.Rapid.Stop(RapidStopMode.QuickStop, RapidTaskScope.AllTasks);// Wait until the controller confirms the program is stoppedwhile (robot.Rws.Rapid.GetExecutionState().State != RapidExecutionState.Stopped)System.Threading.Thread.Sleep(200);
RapidStopMode | How the program stops |
|---|---|
Cycle | At the end of the current cycle |
Instruction | At the end of the current instruction |
Stop | As soon as the robot can decelerate along its path |
QuickStop | As fast as the robot can, leaving the path |
RapidTaskScope.Normal stops the normal tasks only, AllTasks also stops the static and semi static ones. Stop returns before the robot has stopped, so wait until GetExecutionState reports Stopped.
Hold-to-run
In manual mode the program only runs while a client keeps saying that the hold-to-run control is held. Send Press, then Held about every two seconds. The controller stops the program as soon as it stops hearing from your application.
// Manual mode only. Press, then keep sending Held, the controller stops the// program as soon as it stops hearing from your application.robot.Rws.Rapid.SetHoldToRun(RapidHoldToRunState.Press);robot.Rws.Rapid.Start(RapidRegainMode.Continue, RapidExecutionMode.Continue);for (int i = 0; i < 10; i++){robot.Rws.Rapid.SetHoldToRun(RapidHoldToRunState.Held);System.Threading.Thread.Sleep(1000);}robot.Rws.Rapid.SetHoldToRun(RapidHoldToRunState.Release);
This is only honoured by a virtual controller, and only for a client the controller considers local. A real cabinet expects the physical device.
A complete example, with the checks around it, is given in Start & stop a RAPID program.
Methods of RapidService :// Abandons the routine the task is currently running and returns to the level below it (synchronous) This is how a trap or a service routine started by hand is left without stopping the program underneath it.void AbortExecutionLevel(string task);// Gets whether the controller is executing RAPID code, and how many cycles it is set to run (synchronous)RapidExecutionInfo GetExecutionState();// Moves the program pointer of every task back to the entry point of its program (synchronous)void ResetProgramPointer();// Sets how many times the program runs before stopping (synchronous)void SetExecutionCycle(RapidExecutionCycle cycle);// Drives the hold-to-run control that lets the program run in manual mode (synchronous) Send RapidHoldToRunState.Press to allow execution to start, then RapidHoldToRunState.Held about every two seconds to keep it running; the controller stops the program as soon as it stops hearing from the client. Send RapidHoldToRunState.Release to stop it at once.void SetHoldToRun(RapidHoldToRunState state);// Starts executing the RAPID program from where the program pointer stands (synchronous) The controller has to be in automatic mode with the motors on, or in manual mode with the enabling device held. Reset the program pointer first with RapidService.ResetProgramPointer to start from the beginning.void Start(RapidRegainMode regain = RapidRegainMode.Continue, RapidExecutionMode executionMode = RapidExecutionMode.Continue, RapidExecutionCycle cycle = RapidExecutionCycle.Forever, RapidStartCondition condition = RapidStartCondition.None, bool stopAtBreakpoint = false, bool allTasksBySelection = false);// Starts executing from the production entry point of the program rather than from where the program pointer stands (synchronous)void StartFromProductionEntry();// Starts recording the RAPID execution trace into a file (synchronous) The trace names every instruction the controller runs, which is what it takes to find out why a program took a branch it should not have.void StartSpy(string logFile);// Stops the RAPID execution (synchronous)void Stop(RapidStopMode stopMode = RapidStopMode.Stop, RapidTaskScope scope = RapidTaskScope.Normal);// Stops recording the RAPID execution trace (synchronous)void StopSpy();
Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.
public class RapidExecutionInfo {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidExecutionInfo" data-throw-if-not-resolved="false"></xref> classpublic RapidExecutionInfo()// Number of cycles the program is set to runpublic RapidExecutionCycle Cycle { get; set; }// Whether RAPID code is currently runningpublic RapidExecutionState State { get; set; }// Returns a string representation of this execution statepublic override string ToString()}
public enum RapidExecutionState {// RAPID execution is runningRunning = 1// RAPID execution is stoppedStopped = 2// The controller reported a state this library does not knowUnknown = 0}
public enum RapidExecutionCycle {// The cycle currently configured is left untouchedAsIs = 2// The program runs again every time it reaches its endForever = 1// The program runs once and stops at its endOnce = 3// The program was asked to run once and has finished doing soOnceDone = 4// The controller reported a cycle this library does not knowUnknown = 0}
public enum RapidExecutionMode {// Run until something stops itContinue = 0// Step one instruction backwardsStepBack = 4// Step into the routine called by the current instructionStepIn = 1// Step to the last instructionStepLast = 5// Step to the next motion instructionStepMotion = 6// Run until the current routine returnsStepOut = 3// Run the current instruction whole, without entering the routine it callsStepOver = 2}
public enum RapidRegainMode {// Drop the path and resume from the current positionClear = 2// Resume from the current position without moving back to the pathContinue = 0// Resume by entering the consumption of the already generated pathEnterConsume = 3// Move back onto the path before resumingRegain = 1}
public enum RapidStopMode {// Stop when the current cycle endsCycle = 0// Stop when the current instruction endsInstruction = 1// Stop as fast as the robot can, leaving the pathQuickStop = 3// Stop as soon as the robot can decelerate along its pathStop = 2}
public enum RapidStartCondition {// Start only when the call chain of the program pointer is still validCallChain = 1// Start without any additional checkNone = 0}
public enum RapidTaskScope {// Apply to every task of the systemAllTasks = 1// Apply to the tasks the task selection panel has enabledNormal = 0}
public enum RapidHoldToRunState {// Confirm that execution may keep running, which has to be repeated about every two secondsHeld = 1// Ask for execution to be allowed to startPress = 0// Stop execution immediatelyRelease = 2}
Execution trace
The controller can write every instruction it runs into a file. It is the fastest way to find out why a program took a branch it should not have. The two calls take the mastership by themselves, your code does not have to.
// The trace names every instruction the controller runs. No mastership needed,// the controller takes it by itself for these two calls.robot.Rws.Rapid.StartSpy("$HOME/trace.log");Console.WriteLine(robot.Rws.Rapid.GetSpyStatus()); // Logging or NotLoggingSystem.Threading.Thread.Sleep(5000);robot.Rws.Rapid.StopSpy();// Then download the file with the file servicestring trace = robot.Rws.File.GetFileAsText("$HOME/trace.log");Console.WriteLine(trace);
The file is written on the controller, download it afterwards with the file system service. A trace grows fast, do not leave it running.
Execution trace of RapidService :// Gets whether the controller is recording the RAPID execution trace to a file (synchronous)RapidSpyStatus GetSpyStatus();
Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.
public enum RapidSpyStatus {// The execution trace is being writtenLogging = 1// No execution trace is being writtenNotLogging = 2// The controller reported a status this library does not knowUnknown = 0}
Program pointer and motion pointer
Each task has two pointers. The program pointer says which instruction runs next, the motion pointer which one the robot is really executing. They drift apart because the controller plans the path ahead of the movement.
// Where the two pointers of the task standRapidPointers pointers = robot.Rws.Rapid.GetPointers("T_ROB1");if (pointers.ProgramPointer.Available){Console.WriteLine(pointers.ProgramPointer.Module + "/" + pointers.ProgramPointer.Routine);Console.WriteLine(pointers.ProgramPointer.BeginRow + "," + pointers.ProgramPointer.BeginColumn);}// The motion pointer is behind the program pointer, the controller plans the path// ahead of the movement. It is not available in a task that has not moved yet.Console.WriteLine(pointers.MotionPointer.Available);// The piece of source the program pointer covers. The controller refuses the request// when the task has no program pointer, reset it or start the program first.RapidProgramCounterPosition position = robot.Rws.Rapid.GetProgramCounterPosition("T_ROB1");Console.WriteLine(position.Module + " " + position.StartLine + "," + position.StartColumn);// Moving the pointer is a write, it needs the RAPID mastershiprobot.Rws.Mastership.Request(MastershipDomain.Rapid);try{// To the beginning of a routine. The module name is used by an IRC5 only,// an OmniCore looks the routine up in the whole task.robot.Rws.Rapid.SetProgramPointerToRoutine("T_ROB1", "MainModule", "main");// To a service routine, which has to be entered at user levelrobot.Rws.Rapid.SetProgramPointerToRoutineUrl("T_ROB1", "RAPID/T_ROB1/BASEFUN/LoadIdentify", true);// To one position of the source. The routine name is used by an IRC5 only,// an OmniCore works it out from the position itself.robot.Rws.Rapid.SetProgramPointerToCursor("T_ROB1", "MainModule", "main", 12, 1);// One instruction forward or backward, automatic mode onlyrobot.Rws.Rapid.SetProgramPointerToNextInstruction("T_ROB1");robot.Rws.Rapid.SetProgramPointerToPreviousInstruction("T_ROB1");}finally{robot.Rws.Mastership.Release(MastershipDomain.Rapid);}
SetProgramPointerToRoutine takes a module name and SetProgramPointerToCursor a routine name. An IRC5 refuses the request without them, an OmniCore ignores them and finds the routine by itself. Pass them in both cases, your code then works on the two generations.
A few things to know before moving the pointer:
- Moving the pointer needs the
Rapidmastership, and the program has to be stopped. SetProgramPointerToNextInstructionandSetProgramPointerToPreviousInstructionare refused outside automatic mode.- A service routine has to be entered at user level, so pass
trueforuserLevel.GetServiceRoutinesgives the pathsSetProgramPointerToRoutineUrltakes. GetProgramCounterPositionis refused when the task has no program pointer at all. Reset it or start the program first.GetProgramreturns the name of the program the task holds and the routineResetProgramPointergoes back to.
Synchronization and change counters
GetProgramPointerSyncState and GetMotionPointerSyncState say whether the pointers of the tasks are synchronized with each other, for the whole controller or for one task. GetStructuralChangeCount returns two counters that only move when something changed in the task, which is cheaper than downloading the modules again to find out that nothing moved.
// For the whole controllerRapidPointerSyncState program = robot.Rws.Rapid.GetProgramPointerSyncState();RapidPointerSyncState motion = robot.Rws.Rapid.GetMotionPointerSyncState();Console.WriteLine(program + " / " + motion); // On or Off// For one taskConsole.WriteLine(robot.Rws.Rapid.GetTaskProgramPointerSyncState("T_ROB1"));Console.WriteLine(robot.Rws.Rapid.GetTaskMotionPointerSyncState("T_ROB1"));// Two counters that say whether anything changed in the task, cheaper than// downloading the modules again to find out that nothing movedRapidStructuralChangeCount counters = robot.Rws.Rapid.GetStructuralChangeCount("T_ROB1");Console.WriteLine(counters.ChangeCount);Console.WriteLine(counters.StructuralChangeCount);
// Gets whether the motion pointers of every task are synchronized with each other (synchronous)RapidPointerSyncState GetMotionPointerSyncState();// Gets where the program pointer and the motion pointer of a task stand (synchronous) The program pointer says which instruction runs next, the motion pointer which one the robot is actually executing; they drift apart because the controller plans the path ahead of the movement.RapidPointers GetPointers(string task);// Gets the program loaded into a task (synchronous)RapidProgramInfo GetProgram(string task);// Gets which piece of source the program pointer of a task points at (synchronous)RapidProgramCounterPosition GetProgramCounterPosition(string task);// Gets whether the program pointers of every task are synchronized with each other (synchronous)RapidPointerSyncState GetProgramPointerSyncState();// Gets the two counters a task keeps of what has changed in it (synchronous) Comparing them with what a previous reading gave is cheaper than fetching the modules again to find out that nothing moved.RapidStructuralChangeCount GetStructuralChangeCount(string task);// Moves the program pointer of a task to a position of a module (synchronous)void SetProgramPointerToCursor(string task, string module, string routine, int row, int column);// Moves the program pointer of a task forward by one instruction (synchronous)void SetProgramPointerToNextInstruction(string task);// Moves the program pointer of a task back by one instruction (synchronous)void SetProgramPointerToPreviousInstruction(string task);// Moves the program pointer of a task to the beginning of a routine (synchronous)void SetProgramPointerToRoutine(string task, string module, string routine, bool userLevel = false);// Moves the program pointer of a task to a routine named by its path (synchronous) This is what the paths GetServiceRoutines() reports are for.void SetProgramPointerToRoutineUrl(string task, string routineUrl, bool userLevel = false);
Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.
public class RapidPointers {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidPointers" data-throw-if-not-resolved="false"></xref> classpublic RapidPointers()// Instruction the robot is currently moving forpublic RapidPointerPosition MotionPointer { get; set; }// Instruction the task will execute nextpublic RapidPointerPosition ProgramPointer { get; set; }// Returns a string representation of the two pointerspublic override string ToString()}
public class RapidPointerPosition {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidPointerPosition" data-throw-if-not-resolved="false"></xref> classpublic RapidPointerPosition()// Whether the controller reported a position for this pointer at allpublic bool Available { get; set; }// Column the pointer begins at, null when the controller did not report itpublic int? BeginColumn { get; set; }// Line the pointer begins at, null when the controller did not report itpublic int? BeginRow { get; set; }// How many times the pointer has been moved, null when the controller did not report itpublic int? ChangeCount { get; set; }// Column the pointer ends at, null when the controller did not report itpublic int? EndColumn { get; set; }// Line the pointer ends at, null when the controller did not report itpublic int? EndRow { get; set; }// What kind of code the pointer is standing inpublic RapidExecutionType ExecutionType { get; set; }// Name of the module the pointer stands inpublic string Module { get; set; }// Name of the routine the pointer stands inpublic string Routine { get; set; }// Returns a string representation of this pointer positionpublic override string ToString()}
public class RapidProgramCounterPosition {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidProgramCounterPosition" data-throw-if-not-resolved="false"></xref> classpublic RapidProgramCounterPosition()// Column the pointed instruction ends at, null when the controller did not report itpublic int? EndColumn { get; set; }// Line the pointed instruction ends at, null when the controller did not report itpublic int? EndLine { get; set; }// Name of the module the pointer stands inpublic string Module { get; set; }// Name of the routine the pointer stands inpublic string Routine { get; set; }// Column the pointed instruction starts at, null when the controller did not report itpublic int? StartColumn { get; set; }// Line the pointed instruction starts at, null when the controller did not report itpublic int? StartLine { get; set; }// Returns a string representation of this positionpublic override string ToString()}
public enum RapidPointerSyncState {// The pointers are not synchronizedOff = 2// The pointers are synchronizedOn = 1// The controller reported a state this library does not knowUnknown = 0}
public class RapidStructuralChangeCount {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidStructuralChangeCount" data-throw-if-not-resolved="false"></xref> classpublic RapidStructuralChangeCount()// Counter the controller increments whenever anything relevant changes in the taskpublic int? ChangeCount { get; set; }// Counter the controller increments when a module is loaded, unloaded or renamed.//// <p>A rename counts as an unload followed by a load.</p>public int? StructuralChangeCount { get; set; }// Returns a string representation of these counterspublic override string ToString()}
public enum RapidExecutionType {// An event routine is runningEventRoutine = 6// An external interrupt is runningExternalInterrupt = 4// An interrupt is runningInterrupt = 3// Nothing is runningNone = 1// The normal program is runningNormal = 2// The controller reported a type this library does not knowUnknown = 0// A user routine is runningUserRoutine = 5}
Call stack
GetActivationRecord reads one frame of the call stack. Frame 1 holds the program pointer, and the number grows towards the entry point of the program. The controller refuses the request when the task has no program pointer, or when the stack is not that deep.
// Frame 1 is the one holding the program pointer, the number grows towards the entry pointfor (int frame = 1; frame <= 5; frame++){RapidActivationRecord record = robot.Rws.Rapid.GetActivationRecord("T_ROB1", frame);Console.WriteLine(record.RoutineUrl);Console.WriteLine(record.BeginRow + "," + record.BeginColumn);Console.WriteLine(record.ExecutionLevel);}// The routines the program pointer may be moved to, service routines includedforeach (RapidServiceRoutineItem routine in robot.Rws.Rapid.GetServiceRoutines("T_ROB1")){Console.WriteLine(routine.Name + " -> " + routine.Url + " service=" + routine.IsServiceRoutine);}
RapidExecutionLevel | Where execution stands |
|---|---|
Normal | In the program itself |
Trap | In a trap routine |
User | In a routine started by hand, such as a service routine |
None | Nothing is running at this level |
Unknown | The controller reported a level the SDK does not know |
// Gets one frame of the call stack of a task: which routine is running and where execution stands in it (synchronous)RapidActivationRecord GetActivationRecord(string task, int stackFrame = 1);// Gets the routines of a task the program pointer can be moved to (synchronous)RapidServiceRoutineItem[] GetServiceRoutines(string task, int? start = null, int? limit = null);
Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.
public class RapidActivationRecord {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidActivationRecord" data-throw-if-not-resolved="false"></xref> classpublic RapidActivationRecord()// Column the executing statement starts at, null when the controller did not report itpublic int? BeginColumn { get; set; }// Line the executing statement starts at, null when the controller did not report itpublic int? BeginRow { get; set; }// Column the executing statement ends at, null when the controller did not report itpublic int? EndColumn { get; set; }// Line the executing statement ends at, null when the controller did not report itpublic int? EndRow { get; set; }// Level at which this frame is executingpublic RapidExecutionLevel ExecutionLevel { get; set; }// Path of the routine this frame is executingpublic string RoutineUrl { get; set; }// Path identifying this stack frame, which the UI instruction resources also takepublic string StackUrl { get; set; }// Returns a string representation of this stack framepublic override string ToString()}
public class RapidServiceRoutineItem {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidServiceRoutineItem" data-throw-if-not-resolved="false"></xref> classpublic RapidServiceRoutineItem()// Whether this is a service routine rather than an ordinary one, null when the controller// did not report itpublic bool? IsServiceRoutine { get; set; }// Name of the routine, for example "LoadIdentify"public string Name { get; set; }// Returns a string representation of this routinepublic override string ToString()// Path of the routine, which <code>RapidService.SetProgramPointerToRoutineUrl()</code> takespublic string Url { get; set; }}
public enum RapidExecutionLevel {// Nothing is executingNone = 1// The normal user code is executingNormal = 2// A trap routine is executingTrap = 3// The controller reported a level this library does not knowUnknown = 0// A user routine is executingUser = 4}
Answer an operator dialogue
A RAPID program can stop and ask the operator something. The controller then reports one pending instruction, and the program waits until it is answered. GetActiveUiInstruction returns null when nothing is pending.
// Null when the program is not asking the operator for anything right nowRapidUiInstruction question = robot.Rws.Rapid.GetActiveUiInstruction();if (question != null){Console.WriteLine(question.Instruction); // name of the RAPID instruction waitingConsole.WriteLine(question.Message);Console.WriteLine(question.Event); // Send, Post or Abort// What the program passed in, and what it is waiting for. The names of the// parameters depend on the instruction, so read them before writing one.foreach (RapidUiInstructionParameter parameter inrobot.Rws.Rapid.GetUiInstructionParameters(question.StackUrl)){Console.WriteLine(parameter.Name + " = " + parameter.Value);}// Answering is a write, so it needs the mastershiprobot.Rws.Mastership.Request(MastershipDomain.Rapid);try{// Write the parameter carrying the answer, then the one marking it as completedrobot.Rws.Rapid.SetUiInstructionParameter(question.StackUrl, "TPCompleted", "TRUE");}finally{robot.Rws.Mastership.Release(MastershipDomain.Rapid);}Console.WriteLine(robot.Rws.Rapid.GetUiInstructionParameter(question.StackUrl, "TPCompleted"));}
The names of the parameters depend on the instruction the program used, so read them with GetUiInstructionParameters before writing one. The answer is written first, then the parameter marking the dialogue as completed. Writing a parameter needs the Rapid mastership, and fails when the instruction is no longer pending.
// Gets the dialogue a running RAPID program is currently asking an operator for (synchronous) Answering it means writing its parameters with String%2cSystem.String), addressed by the path this returns.RapidUiInstruction GetActiveUiInstruction();// Gets the value of one parameter of a pending UI instruction (synchronous)string GetUiInstructionParameter(string stackUrl, string parameter);// Gets every parameter of a pending UI instruction: what the program passed in, and what it is waiting for (synchronous)RapidUiInstructionParameter[] GetUiInstructionParameters(string stackUrl);// Answers a pending UI instruction by writing one of its parameters (synchronous) An instruction is normally answered by writing the parameter carrying the answer and then the one marking it as completed.void SetUiInstructionParameter(string stackUrl, string parameter, string value);
Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.
public class RapidUiInstruction {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidUiInstruction" data-throw-if-not-resolved="false"></xref> classpublic RapidUiInstruction()// What the instruction is asking of the clientpublic RapidUiInstructionEvent Event { get; set; }// Level at which the instruction is executingpublic RapidExecutionLevel ExecutionLevel { get; set; }// Name of the RAPID instruction that opened the dialogue, for example "TPReadNum"public string Instruction { get; set; }// Text the instruction displayspublic string Message { get; set; }// Path identifying the call, which the parameter methods takepublic string StackUrl { get; set; }// Returns a string representation of this instructionpublic override string ToString()}
public class RapidUiInstructionParameter {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidUiInstructionParameter" data-throw-if-not-resolved="false"></xref> classpublic RapidUiInstructionParameter()// Name of the parameter, for example "TPCompleted"public string Name { get; set; }// Returns a string representation of this parameterpublic override string ToString()// Value of the parameter, written the way RAPID writes itpublic string Value { get; set; }}
public enum RapidUiInstructionEvent {// The instruction has been abandoned and no answer is expected any moreAbort = 3// The instruction only displays something and expects no answerPost = 2// The instruction is waiting for an answerSend = 1// The controller reported an event this library does not knowUnknown = 0}
Signals renamed by the program
A RAPID program can give another name to an I/O signal. GetAliasIo lists these names as long as the program declaring them is loaded. The signals themselves are read and written with the I/O service.
// The signals a loaded program gave another name to. Empty when no program declares any.foreach (RapidAliasIoItem alias in robot.Rws.Rapid.GetAliasIo()){Console.WriteLine(alias.AliasName + " -> " + alias.SignalName + " (" + alias.Type + ")");}
// Gets the I/O signals a running RAPID program has given an alias to (synchronous)RapidAliasIoItem[] GetAliasIo(int? start = null, int? limit = null);
Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.
public class RapidAliasIoItem {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.RapidAliasIoItem" data-throw-if-not-resolved="false"></xref> classpublic RapidAliasIoItem()// Name the RAPID program refers to the signal bypublic string AliasName { get; set; }// Name of the I/O signal the alias points atpublic string SignalName { get; set; }// Returns a string representation of this aliaspublic override string ToString()// Type of the aliased signalpublic IoSignalType Type { get; set; }}
Position of the robot
The position of the robot, its mechanical units and the external axes of a task are read from the motion system service.