- Development
- European Robotics Forum 2011 Workshop on the Orocos Toolchain
- European Robotics Forum 2012: workshops
- Geometric relations semantics
- KDL wiki
- Kuka LBR user group
- Links of Orocos components
- OCL v1.x wiki
- RTT v1.x wiki
- Documentation suggestions
- Examples and Tutorials
- Frequently asked questions (FAQ)
- Installation
- RTT Dictionary
- RTT on MS Windows
- The 1st RTT Developers Workshop
- The Road to RTT 2.0
- Goals for RTT 2.0
- Contribute! Which weakness have you detected in RTT?
- Contribute! Suggest a new feature to be included in RTT 2.0.
- Create Reference Application Architectures
- Detailed Roadmap
- Full distribution support
- RTT 2.0.0-beta1
- RTT 2.0.0-beta2
- RTT and OCL Cleanup
- Real time logging
- Redesign of the data flow interface
- Simplified, more robust default activities
- Streamlined Execution Flow API
- Upgrading from RTT 1.x to 2.0
- Using Eclipse and Orocos
- Using Git and Orocos
- Toolchain v2.x
- Wiki for site admins
- iTaSC wiki
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);
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 }
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 }
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 }
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 }
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(). }
»
- Printer-friendly version
- Login or register to post comments