Overview of the TeleoR language

A TeleoR program comprises sequences of guard >action rules clustered into parameterised procedures of the form:
tel p(t$\sb{1}$,..,t$\sb{k}$) % declaration of the argument types of p
p(X$\sb{1}$,..,X$\sb{k}$){
G$\sb{1}$ ~> A$\sb{1}$
.
.
G$\sb{n}$ ~> A$\sb{n}$
}

The t$_i$ are the types of the procedure's $k$ arguments named by the $k$ different parameter variables X$\sb{1}$,..,X$\sb{k}$. Each t$_i$ may be a primitive QuLog type such as num, list, or a QuLog program defined type, or a QuLog type expression for a relation, function or TeleoR procedure. The typing of TeleoR procedures and the allowing of code arguments is a major difference between TeleoR and T-R.

The parameters X$\sb{1}$,..,X$\sb{k}$ are global variables of the action rule sequence. They must be given fully instantiated values of the required type (or sub-type) when the procedure is called. Other variables appearing in a rule are local variables of that rule. Unless explicitly quantified, they are implicitly universally quantified over the rule in which they appear.

Each guard G$_i$ is a QuLog query to the agent's BS. This is an & conjunction of conditions, negated conditions, and universally quantified condition implications. Disjunction is not allowed in a guard, just as it is not allowed in a QuLog rule body. (A disjunctive condition can always be captured by having a call to an auxiliary QuLog relation with two or more defining rules.) The action is one of:

  • a tuple of actions for robotic resources, to be executed in parallel,
  • a call to a TeleoR procedure, including a recursive call on the procedure p,
  • a type correct call Exp$\sb{j}$(....) where Exp$\sb{j}$ is an expression with value a TeleoR procedure named and defined in the program,
  • a timed sequence of $k>1$ of the above actions of the form;
    [RA$\sb{1}$:T$\sb{1}$, ...,RA$\sb{k}$:T$\sb{k}$]
    where the time limit T$\sb{k}$ on the last action is optional
together with a communication action.

Below are two example TeleoR procedures for a search and grasp task for a mobile robot.

def thing ::= bottle | glass
def robotic_action ::=
move(num) | turn(dir) | grasp() | release()
def dir ::= left | centre | right

percept see(thing, num, dir), holding(thing)

tel get_hold_of(thing)
get_hold_of(Th) {
holding(Th) ~> ()
not exists AnyTh holding(AnyTh) & see(Th, 0, centre) ~>
grasp()
not holding(_) ~> get_to(Th)
% The guard is equivalent to not exists X holding(X)
true ~> release()
}

tel get_to(thing)
get_to(Th) {
see(Th, 0, centre) ~> ()
see(Th, 0, Dir) ~> turn(Dir)
see(Th, centre) ~> move(6)
see(Th, Dir) ~> move(4), turn(Dir)
% The concurrent move and turn actions will cause the robot
% to swerve towards Th, hopefully bringing it into centre view

true ~> turn(left)
}

The two uses of Dir in the second and fourth rules of the get_to procedure are both implicitly universally quantified over their respective rules. The use of AnyTh in the second rule of get_hold_of is inside an existential quantification. Local variables in different rules with the same name are different variables. Any local variable appearing in the rule action must also appear in the rule guard, and be such that it will be have a fully instantiated value by the end of the guard evaluation. These conditions are checked at compile time.

An agent task is started by a single call p(v$\sb{1}$,..,v$\sb{k}$) to some program procedure p, e.g. get_hold_of(glass) or get_to(bottle). The fully instantiated arguments given in the call typically partially or completely instantiate each guard of p's rules, e.g. the first rule of get_hold_of procedure for the call get_hold_of(glass) is fully instantiated, and all the rules of get_to for call get_to(bottle) become fully instantiated. Suppose the guard of the first rule becomes G$'_1$. This is the task goal. That is, by sending a sequence a$\sb{1}$,..,a$\sb{n}$ of n actions to the robotic resources, eventually some instance G$''_1$ of G$'_1$ should become inferable from the agent's updated BS. From the time that the task was started, the BS will have been updated as a result of a percepts update or a received message, at least as many times as different actions have been sent to the robot.

A task call evaluation involves finding the first partially instantiated guard G$'\sb{j}$ which has an instance G$''\sb{j}$ inferable from the current BS. The j'th rule of the call is then fired. The corresponding ground instance1 A$''\sb{j}$ of the rule's action is either a robotic device action, or it is a call to a TeleoR procedure. If it is a procedure call, again the first rule of this call with an instance of its guard inferable from the current BS is found, and that rule fired. Eventually a rule with a tuple of robotic actions will be fired and this tuple will be dispatched to the robotic devices interface, or to the simulator. As mentioned in the final section, it is up to the robot side to deal with these tuples by, for example, stopping actions that are no longer active and modifying actions whose arguments have changed.

The robotic action of the first rule of each TeleoR start procedure is generally the empty action (). When () is received by the robotic device interface it will cause the last dispatched action a$\sb{n}$ to be terminated. If the first rule does not have the empty device action, it should have an action that will normally preserve the task goal. After the first goal achieved rule has been fired, an exogenous action may 'interfere' and after a percept update of the BS the guard of the first rule may no longer be inferable. In that case, the TeleoR task evaluator will start testing the other guards of the procedure, starting with the second guard. In effect, the call p(v$\sb{1}$,..,v$\sb{k}$) is re-evaluated to try to re-achieve the task goal.

Actually, a TeleoR task programmed agent responds to each update of its BS by effectively re-evaluating the task call p(v$\sb{1}$,..,v$\sb{k}$)2.

The environment in which the robot is situated may contain other separately controlled robotic devices, as well as humans, all of which may have their own goals. Their actions may sometimes hinder agent RA or help it. No matter what, the TeleoR control program will determine an appropriate response. It will skip actions if helped and redo actions if hindered. Procedure p, and all the other TeleoR procedures that may be called as part of the evaluation of call C, are a universal conditional action plan for achieving any goal which is a call instantiation of the guard of p's first rule. TeleoR programs recover from setbacks and take advantage of good fortune. This makes TeleoR programs rather different from traditional programs.

TeleoR agents typically reside on the robotic device hardware, especially when this is a mobile robot, but one TeleoR agent could be controlling several robotic devices. When discussing TeleoR agents and programs we will use the term robot side to mean the part of the hardware for collecting perceptual information (percepts) and for realising actions sent from the agent: turning on/off motors, actuators etc.

TeleoR programs typically contain QuLog declarations of types and definitions of relations, functions and actions and so we assume the reader has read the QuLog user guide.

The system comes with its own interpreter that extends the QuLog interpreter with extra functionality that is required to compile and run TeleoR programs. Unless the TeleoR control agent directly communicates with the external robotic devices and sensors using something like ROS [6], and has no need to communicate with other agents using the Pedro communication server, we start the TeleoR interpreter giving the agent process a name which will be registered with Pedro.

teleor -AAgentName
Teleor Version 1.0

| ?~>
The | ?> is the TeleoR command prompt.

The agent process can now communicate with other agents and processes via Pedro, including the robot side process that handles action commands from the agent and sends it sensor readings as percept facts. The actions and the percept facts communicated between the agent and robot side can be tailored to the tasks that the agent is programmed to perform. So programming the robot side from scratch, or modifying and previously programmed robot side, is usually needed in addition to the TeleoR+QuLog programming of the agent. We assume the reader has the competence to do this robot side programming.

The TeleoR language is introduced via a series of example programs. All the programs discussed here can be found in sub-folders of the examples folder.