User Tools

Site Tools


eeros_architecture:sequencer:subsequence

This is an old revision of the document!


Subsequence

A subsequence is a sequence which is called by another sequence. Such a subsequence can be called in a blocking or non-blocking way. Blocking means that the step waits (or blocks) until the subsequence has finished. Non-blocking means that subsequence and main sequence run concurrently.

Blocking Call of a Subsequence

If you want to save your own data in the sequence, you need to create a new instance of a sequence. This should be done in the desired step (method) of the superior sequence. e.g. in the method MoveBlocking()

Simple Example

We first define a class for the sub- or secondary sequence as follows:

class SequenceB : public Sequence<void,double> {
public:
  SequenceA(std::string name, Sequencer* seq, Robot& r) : Sequence<void,double>(name, seq), robot(r){ }
 
  void run(double z) {
    robot.moveXY(z);
    yield();
    robot.moveXY(0);
  }
 
private: 
  Robot& robot;
};

The run() method is called with one parameter of type double. There is no return value. For this reason, our class has to extend the class sequence with the template parameters <void,double>. To keep the example as simple as possible we omit the implementation of init()/exit() functions and pre and post condition check functions.

We can now define our first or main sequence with

class SequenceA : public Sequence<> {
public:
  SequenceA(std::string name, Sequencer* seq, Robot& r) : Sequence<>(name, seq), robot(r), seqB("Seq B", seq, r) { }
 
  void run() {
    robot.moveXY(10, -20);
    seqB(5);
    robot.moveXY(-10, -30);
    seqB(5);
    robot.moveXY(0, 0);
  }
 
private: 
  Robot& robot;
  SequenceB seqB;
};

In our main program we declare a sequencer for the main sequence. The same sequencer will also handle the subsequence. Sequence A and B do not run concurrently. The following figure shows the flow of action.

Nonblocking Call of a Subsequence

A nonblocking subsequence has to run in its own thread. For this reason you need a separate subsequencer for this. e.g.:

MySequencer* subSequencer = new MySequencer("SubSequencer");

Here you can reuse an existing sub-sequence if you want.

MyNonBlockingSubSequence* subSequence = dynamic_cast<MyNonBlockingSubSequence*>(eeros::sequencer::Sequence::getSequence("NonBlockingSubSequence"));
if(!subSequence){
  subSequence = new MyNonBlockingSubSequence("NonBlockingSubSequence",subSequencer);
}

Note:

  • The constructor of the MyNonBlockingSequence class has to call callerThread.addRunnable(this) to add itself to the sub-sequencer runnable list, or else the callback methods are not called by the sub-sequencer.
  • Do not forget to call callerThread.stop() in the last step of the sub-sequence.

As soon as you have created the sub-sequence, you can start the sub-sequencer, which creates the threads to run all steps.

  subSequencer->start();

In an other step of the superior sequence you can wait until the non-blocking sequence is terminated by using the method: ExecutorService::waitForSequenceEnd(…);.

//Here we wait for the subsequencer Thread
eeros::sequencer::Sequencer* seq = eeros::sequencer::Sequencer::getMainSequencer()->findSequencer("SubSequencer");
if(seq && seq->getStatus() != kStopped){
  ExecutorService::waitForSequenceEnd(seq);
}
eeros_architecture/sequencer/subsequence.1446150948.txt.gz · Last modified: 2015/10/29 21:35 by graf