OpenIGTLink/Library/Tutorial

From NAMIC
Revision as of 17:06, 15 July 2008 by Tokuda (talk | contribs) (Using the low level C library)

Jump to: navigation, search
Home < OpenIGTLink < Library < Tutorial

<< OpenIGTLink

Two approaches to use the Open IGT Link

Using the low-level C library

The library has been built on the low-level C-library called igtlutil, which is a collection of several data structures with supporting functions for data serialization, endian conversion and cyclic redundancy check, written in ANSI C. The developers can directly use this low-level C-library from their programs. The library is particularly useful to develop embedded or old systems that do not have any modern C++ compiler.

Using the C++ message classes

The library provides much more simple, portable and safer ways to generate standard Open IGT Link messages using C++ classes. The developers can easily add classes to serialize/deserialize their own data types, by inheriting the base message class. It also provides the multi-platform TCP socket / threading classes; the developers can write multi-platform IGT applications, which communicate with other IGT devices and software, with the Open IGT Link library. Those classes are implemented based on Win32 socket / thread API for Windows and BSD socket / POSIX Thread API for Linux and Mac OS X, and have been tested on those environments.


Please refer OpenIGTLink/Approaches to choose your approach.


Setting up the library

Please refer the Open IGT Link library building instruction.


Code snippet using the igtlutil library

Serializing Open IGT Link message for linear transform data

To generate a transform message using the igtlutil library, first we include following header files:

 #include "igtl_util.h"
 #include "igtl_header.h"
 #include "igtl_transform.h"

Then, prepare a transform:

 /********** pack data body **********/
 igtl_float32 transform[12];
 
 transform[0] = tx;
 transform[1] = ty;
 transform[2] = tz;
 transform[3] = sx;
 transform[4] = sy;
 transform[5] = sz;
 transform[6] = nx;
 transform[7] = ny;
 transform[8] = nz;
 transform[9] = px;
 transform[10] = py;
 transform[11] = pz;
 
 igtl_transform_convert_byte_order(transform);  /* convert endian if necessary */

Once the transform data has been prepared, we create a general header:

 /********** general header **********/  
 igtl_header header;
 igtl_uint64 crc = crc64(0, 0, 0LL);          /* initial crc */
 header.version   = IGTL_HEADER_VERSION;
 header.timestamp = 0;
 header.body_size = IGTL_TRANSFORM_SIZE;
 header.crc       = crc64((unsigned char*)transform, IGTL_TRANSFORM_SIZE, crc);
 
 strncpy(header.name, "TRANSFORM", 12);       /* Device Type: should be "TRANSFORM" */
 strncpy(header.device_name, "Tracker", 20);    /* Device name */
 
 igtl_header_convert_byte_order(&header);   /* convert endian if necessary */

Now it's time to send the serialized data. Since igtlutil library doesn't have a socket implementation, we need to some socket libraries or API, available in the environment we are working on. In case of BSD socket, call:

 send(sock, (void*) &header, IGTL_HEADER_SIZE, 0);
 send(sock, (void*) transform, IGTL_TRANSFORM_SIZE, 0);

after establishing the connection.

Deserializing Open IGT Link message for linear transform data


First of all, we receive the header data from the sender. It may look like the following code, in case of using BSD socket API:

 igtl_header header;
 int n;
 
 n = recv(sock, header, IGTL_HEADER_SIZE);
 if (n != IGTL_HEADER_SIZE)
   {
     /*** do something for error handling ***/
   }  

Then convert byte order of each element:

 igtl_header_convert_byte_order(&header);

Now the header is ready to be read. Header fields e.g. header version, size, CRC etc. can be access as members of igtl_header structure.

The following code shows how to detect which type of message is in the body part.

 char deviceType[13];
 deviceType[12] = 0;
 memcpy((void*)deviceType, header.name, 12);
 
 if (strcmp(deviceType, "TRANSFORM") == 0)
   {
     /*** code to read TRANSFORM data ***/
   }
 else if (strcmp(deviceType, "IMAGE") == 0)
   {
     /*** code to read IMAGE data ***/
   }
 
   /*** .... other types ...  ***/
 
 else
   {
     /*** Unknown type: read the rest of the message and discard it. ***/
   }

Example using the Open IGT Link Library (C++)

Get the example code

The example code is available in the Examples/ directory of Open IGT Link library. The instruction is available in the Open IGT Link Library page.

Writing Tracker Client program

The code "Tracker/TrackerClient.cxx" demonstrates how to create open igt link message, establish connection with the Open IGT Link server, then repeat sending coordinate data to the server, using Open IGT Link Library.

First, establish connection with server (ip: 192.168.0.1, port number: 18944) using igtl::ClientSocket class:

 igtl::ClientSocket::Pointer socket;
 socket = igtl::ClientSocket::New();
 int r = socket->ConnectToServer("192.168.0.1", 18944);
 
 if (r != 0)
   {
   //
   // do error handling
   //
   }

Prepare a class instance for the Open IGT Link message:

 igtl::TransformMessage::Pointer transMsg;
 transMsg = igtl::TransformMessage::New();

Set Open IGT Link device name:

 transMsg->SetDeviceName("Tracker");

Substitute matrix into the Matrix4x4 class:

 igtl::Matrix4x4 matrix;
 GetRandomTestMatrix(matrix);

Set the matrix to the message class:

 transMsg->SetMatrix(matrix);

Pack the data. This member function generates byte stream formatted in Open IGT Link format.

 transMsg->Pack();

Send data through TCP/IP socket connection:

 socket->Send(transMsg->GetPackPointer(), transMsg->GetPackSize());