Impact Acquire SDK C++
GenICamSequencerParameterChangeAtRuntime.cpp

Parts of the GenICamSequencerParameterChangeAtRuntime program are based on the ContinuousCapture.cpp example. The sample shows how to configure the GenICam™ SFNC Sequencer Control from an application. In addition to that it explains how change certain sequencer related parameters in a very fast and efficient way.

Note
This sample is not meant to work with every device as it uses custom features only supported by a limited range of devices!

Sometimes it is necessary to modify certain sequencer parameters. The standard way to do this is to

This depending on the device, the system and the application can take quite some time. This is where the feature explained in this example might come in handy. The mvIMPACT::acquire::GenICam::CustomCommandGenerator class is capable of sending commands to a device that can directly modify one or more parameters in one or more sequencer sets without stopping the running sequencer or the acquisition engine. As this happens fast but asynchronously an application must accept that changes applied this way might become effective not with the next but with the 2nd frame captured after the parameter change applied but most of the time this is OK.

Program location
The source file GenICamSequencerParameterChangeAtRuntime.cpp can be found under:
%INSTALLDIR%\apps\GenICamSequencerParameterChangeAtRuntime\
Note
If you have installed the package without example applications, this file will not be available. On Windows® the sample application can be installed or removed from the target system at any time by simply restarting the installation package.
GenICamSequencerParameterChangeAtRuntime example:
  1. Opens a GenICam™ compliant device.
  2. Configures the sequencer if available.
  3. Captures a sequence as configured.
  4. Applies changes to the sequencer program while it is running.
Console Output
#############################################################################
# This example runs 6 SequencerSets, where the ExposureTime varies between
# the SequencerSets. There are two modes. The example starts in random mode,
# where ExposureTime as well as OffsetX and OffsetY is changed every 100
# images randomly. The manual mode allows to change these parameters using
# keys:
#         [Space]       (re)start manual mode
#         [r]           go back to / restart random mode
#
#         [Left]        move AOI to the left
#         [Right]       move AOI to the right
#         [Up]          move AOI upwards
#         [Down]        move AOI downwards
#
#         [PageUp]      increase ExposureTime by 10ms
#         [+]           increase ExposureTime by 1ms
#         [-]           decrease ExposureTime by 1ms
#         [PageDown]    decrease ExposureTime by 10ms
#############################################################################
#############################################################################
# Press   [ENTER]       to end the application.
#############################################################################

[0]: GX001559 (mvBlueCOUGAR-X122G, Family: mvBlueCOUGAR, interface layout: DeviceSpecific)

Please enter the number in front of the listed device followed by [ENTER] to open it: 0
Using device number 0.
Interface layout of device GX001559(mvBlueCOUGAR-X122G) set to 'GenICam'.

Acquisition start/stop behaviour(Defines the start/stop behaviour of the acquisition engine) of device 
GX001559(mvBlueCOUGAR-X122G) set to 'User'.
In 'Default' mode the acquisition engine will be started and stopped automatically, when set 
to 'User' it is up to the user to start and stop the acquisition engine. When this driver is
running with a 3rd party GenICam™ GenTL producer only 'User' will be available).

Initialising the device. This might take some time...

Property 'UserSetSelector' set to 'Default'.
Property 'ExposureMode' set to 'Timed'.
Property 'ExposureAuto' set to 'Off'.
Property 'GainSelector' set to 'AnalogAll'.
Property 'GainAuto' set to 'Off'.
Property 'GainSelector' set to 'DigitalAll'.
Press [ENTER] to end the application
Image captured: 0x0@1280x960. SequencerSetActive: 0, exposure time: 15006
Image captured: 0x0@1280x960. SequencerSetActive: 1, exposure time: 10006
Image captured: 0x0@1280x960. SequencerSetActive: 2, exposure time: 5012
Image captured: 0x0@1280x960. SequencerSetActive: 0, exposure time: 15011
Image captured: 0x0@1280x960. SequencerSetActive: 1, exposure time: 10007
Image captured: 0x0@1280x960. SequencerSetActive: 2, exposure time: 5013
Image captured: 0x0@1280x960. SequencerSetActive: 0, exposure time: 15011
Image captured: 0x0@1280x960. SequencerSetActive: 1, exposure time: 10006
Image captured: 0x0@1280x960. SequencerSetActive: 2, exposure time: 5012
Image captured: 0x0@1280x960. SequencerSetActive: 0, exposure time: 15011
Image captured: 0x0@1280x960. SequencerSetActive: 1, exposure time: 10007
Image captured: 0x0@1280x960. SequencerSetActive: 2, exposure time: 5013
...
Info from GX006621: FramesPerSecond: 3.827492, ErrorCount: 0, CaptureTime_s: 0.387333
Will set the exposure time of sequencer set 0 to 30000us.
Will set the exposure time of sequencer set 1 to 40000us.
Will set the exposure time of sequencer set 2 to 50000us.
Will set OffsetX of sequencer set 1 to 100.
Will set OffsetX of sequencer set 1 to 200.
Image captured: 0x0@1280x960. SequencerSetActive: 2, exposure time: 5013   // note that the changes are applied as fast as possible but there might already be pending
Image captured: 0x0@1280x960. SequencerSetActive: 0, exposure time: 15011  // images that have been exposed and await transmission or processing on the host!
Image captured: 100x200@1280x960. SequencerSetActive: 1, exposure time: 10006
Image captured: 0x0@1280x960. SequencerSetActive: 2, exposure time: 5012
Image captured: 0x0@1280x960. SequencerSetActive: 0, exposure time: 30011
Image captured: 100x200@1280x960. SequencerSetActive: 1, exposure time: 40010
Image captured: 0x0@1280x960. SequencerSetActive: 2, exposure time: 50008
Image captured: 0x0@1280x960. SequencerSetActive: 0, exposure time: 30010
Image captured: 100x200@1280x960. SequencerSetActive: 1, exposure time: 40009
Image captured: 0x0@1280x960. SequencerSetActive: 2, exposure time: 50007
Image captured: 0x0@1280x960. SequencerSetActive: 0, exposure time: 30011
Image captured: 100x200@1280x960. SequencerSetActive: 1, exposure time: 40010
Image captured: 0x0@1280x960. SequencerSetActive: 2, exposure time: 50008
Image captured: 0x0@1280x960. SequencerSetActive: 0, exposure time: 30011
Image captured: 100x200@1280x960. SequencerSetActive: 1, exposure time: 40009
Image captured: 0x0@1280x960. SequencerSetActive: 2, exposure time: 50008
Image captured: 0x0@1280x960. SequencerSetActive: 0, exposure time: 30011
Image captured: 100x200@1280x960. SequencerSetActive: 1, exposure time: 40010
Image captured: 0x0@1280x960. SequencerSetActive: 2, exposure time: 50007
Image captured: 0x0@1280x960. SequencerSetActive: 0, exposure time: 30011
Image captured: 100x200@1280x960. SequencerSetActive: 1, exposure time: 40009
Image captured: 0x0@1280x960. SequencerSetActive: 2, exposure time: 50008
Image captured: 0x0@1280x960. SequencerSetActive: 0, exposure time: 30011
Image captured: 100x200@1280x960. SequencerSetActive: 1, exposure time: 40010
How it works
After getting the device from user input the sample tries to
  1. set the mvIMPACT::acquire::Device::interfaceLayout to mvIMPACT::acquire::dilGenICam
    pDev->interfaceLayout.write( dilGenICam );
  2. set the mvIMPACT::acquire::Device::acquisitionStartStopBehaviour to mvIMPACT::acquire::assbUser
    pDev->acquisitionStartStopBehaviour.write( assbUser );
    and to
  3. open the device by calling
    pDev->open();
  4. The sample shows, how to configure the Sequencer Control according to the SFNC (Standard Features Naming Convention) however as the things that can be done using the Sequencer Control are very specific and application dependent this example might not work with every GenICam™ compliant device as some features are just assumed as being available.
  5. Every 100th frame captured the application will dynamically change sequencer settings while the acquisition and the sequencer continue to run

The important bit of this application is the following function:

//-----------------------------------------------------------------------------
// This function will configure the sequencer on the device at runtime without
// stopping the acquisition of the sequencer program. This approach is much faster
// than the usual way.
void configureSequencerAtRuntime( ThreadParameter* pTP, const bool boApplyOriginalData )
//-----------------------------------------------------------------------------
{
try
{
if( boApplyOriginalData )
{
for( size_t i = 0; i < s_SequencerData.size(); i++ )
{
cout << "Will set the exposure time of sequencer set " << i << " to " << s_SequencerData[i].exposureTime_us_ << "us." << endl;
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( i ), sspExposureTime, s_SequencerData[i].exposureTime_us_ );
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( i ), sspExposureTime, s_SequencerData[i].exposureTime_us_ );
}
}
else
{
for( size_t i = 0; i < s_SequencerExposureDataForRuntimeChange.size(); i++ )
{
cout << "Will set the exposure time of sequencer set " << i << " to " << s_SequencerExposureDataForRuntimeChange[i] << "us." << endl;
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( i ), sspExposureTime, s_SequencerExposureDataForRuntimeChange[i] );
}
}
pTP->ccg.sendCommandBuffer();
}
catch( const ImpactAcquireException& e )
{
std::cout << "An error occurred while setting up the sequencer for device " << pTP->pDev->serial.read()
<< "(error code: " << e.getErrorCodeAsString() << ")." << endl;
s_boTerminated = true;
}
}

This function uses the mvIMPACT::acquire::GenICam::CustomCommandGenerator to generate custom commands understood by the device that will result in sequencer sets to change to the desired values. Refer to the documentation of the mvIMPACT::acquire::GenICam::CustomCommandGenerator to read more about how the commands are generated and what can be done using this class.

Source code
//
// @description: Example applications for Impact Acquire
// @copyright: Copyright (C) 2012 - 2023 Balluff GmbH
// @authors: APIs and drivers development team at Balluff GmbH
// @initial date: 2012-03-05
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,i
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#include <algorithm>
#include <array>
#include <functional>
#include <iostream>
#include <iomanip>
#include <thread>
#include <apps/Common/exampleHelper.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire_GenICam.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire_GenICam_CustomCommands.h>
#ifdef _WIN32
# include <conio.h>
# include <mvDisplay/Include/mvIMPACT_acquire_display.h>
# define USE_DISPLAY
enum keys
{
KEY_MINUS = 45,
KEY_PLUS = 43,
KEY_PAGEDOWN = 81,
KEY_PAGEUP = 73,
KEY_UP = 72,
KEY_DOWN = 80,
KEY_LEFT = 75,
KEY_RIGHT = 77,
KEY_SPACE = 32,
KEY_L = 108,
KEY_R = 114,
KEY_ENTER_CR = 13,
KEY_ENTER_LF = 10,
KEY_USELESS_ADDITIONAL_KEY_1 = 224,
KEY_USELESS_ADDITIONAL_KEY_2 = 1234, // does not happen
KEY_USELESS_ADDITIONAL_KEY_3 = 2345 // does not happen
};
#else // #ifdef _WIN32
# include <stdio.h>
# include <termios.h>
# include <unistd.h>
char _getch( void )
{
struct termios oldTerminalSettings, newTerminalSettings;
char ch;
tcgetattr( 0, &oldTerminalSettings ); /* grab old terminal i/o settings */
newTerminalSettings = oldTerminalSettings; /* make new settings same as old settings */
newTerminalSettings.c_lflag &= ~ICANON; /* disable buffered i/o */
newTerminalSettings.c_lflag &= ~ECHO; /* set no echo mode */
tcsetattr( 0, TCSANOW, &newTerminalSettings ); /* use these new terminal i/o settings now */
ch = getchar();
tcsetattr( 0, TCSANOW, &oldTerminalSettings ); /* reset to old terminal i/o settings */
return ch;
}
enum keys
{
KEY_MINUS = 45,
KEY_PLUS = 43,
KEY_PAGEDOWN = 54,
KEY_PAGEUP = 53,
KEY_UP = 65,
KEY_DOWN = 66,
KEY_LEFT = 68,
KEY_RIGHT = 67,
KEY_SPACE = 32,
KEY_L = 108,
KEY_R = 114,
KEY_ENTER_CR = 13,
KEY_ENTER_LF = 10,
KEY_USELESS_ADDITIONAL_KEY_1 = 27,
KEY_USELESS_ADDITIONAL_KEY_2 = 91,
KEY_USELESS_ADDITIONAL_KEY_3 = 126
};
#endif // #ifdef _WIN32
using namespace std;
using namespace mvIMPACT::acquire;
//=============================================================================
//================= Data type definitions =====================================
//=============================================================================
//-----------------------------------------------------------------------------
struct SequencerSetParameter
//-----------------------------------------------------------------------------
{
const int64_type setNr_;
const int64_type sequencerSetNext_;
const int64_type alternativeSetNext_;
const double exposureTime_us_;
explicit SequencerSetParameter( const int64_type setNr, const int64_type sequencerSetNext, const int64_type alternativeSetNext, const double exposureTime_us ) :
setNr_( setNr ), sequencerSetNext_( sequencerSetNext ), alternativeSetNext_( alternativeSetNext ), exposureTime_us_( exposureTime_us )
{
}
};
//-----------------------------------------------------------------------------
struct ThreadParameter
//-----------------------------------------------------------------------------
{
Device* pDev;
int curWidth;
int curHeight;
int setWidth;
int setHeight;
int maxSensorWidth;
int maxSensorHeight;
int minSensorWidth;
int minSensorHeight;
int maxAllowedWidth;
int maxAllowedHeight;
int minAllowedWidth;
int minAllowedHeight;
int widthStepWidth;
int heightStepWidth;
int numWidthSteps;
int numHeightSteps;
int curStepX;
int curStepY;
int setStepX;
int setStepY;
int minExpStep;
int maxExpStep;
int curStepExposure;
int setStepExposure;
bool applyInitialParameters;
bool runRandomParameters;
bool runLoopAndUserInputMode;
bool loopAndUserInputModeRunning;
#ifdef USE_DISPLAY
ImageDisplayWindow displayWindow;
#endif // #ifdef USE_DISPLAY
explicit ThreadParameter( Device* p ) : pDev( p ), ac( p ), ifc( p ), sc( p ), ccg( p ), dic( p ), curWidth( 0 ), curHeight( 0 ), setWidth( 0 ), setHeight( 0 ), maxSensorWidth( 0 ), maxSensorHeight( 0 ), minSensorWidth( 0 ), minSensorHeight( 0 ), maxAllowedWidth( 0 ), maxAllowedHeight( 0 ), minAllowedWidth( 0 ), minAllowedHeight( 0 ), widthStepWidth( 0 ), heightStepWidth( 0 ), numWidthSteps( 0 ), numHeightSteps( 0 ), curStepX( 0 ), curStepY( 0 ), setStepX( 0 ), setStepY( 0 ), minExpStep( 0 ), maxExpStep( 0 ), curStepExposure( 0 ), setStepExposure( 0 ), applyInitialParameters( true ), runRandomParameters( true ), runLoopAndUserInputMode( false ), loopAndUserInputModeRunning( false )
#ifdef USE_DISPLAY
// initialise display window
// IMPORTANT: It's NOT safe to create multiple display windows in multiple threads!!!
, displayWindow( "mvIMPACT_acquire sample, Device " + pDev->serial.read() )
#endif // #ifdef USE_DISPLAY
{
}
ThreadParameter( const ThreadParameter& src ) = delete;
ThreadParameter& operator=( const ThreadParameter& rhs ) = delete;
};
//=============================================================================
//================= static variables ==========================================
//=============================================================================
static bool s_boTerminated = false;
static array<SequencerSetParameter, 6> s_SequencerData =
{
SequencerSetParameter( 0, 1, 8, 11000. ), // Set 0: Capture 1 frame with an exposure time of 11000 us, then jump to set 1.
SequencerSetParameter( 1, 2, 8, 12000. ), // Set 1: Capture 1 frame with an exposure time of 12000 us, then jump to set 2.
SequencerSetParameter( 2, 3, 8, 13000. ), // Set 2: Capture 1 frame with an exposure time of 13000 us, then jump to set 3.
SequencerSetParameter( 3, 4, 8, 14000. ), // Set 3: Capture 1 frame with an exposure time of 14000 us, then jump to set 4.
SequencerSetParameter( 4, 5, 8, 15000. ), // Set 4: Capture 1 frame with an exposure time of 15000 us, then jump to set 5.
SequencerSetParameter( 5, 0, 8, 16000. ) // Set 5: Capture 1 frame with an exposure time of 16000 us, then jump back to set 0.
};
static array<SequencerSetParameter, 1> s_SequencerLoopData =
{
SequencerSetParameter( 8, 8, 0, 8888. ) // Set 8: Loop with an exposure time of 8888 us.
};
//=============================================================================
//================= function declarations =====================================
//=============================================================================
static void configureDevice( Device* pDev, ThreadParameter* pTP );
static bool isDeviceSupportedBySample( const Device* const pDev );
static void liveThread( ThreadParameter* pTP );
//=============================================================================
//================= implementation ============================================
//=============================================================================
//-----------------------------------------------------------------------------
void printHelp( void )
//-----------------------------------------------------------------------------
{
cout << "#############################################################################" << endl
<< "#############################################################################" << endl
<< "# This example runs " << s_SequencerData.size() << " SequencerSets, where the ExposureTime varies between" << endl
<< "# the SequencerSets. There are two modes. The example starts in random mode," << endl
<< "# where ExposureTime as well as OffsetX and OffsetY is changed every 100" << endl
<< "# images randomly. The manual mode allows to change these parameters using" << endl
<< "# keys:" << endl
<< "# [Space] (re)start manual mode" << endl
<< "# [l] (re)start loop mode" << endl
<< "# [r] go back to / restart random mode" << endl
<< "#" << endl
<< "# [Left] move AOI to the left" << endl
<< "# [Right] move AOI to the right" << endl
<< "# [Up] move AOI upwards" << endl
<< "# [Down] move AOI downwards" << endl
<< "# [+] increase AOI size" << endl
<< "# [-] decrease AOI size" << endl
<< "#" << endl
<< "# [PageUp] increase ExposureTime" << endl
<< "# [PageDown] decrease ExposureTime" << endl
<< "#############################################################################" << endl
<< "#############################################################################" << endl
<< "# Press [h] to show this help." << endl
<< "#############################################################################" << endl
<< "#############################################################################" << endl
<< "# Press [ENTER] to end the application." << endl
<< "#############################################################################" << endl
<< "#############################################################################" << endl;
}
//-----------------------------------------------------------------------------
// Calls the function bound to an mvIMPACT::acquire::Method object and displays
// an error message if the function call did fail.
void checkedMethodCall( Device* pDev, Method& method )
//-----------------------------------------------------------------------------
{
const TDMR_ERROR result = static_cast<TDMR_ERROR>( method.call() );
if( result != DMR_NO_ERROR )
{
std::cout << "An error was returned while calling function '" << method.displayName() << "' on device " << pDev->serial.read()
<< "(" << pDev->product.read() << "): " << ImpactAcquireException::getErrorCodeAsString( result ) << endl;
}
}
//-----------------------------------------------------------------------------
// Configures all the stuff that needs to be done only once. All the stuff related
// to setting up the actual sequencer could be called multiple times whenever an
// application gets re-configured. This is not the case here, but the code has been
// split in order to logically group what belongs together.
//
// Whenever 'conditionalSetEnumPropertyByString' or 'conditionalSetProperty' is
// not used here the stuff MUST succeed as otherwise when the device doesn't allow
// this feature the whole example does not work!
void configureDevice( Device* pDev, ThreadParameter* pTP )
//-----------------------------------------------------------------------------
{
try
{
// Restore the factory default first in order to make sure nothing is incorrectly configured
conditionalSetEnumPropertyByString( usc.userSetSelector, "Default" );
const TDMR_ERROR result = static_cast<TDMR_ERROR>( usc.userSetLoad.call() );
if( result != DMR_NO_ERROR )
{
std::cout << "An error occurred while restoring the factory default for device " << pDev->serial.read()
<< "(error code: " << ImpactAcquireException::getErrorCodeAsString( result ) << ")." << endl;
}
// Auto exposure or an open shutter will not be helpful for this example thus switch it off if possible.
conditionalSetEnumPropertyByString( acqc.exposureMode, "Timed" );
conditionalSetEnumPropertyByString( acqc.exposureAuto, "Off" );
// Auto gain will not be helpful for this example either thus switch it off if possible.
if( ac.gainSelector.isValid() )
{
// There might be more than a single 'Gain' as a 'GainSelector' is present. Iterate over all
// 'Gain's that can be configured and switch off every 'Auto' feature detected.
vector<string> validGainSelectorValues;
ac.gainSelector.getTranslationDictStrings( validGainSelectorValues );
for( const auto& gainSelectorValue : validGainSelectorValues )
{
conditionalSetEnumPropertyByString( ac.gainSelector, gainSelectorValue );
conditionalSetEnumPropertyByString( ac.gainAuto, "Off" );
}
}
else
{
// There is just a single 'Gain' turn off the 'Auto' feature if supported.
conditionalSetEnumPropertyByString( ac.gainAuto, "Off" );
}
// Chunk mode is needed in order to get back all the information needed to properly check
// if an image has been taken using the desired parameters.
cdc.chunkModeActive.write( bTrue );
// We want to act fast, thus if e.g. Bayer-images arrive in the system do NOT convert them on the fly as depending
// on the device speed the host system might be too slow deal with the amount of data
ImageProcessing ip( pDev );
ip.colorProcessing.write( cpmRaw );
if( ip.tapSortEnable.isValid() )
{
ip.tapSortEnable.write( bFalse );
}
// Get width and height
pTP->maxSensorWidth = static_cast<int>( pTP->ifc.widthMax.read() );
pTP->maxSensorHeight = static_cast<int>( pTP->ifc.heightMax.read() );
pTP->minSensorWidth = static_cast<int>( pTP->ifc.width.getMinValue() );
pTP->minSensorHeight = static_cast<int>( pTP->ifc.height.getMinValue() );
pTP->widthStepWidth = static_cast<int>( pTP->ifc.width.getStepWidth() );
pTP->heightStepWidth = static_cast<int>( pTP->ifc.height.getStepWidth() );
pTP->curWidth = pTP->maxAllowedWidth = ( min( ( pTP->maxSensorWidth - pTP->minSensorWidth ) * 2 / 3, 1600 ) / pTP->widthStepWidth ) * pTP->widthStepWidth;
pTP->curHeight = pTP->maxAllowedHeight = ( min( ( pTP->maxSensorHeight - pTP->minSensorHeight ) * 2 / 3, 1024 ) / pTP->heightStepWidth ) * pTP->heightStepWidth;
pTP->ifc.width.write( pTP->curWidth );
pTP->ifc.height.write( pTP->curHeight );
pTP->minAllowedWidth = ( max( ( pTP->maxSensorWidth - pTP->minSensorWidth ) * 1 / 10, 512 ) / pTP->widthStepWidth ) * pTP->widthStepWidth;
pTP->minAllowedHeight = ( max( ( pTP->maxSensorHeight - pTP->minSensorHeight ) * 1 / 10, 512 ) / pTP->heightStepWidth ) * pTP->heightStepWidth;
do
{
pTP->numWidthSteps = ( pTP->maxSensorWidth - pTP->curWidth ) / pTP->widthStepWidth;
if( pTP->numWidthSteps > 100 )
{
pTP->widthStepWidth *= 2;
}
}
while( pTP->numWidthSteps > 100 );
do
{
pTP->numHeightSteps = ( pTP->maxSensorHeight - pTP->curHeight ) / pTP->heightStepWidth;
if( pTP->numHeightSteps > 100 )
{
pTP->heightStepWidth *= 2;
}
}
while( pTP->numHeightSteps > 100 );
pTP->curStepX = pTP->numWidthSteps / 2;
pTP->curStepY = pTP->numHeightSteps / 2;
cout << "#############################################################################" << endl
<< "#############################################################################" << endl
<< "Width: max=" << pTP->maxSensorWidth << "=" << pTP->maxAllowedWidth << " cur=" << pTP->curWidth << " minAllowed=" << pTP->minAllowedWidth << " min=" << pTP->minSensorWidth << " step=" << pTP->widthStepWidth << endl
<< "Height: max=" << pTP->maxSensorHeight << "=" << pTP->maxAllowedHeight << " cur=" << pTP->curHeight << " minAllowed=" << pTP->minAllowedHeight << " min=" << pTP->minSensorHeight << " step=" << pTP->heightStepWidth << endl
<< "numWidthSteps=" << pTP->numWidthSteps << endl
<< "numHeightSteps=" << pTP->numHeightSteps << endl
<< "curStepX=" << pTP->curStepX << endl
<< "curStepY=" << pTP->curStepY << endl
<< "#############################################################################" << endl
<< "#############################################################################" << endl;
pTP->minExpStep = 1;
pTP->curStepExposure = 10;
pTP->maxExpStep = static_cast<int>( ( acqc.exposureTime.getMaxValue() / 1000 ) - 2 );
}
catch( const ImpactAcquireException& e )
{
// This e.g. might happen if the same device is already opened in another process...
std::cout << "An error occurred while configuring the device " << pDev->serial.read()
<< "(error code: " << e.getErrorCodeAsString() << ")." << endl
<< "Press [ENTER] to end the application..." << endl;
cin.get();
exit( 1 );
}
}
//-----------------------------------------------------------------------------
// Configures a single 'SequencerSet' so that 'X' frames are captured using a
// certain exposure time and afterwards another sets will be used.
void configureSequencerSet( ThreadParameter* pTP, const SequencerSetParameter& ssp )
//-----------------------------------------------------------------------------
{
pTP->sc.sequencerSetSelector.write( ssp.setNr_ );
pTP->ac.exposureTime.write( ssp.exposureTime_us_ );
pTP->sc.sequencerPathSelector.write( 0LL );
pTP->sc.sequencerTriggerSource.writeS( "ExposureEnd" );
pTP->sc.sequencerSetNext.write( ssp.sequencerSetNext_ );
pTP->sc.sequencerPathSelector.write( 1LL );
pTP->sc.sequencerTriggerSource.writeS( "UserOutput0" );
pTP->sc.sequencerSetNext.write( ssp.alternativeSetNext_ );
checkedMethodCall( pTP->pDev, pTP->sc.sequencerSetSave );
}
//-----------------------------------------------------------------------------
// This function will configure the sequencer on the device to take a sequence of
// 'X' images with different exposure times. To change the sequence edit the
// 's_SequencerData' data array and recompile the application.
void configureSequencer( ThreadParameter* pTP )
//-----------------------------------------------------------------------------
{
try
{
pTP->sc.sequencerMode.writeS( "Off" );
pTP->sc.sequencerConfigurationMode.writeS( "On" );
pTP->sc.sequencerFeatureSelector.writeS( "ExposureTime" );
pTP->sc.sequencerFeatureEnable.write( bTrue );
pTP->sc.sequencerFeatureSelector.writeS( "mvImagePositionAndSize" );
pTP->sc.sequencerFeatureEnable.write( bTrue );
for_each( s_SequencerData.begin(), s_SequencerData.end(), [pTP]( const SequencerSetParameter & sequencerSetParameter )
{
configureSequencerSet( pTP, sequencerSetParameter );
} );
for_each( s_SequencerLoopData.begin(), s_SequencerLoopData.end(), [pTP]( const SequencerSetParameter & sequencerSetParameter )
{
configureSequencerSet( pTP, sequencerSetParameter );
} );
pTP->sc.sequencerSetStart.write( 0 );
pTP->sc.sequencerConfigurationMode.writeS( "Off" );
pTP->sc.sequencerMode.writeS( "On" );
}
catch( const ImpactAcquireException& e )
{
std::cout << "An error occurred while setting up the sequencer for device " << pTP->pDev->serial.read()
<< "(error code: " << e.getErrorCodeAsString() << ")." << endl;
s_boTerminated = true;
}
}
//-----------------------------------------------------------------------------
// This function will configure the sequencer on the device at runtime without
// stopping the acquisition of the sequencer program. This approach is much faster
// than the usual way.
void configureSequencerAtRuntime( ThreadParameter* pTP )
//-----------------------------------------------------------------------------
{
try
{
if( pTP->runLoopAndUserInputMode == false && pTP->loopAndUserInputModeRunning == true )
{
pTP->dic.userOutputSelector.write( 0 );
pTP->dic.userOutputValue.write( bFalse );
pTP->dic.userOutputValue.write( bTrue );
pTP->dic.userOutputValue.write( bFalse );
pTP->loopAndUserInputModeRunning = false;
}
if( pTP->runRandomParameters )
{
static bool s_boApplyOriginalData = true;
if( s_boApplyOriginalData )
{
for( size_t i = 0; i < s_SequencerData.size(); i++ )
{
//cout << "Will set the exposure time of sequencer set " << i << " to " << s_SequencerData[i].exposureTime_us_ << "us." << endl;
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( i ), sspExposureTime, s_SequencerData[i].exposureTime_us_ );
}
}
else
{
for( size_t i = 0; i < s_SequencerData.size(); i++ )
{
//cout << "Will set the exposure time of sequencer set " << i << " to " << s_SequencerData[i].exposureTime_us_ * 3 << "us." << endl;
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( i ), sspExposureTime, s_SequencerData[i].exposureTime_us_ * 3 );
}
}
s_boApplyOriginalData = !s_boApplyOriginalData;
// Use random sequencer set number
int sequencerSetNumber = rand() % s_SequencerData.size();
// Set random OffsetX and OffsetY for partial AOIs.
int64_t offsetX = rand() % ( pTP->maxSensorWidth - pTP->curWidth );
offsetX -= offsetX % pTP->ifc.offsetX.getStepWidth();
//cout << "Will set OffsetX of sequencer set " << sequencerSetNumber << " to " << offsetX << "." << endl;
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( sequencerSetNumber ), sspOffsetX, offsetX );
int64_t offsetY = rand() % ( pTP->maxSensorHeight - pTP->curHeight );
offsetY -= offsetY % pTP->ifc.offsetY.getStepWidth();
//cout << "Will set OffsetY of sequencer set " << sequencerSetNumber << " to " << offsetY << "." << endl;
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( sequencerSetNumber ), sspOffsetY, offsetY );
}
else
{
if( pTP->applyInitialParameters )
{
if( pTP->runLoopAndUserInputMode == true && pTP->loopAndUserInputModeRunning == false )
{
pTP->dic.userOutputSelector.write( 0 );
pTP->dic.userOutputValue.write( bFalse );
pTP->dic.userOutputValue.write( bTrue );
pTP->dic.userOutputValue.write( bFalse );
pTP->loopAndUserInputModeRunning = true;
}
pTP->curStepX = pTP->numWidthSteps / 2;
pTP->curStepY = pTP->numHeightSteps / 2;
pTP->curStepExposure = static_cast<int>( ( s_SequencerData[0].exposureTime_us_ / 1000 ) );
pTP->curWidth = ( min( ( pTP->maxSensorWidth - pTP->minSensorWidth ) * 2 / 3, 1600 ) / pTP->widthStepWidth ) * pTP->widthStepWidth;
pTP->curHeight = ( min( ( pTP->maxSensorHeight - pTP->minSensorHeight ) * 2 / 3, 1024 ) / pTP->heightStepWidth ) * pTP->heightStepWidth;
}
int64_t offsetX = pTP->curStepX * pTP->widthStepWidth;
int64_t offsetY = pTP->curStepY * pTP->heightStepWidth;
double startExposure = pTP->curStepExposure * 1000.0;
//cout << "Will set the offsets of all sequencer sets to " << offsetX << "x" << offsetY << " and start exposure to " << startExposure << "us." << endl;
if( pTP->loopAndUserInputModeRunning )
{
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( s_SequencerLoopData[0].setNr_ ), sspExposureTime, startExposure + 880. );
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( s_SequencerLoopData[0].setNr_ ), sspOffsetX, offsetX );
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( s_SequencerLoopData[0].setNr_ ), sspOffsetY, offsetY );
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( s_SequencerLoopData[0].setNr_ ), sspWidth, static_cast<int64_type>( pTP->curWidth ) );
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( s_SequencerLoopData[0].setNr_ ), sspHeight, static_cast<int64_type>( pTP->curHeight ) );
}
else
{
for( size_t i = 0; i < s_SequencerData.size(); i++ )
{
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( i ), sspExposureTime, startExposure + ( i * 1000.0 ) );
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( i ), sspOffsetX, offsetX );
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( i ), sspOffsetY, offsetY );
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( i ), sspWidth, static_cast<int64_type>( pTP->curWidth ) );
pTP->ccg.queueSequencerSetValueModification( static_cast<int64_type>( i ), sspHeight, static_cast<int64_type>( pTP->curHeight ) );
}
}
}
// send out data
int sendCommandBufferResult = pTP->ccg.sendCommandBuffer();
if( sendCommandBufferResult != DMR_NO_ERROR )
{
cout << "sendCommandBuffer failed(error code: " << sendCommandBufferResult << "(" << ImpactAcquireException::getErrorCodeAsString( sendCommandBufferResult ) << "))!" << endl;
}
// reset flags
pTP->setWidth = pTP->curWidth;
pTP->setHeight = pTP->curHeight;
pTP->setStepX = pTP->curStepX;
pTP->setStepY = pTP->curStepY;
pTP->setStepExposure = pTP->curStepExposure;
pTP->applyInitialParameters = false;
}
catch( const ImpactAcquireException& e )
{
std::cout << "An error occurred while setting up the sequencer for device " << pTP->pDev->serial.read()
<< "(error code: " << e.getErrorCodeAsString() << ")." << endl;
s_boTerminated = true;
}
}
//-----------------------------------------------------------------------------
// This function will allow to select devices that support the GenICam interface
// layout(these are devices, that claim to be compliant with the GenICam standard)
// and that are bound to drivers that support the user controlled start and stop
// of the internal acquisition engine. Other devices will not be listed for
// selection as the code of the example relies on these features in the code.
bool isDeviceSupportedBySample( const Device* const pDev )
//-----------------------------------------------------------------------------
{
if( !pDev->interfaceLayout.isValid() &&
{
return false;
}
vector<TDeviceInterfaceLayout> availableInterfaceLayouts;
pDev->interfaceLayout.getTranslationDictValues( availableInterfaceLayouts );
return find( availableInterfaceLayouts.begin(), availableInterfaceLayouts.end(), dilGenICam ) != availableInterfaceLayouts.end();
}
//-----------------------------------------------------------------------------
void liveThread( ThreadParameter* pTP )
//-----------------------------------------------------------------------------
{
pTP->ac.acquisitionFrameRateEnable.write( bTrue );
pTP->ac.acquisitionFrameRate.write( 10.0 );
// establish access to the statistic properties
Statistics statistics( pTP->pDev );
// create an interface to the device found
FunctionInterface fi( pTP->pDev );
configureSequencer( pTP );
configureSequencerAtRuntime( pTP );
// Send all requests to the capture queue. There can be more than 1 queue for some devices, but for this sample
// we will work with the default capture queue. If a device supports more than one capture or result
// queue, this will be stated in the manual. If nothing is mentioned about it, the device supports one
// queue only. This loop will send all requests currently available to the driver. To modify the number of requests
// use the property mvIMPACT::acquire::SystemSettings::requestCount at runtime (note that some devices will
// only allow to modify this parameter while NOT streaming data!) or the property
// mvIMPACT::acquire::Device::defaultRequestCount BEFORE opening the device.
while( ( result = static_cast<TDMR_ERROR>( fi.imageRequestSingle() ) ) == DMR_NO_ERROR )
{
};
if( result != DEV_NO_FREE_REQUEST_AVAILABLE )
{
cout << "'FunctionInterface.imageRequestSingle' returned with an unexpected result: " << result
<< "(" << ImpactAcquireException::getErrorCodeAsString( result ) << ")" << endl;
}
manuallyStartAcquisitionIfNeeded( pTP->pDev, fi );
// run thread loop
mvIMPACT::acquire::Request* pRequest = nullptr;
// we always have to keep at least 2 images as the displayWindow module might want to repaint the image, thus we
// can free it unless we have a assigned the displayWindow to a new buffer.
mvIMPACT::acquire::Request* pPreviousRequest = nullptr;
const unsigned int timeout_ms = { 500 };
unsigned int cnt = { 0 };
while( !s_boTerminated )
{
// wait for results from the default capture queue
int requestNr = fi.imageRequestWaitFor( timeout_ms );
pRequest = fi.isRequestNrValid( requestNr ) ? fi.getRequest( requestNr ) : nullptr;
if( pRequest != nullptr )
{
if( pRequest->isOK() )
{
// within this scope we have a valid buffer of data that can be an image or any other chunk of data.
++cnt;
// here we can display some statistical information every 100th image
if( cnt % 100 == 0 )
{
cout << "Info from " << pTP->pDev->serial.read()
<< ": " << statistics.framesPerSecond.name() << ": " << statistics.framesPerSecond.readS()
<< ", " << statistics.errorCount.name() << ": " << statistics.errorCount.readS()
<< ", " << statistics.captureTime_s.name() << ": " << statistics.captureTime_s.readS() << endl;
configureSequencerAtRuntime( pTP );
}
if( pTP->setStepX != pTP->curStepX || pTP->setStepY != pTP->curStepY || pTP->setStepExposure != pTP->curStepExposure || pTP->applyInitialParameters || pTP->setWidth != pTP->curWidth || pTP->setHeight != pTP->curHeight )
{
configureSequencerAtRuntime( pTP );
}
cout << "Image #" << setw( 5 ) << pRequest->infoFrameID.read() << " captured" << ": " << setw( 4 ) << pRequest->imageOffsetX.read() << "x" << setw( 4 ) << pRequest->imageOffsetY.read()
<< "@" << setw( 4 ) << pRequest->imageWidth.read() << "x" << setw( 4 ) << pRequest->imageHeight.read()
<< " ExposureTime: " << setw( 7 ) << pRequest->chunkExposureTime.read() << " SequencerSetActive: " << setw( 2 ) << pRequest->chunkSequencerSetActive.read() << endl;
#ifdef USE_DISPLAY
pTP->displayWindow.GetImageDisplay().SetImage( pRequest );
pTP->displayWindow.GetImageDisplay().Update();
#endif // #ifdef USE_DISPLAY
}
if( pPreviousRequest )
{
// this image has been displayed thus the buffer is no longer needed...
pPreviousRequest->unlock();
}
pPreviousRequest = pRequest;
// send a new image request into the capture queue
fi.imageRequestSingle();
}
//else
//{
// Please note that slow systems or interface technologies in combination with high resolution sensors
// might need more time to transmit an image than the timeout value which has been passed to imageRequestWaitFor().
// If this is the case simply wait multiple times OR increase the timeout(not recommended as usually not necessary
// and potentially makes the capture thread less responsive) and rebuild this application.
// Once the device is configured for triggered image acquisition and the timeout elapsed before
// the device has been triggered this might happen as well.
// The return code would be -2119(DEV_WAIT_FOR_REQUEST_FAILED) in that case. The documentation will provide
// additional information under TDMR_ERROR in the interface reference.
// If waiting with an infinite timeout(-1) it will be necessary to call 'imageRequestReset' from another thread
// to force 'imageRequestWaitFor' to return when no data is coming from the device/can be captured.
// cout << "imageRequestWaitFor failed (" << requestNr << ", " << ImpactAcquireException::getErrorCodeAsString( requestNr ) << ")"
// << ", timeout value too small?" << endl;
//}
}
manuallyStopAcquisitionIfNeeded( pTP->pDev, fi );
#ifdef USE_DISPLAY
// stop the display from showing freed memory
pTP->displayWindow.GetImageDisplay().RemoveImage();
#endif // #ifdef USE_DISPLAY
// In this sample all the next lines are redundant as the device driver will be
// closed now, but in a real world application a thread like this might be started
// several times an then it becomes crucial to clean up correctly.
// free the last potentially locked request
if( pRequest != nullptr )
{
pRequest->unlock();
}
// clear all queues
fi.imageRequestReset( 0, 0 );
}
//-----------------------------------------------------------------------------
int main( void )
//-----------------------------------------------------------------------------
{
DeviceManager devMgr;
Device* pDev = getDeviceFromUserInput( devMgr, isDeviceSupportedBySample );
if( pDev == nullptr )
{
cout << "Could not obtain a valid pointer to a device. Unable to continue!";
cout << "Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
try
{
cout << "Initialising the device. This might take some time..." << endl << endl;
pDev->interfaceLayout.write( dilGenICam ); // This is also done 'silently' by the 'getDeviceFromUserInput' function but your application needs to do this as well so state this here clearly!
pDev->open();
}
catch( const ImpactAcquireException& e )
{
// this e.g. might happen if the same device is already opened in another process...
cout << "An error occurred while opening device " << pDev->serial.read()
<< "(error code: " << e.getErrorCodeAsString() << ")." << endl
<< "Press [ENTER] to end the application..." << endl;
cin.get();
return 1;
}
try
{
ThreadParameter threadParam( pDev );
configureDevice( pDev, &threadParam );
// start the execution of the 'live' thread.
printHelp();
thread myThread( liveThread, &threadParam );
// now wait for key strokes to change the sequencer sets
int c = 0;
while( c != KEY_ENTER_CR && c != KEY_ENTER_LF )
{
c = _getch();
switch( c )
{
case KEY_MINUS:
if( threadParam.curWidth > threadParam.minAllowedWidth && threadParam.curHeight > threadParam.minAllowedHeight )
{
threadParam.curWidth -= threadParam.widthStepWidth;
threadParam.curHeight -= threadParam.heightStepWidth;
//cout << "Smaller (" << threadParam.curWidth << "x" << threadParam.curHeight << ")" << endl;
}
else
{
cout << "Minimal image size for this test reached!" << endl;
}
break;
case KEY_PLUS:
if( threadParam.curWidth < threadParam.maxAllowedWidth && threadParam.curHeight < threadParam.maxAllowedHeight )
{
threadParam.curWidth += threadParam.widthStepWidth;
threadParam.curHeight += threadParam.heightStepWidth;
//cout << "Larger (" << threadParam.curWidth << "x" << threadParam.curHeight << ")" << endl;
}
else
{
cout << "Maximal image size for this test reached!" << endl;
}
break;
case KEY_PAGEDOWN:
if( threadParam.curStepExposure > threadParam.minExpStep + 10 - 1 )
{
threadParam.curStepExposure -= 10;
//cout << "Darkererer (" << threadParam.curStepExposure << ")" << endl;
}
else if( threadParam.curStepExposure > threadParam.minExpStep )
{
threadParam.curStepExposure = threadParam.minExpStep;
}
else
{
cout << "Darkness reached!" << endl;
}
break;
case KEY_PAGEUP:
if( threadParam.curStepExposure < threadParam.maxExpStep - 10 + 1 )
{
threadParam.curStepExposure += 10;
//cout << "Lightererer (" << threadParam.curStepExposure << ")" << endl;
}
else if( threadParam.curStepExposure < threadParam.maxExpStep )
{
threadParam.curStepExposure = threadParam.maxExpStep;
}
else
{
cout << "Light reached!" << endl;
}
break;
case KEY_UP:
if( threadParam.curStepY > 1 )
{
threadParam.curStepY--;
//cout << "Up (" << threadParam.curStepY << ")" << endl;
}
else
{
cout << "Top reached!" << endl;
}
break;
case KEY_DOWN:
if( threadParam.curStepY < threadParam.numHeightSteps - 1 )
{
threadParam.curStepY++;
//cout << "Down (" << threadParam.curStepY << ")" << endl;
}
else
{
cout << "Bottom reached!" << endl;
}
break;
case KEY_LEFT:
if( threadParam.curStepX > 1 )
{
threadParam.curStepX--;
//cout << "Left (" << threadParam.curStepX << ")" << endl;
}
else
{
cout << "Left - End reached!" << endl;
}
break;
case KEY_RIGHT:
if( threadParam.curStepX < threadParam.numWidthSteps - 1 )
{
threadParam.curStepX++;
//cout << "Right (" << threadParam.curStepX << ")" << endl;
}
else
{
cout << "Right - End reached!" << endl;
}
break;
case KEY_SPACE:
cout << "Resetting..." << endl;
threadParam.runRandomParameters = false;
threadParam.runLoopAndUserInputMode = false;
threadParam.applyInitialParameters = true;
break;
case KEY_L:
cout << "Looping..." << endl;
threadParam.runRandomParameters = false;
threadParam.runLoopAndUserInputMode = true;
threadParam.applyInitialParameters = true; // as trigger
break;
case KEY_R:
cout << "Random..." << endl;
threadParam.runRandomParameters = true;
threadParam.runLoopAndUserInputMode = false;
threadParam.applyInitialParameters = true; // as trigger
break;
case KEY_ENTER_CR:
case KEY_ENTER_LF:
cout << "Ending..." << endl;
break;
case KEY_USELESS_ADDITIONAL_KEY_1:
case KEY_USELESS_ADDITIONAL_KEY_2:
case KEY_USELESS_ADDITIONAL_KEY_3:
// for some of the keys these values are entered additionally and must be ignored
break;
default:
cout << "\n\n\n" << endl;
printHelp();
cout << endl << "unknown: -" << c << "-" << endl << endl << endl;
break;
}
}
s_boTerminated = true;
myThread.join();
}
catch( const ImpactAcquireException& e )
{
// this e.g. might happen if the same device is already opened in another process...
cout << "An error occurred while setting up device " << pDev->serial.read()
<< "(error code: " << e.getErrorCodeAsString() << ")." << endl
<< "Press [ENTER] to end the application..." << endl;
cin.get();
return 1;
}
return 0;
}
std::string displayName(void) const
Returns the display name of the component referenced by this object.
Definition mvIMPACT_acquire.h:1217
bool isValid(void) const
Checks if the internal component referenced by this object is still valid.
Definition mvIMPACT_acquire.h:1721
Grants access to devices that can be operated by this software interface.
Definition mvIMPACT_acquire.h:7159
This class and its functions represent an actual device detected by this interface in the current sys...
Definition mvIMPACT_acquire.h:6118
PropertyS product
A string property (read-only) containing the product name of this device.
Definition mvIMPACT_acquire.h:6536
PropertyS serial
A string property (read-only) containing the serial number of this device.
Definition mvIMPACT_acquire.h:6550
void open(void)
Opens a device.
Definition mvIMPACT_acquire.h:6419
PropertyIDeviceInterfaceLayout interfaceLayout
An enumerated integer property which can be used to define which interface layout shall be used when ...
Definition mvIMPACT_acquire.h:6643
PropertyIAcquisitionStartStopBehaviour acquisitionStartStopBehaviour
An enumerated integer property defining the start/stop behaviour during acquisition of this driver in...
Definition mvIMPACT_acquire.h:6788
ZYX read(int index=0) const
Reads a value from a property.
Definition mvIMPACT_acquire.h:3853
ZYX read(int index=0) const
Reads a value from a property.
Definition mvIMPACT_acquire.h:4907
ZYX read(int index=0) const
Reads a value from a property.
Definition mvIMPACT_acquire.h:4300
const EnumPropertyI & getTranslationDictValues(std::vector< ZYX > &sequence) const
This function queries a list of valid values for this property.
Definition mvIMPACT_acquire.h:4266
const EnumPropertyI & write(ZYX value, int index=0) const
Writes one value to the property.
Definition mvIMPACT_acquire.h:4426
The function interface to devices supported by this interface.
Definition mvIMPACT_acquire.h:10746
Category for the acquisition and trigger control features.
Definition mvIMPACT_acquire_GenICam.h:2108
Category that contains the Analog control features.
Definition mvIMPACT_acquire_GenICam.h:3079
Category that contains the Chunk Data control features.
Definition mvIMPACT_acquire_GenICam.h:11816
Contains convenience functions to control features understood by a devices custom command interpreter...
Definition mvIMPACT_acquire_GenICam_CustomCommands.h:439
Category that contains the digital input and output control features.
Definition mvIMPACT_acquire_GenICam.h:3910
Category for Image Format Control features.
Definition mvIMPACT_acquire_GenICam.h:1132
Category for the Sequencer Control features.
Definition mvIMPACT_acquire_GenICam.h:9798
Category that contains the User Set control features.
Definition mvIMPACT_acquire_GenICam.h:9625
Base class for image processing related properties.
Definition mvIMPACT_acquire.h:13193
A base class for exceptions generated by Impact Acquire.
Definition mvIMPACT_acquire.h:256
std::string getErrorCodeAsString(void) const
Returns a string representation of the error associated with the exception.
Definition mvIMPACT_acquire.h:288
A class to call arbitrary driver functions.
Definition mvIMPACT_acquire.h:2779
int call(const std::vector< std::string > &params) const
Calls an underlying driver function.
Definition mvIMPACT_acquire.h:2859
std::string read(int index=0) const
Reads a value from a property.
Definition mvIMPACT_acquire.h:5323
Contains information about a captured buffer.
Definition mvIMPACT_acquire.h:8628
PropertyI64 infoFrameID
A 64 bit integer property (read-only) containing a frame identifier.
Definition mvIMPACT_acquire.h:9837
PropertyI imageHeight
An integer property (read-only) containing the height of the image in pixels.
Definition mvIMPACT_acquire.h:10319
bool isOK(void) const
Convenience function to check if a request has been processed successfully.
Definition mvIMPACT_acquire.h:9462
PropertyI imageWidth
An integer property (read-only) containing the width of the image in pixels.
Definition mvIMPACT_acquire.h:10308
PropertyF chunkExposureTime
A floating point property (read-only) containing the exposure time used to capture the image as retur...
Definition mvIMPACT_acquire.h:10072
int unlock(void)
Unlocks the request for the driver again.
Definition mvIMPACT_acquire.h:9602
PropertyI64 chunkSequencerSetActive
A 64-bit integer property (read-only) containing the index of the active set of the running sequencer...
Definition mvIMPACT_acquire.h:10092
PropertyI imageOffsetX
An integer property (read-only) containing the X-offset of the image in pixels.
Definition mvIMPACT_acquire.h:10300
PropertyI imageOffsetY
An integer property (read-only) containing the Y-offset of the image in pixels.
Definition mvIMPACT_acquire.h:10306
Contains basic statistical information.
Definition mvIMPACT_acquire.h:14497
A class that can be used to display images in a window.
Definition mvIMPACT_acquire_display.h:587
TDMR_ERROR
Errors reported by the device manager.
Definition mvDriverBaseEnums.h:2601
@ DMR_NO_ERROR
The function call was executed successfully.
Definition mvDriverBaseEnums.h:2603
@ sspOffsetX
Requests the OffsetX property to be modified in a user selected sequencer set.
Definition mvCustomCommandDataTypes.h:138
@ sspOffsetY
Requests the OffsetY property to be modified in a user selected sequencer set.
Definition mvCustomCommandDataTypes.h:143
This namespace contains classes and functions that can be used to display images.
This namespace contains classes and functions belonging to the image acquisition module of this SDK.
Definition mvCommonDataTypes.h:34