Core Instructions ================= Instruction is an abstract interface for all executable instructions. It serves as the base class for various types of instructions. Instructions can be of the following categories: * :ref:`compound` (multiple children) * :ref:`decorator` (one child) * :ref:`action` (no child instructions) There are no restrictions beside the number of children on where an instruction can be used. e.g. a compound instruction can be inside another compound instruction. Next we present the different types of available instructions and some basic examples of how to use them. The examples will contain mainly the body of a procedure in XML and an explanation of how it behaves. .. _async_instr_section: Asynchronous Instructions ------------------------- Asynchronous instructions are instructions that can return a ``RUNNING`` status, indicating that they are still in progress and have not yet completed their execution. Reactive sequences and fallbacks depend heavily on this concept, as they will reset all other child instructions when one of them returns ``RUNNING`` (see :ref:`ReactiveSequence ` and :ref:`Reactive Fallback `). Conditions, on the other hand, are required to be synchronous, i.e. they immediately return ``SUCCESS``, ``FAILURE`` or ``NOT_FINISHED``, since they should not reset a running asynchronous action that is a sibling of the condition. In the following sections, we will explicitly mention when an instruction is asynchronous. .. note:: If a compound or decorator instruction is not explicitly asynchronous, they can still return a ``RUNNING`` status. This can happen when they forward this status from a child instruction. .. _compound: Compound Instructions --------------------- Compound instructions are instructions that have multiple child instructions, and they control the flow of execution among their children based on certain conditions or criteria. Choice ^^^^^^ The choice instruction will execute instructions based on their index. That index is passed from a workspace variable that can be a scalar (single index) or an array (list of indices). An index can be repeated inside the array, making the correspondent instruction execution be repeated as many times as it appears in the array. The execution status returned by the choice instruction follows the same logic as for `Sequence`: a single failure immediately leads to failure and success means all selected child instructions returned success. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - varName - StringType - yes - name of the workspace variable to fetch the index (or array) from **Example** The example below will execute first the second instruction, with index one, then the first and finally, the third child instruction. These all succeed, so the `Choice` will succeed. The last child instruction (inverted wait) will never execute. .. code-block:: xml Fallback ^^^^^^^^ The fallback instruction executes its child instructions one by one in the order they are defined until: * A child instruction returns `SUCCESS`: `Fallback` also returns `SUCCESS`; * All child instructions returned `FAILURE`: `Fallback` returns `FAILURE`. A fallback can be interpreted as aggregating a number of alternatives to reach a specific goal: as soon as one of these alternatives (child instruction) succeeds, the fallback succeeds. `Fallback` has no specific attributes. .. _fall_exp: **Example** In the example, the first child will fail (inverted success), so the fallback will try the second child, which succeeds. This will make the fallback succeed and the third child is never executed. .. code-block:: xml ParallelSequence ^^^^^^^^^^^^^^^^ The parallel sequence instruction executes all its child instructions concurrently. The execution status of the parallel sequence is determined by its attributes (attribute types are denoted by their corresponding `AnyType` from `sup-dto`): .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - successThreshold - UnsignedInteger32Type - no - number of children to succeed for the parallel sequence to succeed * - failureThreshold - UnsignedInteger32Type - no - number of children to fail for the parallel sequence to fail For a parallel sequence with `N` children, the defaults of the above thresholds are `N` and `1` respectively. The sum of both thresholds will always be made to not exceed `N + 1` as that would lead to an undetermined status of the parallel sequence. If needed, that means that the real failure threshold could be made smaller than is indicated in the attribute if the success threshold was overriden. Equivalently, the success threshold can become smaller if only the failure threshold was overriden. .. note:: As soon as an exit condition is reached, i.e. one of the thresholds was reached, the parallel sequence will halt all remaining child instructions. .. _par_exp: **Example** The parallel sequence will execute all its children concurrently. The first two child instructions will return `SUCCESS` after one and two seconds respectively. At this point, the threshold for success is reached and the parallel sequence halts the third child instruction before returning `SUCCESS` itself. .. code-block:: xml .. _choice_exp: .. _react_fb_section: ReactiveFallback ^^^^^^^^^^^^^^^^ The reactive fallback instruction executes its child instructions one by one in the order they are defined until: * A child instruction returns `SUCCESS`: `reactive fallback` also returns `SUCCESS`; * A child instruction returns `RUNNING`: all other child instructions are reset and the reactive fallback returns `RUNNING`; on the next execution cycle, this will lead to the re-execution of the child instructions before the `RUNNING` one. * All child instructions return `FAILURE`: `reactive fallback` returns `FAILURE`. A reactive fallback most often consists of a single synchronous child node that represents a postcondition and multiple alternative child nodes that try to achieve this postcondition. The reactive fallback interrupts any asynchronous child as soon as the postcondition is met or one of the previous child nodes takes priority by returning a `RUNNING` status. They are often combined with `reactive sequence` instructions as follows: .. code-block:: text ReactiveFallback ├── ├── ReactiveSequence │ ├── │ └── ├── ReactiveSequence │ ├── │ └── └── ... `ReactiveFallback` has no specific attributes. .. note:: When all child instructions of the `reactive fallback` are synchronous, i.e. they never return `RUNNING`, it will behave as a normal `fallback`. .. _react_fb_exp: **Example** In the example, two branches are executed in parallel: * The first branch contains the reactive fallback which will execute a reactive sequence if the variable `break` is one. If not, it will run the asynchronous wait instruction. Since the condition will be checked again at each tick, as soon as the `break` variable becomes one, the long wait instruction (LongTask) is interrupted and a shorter one (ShortTask) is executed. * The second branch will wait for one second and then set the variable `break` to one. This will interrupt the long task in the other branch. .. code-block:: xml .. _react_seq_section: ReactiveSequence ^^^^^^^^^^^^^^^^ The reactive sequence instruction executes its child instructions one by one in the order they are defined until: * A child instruction returns `FAILURE`: `reactive sequence` also returns `FAILURE`; * A child instruction returns `RUNNING`: all other child instructions are reset and the reactive sequence returns `RUNNING`; on the next execution cycle, this will lead to the re-execution of the child instructions before the `RUNNING` one. * All child instructions return `SUCCESS`: `reactive sequence` returns `SUCCESS`. A reactive sequence most often consists of synchronous child nodes that represent preconditions and a single asynchronous child node in the end that only should be executed if all preconditions are met. The reactive sequence interrupts the asynchronous child as soon as one of the preconditions is no longer met. `ReactiveSequence` has no specific attributes. .. note:: When all child instructions of the `reactive sequence` are synchronous, i.e. they never return `RUNNING`, it will behave as a normal `sequence`. .. _react_seq_exp: **Example** In the example, two branches are executed in parallel: * The first branch contains the reactive sequence which will execute the (asynchronous) wait instruction as long as the variable `break` is zero. From the moment this variable is no longer zero, the wait instruction will be interrupted and the reactive sequence will return `FAILURE`. * The second branch will wait for one second and then set the variable `break` to one. This will interrupt the reactive sequence in the other branch. .. code-block:: xml Sequence ^^^^^^^^ The sequence instruction executes its child instructions one by one in the order they are defined until: * A child instruction returns `FAILURE`: `sequence` also returns `FAILURE`; * All child instructions returned `SUCCESS`: `sequence` returns `SUCCESS`. A sequence represents a number of steps that all have to succeed for a specific goal to be reached. `Sequence` has no specific attributes. .. _seq_exp: **Example** In the example, the first child will succeed, so the sequence will try the second child, which also succeeds. When the third child returns failure (inverted success), the sequence will stop and return failure. .. code-block:: xml UserChoice ^^^^^^^^^^ This **asynchronous** instruction delegates to the UserInterface a selection to be made from one of its child instructions. It will then execute that child and directly return its status. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - description - StringType - no - text description that will be passed to the UserInterface to guide selection .. note:: If the UserInterface returns an invalid index, i.e. out of bounds for the number of children, the instruction immediately returns `FAILURE`. .. _uchoice_exp: **Example** In this example, the user is asked to select one of the `Wait` instructions with different timeouts. On valid selection, that instruction will be executed and its status (success) will be returned from the `Choice` instruction. .. code-block:: xml .. _decorator: Decorator Instructions ---------------------- Decorator instructions modify or add functionality to a single child instruction, allowing for the addition of behavior to an existing instruction without modifying its core implementation. Async ^^^^^ Decorator that makes the execution of the child instruction asynchronous. This means it will return `RUNNING` until the child instruction has finished executing a single step, at which point it will return the status of the child instruction (`SUCCESS`, `FAILURE` or `NOT_FINISHED`). This decorator is useful when you want to use a synchronous instruction in an asynchronous context, such as a `ReactiveSequence` or `ReactiveFallback`. `Async` has no specific attributes. **Example** In the example, two branches are executed in parallel: * The first branch contains a reactive fallback which will wait asynchronously for 10 seconds or until the variable `break` is one. As soon as the `break` variable becomes one, the wait instruction is interrupted. * The second branch will wait for one second and then set the variable `break` to one. This will interrupt the long wait instruction in the other branch. .. code-block:: xml For ^^^ This instruction applies a child instruction to the elements of an array. Executes the child instruction on the elements of an array, until either: the child fails (FAILURE) or the child instruction is applied to all elements of the provided array (SUCCESS). Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - elementVar - StringType - yes - Element variable to contain the elements of the cycled array * - arrayVar - StringType - yes - Array to cycle .. _for_exp: **Example** This example will apply the Increment instruction to all elements of the array "arr". Note that the array elements will NOT be changed, as only a copy of those elements is inremented. .. code-block:: xml ForceSuccess ^^^^^^^^^^^^ This instruction wraps a child instruction and always return SUCCESS when the child has finished execution. `ForceSuccess` has no specific attributes. **Example** .. code-block:: xml Include ^^^^^^^ Decorator that includes an instruction tree by reference. The reference can point to an instruction tree in the same definition file or to one defined in a separate file (`file` attribute). Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - path - StringType - yes - Name of instruction to include * - file - StringType - no - File name from where to include the new instruction **Example** This example will include an instruction named "Counts" in sequence named "DontWait". .. code-block:: xml IncludeProcedure ^^^^^^^^^^^^^^^^ Decorator instruction that includes an external procedure (workspace and instruction tree). Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - file - StringType - yes - File name where to get the instruction to include * - path - StringType - no - Instruction name where to include the new instruction **Example** This example will include the procedure in file "test_procedure_1.xml" into the procedure where IncludeProcedure instruction is called. test_procedure_1.xml file: .. code-block:: xml Main procedure: .. code-block:: xml Inverter ^^^^^^^^ Instruction that inverts the execution status of its child, interchanging SUCCESS and FAILURE. `Inverter` has no specific attributes. * An example for this instruction is already present in :ref:`Fallback example `. Listen ^^^^^^ **Asynchronous** instruction that executes its child instruction each time specific variables are updated. By default, it will only report a finished status (success or failure) when the child instruction fails. If the user wants to listen to a set of variables in a blocking way, a `blocking` attribute can be set to `true`. Although this would be less CPU consuming, it implies that the instruction is no longer asynchronous, which has implications if it is used as a child of a reactive sequence or fallback. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - varNames - StringType - yes - Name of the variable to listen to * - forceSuccess - BooleanType - no - Always handle child as successful if active (only halt will exit the loop) * - blocking - BooleanType - no - Use a blocking implementation, which is less CPU consuming .. _listen_exp: **Example** This example will "Listen" on the variable "monitor" and check if it is equal to variable "update" everytime "monitor" is updated. .. code-block:: xml Repeat ^^^^^^ Instruction that repeats its child a fixed number of times while successful. Repeatedly executes the child instruction, until either: the child fails (FAILURE) or maximum number of repetitions is reached (SUCCESS). Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - maxCount - Signedinteger32type - no - Maximum number of repetitions .. _repeat_exp: **Example** .. code-block:: xml .. _action: Action Instructions ------------------- An action instruction represents a discrete operation or step within a larger sequence of instructions. Actions are fundamental building blocks that perform specific tasks or operations to achieve a particular goal. Action instructions are typically used within compound or decorator instructions. AddElement ^^^^^^^^^^ Instruction to add a new array element to a workspace variable using the information provided by a different variable. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - inputVar - StringType - yes - Name of the input variable or field thereof containing the information to be added as a new element * - outputVar - StringType - yes - Name of the output variable or field thereof that will receive a new element **Example** This example showcases how the AddElement instruction can be used to add variable var1 "a" to the workspace array variable "var2". .. code-block:: xml AddMember ^^^^^^^^^ Instruction to add a new member to a workspace variable using the information provided by a different variable. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - inputVar - StringType - yes - Name of the input variable or field thereof containing the information to be added to the new member * - varName - StringType - yes - Name of the new member * - outputVar - StringType - yes - Name of the output variable or field thereof that will hold the new member **Example** This example showcases how the AddMember instruction can be used to add member "a" to workspace variable "var2" with the information provided by "var1". The `Equals` instruction can can be used to validate the `AddMember` instruction, since it will check for variable existence and equality. .. code-block:: xml Condition ^^^^^^^^^ Instruction that checks a boolean workspace variable. Returns SUCCESS if the variable is true and FAILURE otherwise. If the variable is not a boolean, it will try to convert it to a boolean first, using the usual arithmetic conversions (e.g. 0 is false). If it cannot be converted to a boolean, the instruction reports FAILURE. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - varName - StringType - yes - Variable name to check .. _condition_exp: **Example** .. code-block:: xml CopyFromProcedure ^^^^^^^^^^^^^^^^^ Instruction that copies a variable from the workspace of an external procedure into the current workspace. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - file - StringType - yes - Filename for the included procedure * - inputVar - StringType - yes - Name of the input variable in the included procedure * - outputVar - StringType - yes - Name of the output variable in the current procedure CopyToProcedure ^^^^^^^^^^^^^^^ Instruction that copies a variable from the current workspace into a workspace of an external procedure. When including (parts of) that external procedure later, it will have access to the copied value. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - file - StringType - yes - Filename for the included procedure * - inputVar - StringType - yes - Name of the input variable in the current procedure * - outputVar - StringType - yes - Name of the output variable in the included procedure Copy ^^^^ Instruction that copies the value of an input variable to an output variable Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - inputVar - StringType - yes - Name of the input variable * - outputVar - StringType - yes - Name of the output variable * An example for this instruction is already present in :ref:`Reset example `. Decrement ^^^^^^^^^ Instruction to decrement a numeric variable by 1. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - varName - StringType - yes - Name of the variable to decrement * An example for this instruction is already present in :ref:`Repeat example `. Equals ^^^^^^ Instruction to check the equality of two variables. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - leftVar - StringType - yes - Name of the left hand side variable to compare * - rightVar - StringType - yes - Name of the right hand side variable to compare * An example for this instruction is already present in :ref:`Listen example `. Fail ^^^^ Instruction node that returns FAILURE after a given timeout. This instruction is **asynchronous** by default, but can be made synchronous by setting its `blocking` attribute to `true`. In this case, the instruction will block until the timeout is reached or it is halted. The `timeout` attribute is optional. When this attribute is not present, the instruction returns FAILURE immediately. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - timeout - Float64Type - no - Maximum time to wait * - blocking - BooleanType - no - Make the instruction blocking, i.e. synchronous GreaterThan ^^^^^^^^^^^ Instruction to check if a variable is greater than other. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - leftVar - StringType - yes - Name of the left hand side variable to compare * - rightVar - StringType - yes - Name of the right hand side variable to compare * The Greater Than usage is similar to that of the `Equals` that can be seen in :ref:`Listen example `. GreaterThanOrEqual ^^^^^^^^^^^^^^^^^^ Instruction to check if a variable is greater or equal to other. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - leftVar - StringType - yes - Name of the left hand side variable to compare * - rightVar - StringType - yes - Name of the right hand side variable to compare * The Greater Than usage is similar to that of the `Equals` that can be seen in :ref:`Listen example `. Increment ^^^^^^^^^ Instruction to increment a numeric variable by 1. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - varName - StringType - yes - Name of the variable to increment * The Increment usage is equal to that of the Decrement that can be seen in :ref:`Sequence example `. Input ^^^^^ **Asynchronous** instruction that writes a user defined value (from UserInterface) into a workspace variable. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - outputVar - StringType - yes - Name of the variable where to write the user input value * - description - StringType - no - Description of the requested variable .. _input_exp: **Example** .. code-block:: xml After the setup, the UserInterface can provide the value to populate the local variable .. code-block:: c++ sup::dto::AnyValue value(1234u); ui.SetValue(value); LessThan ^^^^^^^^ Instruction to check if a variable is smaller than other. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - leftVar - StringType - yes - Name of the left hand side variable to compare * - rightVar - StringType - yes - Name of the right hand side variable to compare * The Greater Than usage is similar to that of the `Equals` that can be seen in :ref:`Listen example `. LessThanOrEqual ^^^^^^^^^^^^^^^ Instruction to check if a variable is smaller or equal to other. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - leftVar - StringType - yes - Name of the left hand side variable to compare * - rightVar - StringType - yes - Name of the right hand side variable to compare * The Greater Than usage is similar to that of the `Equals` that can be seen in :ref:`Listen example `. Log ^^^ Instruction that sends a message and/or variable value to the oac-tree log, which is handled by the specific UserInterface used. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - message - StringType - no - Text message to log * - inputVar - StringType - no - Name of variable to log * - severity - StringType - no - Severity of the log message Note that either the `message` or `inputVar` attribute (or both) need to be defined. The `severity` attribute needs to be one of the following (in decreasing order of severity): emergency, alert, critical, error, warning, notice, info, debug, trace. In the absence of this attribute, the default severity is `info`. Message ^^^^^^^ Instruction forwarding a text message to the UserInterface. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - text - StringType - yes - Message to be passed to the UserInterface Output ^^^^^^ Instruction node that outputs a workspace value to the user interface. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - fromVar - StringType - yes - Name of the variable to be displayed in the UserInterface * - description - StringType - no - Description of the displayed variable **Example** .. code-block:: xml ResetVariable ^^^^^^^^^^^^^ Instruction to reset a variable to its initial state. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - varName - StringType - yes - Name of the variable to reset .. _reset_exp: **Example** .. code-block:: xml UserConfirmation ^^^^^^^^^^^^^^^^ Simple **asynchronous** instruction representing a user defined confirmation (success) or rejection (failure). Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - description - StringType - yes - Description of the needed user confirmation * - okText - StringType - no - text to be displayed in case of positive user confirmation * - cancelText - StringType - no - text to be displayed in case of negative user confirmation VarExists ^^^^^^^^^ Instruction that checks the existence of a variable in the current workspace. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - varName - StringType - yes - Name of variable to check Wait ^^^^ Instruction node that returns SUCCESS after a given timeout. This instruction is **asynchronous** by default, but can be made synchronous by setting its `blocking` attribute to `true`. In this case, the instruction will block until the timeout is reached or it is halted. The `timeout` attribute is optional. When this attribute is not present, the instruction returns SUCCESS immediately. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - timeout - Float64Type - no - Maximum time to wait * - blocking - BooleanType - no - Make the instruction blocking, i.e. synchronous * An example for this instruction is already present in :ref:`ParallelSequence example `. WaitForVariable ^^^^^^^^^^^^^^^ **Asynchronous** instruction node that waits `timeout` seconds for a variable to be readable and non-empty. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - timeout - Float64Type - yes - Maximum time to wait * - varName - StringType - yes - name of the variable to be read * - equalsVar - StringType - no - variable to compare. The instruction will wait until the variables are equal or the timout s reached * - blocking - BooleanType - no - Use a blocking implementation, which is less CPU consuming * An example for this instruction is already present in :ref:`Repeat example `. WaitForVariables ^^^^^^^^^^^^^^^^ **Asynchronous** instruction node that waits `timeout` seconds for all workspace variables of a given type to be available. Attributes: .. list-table:: :widths: 25 25 15 50 :header-rows: 1 * - Attribute name - Attribute type - Mandatory - Description * - timeout - Float64Type - yes - Maximum time to wait * - varType - StringType - yes - typename of the variables to check * - blocking - BooleanType - no - Use a blocking implementation, which is less CPU consuming