Streaming Individual Markers

NatNet, VRPN, TrackD, and Plugins
heath789
Posts: 41
Joined: Wed Aug 10, 2011 7:42 am

Re: Streaming Individual Markers

Post by heath789 »

Morgan,

Thanks for the help. I am writing the overall code in Matlab, I am just using java within matlab as a way of receiving the multicast data.

As a specific reference, I am looking at the code here, from the depacketization example under the Unpack function:



// marker data
int nMarkers = 0; memcpy(&nMarkers, ptr, 4); ptr += 4;
printf("Marker Count : %d\n", nMarkers);

for(int j=0; j < nMarkers; j++)
{
float x = 0; memcpy(&x, ptr, 4); ptr += 4;
float y = 0; memcpy(&y, ptr, 4); ptr += 4;
float z = 0; memcpy(&z, ptr, 4); ptr += 4;
printf("\tMarker %d : [x=%3.2f,y=%3.2f,z=%3.2f]\n",j,x,y,z);
}


So with the stream I received, my first X position is somehow garnered from the following array: [-71 50 26 -60] which is a java type byte array (8-bit integers). I have looked at C references for the memcpy function and I cannot see how it is receiving 8bit integer values and outputting a float %3.2f value.

It doesn't seem that these can be manipulated in the normal way to get floating values, is there a way that I could do this manually?
morgan
NaturalPoint Employee
NaturalPoint Employee
Posts: 199
Joined: Tue Jun 24, 2008 2:01 pm
Location: Corvallis, OR, USA
Contact:

Re: Streaming Individual Markers

Post by morgan »

In C/C++, floats and ints are both 32 bit values.

In the example:

ptr is an array of char (1 byte per char)
x is a float (4 bytes)

the actual value is a 4 byte float (stored sequentialy in memory as 4 chars)


so:

float x = 0; memcpy(&x, ptr, 4); ptr += 4;

copies 4 bytes from the char array into the 4 byte float:

x : 00000000 00000000 00000000 00000000
ptr : ptr[0] ptr[1] ptr[2] ptr[3]

Did the Java byte unpack not work?
heath789
Posts: 41
Joined: Wed Aug 10, 2011 7:42 am

Re: Streaming Individual Markers

Post by heath789 »

This java code does seem to work, however I get erroneous float values with very high exponents.

Assuming the byte array for the X value of marker 1 is something like [A B C D] where these are values from -128 to 127, values C and D seem to stay constant from frame to frame while values A and B fluctuate, all with the marker standing still.

Could this be a problem with endianness? Maybe somehow the bytes A and B represent small decimal values of fluctuation. Regardless, the floats returned vary quite a bit from frame to frame (like 10s of orders of magnitude) and not the nearly constant ~1 or 2 meters I'm looking for.

Thanks for all your help.
morgan
NaturalPoint Employee
NaturalPoint Employee
Posts: 199
Joined: Tue Jun 24, 2008 2:01 pm
Location: Corvallis, OR, USA
Contact:

Re: Streaming Individual Markers

Post by morgan »

yes - sorry - the byte order is little endian. it looks like java's ByteBuffer defaults to big endian, which would reverse the bytes and show the behavior your seeing.

if you're using ByteBuffer you can change it's order easily using:

Code: Select all

ByteBuffer buffer = ...
buffer.order(ByteOrder.LITTLE_ENDIAN);
or just swizzle them yourself.
heath789
Posts: 41
Joined: Wed Aug 10, 2011 7:42 am

Re: Streaming Individual Markers

Post by heath789 »

Morgan,

I switched them myself after no luck with ByteOrder and it seems to work very well. I didn't know I could switch the integers, I thought it had to be the bits (maybe gives the same thing).

Once I get through the code and can read in the data and process it I can post some samples for others since I've had to make some changes to the syntax to have things work with Matlab.

Thanks again for all your help.
morgan
NaturalPoint Employee
NaturalPoint Employee
Posts: 199
Joined: Tue Jun 24, 2008 2:01 pm
Location: Corvallis, OR, USA
Contact:

Re: Streaming Individual Markers

Post by morgan »

Great! Good to know about the byte order under Java - we'll update the docs to reflect that.

If you can share your Java / Matlab code that would be great! I'm sure we have some other custoemrs who would greatly benefit.

We're also happy to test it out here and include it in a "3rd party contributions" section of the NatNet SDK.

best regards,

Morgan
heath789
Posts: 41
Joined: Wed Aug 10, 2011 7:42 am

Re: Streaming Individual Markers

Post by heath789 »

My sample code for streaming from Arena to MATLAB using Java. Not sure what place is best for this, so please feel free to move it if necessary. This also might work with Tracking Tools but is untested.

Code: Select all


%For accessing Arena's multicast stream using Java within MATLAB. Tested
%with MATLAB R2009b. Objects and methods are well documented online and
%this is a method of employing them by using the commands within MATLAB.

%This code may be easliy improved upon and was used as a first pass and
%proof of concept. Use of a loop will be necessary to receive multiple
%packets as they are streamed by Arena. Also, the stream rate might need to
%be lowered depending on how fast this code executes on a given machine.

%create a multicast connection by using Arena's data port and multicast
%address:
Socket = java.net.MulticastSocket(1511);
group = java.net.InetAddress.getByName('239.255.42.99');
Socket.joinGroup(group);

%create a preallocated variable of int8 type. This will be passed to the
%java object which is expecting a variable of type 'byte'. Int8 is the
%closest MATALB equivalent to Java's byte.
buf = int8(zeros(1,500));

%create an object to receive the data from the multicast stream
recv = java.net.DatagramPacket(buf,500);

%Fill buffer with stream data. If stream is started before code is run, a
%single datagram packet will be received.
Socket.receive(recv)

%Pull the data from the buffer into a variable (column of bytes)
data = recv.getData();

%Create java objects to read in the marker position data (or whatever you
%are trying to get from the multicast stream).  The byte array is wrapped
%into a buffer with the java object. This is expecting a byte array, so an
%int8 array is given in MATLAB. The array consists of the 4 integer values
%that correspond to the float X, Y or Z position (or again, whatever float
%value you want). The rows of interest vary depending on what information
%is being streamed. For this example, two 3-marker trackables were streamed
%and the first one had data for X,Y and Z marker positions starting in row
%137 and ending in row 172 (4 integers per float value, 3 coordinates per
%marker, 3 markers).  Using the depacketization sample can help in
%determining where the values of interest reside within the packet.
%Finally, the byte order is switched within each array of 4 bytes to
%convert from little endian to big endian.
s1xDUMMY = java.nio.ByteBuffer.wrap(int8(data(140:-1:137)));
s1yDUMMY = java.nio.ByteBuffer.wrap(int8(data(144:-1:141)));
s1zDUMMY = java.nio.ByteBuffer.wrap(int8(data(148:-1:145)));
s2xDUMMY = java.nio.ByteBuffer.wrap(int8(data(152:-1:149)));
s2yDUMMY = java.nio.ByteBuffer.wrap(int8(data(156:-1:153)));
s2zDUMMY = java.nio.ByteBuffer.wrap(int8(data(160:-1:157)));
s3xDUMMY = java.nio.ByteBuffer.wrap(int8(data(164:-1:161)));
s3yDUMMY = java.nio.ByteBuffer.wrap(int8(data(168:-1:165)));
s3zDUMMY = java.nio.ByteBuffer.wrap(int8(data(172:-1:169)));

%For each variable, use the getFloat method to assign the MATLAB variable a
%float value based on the values in the 4-byte array.
s1x = s1xDUMMY.getFloat();
s1y = s1yDUMMY.getFloat();
s1z = s1zDUMMY.getFloat();
s2x = s2xDUMMY.getFloat();
s2y = s2yDUMMY.getFloat();
s2z = s2zDUMMY.getFloat();
s3x = s3xDUMMY.getFloat();
s3y = s3yDUMMY.getFloat();
s3z = s3zDUMMY.getFloat();

NaturalPoint - Mike
Posts: 1896
Joined: Tue Feb 01, 2011 8:41 am
Location: Corvallis, OR

Re: Streaming Individual Markers

Post by NaturalPoint - Mike »

Copying this to my code samples thread. Thanks!
Abibat
Posts: 6
Joined: Wed Apr 25, 2012 5:51 am

Re: Streaming Individual Markers

Post by Abibat »

Just wandered how you identify the positions in the java line from the depacetisation information provided.
Thanks
Abibat
Posts: 6
Joined: Wed Apr 25, 2012 5:51 am

Re: Streaming Individual Markers

Post by Abibat »

Just wandered how you identify the positions in the java line from the depacetisation information provided.
Thanks
Post Reply