Home › Forum › SOFA › Programming with SOFA › SofaPython3 signal catching
Tagged: 64_bits, Linux_ubuntu, Plugin_other, SOFA_other
- This topic has 2 replies, 2 voices, and was last updated 3 years, 9 months ago by
Damien Marchal.
-
AuthorPosts
-
4 December 2020 at 13:39 #17900
AO
BlockedHello,
I have a scene that roughly looks and works like this :
SceneSince each solver is working on a different object I need to be able to discriminate the sender in my python script. Is there a (clean ?) way to do so ?
I tried to find informations from the value argument in the
def onDoStuffEvent(self, value)
function but it does not provide anything relevant.Is it possible to add a pointer of the sender in the value argument ?
Thanks for your help,
Alban.7 December 2020 at 18:42 #17969AO
BlockedAlright, I managed to find a solution to the problem but it’s clearly not what should be done in the long term. I hope at some point we will be able to get the original sender as a data from the value argument.
An event class is often declared as such :
class SOFA_SIMULATION_CORE_API MyEvent : public sofa::core::objectmodel::Event { public: SOFA_EVENT_H( MyEvent ) MyEvent( SReal dt ); MyEvent() {} void setDt(SReal sdt){dt = sdt;} ~MyEvent() override; SReal getDt() const { return dt; } inline static const char* GetClassName() { return "MyEvent"; } protected: SReal dt; };
The point of interest here is the macro
SOFA_EVENT_H( MyEvent )
which defines a bunch of functions. One of themgetClassName()
defines the name of the event sent to each desired components.
The only way (that I found atleast) to transfer some information along the event propagation is to add it to actual the event name.In my case I only want to give the id of the component that sent the signal but it can easily be adapted to suit your demand.
We can explicit the macro in order to only change the
getClassName
function (and not theGetClassName
one):class SOFA_SIMULATION_CORE_API MyEvent : public sofa::core::objectmodel::Event { public: virtual size_t getEventTypeIndex() const override { return MyEvent::s_eventTypeIndex; } static bool checkEventType( const Event* event ) { return event->getEventTypeIndex() == MyEvent::s_eventTypeIndex; } virtual const char* getClassName() const override {return name.c_str();} MyEvent(SReal dt, uint id=0): sofa::core::objectmodel::Event(), dt(dt) { name = std::string("MyEvent_").append(std::to_string(id)).c_str(); } MyEvent() {} void setDt(SReal sdt){dt = sdt;} ~MyEvent() override; SReal getDt() const { return dt; } inline static const char* GetClassName() { return "MyEvent"; } protected: SReal dt; static const size_t s_eventTypeIndex; std::string name; };
Now from the python script we can catch any event from
def onEvent(self, value)
.
Previously when printing value you’ll get something like this:
{‘type’: ‘MyEvent’, ‘isHandled’: False}But with the modification presented above the display will look a tiny bit different:
{‘type’: ‘MyEvent_0’, ‘isHandled’: False}From this in your python script you can write:
def onEvent(self, value): [event, id] = value['type'].split('_') if event == "the name of the event": doStuff(int(id))
or you can specify each
def onMyEvent_id(self, value)
if you need to.TLDR : Remove the macro, change the name of the event and catch it with onEvent
Alban.
9 December 2020 at 10:40 #17981Damien Marchal
BlockedHello,
This is an interesting topic. Despite being a working solution I think hijacking the class name is definitely not the way to go. In Sofa the Event class was not design to have an “emitter” information. But a subclass of Event called ScriptEvent is specifically doing that. I don’t know if the ScriptEvent is usable in your case and if it is already exposed in python but if this is not the case I would be a nice addendum and pull-request to Sofapython3.
-
AuthorPosts
- You must be logged in to reply to this topic.