XGRIDS文档
  • 简体中文
  • English
  • 繁體中文
  • 日本語
  • Deutsch
  • Español
  • Italiano
  • Français
  • Русский
  • Polski
  • Nederlands
  • 简体中文
  • English
  • 繁體中文
  • 日本語
  • Deutsch
  • Español
  • Italiano
  • Français
  • Русский
  • Polski
  • Nederlands
  • 灵视 P1

    • 产品概述
    • 设备基本操作
    • 使用 LCC Scan App
    • 维护及保养
    • 常见问题
  • 灵光 K 系列

    • 灵光 K1

      • 产品概述
      • 设备基本操作
      • 设备激活与连接
      • 设备采集
      • 获取绝对坐标点云数据
      • 地图融合
      • 典型场景路线规划建议
      • 注意事项
      • 常见问题
    • 灵光 K2

      • 产品概述
      • 设备基本操作
      • 设备激活与连接
      • 设备采集
      • 获取绝对坐标点云数据
      • 地图融合
      • 典型场景路线规划建议
      • 注意事项
      • 常见问题
  • 灵光 L 系列

    • 灵光 L2 Pro

      • 产品概述
      • 设备基本操作
      • 设备激活与连接
      • 设备采集
      • 获取绝对坐标点云数据
      • 实时测量功能
      • 附录
      • 常见问题
    • 灵光 L3

      • 产品概述
      • 设备基本功能
      • 设备激活与连接
      • 设备采集
      • 获取绝对坐标点云数据操作流程
      • 附录
  • 配件

    • 补光灯

      • 安装指导
      • 基本操作
      • 常见问题
  • Lixel Studio

    • 版权
    • 安装与激活
    • 界面说明
    • 文件
    • 工程处理
    • 工具
    • 平面绘制
    • 行业应用
    • 设置
    • 设备感知
    • 常见问题 / FAQ
  • Lixel CyberColor

    • LCC Studio

      • 入门
      • 版本与更新
      • 下载与安装
      • 界面概览与导航
      • 重建前工作
      • 模型重建
      • 单模型重建
      • 地图融合
      • 空地融合
      • 航拍重建
      • 我的模型
      • 其他功能
      • 设置与账号
      • 转换工具
      • 视频重建
      • 常见问题 / FAQ
    • LCC Scene Editor

      • 版本与更新
      • 账号与登录
      • 产品概览与主页
      • 编辑器界面介绍
      • 三种场景漫游快捷操作
      • 文件
      • 设置
      • 编辑操作
      • 窗口
      • 视图工具栏
      • 资产与属性
      • 左侧工具栏
      • 视点
      • 跳转点
      • 天空盒
      • 标注
      • 测量
      • 场景漫游
      • 场景报告
      • 智能户型图(3D Layout)
      • 小地图
      • 预览模式(Viewer)
      • 帮助
      • 常见问题 / FAQ
      • 出生点
    • LCC Model Editor

      • 版本与更新
      • 新手指引
      • 概览与界面
      • 文件操作
      • 选择器
      • 编辑操作
      • 测量
      • 调色
      • 资产管理
      • 设置与帮助
      • 常见问题 / FAQ
    • 采集指南

      • 概述
      • 采集设备总览
      • 通用采集原则
      • 室内场景采集
      • 室外场景采集
      • 大场景采集(地图融合)
      • 空地融合采集
      • 物体采集
      • 人物采集
      • 视频重建采集
      • 高清补拍
      • 控制点(灵视 P1)
      • 常见问题与排查
    • LCC Studio Linux

      • 产品概要说明
      • 基本架构说明书
      • 安装部署说明书
      • 容器启动参数说明书
      • CodeMeter离线授权部署说明书
      • API指令集说明书
      • 附录-开发者数据说明书
      • 附录-错误码列表
      • 单机多卡集群部署QuickStart
    • 使用技巧

      • 多个大型 3DGS 模型融合工作流
    • 历史版本
  • Plugin & SDK

    • Unreal

      • 介绍
      • 快速入门 - Windows
      • 快速入门 - Linux
      • 快速入门 - Quest3
      • 版本与授权
      • 渲染
      • Tiled 光栅化(实验性)
      • 画面调节
      • 法线与光照
      • 场景编辑
      • 性能参数说明
      • 性能优化指南
      • 第三方与引擎插件集成
      • 代理网格
      • 加载动画
      • 碰撞
      • 寻路系统支持
      • 单层水支持
      • 本地化
      • 常见问题
      • 故障排查
      • 日志与诊断
      • 联系我们
      • 最佳实践

        • 用 LixelStudio 网格为 3DGS 重打光
      • API 参考

        • ALCCActorBase
        • ULCCComponentBase
        • ULCCComponent
        • ULCC2Component
        • SOG / SPZ / PLY Actors
        • ALCC2ProxyMesh
        • ALCCClippingVolume
        • ALCCSectionPlane
        • ALCCLoadVolume
        • ULCCUtilLibrary
        • Enums
        • Structs
      • 更新日志

        • v3.4.0
        • v3.3.1
        • v3.0.0
        • v2.2.1
        • v1.0.0
        • v0.9.0
        • v0.8.0
        • v0.7.1
        • v0.6.1
        • v0.5.2
        • v0.4.1
        • v0.4.0
        • v0.3.0
        • v0.0.5
        • v0.0.4
        • v0.0.3
        • v0.0.2
        • v0.0.1
    • X-Brain

      • 产品概述
      • 硬件接口
      • 快速开始
      • 核心概念
      • 集成指南
      • API 参考
      • 数据类型
      • ROS2 桥接
      • 示例程序
      • 部署与网络
      • 排障与 FAQ
      • 版本与发布
    • Web

      • 介绍
      • 渲染性能优化指南
      • 显卡配置
      • 常见开发问题
      • API参考

        • LCCRender::clearIndexDB
        • LCCRender::dispose
        • LCCRender::load
        • LCCRender::setCamera
        • LCCRender::unload
        • LCCRender::update
        • LCCObject::checkRenderNextFrame
        • LCCObject::clearRenderNextFrame
        • LCCObject::ecef2Prj
        • LCCObject::getBounds
        • LCCObject::getEnvInstancedMesh
        • LCCObject::getInstancedMesh
        • LCCObject::getLodInfos
        • LCCObject::getOriginPosition
        • LCCObject::getProjectionCoordinateSystemInfos
        • LCCObject::hasCollision
        • LCCObject::hasEnvironment
        • LCCObject::hasShcoef
        • LCCObject::intersectsCapsule
        • LCCObject::intersectsRayExt
        • LCCObject::intersectsRayFromOriginExt
        • LCCObject::intersectsSphere
        • LCCObject::lowerToBottom
        • LCCObject::prj2Ecef
        • LCCObject::raiseToTop
        • LCCObject::raycast
        • LCCObject::raycastFromOrigin
        • LCCObject::setAlpha
        • LCCObject::setClipBox
        • LCCObject::setClipPlane
        • LCCObject::setEndLod
        • LCCObject::setLodAutoLevelUp
        • LCCObject::setMaxDistance
        • LCCObject::setMaxNodeSplats
        • LCCObject::setMaxSplats
        • LCCObject::setOriginPosition
        • LCCObject::setPointsColor
        • LCCObject::setRenderState
        • LCCObject::setRotation
        • LCCObject::setScale
        • LCCObject::setSemantic
        • LCCObject::setSemanticColor
        • LCCObject::setSmooth
        • LCCObject::setStartLod
        • LCCObject::setTranslation
        • LCCObject::setVisible
        • LCCObject::togglePointsDisplayMode
        • LCCObject::useEnvironment
        • LCCObject::useShcoef
      • 更新日志

        • v0.6.3
        • v0.6.2
        • v0.6.1
        • v0.6.0
        • v0.5.5
        • v0.5.4
        • v0.5.3
        • v0.5.2
        • v0.5.1
        • v0.5.0
        • v0.4.1
        • v0.4.0
        • v0.3.1
        • v0.3.0
        • v0.2.0
    • Lixel OpenAPI

      • 概述
      • 连接与鉴权
      • 消息模型与编解码
      • 接口清单
      • 实时数据
      • 项目文件访问
      • 错误码
      • Python

        • 快速开始
        • 客户端封装与工具
        • 常见问题
      • C++

        • 快速开始
        • 客户端与示例
        • 常见问题

快速开始

本篇带你用最短路径跑通一次完整的请求-响应:连接设备 → 准备消息编解码 → 发出请求 → 收到响应。示例基于项目提供的 Python 客户端封装,不依赖图形界面。

准备工作

开始前,确认以下几项:

  1. 设备已上电,并与你的主机建立网络连接(USB 或 Wi-Fi,见 连接与鉴权)。
  2. 已拿到 OpenAPI Key(获取方式见 连接与鉴权 · 申请 OpenAPI Key)。
  3. 主机已获取示例工程,并装好 Python 环境与依赖(见下)。

环境与依赖

项目要求
操作系统Linux、Windows(图形界面分别使用 PySide2、PySide6)
Python3.8 及以上
MQTT 客户端paho-mqtt,2.0.0 及以上
编解码protobuf、grpcio-tools(用于编译 proto)
点云解压(可选)lz4、zstandard(只在订阅实时点云时需要)

获取示例工程并安装依赖

示例工程是公开仓库 Lixel_OpenAPI。以下命令以 Ubuntu 22.04 为例,Windows 的步骤见仓库里的 README.zh-CN.md:

sudo apt-get update
sudo apt-get install -y python3-pip python3-venv git
git clone --branch 1.1.0 https://github.com/xgrids/Lixel_OpenAPI.git
cd Lixel_OpenAPI                    # 仓库根目录
python3 -m venv venv
source venv/bin/activate            # 激活后可以直接使用 python 和 pip
unset PYTHONPATH                    # 机器上装过 ROS 时需要,避免 ROS 的包混入
pip install --upgrade pip
pip install -r python/requirements.txt     # 含 paho-mqtt、protobuf、grpcio-tools
pip install lz4 zstandard           # 需要实时点云时再装

注意以下几点:

  • 要用虚拟环境,不要用系统自带的 Python 包:Ubuntu 22.04 自带的 python3-protobuf 是 3.12.4,低于 python/requirements.txt 要求的 5.26.0。
  • Ubuntu 22.04 默认没有 pip 和 python3-venv,也没有 python 命令,所以先装上面的软件包,并在虚拟环境激活后再使用 python。
  • 下面所有 Python 片段都要在 python/ 目录下运行(先 cd python,例如把片段保存成 python/quick.py 后执行 python quick.py),否则 from example.core import … 会找不到 example 包。src/generate_proto.py 等带 python/ 前缀的命令则在仓库根目录运行。
  • python/requirements.txt 不含图形界面依赖;运行图形界面需要另外安装 python/requirements-linux.txt(PySide2)或 python/requirements-windows.txt(PySide6)。

第一步:准备 Protobuf 模块

所有业务消息都用 Protobuf 编解码。先把 proto 定义编译为 Python 模块:

python python/src/generate_proto.py

注:编译使用当前环境的 grpc_tools.protoc,确保生成代码与运行时的 protobuf 版本一致。运行时建议设置 PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python,避免不同环境下的 C 扩展不兼容。

第二步:连接设备

用客户端封装建立连接。有线连接时设备默认地址为 192.168.55.1,MQTT 端口为 1883。下面的示例适用于 K1 / L2PRO;使用 MQTTS 的型号见 连接设备,需要 use_tls=True、port=8883 和厂商提供的账号:

from example.core import ClientOptions, OpenApiClient

opts = ClientOptions(
    host="192.168.55.1",
    port=1883,
    openapi_key="<由 XGRIDS 提供>",
)

with OpenApiClient(opts) as client:
    print("connected:", client.is_connected)

with 语句会在进入时连接、退出时断开。连接失败会抛出异常:地址不可达或端口未开放时抛出 OSError(含 ConnectionRefusedError;Python 3.10 及以上的网络超时是 TimeoutError);已连上 TCP 但 10 秒内没有收到成功的 CONNACK(包括 broker 拒绝连接)时抛出 TimeoutError,超时时间由 ClientOptions.connect_timeout 设置。

第三步:发出第一个请求

发一个最简单的"查询设备信息"请求,并等待响应。请求-响应是同步调用,内部会先订阅响应 Topic、再发布请求、阻塞等待应答:

from example.core import ClientOptions, OpenApiClient

opts = ClientOptions(host="192.168.55.1", openapi_key="<由 XGRIDS 提供>")

with OpenApiClient(opts) as client:
    rsp = client.request(
        req_topic="lixel/application/request/device_info",
        req_message="DeviceInfoRequest",
        payload={},                                   # 空负载即可
        rsp_topic="lixel/application/response/device_info",
        rsp_message="DeviceInfoResponse",
    )
    print(rsp)                                        # 已解码为 dict

request() 会自动把 OpenAPI Key 填入消息头。返回值是解码后的字典,包含设备型号、固件版本、相机列表等信息。

第四步:订阅实时上报

除了请求-响应,很多数据是设备主动上报的。订阅设备状态,每秒会收到一次:

import time
from example.core import ClientOptions, OpenApiClient


def on_status(topic, data):      # data 已解码为 dict
    print(topic, data)


opts = ClientOptions(host="192.168.55.1", openapi_key="<由 XGRIDS 提供>")
with OpenApiClient(opts) as client:
    client.subscribe(
        "lixel/application/report/device_status",
        "DeviceStatusReport",
        on_status,
    )
    time.sleep(5)                # 保持连接,等待上报

subscribe() 会立即返回,所以要让程序保持运行,回调才会被触发。回调里抛出的异常会被记录到日志(Python 默认输出到终端),不会中断其他订阅。

注:OpenAPI 公开的接口中,只有心跳采用 JSON 文本。订阅心跳时 message 传空字符串,回调会收到字符串而非字典。

注:收到心跳只说明设备已联网,不表示业务已就绪。设备刚开机时,端口已开放、心跳已经在发,但 device_info 等请求可能在接下来一段时间内没有响应。开机后先重试 device_info,成功后再发其他请求。

完整示例:扫描一次

一次典型的端到端业务流程是:连接 → 确认设备待机 → 启动扫描 → 等设备真正进入扫描中 → 扫描一段时间 → 停止扫描 → 等设备回到待机。

连接设备 → 订阅 device_status → 确认待机 → AC_START → 等待扫描中 → 扫描 → AC_STOP → 等待待机 → 断开

扫描的开始和停止都是异步的。AC_START 的响应只表示设备收到了请求,设备随后依次经过待机、开始扫描中、扫描中;实测 AC_START 后 14 到 15 秒才进入扫描中。进入扫描中之前发出的 AC_STOP 实测会被推迟,设备不会进入扫描中。AC_STOP 之后设备经停止扫描中回到待机,实测从进入停止扫描中算起,43 到 46 秒回到待机(3 次);从发出 AC_STOP 算起,单次实测 52.1 秒(Lixel L2Pro,固件 V3.2.1,状态每秒上报一次,精度 1 秒)。所以示例订阅 report/device_status,读取 modeling_state,等到目标状态再继续,不使用固定的 sleep 等待。modeling_state 的取值见 错误码 · 扫描状态码。

import threading
import time
from example.core import ClientOptions, OpenApiClient

SCAN_READY = 0x1204012C      # EC_ScanReady,待机
SCAN_MODELING = 0x1204012E   # EC_ScanModeling,扫描中

state = {"modeling_state": None}
cond = threading.Condition()


def on_status(topic, data):
    with cond:
        state["modeling_state"] = data["modeling_state"]
        cond.notify_all()


def wait_for(target, timeout):
    deadline = time.monotonic() + timeout
    with cond:
        while state["modeling_state"] != target:
            remaining = deadline - time.monotonic()
            if remaining <= 0:
                return False
            cond.wait(remaining)
    return True


def modeling(client, payload):
    return client.request(
        req_topic="lixel/application/request/modeling",
        req_message="ModelingRequest",
        payload=payload,
        rsp_topic="lixel/application/response/modeling",
        rsp_message="ModelingResponse",
    )


opts = ClientOptions(host="192.168.55.1", openapi_key="<由 XGRIDS 提供>")
with OpenApiClient(opts) as client:
    client.subscribe("lixel/application/report/device_status",
                     "DeviceStatusReport", on_status)
    if not wait_for(SCAN_READY, 10):
        raise SystemExit("设备不在待机状态: 0x%X" % (state["modeling_state"] or 0))   # 取值见 08 页的扫描状态码
    rsp = modeling(client, {"action": "AC_START", "project_name": "demo",
                            "record_mode": "RM_RECORD_CALC", "scan_mode": "SM_PCL",
                            "mount_type": "MT_HAND"})
    code = rsp.get("error", {}).get("code")
    if code not in (0x12040001, 0x12040002):   # EC_Success / EC_SuccessAndReboot
        raise SystemExit("设备未接受启动请求: %s" % rsp.get("error"))
    if wait_for(SCAN_MODELING, 90):      # 实测 AC_START 后 14 到 15 秒进入扫描中
        time.sleep(10)                   # 扫描 10 秒
    else:
        print("等待进入扫描中超时")
    modeling(client, {"action": "AC_STOP"})
    wait_for(SCAN_READY, 180)            # 实测 AC_STOP 后最长 52 秒回到待机,180 秒是余量

这段示例是仓库里 python/example/usage/modeling.py 的简化版:流程相同,但省略了 Ctrl-C 和等待超时之后补发 AC_STOP 的善后处理,也没有退出码。启动请求未被接受通常是密钥错误或消息格式错误,设备不会因为当前不在待机而用返回码拒绝,所以示例先检查 modeling_state。正式使用请直接运行 modeling.py。从 1.0.1 起,它会等设备真正进入扫描中,请求未被接受时退出,被 Ctrl-C 中断或等待超时时也会发出停止:python python/example/usage/modeling.py --host 192.168.55.1 --key <由 XGRIDS 提供> --project demo。完整流程需要一分钟以上。1.0.0 的 modeling.py 只固定等待几秒就发出停止,设备来不及进入扫描中,请使用 1.0.1 及以上版本。

待机时订阅位姿,实测 3 秒内没有数据;位姿和点云都是在扫描中取到的。要在扫描过程中接收,请在设备进入扫描中之后订阅,例如把 client.subscribe("lixel/application/report/lio_pose", "LioPoseReport", 回调) 放在 wait_for(SCAN_MODELING, 90) 成功之后。

注:扫描参数(录制模式、扫描模式、挂载方式等)的取值见 接口清单 · 扫描建图。实时点云需要额外解压,见 实时数据。

下一步

  • 不同型号的连接方式与鉴权细节,见 连接与鉴权。
  • 想了解 Topic 规则、消息头与编解码原理,见 消息模型与编解码。
  • 完整接口清单(扫描、点位、工程、RTK 等),见 接口清单。
  • 更多可直接运行的脚本,见 客户端封装与工具。