Tracking Plugin Interface
→
Return to Development Section
Introduction
Starting with Unifeye 3.5 a flexible plugin mechanism was introduced that allows the integration of custom tracking modules. Unifeye 3.5 and later provides a header file that has to be implemented by a module which has to be built as a DLL. It is recommended to built the according DLL as Multithreaded(-Debug)-DLL (Visual Studio compiler switch
/MDd or
/MD).
Once the DLL is created, an according
tracking configuration file has to be created. The Sensor type provided in the according tracking configuration file has to match the name of the DLL without the .dll extension. The created DLL file itself has to be placed into the directory next to the Unifeye main module (
AS_AR_Browser.ocx) which is usually located inside the
metaio/Unifeye/bin program folder (e.g.
C:\Program Files\metaio\Unifeye\bin) and will be loaded automatically once the according tracking configuration file is loaded.
Tracking Configuration
An example tracking configuration file is given in the following section for a plugin tracking module called
MySensorSource which would match a DLL called
MySensorSource.dll.
The code below specifies the content of the tracking configuration file.
- In the Sensor section a Sensor of type "MySensorSource" is defined with a unique
SensorID.
- The Parameters section contains an enclosing pair of XML tags called
<MySensorSourceParameters> and one parameter called <myParameter1>. Note that your custom tracking/sensor source plugin DLL will receive the XML string below the tag <Parameters> in the init() method and you can specify any parameters in XML format you need. In general it is a good approach to add another pair of enclosing XML tags as done here by <MySensorSourceParameters>.
- Then a
SensorCOS is added, configuring one tracked COS for your tracking plugin. A SensorCOS consists of:
- A unique
SensorCosID
- parameters specific for this
SensorCOS. In this case, only one parameter is specified ("<mySensorCOSParameter1>"). Note that your custom tracking/sensor source plugin DLL will receive the XML string below the tag <Parameters> of the SensorCOS section for every configured SensorCOS via the addSensorCOS() method. For every configured SensorCOS this function will be called with the according parameters. In general it is a good approach to add another pair of enclosing XML tags as done here by <MySensorSourceCOSParameters>.
- Then the
Connections are defined, which link a SensorID with a SensorCosID in terms of COSes.
- In our case one
COS is defined which
- has a name (
Cos1),
- uses a
Fuser of type BestQualityFuser,
- links the
SensorID "MySensorSource1" with the SensorCosID "sensorCOS1",
- holds a
HandEyeCalibration transform which is the identity (no translation and no rotation),
- holds a
COSOffset transform which is also the identity.
Example Tracking configuration
<?xml version="1.0"?>
<TrackingData>
<Sensors>
<Sensor type="MySensorSource"><!-- Name of the according sensor source -->
<SensorID>MySensorSource1</SensorID><!-- give it an ID, as there might be several sensors of the same type -->
<Parameters><!-- sensor specific parameters -->
<MySensorSourceParameters>
<myParameter1>100</myParameter1>
</MySensorSourceParameters>
</Parameters>
<SensorCOS>
<SensorCosID>sensorCOS1</SensorCosID>
<Parameters><!-- sensor cos specific parameters -->
<MySensorSourceCOSParameters>
<mySensorCOSParameter1>dummyValue</mySensorCOSParameter1>
</MySensorSourceCOSParameters>
</Parameters>
</SensorCOS>
</Sensor>
</Sensors>
<Connections>
<COS>
<Name>Cos1</Name>
<Fuser type="BestQualityFuser">
<Parameters></Parameters>
</Fuser>
<!-- There are 1-n SensorCoses -->
<SensorSource trigger="1">
<SensorID>MySensorSource1</SensorID> <!-- Who tracks... -->
<SensorCosID>sensorCOS1</SensorCosID> <!-- what? -->
<HandEyeCalibration>
<TranslationOffset>
<x>0.0</x>
<y>0.0</y>
<z>0.0</z>
</TranslationOffset>
<RotationOffset>
<x>0.0</x>
<y>0.0</y>
<z>0.0</z>
<w>1.0</w>
</RotationOffset> <!-- e.g. Transform between camera and ART body -->
</HandEyeCalibration>
<COSOffset>
<TranslationOffset>
<x>0.0</x>
<y>0.0</y>
<z>0.0</z>
</TranslationOffset>
<RotationOffset>
<x>0.0</x>
<y>0.0</y>
<z>0.0</z>
<w>1.0</w>
</RotationOffset><!-- offset like before -->
</COSOffset>
</SensorSource>
</COS>
</Connections>
</TrackingData>
Implementation of a tracking/sensor source plugin
For implementing a custom tracking DLL you have to create a DLL that implements the header file
metaio_IDLLSensorSource.h to be found in the
/config/plugin subfolder of your Unifeye installation. An example can be found in the
/examples/plugin directory. It contains a Visual Studio project file (
DynamicallyLoadedSensor.vcproj) file which you can open and contains two example implementations:
-
metaio_FramesTriggeredSensorExample.h/cpp will just output tracking values upon every new camera frame it receives and runs out of the box,
-
metaio_OpenThreadsSensorExample.h/cpp contains a threaded example that outputs tracking values independant from the camera image, i.e. threaded by interpolating the translation for x,y,z between given start and end values. To keep the example simple, rotation was not taken into account. Please note that you will need the OpenThreads library in order to use this project, but even without it it should give you a clear idea how things work.
For choosing the example you want to use, adjust the file metaio_DLLProcedures.cpp accordingly (see the first
#define and
#include in the file).
In general you can choose if you want to receive images from the currently active visualization camera or not. The first case makes sense for implementing an optical tracking algorithm, the second if you e.g. want to add a hardware tracking device that doesn't need the visualization image to work with. Pose information is to be returned to the system via the function pointer given by the
init() method. The following functions have to be implemented:
-
virtual bool init(const std::string& xmlParams, const std::string& trackingDataPath, void (*pCallback)( const std::vector &,void * ), void *pContext, bool *pIsFramesSourceTriggered); This function is called by the system while loading the tracking configuration file and is used to setup your custom tracking module/sensor source.
-
virtual bool addSensorCOS(const std::string& cosID, const std::string& cosParameters, const std::string& trackingDataPath, bool *pIsOnlyOneCOSAllowed); This function is called by the system during loading the tracking configuration file for every configured SensorCOS and should be used to perform the per SensorCOS configuration of your tracking module/sensor source.
-
virtual bool start(); This function is called by the system once per tracking module after the complete tracking configuration has been loaded. If your custom tracking module/sensor source requires a separate thread to be started, this should be done within this method. The function has to return true if it contains a separate thread and false otherwise.
-
virtual bool onNewImage(const metaio::ImageHeader& imageHeader, const metaio::Camera& camDist& camDist, double timestamp)); This function is called by the system if you have opted for receiving images of the visualization camera (which is the currently loaded image/video or camera) in the call to the init() function.
-
imageHeader contains the image as a const pointer and information about the given image (like resolution, number of channels). The image will already be undistorted if an according camera calibration (Sextant or Extended Sextant) is loaded into Unifeye. You should NEVER try to alter the given image. Otherwise a system malfunction might occur. Also note that you should omit every needless copy operation of the given image as this introduces performance penalties to the whole system especially in HD image scenarios.
-
camDist contains parameters describing the intrinsics of the camera for the given image (focal length, principal point, distortion parameters).
-
timestamp contains the timestamp of the image in milliseconds according to a high resolution performance timer of your system (see Windows API function: QueryPerformanceCounter, e.g. at http://msdn.microsoft.com/en-us/library/ms644904(VS.85).aspx).
Besides the functions mentioned above you have to implement a create and destroy function which are called by Unifeye to create and destroy the according custom tracking module/sensor source:
-
extern "C" __declspec(dllexport) metaio::IDLLSensorSource* Create(); This function is called by the system after loading the DLL for your custom tracking module/sensor source and should return a pointer to a class that implements the functions listed above. A simple example implementation would look like the following and return a pointer to a new instance of the class called MySensorSource.
extern "C" __declspec(dllexport) metaio::IDLLSensorSource* Create()
{
return new metaio::MySensorSource();
}
-
extern "C" __declspec(dllexport) void Destroy(metaio::IDLLSensorSource* p); This function is called by the system when it has to destroy your custom tracking module/sensor source. This happens e.g. when loading a new tracking configuration file or at system shutdown. It should destroy the given instance of a class created by the Create() function. A simple implementation would look like this:
extern "C" __declspec(dllexport) void Destroy(metaio::IDLLSensorSource* p)
{
metaio::DummySelfTriggeredSS *pDerived = dynamic_cast(p);
if (pDerived != NULL)
{
delete pDerived;
}
}
-
p contains the pointer returned by the Create() function and can be used to destroy the according object.
→
Return to Development Section
--
SupportMetaio - 2011-01-28