minute read
Command Queue in the C API
You are reading our Automation1 API documentation for the C programming language.
The Basics
In the C 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, make sure that you read the Commands page first. This page builds on that information.
When you execute non-queued AeroScript commands through the C API, a quantity of fixed overhead occurs. When you execute two commands, one immediately after the other, there is some delay that occurs between the commands. This delay averages from 3
to 5
milliseconds, based on network latency and the performance of the PC. It also includes all the network latency delays that might occur.
IMPORTANT: If this delay is not compatible with your production environment, use Command Queue.
Command Queue lets you queue 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 the commands. If you are doing submillisecond PVTs, you must add the PVTs inside of a CriticalSectionStart() / CriticalSectionEnd() block. If you do not use the critical section functions, the motion will not be continuous. Refer to the Task Scheduling section of Task and Program Functions for more information.
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 C 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 will execute first. Then the AeroScript commands will execute.
Typically, it is necessary for you to use a command queue when one of these conditions apply:
- Your process cannot accept the delay that occurs between AeroScript commands that are executing.
- 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.
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.
If the command queue is emptied, this will interrupt any velocity blending or lookahead synchronization and the axes will decelerate to zero velocity. Make sure that you add AeroScript commands to the command queue faster than the command queue can execute them.
Tip: After you begin a command queue, you might want to pause it. Then you can add many AeroScript commands before you continue the command queue.
How to Use
Command Queue is part of the controller runtime. Thus the Automation1 controller must be running before you do work with a command queue. For more information, 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. Use the Automation1_CommandQueue_Begin() function. This function gives you an Automation1CommandQueue handle. 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 returns an error.
bool Automation1_CommandQueue_Begin(Automation1Controller controller, int32_t taskIndex, int32_t commandCapacity, bool shouldBlockIfFull, Automation1CommandQueue* commandQueueOut);
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.
Also, 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 continues as Queue Running
.
To pause the execution of commands in the command queue, use Queue Paused
. Refer to the example that follows.
bool Automation1_CommandQueue_Pause(Automation1CommandQueue commandQueue);
If the execution of commands is paused in the command queue, you can use
bool Automation1_CommandQueue_Resume(Automation1CommandQueue commandQueue);
You can use functions to add AeroScript commands to the command queue. These functions require an Automation1CommandQueue handle. 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 functions 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.
bool Automation1_CommandQueue_Enable(Automation1CommandQueue commandQueue, int32_t* axes, int32_t axesLength);
bool Automation1_CommandQueue_MoveLinear(Automation1CommandQueue commandQueue, int32_t* axes, int32_t axesLength, double* distances, int32_t distancesLength, double coordinatedSpeed);
bool Automation1_CommandQueue_Disable(Automation1CommandQueue commandQueue, int32_t* axes, int32_t axesLength);
To see a list of all the C functions that you can use for Command Queue, refer to the Full Reference section of this page.
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.
bool Automation1_CommandQueue_GetStatus(Automation1CommandQueue commandQueue, Automation1CommandQueueStatus* commandQueueStatusOut);
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 Automation1_CommandQueue_WaitForEmpty() function. This function blocks until the command queue is fully empty. Then this function returns and your code execution continues.
bool Automation1_CommandQueue_WaitForEmpty(Automation1CommandQueue commandQueue, int32_t millisecondsTimeout);
When you are done using the command queue, call the Automation1_CommandQueue_End() function. This function ends the command queue, frees memory, and returns the task to its normal state.
Automation1_CommandQueue_End(Automation1CommandQueue commandQueue, int32_t millisecondsTimeout);
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 Automation1_CommandQueue_WaitForEmpty() function when you end the command queue. This function 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 Automation1CommandQueue handle. To make a new command queue, you must call the Automation1_CommandQueue_Begin() function again.
Execute Custom AeroScript
You can execute most AeroScript commands through the C API. In some special cases, you must execute custom AeroScript directly or execute a file that contains the custom AeroScript.
Execute Custom AeroScript Directly
To execute custom AeroScript directly, use the Automation1_CommandQueue_Execute() function to specify the custom AeroScript that you want to add to the command queue. Refer to the example that follows.
bool Automation1_CommandQueue_Execute(Automation1CommandQueue commandQueue, const char* aeroScriptText);
The aeroScriptText parameter can include one or more lines of AeroScript. You can separate one or more lines of AeroScript with newline characters, which include CR, LF, and CRLF. If the aeroScriptText parameter has one or more lines, the Automation1TaskStatusItem_CommandQueueLineNumber
status item will be incremented by the number of lines in the string. If the Automation1TaskStatusItem_CommandQueueExecutedCount
status item and the Automation1CommandQueueStatus struct member NumberOfExecutedCommands have one or more lines, they will be incremented by 1. This occurs because there is a difference between lines of AeroScript and a command that has one or more lines of AeroScript.
Execute Custom AeroScript from a File
You can have the C API read from a file and 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 with all of your AeroScript or if you want to separate your AeroScript process from your custom C application. The specified file can include simple lines of AeroScript only. The file cannot have variables, if
statements, loops, or other control flow statements.
To execute an MDK file that has lines of AeroScript, use the Automation1_CommandQueue_ExecuteFromMdkFile() function. To execute a controller file that has lines of AeroScript, use the Automation1_CommandQueue_ExecuteFromControllerFile() function. For more information about the MDK and controller file systems, see Working with Files.
Aerotech recommends that you set the shouldBlockIfFull argument to True when you create a command queue that is executed from a file. If it is set to False and the command queue fills while reading the file, then Automation1_CommandQueue_Execute() or Automation1_CommandQueue_ExecuteFromFile() will return False.
To increase throughput, lines of AeroScript from the file are added to the command queue as commands that have one or more lines. The numberOfLinesPerCommand argument defines the number of file lines to read from the file for each command. You can set the numberOfLinesPerCommand argument to 1000, which is applicable most of the time. If the command queue is empty before the file is fully read, set the numberOfLinesPerCommand argument to more than 1000. The value of this argument depends on the performance of your PC and is not deterministic.
WARNING: If you specify a value for the numberOfLinesPerCommand argument that is too large, memory allocation errors can occur. If you get memory allocation errors, decrease the value of this argument.
When the Automation1_CommandQueue_ExecuteFromMdkFile() or Automation1_CommandQueue_ExecuteFromControllerFile() function returns, there can be remaining lines of AeroScript from the file that were executed and are still in the command queue. Use the Automation1_CommandQueue_WaitForEmpty() function to make sure all AeroScript commands have executed. Refer to the example that follows.
Automation1CommandQueue commandQueueOut = NULL;
if (!Automation1_CommandQueue_Begin(controller, 1, 100, true, &commandQueueOut)) { /* handle error */}
if (!Automation1_CommandQueue_ExecuteFromMdkFile(commandQueueOut, "MovePvt20kHz.txt" , 1000)) { /* handle error */ }
if (!Automation1_CommandQueue_WaitForEmpty(commandQueue, -1)) { /* handle error */ }
If the controller executes blank lines on the command queue, this 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 paused at this time, use the AeroScript functions that follow to pause the execution of commands from the queue.
CommandQueuePause($task as integer)
If the execution of queued AeroScript commands from the command queue is currently paused, use the AeroScript function that follows to continue the execution of commands from the queue.
Use the AeroScript functions that follow to stop the command queue.
CommandQueueStop($task as integer)
Example Code
int32_t task1 = 1;
int32_t axisX = 0;
double distance1 = 10.0;
double distance2 = 10.0;
Automation1CommandQueue commandQueue = NULL;
// Begin a new command queue on task 1.
if (!Automation1_CommandQueue_Begin(controller, task1, 10, true, &commandQueue)) { /* handle error */ }
// First, pause the command queue so that you can add all the commands before they are executed.
if (!Automation1_CommandQueue_Pause(commandQueue)) { /* handle error */ }
// Add all the AeroScript commands that you want to execute.
if (!Automation1_CommandQueue_VelocityBlendingOn(commandQueue)) { /* handle error */ }
if (!Automation1_CommandQueue_Enable(commandQueue, &axisX, 1)) { /* handle error */ }
if (!Automation1_CommandQueue_MoveLinear(commandQueue, &axisX, 1, &distance1, 1, 5.0)) { /* handle error */ }
if (!Automation1_CommandQueue_MoveLinear(commandQueue, &axisX, 1, &distance2, 1, 5.0)) { /* handle error */ }
if (!Automation1_CommandQueue_Disable(commandQueue, &axisX, 1)) { /* handle error */ }
if (!Automation1_CommandQueue_VelocityBlendingOff(commandQueue)) { /* handle error */ }
// Resume the command queue so that all the commands that you added start to execute.
if (!Automation1_CommandQueue_Resume(commandQueue)) { /* handle error */ }
// 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.
if (!Automation1_CommandQueue_WaitForEmpty(commandQueue, -1)) { /* handle error */ }
// At this time, end the command queue.
// You can also call the Automation1_CommandQueue_End() function to abort the command that is currently executing and discard the remaining commands.
if (!Automation1_CommandQueue_End(commandQueue, -1)) { /* handle error */ }
// Set the command queue handle to null because it is not valid after you end the command queue.
commandQueue = NULL;
Thread Safety
The Automation1_CommandQueue_Begin() function is thread safe. You can call it from two or more threads without interference.
The Automation1_CommandQueue_End() function is not thread safe. Only one thread should call this function for a single Automation1CommandQueue handle.
The other Automation1_CommandQueue_ functions and the Automation1CommandQueue handle are not thread safe. Only one thread at a time can call these functions or access this handle. If it is necessary for two or more threads to call these functions or access this handle, you must use locks to limit the access.
Full Reference
For more information about the structs and functions that are available for Command Queue, refer to the lists that follow.
Automation1CommandQueueStatus struct
Represents the status of a command queue on an Automation1 controller.
Gets information that lets you know if the command queue is currently paused.
Gets information that lets you know if the command queue is empty. If it is empty, there is no AeroScript command that is currently executing and there are no other AeroScript commands in the command queue.
Gets the total number of commands that the command queue executed over its full lifespan. One command can have one or more lines of AeroScript if you call the Automation1_CommandQueue_Execute() function with a string of AeroScript that has one or more lines. This status item gets the number of commands that were executed in the command queue, even when there are one or more lines of AeroScript in each command.
Gets the total number of commands that were added to the command queue and still need to execute. If there is an AeroScript command that is currently executing, it is included in this number. One command can have one or more lines of AeroScript if you call the Automation1_CommandQueue_Execute()function with a string of AeroScript that has one or more lines. This status item gets the number of commands in the command queue that were not executed, even when there are one or more lines of AeroScript in each command.
Gets the number of times the command queue was emptied.
Functions
Gets the current status of a command queue.
commandQueue
(In): The command queue for which to retrieve the status.
commandQueueStatusOut
(Out): The current status of the command queue. Use this argument only if the function call was successful. This argument must have memory preallocated before you pass it into this function.
Returns: True if the status of the command queue was retrieved successfully. False if the status of the command queue was not retrieved. See the Automation1_GetLastError() and Automation1_GetLastErrorMessage() functions for more information. You can find information about these functions in the Errors and Error Handling section of C API Guidelines.
Starts a command queue on the specified task. A command queue on a task will store all the AeroScript commands that are added to the command queue and execute them sequentially, in the order that they were added. When you add AeroScript commands to the command queue, this process does not block unless the command queue is full and the argument shouldBlockIfFull is true. Instead, the AeroScript command is added to the command queue and will be executed in the future after all the previously added commands are executed. A command queue is usually used to prevent communication latency from occurring between AeroScript commands when you execute motion with the Commands API. (For Example: Let's say that you use velocity blending. For this type of motion, the communication latency will cause deceleration to occur.) The specified task can execute only queued commands while the command queue is active. Non-queued commands from the Commands API and AeroScript programs cannot run while the command queue is active. When you are done using the command queue, call the Automation1_CommandQueue_End() function to prevent memory from leaking, stop the command queue on the specified task, and return the task to normal AeroScript execution.
controller
(In): A handle that represents a connection to an Automation1 controller.
taskIndex
(In): The index of the task on which to create a command queue.
commandCapacity
(In): The maximum number of unexecuted AeroScript commands that can be stored in the command queue, after which the command queue is full. If the number of unexecuted AeroScript commands in the command queue increases to this number, the next AeroScript command that you add will either block until the command can be added (if shouldBlockIfFull is true) or return an error (if shouldBlockIfFull is false).
shouldBlockIfFull
(In): Whether or not to block if you add an AeroScript command while the command queue is full. If true, the add will block until the command can be added. If false, an error will occur.
commandQueueOut
(Out): A handle that represents a command queue on a task on the Automation1 controller. Use this handle only if the function call was successful.
Returns: True if the creation of the command queue was successful. False if the creation of the command queue was not successful. See the Automation1_GetLastError() and Automation1_GetLastErrorMessage() functions for more information. You can find information about these functions in the Errors and Error Handling section of C API Guidelines.
Waits for the command queue to become empty, blocking until all the AeroScript commands that you added to the command queue are executed. You can use this function to make sure that the command queue is done executing commands before you end it with the Automation1_CommandQueue_End() function.
commandQueue
(In): The command queue for which you wait for the execution of all the AeroScript commands to be completed.
millisecondsTimeout
(In): The number of milliseconds that you wait for the command queue to empty. If the command queue uses more than this quantity of time to become empty, this function will return. If you set this value to -1
, this function will wait indefinitely for the command queue to become empty.
Returns: True if the command queue successfully completed the execution of all of its AeroScript commands or the timeout has been reached. False if the command queue did not execute all of its AeroScript commands or the timeout was not reached. See the Automation1_GetLastError() and Automation1_GetLastErrorMessage() functions for more information. You can find information about these functions in the Errors and Error Handling section of C API Guidelines.
Resumes the execution of queued AeroScript commands from a command queue.
commandQueue
(In): The command queue from which to start the execution of commands.
Returns: True if the execution of AeroScript commands has resumed or the command queue was already executing AeroScript commands. False if the execution of commands did not resume or the command queue was not already executing AeroScript commands. See the Automation1_GetLastError() and Automation1_GetLastErrorMessage() functions for more information. You can find information about these functions in the Errors and Error Handling section of C API Guidelines.
Pauses the execution of queued AeroScript commands from a command queue. If there is an AeroScript command that is currently executing, it will complete normally. The command will not be aborted.
commandQueue
(In): The command queue for which to pause the execution of AeroScript commands.
Returns: True if the execution of AeroScript commands has paused or the command queue was already paused. False if the execution of AeroScript commands did not pause or the command queue was not already paused. See the Automation1_GetLastError() and Automation1_GetLastErrorMessage() functions for more information. You can find information about these functions in the Errors and Error Handling section of C API Guidelines.
Stops the command queue on the task and returns the task to normal AeroScript execution. If there is an AeroScript command that is currently executing, it will be aborted. All the remaining AeroScript commands that are queued will be discarded. After you calling this function, you cannot continue to use this command queue handle.
commandQueue
(In): The command queue to end.
millisecondsTimeout
(In): The number of milliseconds to wait to end the command queue. If the command queue uses more than this quantity of time to end, the function will fail. If you set this value to -1
, this function will wait indefinitely for the command queue to end.
Returns: True if the execution of commands from the command queue has stopped. False if the execution of commands from the command queue did not stop. See the Automation1_GetLastError() and Automation1_GetLastErrorMessage() functions for more information. You can find information about these functions in the Errors and Error Handling section of C API Guidelines.
Adds an AeroScript command to the command queue. This function does not block unless the command queue is full and commandQueue argument shouldBlockIfFull is set to true. Instead, the AeroScript command is added to the command queue and will execute in the future after all the commands that you previously added are executed.
commandQueue
(In): The command queue on which to perform this AeroScript command.
aeroScriptText
(In): The null-terminated AeroScript string text to compile and add to the command queue.
Returns: True if the AeroScript command was compiled and added to the command queue. False if the AeroScript command was not compiled and added to the command queue. See the Automation1_GetLastError() and Automation1_GetLastErrorMessage() functions for more information. You can find information about these functions in the Errors and Error Handling section of C API Guidelines.