Simple simulator application for faudes generators. More... #include "libfaudes.h" #include <signal.h> Go to the source code of this file.
Detailed DescriptionSimple simulator application for faudes generators. This tutorial demonstrates how to build a simulator application from the class faudes::ProposingExecutor. When compiled with the IO device plugin, the faudes::DeviceExecutor is used to run a hardware-in-the-loop simulation. ~/libfaudes/plugins/simulator/tutorial> ./simfaudes -?
simfaudes: usage:
simfaudes [-q][-v][-i][-bc] [-bt <nnn>][-bs <nnn>] [-l <logfile>] [-ls] [-le] [-lt] <simfile>
where
<simfile>: simulation configuration file or generator file
-q: less console output
-qq: absolutely no console output
-v: more console output
-vv: even more console output
-i: interactive mode
-bc: break on condition
-bt <nnn>: break on time <nnn>
-bs <nnn>: break on step <nnn>
-l <logfile>: log to <logfile>
-ls: log states
-le: log events
-lt: log time
-la: log all
-t <nnn>: fifo trace buffer length <nnn>
-d <devfile>: use io device configured from file
-dt <nnn>: tolerance in time synchronisation
-dr: executer reset on device request
You may test the simulator with the examples provided in the data directory: ~/libfaudes/plugins/simulator/tutorial>./simfaudes -bs 5 data/gausstest.sim
% simfaudes: ========================================= current state:
<DiscreteState> "idle" </DiscreteState>
% simfaudes: ========================================= current time:
<Time> 0 </Time>
% simfaudes: ========================================= proposed action:
<ProposedTime> 205 </ProposedTime>
<ProposedEvent> "alpha" </ProposedEvent>
% simfaudes: ========================================= execute event:
<ExecutedEvent> "alpha" </ExecutedEvent>
% simfaudes: ========================================= current state:
<DiscreteState> "busy" </DiscreteState>
% simfaudes: ========================================= current time:
<Time> 205 </Time>
% simfaudes: ========================================= found conditions satisfied:
<SatisfiedConditions> "BusyCond" </SatisfiedConditions>
% simfaudes: ========================================= proposed action:
<ProposedTime> 51 </ProposedTime>
% simfaudes: ========================================= current state:
<DiscreteState> "busy" </DiscreteState>
% simfaudes: ========================================= current time:
<Time> 256 </Time>
% simfaudes: ========================================= found conditions satisfied:
<SatisfiedConditions> "BusyCond" </SatisfiedConditions>
% simfaudes: ========================================= proposed action:
<ProposedTime> 39 </ProposedTime>
<ProposedEvent> "beta" </ProposedEvent>
% simfaudes: ========================================= execute event:
<ExecutedEvent> "beta" </ExecutedEvent>
% simfaudes: ========================================= current state:
<DiscreteState> "idle" </DiscreteState>
% simfaudes: ========================================= current time:
<Time> 295 </Time>
% simfaudes: ========================================= found conditions satisfied:
<SatisfiedConditions> "IdleCond" </SatisfiedConditions>
% simfaudes: ========================================= proposed action:
<ProposedTime> 191 </ProposedTime>
<ProposedEvent> "alpha" </ProposedEvent>
% simfaudes: ========================================= execute event:
<ExecutedEvent> "alpha" </ExecutedEvent>
% simfaudes: ========================================= current state:
<DiscreteState> "busy" </DiscreteState>
% simfaudes: ========================================= current time:
<Time> 486 </Time>
% simfaudes: ========================================= found conditions satisfied:
<SatisfiedConditions> "BusyCond" </SatisfiedConditions>
% simfaudes: ========================================= proposed action:
<ProposedTime> 51 </ProposedTime>
% simfaudes: ========================================= end simulation
The code is straight forward: after some command line parsing for behavioural configuration, it reads a proposing executor from file and loops to execute the proposed transitions. /** @file simfaudes.cpp Simple simulator application for faudes generators
This tutorial demonstrates how to build a simulator application from
the class faudes::ProposingExecutor. When compiled with the
IO device plugin, the faudes::DeviceExecutor is used to run a
hardware-in-the-loop simulation.
@code
~/libfaudes/plugins/simulator/tutorial> ./simfaudes -?
simfaudes: usage:
simfaudes [-q][-v][-i][-bc] [-bt <nnn>][-bs <nnn>] [-l <logfile>] [-ls] [-le] [-lt] <simfile>
where
<simfile>: simulation configuration file or generator file
-q: less console output
-qq: absolutely no console output
-v: more console output
-vv: even more console output
-i: interactive mode
-bc: break on condition
-bt <nnn>: break on time <nnn>
-bs <nnn>: break on step <nnn>
-l <logfile>: log to <logfile>
-ls: log states
-le: log events
-lt: log time
-la: log all
-t <nnn>: fifo trace buffer length <nnn>
-d <devfile>: use io device configured from file
-dt <nnn>: tolerance in time synchronisation
-dr: executer reset on device request
@endcode
You may test the simulator with the examples provided in the data
directory:
@code
~/libfaudes/plugins/simulator/tutorial>./simfaudes -bs 5 data/gausstest.sim
% simfaudes: ========================================= current state:
<DiscreteState> "idle" </DiscreteState>
% simfaudes: ========================================= current time:
<Time> 0 </Time>
% simfaudes: ========================================= proposed action:
<ProposedTime> 205 </ProposedTime>
<ProposedEvent> "alpha" </ProposedEvent>
% simfaudes: ========================================= execute event:
<ExecutedEvent> "alpha" </ExecutedEvent>
% simfaudes: ========================================= current state:
<DiscreteState> "busy" </DiscreteState>
% simfaudes: ========================================= current time:
<Time> 205 </Time>
% simfaudes: ========================================= found conditions satisfied:
<SatisfiedConditions> "BusyCond" </SatisfiedConditions>
% simfaudes: ========================================= proposed action:
<ProposedTime> 51 </ProposedTime>
% simfaudes: ========================================= current state:
<DiscreteState> "busy" </DiscreteState>
% simfaudes: ========================================= current time:
<Time> 256 </Time>
% simfaudes: ========================================= found conditions satisfied:
<SatisfiedConditions> "BusyCond" </SatisfiedConditions>
% simfaudes: ========================================= proposed action:
<ProposedTime> 39 </ProposedTime>
<ProposedEvent> "beta" </ProposedEvent>
% simfaudes: ========================================= execute event:
<ExecutedEvent> "beta" </ExecutedEvent>
% simfaudes: ========================================= current state:
<DiscreteState> "idle" </DiscreteState>
% simfaudes: ========================================= current time:
<Time> 295 </Time>
% simfaudes: ========================================= found conditions satisfied:
<SatisfiedConditions> "IdleCond" </SatisfiedConditions>
% simfaudes: ========================================= proposed action:
<ProposedTime> 191 </ProposedTime>
<ProposedEvent> "alpha" </ProposedEvent>
% simfaudes: ========================================= execute event:
<ExecutedEvent> "alpha" </ExecutedEvent>
% simfaudes: ========================================= current state:
<DiscreteState> "busy" </DiscreteState>
% simfaudes: ========================================= current time:
<Time> 486 </Time>
% simfaudes: ========================================= found conditions satisfied:
<SatisfiedConditions> "BusyCond" </SatisfiedConditions>
% simfaudes: ========================================= proposed action:
<ProposedTime> 51 </ProposedTime>
% simfaudes: ========================================= end simulation
@endcode
The code is straight forward: after some command line parsing
for behavioural configuration, it reads a proposing executor from file
and loops to execute the proposed transitions.
@ingroup Tutorials
@include simfaudes.cpp
*/
#include "libfaudes.h"
#include <signal.h>
using namespace faudes;
// global vars used in exit handler
int mConsoleOut=0;
std::string mMark="% simfaudes: ========================================= ";
// simulator clean-up on exit
// signal handler to stop devices
// report
std::cout << std::endl;
// clean up
// re-install default handler
signal(sig, SIG_DFL);
// pass on
raise(sig);
}
// clean-up on exit
// clean up only once
static sig_atomic_t exit_in_progress = 0;
if(exit_in_progress>0) return;
exit_in_progress++;
std::cout << mMark << "simfaudes: exit handler" << std::endl;
#ifdef FAUDES_PLUGIN_IODEVICE
// report device performance
dev->WritePerformance();
}
// stop all devices
#endif
// report statistics
if(mConsoleOut>=-1) {
cit!=mExecutor.ConditionsEnd(); cit++) {
std::cout << mMark << "statistics for simulation condition \"" <<
}
}
// close log file
// reset incl device if such
}
// print usage info and exit
if(message!="") {
std::cout << "simfaudes: " << message << std::endl;
std::cout << "" << std::endl;
exit(-1);
}
std::cout << "simfaudes: version " << VersionString() << std::endl;
std::cout << "" << std::endl;
std::cout << "simfaudes: usage: " << std::endl;
std::cout << " simfaudes [-q][-v][-i][-bc] [-bt <nnn>][-bs <nnn>] [-l <logfile>] [-ls] [-le] [-lt] <simfile> " << std::endl;
std::cout << "where " << std::endl;
std::cout << " <simfile>: simulation configuration file" << std::endl;
std::cout << "" << std::endl;
std::cout << " -q: less console output " << std::endl;
std::cout << " -qq: absolutely no console output " << std::endl;
std::cout << " -v: more console output" << std::endl;
std::cout << " -vv: even more console output" << std::endl;
std::cout << " -i: interactive mode " << std::endl;
std::cout << "" << std::endl;
std::cout << " -bc: break on condition" << std::endl;
std::cout << " -bt <nnn>: break on time <nnn> " << std::endl;
std::cout << " -bs <nnn>: break on step <nnn> " << std::endl;
std::cout << "" << std::endl;
std::cout << " -l <logfile>: log to <logfile> " << std::endl;
std::cout << " -ls: log states" << std::endl;
std::cout << " -le: log events" << std::endl;
std::cout << " -lt: log time" << std::endl;
std::cout << " -la: log all" << std::endl;
std::cout << " -t <nnn>: fifo trace buffer length <nnn> " << std::endl;
#ifdef FAUDES_PLUGIN_IODEVICE
std::cout << "" << std::endl;
std::cout << " -d <devfile>: use io device configured from file" << std::endl;
std::cout << " -dt <nnn>: tolerance in time synchronisation" << std::endl;
std::cout << " -dr: executer reset on device request" << std::endl;
#endif
std::cout << "" << std::endl;
std::cout << "" << std::endl;
exit(-1);
}
// parse commandline, read executor and run executor
{
// install my signal handler
// install my exit fnct
atexit(simfaudes_exit);
// default behaviour
mConsoleOut=0;
bool mInteractive=false;
std::string mSimFile="";
std::string mDevFile="";
Time::Type mTolerance=-1;
bool mBreakCondition=false;
Time::Type mBreakTime=Time::Max();
int mBreakStep=-1;
std::string mLogFile="";
int mLogMode=0;
int mTraceLength=5;
bool mResetRequest=false;
// primitive commad line parsing
for(int i=1; i<argc; i++) {
std::string option(argv[i]);
// option: quiet
if((option=="-q") || (option=="--quiet")) {
mConsoleOut=-1;
continue;
}
// option: more quiet
if((option=="-qq") || (option=="--quietquiet")) {
mConsoleOut=-2;
continue;
}
// option: verbose
if((option=="-v") || (option=="--verbose")) {
mConsoleOut=1;
continue;
}
// option: more verbose
if((option=="-vv") || (option=="--verboseverbose")) {
mConsoleOut=2;
continue;
}
// option: interactive
if((option=="-i") || (option=="--interactive")) {
mInteractive=true;
continue;
}
// option: io device
if((option=="-d") || (option=="--device")) {
i++; if(i>=argc) usage_exit();
mDevFile=argv[i];
continue;
}
// option: io device tolerance
if((option=="-dt") || (option=="--tolerance")) {
i++; if(i>=argc) usage_exit();
mTolerance=(Time::Type) ToIdx(argv[i]);
continue;
}
// option: io device reset request
if((option=="-dr") || (option=="--resetrequest")) {
mResetRequest=true;
continue;
}
// option: break condition
if((option=="-bc") || (option=="--breakcondition")) {
mBreakCondition=true;
continue;
}
// option: break time
if((option=="-bt") || (option=="--breaktime")) {
i++; if(i>=argc) usage_exit();
mBreakTime=(Time::Type) ToIdx(argv[i]);
continue;
}
// option: break step
if((option=="-bs") || (option=="--breakstep")) {
i++; if(i>=argc) usage_exit();
mBreakStep=(int) ToIdx(argv[i]);
continue;
}
// option: log file
if((option=="-l") || (option=="--logfile")) {
i++; if(i>=argc) usage_exit();
mLogFile=argv[i];
continue;
}
// option: log states
if((option=="-ls") || (option=="--logstates")) {
mLogMode |= LoggingExecutor::LogStates;
continue;
}
// option: log events
if((option=="-le") || (option=="--logevents")) {
mLogMode |= LoggingExecutor::LogEvents;
continue;
}
// option: log time
if((option=="-lt") || (option=="--logtime")) {
mLogMode |= LoggingExecutor::LogTime;
continue;
}
// option: log all
if((option=="-la") || (option=="--logall")) {
mLogMode |= 0xff;
continue;
}
// option: trace
if((option=="-t") || (option=="--trace")) {
i++; if(i>=argc) usage_exit();
mTraceLength=(int) ToIdx(argv[i]);
continue;
}
// option: help
if((option=="-?") || (option=="--help")) {
usage_exit();
continue;
}
// option: unknown
if(option.c_str()[0]=='-') {
usage_exit("unknown option "+ option);
continue;
}
// filename
if(mSimFile!="")
usage_exit("more than one filname specified" );
mSimFile=option;
}
// insist in filename
if(mSimFile=="")
usage_exit("you must specify a filename" );
// dont have both, interactive and sync physics
if(mDevFile!="" && mInteractive)
usage_exit("you must not specify both interactive and synchrone mode");
// mute libFAUDES console out
if(mConsoleOut<0)
try{
// relaxed read configuration: test for generator file
bool gfile=false;
Token token;
tr->Peek(token);
gfile=true;
// read configuration
if(gfile) {
} else {
}
std::cout << std::flush;
std::cerr << "simfaudes: presumably missing/missformed configuration file" << std::endl;
return 1;
}
// report configuration
if(mConsoleOut>=1) {
std::cout << mMark << "dumping configuration" << std::endl;
// generators
std::cout << mMark << "found generator #" << i+1 <<
}
// event attributes
std::cout << mMark << "found event attributes for \"" <<
}
// conditions
cit!=mExecutor.ConditionsEnd(); cit++) {
std::cout << mMark << "found simulation condition \"" <<
}
}
// report generators (disabled, max output level is 2)
if(mConsoleOut>=3) {
// generators
std::cout << mMark << "generator #" << i+1 << std::endl;
}
}
// initialze log file
if(mLogFile!="") {
}
if(mLogFile=="" && mLogMode!=0) {
}
// set trace buffer
mExecutor.TraceClear(mTraceLength);
// ************************************************ synchronous prep
if(mDevFile!="") {
#ifdef FAUDES_PLUGIN_IODEVICE
// create device from file
vDevice* dev;
try {
dev=vDevice::FromFile(mDevFile);
std::cout << std::flush;
std::cerr << "simfaudes: presumably missing/missformed configuration file" << std::endl;
return 1;
}
#ifdef FAUDES_NETWORK
#ifdef FAUDES_WINDOWS
// initialise winsocks
if(mConsoleOut>=0)
std::cout << mMark << "Initialze network" << std::endl;
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2), &wsaData)!=0) {
usage_exit("cannot start winsock (network error)");
}
#endif
#endif
// report
if(mConsoleOut>=0)
// set tolerance
// assign device to executor and wait for startup to complete
std::cout << mMark << "Starting IO device \""<< dev->Name() << "\" Status: " << dev->StatusString() << std::endl;
faudes_sleep(1);
}
dev->CurrentTime(0); // sync time; dont use reset, since we would loose events
#else
// cannot run device without plugin
#endif
}
// ************************************************* interactive loop
bool mRunning=true;
bool mInterTemp=mInteractive;
SimConditionSet mSatisfied;
mSatisfied.Name("SatisfiedConditions");
while(mRunning) {
// report current state
if(mConsoleOut>=2) {
std::cout << mMark << "current state:" << std::endl;
std::cout << mMark << "marking reached:" << std::endl;
}
}
// report current state
std::cout << mMark << "current state:" << std::endl;
std::cout << mExecutor.CurrentParallelTimedState().ToString("DiscreteState",&mExecutor) << std::endl;
}
// report current time
if(mConsoleOut>=1) {
std::cout << mMark << "current time:" << std::endl;
}
// report current time
if(mConsoleOut==0) {
std::cout << mMark << "current time:" << std::endl;
}
// report satisfied conditions
if(mConsoleOut>=0) {
mSatisfied.Clear();
cit!=mExecutor.ConditionsEnd(); cit++) {
}
if(mSatisfied.Size()>0) {
std::cout << mMark << "found conditions satisfied:" << std::endl;
std::cout << mSatisfied.ToString() << std::endl;
}
}
// report internal state
if(mConsoleOut>=2) {
std::cout << mMark << "simulation event states:" << std::endl;
std::cout << mExecutor.EventStatesToString() << std::endl;
}
// report enables per component
std::cout << mMark << "disabled events (per component):" << std::endl;
}
}
// report enabled transitions
if(mConsoleOut>=1) {
std::cout << mMark << "enabled events:" << std::endl;
std::cout << mMark << "enabled interval:" << std::endl;
std::cout << mMark << "enabled time:" << std::endl;
}
// test break: time up
mInterTemp=false;
mRunning=false;
break;
}
// test break: condition
mInterTemp=mInteractive;
mRunning=mInteractive;
}
// test break: time
if(mBreakTime!=Time::UnDef())
mInterTemp=mInteractive;
mRunning=mInteractive;
}
// test break: step
if(mBreakStep>=0)
mInterTemp=mInteractive;
mRunning=mInteractive;
}
// test break: synchronous device
mInterTemp=false;
mRunning=false;
break;
}
// proposed action
if(mConsoleOut>=0) {
std::cout << mMark << "proposed action:" << std::endl;
if(mPropTrans.mTime>0)
std::cout << "<ProposedTime> " << ToStringInteger(mPropTrans.mTime) << " </ProposedTime>" << std::endl;
if(mPropTrans.mEvent!=0)
std::cout << "<ProposedEvent> \"" << mExecutor.EventName(mPropTrans.mEvent) << "\" </ProposedEvent>" << std::endl;
std::cout << "+DeadLock+" << std::endl;
}
// record transition
Idx mEvent=0;
// ask choice
while(mInterTemp) {
// get user input
std::cout << mMark << "enter command:" << std::endl;
std::string line;
std::getline(std::cin,line);
// separate cmd from arg
std::string choice;
std::string param;
std::istringstream sline(line);
sline >> choice;
sline >> param;
// convert to int
int ichoice =-1;
std::istringstream schoice(choice);
schoice >> ichoice;
if(!schoice) ichoice=-1;
int iparam =-1;
std::istringstream sparam(param);
sparam >> iparam;
if(!sparam) iparam=-1;
// convert to symbol
std::string nchoice=choice;
if(choice.length()>2)
if(choice.at(0)=='"' && choice.at(choice.length()-1)== '"')
nchoice=choice.substr(1,choice.length()-2);
// switch cases
bool err=false;
if(choice=="x" || choice == "exit") {
mRunning=false;
} else
if(choice=="p" || choice=="proposal" || choice=="") {
mEvent=mPropTrans.mEvent;
} else
if(choice=="r" || choice=="run") {
mInterTemp=false;
} else
if(choice=="v" || choice=="revert") {
if(iparam!=-1) step=iparam;
std::cout << mMark << "revert to step " << step << std::endl;
mExecutor.RevertToStep(step);
} else
if(choice=="t" || choice=="trace") {
std::cout << mMark << "system trace" << std::endl;
continue;
} else
if(ichoice>0) {
mExecutor.ExecuteTime(ichoice);
} else
mEvent=mExecutor.EventIndex(nchoice);
} else {
std::cout << mMark << "simfaudes interactive mode" << std::endl;
std::cout << "%" << std::endl;
std::cout << "% execute time and/or transitions" << std::endl;
std::cout << "% * <nn> to pass a specified duration <nn> (excl brackets)" << std::endl;
std::cout << "% * \"event\" to execute an event (incl quotes)" << std::endl;
std::cout << "% * [P] or [Ret] to execute the recent proPosal " << std::endl;
std::cout << "%" << std::endl;
std::cout << "% show trace and revert" << std::endl;
std::cout << "% * [T] to show a Trace of recent events and states" << std::endl;
std::cout << "% * [V] <nn> to reVert to step <nn> (obmit <nn> for one step backward) "<< std::endl;
std::cout << "%" << std::endl;
std::cout << "% other" << std::endl;
std::cout << "% * [X] to eXit" << std::endl<< std::endl;
err=true;
}
if(!err) break;
}
// execute proposal
if(!mInterTemp && mDevFile=="") {
mEvent=mPropTrans.mEvent;
}
#ifdef FAUDES_PLUGIN_IODEVICE
// sync step
if(mDevFile!="") {
// reset request ?
if(rr && mConsoleOut>=0 && !mResetRequest) {
std::cout << mMark << "ignoring reset request" << std::endl;
rr=false;
}
if(rr && mConsoleOut>=0)
std::cout << mMark << "reset on request" << std::endl;
if(rr)
// sync proposal
if(!rr) {
std::cout << mMark << "sync wait" << std::endl;
}
}
#endif
// report event
if(mConsoleOut>=0 && mEvent!=0) {
std::cout << mMark << "execute event:" << std::endl;
<< std::endl;
}
} // loop: while mRunning
// done
return 0;
}
Definition in file simfaudes.cpp. Function Documentation
Definition at line 126 of file simfaudes.cpp.
Definition at line 215 of file simfaudes.cpp.
Definition at line 139 of file simfaudes.cpp.
Definition at line 174 of file simfaudes.cpp. Variable Documentation
Definition at line 119 of file simfaudes.cpp.
Definition at line 118 of file simfaudes.cpp.
Definition at line 120 of file simfaudes.cpp. libFAUDES 2.28a --- 2016.09.13 --- c++ api documentaion by doxygen |