Natnet SDK 2.7 PacketClient.cpp issues

NatNet, VRPN, TrackD, and Plugins
Post Reply
luis.gonzalez
Posts: 2
Joined: Thu May 28, 2015 1:59 pm

Natnet SDK 2.7 PacketClient.cpp issues

Post by luis.gonzalez »

Hello to everyone, I'm new to the forum.

My university recently acquired two OptiTrack systems, with the Motive:Body license, and I'm in charge of starting them up, as well as developing the code needed to get the data available on the client machines (mostly Linux).
Therefore, I'm implementing the NatNet API in Qt, in order to make it available across platforms (Linux and Windows users). The project is open source, I encourage it's use and feedback, and the client can be found here:
https://bitbucket.org/lcgonzalez/natnet_client_qt

While this project is on an early stage, I've found some issues, that I think are bugs, in the PacketClient.cpp file, of the NatNet SDK version 2.7, which I'm using as the NatNet communication protocol source.
The NatNet server app that I'm using is Motive:Body version 1.73.0.0.
I would like to flag these issues in order to help the community.
  1. The first one has to do with obtaining the sending app's NatNet version number, while the PacketClient.cpp does the job with a structure, there are problems regarding the structure's bytes padding that compilers add at their discretion.
    One possible fix, that I propose, is this:

    Code: Select all

    // PacketClient.cpp
    DWORD WINAPI CommandListenThread(void* dummy)
    {
    ...
            // handle command
            switch (PacketIn.iMessage)
            {
            case NAT_MODELDEF:
                Unpack((char*)&PacketIn);
                break;
            case NAT_FRAMEOFDATA:
                Unpack((char*)&PacketIn);
                break;
            case NAT_PINGRESPONSE:
    //          // This can be used in conjunction with precompiler directive:
    //          // #pragma pack(push, 1)
    //          for(int i=0; i<4; i++)
    //          {
    //              NatNetVersion[i] = (int)PacketIn.Data.Sender.NatNetVersion[i];
    //              ServerVersion[i] = (int)PacketIn.Data.Sender.Version[i];
    //          }
    
                // This is the alternative: Directly access the sPacket structure fields
                // The pointer needs to traverse the datagram manually.
                char *ptr = (char*)&PacketIn;
                // message ID
                ptr += 2;
                // payload size
                ptr += 2;
                // sending app's name
                ptr += MAX_NAMELENGTH;
                // sending app's version [major.minor.build.revision]
                // sending app's NatNet version [major.minor.build.revision]
                for(int i=0; i<4; i++){
                    ServerVersion[i] = (int)*ptr;
                    NatNetVersion[i] = (int)*(ptr+4); ptr++;
                }
                break;
    ....
    
    For more information regarding this fix, and the Open Source project, follow this link:
    https://bitbucket.org/lcgonzalez/natnet ... 2effbaa85e
  2. The other issue is more tricky, because it is only displayed when a skeleton is being streamed. The unpack() function of PacketClient.cpp seems to loose synchrony with the datagram, when decoding the skeleton's rigid bodies info (position, orientation, etc.).
    The source problem seems to be the same, a structure padding that is happening in the NatNet server app (Motive version 1.73.0.0), because there is an extra 2 bytes padding between each rigid body info.
    One possible fix, that I propose, is this:

    Code: Select all

    // PacketClient.cpp
    void Unpack(char* pData) {
    ...
        // skeletons (version 2.1 and later)
            if( ((major == 2)&&(minor>0)) || (major>2)) {
                ...
                       // Mean marker error
                       float fError = 0.0f; memcpy(&fError, ptr, 4); ptr += 4;
                       printf("Mean marker error: %3.2f\n", fError);
    
                       // release resources
                       if(markerIDs)
                           free(markerIDs);
                       if(markerSizes)
                           free(markerSizes);
                       if(markerData)
                           free(markerData);
    
                       // Issue #5 Fix : Motive:body is appending 2 bytes of zero data
                       // to the end of each rigid body (belonging to a skeleton) data.
                       // The problem may be caused by structure padding on the
                       // Motive:body software.
                       // NOTE: Please contact NaturalPoint, Inc to solve the issue at the source.
                       ptr += 2;   // Issue #5 Fix.
    
                     } // next rigid body
    
                 } // next skeleton
    
            }
            
    	// labeled markers (version 2.3 and later)
    	if( ((major == 2)&&(minor>=3)) || (major>2))
    	{
    ....
    
    For more information regarding this fix, and the Open Source project, follow this link:
    https://bitbucket.org/lcgonzalez/natnet ... fea501ac98
By the way, it would be very useful if you could help me with the NatNet protocol documentation, besides that of the PacketClient.cpp, because I've sought throughout the forum and website, and I haven't found any documentation. I would really appreciate it.

Greetings,
-Luis
NaturalPoint-Dustin
Posts: 609
Joined: Tue Mar 19, 2013 5:03 pm

Re: Natnet SDK 2.7 PacketClient.cpp issues

Post by NaturalPoint-Dustin »

Hi Luis,

Thank you for reporting this. I will forward your post to our dev team to have a look.

Best Regards,
Dustin
Technical Support Engineer
OptiTrack | TrackIR | SmartNav
morgan
NaturalPoint Employee
NaturalPoint Employee
Posts: 199
Joined: Tue Jun 24, 2008 2:01 pm
Location: Corvallis, OR, USA
Contact:

Re: Natnet SDK 2.7 PacketClient.cpp issues

Post by morgan »

Thanks for the great post - it looks like the new tracking flags for the skeleton bone's rigid body were getting overlooked in the skeleton depacketization causing the alignment issue you found. We've checked in a fix for this in the PacketClient, which will be available in the next release.

The code should look like this:

Code: Select all


 ...
 ...
    // Mean marker error (2.0 and later)
    if(major >= 2)
    {
        float fError = 0.0f; memcpy(&fError, ptr, 4); ptr += 4;
        printf("Mean marker error: %3.2f\n", fError);
    }

    // Tracking flags (2.6 and later)
    if( ((major == 2)&&(minor >= 6)) || (major > 2) || (major == 0) ) 
    {
          // params
          short params = 0; memcpy(&params, ptr, 2); ptr += 2;
          bool bTrackingValid = params & 0x01; // 0x01 : rigid body was successfully tracked in this frame
     }

     // release resources
     if(markerIDs)
         free(markerIDs);

     ...
     ...


Regarding docs for the bitstream syntax, we don't have any specific doc describing the syntax specifically, as the working code typically will be more up to date. The direct depacketization however follows the FrameOfMocap structure in the NatNet SDK, so the description for those fields will apply.

Hope this helps,

Morgan
fgraffagnino
Posts: 5
Joined: Fri Jun 12, 2015 3:10 pm

Re: Natnet SDK 2.7 PacketClient.cpp issues

Post by fgraffagnino »

I've integrated these fixes, but I still get crashes in packetclient, both in the one distributed and in one that I've modified to work in linux.

Can someone confirm that the packetclient.cpp runs with simpleserver out of the box on windows? Or, that it runs with the fix suggested by naturalpoint? I get a crash and it appears to always be on the second RigidBody that it is processing, and it always seems to print ID "13172736". The numbers are all garbage and I eventually get a seg fault. Obviously there is still a misalignment somewhere.

Here's my output:

Multicast Group: 239.255.42.99
Packet Client started

Commands:
s send data descriptions
f send frame of data
t send test request
q quit

Begin Packet
-------
Message ID : 7
Byte count : 3476
Frame # : 496045
Marker Set Count : 1
Model Name: Katie
Marker Count : 10
Marker 0 : [x=0.64,y=0.77,z=0.84]
Marker 1 : [x=10.66,y=20.75,z=30.87]
Marker 2 : [x=20.67,y=40.74,z=60.90]
Marker 3 : [x=30.68,y=60.73,z=90.93]
Marker 4 : [x=40.69,y=80.72,z=120.97]
Marker 5 : [x=50.71,y=100.71,z=151.00]
Marker 6 : [x=60.72,y=120.69,z=181.04]
Marker 7 : [x=70.73,y=140.68,z=211.07]
Marker 8 : [x=80.74,y=160.67,z=241.11]
Marker 9 : [x=90.75,y=180.66,z=271.15]
Unidentified Marker Count : 0
Rigid Body Count : 20
ID : 0
pos: [0.77,0.64,1.19]
ori: [0.13,0.44,0.40,0.79]
Marker Count: 3
Marker 0: pos = [0.10,0.20,0.30]
Marker 1: pos = [1.10,1.20,1.30]
Marker 2: pos = [2.10,2.20,2.30]
ID : 13172736
pos: [0.00,0.00,0.00]
ori: [0.00,0.00,0.00,0.00]
Marker Count: 1061614346
<seg fault>

FG
morgan
NaturalPoint Employee
NaturalPoint Employee
Posts: 199
Joined: Tue Jun 24, 2008 2:01 pm
Location: Corvallis, OR, USA
Contact:

Re: Natnet SDK 2.7 PacketClient.cpp issues

Post by morgan »

The output looks like the stream is coming form the simpleserver app, which has been deprecated. We now provide trial versions of Motive and sample TAK files, which represent a much more accurate test.

Can you confirm the packetclient is crashing against Motive or TrackingTools, and if so which version you are using?

We can then test against that version here and try to reproduce.

thx

Morgan
fgraffagnino
Posts: 5
Joined: Fri Jun 12, 2015 3:10 pm

Re: Natnet SDK 2.7 PacketClient.cpp issues

Post by fgraffagnino »

Ahh. I didn't know simpleserver had been deprecated.

I can definitely try out Motive. I don't see a trial version anywhere, do I just download a version off the downloads page and run it without a license? (I'm not near a windows machine to try it out right now) Also, can I run that without any hardware hooked up?

Thanks!
luis.gonzalez
Posts: 2
Joined: Thu May 28, 2015 1:59 pm

Re: Natnet SDK 2.7 PacketClient.cpp issues

Post by luis.gonzalez »

I confirm that the packetclient.exe (out of the box) of the NatNet SKD version 2.7 is crashing against Motive version 1.73.
packetclient.exe (out of the box) of the NatNet SKD version 2.7 is crashing against Motive version 1.73.
packetclient.exe (out of the box) of the NatNet SKD version 2.7 is crashing against Motive version 1.73.
natnet_1.png (239.33 KiB) Viewed 20872 times
The problem is not Motive, but the way packetclient.cpp is implemented.
Probably, the misalignment problem is due to packetclient not recognizing the appropriate NatNet version number, and this is because packetclient.cpp uses a structure to access the elements of the income packet in order to get the NatNet and Server versions.
The problem with structures accessing arrays in this way, is that, if the elements of the structure are of different types, odds are that the compiler will add padding bytes to the structure, in order to make it multiple of the host computer architecture.
This practice of structure padding is applied at the compiler's discretion, and can be overridden by the #pragma pack(push,1) pre-compiler directive, but it's still not portable.

This structure padding problem can be easily solved by accessing the elements inside the packet "by hand", which means that you have to traverse the packet, using a pointer, until you reach the place where the NatNet and Server versions are stored, then, one number at a time, retrieve those versions.
I have mentioned this problem, and the fix, in my first post on this thread, please read it. Anyway, here is the packetclient.cpp code again:

Code: Select all

//file: packetclient.cpp
...
// command response listener thread
DWORD WINAPI CommandListenThread(void* dummy)
{
    ...
    while (1)
    {
        ...
        // handle command
        switch (PacketIn.iMessage)
        {
        ...
        case NAT_PINGRESPONSE:
            for(int i=0; i<4; i++)
            {
                // This is the alternative to directly accessing the sPacket structure fields.
                // The pointer needs to traverse the datagram manually.
                char *ptr = (char*)&PacketIn;
                // message ID
                ptr += 2;
                // payload size
                ptr += 2;
                // sending app's name
                serverName_ = std::string(ptr);
                ptr += MAX_NAMELENGTH;

                // sending app's version [major.minor.build.revision]
                for(int i=0; i<4; i++){
                    ServerVersion[i] = (int)*ptr; ptr++;
                     NatNetVersion[i] = (int)*(ptr+4); ptr++;
                }
            break;
            ...
I'm developing a Qt cross platform library for NatNet, and I've experienced these problems on packetclient.cpp. You can have a look at how I solved this NatNet version problem here:
https://bitbucket.org/lcgonzalez/natnet ... 2effbaa85e

When packetclient misreads the NatNet version, the pieces of code like this:

Code: Select all

//file: packetclient.cpp
...
void Unpack(char* pData)
{
...
        // rigid bodies
        int nRigidBodies = 0;
        memcpy(&nRigidBodies, ptr, 4); ptr += 4;
        printf("Rigid Body Count : %d\n", nRigidBodies);
        for (int j=0; j < nRigidBodies; j++)
        {
        ...
            if(major >= 2)
            {
            // Some code used in version 2 of NatNet
            ...
Are not executed, because major is 0 (or any other random number), thus, packetclient thinks that this is a packet that uses a NatNet version lower than 2, but in reality it is a packet of NatNet version 2, thus, because there are differences on the packet's layout of these two versions, the misalignment problem becomes arises.
fgraffagnino
Posts: 5
Joined: Fri Jun 12, 2015 3:10 pm

Re: Natnet SDK 2.7 PacketClient.cpp issues

Post by fgraffagnino »

ok, i've downloaded Motive but after installation it just stops asking for a license. Maybe I've missed where the trial version is on the website. Can you point me to how I can install a trial version and run it without any hardware attached?

Thanks.
steven.andrews
NaturalPoint Employee
NaturalPoint Employee
Posts: 737
Joined: Mon Jan 19, 2015 11:52 am

Re: Natnet SDK 2.7 PacketClient.cpp issues

Post by steven.andrews »

Hi fgraffagnino,

I've confirmed that to acquire a trial license you can reach out to our sales representatives to let them know you are trying to develop off of the NatNet SDK.

If we were in a support ticket I could rout you to them, but this public forum does not afford me the same capabilities. Please feel free to reach out to sales@optitrack.com

If you need further assistance, or if you have any issues reaching our sales reps, please feel free to reach out to us by opening a support ticket at help.naturalpoint.com

Cheers,
Steven
Post Reply