1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    2%
    3% FILE: Env/env_sim.pl
    4%
    5%  Author    : Sebastian Sardina
    6%  Time-stamp: <03/12/19 10:51:50 ssardina>
    7%  email     : ssardina@cs.toronto.edu
    8%  WWW       : www.cs.toronto.edu/~ssardina
    9%  TESTED    : SWI Prolog 5.0.10 http://www.swi-prolog.org
   10%	       ECLiPSe 5.3 on RedHat Linux 6.2-7.2
   11%  TYPE CODE : system independent predicates
   12%
   13% This files provides a *simulted* environment interface with which
   14% it is possible to set exogenous events in an asynchronous ways using
   15% a TCL/TK application, type sensing outcome for actions
   16%
   17%   The interface to enter exogenous events from the keyboard is
   18%     achieved with a simple TCL/TK program where exogenous action can
   19%     be typed at any time. 
   20%
   21%
   22% This environment is self-contained (automatically it loads the required
   23%  libraries). It should be called as follows:
   24%
   25%   eclipse host=<HOST> port=<PORT> -b env_sim.pl -e start
   26%   pl host=<HOST> port=<PORT> -b env_sim.pl -e start
   27%
   28% where HOST/PORT is the address of the environment manager socket.
   29%
   30% Written for ECLiPSe Prolog (http://www.icparc.ic.ac.uk/eclipse/)
   31% and SWI Prolog (http://www.swi-prolog.org) running under Linux 6.2-8.0
   32%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   33%
   34%                             March 22, 2003
   35%
   36% This software was developed by the Cognitive Robotics Group under the
   37% direction of Hector Levesque and Ray Reiter.
   38%
   39%        Do not distribute without permission.
   40%        Include this notice in any copy made.
   41%
   42%
   43%         Copyright (c) 2000 by The University of Toronto,
   44%                        Toronto, Ontario, Canada.
   45%
   46%                          All Rights Reserved
   47%
   48% Permission to use, copy, and modify, this software and its
   49% documentation for non-commercial research purpose is hereby granted
   50% without fee, provided that the above copyright notice appears in all
   51% copies and that both the copyright notice and this permission notice
   52% appear in supporting documentation, and that the name of The University
   53% of Toronto not be used in advertising or publicity pertaining to
   54% distribution of the software without specific, written prior
   55% permission.  The University of Toronto makes no representations about
   56% the suitability of this software for any purpose.  It is provided "as
   57% is" without express or implied warranty.
   58% 
   59% THE UNIVERSITY OF TORONTO DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
   60% SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
   61% FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TORONTO BE LIABLE FOR ANY
   62% SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
   63% RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
   64% CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
   65% CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   66% 
   67%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   68% 
   69% This file assumes that the following is defined in env_gen.pl:
   70%
   71% -- start/0     : initialization of the environment (called when loaded)
   72% -- finalize/0  : finalization of the environment (called when exiting)
   73% -- main_dir/1  : obtain the root IndiGolog directory
   74% -- report_exog_event(A, M): 
   75%                  report exogenous event A with message M to the
   76%                  environment manager
   77% -- All compatibility libraries depending on the architecture such us:
   78%    -- compat_swi/compat_ecl compatibility libraries providing:
   79%
   80% -- The following two dynamic predicates should be available:
   81%    -- listen_to(Type, Name, Channel) 
   82%            listen to Channel of Type (stream/socket) with Name
   83%    -- terminate/0
   84%            order the termination of the application
   85%
   86%
   87% -- The following should be implemented here:
   88%
   89%  -- name_dev/1              : mandatory *
   90%  -- initializeInterfaces(L) : mandatory *
   91%  -- finalizeInterfaces(L)   : mandatory *
   92%  -- execute/4               : mandatory *
   93%  -- handle_steam/1          : as needed
   94%  -- listen_to/3             : as needed
   95%
   96% FROM PROLOG DEPENDENT USER LIBRARY (SWI, ECLIPSE, LIBRARY):
   97%
   98% -- call_to_exec(+System, +Command, -Command2)
   99%      Command2 executes Command in plataform System
  100%
  101%
  102% Also, this device manager requires:
  103%
  104%    -- wish for running TCL/TK applications
  105%    -- exog.tcl TCL/TK script
  106%
  107%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  108:- include(env_gen).      % INCLUDE THE CORE OF THE DEVICE MANAGER
  109
  110%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  111% CONSTANTS TO BE USED
  112%
  113% name_dev/1 : state the name of the device manager (e.g., simulator, rcx)
  114%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  115
  116% Name of the environment: <SIMULATOR>
  117% Set name of the environment here.
  118% THIS CONSTANT IS MANDATORY, DO NOT DELETE!
  119name_dev(simulator). 
  120
  121% Set verbose debug level
  122:- set_debug_level(3).  123
  124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  125% A - INITIALIZATION AND FINALIZATION OF INTERFACES
  126%     initializeInterfaces/1 and finalizeInterfaces/1
  127%
  128% HERE YOU SHOULD INITIALIZE AND FINALIZE EACH OF THE INTERFACES TO BE USED
  129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  130initializeInterfaces(_) :- initializeExog(tcltk).
  131finalizeInterfaces(_)   :- finalizeExog(tcltk).
  132
  133
  134
  135%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  136% TCL/TK EXOGENOUS ACTIONS  GENERATOR - from keyboard via Tcl/Tk interface
  137%
  138% This part implements a keyboard interface to enter exogenous events
  139% in an asynchronous manner.
  140%
  141% If an exogenous event arrives via the keyboard, it is handled as soon
  142% as possible by calling handle_event/1
  143%
  144% -- initializeExog(virtual): 
  145%                    perform any initialization of other sources of
  146%                    exogenous actions that is required
  147% -- finalizeExog(virtual):
  148%                    things to do for other sources of exogenous actions
  149%                    at end of program
  150% -- checkOtherExog(virtual,-ExogList): 
  151%                    check whether a request has been entered via keyboard
  152%
  153%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  154
  155% initializeExog(tcltk): initialization for sources of exogenous actions from
  156%                        virtual interface
  157%
  158% An TCL/TK independent process is initiated to read exogenous events
  159%  the program exog.tcl writes each exogenous action entered to a special pipe.
  160% At that time, a sigio signal is assigned to such pipe so that whenever data
  161% arrives to the pipe an interrupt is triggered which can be cached
  162%  by the main cycle to handle the exog action entered.
  163tcltk_exog_file(File):- main_dir(Dir),
  164                        concat_atom([Dir,'Env/exog.tcl'], File).
  165
  166initializeExog(tcltk) :- 
  167        printKbInstructions,
  168	        % Run the command as a child and send its *output* to pipe "tcltk"
  169        tcltk_exog_file(File),
  170        concat_atom(['wish ', File], Command),
  171	call_to_exec(unix, Command, Command2),
  172        exec_group(Command2, [null, tcltk, null], P),
  173        sleep(2),    % Give time to TCL/TK program to appear
  174        assert(exog_proc(P)),     % Store child pid for later
  175        assert(listen_to(stream, tcltk, tcltk)).  % listen to tcltk
  176
  177% finalizeExog: Things to do for sources of exogenous actions from the
  178%               virtual interface
  179finalizeExog(tcltk) :- 
  180	listen_to(stream, tcltk, tcltk), !,	% tcltk is still open
  181        report_message(system(1), 'Closing Tcl/Tk interface.'), 
  182        retract(listen_to(stream, tcltk, tcltk)),	% de-register interface
  183        retract(exog_proc(P)), 
  184        (proc_kill(P) -> true ; true).
  185finalizeExog(tcltk).	% It was already down
  186
  187% printKbInstructions: Print instructions on how to enter keyboard input
  188printKbInstructions :-
  189    writeln('*********************************************************'), 
  190    writeln('* NOTE: This is the SIMULATOR environment'), 
  191    writeln('*   You can enter exogenous actions using the TCL/TK window.'), 
  192    writeln('*   Action execution will be printed here and sensing '), 
  193    writeln('*   outcome will be asked to the user'), 
  194    writeln('*   Actions that are not executed in any other device are'), 
  195    writeln('*   executed here.'), 
  196    writeln('*********************************************************'), nl.
  197
  198
  199%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  200% B - HANDLERS FOR EACH STREAM/SOCKET THAT IS BEING HEARD:  handle_stream/1
  201%
  202% HERE YOU SHOULD WRITE HOW TO HANDLE DATA COMMING FROM EACH OF THE
  203% INTERFACES/CHANNELS USED
  204%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  205
  206% Handle tcl/tk stream: called when there is data comming from the tcl/tk app
  207handle_stream(tcltk) :- 
  208        read(tcltk, A),
  209        (A=end_of_file ->
  210             true          % Tcl/Tk finished
  211        ;
  212             report_exog_event(A, ['Exogenous action *',A,'* received from TCL/TK'])
  213        ).
  214
  215
  216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  217% C - EXECUTION MODULE: execute/4
  218%
  219% This part implements the execution capabilities of the environment
  220%
  221% execute(Action, Type, N, Sensing) : execute Action of Type and return Sensing
  222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  223% Simulate the execution of Action. 
  224% SensingResult is the sensing outcome of Action
  225execute(Action, T, _, Sensing) :- 
  226	member(T, [sensing, simsensing]), !,
  227        report_message(action, ['Executing sensing action: *',Action,'*']),
  228        write('    ------------> Enter Sensing value, terminate with ".": '),
  229        read(Sensing), nl.
  230
  231execute(Action, _, _, ok) :- 
  232        report_message(action, ['Executing non-sensing action: *',Action,'*']).
  233
  234
  235
  236%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  237%%%%%%%%%%%%%%%%%% OTHER CODE %%%%%%%%%%%%%%%%%
  238%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  239:- type_prolog(ecl) -> 
  240	set_event_handler(170, my_system_error_handler/2) ; true.  241
  242my_system_error_handler(E, Goal) :-
  243        (
  244            errno_id(`Interrupted system call`),
  245%            errno_id(170, M), errno_id(M),  % M is "Unknown error 170" ??
  246            restartable_builtin(Goal)
  247        ->
  248            call(Goal)
  249        ;
  250            errno_id(M),
  251            report_message(error, M),
  252            read(_),
  253            error(default(E), Goal)
  254        ).
  255
  256% Builtins that can raise EINTR and can be restarted after that
  257restartable_builtin(accept(_,_,_)).
  258restartable_builtin(cd(_)).
  259restartable_builtin(close(_)).
  260restartable_builtin(connect(_,_)).
  261restartable_builtin(select_stream(_,_,_)).
  262restartable_builtin(stream_select(_,_,_)).
  263restartable_builtin(wait(_,_)).
  264
  265
  266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  267% Exogenous action window in SWI itself (instead of TCL/TK)
  268%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  269/*
  270:- use_module(library(pce)).
  271
  272fileviewer(Dir) :-
  273        new(F, frame('File Viewer')),
  274        send(F, append(new(B, browser))),
  275        send(new(D, dialog), below(B)),
  276        send(D, append(button(view,
  277                              message(@prolog, view,
  278                                      B?selection?key)))),
  279        send(D, append(button(quit,
  280                              message(F, destroy)))),
  281        send(B, members(directory(Dir)?files)),
  282        send(F, open).
  283
  284view(F) :-
  285        send(new(V, view(F)), open),
  286        send(V, load(F)).
  287
  288	
  289
  290%:- pce_autoload(file_item, library(file_item)).
  291 
  292
  293edit_file_dialog :-
  294        new(D, dialog('Exogenous Events')),
  295        send(D, append, new(E, text_item(exog, @default, 
  296						and(message(@prolog, reportTea, @arg1),
  297					    	    message(@receiver,clear))
  298					))),
  299        send(D, append, button(send, 
  300				and(message(@prolog, reportTea, E?selection),
  301				    message(E,clear))
  302			)),
  303        send(D, append, button(cancel, message(D, destroy))),
  304        send(D, append, button(halt,   message(@prolog, terminateTea))),
  305        send(D, open).	
  306
  307	
  308reportTea(E) :- report_message(action, ['Executing non-sensing action: *',E,'*']).
  309terminateTea :- report_message(action, terminate).
  310
  311
  312
  313	%	ask_name(+Prompt, +Label, -Name)
  314	%	Put a prompter on the screen and wait till the user has
  315	%	entered a name.  Pressing cancel makes this predicate fail.
  316	%	Prompt is a long string, giving explanation; Label is a short
  317	%	label displayed for the text entry field.
  318	
  319	
  320	:- pce_global(@name_prompter, make_name_prompter).
  321	
  322	make_name_prompter(P) :-
  323		new(P, dialog),
  324		send(P, kind, transient),
  325		send(P, append, label(prompt)),
  326		send(P, append,
  327		        new(TI, text_item(name, '',
  328				 message(P?ok_member, execute)))),
  329		send(P, append, button(ok, message(P, return, TI?selection))),
  330		send(P, append, button(cancel, message(P, return, @nil))).
  331	
  332	
  333	ask_name(Prompt, Label, Name) :-
  334		send(@name_prompter?prompt_member, selection, Prompt),
  335		send(@name_prompter?name_member, label, Label),
  336		send(@name_prompter?name_member, clear),
  337		get(@name_prompter, confirm_centered, RawName),
  338		send(@name_prompter, show, @off),
  339		RawName \== @nil,
  340		Name = RawName.
  341	
  342	ask_name :-
  343		ask_name('Street', name, Street),
  344		writeln(Street).
  345	
  346		
  347create_fill_pattern_dialog :-
  348	new(Dialog, dialog('Fill Patterns')),
  349	send(Dialog, append,
  350		 new(M, menu(fill_pattern, cycle,
  351						 message(@prolog, write_ln, @arg1)))),
  352		send_list(M, append,
  353			[ menu_item(white,  @default, opcion1)
  354			, menu_item(grey12, @default, opcion2)
  355			, menu_item(grey25, @default, opcion3)
  356			, menu_item(grey50, @default, opcion4)
  357			]),
  358	send(Dialog, open).
  359		
  360*/
  361
  362
  363
  364%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  365% EOF:  Env/env_sim.pl
  366%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%