Matlab point cloud file io
The MATLAB Agentic Toolkit brings trusted MATLAB capabilities to AI agents, making engineering and scientific workflows agent-ready.
npx -y skills add matlab/matlab-agentic-toolkit --skill matlab-point-cloud-file-ioAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
What its author says it does
Copied from the file, not written here
Read and write 3-D point cloud data using Lidar Toolbox file I/O. Covers PLY, PCD, LAS/LAZ, PCAP (Velodyne/Ouster/Hesai), E57, and IDC (Ibeo) formats. Use when loading point clouds from disk, saving to disk, choosing the correct reader or writer for a file format, extracting or preserving lidar point attributes, reading Ibeo IDC sensor recordings, or converting between formats.
The file declares its own license as MathWorks BSD-3-Clause. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
13.8 KB, ~3.6k tokens by cl100k_base, as published. Nobody here has run it
Point Cloud File I/O
Read and write 3-D point cloud data in MATLAB using Lidar Toolbox file I/O functions, covering PLY, PCD, LAS/LAZ, sensor PCAP, E57, and IDC (Ibeo) formats.
When to Use
- Loading a point cloud file from disk into a
pointCloudobject - Saving a
pointCloudobject to disk in any supported format - Deciding which reader or writer function to use for a given file format
- Reading LAS/LAZ files with selective filtering (ROI, classification, GPS time)
- Extracting or preserving lidar point attributes (classification, GPS timestamps, scan angle)
- Reading Velodyne, Ouster, or Hesai PCAP sensor recordings frame-by-frame
- Reading multi-scan E57 files with indexed access
- Reading Ibeo IDC sensor recordings with message-based access
- Converting between point cloud formats (e.g., LAS to PLY, PCD to LAZ)
When NOT to Use
- Streaming live sensor data in real time (use
velodynelidar,ousterlidar,sicklidar) - Processing or filtering point clouds after reading (use
pcdownsample,pcdenoise) - Reading or writing surface meshes (use
readSurfaceMesh,writeSurfaceMesh) - Saving point cloud variables to MAT-files (use
save) - Visualizing point clouds (use
pcshow,pcplayer,pcviewer)
Must-Follow Rules
-
Route by file extension, not by habit —
pcreadONLY supports.plyand.pcdfiles. For.las/.lazuselasFileReader+readPointCloud. For.pcapuse the sensor-specific file reader (velodyneFileReader,ousterFileReader, orhesaiFileReader). For.e57usee57FileReader. Callingpcreadon a LAS or PCAP file produces an error, not a warning. Similarly,pcwriteONLY writes PLY and PCD — for LAS/LAZ output uselasFileWriter+writePointCloud. -
PCAP file readers require a mandatory device identifier — never guess it —
velodyneFileReaderrequires aDeviceModelstring (e.g.,"HDL32E").hesaiFileReaderrequires aDeviceModelstring (e.g.,"PandarXT32").ousterFileReaderrequires aCalibrationFilepath (JSON). If the user has not specified the device model or calibration file, ASK — do not assume a default. There is no default value; omitting it causes an error. -
Use two-output syntax to get point attributes from LAS/LAZ —
[ptCloud, ptAttributes] = readPointCloud(reader)returns alidarPointAttributesobject containing Classification, GPSTimeStamp, LaserReturn, NumReturns, ScanAngle, and more. The single-output form discards these attributes permanently. Intensity is on thepointCloudobject (.Intensityproperty), NOT onlidarPointAttributes. -
Preserve attributes with three-argument writePointCloud —
writePointCloud(writer, ptCloud, ptAttributes)preserves Classification, GPSTimeStamp, and other lidar attributes in LAS/LAZ output. The two-argument formwritePointCloud(writer, ptCloud)discards all attributes. If the user has attributes fromlasFileReader/readPointCloud, always pass them through. -
PLY only supports ascii and binary encoding — Calling
pcwrite(ptCloud, "file.ply", Encoding="compressed")throws an error. Only"ascii"and"binary"are valid for PLY. The"compressed"encoding is exclusive to PCD format. Defaults (R2026a+): PLY="binary", PCD="compressed". -
Always use string syntax — Use double-quoted strings (
"text") for all literal text arguments (filenames, device models, encoding values, Name=Value values). UseName=Valuesyntax for all name-value pairs. Never use character vectors ('text') or legacy'Name','Value'pair syntax.
Preflight Procedure
- List MATLAB functions to call
- Check
references/INDEX.mdfor each (function-level + task-level tables) - Read required quick-ref files
- State at response top:
Preflight: quick-ref/xxx.md, quick-ref/yyy.md(orPreflight: none required)
Key Functions
| Function | Purpose | Format | Key Constraint |
|---|---|---|---|
pcread | Read point cloud from file | PLY, PCD | Single call, returns pointCloud |
pcwrite | Write point cloud to file | PLY, PCD | Encoding varies by format |
lasFileReader | Create LAS/LAZ reader object | LAS, LAZ | Two-step: create reader, then readPointCloud |
lasFileWriter | Create LAS/LAZ writer object | LAS, LAZ | Two-step: create writer, then writePointCloud |
velodyneFileReader | Create Velodyne PCAP reader | PCAP | Mandatory DeviceModel (2nd arg) |
ousterFileReader | Create Ouster PCAP reader | PCAP | Mandatory CalibrationFile (2nd arg) |
hesaiFileReader | Create Hesai PCAP reader | PCAP | Mandatory DeviceModel (2nd arg) |
e57FileReader | Create E57 reader object | E57 | Use readPointCloud(reader, idx) for multi-scan |
ibeoLidarReader | Create Ibeo IDC reader object | IDC | Use readMessages to read scan data |
Decision Framework
READING — What is the file extension?
├── .ply / .pcd → pcread(filename)
├── .las / .laz → lasFileReader(filename) + readPointCloud(reader)
├── .pcap (Velodyne) → velodyneFileReader(filename, deviceModel)
├── .pcap (Ouster) → ousterFileReader(filename, calibrationFile)
├── .pcap (Hesai) → hesaiFileReader(filename, deviceModel)
├── .e57 → e57FileReader(filename) + readPointCloud(reader, idx)
└── .idc (Ibeo) → ibeoLidarReader(filename) + readMessages(reader)
WRITING — What output format does the user need?
├── .ply → pcwrite(ptCloud, "file.ply")
│ Encoding: "ascii" or "binary" (default: binary)
├── .pcd → pcwrite(ptCloud, "file.pcd")
│ Encoding: "ascii", "binary", or "compressed" (default: compressed)
├── .las → lasFileWriter("file.las") + writePointCloud(writer, ptCloud)
└── .laz → lasFileWriter("file.laz") + writePointCloud(writer, ptCloud)
Optional: pass ptAttributes as 3rd arg to preserve attributes
PCAP sensor identification: If the user says "Velodyne", "Ouster", or "Hesai" — use the matching reader. If they just say "PCAP file" without specifying the sensor, ASK which sensor produced it.
Ibeo IDC files: If the user has an .idc file, use ibeoLidarReader. Unlike other readers, it uses readMessages (not readPointCloud or readFrame) and returns message-based scan data.
Velodyne device models: VLP16, PuckLITE, PuckHiRes, VLP32C, HDL32E, HDL64E, VLS128, VelarrayH800
Hesai device models: Pandar128E3X, Pandar64, PandarQT, PandarXT32
Gotchas
pcread called on LAS/LAZ file
pcread only supports PLY and PCD formats. Attempting to use it on LAS, LAZ, PCAP, or E57 files throws an error.
% WRONG: pcread does not support LAS
ptCloud = pcread("survey.las");
% CORRECT: Use lasFileReader for LAS/LAZ
reader = lasFileReader("survey.las");
ptCloud = readPointCloud(reader);
Compressed encoding on PLY file
The "compressed" encoding is only valid for PCD format. PLY supports only "ascii" and "binary".
% WRONG: compressed not supported for PLY
pcwrite(ptCloud, "output.ply", Encoding="compressed");
% CORRECT: use binary for compact PLY
pcwrite(ptCloud, "output.ply", Encoding="binary");
% CORRECT: compressed is valid for PCD
pcwrite(ptCloud, "output.pcd", Encoding="compressed");
Using pcwrite for LAS/LAZ output
pcwrite does not support LAS or LAZ format. It only handles PLY and PCD.
% WRONG: pcwrite cannot write LAS
pcwrite(ptCloud, "output.las");
% CORRECT: use lasFileWriter for LAS/LAZ
writer = lasFileWriter("output.las");
writePointCloud(writer, ptCloud);
Losing attributes with two-argument writePointCloud
When writing LAS/LAZ, the two-argument form discards lidar point attributes. Always pass the attributes object if available.
% WRONG: attributes are discarded
reader = lasFileReader("input.laz");
[ptCloud, ptAttr] = readPointCloud(reader);
writer = lasFileWriter("output.laz");
writePointCloud(writer, ptCloud); % ptAttr lost!
% CORRECT: preserve attributes with 3-argument form
reader = lasFileReader("input.laz");
[ptCloud, ptAttr] = readPointCloud(reader);
writer = lasFileWriter("output.laz");
writePointCloud(writer, ptCloud, ptAttr);
Accessing classification from the wrong object
Classification, GPSTimeStamp, LaserReturn, and other lidar-specific attributes are on lidarPointAttributes, not on pointCloud. The pointCloud object holds Intensity (and Location, Color, Normal).
% WRONG: pointCloud does not have Classification
reader = lasFileReader("data.laz");
ptCloud = readPointCloud(reader);
labels = ptCloud.Classification; % Error
% CORRECT: Use two-output syntax
reader = lasFileReader("data.laz");
[ptCloud, ptAttributes] = readPointCloud(reader);
labels = ptAttributes.Classification;
intensity = ptCloud.Intensity; % Intensity is on pointCloud
Reading all PCAP frames without a loop
PCAP readers are frame-based iterators. There is no single function to load all frames at once.
% WRONG: No readAll or similar function
reader = velodyneFileReader("lidarData_ConstructionRoad.pcap", "HDL32E");
allPoints = readPointCloud(reader); % readPointCloud is not a method
% CORRECT: Loop with hasFrame/readFrame
reader = velodyneFileReader("lidarData_ConstructionRoad.pcap", "HDL32E");
while hasFrame(reader)
ptCloud = readFrame(reader);
end
Patterns
Read a PLY or PCD file
ptCloud = pcread("scene.ply");
fprintf("Points: %d\n", ptCloud.Count);
fprintf("X range: [%.2f, %.2f]\n", ptCloud.XLimits);
Read LAS file with classification filtering
reader = lasFileReader("aerial.laz");
[ptCloud, ptAttributes] = readPointCloud(reader, Classification=[2 6]);
labels = ptAttributes.Classification;
fprintf("Ground + building points: %d\n", ptCloud.Count);
Read Velodyne PCAP frames
reader = velodyneFileReader("lidarData_ConstructionRoad.pcap", "HDL32E");
fprintf("Total frames: %d\n", reader.NumberOfFrames);
while hasFrame(reader)
ptCloud = readFrame(reader);
end
Read E57 file with multiple scans
reader = e57FileReader("building.e57");
fprintf("Scans in file: %d\n", reader.NumPointClouds);
for idx = 1:reader.NumPointClouds
ptCloud = readPointCloud(reader, idx);
fprintf("Scan %d: %d points\n", idx, ptCloud.Count);
end
Write point cloud to PLY (binary)
ptCloud = pointCloud(rand(1000,3), Color=uint8(rand(1000,3)*255));
pcwrite(ptCloud, fullfile(tempdir, "output.ply"), Encoding="binary");
Write point cloud to PCD (compressed)
ptCloud = pcread(fullfile(toolboxdir("lidar"), "lidardata", "highwayScene.pcd"));
pcwrite(ptCloud, fullfile(tempdir, "scene_compressed.pcd"), Encoding="compressed");
Read LAS and write to LAZ preserving attributes
reader = lasFileReader("input.las");
[ptCloud, ptAttr] = readPointCloud(reader);
writer = lasFileWriter(fullfile(tempdir, "output.laz"));
writePointCloud(writer, ptCloud, ptAttr);
Convert PCD to PLY
ptCloud = pcread("scene.pcd");
pcwrite(ptCloud, fullfile(tempdir, "scene.ply"), Encoding="binary");
Convert LAS to PCD
reader = lasFileReader("survey.las");
ptCloud = readPointCloud(reader);
pcwrite(ptCloud, fullfile(tempdir, "survey.pcd"), Encoding="compressed");
Read Ibeo IDC file
reader = ibeoLidarReader("sensor_data.idc");
fprintf("Message types: %s\n", strjoin(reader.MessageTypes, ", "));
fprintf("Total messages: %d\n", reader.NumMessages);
% Read all messages — returns array of pointCloud objects
ptClouds = readMessages(reader);
% Two-output form: get message metadata (timestamps, labels, plane info)
[ptClouds, messageData] = readMessages(reader);
% Filter by message type: "Scan" or "PointCloudPlane"
ptClouds = readMessages(reader, Messages="Scan");
% Filter by time range
tStart = reader.FileInfo.TimeStamps{1}(1);
tEnd = tStart + seconds(10);
ptClouds = readMessages(reader, Time=[tStart tEnd]);
ibeoLidarReader key details:
- Supports IDC files from Ibeo FUSION SYSTEM/ECU sensors
- Two message types:
"Scan"(data type 0x2205) and"PointCloudPlane"(data type 0x7510) readMessagesreturns an array ofpointCloudobjects (one per message)- Second output
messageDatais a cell array of structs withMessageType,TimeStamp, and (for PointCloudPlane)Label,ReferencePoint,PlaneOrientation FileInfoproperty is a table with columns: MessageType, DataType, Description, NumMessages, TimeStamps- All properties are read-only
Conventions
- Use
tempdirfor output paths in examples and tests to avoid permission issues - Default to
Encoding="binary"for PLY and omit encoding for PCD (default compressed is best) - Always use double-quoted strings (
"text") andName=Valuesyntax — never character vectors or'Name','Value'pairs - Include file extension explicitly in filename — format is determined from extension
- PLY flattens organized M-by-N-by-3 to unorganized M-by-3; use PCD to preserve organized structure
- NaN/Inf values are skipped when writing to PLY
lasFileWriteronly supports unorganizedpointCloudobjects
References
| Load when... | Reference |
|---|---|
| Reading or writing LAS/LAZ files, need filtering NV-pairs, attribute details, or writer properties | references/quick-ref/las-io.md |
| Reading PCAP files from Velodyne, Ouster, or Hesai sensors | references/quick-ref/pcap-readers.md |