PMDSDK / PMDMDK User Manual
Introduction and General Description
This section describes how to get started with the PMDSDK or PMDMDK. The Api is accessed via a library which is included in an application. All the neccessary functions, a short explanation and some examples are provided here, in order to make it easy for developers to get started with the basic and advanced functions of the Argos3D - P100 Camera.
Building Applications for Microsoft Windows
Files needed:
- pmdsdk2.h: Contains declarations of the functions in the dll
- pmdaccess2.lib: The improt library to be linked to the application
- pmdaccess2.dll: The library containing the functions for accessing the camera
- pmdsdk2common.h: This header file contains some defines, typedefs and enums and is indirectly included by pmdsdk2.h
- pmddatadescription.h: This header file contains some defines, typedefs and structs and is indirectly included by pmdsdk2.h
- A source plugin file: For example "digicam.W32.pap"
- A processing plugin file: For example "digicamproc.W32.ppp"
Building Applications for Linux
Files needed:
- pmdsdk2.h: Contains declarations of the functions in the dll
- libpmdaccess2.so: The library containing the functions for accessing the camera
- pmdsdk2common.h: This header file contains some defines, typedefs and enums and is indirectly included by pmdsdk2.h
- pmddatadescription.h: This header file contains some defines, typedefs and structs and is indirectly included by pmdsdk2.h
- A source plugin file: For example "digicam.L32.pap"
- A processing plugin file: For example "digicamproc.L32.ppp"
Building Matlab Applications for Windows
The PMDMDK is a wrapper to use the PMDSDK in MATLAB. It can be used by adding the 'PMDMDK' path to your Matlab script or copying all of its files to a location that MATLAB can find.
Files included:
- pmdaccess2.dll: The library containing the functions for accessing the camera
- A source plugin file: For example "digicam.W32.pap"
- A processing plugin file: For example "digicamproc.W32.ppp"
- The precompiled MATLAB executables: For example "*.mexw32"
General Api Description
Using the PMDSDK
A connection to a camera (or source plugin) is established and held up via a handle. This handle is needed for all function calls. Information such as error codes are stored per handle, meaning that more than one connection to more than one camera can be handled by the PMDSDK or PMDMDK. Common to all functions is the code which is returned. The code is always PMD_OK on success. On failure an error code provides more information.
A typical usecase involves the following commands:
// establish a connection and get a handle PMDHandle hndl; int result = pmdOpen(&hndl, "digicam", "", "digicamproc", ""); if (result != PMD_OK) { // abort } // fetch a frame from usb controller result = pmdUpdate(hndl); if (result != PMD_OK) { // error } // get basic information about the current frame PMDDataDescription dd; result = pmdGetSourceDataDescription(hndl, &dd); if (result != PMD_OK) { // error } int Xres = dd.img.numColumns; int Yres = dd.img.numRows; printf("Pixels in current frame %d\n", Xres * Yres); // get distance data in meters (same procedure with pmdGetAmplitudes float[] dist = new float[Xres * Yres]; int result = GetDistances(hndl, dist, sizeof(float)*Xres*Yres); if (result != PMD_OK) { // error } printf("Center pixel sees an obstacle at %f meters\n", dist[Xres/2 + Yres/2 * Xres]); // ...or get raw pixel data including header data (here only distances) int sizeData = 0; pmdGetSourceDataSize(hndl, &sizeData); unsigned char[] data = new char[sizeData]; int result = pmdGetSourceData(hndl, (void *) data, sizeData); if (result != PMD_OK) { // error } uint32[] header = new uint32[128]; for (int i = 0; i < 128; i++) { header[i] = (data[4*i] << 24) & (data[4*i + 1] << 16) & (data[4*i + 2] << 8) & data[4*i + 3]; } ushort[] distances = new ushort[Xres * Yres]; for (int i = 0; i < Xres * Yres; i++) { distances[i] = data[512 + 2*i] & (data[512 + 2*i + 1] << 8); } printf("Center pixel raw distance is %d\n", distances[Xres/2 + Yres/2 * Xres]); // close handle when finished pmdClose(hndl);
Using the PMDMDK
The functions of the PMDMDK are very similar to those of the PMDSDK. Each function of the PMDSDK has its counterpart in the PMDMDK. There are however, a few important things to know.
- In the PMDMDK, no error codes are returned by the functions. If an error occurs, an exception is raised instead.
- There are no by-reference parameters in the PMDMDK. Output data is always returned in one or more return values.
- pmdGetSourceDataDescription() returns a Matlab structure containing the fields of a PMDDataDescription. The fields std and gen appear as sub structures.
- Size parameters are not necessary and must be omitted for all functions. The PMDMDK does automatic memory management.
A typical usecase involves the following commands:
addpath('PMDMDK') % establish a connection and get a handle hndl = pmdOpen('PMDMDK\digicam',' ','PMDMDK\digicamproc',' '); % fetch a frame from usb controller pmdUpdate(hndl); % get basic information about the current frame dd = pmdGetSourceDataDescription(hndl); Xres = dd.std.numColumns; Yres = dd.std.numRows; fprintf('Pixels in current frame %d\n', Xres * Yres); % get distance data in meters (same procedure with pmdGetAmplitudes) dist = pmdGetDistances(hndl); fprintf('Center pixel sees an obstacle at %f meters\n', dist(Xres/2, Yres/2)); % ...or get raw pixel data including header data (here only distances) raw = zeros(1, Xres*Yres); sizeData = pmdGetSourceDataSize(hndl); data = pmdGetSourceData(hndl); raw = reshape(typecast(data(513:(512+2*Xres*Yres)),'uint16'),Xres,Yres); header = typecast(data(1:512),'uint32'); fprintf('Center pixel raw distance is %f\n', raw(Xres/2, Yres/2)); % close handle when finished pmdClose(hndl);
Reference Manual
This section describes the commands in the library, how to use them to obtain image data from the camera and how to change its configuration.
Example code is written both in C++ and Matlab.
PMDSDK Commands
pmdOpen
Parameter | Type | Description |
---|---|---|
handle | PMDHandle * | Empty PMDHandle structure. On success, this value will contain the handle for subsequent operations |
rplugin | const char * | Camera (source) plugin. The extension can be omitted. It can be relative or absolute. |
rparam | const char * | Parameter for the camera (source) plugin |
pplugin | const char * | Processing plugin. The extension can be omitted. It can be relative or absolute. Can be Null, then no processing plugin is loaded |
pparam | const char * | Parameter for the processing plugin |
returns | int | PMD_OK on success, errorcode otherwise |
The pmdOpen command connects the camera and provides a handle for subsequent operation. The parameters 'rplugin' and 'pplugin' must be provided as references to actual files (provided by Bluetechnix).
PMDSDK Example
PMDHandle hndl = 0; int result = pmdOpen(&hndl, "digicam", "", "digicamproc", ""); if (result != PMD_OK) { // error, handle is not valid }
PMDMDK Example
hndl = pmdOpen('PMDMDK\digicam', ' ', 'PMDMDK\digicamproc',' ');
pmdOpenSourcePlugin
Parameter | Type | Description |
---|---|---|
handle | PMDHandle * | Empty PMDHandle structure. On success, this value will contain the handle for subsequent operations |
rplugin | const char * | Camera (source) plugin. The extension can be omitted. It can be relative or absolute. |
rparam | const char * | Parameter for the camera (source) plugin |
returns | int | PMD_OK on success, errorcode otherwise |
The pmdOpenSourcePlugin command connects the camera and provides a handle for subsequent operation. The difference to pmdOpen is that no processing commands can be run. I.e. with only a source plugin loaded only the following commands are supported:
- pmdGetSourceData()
- pmdUpdate()
- pmdGetSourceDataDescription()
- pmdGetSourceDataSize()
- pmdSetIntegrationTime()
- pmdGetIntegrationTime()
- pmdGetValidlntegrationTime()
- pmdSetModulationFrequency()
- pmdGetModulationFrequency()
- pmdGetValidModulationFrequency()
- pmdSourceCommand()
PMDSDK example
PMDHandle hndl = 0; int result = pmdOpenSourcePlugin(&hndl, "digicam", ""); if (result != PMD_OK) { // error, handle is not valid }
PMDMDK example
hndl = pmdOpenSourcePlugin('PMDMDK\digicam', ' ');
pmdOpenProcessingPlugin
Parameter | Type | Description |
---|---|---|
handle | PMDHandle * | Empty PMDHandle structure. On success, this value will contain the handle for subsequent operations |
pplugin | const char * | Processing plugin. The extension can be omitted. It can be relative or absolute. Can be Null, then no processing plugin is loaded |
pparam | const char * | Parameter for the processing plugin |
returns | int | PMD_OK on success, errorcode otherwise |
The pmdOpenProcessingPlugin command connects the camera and provides a handle for subsequent operation. The difference to pmdOpen is that no source commands can be run. I.e. with only a processing plugin loaded only the following commands are supported:
Example
PMDHandle hndl = 0; int result = pmdOpenProcessingPlugin(&hndl, "digicamproc", ""); if (result != PMD_OK) { // error, handle is not valid }
pmdClose
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
returns | int | PMD_OK on success, errorcode otherwise |
Disconnect and close the handle.
PMDSDK Example
int result = pmdClose(hndl); if (result != PMD_OK) { // error }
PMDMDK Example
pmdClose(hndl);
pmdUpdate
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
returns | int | PMD_OK on success, errorcode otherwise |
Retrieve a new frame from the camera. This function must be called before beeing able to obtain image data. To obtain the actual data, use pmdGetSourceData, pmdGetDistances, pmdGetAmplitudes etc. Those calls to the above get-functions will produce the same data from the same frame until pmdUpdate is called again.
PMDSDK Example
int result = pmdUpdate(hndl); if (result != PMD_OK) { // error }
PMDMDK Example
pmdUpdate(hndl);
pmdGetSourceDataDescription
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
dd | PMDDataDescription * | Will contain the PMDDataDescription after the call. |
returns | int | PMD_OK on success, errorcode otherwise |
Get the description of the current raw data frame (refer to PMDDataDescription).
PMDSDK Example
PMDDataDescription dd; int result = pmdGetSourceDataDescription(hndl, &dd); if (result != PMD_OK) { // error }
PMDMDK Example
dd = pmdGetSourceDataDescription(hndl);
pmdGetSourceData
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
data | void * | Pointer to a block of memory to contain the data. |
maxLen | size_t | Maximum amount of bytes that can be written to memory allocated in data |
returns | int | PMD_OK on success, errorcode otherwise |
If the result data should be longer than maxLen the function results in an error. This function provides the raw data of the current frame. It may contain up to four containers in the following format:
header (128 x 4 bytes) | data (2 bytes per pixel) | header (128 x 4 bytes) | data (2 bytes per pixel) | header (128 x 4 bytes) | data (2 bytes per pixel) | header (128 x 4 bytes) | data (2 bytes per pixel) |
The overall size of the data block can be obtained calling pmdGetSourceDataSize and depends on the amount of containers and their resolutions in pixels
Header:
The header contains 128 32-bit words in network order. For a listing of these fields refer to Source Data Container Header.
Data:
The data block contains a 16-bit value per pixel. What data lies in each container depends on PMD Calculation Mode. By default three containers are available: Distances, Amplitudes and Plausibilities. Distances are scaled on the uniqueness range. Amplitudes are scaled equally as in pmdGetAmplitudes. Plausibilities contain flags providing more information about each pixel (refer to Plausibility Flags).
PMDSDK Example (only one container is processed)
unsigned int sizeData = 0; pmdGetSourceDataSize(hndl, &sizeData); unsigned char *data = new unsigned char[sizeData]; int result = pmdGetSourceData(hndl, (void *) data, sizeData); if (result != PMD_OK) { // error } insigned int *header = new unsigned int[128]; for (int i = 0; i < 128; i++) { header[i] = (data[4*i]) | (data[4*i + 1] << 8) | (data[4*i + 2] << 16) | (data[4*i + 3] << 24); } unsigned short *distances = new unsigned short[Xres * Yres]; for (int i = 0; i < Xres * Yres; i++) { distances[i] = data[512 + 2*i] | (data[512 + 2*i + 1] << 8); }
PMDMDK Example
raw = zeros(1, Xres*Yres); data = pmdGetSourceData(hndl); raw = reshape(typecast(data(513:(512+2*Xres*Yres)),'uint16'),Xres,Yres); header = typecast(data(1:512),'uint32');
pmdGetSourceDataSize
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
maxLen | size_t * | Will contain the size of present source data |
returns | int | PMD_OK on success, errorcode otherwise |
Gets the size of the current frame in bytes. It is needed when calling pmdGetSourceData
Example
pmdGetAmplitudes
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
data | float * | Pointer to a block of memory to contain the data. |
maxLen | size_t | Maximum amount of bytes that can be written to memory allocated in data |
returns | int | PMD_OK on success, errorcode otherwise |
Get the amplitude data from the current frame. If there is more data available than maxLen, an error is returned. The data in the buffer received looks like follows. The pixel orientation is illustrated in the coordinate system figure. Amplitudes are raw values between 0 and 65535.
32 bit float | |
---|---|
Amplitude Pixel 0 | Addr 0 |
Amplitude Pixel 1 | Addr 1 |
Amplitude Pixel 2 | Addr 2 |
... | ... |
PMDSDK Example
float[] amp = new float[Xres * Yres]; // Xres and Yres are obtained from PMDDataDescription struct int result = pmdGetAmplitudes(hndl, amp, sizeof(float)*Xres*Yres); if (result != PMD_OK) { // error }
PMDMDK Example
amp = pmdGetAmplitudes(hndl);
pmdGetDistances
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
data | float * | Pointer to a block of memory to contain the data. |
maxLen | size_t | Maximum amount of bytes that can be written to memory allocated in data |
returns | int | PMD_OK on success, errorcode otherwise |
Get the distance data from the current frame. If there is more data available than maxLen, an error is returned. The data in the buffer received looks like follows. The pixel orientation is illustrated in the coordinate system figure. Distances are in [m].
32 bit float | |
---|---|
Distance Pixel 0 | Addr 0 |
Distance Pixel 1 | Addr 1 |
Distance Pixel 2 | Addr 2 |
... | ... |
PMDSDK Example
float[] dist = new float[Xres * Yres]; // Xres and Yres are obtained from PMDDataDescription struct int result = pmdGetDistances(hndl, dist, sizeof(float)*Xres*Yres); if (result != PMD_OK) { // error }
PMDMDK Example
dist = pmdGetDistances(hndl);
pmdGetFlags
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
data | uint32 * | Pointer to a block of memory to contain the data. |
maxLen | size_t | Maximum amount of bytes that can be written to memory allocated in data |
returns | int | PMD_OK on success, errorcode otherwise |
Get the plausibility data from the current frame. If there is more data available than maxLen, an error is returned. A plausability value contains flags providing more information about each pixel (refer to Plausibility Flags). The data in the buffer received looks like follows. The pixel orientation is illustrated in the coordinate system figure.
32 bit float | |
---|---|
Flags Pixel 0 | Addr 0 |
Flags Pixel 1 | Addr 1 |
Flags Pixel 2 | Addr 2 |
... | ... |
PMDSDK Example
uint32[] flags = new uint32[Xres * Yres]; // Xres and Yres are obtained from PMDDataDescription struct int result = pmdGetFlags(hndl, flags, sizeof(uint32)*Xres*Yres); if (result != PMD_OK) { // error }
PMDMDK Example
flags = pmdGetFlags(hndl);
pmdGet3DCoordinates
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
data | float * | Pointer to a block of memory to contain the data. |
maxLen | size_t | Maximum amount of bytes that can be written to memory allocated in data |
returns | int | PMD_OK on success, errorcode otherwise |
Get 3D coordinates from the current frame. If there is more data available than maxLen, an error is returned. 3D Coordinates are organised as iterations of x, y, z float values. The data in the buffer received looks like follows. The pixel orientation is illustrated in the coordinate system figure. Coordinates are in [m].
32 bit float | |
---|---|
X coordinate Pixel 0 | Addr 0 |
Y coordinate Pixel 0 | Addr 1 |
Z coordinate Pixel 0 | Addr 2 |
X coordinate Pixel 1 | Addr 0 |
Y coordinate Pixel 1 | Addr 1 |
Z coordinate Pixel 1 | Addr 2 |
... | ... |
PMDSDK Example
float[] pos = new float[Xres * Yres * 3]; // Xres and Yres are obtained from PMDDataDescription struct int result = pmdGet3DCoordinates(hndl, pos, sizeof(float)*Xres*Yres*3); if (result != PMD_OK) { // error } float[] posx = new float[Xres * Yres]; float[] posy = new float[Xres * Yres]; float[] posz = new float[Xres * Yres]; for (int i = 0; i < Xres * Yres; i++) { posx[i] = pos[i*3]; posy[i] = pos[i*3+1]; posz[i] = pos[i*3+2]; } delete[] pos;
PMDMDK Example
pos = pmdGet3DCoordinates(hndl);
pmdGetIntegrationTime
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
t | unsigned | The integration time |
idx | unsigned | Sequence index of the integration time (usually 0) |
returns | int | PMD_OK on success, errorcode otherwise |
Get the current integration time of a specified sequence.
PMDSDK Example
unsigned intTime; int result = pmdGetIntegrationTime(hndl, &intTime, 0); if (result != PMD_OK) { // error }
PMDMDK Example
intTime = pmdGetIntegrationTime(hndl, 0);
pmdGetModulationFrequency
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
t | unsigned | The modulation frequency |
idx | unsigned | Sequence index of the modulation frequency (usually 0) |
returns | int | PMD_OK on success, errorcode otherwise |
Get the current modulation frequency of a specified sequence.
PMDSDK Example
unsigned modFreq; int result = pmdGetModulationFrequency(hndl, &modFreq, 0); if (result != PMD_OK) { // error }
PMDMDK Example
modFreq = pmdGetIntegrationTime(hndl, 0);
pmdGetValidIntegrationTime
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
result | unsigned * | Pointer to a variable to contain the integration time in microseconds |
idx | unsigned | Sequence index of the integration time (usually 0) |
w | Proximity | Where to look for a valid integration time in respect to the desired integration time (CloseTo, AtLeast or AtMost) |
t | unsigned | The desired integration time |
returns | int | PMD_OK on success, errorcode otherwise |
Get a supported integration time of the camera based on a given desired integration time.
PMDSDK Example
unsigned intTime; int result = pmdGetValidIntegrationTime(hndl, &intTime, 0, CloseTo, 1000); if (result != PMD_OK) { // error }
PMDMDK Example
intTime = pmdGetValidIntegrationTime(hndl, 0, CloseTo, 1000);
pmdGetValidModulationFrequency
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
result | unsigned * | Pointer to a variable to contain the modulation frequency in Hertz |
idx | unsigned | Sequence index of the modulation frequency (usually 0) |
w | Proximity | Where to look for a valid integration time in respect to the desired modulation frequency (CloseTo, AtLeast or AtMost) |
t | unsigned | The desired modulation frequency |
returns | int | PMD_OK on success, errorcode otherwise |
Get a supported modulation frequency of the camera based on a given desired modulation frequency.
PMDSDK Example
unsigned modFreq; int result = pmdGetValidModulationFrequency(hndl, &modFreq, 0, CloseTo, 20000000); if (result != PMD_OK) { // error }
PMDMDK Example
modFreq = pmdGetValidModulationFrequency(hndl, 0, CloseTo, 20000000);
pmdSetIntegrationTime
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
idx | unsigned | Sequence index of the integration time (usually 0) |
t | unsigned | Integration time in microseconds |
returns | int | PMD_OK on success, errorcode otherwise |
Set the integration time of the camera
PMDSDK Example
int result = pmdSetIntegrationTime(hndl, 0, 1000); if (result != PMD_OK) { // error }
PMDMDK Example
pmdSetIntegrationTime(hndl, 0, 1000);
pmdSetModulationFrequency
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
idx | unsigned | Sequence index of the modulation frequency (usually 0) |
t | unsigned | Modulation frequency in Hertz |
returns | int | PMD_OK on success, errorcode otherwise |
Set the modulation frequency of the camera. The range of valid modulation frequencies goes from 5MHz up to 30MHz. Note that not every frequency in this area can possibly set. Please refer to pmdGetValidModulationFrequency
PMDSDK Example
int result = SetModulationFrequency(hndl, 0, 20000000); if (result != PMD_OK) { // error }
PMDMDK Example
pmdSetModulationFrequency(hndl, 0, 20000000);
pmdSourceCommand
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
result | char * | Pointer to a block of memory to contain the result string |
maxLen | size_t | Maximum length of the result string, including terminating 0 |
cmd | char * | The command to be executed |
returns | int | PMD_OK on success, errorcode otherwise |
Execute an source plugin-specific command. Feedback is literally provided in the result char sequence additionally to the result code. This command is a wrapper for many other functionalities such as direct write to the register set of the camera (Camera Registers). Valid commands are listed in Source Commands. If the result string should be longer than maxLen it is truncated.
PMDSDK Example
char *answer = new char[128]; int result = pmdSourceCommand(hndl, answer, 128, "SetOffset 0 -133"); if (result != PMD_OK) { // error }
PMDMDK Example
result = pmdSourceCommand(hndl, 'SetOffset 0 -133');
pmdProcessingCommand
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
result | char * | Pointer to a block of memory to contain the result string |
maxLen | size_t | Maximum length of the result string, including terminating 0 |
cmd | char * | The command to be executed |
returns | int | PMD_OK on success, errorcode otherwise |
Execute an processing plugin-specific command. Feedback is literally provided in the result char sequence additionally to the result code. Valid commands are listed in Processing Commands. If the result string should be longer than maxLen it is truncated.
Example
char *answer = new char[128]; int result = pmdProcessingCommand(hndl, answer, 128, "SetBilateralFilter off"); if (result != PMD_OK) { // error }
PmdMdk Example
result = pmdProcessingCommand(hndl, 'SetBilateralFilter off');
pmdGetLastError
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
error | char * | Pointer to a block of memory to contain the result string |
maxLen | size_t | Maximum length of the result string, including terminating 0 |
returns | int | PMD_OK on success, errorcode otherwise |
Get an error description for the last error. Error messages are stored per handle. A new error associated with PMDHandle A does not overwrite the last error message associated with PMDHandle B. If the result string should be longer than maxLen it is truncated.
PMDSDK Example
char *answer = new char[128]; int result = pmdGetLastError(hndl, answer, 128); if (result != PMD_OK) { // error }
PMDMDK Example
answer = pmdGetLastError(hndl);
pmdCalcDistances
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
data | float * | Pointer to a block of memory to contain the data. |
maxLen | size_t | Maximum amount of bytes that can be written to memory allocated in data |
sourceDD | PMDDataDescription | Struct of the source data description |
sourceData | void * | Pointer to a block of memory containing the source data |
returns | int | PMD_OK on success, errorcode otherwise |
Calc the distance data from stored source data. If there is more data available than maxLen, an error is returned. For a description of the result data buffer refer to pmdGetDistances.
PMDSDK Example
PMDDataDescription dd; int result = pmdGetSourceDataDescription(hndl, &dd); if (result != PMD_OK) { // error } int sizeData = 0; pmdGetSourceDataSize(hndl, &sizeData); unsigned char[] data = new char[sizeData]; int result = pmdGetSourceData(hndl, (void *) data, sizeData); if (result != PMD_OK) { // error } float[] dist = new float[dd.img.numColumns * dd.img.numRows]; int result = pmdCalcDistances(hndl, dist, sizeof(float)*dd.img.numColumns * dd.img.numRows, dd, data); if (result != PMD_OK) { // error }
PMDMDK Example
dd = pmdGetSourceDataDescription(hndl); data = pmdGetSourceData(hndl); dist = pmdCalcDistances(hndl, dd, data);
pmdCalcAmplitudes
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
data | float * | Pointer to a block of memory to contain the data. |
maxLen | size_t | Maximum amount of bytes that can be written to memory allocated in data |
sourceDD | PMDDataDescription | Struct of the source data description |
sourceData | void * | Pointer to a block of memory containing the source data |
returns | int | PMD_OK on success, errorcode otherwise |
Calc the amplitude data from stored source data. If there is more data available than maxLen, an error is returned. For a description of the result data buffer refer to pmdGetAmplitudes.
PMDSDK Example
PMDDataDescription dd; int result = pmdGetSourceDataDescription(hndl, &dd); if (result != PMD_OK) { // error } int sizeData = 0; pmdGetSourceDataSize(hndl, &sizeData); unsigned char[] data = new char[sizeData]; int result = pmdGetSourceData(hndl, (void *) data, sizeData); if (result != PMD_OK) { // error } float[] dist = new float[dd.img.numColumns * dd.img.numRows]; int result = pmdCalcAmplitudes(hndl, dist, sizeof(float) * dd.img.numColumns * dd.img.numRows, dd, data); if (result != PMD_OK) { // error }
PMDMDK Example
dd = pmdGetSourceDataDescription(hndl); data = pmdGetSourceData(hndl); amp = pmdCalcAmplitudes(hndl, dd, data);
pmdCalc3DCoordinates
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
data | float * | Pointer to a block of memory to contain the data. |
maxLen | size_t | Maximum amount of bytes that can be written to memory allocated in data |
sourceDD | PMDDataDescription | Struct of the source data description |
sourceData | void * | Pointer to a block of memory containing the source data |
returns | int | PMD_OK on success, errorcode otherwise |
Calc the distance data from stored source data. If there is more data available than maxLen, an error is returned. 3D Coordinates are organised as iterations of x, y, z float values. For a description of the result data buffer refer to pmdGet3DCoordinates.
PMDSDK Example
PMDDataDescription dd; int result = pmdGetSourceDataDescription(hndl, &dd); if (result != PMD_OK) { // error } int sizeData = 0; pmdGetSourceDataSize(hndl, &sizeData); unsigned char[] data = new char[sizeData]; int result = pmdGetSourceData(hndl, (void *) data, sizeData); if (result != PMD_OK) { // error } float[] pos = new float[dd.img.numColumns * dd.img.numRows * 3]; int result = pmdCalc3DCoordinates(hndl, pos, sizeof(float) * dd.img.numColumns * dd.img.numRows * 3, dd, data); if (result != PMD_OK) { // error } float[] posx = new float[dd.img.numColumns * dd.img.numRows]; float[] posy = new float[dd.img.numColumns * dd.img.numRows]; float[] posz = new float[dd.img.numColumns * dd.img.numRows]; for (int i = 0; i < dd.img.numColumns * dd.img.numRows; i++) { posx[i] = pos[i*3]; posy[i] = pos[i*3+1]; posz[i] = pos[i*3+2]; } delete[] pos;
PMDMDK Example
dd = pmdGetSourceDataDescription(hndl); data = pmdGetSourceData(hndl); pos = pmdCalc3DCoordinates(hndl, dd, data);
pmdCalcFlags
Parameter | Type | Description |
---|---|---|
handle | PMDHandle | Handle of the connection |
data | uint32 * | Pointer to a block of memory to contain the data. |
maxLen | size_t | Maximum amount of bytes that can be written to memory allocated in data |
sourceDD | PMDDataDescription | Struct of the source data description |
sourceData | void * | Pointer to a block of memory containing the source data |
returns | int | PMD_OK on success, errorcode otherwise |
Get the plausibility data from stored source data. If there is more data available than maxLen, an error is returned. For a description of the result data buffer refer to pmdGetFlags.
PMDSDK Example
PMDDataDescription dd; int result = pmdGetSourceDataDescription(hndl, dd); if (result != PMD_OK) { // error } int sizeData = 0; pmdGetSourceDataSize(hndl, &sizeData); unsigned char[] data = new char[sizeData]; int result = pmdGetSourceData(hndl, (void *) data, sizeData); if (result != PMD_OK) { // error } uint32[] flags = new uint32[dd.img.numColumns * dd.img.numRows]; int result = pmdCalcFlags(hndl, flags, sizeof(uint32) * dd.img.numColumns * dd.img.numRows, dd, data); if (result != PMD_OK) { // error }
PMDMDK Example
dd = pmdGetSourceDataDescription(hndl); data = pmdGetSourceData(hndl); flags = pmdCalcFlags(hndl, dd, data);
Processing Commands
Processing commands interact directly with the processing plugin.
Usage:
- Pass the command as a string calling pmdProcessingCommand
- Numeric parameters can be provided in decimal or hexadecimal format with leading 0x
- Parameters are separated by spaces
- pmdProcessingCommand reports the result of the processing command as a literal string in its parameter 'result' (here denoted as "returns")
PMDSDK Example
char answer[128]; answer[0] = 0; int result = pmdProcessingCommand(hndl, answer, sizeof(answer), "SetBilateralFilter off");
PMDMDK Example
answer = pmdProcessingCommand(hndl, 'SetBilateralFilter off');
SetBilateralFilter
Parameter | Description |
---|---|
modifier | "on" or "off" |
returns | "OK" |
This command turns bilateral filtering on or off.
Source Commands
Source commands interact directly with the source plugin.
Usage:
- Pass the command as a string calling pmdSourceCommand
- Numeric parameters can be provided in decimal or hexadecimal format with leading 0x
- Parameters are separated by spaces
- pmdSourceCommand reports the result of the source command as a literal string in its parameter 'result' (denoted as "returns" in following tables)
PMDSDK Example
char result[128]; result[0] = 0; int res= pmdSourceCommand(hndl, result, sizeof(result), "SetRegister 0x1A 137");
PMDMDK Example
result = pmdSourceCommand(hndl, 'SetRegister 0x1A 137');
GetRegister
Parameter | Description |
---|---|
address | Address of the register to write (see Camera Registers) |
returns | The register content |
This command returns the content of the denoted register.
SetRegister
Parameter | Description |
---|---|
address | Address of the register to write (see Camera Registers) |
value | Value to write into register |
returns | "OK" |
This command writes a designated value directly into the denoted register. Some registers are read only, while others should not be written directly (such as distance offset). Register address overflows are not checked!
LoadRegisterMap
Parameter | Description |
---|---|
filename | The text file that is parsed and loaded into the registers |
returns | "OK" |
The complete set of registers is parsed out of the file and then written into the camera's volatile internal memory. Use with care and with files provided by Bluetechnix only.
GetOffset
Parameter | Description |
---|---|
Sequence index | Sequence to which the offset is to be applied to |
returns | The offset for the indexed sequence in millimeters |
Returns the offset, that is applied globally to all computed distances for a certain sequence. The offset may vary for different modulation frequencies. The offset returned by this source command will allways be positive and may not necessarily be the same value that was set using SetOffset.
SetOffset
Parameter | Description |
---|---|
Sequence index | Sequence to which the offset is to be applied to |
value | A signed offset in millimeters |
returns | The new offset for the indexed sequence in millimeters |
Sets the offset for the indexed modulation frequency. The offset is given in [mm] and may be positive or negative. Negative values are converted to positive equivalents. This means when setting negative offset values using SetOffset, GetOffset will not return the same value.
GetSerialNumber
Parameter | Description |
---|---|
returns | The serial number of the device (see No. Serial/Customer) |
Retrieves the serial number from the sensor. The serial number is provided as hexadecimal value of eight characters length with a leading 0x.
GetTriggerMode
Parameter | Description |
---|---|
returns | "Freerun" or "Hard" |
Returns the current trigger mode.
SetTriggerMode
Parameter | Description |
---|---|
Trigger mode | "Freerun" or "Hard" |
returns | "OK" |
Set the current trigger mode of the camera.
LoadCalibrationData
Parameter | Description |
---|---|
filename | Filename of calibration file |
returns | "OK" |
Loads the calibration data from the given file. If no file parameter is provided, the plugin tries to automatically load argos3d.cal from the executable folder.
IsCalibrationDataLoaded
Parameter | Description |
---|---|
returns | "YES" or "NO" |
If calibration data was loaded previously "YES" is returned. Otherwise "NO".
WriteConfigToFlash
Parameter | Description |
---|---|
returns | "OK" |
Writes the whole sensor configuration to persistent flash memory. This current configuration will then be used as startup parameterization everytime the device is powered on. Use with care!
DisableIntegrationTimeCheck
Parameter | Description |
---|---|
returns | "OK" |
Disables any limit for the integration time. Use with care! The camera will heat up to destruction (of itself and surroundings) if unrecommended values get involved.
From plugin version 0.3.0 onward this command is no longer supported. The integration time check is always deactivated and can no longer be switched on.
PMDSDK Data Structures
PMDDataDescription
The Data Description struct is always 128 bytes long and contains information about the captured frame.
struct PMDDataDescription { unsigned PID; unsigned DID; unsigned type; unsigned size; unsigned subHeaderType; union { struct PMDGenericData gen; struct PMDImageData img; char fillUpToSizeOfStructure[108]; }; };
PMDGenericData
Generic data
struct PMDGenericData { unsigned subType; unsigned numElem; unsigned sizeOfElem; };
PMDImageData
Image data
struct PMDImageData { unsigned subType; unsigned numColumns; // image x-size in pixels unsigned numRows; // image y-size in pixels unsigned numSubImages; int integrationTime[4]; // integration time for up to four different sequences int modulationFrequency[4]; // modulation frequency for up to four different sequences int offset[4]; // offset for up to four different sequences int pixelAspectRatio; int pixelOrigin; unsigned timeStampHi; not working unsigned timeStampLo; not working char reserved[24]; unsigned userData0; };
Plausibility Flags
The plausibility data contains flags providing more information on each pixel.
PMD_FLAG_INVALID 0x1 // The pixel is not to be relied on. Do not use this depth value PMD_FLAG_SATURATED 0x2 // The calculated distance is not within a defined range and can therefore not be used PMD_FLAG_INCONSISTENT 0x4 // The pixel’s raw data values are inconsistent with each other. This can happen when there are very fast changes in the scene (motion artefacts) PMD_FLAG_LOW_SIGNAL 0x8 // The pixel's exposure was too low PMD_FLAG_SBI_ACTIVE 0x10
PMD Result Codes
Result code returned by all PMDSDK Commands
PMD_OK 0 PMD_RUNTIME_ERROR 1024 PMD_GENERIC_ERROR 1025 PMD_DISCONNECTED 1026 PMD_INVALID_VALUE 1027 PMD_TIMEOUT_ERROR 1028 PMD_LOGIC_ERROR 2048 PMD_UNKNOWN_HANDLE 2049 PMD_NOT_IMPLEMENTED 2050 PMD_OUT_OF_BOUNDS 2051 PMD_RESOURCE_ERROR 4096 PMD_FILE_NOT_FOUND 4097 PMD_COULD_NOT_OPEN 4098 PMD_DATA_NOT_FOUND 4099 PMD_END_OF_DATA 4100 PMD_DEVICE_IS_BUSY 4101
Source Data Container Header
No. 32bit doubleword - network byte order | Header Data | Description |
---|---|---|
0 | PMD Status | |
1 | No. Serial/Customer | |
2 | No. Release/Date | |
3 | No. Framebytes | |
4 | No. Rows | |
5 | No. Columns | |
6 | Set ROI | |
7 | ROI_Column_Begin | |
8 | ROI_Column_End | |
9 | ROI_Row_Begin | |
10 | ROI_Row_end | |
11 | Sequence Length | |
12 | Sequence Combine | |
13 | Output Mode | |
14 | PMD Acquisition Mode | |
15 | PMD Calculation Mode | |
16 | Temperature PMD | |
17 | Temperature Illumination | |
18 | Temperature Customer | |
19 | 0 | |
20 | 0 | |
21 | 0 | |
22 | Chipsize Columns | |
23 | Chipsize Rows | |
24 | Time Stamp Increment | timestamp increment as configured in register 24 |
25 | Trigger Mode | |
32-95 | Customer Specification Area | |
96 | Sequence pll_select | |
97 | Sequence int_time | |
98 | Sequence mod_frequency | |
99 | Sequence frame_time | |
100 | Sequence grayscale phase shift | |
101 | Sequence no phases | |
102 | Sequence distance offset | |
103 | Sequence Amplitude Min | |
104 | Sequence Saturation | |
105 | Sequence Symmetry | |
106 | Frame Counter | |
107 | Time Stamp |
|
PmdMdk Types and Data Structures
Handle
The handle for a camera connection is stored as a number. This handle is used for all operations that interact with a data source. It is initialized with the functions pmdOpen() or pmdOpenSourcePlugin() and is diposed when calling pmdClose().
Data Description Structure
The data description structure is returned by pmdGetSourceDataDescription(). It contains information about a data block. This is used to describe the source data of a camera.
Field | Description |
---|---|
PID | Identifier of the plugin that generated of modified the data block. |
DID | Identifier of the data block. This is unique for a plugin. |
type | Type of the data. This is used to describe what kind of data is in the block. |
size | Size in bytes of the data block. |
subHeaderType | Identifier for the active subheader structure. This can be ignored in MATLAB because the right substructure is automatically available. |
Substructures (only one of these fields is used at the same time)
Substructure | Description |
---|---|
gen | Generic data substructure |
std | Image data substructure |
Generic data substructure
Contains information about a generic data block. This structure is used as a field inside a data description structure for special information.
Field | Description |
---|---|
subType | Sub-type of the data. This depends of type in the data description structure and allows further refinement of the type. |
numElem | Number of data elements. |
sizeOfElem | Size in bytes of one data element. |
Image data substructure
Contains information about a PMD- or image-data block. This structure is used as a field inside a data description structure for special information.
Field | Description |
---|---|
subType | Sub-type of the data. This depends of type in the data description structure and allows further refinement of the type. |
numColumns | Number of pixel columns in the image. |
numRows | Number of pixel rows in the image. |
numSubImages | Number of sub-images (e.g. phase images) in the data block. |
integrationTime0-3 | Up to four integration times used to generate the image. |
modulationFrequency0-3 | Up to four modulation frequencies used to generate the image. |
Camera Registers
Register Name | Address | Hex Address | Bit Length | Interpretation | Read/Write | Description |
---|---|---|---|---|---|---|
General | ||||||
PMD Status | 0 | 0x00 | uint32 | bitwise | r | |
No. Serial/Customer | 1 | 0x01 | uint32 | bit 31 - bit 20: Device Type; bit19 - bit 0: Serial Number | r | |
No. Release/Date | 2 | 0x02 | uint32 | nibblewise | r | Firmware release date |
No. Framebytes | 3 | 0x03 | uint32 | num | r | Size of raw data |
No. Rows | 4 | 0x04 | uint16 | num | r | Vertical count of imager pixels |
No. Columns | 5 | 0x05 | uint16 | num | r | Horizontal count of imager pixels |
Sequence Length | 11 | 0x0B | uint8 | num 0…12 | r/w | |
Sequence Combine | 12 | 0x0C | uint8 | num 0…12 | r/w | |
Output Mode | 13 | 0x0D | uint8 | num 1..2 | r/w | |
PMD Acquisition Mode | 14 | 0x0E | uint8 | bitwise | r/w | |
PMD Calculation Mode | 15 | 0x0F | uint32 | bitwise | r/w | |
Temperature PMD | 16 | 0x10 | uint32 | word | r | Temperature of Imager (if available) |
Temperature Illumination | 17 | 0x11 | uint32 | fixedpoint 9.4 °C | r | Temperature of LED board |
Temperature Customer | 18 | 0x12 | uint32 | word | r | |
Update Camera Data | 19 | 0x13 | uint32 | bitwise | r/w | |
Update_Flash_Data | 20 | 0x14 | uint32 | bitwise | r/w | |
Flash_Magic | 21 | 0x15 | uint32 | num | r/w | |
Chipsize_Columns | 22 | 0x16 | uint16 | num | r/w | |
Chipsize_Rows | 23 | 0x17 | uint16 | num | r/w | |
TimeStamp Increment | 24 | 0x18 | uint32 | num | r/w |
|
Trigger Mode | 25 | 0x19 | uint8 | logic | r/w | 00: freerun, 01: hardware trigger |
Temperature Compensation | 26 | 0x1A | uint16 | fixcomma 11.5 mm/°C | r/w | |
Illumination | ||||||
Mod Led Enable | 48 | 0x30 | uint8 | bitwise | r/w | |
Sequencing | ||||||
Sequence 0 int_time | 129 | 0x81 | uint16 | us | r/w | |
Sequence 0 mod_frequency | 130 | 0x82 | uint32 | Hz | r/w | |
Sequence 0 frame_time | 131 | 0x83 | uint32 | us | r/w | |
Sequence 0 distance offset | 134 | 0x86 | uint16 | mm | r/w | |
Sequence 0 Amplitude Min | 135 | 0x87 | uint16 | num 0..2^16-1 | r/w | |
Sequence 0 Saturation | 136 | 0x88 | uint32 | 2x num 0..2^16-1 | r/w | |
Sequence 0 Symmetry | 137 | 0x89 | uint32 | 2x num 0..2^16-1 | r/w |
Register Details
No. Serial/Customer
The Serial/Customer Number of the camera contains the serial number and the device type code:
Bit | Description |
---|---|
bit 31 - bit 20 | PON code |
bit 19 - bit 0 | Serial Number (found on the label on the camera's back) |
PON code to PON table:
Code | PON |
---|---|
0x001 | 150-2001-1 |
0x002 | 160-0001-1 |
0x003 | 160-0001-2 |
0x004 | 150-2201-1 |
0x005 | 170-2201-2 |
0x006 | 160-0001-3 |
0x007 | 150-2201-2 |
0x008 | 909-2222-1 |
0x700 | Reserved |
Trigger Mode
Value | Description |
---|---|
0x0 | Free run mode |
0x1 | Hardware trigger mode |
Mod Led Enable
Bit | Name | Description |
---|---|---|
Bit0: | enable pmd_mod | |
Bit1: | enable led_mod | Enables internal modulation signal |
Bit2: | enable ext_mod | Enables external modulation signal (Modulation light interface) |
Bit3: | enable led1_en | Currently not supported |
Bit4: | enable led2_en | Enables built-in leds |