搞到一款图漾的3d相机(型号为FM810-C)有好久了,一直也只是编译了sample代码跑起来看看样子,并没有着手看SDK以及开发的事。近几日对照SDK以及其中的SimpleView_FetchFrame例子,捋了捋头绪。
先看一下官方文档给出的开发流程:
- 初始化 API。
- 操作设备。
(a) 获取设备列表。
初次获取设备信息时可以通过 TYGetDeviceList() 查询已连接的设备。在已知设备 ID 的情况下,
可以不调用该函数查询。
(b) 打开设备。
对于 USB 设备可以通过 TYOpenDevice() 打开设备;对于网络设备可以通过 TYOpenDevice-
WithIP() 打开设备。- 操作组件。
(a) 查询组件状态。
使用 TYGetComponentIDs() 可查询所有组件状态;使用 TYGetEnabledComponents() 查询使能
状态的组件。
(b) 配置组件。
每个设备打开后都必须配置组件,
默认情况下只有虚拟组件 TY_COMPONENT_DEVICE
是使能状态。多个设备可以通过位或方式同时使能。代码示例如下:
cd source
int32_t componentIDs = TY_COMPONENT_DEPTH_CAM | TY_COMPONENT_RGB_CAM ;
TYEnableComponents ( hDevice , componentIDs ) ;
- 操作参数。
(a) 查询指定参数的信息。通过填充结构体 TY_FEATURE_INFO 来获取指定组件的指定参数的信息。
如果该组件不包含所指定的参数,则 TY_FEATURE_INFO 中 isValid 值为 false。
(b) 配置参数。
配置参数的 API 按照参数的数据类型分类,如 TYGetIntRange,和 TYSetFloat 等。- 给驱动程序分配 framebuffer。
(a) 查询当前配置下每个 framebuffer 的大小。
(b) 分配 framebuffer 并压入驱动内的缓冲队列。
驱动内部维护一个缓冲队列(buffer queue),每帧数据传出时会将填充好的 buffer 作 dequeue
操作,并完全传出给用户使用。用户需要保证新的一帧数据到来时驱动的缓冲队列 buffer queue
不为空,否则该帧数据将被丢弃。- 注册回调函数(主动获取模式下不调用)。
- 启动采集。
- 主动获取帧数据(主动获取模式下不调用)。
- 停止采集。
- 关闭设备。
- 释放 API。
看起来流程还算清晰,但是只有这个感觉还是一头雾水。于是对应sample中的SimpleView_FetchFrame源码,慢慢的理了理头绪。先贴一个最最最简单核心的骨架流程:
1、初始化设备 TYInitLib();
2、打开设备 TYOpenDevice();
3、使能组件 TYEnableComponents();
4、将帧缓存压入队列 TYEnqueueBuffer();
5、开始拍摄 TYStartCapture();
6、获取帧数据 TYFetchFrame();
7、解析帧数据 parseFrame();
8、显示图像 cv::imshow();
9、停止拍摄 TYStopCapture();
10、关闭设备 TYCloseDevice();
11、注销API TYDeinitLib();
流程看起来跟SDK上说的没有什么差别啊,是的,并没有太多的差别,但是后面贴的代码是核心流程中最最最简化的核心流程,用于抽出框架,其他的功能在此框架上添加(比如SimpleView_FetchFrame例子中的一些信息状态输出,运行状态检测,等等)。
贴上对应的代码:
#include "../common/Utils.hpp"
int main(int argc, char* argv[])
{
//初始化
TYInitLib();
// 打开设备
// 用设备ID打开设备,同时构建此设备的设备管理器。
TY_DEV_HANDLE hDevice;
TYOpenDevice("207000000866", &hDevice);
// 使能组件
// 按位或上组件结构体中的值,即可打开设备。
TYEnableComponents(hDevice, TY_COMPONENT_RGB_CAM | TY_COMPONENT_DEPTH_CAM | TY_COMPONENT_IR_CAM_LEFT | TY_COMPONENT_IR_CAM_RIGHT);
// 取得帧缓存大小。
// 说一下这一步的目的,由于打开不同组件(打开哪些组件),以及不同组件参数设定(分辨率)的原因,每一帧数据的大小是不固定的,
// 所以要用此函数计算一下当前设备以及当前设定下,一帧数据出来,需要多大的缓存buffer。
// 因为后面需要压入buffer队列进行数据读取,所以要保证buffer的大小能否装下一帧数据。
int32_t frameSize;
TYGetFrameBufferSize(hDevice, &frameSize);
// 驱动内部维护一个queue,用户往队列中enqueue空的buffer,
// 设备用每一帧的framedata去填充这个空的buffer,填充后,将此buffer弹出队列(dequeue),返回给用户使用。
// 这几个buffer是循环使用的,弹出被用户取出数据后,又会回到队列尾部。理论上将,只需要两个buffer即可循环使用。
int frameBuffer_number = 3;
char* frameBuffer[frameBuffer_number];
for (int i = 0; i < frameBuffer_number; ++i)
{
frameBuffer[i] = new