The third example implements the LTL operator "Until". This operator is used to imposed that, starting from the current time step, some properties have to hold until other are verified. In the particular case of the waiter robot task, this property can be used to verify that the execution of the plan is correct. Here, the property to be verified is that the arm of the robot remains free until the robot reaches the kitchen, where the drink is located, and grabs it.
Figures show the DFA and the linear trace associated to the LTL property, and the plan generated by the automated planner. It is easy to verify that the DFA reaches the goal state only once the robot has executed the action of grabbing the drink inside the kitchen, and stays there for the rest of the plan execution.
(define(domain robotdomain) (:requirements :equality :adl) (:predicates (happy ?client) (robot ?robot) (free_arm ?robot) (room ?room) (client ?client) (coke ?coke) (dfa ?dfa) (instate ?state) (in ?object ?room) (update ?dfa) (edge ?s-state ?e-state) (near ?from-room ?to-room) (state ?state) (grab ?coke) ) (:action go_to :parameters (?robot ?from-room ?to-room ?dfa) :precondition (and (robot ?robot) (room ?from-room) (room ?to-room) (near ?from-room ?to-room) (in ?robot ?from-room) (dfa ?dfa) (update ?dfa) ) :effect (and (not (in ?robot ?from-room)) (in ?robot ?to-room) (not(update ?dfa)) ) ) (:action grab :parameters(?robot ?coke ?room ?dfa) :precondition (and (robot ?robot) (coke ?coke) (free_arm ?robot) (dfa ?dfa) (update ?dfa) (in ?robot ?room) (in ?coke ?room) ) :effect (and (not (free_arm ?robot)) (not (update ?dfa)) (not (in ?coke ?room)) (grab ?coke) ) ) (:action give_to :parameters (?robot ?client ?coke ?where-room ?dfa) :precondition (and (robot ?robot) (coke ?coke) (in ?robot ?where-room) (in ?client ?where-room) (not (free_arm ?robot)) (dfa ?dfa) (update ?dfa) ) :effect (and (free_arm ?robot) (happy ?client) (not(update ?dfa)) ) ) (:action move13 :parameters(?robot ?e-state ?dfa) :precondition (and (robot ?robot) (state ?e-state) (instate state_1) (edge state_1 ?e-state) (dfa ?dfa) (not(update ?dfa)) (not(free_arm ?robot)) (in ?robot kitchen) (grab coke_1) ) :effect (and (instate ?e-state) (not(instate state_1)) (update ?dfa) ) ) (:action move131 :parameters(?robot ?e-state ?dfa) :precondition (and (robot ?robot) (state ?e-state) (instate state_1) (edge state_1 ?e-state) (free_arm ?robot) (in ?robot kitchen) (grab coke_1) (dfa ?dfa) (not(update ?dfa)) (in ?robot kitchen) ) :effect (and (instate ?e-state) (not(instate state_1)) (update ?dfa) ) ) (:action move111 :parameters(?robot ?e-state ?dfa) :precondition (and (robot ?robot) (not(in ?robot kitchen)) (free_arm ?robot) (instate state_1) (= ?e-state state_1) (edge state_1 ?e-state) (dfa ?dfa) (not(update ?dfa)) ) :effect (and (instate ?e-state) (not(instate state_1)) (update ?dfa) ) ) (:action move11 :parameters(?robot ?e-state ?dfa) :precondition (and (robot ?robot) (in ?robot kitchen) (free_arm ?robot) (instate state_1) (= ?e-state state_1) (edge state_1 ?e-state) (not(grab coke_1)) (dfa ?dfa) (not(update ?dfa)) ) :effect (and (instate ?e-state) (not(instate state_1)) (update ?dfa) ) ) (:action move22 :parameters(?robot ?e-state ?dfa) :precondition (and (robot ?robot) (state ?e-state) (instate state_2) (edge state_2 ?e-state) (dfa ?dfa) (not(update ?dfa)) ) :effect (and (instate ?e-state) (not(instate state_2)) (update ?dfa) ) ) (:action move12 :parameters(?robot ?s-state ?e-state ?dfa) :precondition (and (robot ?robot) (state ?s-state) (state ?e-state) (= ?e-state state_2) (instate ?s-state) (edge ?s-state ?e-state) (not(free_arm ?robot)) (not(in ?robot kitchen)) (dfa ?dfa) (not(update ?dfa)) ) :effect (and (instate ?e-state) (not(instate ?s-state)) (update ?dfa) ) ) (:action move12 :parameters(?robot ?s-state ?e-state ?dfa) :precondition (and (robot ?robot) (state ?s-state) (state ?e-state) (= ?e-state state_2) (instate ?s-state) (edge ?s-state ?e-state) (not(free_arm ?robot)) (in ?robot kitchen) (not (grab coke_1)) (dfa ?dfa) (not(update ?dfa)) ) :effect (and (instate ?e-state) (not(instate ?s-state)) (update ?dfa) ) ) (:action move33 :parameters(?robot ?e-state ?dfa) :precondition (and (robot ?robot) (instate state_3) (edge state_3 ?e-state) (dfa ?dfa) (not(update ?dfa)) ) :effect (and (instate ?e-state) (not(instate state_3)) (update ?dfa) ) ))(define (problem robotproblem) (:domain robotdomain) (:objects livingroom kitchen bedroom bathroom corridor hall robot_1 state_1 state_2 state_3 dfa_1 coke_1 client_1 ) (:init (robot robot_1) (client client_1) (room livingroom) (room kitchen) (room bedroom) (room corridor) (room hall) (coke coke_1) (room bathroom) (free_arm robot_1) (in client_1 livingroom) (in robot_1 livingroom) (in coke_1 kitchen) (near livingroom corridor) (near corridor livingroom) (near livingroom bedroom) (near bedroom livingroom) (near bathroom kitchen) (near kitchen bathroom) (near bedroom bathroom) (near bathroom bedroom) (near corridor hall) (near hall corridor) (near hall kitchen) (near kitchen hall) (instate state_1) (dfa dfa_1) (update dfa_1) (state state_1) (state state_2) (state state_3) (edge state_1 state_2) (edge state_1 state_3) (edge state_2 state_2) (edge state_3 state_3) (edge state_1 state_1) ) (:goal (and (happy client_1) (instate state_3) ) ))