NatNet: Creating a Native (C++) Client Application
Last updated
Was this helpful?
Last updated
Was this helpful?
This guide covers essential points to developing a native client application using the NatNet SDK. The guideline uses sample codes in the SampleClient.cpp application in the \NatNet SDK\Sample
folder, please refer to this project as an additional reference.
a. Link the Library
When developing a native NatNet client application, NatNetLib.dll file needs to be linked to the project and placed alongside its executable in order to utilize the library classes and functions. Make sure the project is linked to DLL files with matching architecture (32-bit/64-bit).
b. Include the Header Files
After linking the library, include the header files within your application and import required library declarations. The header files are located in the NatNet SDK/include
folder.
include "NatNetTypes.h"
include "NatNetClient.h"
Connection to a NatNet server application is accomplished through an instance of NatNetClient object. The client object is instantiated by calling the NatNetClient constructor with desired connection protocol (Multicast/Unicast) as its argument. Designate a desired connection protocol and instantiate the client object. In the SampleClient example, this step is done within the CreateClient function.
ConnectionType_Multicast = 0
ConnectionType_Unicast = 1
[C++] SampleClient.cpp : Server Discovery
[C++] SampleClient.cpp : Connect to the Server
[C++] SampleClient.cpp : Request Server Description
[C++] SampleClient.cpp : Send NatNet Commands
[C++] SampleClient.cpp : Get Data Descriptions
After an sDataDescriptions instance has been saved, data descriptions for each of the assets (marker, Rigid Body, Skeleton, and force plate from the server) can be accessed from it.Collapse
[C++] SampleClient.cpp : Parsing Data Descriptions
Now that we have data descriptions, let's fetch the corresponding frame-specific tracking data. To do this, a callback handler function needs to be set for processing the incoming frames. First, create a NatNetFrameReceivedCallback function that has the matching input arguments and the return values as described in the NatNetTypes.h file:typedef void (NATNET_CALLCONV* NatNetFrameReceivedCallback)(sFrameOfMocapData* pFrameOfData, void* pUserData);
The SampleClient.cpp project sets DataHandler function as the frame handler function.void NATNET_CALLCONV DataHandler(sFrameOfMocapData* data, void* pUserData)
When exiting the program, call Disconnect method to disconnect the client application from the server.
The NatNet SDK includes functions for discovering available tracking servers. While client applications can connect to a tracking server by simply inputting the matching IP address, the auto-detection feature provides easier use.The function searches the network for a given amount of time and reports IP addresses of the available servers. The reported server information can be used to establish the connection. The function continuously searches for available tracking servers by repeatedly calling a callback function. This is all demonstrated in the SampleClient application.
Now that you have instantiated a NatNetClient object, connect the client to the server application at the designated IP address by calling the method.The Connect method requires a sNatNetClientConnectParams struct for the communication information; including the local IP address that the client is running on and the server IP address that the tracking data is streamed to. It is important that the client connects to appropriate IP addresses; otherwise, the data will not be received.Once the connection is established, you can use methods within the NatNetClient object to send commands and query data.
Now that the NatNetClient object is connected, let’s confirm the connection by querying the server for its descriptions. This can be obtained by calling the method and the information gets saved in the provided instance of sServerDescriptions. This is also demonstrated in the CreateClient function of the SampleClient project.
You can also confirm connection by sending a NatNet remote command to the server. NatNet commands are sent by calling the method with supported as one of its input arguments. The following sample sends a command for querying the number of analog sample for each of the mocap frames. If the client is successfully connected to the server, this method will save the data and return 0.
Now that the client application is connected, for the streamed capture session can be obtained from the server. This can be done by calling the method and saving the descriptions list into an instance of sDataDescriptions. From this instance, the client application can figure out how many assets are in the scene as well as their descriptions.This is done by the following line in the SampleClient project:Collapse
When you are finished using the data description structure, you should free the memory resources allocated by GetDataDescription using the NatNet helper routine .
The method creates a new thread and assigns the frame handler function. Call this method with the created function and the NatNetClient object as its arguments. In the SampleClient application, this is called within the CreateClient function:
Once you call the SetDataCallback method to link a data handler callback function, this function will receive a packet of each time a frame is received. The sFrameOfMocapData contains a single frame data for all of the streamed assets. This allows prompt processing of the capture frames within the handler function.