A data-driven task is a task that wants to perform computations whenever new data is available on its input ports. In general, data-processing tasks (as for instance image processing tasks) fall into that category: their goal is to take data from their input, process it, and push it to their outputs.
Note that in Orocos, port-triggering is a mechanism that can be overlaid on top of other triggering mechanisms like periodic or file-descriptor triggerings.
Declaration
A data-driven task is declared by using the #port_driven statement.
Let’s look at the following example declaration:
task_context "Task" do
input_port 'image', '/Camera/Frame'
input_port 'parameters', '/SIFT/Parameters'
output_port 'features' '/SIFT/FeatureSet'
port_driven 'image'
end
During runtime, the updateHook() method of the corresponding C++ task will be called when new data arrives on the listed ports (in this case ‘image’). Other input ports are ignored by the triggering mechanism.
Note that, obviously, the listed ports must be input ports. Moreover, they must be declared before the call to port_driven.
Finally, if called without arguments, port_driven will activate the port triggering on all input ports declared before it is called. This means that, in
task_context "Task" do
input_port 'image', '/Camera/Frame'
input_port 'parameters', '/SIFT/Parameters'
output_port 'features' '/SIFT/FeatureSet'
port_driven
end
both ‘parameters’ and ‘image’ are triggering. Now, in
task_context "Task" do
input_port 'image', '/Camera/Frame'
port_driven
input_port 'parameters', '/SIFT/Parameters'
output_port 'features' '/SIFT/FeatureSet'
end
only ‘image’ is.
C++ task implementation
In the C++ task implementation, the behaviour is slightly different between version up to RTT 2.X.
In the updateHook(), you will have to read the ports and test if a new data sample arrived.
Camera::Frame frame;
if(_image.read(frame) == RTT::NewData)
{
}
SIFT::Parameters parameters;
if(_parameters.read(parameters) == RTT::NewData)
{
}
Deployment
As we mentioned at the beginning of this page, the port-triggering mechanism can be overlaid on top of the other mechanisms.
If one uses the default task declaration
deployment "test" do
t = task('Task')
end
then the deployed task instance will only be triggered when new data is received on its input ports. It is however possible to use FD-based and port-based triggering at the same time.
deployment "test" do
t = task('Task').
fd_driven
end
However, deploying with the periodic triggering will override (i.e. disable) the port-triggering.