Terrestrial LiDAR Pipeline
Use this pipeline when you work with static or handheld LiDAR scanners (Leica, FARO, Trimble, BLK2GO, etc.) and need to turn point clouds into WebAR³ VPS maps.
Pre-processing
- Clean the raw scans — remove tripod artefacts, multiple returns, and moving objects in Cyclone, ReCap, CloudCompare, or similar tools.
- Register the stations — align separate scans using targets or cloud-to-cloud methods.
- Colourise — apply photographic textures if available; otherwise map LiDAR intensity to greyscale.
Export
- Produce a simplified mesh (≤ 5 million triangles) for visual preview.
- Export the point cloud as E57/LAZ/PLY.
- Keep the coordinate system consistent: use a local tangent plane indoors, or a geo-referenced CRS outdoors.
Upload with the Python REST API
# upload_lidar.py
from pathlib import Path
import os
import requests
API_BASE = "https://was-vps.web-ar.xyz/vps/api/v3"
TOKEN = os.environ["WEBAR3_TOKEN"]
DATA_PATH = Path("outputs/plant.e57")
headers = {"Authorization": f"Bearer {TOKEN}"}
payload = {
"name": "Factory Floor",
"dataType": "point_cloud",
"sourceFormat": "e57",
"hybrid": True,
"coordinate": {"lat": 35.68124, "lon": 139.76712}
}
init = requests.post(f"{API_BASE}/maps/import", json=payload, headers=headers)
init.raise_for_status()
info = init.json()
upload_url, map_id = info["uploadUrl"], info["mapId"]
with DATA_PATH.open("rb") as src:
put = requests.put(upload_url, data=src, headers={"Content-Type": "application/octet-stream"})
put.raise_for_status()
finalize = requests.post(f"{API_BASE}/maps/{map_id}/finalize", json={"publish": False}, headers=headers)
finalize.raise_for_status()
print(f"LiDAR map {map_id} queued → {finalize.json()['status']}")
hybrid=Truesignals that the upload contains both a point cloud and an optional mesh (if present in the E57/LAZ bundle).- For indoor-only datasets omit the coordinate block.
Post-processing & Anchors
After the map reaches READY:
- Define anchor points for machinery, entries, and exits.
- Upload them via a small JSON file:
import json
anchors = [
{"name": "CNC-01", "position": [2.4, 0.0, 8.7]},
{"name": "safety_exit", "position": [-11.2, 0.0, 3.1]}
]
resp = requests.post(
f"{API_BASE}/maps/{map_id}/anchors",
headers=headers,
json={"items": anchors}
)
resp.raise_for_status()
- Publish the map from the Console or call
POST /maps/{id}/publishwhen QA is done.