Xvisio SDK 深度
Xvisio 功能介绍和快速启动
Xvisio SDK 文档主页

PMD TOF


1. 概述

Xvisio SeerSense™ GR45 系列模组以及Xvisio SeerLens™ One glass Pro会使用到此类型模组,其他产品可以参考对应的数据手册来确认 TOF Camera 类型。PMD 类型 TOF Camera 使用的也是 iTOF 算法 ,波长为940nm 。

2. 特性

2.1 工作模式

Xvisio SDK 提供了三种模式以应对不同的应用场景, 设置了模式后会自动适配对应的频率模式、帧率、曝光时间:

工作模式 频率模式 帧率 曝光时间 描述
短距 单频 30fps 250us 适用在测距距离1米内,需要快速刷新的工作场景,例如手势或人脸识别等
中距 双频 15fps 450us 适用在测距距离2米内,需要快速刷新的工作场景,例如物体扫描和检测等
远距 双频 5fps 1200us 适用在测距距离4米内,刷新率要求不高的工作场景,例如三维重建等

工作模式类型定义:

enum class DistanceMode { Short = 0, Middle, Long };

设置 API 示例:

device->tofCamera()->setDistanceMode(TofCamera::DistanceMode::Short);

2.2 数据流模式

Xvisio SDK 提供一个设置接口用来设置数据流模式,不同的模式对应不同的数据流类型或组合。

数据流模式 描述
DepthOnly 只输出深度数据流
CloudOnly 只输出点云数据流(相机坐标系)
DepthAndCloud 同时输出深度和点云数据流(相机坐标系)
None 无数据流输出
CloudOnLeftHandSlam 只输出点云数据流,但坐标系转换为SLAM坐标系(左手)

定义:

enum class StreamMode { DepthOnly = 0, CloudOnly, DepthAndCloud, None, CloudOnLeftHandSlam};

设置 API 示例:

device->tofCamera()->setStreamMode(TofCamera::StreamMode::DepthAndCloud);
2.3 调制频率

Xvisio SDK 不开放 PMD 类型 TOF Camera 的“调制频率”设置接口,只能通过设置 “工作模式”来选择对应的单双频模式。

2.4 分辨率

Xvisio SDK 不开放 PMD 类型 TOF Camera 的分辨率设置,目前固定为 224 * 172 。

2.5 帧率

可以设置帧率,范围在5-30 fps ,不同的帧率对应的曝光时间请查看表格:

帧率 曝光时间
5fps 2000us
10fps 1080us
15fps 720us
20fps 540us
25fps 440us
30fps 360us

用户根据使用场景和需求选择不同模式和设置。
设置 API 示例:

device->tofCamera()->setFramerate(30.0f);

传参的帧率值为 float 型,范围在 5-30 。

2.6 带宽

PMD 类型 TOF的数据量比较小,这里列出 30fps 下的不同数据类型带宽:

数据 带宽
深度 35.2Mbps
点云 105.8Mbps
IR 17.6Mbps
2.7 IR 数据流使能

PMD 类型的 TOF 可以使能或关闭 IR 数据流输出,默认 IR 数据流不输出。
这个设置使用 hid 命令来设置,IR 使用命令: “0x02,0x10,0xf5,0x02,0x01”,IR 关闭命令: “0x02,0x10,0xf5,0x02,0x00” 。
设置 API 示例:

std::vector<unsigned char> result(63);
bool bOK = device->hidWriteAndRead({0x02,0x10,0xf5,0x02,0x01}, result);
if(bOK)
    std::cout << "Enable IR successfully" << std::endl;
else
    std::cout << "Enable IR failed" << std::endl;

3 深度数据、IR 数据、点云数据

PMD 类型的 TOF 深度数据和点云数据是32位深度数据,单位米,同时也能够支持 IR 灰度数据。

3.1 DepthImage定义
/**
 * @brief An image provided by a TOF camera.
 * @note  There are two manufacturers of TOF camera, Pmd and sony.
 *        Pmd TOF depth type is Depth_32,sony TOF depth type is Depth_16.
 *        Cloud type just use for Pmd point cloud,the coordinate system of the point cloud is the camera coordinate system, and the data unit is meters.
 *        Length, width and depth are in meters use Pmd TOF.
 *        Length, width and depth are in metmillimeterers use sony TOF. 
 */
struct DepthImage {
    enum class Type { Depth_16 = 0, Depth_32, IR, Cloud, Raw, Eeprom, IQ };
    Type type = Type::Depth_32;
    std::size_t width = 0; //!< width of the image (in pixel)
    std::size_t height = 0; //!< height of the image (in pixel)
    double  confidence = 0.0; //!< confidence of depth [0.0,1.0]
    std::shared_ptr<const std::uint8_t> data = nullptr; //! image of depth
    unsigned int dataSize = 0;
    double hostTimestamp = std::numeric_limits<double>::infinity(); //!< host timestamp of the physical measurement (in second based on the `std::chrono::steady_clock`).
    std::int64_t edgeTimestampUs = (std::numeric_limits<std::int64_t>::min)(); //!< timestamp of the physical measurement (in microsecond based on edge clock).
    /**
     * @brief Convert to a #xv::RgbImage
     */
    RgbImage toRgb() const;
};

说明:

  1. “type”值为 “Depth_32” 或 “IR” 或 “Cloud”。
  2. “width” 和 “height” 和 TOF 分辨率对应。
  3. “data” 的类型需要通过"type"来确定:
    当"type"为“Depth_32”时“data”是深度数据单位米,每个像素32位的位宽,"float" 类型;
    当"type"为“Cloud”时“data”是点云数据,单位米,每一个像素由3个 float 类型组成,代表 x , y ,z 轴向的深度数据,单位米;
    当"type"为“IR”时“data”是 IR 数据,代表灰度值,每一个像素16位位宽,实际只有低8位有效,高8位为0。
  4. “data size” 等同于 “width” * “height” * 位宽。其中“Depth_32”类型的位宽是32位,“Cloud”类型的位宽是128位,“IR”类型的位宽是16位。
  5. “confidence” 暂无效,保留。
  6. “hostTimestamp” 经过 SDK 的时间戳同步转换为主机端相同基准的时间戳,单位秒,精度可达到微秒。
  7. “edgeTimestampUs” ,Xvisio 设备端采样时间戳,单位微秒。
  8. “toRgb()” 暂无效,保留。
3.2 获取 DepthImage

使用注册回调方式获取 DepthImage,接口调用流程如下所示:

  1. 注册tofCamera的callback;
  2. 调用start(),启动 TOF streaming;
  3. 触发回调,在回调里做数据处理;
  4. 反注册回调后调用 stop(),停止 TOF Streaming。
    具体code参考demo-api.cpp(case 11),demo-api

4 点云数据转换

Xvisio SDK 提供了 API 可以把深度数据转换为点云数据格式。
第3章里介绍了如果在 DepthImage里直接获取到点云数据,这种方式由 Xvisio 设备在设备端计算好点云上报的。同时也支持本章介绍的通过 API 可以把深度数据转换为点云数据格式。
这两种方式都可以使用,用户可以选择其一。

4.1 PointCloud定义
/**
 * @brief A point cloud of 3D points.
 */
struct PointCloud {
    double hostTimestamp = std::numeric_limits<double>::infinity(); //!< host timestamp of ? (in second based on the `std::chrono::steady_clock`).
    std::int64_t edgeTimestampUs = (std::numeric_limits<std::int64_t>::min)(); //!< timestamp of ? (in microsecond based on edge clock).
    std::vector<Vector3f> points;
};

说明:

  1. “hostTimestamp” 经过 SDK 的时间戳同步转换为主机端相同基准的时间戳,单位秒,精度可达到微秒。
  2. “edgeTimestampUs” ,Xvisio 设备端采样时间戳,单位微秒。
  3. “points”,点云数据,每一个像素有3个 float 类型组成,代表 x , y ,z 轴向的深度数据,单位米。
4.2 转换 PointCloud

转换 PointCloud 必须要先获取 DepthImage,然后再调用接口做转换,流程如下:

  1. 注册tofCamera的callback;
  2. 调用start(),启动 TOF streaming;
  3. 触发回调,在回调里做点云转换处理,使用的 API:
    device->tofCamera()->depthImageToPointCloud(tofDepthImage)
  4. 反注册回调后调用 stop(),停止 TOF Streaming。
    具体code参考demo-api.cpp(case 11),demo-api

5 代码

  • 定义 Xvisio Device
    std::shared_ptr<xv::Device> device = nullptr;

  • 读取 device_list,超时 10 秒(推荐值,也可以缩短)
    auto device_list = xv::getDevices(10., "");

  • 判断获取的 devices 是否为空,为空则失败

    if (device_list.empty())`
    {
            LOG(LOG_Function,"initDevice faiiled:Timeout for device detection.");
            return false;
    }
    
    
  • 获取 device (这里只针对单设备,多设备请参考相应文档描述)
    device = device_list.begin()->second;

  • 注册回调,回调定义里获取深度数据或者 IR 数据 、点云数据

    int tofId = -1;
    tofId = device->tofCamera()->registerCallback([&](xv::DepthImage const & tofDepthImage){
            if (tof.type == xv::DepthImage::Type::Depth_16 ) {
                //Operation on tofDepthImage
                //...
    
                //point cloud process
                if(enableDevMap["tof_point_cloud"])
                {
                    auto points = device->tofCamera()->depthImageToPointCloud(tofDepthImage)->points;
            
                    for (auto iter = points.begin(); iter != points.end();iter++)
                    {
                        auto point = *iter;
                        printf(buff, "x=%f ,y=%f ,z=%f\n", point[0], point[1], point[2]);
                        //...
                    }
            
                }
            }
            else if(tof.type == xv::DepthImage::Type::IR )
            {
                //Operation on tofDepthImage
                //...
            }
             else if(tof.type == xv::DepthImage::Type::Cloud )
            {
                //Operation on tofDepthImage
                //...
            }
        });
    
  • TOF 启动

    //start tof
    device->tofCamera()->start();
    
  • TOF 停止
    此处用到的 tofId 是注册callback时赋值。

    device->tofCamera()->unregisterCallback(tofId);
    device->tofCamera()->stop();
    

6 注意事项

  1. TOF 的功耗需求 ,使能TOF后,因为TOF 相机具有红外投射器会周期性的发射红外波而带来周期性的负载峰值,所以设备的电流峰值对主机的 USB 供电负载能力有一定要求,具体可查看Xvisio 设备和使用注意事项
  2. PMD TOF 和 SONY TOF 深度数据格式的不同,单位不同 :PMD 32位 单位米,SONY 16位 单位毫米。
    Xvisio SDK 深度
    Xvisio 功能介绍和快速启动
    Xvisio SDK 文档主页

PMD TOF

  1. 特性

3 深度数据、IR 数据、点云数据

4 点云数据转换