NatNet: Creating a Managed (C sharp) Client Application
The following guide references SampleClientML.cs client application that is provided with the SDK. This sample demonstrates the use of .NET NatNet assembly for connecting to a NatNet server, receiving a data stream, and parsing and printing out the received data.
1. NatNet Library
When developing a managed client applications, you will need to link both native and managed DLL files(NatNetLib.dll and NatNetML.dll). The managed NatNet assembly is derived from the native library, so without the NatNetLib.dll, NatNetML.dll will not be imported properly. These library files can be found in the NatNetSDK\lib
folder for 32-bit platform and in the NatNetSDK\lib\x64
folder for 64-bit platform. Make sure these DLL files are properly linked and placed alongside the executables.
Also, when using the NatNetML assembly, place the NatNetML.xml file alongside imported DLL file. This allows XML documentation to be included as a reference. These library files can be found in the NatNetSDK\lib
folder for 32-bit platform and in the NatNetSDK\lib\x64
folder for 64-bit platform. Make sure these DLL files are properly linked and placed alongside the executables.
2. Connect
a. Create a NatNetClientML object
Tracking server and client network is established through an instance of NatNet client object (NatNetML.NatNetClientML). Also, this NatNetClientML object will be used for receiving tracking data and sending NatNet commands to and from the server application. When instantiating the NatNetClientML object, input an integer value for determining the desired type of UDP connection; whether it connects via multicast (0) or unicast (1).
[C#] SampleClientML.cs : Instantiating NatNetClientML
b. Connect to Server
To connect to the server, use the Initialize method from the instantiated NatNetClientML object. When calling this method, input the proper Local IP address and the Server IP address. The local IP address must match the IP address of the host PC, and the server IP address must match the address that the server is streaming onto, which is defined in the Data Streaming panel in Motive.
[C#] SampleClientML.cs : Connect to Server. Initialize
c. Confirm connection
To confirm whether the client has successfully connected to the server application, let's try querying for a ServerDescriptor packet using the GetServerDescription method. If the server is connected, the corresponding server descriptions will be obtained. This method returns an ErrorCode value, and when successfully operated it will return a value of 0.
[C#] SampleClientML.cs : GetServerDescription
3. Get DataDescriptions
As explained in the NatNet: Data Types page, there are two kinds of data formats included in streamed NatNet packets; one of which is Data Descriptions. In managed NatNet assembly, data descriptions for each of the assets (Marker Sets, Rigid Bodies, Skeletons, and force plates) included in the capture session is stored in a DataDescriptor class. A single capture take (or live streaming) may contain more than one assets, and respectively, there may be more than one data descriptions. For this reason, data descriptions are stored in a list format.
a. GetDataDescription
GetDataDescriptions method in the NatNetClientML class queries a list of DataDescriptors from the connected server and saves it in a declared list of NatNetML.DataDescriptions. In the SampleClientML sample, the following lines are executed to accomplish this:
[C#] SampleClientML.cs : GetDataDescription
b. ParseDataDescription
After obtaining a list of data descriptions, use the saved DataDescriptor objects to access and output data descriptions as needed. In many cases, it is better to re-organize and save the received descriptor objects into separate lists, or into hashtables, of corresponding data types, so that they can be referenced later in the program.
[C#] SampleClientML.cs : Parsing/Saving Data Descriptions
4. Get Frame Data
Now, let's obtain the tracking data from the connected server. Tracking data for a captured frame is stored in an instance of NatNetML.FrameOfMocapData. As explained in the Data Types page, every FrameOfMocapData contains tracking data of the corresponding frame. There are two approaches for obtaining frame data using the client object; by calling the GetLastFrameOfData method or by linking a callback handler function using the OnFrameReady method. In general, creating a callback function is recommended because this approach ensures that every frame of tracking data gets received.
a. Callback Handler (OnFrameReady)
The best way to receive tracking data without losing any of its frames is to create a callback handler function for processing the data. The OnFrameReady event type from the client object can be used to declare a callback event, and the linked function gets called each time a frame is received from the server. Setting up a frame handler function will ensure that every frame gets processed promptly. However, these handler functions should return as quickly as possible to prevent accumulation of frames due to processing latency within the handler.
OnFrameReady2: Alternate function signatured frame ready callback handler for .NET applications/hosts that don't support the OnFrameReady event type defined above (e.g. MATLAB)
[C#] SampleClientML.cs : Frame Data Callback Handler
b. Single Frame (GetLastFrameOfData)
Calling the GetLastFrameOfData method returns a FrameOfMocapData of the most recent frame that was streamed out from the connected server application. This approach is should only be used for .NET applications/hosts that do not support the OnFrameReady callback handler function.
5. Disconnect
When exiting the program, call Uninitialize method using the connected client object and disconnect the client application from the server.
[C#] SampleClientML.cs : Disconnect
Last updated
Was this helpful?