Skip to main content

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

  1. Clean the raw scans — remove tripod artefacts, multiple returns, and moving objects in Cyclone, ReCap, CloudCompare, or similar tools.
  2. Register the stations — align separate scans using targets or cloud-to-cloud methods.
  3. 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=True signals 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:

  1. Define anchor points for machinery, entries, and exits.
  2. 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()
  1. Publish the map from the Console or call POST /maps/{id}/publish when QA is done.