8.8.11. Plugin class - DataIO#

8.8.11.1. Base idea behind any DataIO#

  • Plugins of class dataIO operate systems that have input or output data, e.g. frame grabbers, cameras, serial ports, AD-DA-converters…

  • Every single instance of class dataIO has an exclusive communication with one connected device. More cameras or ADDA-converter of the same type should be managed with a corresponding number of instances.

  • Depending on the plugin, more than one DataIO can be separately controlled by the plug-number or the vendor/camera-ID.

  • Like any other plugin, every DataIO has a set of parameters, which can be set/get using python by the commands setParam and getParam.

  • Every DataIO is executed in its own thread.

  • Every DataIO can have one configuration dialog and one toolbox (dockWidget).

  • All parameters are stored in the member m_params of type QMap. They can be read or changed by methods getParam and setParam. Some parameters are read only!

  • If parameters of DataIO change, they also must be updated in the m_params-map and the signal parametersChanged must be emitted.

  • The data acquisition is performed according to the grabber subtype. These subtypes are ‘typeGrabber’, ‘typeADDA’ and ‘typeRawIO’.

8.8.11.2. Grabber plugin#

This is a subtype of DataIO for camera / framegrabber communication. Plugins of this type are inherited from ito::AddInGrabber. The data acquisition is managed as follows:

  • The methods startDevice and stopDevice open and close the capture logic of the devices to reduce CPU-load. For serial ports these functions are unnecessary.

  • The method acquire starts the DataIO grabbing a frame with the current parameters. The function returns after sending the trigger. The function should be callable several times without calling get-/copyVal().

  • The methods getVal and copyVal are the external interfaces for data grabbing. They call retrieveData. The function should not be callable without a previous call of acquire and than only once.

  • In retrieveData the data transfer is done and frame has to copied. The function blocks until the triggered data is copied. In case retrieveData is called by getVal the frame has to be copied to m_data, an internal dataObject.

  • The function getVal overwrites the IO-dataObject by a shallow copy of the internal dataObject. Empty objects are allowed. Warning read shallow copy of dataObject before usage.

  • The function copyVal deeply copies data to the externally given dataObject. The dataObject must have the right size and type. dataObject with ROI must not be overwritten. The ROI should be filled. Empty objects are allowed. In case of empty dataObject a new object with right size and type must be allocated.

  • The internal dataObject is checked after parameter changes by checkData (sizex, sizey and bpp) and, if necessary, reallocated.

A typical sequence in python is

1device.startDevice()
2device.acquire()
3device.getVal(dObj)
4device.acquire()
5device.getVal(dObj)
6device.stopDevice()

A sample header file of the DataIO’s plugin class might look like the following snippet:

 1#include "common/addInGrabber.h"
 2#include <qsharedpointer.h>
 3
 4class MyCamera : public ito::AddInGrabber
 5{
 6    Q_OBJECT
 7
 8    protected:
 9        ~MyDataIO(); /*! < Destructor*/
10        MyDataIO();    /*! < Constructor*/
11
12        ito::RetVal retrieveData(ito::DataObject *externalDataObject = NULL); /*!< Wait for acquired picture */
13
14    public:
15        friend class MyDataIOInterface;
16        const ito::RetVal showConfDialog(void);    //! Open the config nonmodal dialog to set camera parameters
17        int hasConfDialog(void) { return 1; }; //!< indicates that this plugin has got a configuration dialog
18
19    private:
20
21    public slots:
22        ito::RetVal getParam(QSharedPointer<ito::Param> val, ItomSharedSemaphore *waitCond);
23        ito::RetVal setParam(QSharedPointer<ito::Param> val, ItomSharedSemaphore *waitCond);
24
25        ito::RetVal init(QVector<ito::Param> *paramsMand, QVector<ito::Param> *paramsOpt, ItomSharedSemaphore *waitCond = NULL);
26        ito::RetVal close(ItomSharedSemaphore *waitCond);
27
28        ito::RetVal startDevice(ItomSharedSemaphore *waitCond);
29        ito::RetVal stopDevice(ItomSharedSemaphore *waitCond);
30
31        ito::RetVal acquire(const int trigger, ItomSharedSemaphore *waitCond = NULL);
32
33        ito::RetVal getVal(void *vpdObj, ItomSharedSemaphore *waitCond);
34
35        ito::RetVal copyVal(void *vpdObj, ItomSharedSemaphore *waitCond);
36
37    private slots:
38        void dockWidgetVisibilityChanged(bool visible);
39};
40
41class MyCameraInterface : public ito::AddInInterfaceBase
42{
43    Q_OBJECT
44#if QT_VERSION >=  QT_VERSION_CHECK(5, 0, 0)
45    Q_PLUGIN_METADATA(IID "ito.AddInInterfaceBase" )
46#endif
47    Q_INTERFACES(ito::AddInInterfaceBase)
48    PLUGIN_ITOM_API
49
50    protected:
51
52    public:
53        MyCameraInterface();
54        ~MyCameraInterface();
55        ito::RetVal getAddInInst(ito::AddInBase **addInInst);
56
57    private:
58        ito::RetVal closeThisInst(ito::AddInBase **addInInst);
59};

8.8.11.2.1. Parameters and Unit Conventions#

In order to have a unified behaviour of all camera plugins, respect the following unit conventions. That means, the plugin should store related parameters using these conventions, such that getParam and setParam returns and obtains values using these units. Internally, it is sometimes necessary to convert these units to the units required by the interface of the real camera device.

  • Integration time, frame time… in sec

  • bit depth / resolution in bit [8, 10, 12, 14, 16, 24]

Implement the following mandatory parameters in the map m_params:

  • “name”: {string | readonly}

    name of the plugin

  • “bpp”: {int}

    current bit depth (will be read e.g. when opening a live window)

  • “sizex”: {int | readonly}

    current width of the camera image (considering a possible ROI). This parameter is always read-only and needs to be changed if the optional parameters x0 or x1 change. This parameter is read e.g. when a live window is opened.

  • “sizey”: {int | readonly}

    current height of the camera image (considering a possible ROI). This parameter is always read-only and needs to be changed if the optional parameters y0 or y1 change. This parameter is read e.g. when a live window is opened.

If desired implement the following optional parameters in the map m_params:

  • “integration_time”: {double}

    Exposure or integration time in seconds

  • “frame_time”: {double}

    The time between two frames (in seconds, often read-only)

  • “gain”: {double}

    Normalized gain in the range [0.0,1.0]

  • “offset”: {double}

    Normalized offset in the range [0.0,1.0]

  • “x0”, “y0”: {int, deprecated (see roi)}

    pixel coordinate of the left top corner of the image or ROI [0..width-1/height-1] If this changes, “sizex” or “sizey” must be changed, too.

  • “x1”, “y1”: {int, deprecated (see roi)}

    pixel coordinate of the right bottom corner of the image or ROI [x0+1/y0+1..width-1/height-1] If this changes, “sizex” or “sizey” must be changed, too.

  • “roi”: {int-array}

    Since itom AddIn Interface version 1.3.1 (itom 1.4.0 or higher), it is recommended to replace x0 y0, x1 and y1 by the integer array based parameter roi which expects an array [left, top, width, height]. This parameter can easily be parametrized using the meta information ito::RectMeta and allows the direct configuration of the entire ROI or a single access to one of the four components, by passing the parametername roi[0], roi[1]….

8.8.11.3. AD-Converters#

AD-Converter plugins are directly inherited from ito::AddInDataIO. An AD-DA-converter plugin has the following characteristics:

  • It can communicate with 1 or multiple input and/or output channels. To set the number of total channels and to define if a channel is an incoming or outgoing channel, the plugin’s parameters or initialization parameters should be used. Sometimes it is not possible to change the direction after initialization, this depends on the device.

  • The method startDevice must be called like in a camera before the first usage of the device in order to establish the connection. Create a no-operation method, if this is not necessary for your device. It is possible, that startDevice is called multiple time, therefore count the number of starts and only establish the connection upon the first call.

  • As counterpart to startDevice, the method stopDevice disconnects the device. For every call of startDevice, stopDevice must be called and at the last call, the connection should be interrupted.

  • In difference to a camera dataIO plugin, the method acquire can be used to start the acquisition of a series of input data values at all previously selected input channels. It is also possible to create an empty function here. Then the reading-process of new single data values for each input channel is totally executed in the method getVal.

  • The method copyVal needs not to be implemented for AD-DA-converters.

  • Method getVal: This method registers input values from all previously selected input channels (depending on your implementation and parametrization it is also possible to register multiple values per channel) and returns these values to the user.

    • If you have one or multiple input channels, use the definition getVal(void *dObj, ItomSharedSemaphore *waitCond). The parameter dObj is then a pointer to ito::DataObject and can be cast to this class. Return an MxN data object, where M corresponds to the number of read input channels and N corresponds to the data samples per channel. If you want to, you can also force the user to previously allocate the given data object such that you can get a hint how many samples should be registered.

    • For only one input channel, it is also possible to implement the definition getVal(QSharedPointer<char> data, QSharedPointer<int> length, ItomSharedSemaphore *waitCond = NULL) where an allocated char-buffer whose size is defined by length is given. Fill in the data samples into the buffer (considering the given length) or use the length value to see how many samples are requested.

  • Method setVal: This method is called if the user wants the plugin to set data to all selected output channels. The definition is setVal(const char *data, const int length, ItomSharedSemaphore *waitCond = NULL). In case of AD-DA-converter plugins, length is always 1 and data must be cast to ito::DataObject*. The given data object must then have a size of MxN where M denotes the number of output channels (must correspond to the number of channels to write data) and N is the number of samples. You can then send all samples to each channel either as fast as possible or using a timer, using the timer of the device. This depends on its abilities.

A sample header file of the DataIO’s plugin class for AD-converters might look like the following snippet:

 1#include "common/addInInterface.h"
 2#include <qsharedpointer.h>
 3
 4class MyADConverter : public ito::AddInDataIO
 5{
 6    Q_OBJECT
 7
 8    protected:
 9        ~MyADConverter(); /*! < Destructor*/
10        MyADConverter();    /*! < Constructor*/
11
12    public:
13        friend class MyADConverterInterface;
14        const ito::RetVal showConfDialog(void);    //! Open the config nonmodal dialog to set camera parameters
15        int hasConfDialog(void) { return 1; }; //!< indicates that this plugin has got a configuration dialog
16
17    private:
18
19    public slots:
20        ito::RetVal getParam(QSharedPointer<ito::Param> val, ItomSharedSemaphore *waitCond);
21        ito::RetVal setParam(QSharedPointer<ito::Param> val, ItomSharedSemaphore *waitCond);
22
23        ito::RetVal init(QVector<ito::Param> *paramsMand, QVector<ito::Param> *paramsOpt, ItomSharedSemaphore *waitCond = NULL);
24        ito::RetVal close(ItomSharedSemaphore *waitCond);
25
26        ito::RetVal startDevice(ItomSharedSemaphore *waitCond);
27        ito::RetVal stopDevice(ItomSharedSemaphore *waitCond);
28
29        ito::RetVal getVal(void *vpdObj, ItomSharedSemaphore *waitCond);
30        ito::RetVal getVal(QSharedPointer<char> data, QSharedPointer<int> length, ItomSharedSemaphore *waitCond = NULL);
31        ito::RetVal setVal(const char *data, const int length, ItomSharedSemaphore *waitCond = NULL);
32
33    private slots:
34        void dockWidgetVisibilityChanged(bool visible);
35};
36
37class MyADConverterInterface : public ito::AddInInterfaceBase
38{
39    Q_OBJECT
40#if QT_VERSION >=  QT_VERSION_CHECK(5, 0, 0)
41    Q_PLUGIN_METADATA(IID "ito.AddInInterfaceBase" )
42#endif
43    Q_INTERFACES(ito::AddInInterfaceBase)
44    PLUGIN_ITOM_API
45
46    protected:
47
48    public:
49        MyADConverterInterface();
50        ~MyADConverterInterface();
51        ito::RetVal getAddInInst(ito::AddInBase **addInInst);
52
53    private:
54        ito::RetVal closeThisInst(ito::AddInBase **addInInst);
55};

8.8.11.4. RawIO-Plugins#

Further IO plugins are directly inherited from ito::AddInDataIO.