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_qtWhile 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.
- 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
- 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