Hi, <br>
<br>
I&#39;ve installed Spread3.17.3 and am using it in a multi-agent robotics
application where each robot communicates with a peer using Spread
messaging. I&#39;m having this reoccurring problem that I just cannot
figure out:<br>
<br>
On the sender side, I have a single agent first connect to the Spread
Daemon, then join a group, and then after joining the group, broadcast
position information and a set of 361 data points (that come from a
laser scanner) --encoded appropriately in a long character string-- to
the group in a neverending for loop. <br>
<br>
On the receiver side, I join the group and receive the long string of
data, parse it and plot it through some openGL program I wrote. <br>
<br>
When i test my program in simulation, I have the daemon, sender, and
receiver all running on my local machine through different terminals.
I&#39;m noticing that after about ~1500 messages are sent from the sender,
the sender program quits with the following message:<br>
<br>
SP_error: (-8) Connection closed by spread<br>
<br>
And it&#39;s not always after the same number of messages sent that the
program quits. Sometimes, it send about 1553 messages or 1519 messages
and so forth and quits. <br>
<br>
Does anyone know why this is? I&#39;m guessing it has something to do with
a buffer being filled or something but I cannot figure it out. I&#39;ve
attached the sender code that I&#39;m using. <br>
<br>
Thanks,<br>
<br>
Jeremy<br>
<br>
<br>
///////////////////////////////////////////////////<br>
<br>
#include &lt;libplayerc++/playerc++.h&gt;<br>
#include &lt;iostream&gt;<br>
#include &lt;vector.h&gt;<br>
#include &quot;args.h&quot;<br>
#include &lt;sp.h&gt;<br>
<br>
#define MAX_MESSLEN&nbsp;&nbsp; 102400<br>
<br>
struct Vertex {<br>
double x;<br>
double y;<br>
};<br>
<br>
static&nbsp; mailbox Mbox;<br>
static&nbsp;&nbsp;&nbsp; char&nbsp;&nbsp;&nbsp; User[80];<br>
static&nbsp; char&nbsp;&nbsp;&nbsp; Spread_name[80];<br>
static&nbsp; char&nbsp;&nbsp;&nbsp; Private_group[MAX_GROUP_NAME];<br>
<br>
int main(int argc, char **argv)<br>
{<br>
&nbsp; parse_args(argc,argv);<br>
<br>
&nbsp; // we throw exceptions on creation if we fail<br>
&nbsp; try<br>
&nbsp; {<br>
&nbsp;&nbsp;&nbsp; using namespace PlayerCc;<br>
<br>
&nbsp;&nbsp;&nbsp; PlayerClient robot(gHostname, gPort);<br>
&nbsp;&nbsp;&nbsp; Position2dProxy pp(&amp;robot, gIndex);<br>
&nbsp;&nbsp;&nbsp; LaserProxy lp(&amp;robot, gIndex);<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; robot &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; //pp.SetMotorEnable (true);<br>
&nbsp;&nbsp;&nbsp; pp.SetOdometry(8,0,M_PI/2);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; double RADIUS = 8;<br>
&nbsp;&nbsp;&nbsp; double DIST_THRESH= 1; //1 meter<br>
&nbsp;&nbsp;&nbsp; double newspeed, newturnrate, range_dist;<br>
&nbsp;&nbsp;&nbsp; double pose_x, pose_y, pose_yaw;<br>
&nbsp;&nbsp;&nbsp; int FLAG;<br>
&nbsp;&nbsp;&nbsp; int START_DATA_GATHER=1;<br>
&nbsp;&nbsp;&nbsp; int STOP_DATA_GATHER=0;<br>
&nbsp;&nbsp;&nbsp; int ret;<br>
&nbsp;&nbsp;&nbsp; int numpts;<br>
&nbsp;&nbsp;&nbsp; char group[80];<br>
&nbsp;&nbsp;&nbsp; char name[80];<br>
&nbsp;&nbsp;&nbsp; vector&lt;Vertex&gt; v_pts;<br>
&nbsp;&nbsp;&nbsp; Vertex v_sensor, v_robot, v_global;<br>
&nbsp;&nbsp;&nbsp; char* vBuffer = new char[MAX_MESSLEN];&nbsp; <br>
&nbsp;&nbsp;&nbsp; sp_time test_timeout;<br>
<br>
&nbsp;&nbsp;&nbsp; test_timeout.sec = 5;<br>
&nbsp;&nbsp;&nbsp; test_timeout.usec = 0;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; cout &lt;&lt; &quot;Please enter your user name: &quot; &lt;&lt; endl;<br>
&nbsp;&nbsp;&nbsp; cin &gt;&gt; User;<br>
<br>
&nbsp;&nbsp;&nbsp; cout &lt;&lt; &quot;Please enter Spread_name-- typing &#39;n&#39;
will set to default (i.e. 4803@localhost): &quot; &lt;&lt; endl;<br>
&nbsp;&nbsp;&nbsp; cin &gt;&gt; name;<br>
&nbsp;&nbsp;&nbsp; if(!strcmp(name,&quot;n&quot;))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; strcpy(Spread_name, &quot;4803@localhost&quot;);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; //ret = SP_connect_timeout( Spread_name, User, 0, 1, &amp;Mbox, Private_group, test_timeout );<br>
&nbsp;&nbsp;&nbsp; ret = SP_connect( Spread_name, User, 0, 1, &amp;Mbox, Private_group );<br>
&nbsp;&nbsp;&nbsp; if( ret != ACCEPT_SESSION ) <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; SP_error( ret );<br>
&nbsp;&nbsp;&nbsp; exit(0);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; printf(&quot;Private_group is: %s\n&quot;, Private_group);<br>
&nbsp;&nbsp;&nbsp; printf(&quot;User: connected to %s with private group %s \n&quot;, Spread_name, Private_group );<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; cout &lt;&lt; &quot;Please enter group to join: &quot; &lt;&lt; endl;<br>
&nbsp;&nbsp;&nbsp; cin &gt;&gt; group;<br>
&nbsp;&nbsp;&nbsp; ret = SP_join( Mbox, group );<br>
&nbsp;&nbsp;&nbsp; if( ret &lt; 0 ) SP_error( ret );<br>
<br>
&nbsp;&nbsp;&nbsp; int count =0;<br>
&nbsp;&nbsp;&nbsp; for(;;)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; // this blocks until new data comes; 10Hz by default<br>
&nbsp;&nbsp;&nbsp; robot.Read();<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; newspeed = 1;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; newturnrate = 1/RADIUS;<br>
&nbsp;&nbsp;&nbsp; v_pts.clear();<br>
<br>
&nbsp;&nbsp;&nbsp; pose_x = pp.GetXPos();<br>
&nbsp;&nbsp;&nbsp; pose_y = pp.GetYPos();<br>
&nbsp;&nbsp;&nbsp; pose_yaw = pp.GetYaw();<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; //printf(&quot;lp.GetCount(): %u\n&quot;,lp.GetCount());<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; if(lp.GetCount()&gt;0)<br>
&nbsp;&nbsp;&nbsp; &nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(uint i=0;i&lt;lp.GetCount()-1;i++)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; range_dist = lp.GetRange(i+1)-lp.GetRange(i);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(FLAG==START_DATA_GATHER)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //these points are in the sensor frame<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v_sensor.x = lp.GetRange(i)*cos(lp.GetBearing(i));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v_sensor.y = lp.GetRange(i)*sin(lp.GetBearing(i));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //these points are now in the robot frame<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v_robot.x = cos(M_PI/2)*v_sensor.x - sin(M_PI/2)*v_sensor.y;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v_robot.y = sin(M_PI/2)*v_sensor.x + cos(M_PI/2)*v_sensor.y;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //these points are now in the global frame<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v_global.x =
cos(pp.GetYaw())*v_robot.x - sin(pp.GetYaw())*v_robot.y + pp.GetXPos();<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v_global.y =
sin(pp.GetYaw())*v_robot.x + cos(pp.GetYaw())*v_robot.y + pp.GetYPos();<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v_pts.push_back(v_global);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(range_dist&lt;-1*DIST_THRESH)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; FLAG = START_DATA_GATHER;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if(range_dist &gt; DIST_THRESH)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; FLAG = STOP_DATA_GATHER;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp; }&nbsp;&nbsp;&nbsp; <br>
<br>
&nbsp;&nbsp;&nbsp; char* pBuffer = vBuffer;<br>
&nbsp;&nbsp;&nbsp; int bytesToSend = 0;<br>
&nbsp;&nbsp;&nbsp; numpts = v_pts.size();<br>
<br>
&nbsp;&nbsp;&nbsp; memcpy(pBuffer, &amp;pose_x, sizeof(double));<br>
&nbsp;&nbsp;&nbsp; pBuffer += sizeof(double);<br>
&nbsp;&nbsp;&nbsp; bytesToSend += sizeof(double);<br>
<br>
&nbsp;&nbsp;&nbsp; memcpy(pBuffer, &amp;pose_y, sizeof(double));<br>
&nbsp;&nbsp;&nbsp; pBuffer += sizeof(double);<br>
&nbsp;&nbsp;&nbsp; bytesToSend += sizeof(double);<br>
<br>
&nbsp;&nbsp;&nbsp; memcpy(pBuffer, &amp;pose_yaw, sizeof(double));<br>
&nbsp;&nbsp;&nbsp; pBuffer += sizeof(double);<br>
&nbsp;&nbsp;&nbsp; bytesToSend += sizeof(double);<br>
<br>
&nbsp;&nbsp;&nbsp; memcpy(pBuffer, &amp;numpts, sizeof(int));<br>
&nbsp;&nbsp;&nbsp; pBuffer += sizeof(int);<br>
&nbsp;&nbsp;&nbsp; bytesToSend += sizeof(int);<br>
<br>
&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;numpts;i++)<br>
&nbsp;&nbsp;&nbsp; &nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //copying v object into the location pointed to by pBuffer<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; memcpy(pBuffer, (char*)&amp;v_pts[i], sizeof(Vertex));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pBuffer += sizeof(Vertex);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; bytesToSend += sizeof(Vertex);<br>
&nbsp;&nbsp;&nbsp; &nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; //use SP_multigroup_multicast if sending to more than one group<br>
&nbsp;&nbsp;&nbsp; //printf(&quot;bytesToSend: %u \n&quot;, bytesToSend);<br>
&nbsp;&nbsp;&nbsp; ret= SP_multicast( Mbox, SAFE_MESS, (const char*) group, 1, bytesToSend, vBuffer );<br>
<br>
&nbsp;&nbsp;&nbsp; if( ret &lt; 0 )<br>
&nbsp;&nbsp;&nbsp; &nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; SP_error( ret );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;quitting because of spread \n&quot;);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(0);<br>
&nbsp;&nbsp;&nbsp; &nbsp; }<br>
<br>
<br>
&nbsp;&nbsp;&nbsp; // write commands to robot<br>
&nbsp;&nbsp;&nbsp; pp.SetSpeed(newspeed, newturnrate);<br>
&nbsp;&nbsp;&nbsp; //printf(&quot;pp.XPos(): %f&nbsp;&nbsp; pp.YPos():
%f&nbsp;&nbsp; pp.Yaw(): %f&nbsp;
\n&quot;,pp.GetXPos(),pp.GetYPos(),pp.GetYaw());<br>
&nbsp;&nbsp;&nbsp; count++;<br>
&nbsp;&nbsp;&nbsp; printf(&quot;messages sent: %d\n&quot;, count);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp; }<br>
&nbsp; catch (PlayerCc::PlayerError e)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cerr &lt;&lt; e &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>