Replacing Commands

RTT 2.0 has dropped the support for the RTT::Command class. It has been replaced by the more powerful Methods vs Operations construct.

The rtt2-converter tool will automatically convert your Commands to Method/Operation pairs. Here's what happens:

// RTT 1.x code:
class ATask: public TaskContext
{
  bool prepareForUse();
  bool prepareForUseCompleted() const;
public:
  ATask(): TaskContext("ATask")
  {
    this->commands()->addCommand(RTT::command("prepareForUse",&ATask::prepareForUse,&ATask::prepareForUseCompleted,this),
                                             "prepares the robot for use");
  }
};

After:

// After rtt2-converter: RTT 2.x code:
class ATask: public TaskContext
{
  bool prepareForUse();
  bool prepareForUseCompleted() const;
public:
  ATask(): TaskContext("ATask")
  {
    this->addOperation("prepareForUse", &ATask::prepareForUse, this, RTT::OwnThread).doc("prepares the robot for use");
    this->addOperation("prepareForUseDone", &ATask::prepareForUseCompleted, this, RTT::ClientThread).doc("Returns true when prepareForUse is done.");
  }
};

What has happened is that the RTT 1.0 Command is split into two RTT 2.0 Operations: "prepareForUse" and "prepareForUseDone". The first will be executed in the component's thread ('OwnThread'), analogous to the RTT::Command semantics. The second function, prepareForUseDone, is executed in the callers thread ('ClientThread'), also analogous to the behaviour of the RTT::Command's completion condition.

The old behavior can be simulated at the callers side by these constructs:

Calling a 2.0 Operation as a 1.0 Command in C++

Polling for commands in RTT 1.x was very rudimentary. One way of doing it would have looked like this:
  Command<bool(void)> prepare = atask->commands()->getCommand<bool(void)>("prepareForUse");
  prepare(); // sends the Command object.
  while (prepare.done() == false)
    sleep(1);
You look up the command with the signature bool(void) and invoke it. Next you needed to poll for done() to return true.

In RTT 2.0, the caller's code looks up the prepareForUse Operation and then 'sends' the request to the ATask Component. Optionally, the completion condition is looked up manually and polled for as well:

  Method<bool(void)> prepare = atask->getOperation("prepareForUse");
  Method<bool(void)> prepareDone = atask->getOperation("prepareForUseDone");
  SendHandle h = prepare.send();
 
  while ( !h.collectIfDone() && prepareDone() == false )
     sleep(1);

The collectIfDone() and prepareDone() checks are now made explicit, while they were called implicitly in the RTT 1.x's prepare.done() function. Writing your code like this will case the exact same behaviour in RTT 2.0 as in RTT 1.x.

In case you don't care for the 'done' condition, the above code may just be simplified to:

  Method<bool(void)> prepare = atask->getOperation("prepareForUse");
  prepare.send();

In that case, you may ignore the SendHandle, and the object will cleanup itself at the appropriate time.

Calling a 2.0 Operation as a 1.0 Command in Scripting

Scripting was very convenient for using commands. A typical RTT 1.x script would have looked like:

program foo {
  do atask.prepareForUse();
  // ... rest of the code
}
The script would wait at the prepareForUse() line (using polling) until the command's completion.

To have the same behaviour in RTT 2.x using Operations, you need to make the 'polling' explicit. Furthermore, you need to 'send' the method to indicate that you do not wish to block:

program foo {
  var SendHandle h;
  set h = atask.prepareForUse.send();
  while (h.collectIfDone() == false && atask.prepareForUseDone() == false)
     yield;
  // ... rest of the code
}
Just like in the C++ code, you need to create a SendHandle variable and store the result of the send in it. You can then use h to see if the operation finished yet and if so, check the status of prepareForUseDone(). It may be convenient to put these in a function in RTT 2.x:

function prepare_command() {
  var SendHandle h;
  set h = atask.prepareForUse.send();
  while (h.collectIfDone() == false && atask.prepareForUseDone() == false)
     yield;
}
program foo {
   call prepare_command(); // note: using 'call'
  // ... rest of the code
}
In order to avoid blocking in the 'foo' program, you need prefix prepare_command with 'call'. This will 'inline' the function such that 'foo' will not block the ExecutionEngine until prepare_command returns. For comparison purposes, if you would omit the 'call' prefix, program would need to loop on prepare_command() in turn:

export function prepare_command()  // note: we must export the function
{
  var SendHandle h;
  set h = atask.prepareForUse.send();
  while (h.collectIfDone() == false && atask.prepareForUseDone() == false)
     yield;
}
program foo {
  var SendHandle h;
  set h = prepare_command(); // note: not using 'call'
  while (h.collectIfDone() == false)
     yield;
  // ... rest of the code
}
In RTT 2.x, a program script will only yield when the word 'yield' (equivalent to RTT 1.x 'do nothing') is seen. Both function and program must yield in order to not spin in an endless loop in the ExecutionEngine.

note

Code without 'yield' can spin forever. This blocking 'trap' in 2.0 can be very inconvenient. It's likely that an alternative system will be provided to allow 'transparant' polling for a given function. For example this syntax could be introduced:
program foo {
  prepare_command.call(); // (1) calls and blocks for result.
  prepare_command.send(); // (2) send() and forget.
  prepare_command.poll(); // (3) send() and poll with collectIfDone().
}
Syntax (1) and (2) are already present. Syntax (3) would indicate that the script must send and poll (using collectIfDone() behind the scenes) the prepare_command operation. This would always work and save users from writing the bulky SendHandle code.