Converting PCAPs to Other Formats

PCAPs to CSV

Sometimes we want to get a point cloud (XYZ + other fields) as a CSV file for further analysis with other tools.

To convert the first 5 scans of our sample data from a pcap file, you can try:

$ python3 -m ouster.sdk.examples.pcap $SAMPLE_DATA_PCAP_PATH $SAMPLE_DATA_JSON_PATH pcap-to-csv --scan-num 5

The source code of an example below:

 1from itertools import islice
 2# precompute xyzlut to save computation in a loop
 3xyzlut = client.XYZLut(metadata)
 4
 5# create an iterator of LidarScans from pcap and bound it if num is specified
 6scans = iter(client.Scans(source))
 7if num:
 8    scans = islice(scans, num)
 9
10for idx, scan in enumerate(scans):
11
12    # initialize the field names for csv header
13    if not field_names or not field_fmts:
14        field_names, field_fmts = get_fields_info(scan)
15
16    # copy per-column timestamps for each channel
17    timestamps = np.tile(scan.timestamp, (scan.h, 1))
18
19    # grab channel data
20    fields_values = [scan.field(ch) for ch in scan.fields]
21
22    # use integer mm to avoid loss of precision casting timestamps
23    xyz = (xyzlut(scan.field(client.ChanField.RANGE)) * 1000).astype(
24        np.int64)
25
26    if dual:
27        xyz2 = (xyzlut(scan.field(client.ChanField.RANGE2)) * 1000).astype(
28            np.int64)
29
30        # get all data as one H x W x num fields int64 array for savetxt()
31        frame = np.dstack((timestamps, *fields_values, xyz, xyz2))
32
33    else:
34        # get all data as one H x W x num fields int64 array for savetxt()
35        frame = np.dstack((timestamps, *fields_values, xyz))
36
37    # not necessary, but output points in "image" vs. staggered order
38    frame = client.destagger(metadata, frame)
39
40    # write csv out to file
41    csv_path = os.path.join(csv_dir, f'{csv_base}_{idx:06d}.{csv_ext}')
42    print(f'write frame #{idx}, to file: {csv_path}')
43
44    header = '\n'.join([f'frame num: {idx}', field_names])
45
46    np.savetxt(csv_path,
47               frame.reshape(-1, frame.shape[2]),
48               fmt=field_fmts,
49               delimiter=',',
50               header=header)

Because we stored the scan as structured 2D images, we can easily recover it by loading it back into a numpy.ndarray and continuing to use it as a 2D image.

import numpy as np

# read array from CSV
frame = np.loadtxt('my_frame_00000.csv', delimiter=',')

# convert back to "fat" 2D image [H x W x num_fields] shape
frame = frame.reshape((128, -1, frame.shape[1]))

We used 128 while restoring 2D image from a CSV file because it’s the number of channels of our OS-1-128.pcap sample data recording.

PCAPs to LAS

To convert to the first 5 scans of our sample data from a pcap file to LAS, you can try:

$ python3 -m ouster.sdk.examples.pcap $SAMPLE_DATA_PCAP_PATH $SAMPLE_DATA_JSON_PATH pcap-to-las --scan-num 5

Checkout the examples.pcap.pcap_to_las() documentation for the example source code.

PCAPs to PCD

To convert to the first 5 scans of our sample data from a pcap file to PCD, you can try:

$ python3 -m ouster.sdk.examples.pcap $SAMPLE_DATA_PCAP_PATH $SAMPLE_DATA_JSON_PATH pcap-to-pcd --scan-num 5

Checkout the examples.pcap.pcap_to_pcd() documentation for the example source code.

PCAPs to PLY

Here we will reuse the PCAP to PCD function that uses Open3d and will exploit the extensive Open3d File IO that gives us an easy way to save the loaded point cloud to PLY. Alternative ways are available via plyfile library.

To convert to the first 5 scans of our sample data from a pcap file to PLY, you can try:

$ python3 -m ouster.sdk.examples.pcap $SAMPLE_DATA_PCAP_PATH $SAMPLE_DATA_JSON_PATH pcap-to-ply --scan-num 5

Checkout the examples.pcap.pcap_to_ply() documentation for the example source code.