Overview
The output of a DIRSIG Lidar simulation is a binary file that contains a series of spatial x spatial x time cubes for each pulse with some platform ephemeris data mixed in. Because this file contains the number of photons arriving at each detector during the set of time bins determined by the range gate defined for the simulation, these files are sometimes called "bin" files.
This output file is usually feed to a detector model which "senses" when the detector will mark a "return" based on the incident flux for a given pixel. This detection model might find multiple returns within one pulse (common in most Linear-mode systems) or only a single-return (common in most Geiger-mode systems). Regardless of the detector model applied, the output of DIRSIG is the same.
This document describes the raw photon arrival data computed by DIRSIG. It does not describe a point cloud data format that might be generated by a detector model that takes this file as an input. |
Tracking Changes
This document emphasizes the current format of the "bin" file. The descriptions of each section include all entries since the first version of this file was defined. Deprecated entries (obsolete entries that have been removed) are struck through, although they remain in the document for reference. The History section near the end of this document summarizes the changes for each revision.
Format Details
File Structure
The general format of the BIN file is as follows:
-
File Header
-
Task Header
-
Pulse Header
-
Pulse Data
-
-
There is always only one File Header in a file. There may be multiple tasks in a file, each starting with a Task Header. Within a task, there may be multiple pulses, each starting with a Pulse Header that is immediately followed by the Pulse Data. Note that the File Header indicates the number of tasks contained in the file and the Task Header indicates the number of pulses contained in that task.
See below for a more complete example of how a larger file is arranged:
-
File Header (indicates there are N tasks in this file)
-
Task Header #1 (indicates there are M1 pulses in this task)
-
Pulse Header #1
-
Pulse Data #1
-
Pulse Header #2
-
Pulse Data #2
-
Pulse Header #3
-
Pulse Data #3
-
…
-
Pulse Header #M1
-
Pulse Data #M1
-
-
Task Header #2 (indicates there are M2 pulses in this task)
-
Pulse Header #1
-
Pulse Data #1
-
Pulse Header #2
-
Pulse Data #2
-
…
-
Pulse Header #M2
-
Pulse Data #M2
-
-
…
-
Task Header #N (indicates there are M3 pulses in this task)
-
Pulse Header #1
-
Pulse Data #1
-
Pulse Header #2
-
Pulse Data #2
-
…
-
Pulse Header #M3
-
Pulse Data #M3
-
-
Multiple Files
A single DIRSIG simulation might produce multiple output BIN files. That is because the user has three (3) options available related to the output file schedule:
-
A single BIN file for the whole simulation where all pulses for all tasks appear in one file. For example
lidar.bin
.-
In this situation, the BIN file will contain multiple tasks, and each task can contain multiple pulses.
-
-
Individual BIN files for each task, where all the pulses for a given task appear in one file. The output files will have a unique file name for each task. For example
lidar-t0000.bin
,lidar-t0001.bin
, etc.-
In this situation, the each BIN file will contain a single task, but each task can contain multiple pulses.
-
The "file header" will be the same in every file.
-
-
Individual BIN files for each pulse, where each pulse appears in it’s own file. The resulting files with have a unique file name for each pulse and each task. For example,
lidar-t0000-c0000.bin
,lidar-t0000-c0001.bin
, …lidar-t0001-c0000.bin
,lidar-t0001-c0001.bin
, …, etc.-
In this situation, each BIN file will contain a single task containing a single pulse.
-
The "file header" will be the same in every file.
-
The "task header" will be the same for all pulse files from the same task.
-
The detector model that processes these file can choose to merge the returns for all these files into one output product.
Data Types
The following section outlines the data types used in the various sections of this file:
Type | Description |
---|---|
int8 |
8 bits, signed via two’s complement, -128 to +127 |
int32 |
4 bytes, signed via two’s complement, -2,147,483,648 to +2,147,483,647 |
uint16 |
2 bytes, unsigned, 0 to +65,535 |
uint32 |
4 bytes, unsigned, 0 to +4,294,967,295 |
uint64 |
8 bytes, unsigned, 0 to +18,446,744,073,709,55 |
double |
8 bytes, IEEE754 format |
Data is written in native endian of the host machine. The File Header contains the Byte ordering variable that indicates if the host machine was big endian (Most Significant Byte First (MSF)) or little endian (Least Significant Byte First (LSF)). |
File Header
This section describes the data layout of the File Header section of the BIN file. There is exactly one File Header section and it appears at the start of the file.
File Identifier |
char[11] |
|
File format revision |
int8 |
|
Byte ordering |
int8 |
|
File creation date/time |
char[15] |
|
DIRSIG version string |
char[32] |
|
Simulation description |
char[256] |
|
Scene origin latitude |
double |
|
Scene origin longitude |
double |
|
Scene origin height |
double |
|
Transmitter mount type |
char[16] |
|
Receiver mount type |
char[16] |
|
Pixel count, X dimension |
uint32 |
|
Pixel count, Y dimension |
uint32 |
|
Pixel pitch, X dimension |
double |
|
Pixel pitch, Y dimension |
double |
|
Array offset, X dimension |
double |
Added in [v.1] |
Array offset, Y dimension |
double |
Added in [v.1] |
Lens distortion coefficient (k1) |
double |
Added in [v.1] |
Lens distortion coefficient (k2) |
double |
Added in [v.1] |
Task count |
uint32 |
|
Focal plane array (FPA) ID |
uint16 |
Added in [v.2] |
The total size of this header is currently 434 bytes ([v.1]: 432 bytes [v.0]: 400 bytes).
- File Identifier
-
Initial bytes always read "
DIRSIGPROTO
", used to verify file type. - File format revision
-
Version of file format specification. Currently
0
(DIRSIG 4.3.0),1
(DIRSIG 4.3.1 - 4.4.4), and2
(DIRSIG 4.5 and later) - Byte ordering
-
0
indicates big endian,1
for little endian. - File creation date/time
-
The date and times for when the file was created (Format: YYYYMMDDhhmm.ss).
- DIRSIG version
-
The DIRSIG version used to create file. Unused characters at end should be filled with nulls (ASCII code
0
) - Simulation description
-
An arbitrary user-supplied text describing simulation, primarily used for documentation purposes. Unused characters at end should be filled with nulls (ASCII code
0
) - Scene origin latitude
-
Latitude of scene origin in degrees [-90,90], where negative is South.
- Scene origin longitude
-
Longitude of scene origin in degrees [-180,180), where negative is West.
- Scene origin height
-
Height of scene origin in meters above WGS84 reference ellipsoid.
- Transmitter mount type
-
A string description of mount type for laser source (transmitter), primarily used for documentation purposes. Unused characters at end should be filled with nulls (ASCII code
0
). - Receiver mount type
-
A string description of mount type for detector (receiver), primarily used for documentation purposes. Unused characters at end should be filled with nulls (ASCII code
0
). - Pixel count, X dimension
-
Number of detector elements in the X dimension of the array.
- Pixel count, Y dimension
-
Number of detector element in the Y dimension of the array.
- Pixel pitch, X dimension
-
Distance between detector centers in microns, for the X dimension of the array.
- Pixel pitch, Y dimension
-
Distance between detector centers in microns, for the Y dimension of the array.
- Array offset, X dimension
-
Distance between array center and optical axis in microns.
- Array offset, Y dimension
-
Distance between array center and optical axis in microns.
- Lens distortion coefficient, k1
-
Radial lens distortion coefficient.
- Lens distortion coefficient, k2
-
Radial lens distortion coefficient.
- Task count
-
The number of tasks contained in the file.
- Focal Plane Array (FPA) ID
-
Unique ID for the focal plane array used to create this file. FPAs are numbered in the order they appear in the instrument, starting at
0
. The FPA IDs are not unique across multiple instruments.
Task Header
This section describes the data layout of the Task Header section of the BIN file. There is one Task Header section at the start of each task block within the file.
Task description |
char[64] |
Task start date/time |
char[15] |
Task stop date/time |
char[15] |
Focal length |
double |
Pulse repetition frequency |
double |
Pulse duration |
double |
Pulse energy |
double |
Laser spectral center |
double |
Laser spectral width |
double |
Pulse count |
uint32 |
The total size of this header is currently 146 bytes.
- Task description
-
An arbitrary text string describing task, primarily used for documentation purposes. Unused characters at end should be filled with nulls (ASCII code
0
). - Task start date/time
-
The date and timestamp for the start of this task (Format: YYYYMMDDhhmm.ss).
- Task stop date/time
-
The date and timestamp for the stop (end) of this task (Format: YYYYMMDDhhmm.ss).
- Focal length
-
The focal length of the receiver in millimeters.
- Pulse repetition frequency
-
The mean pulse repetition rate in Hertz.
- Pulse duration
-
The temporal width of the transmitted laser pulse in seconds (assumed Gaussian).
- Pulse energy
-
The energy of each transmitted laser pulse in in Joules.
- Laser spectral center
-
The spectral center of the transmitted laser pulse in microns.
- Laser spectral width
-
The spectral width of the transmitted laser pulse in microns (assumed Gaussian).
- Pulse count
-
The number of pulses in this task.
Pulse Header
This section describes the data layout of the Pulse Header section of the BIN file. There is one Pulse Header section at the start of each pulse block within the file.
Pulse time |
double |
|
Time gate start |
double |
|
Time gate stop |
double |
|
Time gate bin count |
uint32 |
|
Samples per time bin |
uint32 |
Added in [v.1] |
Platform location |
double[3] |
|
Platform orientation: Angle order |
char[3] |
removed in [v.2] |
Platform rotation |
double[3] |
|
Transmitter to mount affine |
double[16] |
Added in [v.2] |
Transmitter mount pointing offset |
double[3] |
removed in [v.2] |
Transmitter orientation: Angle order |
char[3] |
removed in [v.2] |
Transmitter mount pointing rotation |
double[3] |
|
Transmitter mount to platform affine |
double[16] |
Added in [v.2] |
Receiver to mount affine |
double[16] |
Added in [v.2] |
Receiver mount pointing offset |
double[3] |
removed in [v.2] |
Receiver orientation: Angle order |
char[3] |
removed in [v.2] |
Receiver mount pointing rotation |
double[3] |
|
Receiver mount to platform affine |
double[16] |
Added in [v.2] |
Pulse data type |
int32 |
|
Data compression type |
int8 |
|
Delta histogram flag |
char |
removed in [v.2] |
Pulse index |
uint32 |
Added in [v.2] |
Pulse data bytes |
uint64 |
Guaranteed to be 64-bits in [v.2] |
System transmit Mueller matrix |
double[16] |
Added in [v.2] |
System receive Mueller matrix |
double[16] |
Added in [v.2] |
The total size of this header is currently 913 bytes ([v.1]: 199 bytes, [v.0]: 192 bytes).
- Pulse time
-
Pulse time relative to task start [seconds].
- Time gate start
-
Time gating start time relative to pulse start [seconds].
- Time gate stop
-
Time gating stop time relative to pulse stop [seconds].
- Time gate bin count
-
Number of time bins (equally spaced, temporal samples) over range gate.
- Samples per time bin
-
The number of samples per time bin. This value can also be interpreted as a multiplier for Time gate bin count.
- Platform location
-
The platform location in the Scene ENU coordinate frame [meters].
- Platform rotation
-
The Euler angles for the orientation of the platform in the Scene ENU coordinate frame [radians]. The data is stored in "XYZ" order, but the angles must be applied in "YZX" order.
- Transmitter to mount affine
-
Affine transform (4x4, row-major order) placing the transmitter relative to its respective mount (this represents the instrument to mount attachment).
- Transmitter mount pointing rotation
-
The Euler angles for the rotation of the transmitter mount [radians]. The data is stored in "XYZ" order, but the angles must be applied in "YZX" order.
- Transmitter mount to platform affine
-
Affine transform (4x4, row-major order) placing the transmitter mount relative to the platform (this represents the transmitter mount to platform attachment).
- Receiver to mount affine
-
Affine transform (4x4, row-major order) placing the receiver relative to its respective mount (this represents the instrument to mount attachment).
- Receiver mount pointing rotation
-
The Euler angles for the rotation of the receiver mount [radians]. The data is stored in "XYZ" order, but the angles must be applied in "YZX" order.
- Receiver mount to platform affine
-
Affine transform (4x4, row-major order) placing the receiver mount relative to the platform (this represents the receiver mount to platform attachment).
- Pulse data type
-
The data type used in pulse results with only type
5
(double precision floating-point) being currently supported. This value corresponds to the "data type" values defined in the ENVI image header file. - Data compression type
-
0
indicates no compression,1
indicates zlib compression of the pulse data. - Pulse index
-
The index of this pulse in the current task (indexes start at
0
). - Pulse data bytes
-
The number of bytes of (possibly compressed) pulse data. If the data is not compressed, the size should be X x Y x (T + 1).
- System transmit Mueller matrix
-
A Mueller matrix that captures all the polarizing elements between the transmitter exit aperture (assumed to be unpolarized) and the exit point of the platform, including scan mirrors, glass, polarization state generators, etc.
- System receive Mueller Matrix
-
A Mueller matrix that captures all the polarizing elements between the entrance point of the platform and the focal plane array (FPA), including scan mirrors, glass, filters, polarization state analyzers, etc.
Pulse Data
The pulse data contains the number of photons received in each listening window (range gate) time bin, for each pixel in the receiver. The pulse data separately contains the background (passive) flux as a rate (units of photons/second). This passive flux appears in the first "time bin" of the pulse data. Therefore, to get the total number of photons arriving within a given time bin, the background (passive) value in the first "bin" (the passive "bin") should be multiplied by the width of a time bin and added to the value in each remaining bin (the "active" bins).
The total number of "active" bins is the Time gate bin count multiplied by the Samples per time bin. |
From a data dimensionality standpoint, the pulse data always contains the number of "active" time bins plus an extra bin for the background (passive) flux.
The "extra" bin containing the background (passive) flux is not included in the value stored in the Time gate bin count field. |
The 3D data cube is packed into the 1D data stream of the file in the order time, then X, then Y ("time interleaved by pixel"). For example:
(X0,Y0,Bkg) (X0,Y0,T0) (X0,Y0,T1) ... (X0,Y0,Tmax) (X1,Y0,Bkg) (X1,Y0,T0) (X1,Y0,T1) ... (X1,Y0,Tmax) ... (Xmax,Y0,Bkg) (Xmax,Y0,T0) (Xmax,Y0,T1) ... (Xmax,Y0,Tmax) (X0,Y1,Bkg) (X0,Y1,T0) (X0,Y1,T1) ... (X0,Y1,Tmax) (X1,Y1,Bkg) (X1,Y1,T0) (X1,Y1,T1) ... (X1,Y0,Tmax) ... (Xmax,Ymax,Bkg) (Xmax,Ymax,T0) (Xmax,Ymax,T1) ... (Xmax,Ymax,Tmax)
The background (temporally constant) bin has units of photons/second and the remaining (temporally varying) bins have units of photons. |
File Parsing Guidance and Tools
The following is a set of hints and suggestions for reading BIN files:
-
Each BIN file can have a unique number of tasks, and each task within a file can have a unique number of pulses.
-
The pulse data includes all bins in the range gate inclusively.
Example MATLAB Code
Each DIRSIG release includes MATLAB code for reading the BIN file. This code can be used as a template to write your own detector model or to perform analysis on a file.
This code is contained in the extras/matlab-lidar
folder in the
DIRSIG installation folder.
Computing Pixel Line of Sight Vectors
Computing pixel line-of-sight vectors that include all of the platform relative offset and pointing effects must consider the following information:
-
The transmitter and receiver are located and oriented relative to the platform coordinate system.
-
The transmitter and receiver are oriented based on the supplied angles. This rotation is about the translated location of the respective instrument. Therefore the order is rotate the instrument relative to the platform, then translate the instrument (again, relative to the platform).
The final line-of-sight vector is the result of applying a series of affine transforms to a camera-relative pixel vector. The various transforms change on a pulse-to-pulse basis due to platform motion and platform-relative pointing (scanning). The following instructions attempt to detail the chain of transforms employed in the computation:
-
A given pixel’s camera-relative pointing vector can be computed using the pixel pitch and array offset in the File Header section and the focal length in the Pulse Header section.
-
Note that by default, DIRSIG cameras point down from the platform. The easiest way to achieve this is to use the negative of the focal length as the Z component of the pixel vector.
-
-
The camera-relative vectors must now be modified by the mount pointing (scanning) transform. This is driven by the receiver mount pointing rotation angles in the corresponding Pulse Header section. The combined rotation transform can be computed by chaining the individual axis rotation transforms in the order Y, then Z, then X.
-
The resulting mount-relative vectors must now be modified by the receiver mount to platform affine transform in corresponding Pulse Header section. This transform handles any spatial and angular offsets of the mount relative to the platform body.
-
The platform-relative vectors must now be transformed into the Scene ENU coordinate system by accounting for the platform orientation and translation.
-
The platform orientation transform is then applied using the platform rotation values in the Pulse Header section. The combined rotation transform can be computed by chaining the individual axis rotation transforms in the order Y, then Z, then X.
-
Finally, the platform translation transform is applied using the platform location values in the Pulse Header. The combined translation transform can be computed by combining the individual axis translation transforms.
-
Constructing a 3D point from a time-of-flight
Level-1 (L1) LIDAR data is usually a 3D point cloud, where points represent a location in 3D space that is corresponding to a singal return for which a time-of-flight was measured. If you are implementing your own detector model (which produces a time-of-flight measurement) and want to construct a 3D point for that time-of-flight, the following process is suggested:
-
Compute the pointing vector for the given pixel.
-
Compute the absolute location of the camera using the sames steps to produce the pointing vector, but using the 3D origin point (0,0,0) rather than the camera-relative pixel pointing vector.
-
Compute the time-of-flight for a given pixel using the waveform contained in the Pulse data.
-
Compute the round-trip distance corresponding to that time-of-flight.
-
Compute the platform-relative 3D point by projecting half the round-trip distance along the pixel pointing vector.
-
Compute the absolute location of the 3D point by adding the absolute camera origin (described in step #2) to the platform-relative 3D point computed in the previous step.
Depending on the atmospheric configuration supplied to DIRSIG, the index of refraction along the path might vary, which results in the speed of light varying along the path. |
History
This section details the history of this file format, including changes made between revisions (see the File format revision field in the File Header).
Revision 0
The initial version of this file.
Revision 1 Changes
Below is the list of changes that were introduced in Revision 1:
-
File Header
-
Added detector array X/Y offsets
-
Added radial lens distortion model coefficients (K1 and K2)
-
-
Pulse Header
-
Added "Samples per time bin" to pulse header
-
Revision 2 Changes
Below is the list of changes that were introduced in Revision 2:
-
File Header
-
Added the Focal plane array (FPA) ID
-
-
Pulse Header
-
Added affine matrices for the "instrument to mount" and "mount to platform" attachment transformations
-
Removed transmitter and receiver mount offsets (more accurately captured by the two new affine transforms)
-
Removed various Euler angle rotation order fields because the angles always follow "YZX" order
-
Removed deprecated (and unused) delta histogram flag
-
Added the Pulse index
-
Guaranteed that the Pulse data bytes will always be 64-bits (prior to v.2, it was 32-bits on a 32-bit system and 64-bits on a 64-bit system)
-
Added Mueller matrices for transmit and receive optical paths
-
Proposed Changes
Below is a proposed list of changes to made to the file at a future date:
-
File Header
-
Switch to ISO8601 for date/time strings (seconds precision issue)
-
Include support for other lens distortion models (some sort of ID and the number of bytes used to store the parameters for the model).
-
-
Task Header
-
Switch to ISO8601 for date/time strings (seconds precision issue)
-
Include the task index (this was supposed to go into rev. 2)
-
Include the "shape" of the temporal pulse profile and the spectral pulse shape. Right now these widths are assumed to correspond to a Gaussian shape, but the user might not have setup DIRSIG to use a Gaussian shape. Even if we included the name of the functional form used in the simulation the user would need to refer to the DIRSIG Beam Manual to know what the widths mean, and it would not address a user-defined profile. Including a 1D rendering of each profile would address all of these limitations.
-