adding an event Port to two taskcontexts

Hi,

We are working towards composite components and are trying to promote
ports from elementary components to the interface of a composite
component (itself just a TaskContext).

Adding one port to two TaskContexts is not (yet) officially supported
bu the RTT model, although it works well out of the box (kudos to
Peter!) The only limitation (applying only to for EventPorts) is that
it only wakes up the last Component to which the port was added and
not all.

See the attached Lua script for test. Having all components being
woken up would be requirement for implementing such composite
components. Can someone estimate efforts and intrusiveness of such a
change?

Thanks!

Markus

<script>?
d:loadComponent("l1", "OCL::LuaComponent")
d:loadComponent("l2", "OCL::LuaComponent")
l1=d:getPeer("l1")
l2=d:getPeer("l2")

port=rtt.InputPort("string")

l1:addEventPort(port, "my-event-port on l1")
l2:addEventPort(port, "my-event-port on l2")

pout=rttlib.port_clone_conn(port)
print("pout:", pout)
print("port:", port) -- [in, string, unconn, local] //

l1:exec_str("function updateHook() print('in l1 updateHook') end")
l2:exec_str("function updateHook() print('in l2 updateHook') end")

l1:configure()
l2:configure()
l1:start()
l2:start()

pout:write("foo") -- in l2 updateHook
pout:write("foo") -- in l2 updateHook
pout:write("foo") -- in l2 updateHook
pout:write("foo") -- in l2 updateHook

<script>?

$ rttlua-gnulinux -i ports.lua
0.074 [ Warning][DeploymentComponent::import] The ROS package 'ocl' in
'/home/mk/src/electric/orocos_toolchain/ocl' nor its dependencies
contained a lib/orocos directory. I'll look in the RTT_COMPONENT_PATH
next.
OROCOS RTTLua 1.0-beta4 / Lua 5.1.4 (gnulinux)
pout: my-event-port on l2 [out, string, conn, local] // Inverse port of .my-event-port on l2
port: my-event-port on l2 [in, string, conn, local] //
in l1 updateHook
in l2 updateHook
in l2 updateHook
in l2 updateHook

adding an event Port to two taskcontexts

On Mon, Dec 12, 2011 at 1:40 PM, Markus Klotzbuecher
<markus [dot] klotzbuecher [..] ...> wrote:
> Hi,
>
> We are working towards composite components and are trying to promote
> ports from elementary components to the interface of a composite
> component (itself just a TaskContext).
>
> Adding one port to two TaskContexts is not (yet) officially supported
> bu the RTT model, although it works well out of the box (kudos to
> Peter!)  The only limitation (applying only to for EventPorts) is that
> it only wakes up the last Component to which the port was added and
> not all.
>
> See the attached Lua script for test.  Having all components being
> woken up would be requirement for implementing such composite
> components. Can someone estimate efforts and intrusiveness of such a
> change?

All the logic is in PortInterface.cpp/hpp and can DataFlowInterface*
iface be trivially replaced by a std::vector<DataFlowInterface> iface.
Next InputPort.cpp wakes up all in the list 'iface'. getInterface()
would return the first DataFlowInterface to which the port was added,
ie, the 'real' owner of the port. You could add a method
'getInterfaces()' to return all interfaces, in case you want to
introspect a port of a composite in order to find out if it is present
in multiple interfaces.

This change would imo not break the rest of the software which relies
on 'getInterface()'. We're adding some heap to each port though.

Peter

adding an event Port to two taskcontexts

Markus, Peter, ...

you may know that we also made an implementation of composite
components. We are willing to share, but our code is not really is a
state that it can be included. Our ideas have developed however (or we
are now biased :-).

Two points that I would like to raise:

- we do not promote ports from elementary components to the interface
of a composite component, but rather make connections from the port of
a subcomponent to an internal representation (we call it a plug) of
the port of the container. This is analogous to how it works in
Simulink and 20-sim. So you get an input of the container that is
connected to the input of the subcomponent, and an output of the
subcomponent that is connected to the output of the container. A
common pattern is that multiple subcomponents connect to the same
input and output of the container and 'compete' for activity; only one
of them actually executes updateHook().

- we initially had composite TaskContexts, I think much like what you
now work on. But I find the concept of composite activities confusing.
So we decided to modify the hierarchy of TaskContext: we made a base
class that introduces component behavior, and two specialisations: one
that has an execution engine and actually is just the original
TaskContext, and one that can be composite. A TaskContext can be
implemented by a composite, in which case clones of the unconnected
inputs and outputs of the composite are promoted to the TaskContext
and the TaskContext delegates its "computation" to the composite.
Ports inside a composite all run in the same thread and hence do not
need to be thread-safe; therefore, a simplified port can be used.

Let me know what you think.

Cheers, Theo

2011/12/12 Peter Soetens <peter [..] ...>:
> On Mon, Dec 12, 2011 at 1:40 PM, Markus Klotzbuecher
> <markus [dot] klotzbuecher [..] ...> wrote:
>> Hi,
>>
>> We are working towards composite components and are trying to promote
>> ports from elementary components to the interface of a composite
>> component (itself just a TaskContext).
>>
>> Adding one port to two TaskContexts is not (yet) officially supported
>> bu the RTT model, although it works well out of the box (kudos to
>> Peter!)  The only limitation (applying only to for EventPorts) is that
>> it only wakes up the last Component to which the port was added and
>> not all.
>>
>> See the attached Lua script for test.  Having all components being
>> woken up would be requirement for implementing such composite
>> components. Can someone estimate efforts and intrusiveness of such a
>> change?
>
> All the logic is in PortInterface.cpp/hpp and can DataFlowInterface*
> iface be trivially replaced by a std::vector<DataFlowInterface> iface.
> Next InputPort.cpp wakes up all in the list 'iface'. getInterface()
> would return the first DataFlowInterface to which the port was added,
> ie, the 'real' owner of the port. You could add a method
> 'getInterfaces()' to return all interfaces, in case you want to
> introspect a port of a composite in order to find out if it is present
> in multiple interfaces.
>
> This change would imo not break the rest of the software which relies
> on 'getInterface()'. We're adding some heap to each port though.
>
> Peter
> --
> Orocos-Dev mailing list
> Orocos-Dev [..] ...
> http://lists.mech.kuleuven.be/mailman/listinfo/orocos-dev

adding an event Port to two taskcontexts

On Wed, Dec 14, 2011 at 08:12:24PM +0100, Vries, Theo J.A. de [imotec bv] wrote:
> Markus, Peter, ...
>
> you may know that we also made an implementation of composite
> components. We are willing to share, but our code is not really is a
> state that it can be included. Our ideas have developed however (or we
> are now biased :-).

I would suggest to post it, no matter if it's not perfect. Is for RTT
v1 or v2?

> Two points that I would like to raise:
>
> - we do not promote ports from elementary components to the interface
> of a composite component, but rather make connections from the port of
> a subcomponent to an internal representation (we call it a plug) of
> the port of the container. This is analogous to how it works in
> Simulink and 20-sim. So you get an input of the container that is
> connected to the input of the subcomponent, and an output of the
> subcomponent that is connected to the output of the container. A
> common pattern is that multiple subcomponents connect to the same
> input and output of the container and 'compete' for activity; only one
> of them actually executes updateHook().

But do you use the master-slave activities for this? Or is this based
on event-driven input ports?

> - we initially had composite TaskContexts, I think much like what you
> now work on. But I find the concept of composite activities confusing.

Yes, I also see a danger of the composite activities getting
unmanageable quickly.

> So we decided to modify the hierarchy of TaskContext: we made a base
> class that introduces component behavior, and two specialisations: one
> that has an execution engine and actually is just the original
> TaskContext, and one that can be composite. A TaskContext can be
> implemented by a composite, in which case clones of the unconnected
> inputs and outputs of the composite are promoted to the TaskContext
> and the TaskContext delegates its "computation" to the composite.
> Ports inside a composite all run in the same thread and hence do not
> need to be thread-safe; therefore, a simplified port can be used.

That sounds very much like the container concept that Herman is
suggesting (although I didn't fully understand how you implemented
this). Maybe you can give some more detail?

Markus

adding an event Port to two taskcontexts

On Wed, 14 Dec 2011, Vries, Theo J.A. de [imotec bv] wrote:

> Markus, Peter, ...
>
> you may know that we also made an implementation of composite
> components. We are willing to share, but our code is not really is a
> state that it can be included. Our ideas have developed however (or we
> are now biased :-).
>
> Two points that I would like to raise:
>
> - we do not promote ports from elementary components to the interface
> of a composite component, but rather make connections from the port of
> a subcomponent to an internal representation (we call it a plug) of
> the port of the container. This is analogous to how it works in
> Simulink and 20-sim. So you get an input of the container that is
> connected to the input of the subcomponent, and an output of the
> subcomponent that is connected to the output of the container.

>From a model/semantic point of view, that is the same thing as "promotion",
isn't it?

>A
> common pattern is that multiple subcomponents connect to the same
> input and output of the container and 'compete' for activity; only one
> of them actually executes updateHook().

This is one particular configuration/policy/architecture of how one can do
promotion, I guess.

> - we initially had composite TaskContexts, I think much like what you
> now work on. But I find the concept of composite activities confusing.

Of course :-) The coupling of a TaskContext to an activity is one of the major
design flaws that we made some years ago: it couples the "container"
version of a TaskContext to the "component" version, and that's not good.
("component" version = only considering the functional behaviour of the
piece of code, without concerns about on which "platform" (activity,
process,....) the component will be running.)

> So we decided to modify the hierarchy of TaskContext: we made a base
> class that introduces component behavior, and two specialisations: one
> that has an execution engine and actually is just the original
> TaskContext, and one that can be composite.

I guess this would semantically correspond to the "component" and
"container" versions that I mentioned above?

> A TaskContext can be implemented by a composite, in which case clones of
> the unconnected inputs and outputs of the composite are promoted to the
> TaskContext and the TaskContext delegates its "computation" to the
> composite.
> Ports inside a composite all run in the same thread and hence do not
> need to be thread-safe; therefore, a simplified port can be used.
>
> Let me know what you think.

I just did :-)

> Cheers, Theo

Herman

>
> 2011/12/12 Peter Soetens <peter [..] ...>:
>> On Mon, Dec 12, 2011 at 1:40 PM, Markus Klotzbuecher
>> <markus [dot] klotzbuecher [..] ...> wrote:
>>> Hi,
>>>
>>> We are working towards composite components and are trying to promote
>>> ports from elementary components to the interface of a composite
>>> component (itself just a TaskContext).
>>>
>>> Adding one port to two TaskContexts is not (yet) officially supported
>>> bu the RTT model, although it works well out of the box (kudos to
>>> Peter!)  The only limitation (applying only to for EventPorts) is that
>>> it only wakes up the last Component to which the port was added and
>>> not all.
>>>
>>> See the attached Lua script for test.  Having all components being
>>> woken up would be requirement for implementing such composite
>>> components. Can someone estimate efforts and intrusiveness of such a
>>> change?
>>
>> All the logic is in PortInterface.cpp/hpp and can DataFlowInterface*
>> iface be trivially replaced by a std::vector<DataFlowInterface> iface.
>> Next InputPort.cpp wakes up all in the list 'iface'. getInterface()
>> would return the first DataFlowInterface to which the port was added,
>> ie, the 'real' owner of the port. You could add a method
>> 'getInterfaces()' to return all interfaces, in case you want to
>> introspect a port of a composite in order to find out if it is present
>> in multiple interfaces.
>>
>> This change would imo not break the rest of the software which relies
>> on 'getInterface()'. We're adding some heap to each port though.
>>
>> Peter