API 参考
本篇描述每个接口的作用、参数、返回值、副作用,以及订阅回调中指针/变量的内存与生命周期。接口涉及的数据结构详见数据类型。
- C++ 接口:
xg/robot_sdk.h(header-only) - C 接口:
xg/robot_sdk_c.h(ABI 真源) - 版本:
xg_sdk_version()="1.0.0"
通则
错误模型
所有会失败的接口以返回值报错,不抛异常。C++ xg::Error 与 C xg_err_t 数值一一对应。
| C | C++ | 值 | 含义与集成方动作 |
|---|---|---|---|
XG_OK | Error::Ok | 0 | 成功。启停时只表示命令已接受,不表示状态已到达 |
XG_ERR_INVALID_ARG | InvalidArg | -1 | 空指针、struct_size 不匹配、IP 空/过长、相机枚举越界。修正参数后重试 |
XG_ERR_NOT_CONNECTED | NotConnected | -2 | 未连接 |
XG_ERR_TIMEOUT | Timeout | -3 | 未在超时内收到设备应答。命令是否送达未知,禁止对启停直接重发,先 queryRecordStatus |
XG_ERR_REJECTED | Rejected | -4 | 设备拒绝,或订阅槽已被占。查询状态或先 unsubscribe |
XG_ERR_DEVICE_ERROR | DeviceError | -5 | 设备故障态(录制路径更多通过 RecordState::Error 表达) |
XG_ERR_PROTOCOL | Protocol | -6 | 应答无法解析,通常为固件/SDK 协议不匹配 |
XG_ERR_INTERNAL | Internal | -7 | SDK 内部错误 |
xg_err_str / xg::toString(Error) 返回静态 UTF-8 字符串,不必释放。
struct_size
C 侧由调用方分配的结构(xg_options_t、xg_record_status_t、各 *_calib_t、xg_device_info_t、xg_init_pose_t、xg_data_path_t)必须先置 struct_size = sizeof(...),否则返回 InvalidArg(当前实现要求精确相等)。由 SDK 填写的回调结构(xg_pose_t 等)的 struct_size 由 SDK 写入,调用方只读。C++ 封装已代填。
线程与寿命
- 同一
Device/xg_device_t不可重入,多线程须调用方加锁。 - 订阅回调在 SDK 内部线程触发,不可阻塞、不可在回调内再调同一句柄的 SDK 接口。
- 回调里的指针(
points、jpegData、C 的entries)返回后不可访问,需持久化必须回调内拷贝。
连接接口
open / xg_device_open
| 签名 | |
|---|---|
| C++ | static std::unique_ptr<Device> Device::open(const Options& opts, Error* error = nullptr) |
| C | xg_err_t xg_device_open(const xg_options_t* opts, xg_device_t** out_dev) |
作用: 建立到设备端口(默认 7448)的连接,并做一次真实查询作为连通性探测。 入参: Options / xg_options_t(须 struct_size)。 出参: C++ 返回 unique_ptr<Device>,失败为 nullptr 且可写 error;C 写 *out_dev,失败为 NULL。
| 返回 | 条件 |
|---|---|
Ok | 探测收到可解析应答 |
InvalidArg | 空指针、struct_size 错、IP 非法 |
Timeout | 超时内设备无应答(端口不通 / 服务未起 / IP 错) |
| 其他 | 探测应答协议错误等 |
副作用: 分配句柄与会话;未成功不泄漏句柄。调用线程阻塞至探测结束(最长约 connectTimeoutMs)。
~Device / xg_device_close
| 签名 | |
|---|---|
| C++ | Device::~Device()(析构自动调用) |
| C | void xg_device_close(xg_device_t* dev) |
取消全部订阅,关闭会话。dev == NULL 为空操作。关闭后指针不得再用。
isConnected / xg_device_is_connected
| 签名 | |
|---|---|
| C++ | bool Device::isConnected() const |
| C | int xg_device_is_connected(const xg_device_t* dev) |
探测连接是否正常,返回 true/1 或 false/0,dev == NULL → 0。
注:实现上可能再发一次查询(最长约 3 s),不要在热路径高频调用。
录制控制接口
共同前置: 句柄已 open。共同副作用: start/stop 向设备派发命令,不等待状态机到达目标。
startRecord / xg_record_start
| 签名 | |
|---|---|
| C++ | Error Device::startRecord() |
| C | xg_err_t xg_record_start(xg_device_t* dev) |
下发开始录制命令,只下发不等待,须轮询 queryRecordStatus 确认。
| 返回 | 含义 | 动作 |
|---|---|---|
Ok | 已接受,或本就在录(幂等) | 轮询直到 Recording 或 Error |
Timeout | 无应答 | 先 query,再决定是否重发 |
Rejected | 明确拒绝且非幂等 | query 原因 |
Protocol | 应答坏 | 核对版本 |
InvalidArg | dev == NULL | — |
轮询建议间隔 ≥ XG_RECOMMENDED_POLL_INTERVAL_MS(500ms)。Idle/Starting 继续等;Error 立即停。
stopRecord / xg_record_stop
| 签名 | |
|---|---|
| C++ | Error Device::stopRecord() |
| C | xg_err_t xg_record_stop(xg_device_t* dev) |
与 start 对称,目标态 Idle。warning == true 时仍可停。落盘耗时随数据量变化。返回值语义同 startRecord。
queryRecordStatus / xg_record_query
| 签名 | |
|---|---|
| C++ | Error Device::queryRecordStatus(RecordStatus* status) |
| C | xg_err_t xg_record_query(xg_device_t* dev, xg_record_status_t* out_status) |
查询当前录制状态,不改变设备状态,可安全轮询。出参 RecordStatus 不可空,C 须填 struct_size。
| 返回 | 含义 |
|---|---|
Ok | status 已填 |
InvalidArg | 空或 struct_size 错 |
Timeout | 无应答;不代表录制失败,可重试 |
Protocol | 应答无记录状态或非数字 |
订阅接口
共同约定:
- 所有订阅须在
open成功后调用;出数据通常要求设备已在录制且定位在跑,否则可能长时间 0 帧。 - 每类数据同一句柄只占一个订阅槽,重复订阅返回
Rejected(图像按相机分三个独立槽)。 - 回调在 SDK 内部线程触发,不可阻塞、不可在回调内再调同一句柄的接口。
- 取消订阅幂等:无活跃订阅时也返回
Ok;返回后保证不再触发对应回调。
位姿订阅
| C++ | C | |
|---|---|---|
| 订阅 | Error subscribePose(std::function<void(const Pose&)>) | xg_subscribe_pose(dev, cb, user) |
| 取消 | Error unsubscribePose() | xg_unsubscribe_pose(dev) |
订阅设备位姿流。约 100 Hz,设备(IMU)系。数据结构见数据类型 · Pose。
| 返回 | 条件 |
|---|---|
Ok | 订阅成功 |
InvalidArg | dev / cb 空 |
Rejected | 已有位姿订阅(须先 unsubscribePose) |
Internal | 内部声明失败 |
内存: Pose 纯标量、无堆指针,回调参数可整体按值保存(Pose saved = pose;),无需 free/delete。
点云订阅
点云有两个来源,共用同一结构体 CloudFrame,语义不同:
| 来源 | C++ | C | 频率 | 坐标系 | 说明 |
|---|---|---|---|---|---|
| reloc 点云 | subscribeCloud / unsubscribeCloud | xg_subscribe_cloud / xg_unsubscribe_cloud | ~10 Hz | 设备(IMU)系 | 重定位配准点云(NDT 产物),不是每帧雷达扫描 |
| 原始点云 | subscribeRawCloud / unsubscribeRawCloud | xg_subscribe_raw_cloud / xg_unsubscribe_raw_cloud | ~10 Hz | 雷达系 | 去畸变原始帧,未经 SLAM |
两个订阅槽独立。返回值:Ok / InvalidArg / Rejected(对应类型已有订阅)/ Internal。
内存: points 指向 SDK 内部复用缓冲,仅回调期内有效,下一帧覆盖。要留整帧回调内深拷贝:memcpy(dst, frame.points, frame.count * sizeof(xg_point_t))(即 count * 16 字节)。禁止对 points 调用 free/delete。
IMU 订阅
| C++ | C | |
|---|---|---|
| 订阅 | Error subscribeImu(std::function<void(const Imu&)>) | xg_subscribe_imu(dev, cb, user) |
| 取消 | Error unsubscribeImu() | xg_unsubscribe_imu(dev) |
订阅原始 IMU 流(未经 SLAM 处理),约 200 Hz。返回值:Ok / InvalidArg / Rejected / Internal。
内存: 纯标量、无堆指针,规则同 Pose。
图像订阅
| C++ | C | |
|---|---|---|
| 订阅 | Error subscribeImage(CameraId, std::function<void(const ImageFrame&)>) | xg_subscribe_image(dev, camera_id, cb, user) |
| 取消 | Error unsubscribeImage(CameraId) | xg_unsubscribe_image(dev, camera_id) |
订阅相机 JPEG 图像流。三路相机各占独立订阅槽(Left/Center/Right)。帧率取决于设备端 JPEG 编码配置(默认约 2fps)。
返回值:Ok / InvalidArg(空 / cameraId 越界)/ Rejected(该相机已有订阅)/ Internal。
注:此
CameraId(0/1/2)与getCameraCalib(0..3)的标定索引不是同一套映射。
内存: jpegData 指向 SDK 内部缓冲,回调返回即失效。要存图/解码留用须回调内 memcpy(dst, frame.jpegData, frame.jpegSize)。回调里的 jpegData/jpegSize 就是纯 JPEG(SDK 已解析线上头部)。禁止 free/delete。
错误码订阅
| C++ | C | |
|---|---|---|
| 订阅 | Error subscribeErrCode(std::function<void(const ErrCodeFrame&)>) | xg_subscribe_err_code(dev, cb, user) |
| 取消 | Error unsubscribeErrCode() | xg_unsubscribe_err_code(dev) |
订阅设备各模块(定位、建图、SLAM 等)错误码,设备批量推送,量级 ~10 Hz,空数组不回调。返回值:Ok / InvalidArg / Rejected / Internal。
内存:
- C 侧:
entries指向 SDK 内部复用缓冲,回调后被下一帧覆盖;留用须memcpy(dst, frame->entries, frame->count * sizeof(xg_err_code_entry_t))。禁止free/delete。 - C++ 侧:
ErrCodeFrame.entries是已拷出的std::vector,回调内可随意读;跨回调持有仍需再拷(auto saved = frame.entries;)。
标定查询接口
三者可在未录制时调用(读设备文件)。C 出参必须 struct_size。结构体字段见数据类型。
getCameraCalib / xg_get_camera_calib
| 签名 | |
|---|---|
| C++ | Error Device::getCameraCalib(int cameraIndex, CameraCalib* out) |
| C | xg_err_t xg_get_camera_calib(xg_device_t* dev, int camera_id, xg_camera_calib_t* out) |
查询指定相机标定参数。cameraIndex/camera_id:0–3(标定索引,不是 CameraId)。
| 返回 | 条件 |
|---|---|
Ok | 找到对应 index |
InvalidArg | 空、index 非 0–3、struct_size 错 |
Timeout | 无应答 |
Protocol | 应答坏或找不到该 index |
getImuCalib / xg_get_imu_calib
| 签名 | |
|---|---|
| C++ | Error Device::getImuCalib(ImuCalib* out) |
| C | xg_err_t xg_get_imu_calib(xg_device_t* dev, xg_imu_calib_t* out) |
查询 IMU 标定参数。返回值:Ok / InvalidArg / Timeout / Protocol。缺节点时对应数组保持 0。
getLidarCalib / xg_get_lidar_calib
| 签名 | |
|---|---|
| C++ | Error Device::getLidarCalib(LidarCalib* out) |
| C | xg_err_t xg_get_lidar_calib(xg_device_t* dev, xg_lidar_calib_t* out) |
查询雷达标定参数(含 Lidar→IMU、Lidar→Cam0 外参)。返回值同上。
设备状态接口
getDeviceInfo / xg_get_device_info
| 签名 | |
|---|---|
| C++ | Error Device::getDeviceInfo(DeviceInfo* out) |
| C | xg_err_t xg_get_device_info(xg_device_t* dev, xg_device_info_t* out) |
查询设备电量/存储/内存/建图状态等。
| 返回 | 条件 |
|---|---|
Ok | 解析到状态数据 |
InvalidArg | 空 / struct_size |
Timeout | 无应答 |
Protocol | 应答格式非法 |
注:
modelingState是内部建图码,仅供参考,不是RecordState;录制状态请用queryRecordStatus。
定位初值接口
setLocInitPose / xg_set_loc_init_pose
| 签名 | |
|---|---|
| C++ | Error Device::setLocInitPose(const InitPose& pose) |
| C | xg_err_t xg_set_loc_init_pose(xg_device_t* dev, const xg_init_pose_t* pose) |
向已加载地图的定位库注入世界系位姿先验。
前置: 设备宜已 Recording 且定位已启动,否则设备可能丢弃初值仍回成功。 入参: InitPose;C 须 struct_size。四元数模长须 > 0.1。
| 返回 | 条件 |
|---|---|
Ok | 应答成功(已收下先验) |
InvalidArg | 空 / struct_size |
Timeout | 无应答 |
Rejected | 缺字段、四元数模长 ≤ 0.1、定位未就绪等 |
Protocol | 应答格式非法 |
注:
Ok只表示设备收下了先验,不代表已定位到地图,也没有阶段/结果查询。本版通过设备开始输出合理位姿来间接判断重定位是否生效。
工程路径接口
getDataPath / xg_get_data_path
| 签名 | |
|---|---|
| C++ | Error Device::getDataPath(std::string* path) |
| C | xg_err_t xg_get_data_path(xg_device_t* dev, xg_data_path_t* out) |
查询当前工程的录制数据存储路径。录制中为当前工程;未录制可能为空或上一工程。
| 返回 | 条件 |
|---|---|
Ok | 有路径数据(path 可为空串) |
InvalidArg | 空 / struct_size / C++ path == nullptr |
Timeout | 无应答 |
Protocol | 解析失败 |
地图管理接口
用于把上位机本机的一整套全局初始化重定位地图上传到设备,供设备端做全局初始化重定位;并支持激活、列出、删除。集成方只提供本机目录 + mapId,设备端真实存放路径不暴露。
典型流程:uploadMap(上传,带进度)→ setActiveMap(激活)→ (可选)setLocInitPose(给初值)→ 设备开始全局初始化重定位。
本机地图目录结构要求(uploadMap 上传前会本地校验,缺文件立即失败):
<地图目录>/
├── location_map.las
└── loc_database/
├── camera_param.proto
├── fpfh_feature.proto
├── keyframes.proto
└── vlad.proto
uploadMap / xg_upload_map
| 签名 | |
|---|---|
| C++ | Error Device::uploadMap(const MapUploadOptions& opts, std::function<void(float)> progressCb = nullptr) |
| C | xg_err_t xg_upload_map(xg_device_t* dev, const xg_map_upload_opts_t* opts, xg_map_progress_cb_t on_progress, void* user_data) |
上传一整套重定位地图到设备。阻塞至完成或失败,进度经回调上报(进度范围 [0.0, 1.0],回调可空)。内部走分片 + NACK 重传。
入参: MapUploadOptions / xg_map_upload_opts_t(C 须 struct_size)。数据结构见数据类型 · MapUploadOptions。
| 返回 | 条件 |
|---|---|
Ok | 上传成功就绪 |
InvalidArg | 参数非法(多为本机地图目录结构不全,见上方要求) |
NotConnected | 未连接 |
Timeout | 超时 |
Rejected | 设备拒绝(磁盘不足 / mapId 冲突 / 完整性校验失败) |
Internal | 本地打包或传输失败 |
注:上传后需调
setActiveMap激活,再(可选)setLocInitPose给初值。mapId仅允许[A-Za-z0-9_-]。
setActiveMap / xg_set_active_map
| 签名 | |
|---|---|
| C++ | Error Device::setActiveMap(const std::string& mapId) |
| C | xg_err_t xg_set_active_map(xg_device_t* dev, const char* map_id) |
激活指定地图用于重定位(把设备定位路径切到该地图目录)。map_id 不可为空。
| 返回 | 条件 |
|---|---|
Ok | 成功 |
InvalidArg | 参数非法 |
Rejected | 地图不存在 |
Timeout | 设备未应答 |
listMaps / xg_list_maps
| 签名 | |
|---|---|
| C++ | Error Device::listMaps(std::vector<MapInfo>* out) |
| C | xg_err_t xg_list_maps(xg_device_t* dev, xg_map_list_t* out) |
查询设备上已有的地图列表(含每个地图的文件层次清单)。出参不可空,C 须 struct_size。数据结构见数据类型 · MapInfo。
| 返回 | 条件 |
|---|---|
Ok | 成功 |
InvalidArg | 参数非法 |
Timeout | 设备未应答 |
内存:
- C 侧:
out->maps及其内部files/path指针指向 SDK 内部缓冲,仅本次调用有效,下次调用同接口会覆盖。需持久化请在返回后立即深拷贝。禁止free/delete。 - C++ 侧:
listMaps已把结果拷进std::vector<MapInfo>(含每个MapInfo.files),可安全长期持有。
deleteMap / xg_delete_map
| 签名 | |
|---|---|
| C++ | Error Device::deleteMap(const std::string& mapId) |
| C | xg_err_t xg_delete_map(xg_device_t* dev, const char* map_id) |
删除设备上指定地图(回收空间)。map_id 不可为空。
| 返回 | 条件 |
|---|---|
Ok | 成功(幂等,地图不存在也返回成功) |
InvalidArg | 参数非法 |
Rejected | 删除激活中的地图被拒绝 |
Timeout | 设备未应答 |
辅助接口
| 接口 | 返回 | 说明 |
|---|---|---|
xg_err_str / toString(Error) | const char* | 静态,勿 free;未知码 "unknown error" |
xg_record_state_str / toString(RecordState) | const char* | 静态 |
xg_sdk_version / sdkVersion | "1.0.0" | C++ 为 std::string 拷贝 |
本版未提供的能力
以下能力本版本不提供,请勿据字段名或经验推测调用:
- 重定位结果 / 阶段 / 分数查询:无接口。是否重定位成功需由集成方观察位姿是否收敛到初值附近并稳定来人工判断(
setLocInitPose返回Ok只表示设备收下先验)。 Pose.isLocal:保留字段,本版恒为 0,不可用于判别有图/无图。- 定位模式切换(建图 / 纯定位):无接口。
- 身份认证:无。设备控制接口对同网段开放,需靠网络隔离保障安全(见 部署与网络)。