RTT::Events

Hi,

I'm having problems with making the RTT::Event class send/receive
commands over CAN.
I have a EventProxy derived from the signal<Signature> template
implementing a RTT::LocalCommand with a overridden operator()(). In this
operator I do:

void CLocalEventProxy<void(void)>::operator()()
{

	if(m_El)
		m_El->sendEvent(m_Id); //--> send a CAN message.
	this->emit();

}

Where I receive the CAN message I just call emit() thus preventing an
other CAN message being sent.

Using this construction I can fire an event over the CAN network from a
proxy to a server. It is the other way around I can't get away with.

For Commands and DataPorts I change the implementation to a
server-implementation if they are in the interface of the TaskContex's I
want to export over CAN (using commands() and ports()). I was hoping I
could do the same thing with Events. The problem is that the objects
stored in the EventService, returned by events(), are already
implementations. So I can't just change them can I? Or are the shared
pointers smart enough to handle this?

Kind regards,
Sander Vandenbroucke

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

RTT::Events

On Monday 14 May 2007 11:50:06 Vandenbroucke Sander wrote:
> Hi,
>
> I'm having problems with making the RTT::Event class send/receive
> commands over CAN.
> I have a EventProxy derived from the signal<Signature> template
> implementing a RTT::LocalCommand with a overridden operator()(). In this
> operator I do:
>
> void CLocalEventProxy<void(void)>::operator()()
> {
> if(m_El)
> m_El->sendEvent(m_Id); //--> send a CAN message.
> this->emit();
> }

Interesting, using a commandi for emiting events.

>
> Where I receive the CAN message I just call emit() thus preventing an
> other CAN message being sent.
>
> Using this construction I can fire an event over the CAN network from a
> proxy to a server. It is the other way around I can't get away with.
>
> For Commands and DataPorts I change the implementation to a
> server-implementation if they are in the interface of the TaskContex's I
> want to export over CAN (using commands() and ports()). I was hoping I
> could do the same thing with Events. The problem is that the objects
> stored in the EventService, returned by events(), are already
> implementations. So I can't just change them can I? Or are the shared
> pointers smart enough to handle this?

I'll have to look into this. You can use Event<T>::operator= to assign a new
implementation before adding the event to the EventService (before
events()->addEvent( &e ) or after you get the Event (this completely removes
the old function then) and there is also an Event constructor which accepts
the implementation. You may change the implementation of an Event (about) at
any time. I don't fully understand your case yet though.

Do you need both local and remote delivery implementations of the Event ?

Peter

RE: RTT::Events

> >
> > void CLocalEventProxy<void(void)>::operator()()
> > {
> > if(m_El)
> > m_El->sendEvent(m_Id); //--> send a CAN message.
> > this->emit();
> > }
>
> Interesting, using a commandi for emiting events.
>
It is not a command, it is a plain c++ function.

>
> I'll have to look into this. You can use Event<T>::operator= to
assign a
> new
> implementation before adding the event to the EventService (before
> events()->addEvent( &e ) or after you get the Event (this completely
> removes
> the old function then) and there is also an Event constructor which
> accepts
> the implementation. You may change the implementation of an Event
(about)
> at
> any time. I don't fully understand your case yet though.
>
Ok, I'll try to clarify.

For real-time communication between components on different platforms I
use a CAN network. Platform A has Component1 with its peer a proxy of
Component2, platform B just has a server jacket for Component2 and a
actual Component2. A proxy is a lightweight equivalent of a component
that just forwards the Command/Ports/Events to/from the CAN network. The
server jacket is pretty much the same as a Proxy except that it is
constructed in run-time. The server jacket inspects a component and
creates access points for the Commands/Ports/Events to the CAN network.
In the end the Proxy and server jacket connect Component1 and Component2
as if they where on the same platform.

It is in the server jacket I'm in trouble. I can get the events of
Component2 but I have to change their implementation in run-time!

> Do you need both local and remote delivery implementations of the
Event ?
>
Yes, I think I do. Lets say there are three components, two on one
platform a third on a second platform. A component on the first platform
emits an Event both other components are interested in. Then the Event
should be emitted on both platforms.

Sander.

RTT::Events

On Monday 14 May 2007 14:13:27 Vandenbroucke Sander wrote:
> Ok, I'll try to clarify.
>
> For real-time communication between components on different platforms I
> use a CAN network. Platform A has Component1 with its peer a proxy of
> Component2, platform B just has a server jacket for Component2 and a
> actual Component2. A proxy is a lightweight equivalent of a component
> that just forwards the Commandi/Ports/Events to/from the CAN network. The
> server jacket is pretty much the same as a Proxy except that it is
> constructed in run-time. The server jacket inspects a component and
> creates access points for the Commands/Ports/Events to the CAN network.
> In the end the Proxy and server jacket connect Component1 and Component2
> as if they where on the same platform.
>
> It is in the server jacket I'm in trouble. I can get the events of
> Component2 but I have to change their implementation in run-time!

So if a component gets served, its events should start broadcasting on your
CAN bus, but if not, it should only broadcast locally.

Doesn't this resemble DataPorts ? Or don't you publish/push data porti changes
on your bus (only pull model) ?

The only solution I see for now is to initialise your served component's
events with an implementation that always tries to publish the event on the
CAN bus, in fact, the Proxy implementation.

The broadcast nature of ports and events cause this problem and it can only be
solved by installing an implementation which does the broadcast locally and
on the network.

Peter

RE: RTT::Events

> So if a component gets served, its events should start broadcasting on
> your
> CAN bus, but if not, it should only broadcast locally.
>
Yes.

> Doesn't this resemble DataPorts ?
Yes, but changing the implementation afterwards for DataPorts is easy.

>Or don't you publish/push data porti
> changes
> on your bus (only pull model) ?
>
Nope, it't push/pull.

> The only solution I see for now is to initialise your served
component's
> events with an implementation that always tries to publish the event
on
> the
> CAN bus, in fact, the Proxy implementation.
>
After goofing around with the EventService and changing implementation
(which didn't work) I tend to agree.

I tried:
boost::shared_ptr<RTT::ActionInterface> EvntImpl =
Tc->events()->getEvent<void(void)>((*i)); //-> (*i) is a name of an
Event.

boost::shared_ptr<RTT::detail::LocalEvent<void(void)> > EvntVoid;
boost::shared_ptr<RTT::detail::LocalEvent<void(V_U32)> > EvntVU32;
if((EvntVoid =
boost::dynamic_pointer_cast<RTT::detail::LocalEvent<void(void)>
>(EvntImpl))!=0)
{

	//Now change its implementation.
	EvntImpl = EventProxy<void(void)>(Tc->getName(), (*i));

}
But this seems to leave the original implementation in place for the
Event object in my served component.

> The broadcast nature of ports and events cause this problem and it can
> only be
> solved by installing an implementation which does the broadcast
locally
> and
> on the network.
>
Indeed. I'll try that tomorrow.

Sander.

RTT::Events

On Monday 14 May 2007 16:48:15 Vandenbroucke Sander wrote:
>
> After goofing around with the EventService and changing implementation
> (which didn't work) I tend to agree.
>
> I tried:
> boost::shared_ptr<RTT::ActionInterface> EvntImpl =
> Tc->events()->getEvent<void(void)>((*i)); //-> (*i) is a name of an
> Event.
>
> boost::shared_ptr<RTT::detail::LocalEvent<void(void)> > EvntVoid;
> boost::shared_ptr<RTT::detail::LocalEvent<void(V_U32)> > EvntVU32;
> if((EvntVoid =
> boost::dynamic_pointer_cast<RTT::detail::LocalEvent<void(void)>
>
> >(EvntImpl))!=0)
>
> {
> //Now change its implementation.
> EvntImpl = EventProxy<void(void)>(Tc->getName(), (*i));
> }
> But this seems to leave the original implementation in place for the
> Event object in my served component.

Indeed. You only changed the local pointer, nothing in the EventService. You
can 'hack' around this by doing:

if((EvntVoid =

 boost::dynamic_pointer_cast<RTT::detail::LocalEvent<void(void)>

(EvntImpl))!=0)
{

        // first remove the old event
	Tc->events()->remove( (*i) );
	//Now change its implementation.         
 	EvntVoid = EventProxy<void(void)>(Tc->getName(), (*i));
        // Install new event.
        Tc->events()->addEvent( EvntVoid );

}

This solution removes any previously added event handler though.

Peter

RE: RTT::Events

>
> Indeed. You only changed the local pointer, nothing in the
EventService.
> You
> can 'hack' around this by doing:
>
> if((EvntVoid =
> boost::dynamic_pointer_cast<RTT::detail::LocalEvent<void(void)>
> (EvntImpl))!=0)
> {
> // first remove the old event
> Tc->events()->remove( (*i) );
> //Now change its implementation.
> EvntVoid = EventProxy<void(void)>(Tc->getName(), (*i));
> // Install new event.
> Tc->events()->addEvent( EvntVoid );
> }
>
> This solution removes any previously added event handler though.
>

Is there any way to copy them?

Sander.

RE: RTT::Events

Quoting Vandenbroucke Sander <Sander.Vandenbroucke at vandewiele [dot] com>:
>>
>> This solution removes any previously added event handler though.
>>
>
> Is there any way to copy them?
>

That was a though question :-) Technically, the 'connections' list can
be copied into the new implementation as long as the new implementation
uses the same connection type. But the current class is not foreseen on
this scenario. First, when you delete the old implementation, it
destroys all the existing connections. Second, the connection list is a
protected member, thus another implementation can not access it. Third,
each connection object holds a pointer to its event implementation,
which must be changed as well when the implementation changes. The
easiest solution would be to clone() each connection of the connection
list into a new event and provide clone() with the pointer to the new
implementation.

All these issues can be solved by adding the appropriate member
functions, but I don't know if you can wait until RTT 1.4.0 :-)

If this is urgent, I can see if I can figure out a quick patch and test case.

Peter