Home › Forum › SOFA › Using SOFA › [SOLVED] How to send data to SOFA through socket ?
- This topic has 5 replies, 3 voices, and was last updated 7 years, 9 months ago by
luibass92.
-
AuthorPosts
-
25 November 2016 at 11:49 #7990
luibass92
BlockedHi everyone,
finally I’ve completed the creation of my hand with kinematics, meshes, collision detection and everything seems to work properly.
Now I have to do another step in my project, I would like to send some data (joints rotation value) from an external server (that I already have and it works fine) to the SOFA scene and use these data in order to move the hand’s joints in real-time.
I have a plugin that should read the data sent by the server and I’ve added it in the scene in this way:
<Node dt="0.01" gravity="0 0 0" name="root"> <RequiredPlugin pluginName="MyPlugin" /> . . .
and the loading goes fine.
Then I have:
<Node name="joints"> <MyClass name="jt" template="Vec3d"/> </Node>
And forward in the code I have:
<ArticulatedHierarchyContainer q1="@../joints/jt/q1"/>
The result is that when I click on “Animate” button I can read on SOFA’s terminal the correct value passed by the server, but then SOFA crashes and I can’t do anything more…
I’m sure that the code that causes the crash is:
<Node name="joints"> <MyClass name="jt" template="Vec3d"/> </Node>
Do you have some tips?
Cheers,
Luigi25 November 2016 at 17:37 #7997Guillaume
KeymasterHi Luigi,
Your link seems malformed.
jt
is a Component and not a Node so you can’t dojt/q1
.Did you mean
<ArticulatedHierarchyContainer q1="@../joints/jt.q1"/>
?Cheers,
Guillaume.25 November 2016 at 17:49 #7998luibass92
BlockedYes, I think you are right. Anyway the problem is caused by this part of the code:
<Node name="joints"> <joints name="jt" template="Vec3d"/> </Node>
(joints is the new name of MyClass)
I’ve tried to comment it and the simulation doesn’t crash anymore.
In particular in joints.cpp I found out that the function:r = read( socket_in, buf, sizeof(buf) );
is the problem (I can’t figure out why)…
The complete code of the joints.cpp file is the following (it is just a client):
#define JOINTS_CPP #include "joints.h" #include <sofa/core/ObjectFactory.h> #include <sofa/defaulttype/Vec3Types.h> using namespace std; typedef struct Giunti { double q1; }Giunti; namespace sofa { namespace component { namespace behaviormodel { template <class DataTypes> joints<DataTypes>::joints() :q1(initData(&q1,"q1", "Giunto 1")) { this->f_listening.setValue(true); } template <class DataTypes> joints<DataTypes>::~joints() { } template <class DataTypes> void joints<DataTypes>::init() { std::cout << " init ok " << std::endl; } template <class DataTypes> void joints<DataTypes>::reinit() { } template <class DataTypes> void joints<DataTypes>::handleEvent(sofa::core::objectmodel::Event* event) { if (dynamic_cast<simulation::AnimateBeginEvent*>(event)) { int t = (int)this->getContext()->getTime(); int socket_in; listener_socket( 9090, &socket_in ); Giunti giunti_read; int r, bufflen = 16; char buf[bufflen]; int slen, rlen; sockaddr_in si_other; r = read( socket_in, buf, sizeof(buf) ); //-----> crash SOFA cout << "letto: " << r << endl; giunti_read = *(( Giunti *)(buf)); q1.setValue(giunti_read.q1); cout << " q1 = " << q1 << endl; } } #ifndef SOFA_FLOAT using sofa::defaulttype::Vec3dTypes; #endif #ifndef SOFA_DOUBLE using sofa::defaulttype::Vec3fTypes; #endif SOFA_DECL_CLASS(joints) int jointsClass = core::RegisterObject("jts") #ifndef SOFA_FLOAT .add< joints<Vec3dTypes> >() #endif #ifndef SOFA_DOUBLE .add< joints<Vec3fTypes> >() #endif ; #ifndef SOFA_FLOAT template class joints<Vec3dTypes>; //template class EulerianFluidModel<Vec2dTypes>; #endif #ifndef SOFA_DOUBLE template class joints<Vec3fTypes>; //template class EulerianFluidModel<Vec2fTypes>; #endif } //behaviormodel } //component } //sofa
27 November 2016 at 20:09 #7999luibass92
BlockedHey Guillaume,
I’ve solved this issue, I don’t know if I should post the code here because it’s quite long…
Anyway the problem is caused by the fact that in my .ccp file I have:void joints<DataTypes>::handleEvent(sofa::core::objectmodel::Event* event) { if (dynamic_cast<simulation::AnimateBeginEvent*>(event)){ // All the code here for the communication through socket (client side) } }
that is inside a “big loop” since the moment I click on the Animate button.
So the software crashes because it tries to recreate for each loop a socket for the communication, so I just added an “if” statement that imply the creation of the socket just one time.
In this way it runs and the communication works if I run the server first.I don’t know why, if I try to run the plugin before it continue to crash…
Cheers,
Luigi29 November 2016 at 00:38 #8005Hugo
KeymasterHi Luigi,
yes please, for other users it might be useful.
can you share the part that solved the issue ? and you can also set this discussion as solved.Cheers,
Hugo
29 November 2016 at 10:29 #8006luibass92
BlockedOK, this is the code that works.
template <class DataTypes> void joints<DataTypes>::handleEvent(sofa::core::objectmodel::Event* event) { if (dynamic_cast<simulation::AnimateBeginEvent*>(event)){ Joints giunti_read; //This is a struct made of 20 doubles ("giunti" means //"joints" in italian :D ) int r, bufflen = 160; char buf[bufflen]; if(socket_in==0){ //This if solved the issue, now the socket is created //just one time socket_create_UDP_Recipient( socket_in, 9090 ); //This is a typical client cout << socket_in << endl; } r = read( socket_in, buf, sizeof(buf) ); cout << "read: " << r << endl; giunti_read = *(( Joints *)(buf)); J1.setValue(giunti_read.J1); J2.setValue(giunti_read.J2); J3.setValue(giunti_read.J3); J4.setValue(giunti_read.J4); J5.setValue(giunti_read.J5); J6.setValue(giunti_read.J6); J7.setValue(giunti_read.J7); J8.setValue(giunti_read.J8); J9.setValue(giunti_read.J9); J10.setValue(giunti_read.J10); J11.setValue(giunti_read.J11); J12.setValue(giunti_read.J12); J13.setValue(giunti_read.J13); J14.setValue(giunti_read.J14); J15.setValue(giunti_read.J15); J16.setValue(giunti_read.J16); J17.setValue(giunti_read.J17); J18.setValue(giunti_read.J18); J19.setValue(giunti_read.J19); J20.setValue(giunti_read.J20); cout << " J1 = " << J1 << endl; cout << " J2 = " << J2 << endl; cout << " J3 = " << J3 << endl; cout << " J4 = " << J4 << endl; cout << " J5 = " << J5 << endl; cout << " J6 = " << J6 << endl; cout << " J7 = " << J7 << endl; cout << " J8 = " << J8 << endl; cout << " J9 = " << J9 << endl; cout << " J10 = " << J10 << endl; cout << " J11 = " << J11 << endl; cout << " J12 = " << J12 << endl; cout << " J13 = " << J13 << endl; cout << " J14 = " << J14 << endl; cout << " J15 = " << J15 << endl; cout << " J16 = " << J16 << endl; cout << " J17 = " << J17 << endl; cout << " J18 = " << J18 << endl; cout << " J19 = " << J19 << endl; cout << " J20 = " << J20 << endl; cout << endl; }
Note that this plugins works only if the server is already in running mode. Otherwise crashes.
Hugo and Guillaume I’ve posted another question always about this project, it’s the final part and I don’t know how to use these data J1…J20 in my scene. If you read can you help me please (this is the post https://www.sofa-framework.org/community/forum/topic/how-to-use-external-data-in-sofa/)?
Thanks and cheers,
Luigi -
AuthorPosts
- You must be logged in to reply to this topic.