Skip to content
This repository has been archived by the owner. It is now read-only.

Commit

Permalink
Moved statemachine to separate class
Browse files Browse the repository at this point in the history
MPIBR-kretschmerf committed Sep 7, 2016
1 parent 22ca327 commit 305f526
Showing 4 changed files with 288 additions and 341 deletions.
173 changes: 173 additions & 0 deletions StateMachineController.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#include "StateMachineController.h"

StateMachineController::StateMachineController(QWidget *parent)
{
// seed randomizer
srand(time(0));
// //timerDialog = new TimerDialog();

mainTimer = new QTimer(this);
mainTimer->setSingleShot(true);

// Create and start the state machine
setupStateMachine();

}

void StateMachineController::setupStateMachine()
{
stateMachine = new QStateMachine(this);

// Create the two top-level states
QState *runningState = new QState(stateMachine);
QState *pausedState = new QState(stateMachine);

// set up state machine
QState *state_preDelay = new QState(runningState);
QState *state_iti = new QState(runningState);
QState *state_userReaction = new QState(runningState);
QState *state_acquisitionBaseline = new QState(runningState);
QState *state_sound = new QState(runningState);

QHistoryState *historyState = new QHistoryState(runningState);

/**
* Depending on whether we are in runningState or pausedState, the 'paused' property
* of the object will be set to false/true.
*/

runningState->assignProperty(this, "paused", false);
pausedState->assignProperty(this, "paused", true);

state_preDelay->addTransition(mainTimer, SIGNAL(timeout()), state_iti);
state_iti->addTransition(mainTimer, SIGNAL(timeout()), state_userReaction);
state_userReaction->addTransition(mainTimer, SIGNAL(timeout()), state_acquisitionBaseline);
state_acquisitionBaseline->addTransition(mainTimer, SIGNAL(timeout()), state_sound);
state_sound->addTransition(mainTimer, SIGNAL(timeout()), state_iti);

/**
* If we are in runningState and the pauseRequested() signal is emitted (that happens
* when the pause() slot has been invoked) then we go to the pausedState.
* If we are now in the pausedState and the pauseRequested() signal is emitted again,
* we go to the historyState which will forward us to the phase state we have been in
* when we left the runningState.
*/
runningState->addTransition(this, SIGNAL(pauseRequested()), pausedState);
pausedState->addTransition(this, SIGNAL(pauseRequested()), historyState);

// Define which child state should be the initial state
runningState->setInitialState(state_preDelay);
stateMachine->setInitialState(runningState);

// connect states to functions for starting timers
// state pre delay
connect(state_preDelay, SIGNAL(entered()), this, SLOT(onStatePreDelayEntered()));
//connect(state_preDelay, SIGNAL(entered()), mainTimer, SLOT(start())); // start timer on state entered
// state ITI
connect(state_iti, SIGNAL(entered()), this, SLOT(onStateItiEntered()));
//connect(state_iti, SIGNAL(entered()), mainTimer, SLOT(start()));
// state user reaction
connect(state_userReaction, SIGNAL(entered()), this, SLOT(onStateUserReactionEntered()));
/////connect(state_userReaction, SIGNAL(exited()), timerDialog, SLOT(removeTimer()));
//connect(state_userReaction, SIGNAL(entered()), mainTimer, SLOT(start()));
// state baseline
connect(state_acquisitionBaseline, SIGNAL(entered()), this, SLOT(onStateAcquisitionBaselineEntered()));
//connect(state_acquisitionBaseline, SIGNAL(entered()), mainTimer, SLOT(start()));
// state sound
connect(state_sound, SIGNAL(entered()), this, SLOT(onStateSoundEntered()));
//connect(state_sound, SIGNAL(entered()), mainTimer, SLOT(start()));
connect(state_sound, SIGNAL(exited()), this, SLOT(onStateSoundExited()));

}

void StateMachineController::runStateMachine()
{
trialsCurrent = 1; // set index for first trial (1-based)
trialsTotal = trialSequence.length();

// start state machine
stateMachine->start();
}


void StateMachineController::onStatePreDelayEntered()
{
qDebug() << "Pre delay";
emit(statusMessage("Pre delay running"));

mainTimer->setInterval(preDelay * 1000);
mainTimer->start();
}

void StateMachineController::onStateItiEntered()
{
qDebug() << "Entered Iti";
emit(statusMessage("Starting trial begin"));

double nextItiValue = itiSequence.at(trialsCurrent - 1); // -1 because trialsCurrent is 1-based
mainTimer->setInterval(nextItiValue * 1000);
mainTimer->start();

}

void StateMachineController::onStateUserReactionEntered()
{
// timerDialog->removeTimer(); // remove previous timer dialog
// timerDialog->setUpTimer(userReaction);
// timerDialog->show();
// timerDialog->startTimer();

qDebug()<< "Starting user reaction";
emit(statusMessage("Starting user reaction"));

mainTimer->setInterval(userReaction * 1000);
mainTimer->start();
}

void StateMachineController::onStateAcquisitionBaselineEntered()
{
qDebug()<< "Starting baseline";

emit(statusMessage("Starting baseline"));

mainTimer->setInterval(preImaq * 1000);
mainTimer->start();
}

void StateMachineController::onStateSoundEntered()
{

int soundType = trialSequence.first();
trialSequence.pop_front();

if (soundType == 1) {
mainTimer->setInterval(soundDurationPositive * 1000);
//state_sound->assignProperty(mainTimer, "interval", (soundDurationPositive * 1000));
} else if (soundType == 0) {
mainTimer->setInterval(soundDurationNegative * 1000);
//state_sound->assignProperty(mainTimer, "interval", (soundDurationNegative * 1000));
}
mainTimer->start();

qDebug()<< "Starting sound";
emit(statusMessage("Starting sound"));

}

void StateMachineController::onStateSoundExited()
{
qDebug()<< "Finished sound";
emit(statusMessage("Finished sound"));
// go to next trial
if(trialsCurrent < trialsTotal) {
//increase trial index
trialsCurrent++;
// or terminate
} else {
mainTimer->stop();
stateMachine->stop();
qDebug() << "Terminated";
//ui->statusBar->showMessage("Terminated");
//ui->pushButton_Run->setText("Run");
}
}
79 changes: 79 additions & 0 deletions StateMachineController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#ifndef STATEMACHINECONTROLLER_H
#define STATEMACHINECONTROLLER_H
#include <QObject>
#include <QTimer>
#include <QElapsedTimer>
#include <QVector>
#include <QStateMachine>
#include <QState>
#include <QHistoryState>
#include <QDebug>

#include <ctime>
#include <algorithm> //std::random_shuffle

class StateMachineController : public QObject
{
Q_OBJECT

public:
explicit StateMachineController(QWidget *parent = 0);

double preDelay = -1;
double iti = -1;
double userReaction = 30; //sec
double preImaq = -1;
double soundDurationPositive = -1;
double soundDurationNegative = -1;

QVector<int> trialSequence;
QVector<double> itiSequence;

void setupStateMachine();
void runStateMachine();

private:
// state machine
QStateMachine *stateMachine;
QState *state_preDelay;
QState *state_iti;
QState *state_userReaction;
QState *state_acquisitionBaseline;
QState *state_sound;

bool m_paused;

// the timer that triggers the state changes
QTimer *mainTimer;

int trialsTotal = -1;
int trialsCurrent = -1; // is gonna be 1-based, so first trial has index 1


public slots:
void onStatePreDelayEntered();
void onStateItiEntered();
void onStateUserReactionEntered();
void onStateAcquisitionBaselineEntered();
void onStateSoundEntered();
void onStateSoundExited();




signals:
void statusMessage(QString);

Q_SIGNALS:
// change notification signals for the state properties
void pausedChanged();
/**
* This signal is emitted when the pause() slot is invoked and is used
* by the internal state machine only.
*/
void pauseRequested();


};

#endif // STATEMACHINECONTROLLER_H
Loading

0 comments on commit 305f526

Please sign in to comment.