Sensor API v2.5.0
Sensor Configuration

This page clarifies usage of sensor parameters in the SDK.

Sensor Modes

The sensor works either in peak or raw data mode. Changing of mode during grabbing is a slow operation (typically about 1 second).

The Peak Mode (default)

Typically peak mode is used. In this mode the sensor processes a raw image and provides points to the application. Each point output contains x coordinate, height and intensity values.

Example of received 3D points when two grooves are measured:

PeakMode.png

Raw Mode

In a raw mode gray scale image from the sensor is captured. This mode is useful when sensor capabilities are studied.

Example of raw image where two grooves are measured:

C++:

CameraStatus status = static_cast<CameraStatus>(_SetIntParameter(sensor_ids[0], PARAM_PEAK_ENABLE, 1));
{
printf("FSAPI error: %d\n", status);
}

C#:

var cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.PeakEnabled, 1);
RawMode.png

Maximum size of the raw image equals sensor size. Sensor size for LCI401, LCI1200, LCI1201 and LCI1600 sensors is 1088 (vertical) x 2048 (horizontal) pixels. For LCI2020 and LCI1620 sensors size is 1400 (vertical) x 1728 (horizontal) pixels.

Maximum frequency of raw image is limited by the Ethernet interface. Required throughput can be calculated by formula image_height x 2048 x imaging_frequency.

Disable peak mode:

C++:

CameraStatus status = static_cast<CameraStatus>(_SetIntParameter(sensor_ids[0], PARAM_PEAK_ENABLE, 0));
{
printf("FSAPI error: %d\n", status);
}

C#:

var cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.PeakEnabled, 0);

Calibration Files

The sensor is calibrated in the FocalSpec's production to produce exact micrometer coordinates. Calibration files are stored in the sensors for those which are manufactured after 02/2019. If files are not in the sensor those must be set before image grabbing.

The sensor must be in the peak mode when calibration files are used. After files are set sensor unit must be set to use micrometers. If unit is not changed pixel units without calibration are used.

Use calibration files from the sensor

Following examples check whether calibration files exist in the sensor or not. If files exist only peak unit change is needed.

CameraStatus status = static_cast<CameraStatus>(_SetIntParameter(sensor_ids[0], PARAM_PEAK_ENABLE, 1));
int calibrations_in_sensor = 0;
_GetIntParameter(sensor_ids[0], const_cast<char*>(PARAM_SENSOR_DATA_IN_FLASH), &calibrations_in_sensor);
if (!calibrations_in_sensor)
{
_SetStringParameter(sensor_ids[0], PARAM_SENSOR_CALIBRATION_FILE, "C:\\temp\\zcalibration.calib");
_SetStringParameter(sensor_ids[0], PARAM_SENSOR_X_CALIBRATION_FILE, "C:\\temp\\xcalibration.calib");
}

C#:

var cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.PeakEnabled, 1);
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;
_sensor.GetParameter(_sensorId, SensorParameter.SensorDataInFlash, out int calibrationsInCamera);
if (calibrationsInCamera == 1)
{
cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.ZCalibrationFile, "C:\\temp\\lci1200z.dat");
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;
cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.XCalibrationFile, "C:\\temp\\lci1200x.dat");
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;
}
cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.PeakXUnit, 1);
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;
cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.PeakYUnit, 1);
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;

Set calibration files manually

C++:

CameraStatus status = static_cast<CameraStatus>(_SetIntParameter(sensor_ids[0], PARAM_PEAK_ENABLE, 1));
{
printf("FSAPI error: %d\n", status);
return;
}
status = static_cast<CameraStatus>(_SetStringParameter(sensor_ids[0], PARAM_SENSOR_CALIBRATION_FILE, "C:\\temp\\lci1200z.dat"));
{
printf("FSAPI error: %d\n", status);
return;
}
status = static_cast<CameraStatus>(_SetStringParameter(sensor_ids[0], PARAM_SENSOR_X_CALIBRATION_FILE, "C:\\temp\\lci1200x.dat"));
{
printf("FSAPI error: %d\n", status);
return;
}
status = static_cast<CameraStatus>(_SetIntParameter(sensor_ids[0], PARAM_PEAK_Y_UNIT, 1));
{
printf("FSAPI error: %d\n", status);
return;
}
status = static_cast<CameraStatus>(_SetIntParameter(sensor_ids[0], PARAM_PEAK_X_UNIT, 1));
{
printf("FSAPI error: %d\n", status);
return;
}

C#:

var cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.PeakEnabled, 1);
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;
cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.ZCalibrationFile, "C:\\temp\\lci1200z.dat");
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;
cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.XCalibrationFile, "C:\\temp\\lci1200x.dat");
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;
cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.PeakXUnit, 1);
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;
cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.PeakYUnit, 1);
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;

Imaging Frequency

Camera works either in internal (free run) or external pulsing mode. In free run mode user can set imaging frequency. In external pulsing mode frequency is set to 0 and the frequency is defined by an external triggering to the camera I/O. Maximum imaging frequency is limited by

  1. sensor's capability,
  2. LED pulse duration or
  3. Ethernet throughput in raw image mode.

Sensor capability

Maximum camera frequency is increased when depth of field is decreased. Following formulas can be used to calculate maximum window height in pixels when a frequency is known.

Recommended way to calculate maximum frequency is to use _AdjustRoiAndFps() function.

_sensor.AdjustRoiAndFps(_sensorId, (int)(RoiOperation.GetFpsForHeight), height, out var frequency);

For LCI401, LCI1200, LCI1201 and LCI1600 sensors maximum frequency is 5000 Hz and height can be calculate with the following equation: int height = (int)(47.5 / 129 * (1e6 / frequency - 1548 / 47.5)); Safety margin. height -= (int)(0.2 * height);

See Depth of Field chapter to map height into micrometers.

LED Pulse Duration

For LCI401, LCI1200, LCI1201 and LCI1600 sensors LED pulse duration must be at least 100 us less than minimum interval between two image captures. For example, if maximum imaging frequency is 500 Hz maximum LED pulse duration is (1/500 Hz) * 1000 * 1000-100 us = 1900 us.

For LCI1220 and LCI1620 sensors LED pulse duration must be at least 31 us less than minimum interval between two image captures.

Recommended way to calculate maximum led pulse duration is to use _AdjustRoiAndFps() function.

_sensor.AdjustRoiAndFps(_sensorId, (int)(RoiOperation.GetLedPulseForFps), frequency, out var pulseLength);

Ethernet Throughput

In peak mode required ethernet throughput can be calculated by following formula: imaging_frequency * 64 bits/points * points_per_frame

For example, if we have two surfaces and imaging frequency is 500 Hz resulting Ethernet throughput is

  1. LCI401, LCI1200, LCI1201 and LCI1600 sensors: 500 Hz * 64 * 2048 *2 = 128 Mbps.
  2. LCI1220 and LCI1620 sensors: 500 Hz * 64 * 1728 *2 = 111 Mbps.

In raw mode required throughput is:

  1. LCI401, LCI1200, LCI1201 and LCI1600 sensors: image_height x 2048 x imaging_frequency
  2. LCI1220 and LCI1620 sensors: image_height x 1728 x imaging_frequency

Depth of Field (Height and Offset of the Image)

Sensor's maximum imaging frequency can be increased by decreasing the image height.

Recommended way to adjust PARAM_IMAGE_HEIGHT and PARAM_IMAGE_OFFSETY parameters is to use _AdjustRoiAndFps() function with SetRoiForFps or RoiOperation.SetFpsForRoi attribute.

Example to adjust imaging height and offset when maximum imaging frequency is known:

_sensor.AdjustRoiAndFps(_sensorId, (int)(RoiOperation.SetRoiForFps), freq, out var zHeight);

Example to adjust imaging height and offset when needed depth of field is known. The maximum imaging frequency is returned.

_sensor.AdjustRoiAndFps(_sensorId, (int)(RoiOperation.SetFpsForRoi), height, out var frequency);

Exposure Control

Amount of light in the sensor can adjusted in three ways

  1. changing LED pulse length,
  2. changing LED current or
  3. changing gain of the sensor.

LED Pulse Width

Usually exposure is controlled by setting proper value for the LED pulse width. Width is given as microseconds typically varying between 1 us (high gloss, such as a mirror surface) and 100 us, but it can be also higher in low gloss surfaces.

C++:

float pulseWidth = 15.5;
status = static_cast<CameraStatus>(_SetFloatParameter(sensor_ids[0], PARAM_REG_PULSE_WIDTH_FLOAT, pulseWidth ));
{
printf("FSAPI error: %d\n", status);
return;
}

C#:

float pulseWidth = 15.5;
CameraStatusCode status = _sensor.SetParameter(_sensorId, SensorParameter.PulseWidthFloat, pulseWidth );
if (status != CameraStatusCode.Ok)
return status;

AGC is a camera function to adjust LED pulse width automatically to a proper value. This functionality can be used if the surface is continuous and no rapid changed are expected. The controller continuously calculates average intensity value of measured 3D points and compares this value to predefined value. LED pulse width is adjusted to minimize the error between measured and predefined value. Adjusted LED pulse width can be read from Header.PulseWidth of each received profile.

C++:

CameraStatus status;
int agcEnabled = 1; // Enable AGC
float agcTarget = 80.0; // Average intensity of measured points
int agcPulseWidthLimit = 300; // in microseconds
int agcMinPulseWidthLimit =10;// in microseconds
float agcGain = 1.2; // Gain for AGC controller
status = static_cast<CameraStatus>(_SetIntParameter(sensor_ids[0], PARAM_AGC_ENABLED, agcEnabled));
return 1;
if (agcEnabled)
{
status = static_cast<CameraStatus>(_SetFloatParameter(sensor_ids[0], PARAM_AGC_TARGET, agcTarget));
if (status != CameraStatus::CAMERA_OK)
return 1;
status = static_cast<CameraStatus>(_SetIntParameter(sensor_ids[0], PARAM_AGC_PULSE_WIDTH_LIMIT, agcPulseWidthLimit));
if (status != CameraStatus::CAMERA_OK)
return 1;
status = static_cast<CameraStatus>(_SetIntParameter(sensor_ids[0], PARAM_AGC_MIN_PULSE_WIDTH_LIMIT, agcMinPulseWidthLimit));
if (status != CameraStatus::CAMERA_OK)
return 1;
status = static_cast<CameraStatus>(_SetFloatParameter(sensor_ids[0], PARAM_AGC_GAIN, agcGain));
if (status != CameraStatus::CAMERA_OK)
return 1;
}

C#:

CameraStatusCode status;
int agcEnabled = 1; // Enable AGC
float agcTarget = 80.0; // Average intensity of measured points
int agcPulseWidthLimit = 300; // in microseconds
int agcMinPulseWidthLimit =10;// in microseconds
float agcGain = 1.2; // Gain for AGC controller
status = _sensor.SetParameter(_sensorId, SensorParameter.AgcEnabled, agcEnabled);
if (status != CameraStatusCode.Ok)
return status;
if (agcEnabled == 1)
{
_sensor.SetParameter(_sensorId, SensorParameter.AgcWiLimit, agcPulseWidthLimit);
_sensor.SetParameter(_sensorId, SensorParameter.AgcMinPulseWidthLimit, agcMinPulseWidthLimit);
_sensor.SetParameter(_sensorId, SensorParameter.AgcTarget, agcTarget);
_sensor.SetParameter(_sensorId, SensorParameter.AgcGain, agcGain);
}

LED Current

Used current for the LED lighting can be tuned. There are separate values for edge and center areas of the illuminator which can be used to smooth the illumination profile. Typically 1 ampere current is used.

C++:

CameraStatus fsapi_status;
float pulseCurrentMiddle = 1.0;
float pulseCurrentEdges = 1.0;
fsapi_status = m_fsapi->SetDoubleParameter(head_id_cstr, PARAM_PULSE_CURRENT_MIDDLE, pulseCurrentMiddle);
if (fsapi_status != CAMERA_OK)
return fsapi_status;
fsapi_status = m_fsapi->SetDoubleParameter(head_id_cstr, PARAM_PULSE_CURRENT_EDGES, pulseCurrentEdges);
if (fsapi_status != CAMERA_OK)
return fsapi_status;

C#:

float pulseCurrentMiddle = 1.0;
float pulseCurrentEdges = 1.0;
CameraStatusCode status;
status = _sensor.SetParameter(_sensorId, SensorParameter.PulseCurrentMiddle, pulseCurrentMiddle);
if (status != CameraStatusCode.Ok)
return status;
status = _sensor.SetParameter(_sensorId, SensorParameter.PulseCurrentEdges, pulseCurrentEdges);
if (status != CameraStatusCode.Ok)
return status;

Gain of the Sensor

The gain controls the amplification of the signal from the camera sensor. When the gain is increased also background noise is increased. Typically there is no need to change default gain value.

For LCI401, LCI1200, LCI1201 and LCI1600 sensors the default gain value is 1 and the range is 1.0 - 3.2. For LCI1220 and LCI1620 sensors the default gain value is 2 and the range is 2.0 - 8.0.

C++:

CameraStatus status;
float gain = 1.0;
status = static_cast<CameraStatus>(_SetIntParameter(sensor_ids[0], PARAM_GAIN, gain));
return 1;

C#:

float gain = 1.0;
CameraStatusCode status;
status = _sensor.SetParameter(_sensorId, SensorParameter.Gain, gain);
if (status != CameraStatusCode.Ok)
return status;

3D Point Detection

3D points detection starts with applying Signal Detection Filter to the signal. If the averaged value is greater than a specified threshold a peak is detected. After that exact location of the peak is calculated with FIR. Finally, an average peak intensity is calculated with Average Intensity Filter. Length of filters and threshold are user configurable. Usually filter length 16 gives the best results if material type is opaque. A shorter value may be needed if highly glossy surface (like mirror) is measured. Also, transparent surfaces may need lower values since layers needs to be separated from each other.

User has a possibility to select which intensity value is returned per layer. This is useful in multilayer surfaces where some layers might be thinner.

Parameters:

  1. PARAM_SIGNAL_DETECTION_FILTER_LENGTH
  2. PARAM_PEAK_FIR_LENGTH
  3. PARAM_PEAK_AVERAGE_INTENSITY_FILTER_LENGTH
  4. PARAM_PEAK_THRESHOLD
  5. PARAM_LAYER_INTENSITY_TYPE
DetectionFilters.png

Recommended way to set all peak detection parameters is to use _SetPeakDetectionParameters() function.

C++:

C#:

_sensor.SetParameter(_sensorId, SensorParameter.LayerMinThickness, 80);
_sensor.SetPeakDetectionParameters(_sensorId, MaterialType.Transparent, DetectionSensitivity.BestAccuracy);

After _SetPeakDetectionParameters() function threshold and filter parameters can be tuned.

Intensity Type Selection

By default intensity is calculated with Average Intensity Filter. If transparent material has a thin layer the filter might be too large. In order to reduce crosstalk user can select filter for each layer separately.

IntensityType.png

Reordering of Profiles

This chapter applies only for LCI401, LCI1200, LCI1201 and LCI1600 sensors. In LCI1220 and LCI1620 sensors reordering is not needed.

Received profiles are not guaranteed to arrive in order without reordering. All profiles have a header where order is in header->index attribute. Normally index increases linearly but sometimes there are out of order profiles caused by the Ethernet buffering.

You have two options to do reordering. One is to check the index in the application and do necessary processing, or you can enable reordering in the FS SDK.

FS SDK's reordering functionality buffers profiles until all are in order. Downside of reordering is that if packets are out of order jitter of the profiles will be increase.

Reordering uses 500 ms timeout for waiting pending packets. All received profiles are delivered to the application even though the timeout is expired. This is very unlikely but may happen if the PC is stalled longer than the timeout.

Reordering could be useful to activate on the cased when higher reception frequency ~5000Hz are used and frames are constantly being delivered not in order.

C++:

// Enable line reordering
status = static_cast<CameraStatus>(_SetIntParameter(sensor_ids[0], PARAM_REORDERING, 1));
{
printf("FSAPI error: %d\n", status);
return 1;
}
// defines reordering span time window in milliseconds
status = static_cast<CameraStatus>(_SetIntParameter(*sensor_ids[0], PARAM_REORDERING_SPAN, 300));
{
printf("FSAPI error: %d\n", status);
return 1;
}
// Define maximum index deviation unless reordering buffer is cleared.
status = static_cast<CameraStatus>(_SetIntParameter(*sensor_ids[0], PARAM_REORDERING_DEVIATION, 3000));
{
printf("FSAPI error: %d\n", status);
return 1;
}

C#:

cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.Reordering, 1);
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;
cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter. SensorParameter.ReorderingSpan, 500);
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;
cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.ReorderingDeviation, 5000);
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;

External Trigger Configurations

The trigger inputs can be used to synchronize the sensor with an external device. Application examples include: synchronizing the profile measurement into a certain signal of a production process or combining profiles into 3D point clouds based on the trigger index.

To measure the profile at each trigger event, input A should be used (input B is unconnected and is pulled down internally). This way every rising edge of the A signal triggers a measurement. The figure below shows the timing diagram of A and B signals when connected to a quadrature encoder. Only the B forwards triggers the measurement, because the B channel is on low state at the moment of a rising edge of the A channel.

Timing diagram of a quadrature encoder:

triggersA.png

External logic B enables trigger A at edges 5-7: Another way of configuring the encoder inputs is shown in the figure below. B input of the encoder can be used as a “disable” signal. On every rising edge of the encoder input signal A, the edge is accepted as a trigger if the encoder input signal B is simultaneously at a low state. An external logic can be used to generate B signal. B signal can be used, for example, to disable measurement during a relocation of the sensor.

triggersAB.png

Any of inputs 1-4 can be configured as A, B and Zero input. Input state is also transferred to PC embedded in each peak frame and can be used as general-purpose input that way. The sensor keeps count of the trigger location internally and embeds this information for each frame. Every rising edge of the A input, while the B input is in low state, increases location count. Every rising edge of the A input, while the B input is in high state, decreases location count. A rising edge of the Zero input.

FS API default input source definitions:

PARAM_TRIGGER_SOURCE default is 1.

PARAM_TRIGGER_DISABLE_SOURCE default is 2.

PARAM_TRIGGER_ZERO_SOURCE default is 3.

PARAM_REG_PULSE_DIVIDER default is 1.

C++:

// defines input 2 used as triggering source
status = static_cast<CameraStatus>(_SetIntParameter(sensor_ids[0], REG_TRIGGER_SOURCE, 2));
{
printf("FSAPI error: %d\n", status);
return 1;
}
// sets triggering disable source as unused -> 0
status = static_cast<CameraStatus>(_SetIntParameter(*sensor_ids[0], REG_TRIGGER_DISABLE_SOURCE, 0));
{
printf("FSAPI error: %d\n", status);
return 1;
}
// Every twentieth pulse triggers sensors
status = static_cast<CameraStatus>(_SetIntParameter(*sensor_ids[0], PARAM_REG_PULSE_DIVIDER, 20));
{
printf("FSAPI error: %d\n", status);
return 1;
}

C#:

cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.TriggerSource, 1);
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;
cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.TriggerDisableSource, 2);
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;
cameraStatus = _sensor.SetParameter(_sensorId, SensorParameter.PulseDivider, 10);
if (cameraStatus != CameraStatusCode.Ok)
return cameraStatus;

Detect Missing First Layer

Points in transparent surfaces are sorted to different layers according to z-coordinate. Problem is that if the first layer point is missing second layer point is detected as a first layer point. This feature improves classification by using prior information about the surface.

Missing first layer is detected by setting following parameters:

MissingFirstLayer.png
  • PARAM_DETECT_MISSING_FIRST_LAYER Defines minimum height distance between two layers in micrometers. Typical value is 30 -100 um.
  • PARAM_DETECT_MISSING_FIRST_LAYER Defines maximum x-coordinate distance between two points in micrometers. Typical value is 100 um.
  • PARAM_DETECT_MISSING_FIRST_LAYER_MIN_LENGTH Defines minimum length in micrometers for surface which is detected as the first layer. This is useful to filter small defects (like dust) from the first layer classification. Value can be relatively long i.e. 1000 um for flat surfaces.

Thickness Filtering

FSSDK provides possibility to use a priori information to enhance missing layer detection.

Maximum layer thickness (PARAM_LAYER_MAX_THICKNESS) can be set for each layer

ThicknessFiltering.png

High Dynamic Range (HDR)

HDR imaging is supported by the sensor and it might be useful in situations where the target has high level of contrast.

If HDR is not used in high contrast cases, exposuring dark areas with a proper LED length saturates bright areas. This might cause reduced accuracy of detected peaks.

If HDR is used, no bright pixels are saturating and the relative order of brightness is maintained between all pixels. This improves accuracy of detected peaks.

Pixel intensity without HDR:

WithoutHDR.png

HDR with Sensors LCI401, LCI1200, LCI1201 and LCI1600

If HDR is enabled sensor sensitivity is dropped approximately 20%. Only values below are supported. Behavior of other values is not tested.

  • Kp1=33
  • Kp2=66
  • VLow2=114
  • VLow3=116
HDR_STD.png

HDR with Sensors LCI1220 and LCI1620

  • Only the first knee point is supported
  • Float versions of HDR parameters are used
  • PARAM_HDR_KP1_POS_FLOAT, range 95.00 - 99.99 is supported
  • PARAM_HDR_VLOW2_FLOAT , range 30.0 - 33.0 is supported
  • Maximum imaging frequency is different than without HDR. Use _AdjustRoiAndFps() with GetFpsForRoi attribute to read actual maximum frequency.
HDR_HS.png

Interpolating Missing Measurement Points

This functionality fills areas which are not measured with interpolated points.

PARAM_FILL_GAP_X_MAX Defines maximum gap of missing measurement points filled by interpolation. If 0, interpolation feature is disabled.

Additionally a user can configure z difference of the gap area:

PARAM_LAYER_MIN_THICKNESS parameter defines maximum Z difference for interpolated points. For opaque materials, a user can set parameter for the first layer.

If PARAM_LAYER_MIN_THICKNESS is 0 (default behavior), the missing area is interpolated except areas where the gap is less than 4 pixels wide. In those cases interpolation is not used when the Z difference is big.

FillGapX.png

Trim Edges Filter

Trim Edges filter is indented to remove artificial points detected at the end of the surfaces. The filter can be disabled/enabled at runtime in the line callback function and it takes effect on the next processed profiles

The filter works optimally for those edges which are clearly visible. It may remove real points if edges are gradually disappearing. Therefore, it is recommended to use the filter only for profiles which have clear edges. Additionally, it might be useful to use PARAM_FILL_GAP_X_MAX parameter to fill not measured areas on the edge.

Filtering is done for each profile separately which means that only horizontal edges are trimmed.

Following issues are handled with the filter:

TrimEdges1.png
TrimEdges2.png
TrimEdgesAlgo.png

Recipes

Loading a recipe is the recommended way to configure the sensor at application startup and during the parameter set change. For online changes, user shall use the SetParameter/GetParameter functions.

A typical use case for the recipe is following (this is how FSSDK GuiExample works):

  • The application initializes the sensor
  • The application loads a recipe and starts acquisition
  • The application makes changes to the camera parameters with SetParameter functions
  • The application saves the recipe

In another use case the application only uses the recipe (this is how FSSDK ConsoleExample works):

  • The application initializes the sensor
  • The application loads the recipe and starts acquisition

Following steps are needed for the sensor initialization with a recipe.

1) Open()-function to discover sensors and Connect()-function to set IP addresses

int camera_count = 1;
char **camera_ids = nullptr;
_Open(&camera_count, &camera_ids, 5000);
_Connect(camera_ids[0], 0);

2) Check is the calibration available in the sensor.

int calibrations_in_camera = 0;
GetIntParameter(camera_ids[0], const_cast<char*>(PARAM_SENSOR_DATA_IN_FLASH), &calibrations_in_camera);
// if calibrations not found from camera, needs to be defined.
if(!calibrations_in_camera)
{
printf("Calibration files not in camera, must be provided by user\n");
status = static_cast<CameraStatus>(_SetStringParameter(camera_ids[0], const_cast<char*>(PARAM_SENSOR_CALIBRATION_FILE), z_calib_file));
{
printf("FSAPI error: %d. Failed to set Z calibration file.\n", status);
return 1;
}
status = static_cast<CameraStatus>(_SetStringParameter(camera_ids[0], const_cast<char*>(PARAM_SENSOR_X_CALIBRATION_FILE), x_calib_file));
{
printf("FSAPI error: %d Failed to set X calibration file.\n", status);
return 1;
}
}

3) Load a recipe

status = static_cast<CameraStatus>(_SetStringParameter(camera_ids[0], const_cast<char*>(PARAM_LOAD_RECIPE), recipeName));
{
printf("Recipe error");
return;
}

4) Set image acquisition parameters which are not defined in the recipe. For example:

_SetLineCallback(camera_ids[0], 0, LineCallbackHandlerLayer1);
_SetLineCallback(camera_ids[0], 1, LineCallbackHandlerLayer2);
_SetLineCallback(camera_ids[0], 2, LineCallbackHandlerLayer3);
_StartGrabbing(camera_ids[0]);

Z-Compensation

Calibration

A strong surface texture may cause edge artifacts in Z values. In order to reduce edge artifacts the sensor can be calibrated for Z-Compensation.

An example of calibration procedure is implemented in FieldCalibrationTool. The tool can be used as is or it can be customized by using provided source codes.

Calculation

Z-Compensation can be enabled separately for X or Y direction. Y direction means moving direction acquisition with external triggering. Typically, both X and Y direction are needed for compensation calculation.

Note that Z-Compensation in Y direction is available only for BatchCallback data and there is no effect on LineCallback data. Additionally PARAM_MOVING_DIRECTION and PARAM_ENCODER_PULSE_WIDTH parameters need to be set properly when Y direction compensation is used.

A calibration file is read when the user enables either compensation direction. By default, calibration file location is the same as other calibration files (C:\FocalSpec\Calibration). If calibration used this path there is no need to set the file manually. Optionally users can set full path with paramter PARAM_SENSOR_Z_COMPENSATION_FILE .

In console example application X and Y compensations are enabled for batch call back function:

status = static_cast<CameraStatus>(_SetIntParameter(camera_ids[0], const_cast<char*>(PARAM_Z_COMPENSATION_X_DIRECTION), 1));
if (status == CAMERA_OK)
printf("Z Compensation X direction enabled\n");
status = static_cast<CameraStatus>(_SetIntParameter(camera_ids[0], const_cast<char*>(PARAM_Z_COMPENSATION_Y_DIRECTION), 1));
if (status == CAMERA_OK)
printf("Z Compensation Y direction enabled\n");

For some materials it might be beneficial to adjust Z-compensation algorithm. User can increase or decrease Z-compensation effect by following multipliers: PARAM_Z_COMPENSATION_X_BRIGHT_TO_DARK_MUL, PARAM_Z_COMPENSATION_X_DARK_TO_BRIGHT_MUL, PARAM_Z_COMPENSATION_Y_BRIGHT_TO_DARK_MUL, PARAM_Z_COMPENSATION_Y_DARK_TO_BRIGHT_MUL.

User has an option remove points where calculated Z-Compensation is big. This is useful feature if the material has a strong texture and compensation is suboptimal for those points. The feature can be used with parameter PARAM_Z_COMPENSATION_THRESHOLD.

If points are removed by PARAM_Z_COMPENSATION_THRESHOLD feature, empty areas can be interpolated by using neighboring points. Interpolation can be enabled with parameter PARAM_Z_COMPENSATION_INTERPOLATE.