minute read
Command Queue in the .NET API
You are reading our Automation1 API documentation for the .NET programming language.
In the .NET API, Command Queue lets you execute AeroScript commands on the Automation1 controller in a first-in, first-out process.
IMPORTANT: Before you read more about the command queue, read the .NET API Commands page. This page adds to that information.
The Basics
When you execute 3
to 5
milliseconds, based on the performance of the PC. It also includes all the network latency delays that might occur. If this delay is not compatible with your production environment, use Command Queue.
Command Queue lets you queue up multiple commands on the controller to prevent overhead and delay. Some AeroScript commands are available only in Command Queue because they cannot accept this overhead and delay. These commands include all the AeroScript commands that require Lookahead Synchronization, such as velocity blending, cutter radius compensation, and corner rounding. If you execute a series of MovePt() or MovePvt() commands, this process also requires a command queue. If you do not use one, your profile will stutter and drop out because of the delay that occurs between commands.
A command queue on a task stores all the AeroScript commands that you add. It executes them sequentially, in the order that they were added, which is a first-in, first-out process. If you add AeroScript commands to the command queue, the .NET function that you called to add the commands does not block unless the conditions that follow occur:
- The command queue is full.
- You specified the command queue to block when it is full.
If these two conditions do not occur, the AeroScript commands are added to the command queue. But all the commands that were previously added execute first. Then the AeroScript commands will execute.
Typically, a command queue is necessary for you to use when one of these use-cases apply:
- Your process cannot accept the delay that occurs between executing AeroScript commands.
- You want to use AeroScript commands that are compatible only with a command queue.
A command queue exists on a specific controller task. That task can execute only queued commands while the command queue is active. While a command queue is active, the restrictions that follow apply:
- Non-queued AeroScript commands cannot execute.
- AeroScript programs cannot run.
- You cannot use retrace.
- You cannot use interrupt motion.
- You cannot use the AeroScript sync statement to execute a function on the controller task where a command queue exists. You can use the AeroScript sync statement to execute a function on a different task.
- You cannot use the AeroScript statements that follow:
- program statement
- if statement
- switch statement
- goto statement
- break statement
- continue statement
- while loop
- for loop
- foreach loop
- repeat loop
- You cannot declare an AeroScript variable, struct, enum, property, or function.
- You cannot execute the AeroScript functions that follow:
- ProgramStop()
- ProgramPause()
- ProgramReset()
- ProgramRestart()
- ProgramLoad()
- ProgramStepInto()
- ProgramStepOver()
- ProgramStepOut()
- AeroScript functions apply all relative paths as absolute paths.
How to Use
In the .NET API, Command Queue is part of the Controller.Runtime property. For all the APIs that operate under this property, the Automation1 controller must be running before you can do work with a command queue. For more information about this property, see the Controller page. If you reset the Automation1 controller, this process will stop all the active command queues.
To use a command queue, you must first begin a command queue on a specific task and with a specific AeroScript command capacity. The shouldBlockIfFull argument controls the behavior of how an AeroScript command is added to a command queue that is full:
- If you specify the argument as true, the add blocks until the AeroScript command can be added to the queue.
- If you specify the argument as false, the add throws an exception.
Refer to the example that follows.
CommandQueue commandQueue = controller.Runtime.Commands.BeginCommandQueue(string taskName, int commandCapacity, bool shouldBlockIfFull);
The command capacity specifies the maximum number of AeroScript commands that you can add to the command queue before it is full. When the command queue is full, you cannot continue to add new AeroScript commands. A larger command capacity uses more controller memory. The controller memory is limited.
WARNING: If you specify a command capacity that is too large, memory allocation errors can occur. If they occur, you must decrease your command capacity.
When the command queue begins on a specific task, non-queued AeroScript commands cannot execute and AeroScript programs cannot run on that task.
When the command queue begins on a specific task, the execution of commands is not paused. Thus, AeroScript commands that you add to the queue will immediately start to execute and the state of the task becomes Queue Running. If you enable the feedhold state on the task, the state of the task stays Queue Running.
If you want to pause the execution of commands in the command queue, use the Pause method. This method pauses the execution of commands from the command queue after the controller finishes executing the current command and the state of the task becomes Queue Paused. Refer to the example that follows.
commandQueue.Pause();
If the execution of commands in the command queue is paused, you can use the Resume method to resume the execution of commands. Refer to the example that follows.
commandQueue.Resume();
The CommandQueue object has the Commands property. You can use this property to add AeroScript commands to the command queue. When you add AeroScript commands, they are not executed immediately. Instead, they are queued for execution. All the commands that you previously added are executed first. Then the newest AeroScript commands that you added will execute. These methods do not block unless the conditions that follow occur:
- The command queue is full.
- You specified the command queue to block when it is full.
Refer to the example that follows.
commandQueue.Commands.Motion.Enable(string axis);
commandQueue.Commands.Motion.MoveLinear(string axis, double distance, double coordinatedSpeed);
commandQueue.Commands.Motion.Disable(string axis);
To see a list of all the .NET properties and methods that you can use for Command Queue, refer to the Full Reference section.
While the command queue is active, you can examine its status to find the information that follows:
- The number of AeroScript commands that were executed.
- The number of AeroScript commands in the command queue that still need to be executed.
Refer to the example that follows.
commandQueue.Status.IsEmpty
commandQueue.Status.NumberOfExecutedCommands
commandQueue.Status.NumberOfUnexecutedCommands
Each time that you access the Status property, you get a new status from the controller. For best results, access the Status property one time only to get the most current status. Then use the returned CommandQueueStatus object until you need to get the most current status of the controller again. If you do not do this and try to access the Status property too many times, bugs known as race conditions can occur. These bugs occur when the status of the task changes between multiple accesses of the property.
If you want to wait for the command queue to empty and complete its execution of all the commands that you added to it, use the WaitForEmpty method. This method blocks until the command queue is fully empty. Then this method returns and your code execution continues. Refer to the example that follows.
commandQueue.WaitForEmpty();
When you are done using the command queue, call the EndCommandQueue method to end the command queue and return the task to its normal state. Refer to the example that follows.
controller.Runtime.Commands.EndCommandQueue(CommandQueue commandQueue);
If you end a command queue that is currently executing a command, that command is aborted and all the queued AeroScript commands are discarded. To prevent this from occurring, use the WaitForEmpty method when you end the command queue. This method makes sure that the command queue is not executing commands.
After you end the command queue, non-queued AeroScript commands can execute and AeroScript programs can run on that task. You cannot continue to use the CommandQueue object. To make a new command queue, you must call the BeginCommandQueue method again.
Execute Custom AeroScript
You can execute most AeroScript commands through the .NET API. In some special cases, you must execute custom AeroScript directly or execute a file that includes custom AeroScript.
Execute Custom AeroScript Directly
To execute custom AeroScript directly, use the CommandQueue.Commands.Execute method to specify the arbitrary AeroScript that you want to add to the command queue. Refer to the example that follows.
commandQueue.Commands.Execute(string stringAeroScript);
stringAeroScript can include multiple lines of AeroScript. You can separate lines of AeroScript with newline characters, including CR, NL, CRNL. If the string has multiple lines, TaskStatusItem.ProgramLineNumber and TaskStatusItem.CommandQueueLineNumber will be incremented by the number of lines in the string, but TaskStatusItem.CommandQueueExecutedCount and CommandQueueStatus.NumberOfExecutedCommands will be incremented by 1. This occurs because there is a difference between lines of AeroScript and a command that has multiple lines of AeroScript. If you add a newline to the end of stringAeroScript, TaskStatusItem.ProgramLineNumber, TaskStatusItem.CommandQueueLineNumber, TaskStatusItem.CommandQueueExecutedCount, and CommandQueueStatus.NumberOfExecutedCommands will be incremented an additional time. To prevent this, do not add a newline to the end.
Execute Custom AeroScript from a File
The .NET API can automatically insert lines of AeroScript as commands into a command queue. You can do this with an MDK file or a controller file. This process can help you if you already have a file that includes all of your AeroScript or if you want to separate your AeroScript process from your custom .NET application. The specified file can include only simple lines of AeroScript. The file cannot include variables, if statements, loops, or other control flow statements.
To execute an MDK file that has lines of AeroScript, use the CommandQueue.Commands.ExecuteFromMdkFile method. To execute a controller file that has lines of AeroScript, use the CommandQueue.Commands.ExecuteFromControllerFile method. For more information about the MDK and controller file systems, see Working with Files.
Aerotech recommends that you set CommandQueue.ShouldBlockIfFull to true when you create the command queue that is executed from a file. If it is set to false and the command queue fills while reading the file, a ControllerOperationException
will be thrown.
To increase throughput, lines of AeroScript from the file are added to the command queue as commands that have multiple lines. By default, numberOfLinesPerCommand is set to 1000, which works in most cases. The numberOfLinesPerCommand argument defines how many file lines to read from the file for each command. If the command queue is empty before the file is fully read, call the overload of CommandQueue.Commands.ExecuteFromMdkFile or CommandQueue.Commands.ExecuteFromControllerFile with the numberOfLinesPerCommand argument set to a value greater than 1000. The value of the numberOfLinesPerCommand depends on the performance of your PC and is not deterministic.
IMPORTANT: If you specify a value for numberOfLinesPerCommand that is too large, memory allocation errors can occur. If you get memory allocation errors, decrease the value of the numberOfLinesPerCommand.
When CommandQueue.Commands.ExecuteFromMdkFile or CommandQueue.Commands.ExecuteFromControllerFile return, there can be lines of AeroScript from the file that have not executed and are still in the command queue. Use the CommandQueue.WaitForEmpty method to make sure all AeroScript commands have executed. Refer to the example that follows.
CommandQueue commandQueue = controller.Runtime.Commands.BeginCommandQueue("Task 1", 100, true);
commandQueue.Commands.ExecuteFromMdkFile("MovePvt20kHz.txt", 1000);
commandQueue.WaitForEmpty();
Executing blank lines on the command queue will not cause an exception.
AeroScript Commands
You can use AeroScript commands to change the state of a command queue.
If the execution of queued AeroScript commands from the command queue is not currently paused, use the functions that follow to pause the execution of commands from the queue.
CommandQueuePause()
CommandQueuePause($task as integer)
If the execution of queued AeroScript commands from the command queue is currently paused, use the function that follows to resume the execution of commands from the queue.
CommandQueueStart($task as integer)
Use the functions that follow to end the command queue.
CommandQueueStop()
CommandQueueStop($task as integer)
Keep a Command Queue Full
WARNING: You must keep the command queue populated at all times. If the command queue is not populated, your process will stall and motion problems might occur.
When the command queue begins on a task, the controller executes all the commands that are in the command queue as quickly as possible. If the controller automatically executes commands from the command queue more quickly than you can add them, the command queue will not have a sufficient quantity of commands to execute. This condition is known as a starvation of the command queue.
While the command queue is active, you can examine its status to find the number of times that a starvation of the command queue has occurred. Refer to the example that follows.
commandQueue.Status.NumberOfTimesEmptied
For the axes that you specify to a command, the controller automatically decelerates them to zero velocity to prevent motion problems from occurring when all the conditions that follow are true:
- Velocity Blending mode is enabled on the task.
- A starvation of the command queue occurs.
- The most recently executed command from the command queue is a MoveCcw(), MoveCw(), or MoveLinear() command.
But when the two conditions that follow are true, the controller does not automatically decelerate the axes that you specify to a command to zero velocity:
- A starvation of the command queue occurs.
- The most recently executed command from the command queue is a MovePt() or MovePvt() command.
As a result, motion problems can occur.
To prevent a starvation of the command queue, do one or more of the options that follow:
-
Issue a Dwell() command as the first command. Also issue it in other important locations. When you issue the Dwell() command in multiple locations, you get more time to add commands to the command queue before the controller executes them.
-
Pause the command queue before you add more commands. You can pause the command queue by using the CommandQueue.Pause() method. You can also issue a CommandQueuePause() command as the first command.
-
Issue a wait statement first. Then use the CommandQueueCount task status item to make the first command wait for the command queue to fill with a specified number of commands before the controller executes them. Refer to the code sample that follows:
commandQueue.Execute("wait(StatusGetTaskItem ... >= 20)");
Example Code
For more information about how to use a command queue, refer to the example program that follows.
// Begin a new command queue on task 1.
CommandQueue commandQueue = controller.Runtime.Commands.BeginCommandQueue("Task 1", 10, true);
// First, pause the command queue so you can add all the commands before they are executed.
commandQueue.Pause();
// Add all the AeroScript commands that you want to execute.
commandQueue.Commands.AdvancedMotion.VelocityBlendingOn();
commandQueue.Commands.Motion.Enable("X");
commandQueue.Commands.Motion.MoveLinear("X", 10, 5);
commandQueue.Commands.Motion.MoveLinear("X", 5, 5);
commandQueue.Commands.Motion.Disable("X");
commandQueue.Commands.AdvancedMotion.VelocityBlendingOff();
// Resume the command queue so that all the commands that you added start to execute.
commandQueue.Resume();
// Here you can do other things such as more process, get status, etc.
// You can do these things because the command queue is executing commands on the controller and is not blocking your code execution.
// Here you wait to make sure that the command queue executes all the commands. You must do this before you end the command queue.
// When you end the command queue, this process aborts all motion and commands.
commandQueue.WaitForEmpty();
// At this time, end the command queue.
// You can also call CommandQueue.EndCommandQueue to abort the command that is currently executing and discard the remaining commands.
controller.Runtime.Commands.EndCommandQueue(commandQueue);
Thread Safety
The Controller.Runtime.Commands.BeginCommandQueue method is thread safe. You can call it from two or more threads without interference.
The CommandQueue class is not thread safe. Only one thread at a time can access an instance of this class. If it is necessary for two or more threads to access or change an instance of this class, you must use locks to limit the access. You must also use locks when you pass a CommandQueue instance to the Controller.Runtime.Commands.EndCommandQueue method.
The Controller.Runtime.Commands.EndCommandQueue method is thread safe. You can call it from two or more threads without interference. But if you pass the CommandQueue instance into this method, this instance is not thread safe. If it is necessary for two or more threads to access or change an instance of the CommandQueue class, you must use locks to limit the access.
Full Reference
For more information about the properties and methods that are available for Command Queue, refer to the lists that follow.
CommandQueue Properties
Gets the name of the task on which this command queue exists.
Gets the numeric index of the task on which this command queue exists.
Gets the maximum number of unexecuted AeroScript commands that you can store in this command queue. When you store the maximum number of commands, the command queue is full.
Gets information about whether or not to block if you add an AeroScript command while this command queue is full. If true, the add blocks until the command is added. If false, a ControllerOperationException is thrown.
Gets the current status of this command queue by returning a new CommandQueueStatus object that represents a moment in time for this task.
CommandQueue Methods
Pauses the execution of queued AeroScript commands from the command queue. If an AeroScript command is currently executing, the execution completes normally. That command is not aborted.
Resumes the execution of queued AeroScript commands from this command queue.
Waits for the command queue to be empty and blocks until all the AeroScript commands that you added to it are executed. Use this method to make sure that the command queue is done executing commands. Then you can use the Controller.Runtime.Commands.EndCommandQueue method to end the command queue.
Waits for the command queue to be empty and blocks until all the AeroScript commands that you added to it are executed. Use this method to make sure that the command queue is done executing commands. Then you can use the Controller.Runtime.Commands.EndCommandQueue method to end the command queue.
millisecondsTimeout: The number of milliseconds to wait until the command queue is empty. If the command queue uses a larger quantity of time to become empty, this method returns when the command queue is empty.
CommandQueueStatus Properties
Gets the status that lets you know if the command queue is currently paused.
Gets the status that lets you know if the command queue is empty. When the command queue is empty, there are no AeroScript commands currently executing and no other AeroScript commands in the command queue.
Gets the program line number of the command that was most recently executed from the command queue.
Gets the total number of commands that the command queue executed during its lifespan. A command can have one or more lines of AeroScript if you call the CommandQueue.Commands.Execute method with a string of AeroScript that has multiple lines. This property gets the number of executed commands in the command queue, even when there are multiple lines of AeroScript in each command.
Gets the total number of times that you emptied the command queue.
Gets the total number of unexecuted commands that you added to the command queue. If an AeroScript command is currently executing, that command is included in the total. One command can have one or more lines of AeroScript if you call the CommandQueue.Commands.Execute method with a string of AeroScript that has multiple lines. This property gets the number of commands in the command queue that were unexecuted, even when there are multiple lines of AeroScript in each command.