背景
此文档提供了关于SDK的结构和API函数的详细解释。我们假设你有
- 一个Guidance系统,
- 一台安装了OpenCV的计算机
并且你:
- 熟悉Linux编程,
- 或者熟悉Windows编程和Microsoft Visual Studio使用。
简介
本节介绍指导SDK的结构。该SDK分为三个层次:
- 应用: 该层处理由HAL层传来的数据,由开发者编写。
- HAL: 硬件抽象层。该层打包/解析从驱动层传来的数据,由示例代码实现(串口)SDK库(用于USB)实现,例如libDJI_guidance.so。
- 驱动: 该层通过USB或者串口从Guidance接收数据,由操作系统或第三方库(如_libusb_)实现。
接口
Guidance SDK支持两种通信协议:USB和串口。
1. USB
支持的数据类型包括速度数据,障碍物距离数据,IMU数据,超声波数据,灰度图像和深度图像。
有两种方法可以通过USB订阅数据。
-
Guidance Assist软件
用户可以使用Guidance Assist软件中的“DIY-> API - > USB”选项卡来订阅数据。
- 使用USB线连接Guidance和PC,将Guidance上电
- 选择“启用”复选框
- 根据您的需求选择数据
注: 可用带宽是受制于选择的图像数据和输出频率。订阅图像数据和输出频率的选择将被保存在Guidance系统上,并在Guidance下一次启动时生效。
-
Guidance API
用户可以通过Guidance API订阅数据,这些API函数的名字都以"select"开头。
注: 如果用户通过Guidance API函数来订阅图像数据和输出频率,它只会在Guidance上电期间临时生效,Guidance断电后将恢复到Guidance Assist设置的状态。
2. 串口
串口的输出数据类型包括速度数据,障碍物距离数据,IMU数据和超声波数据。由于带宽限制,图像数据不通过UART输出。
注: Guidance串口目前只支持115200波特率。
-
订阅数据
您只能使用Guidance Assist软件订阅UART数据。从“DIY-> API - > UART”页面启用串口。与USB相同,该配置将被保存在Guidance系统上,除非你在“UART”选项卡中取消选择“启用”选项。
-
协议说明
协议帧格式:
SOF |
LEN |
VER |
RES |
SEQ |
CRC16 |
DATA |
CRC32 |
协议帧解释:
Field |
Byte Index |
Size(bit) |
Description |
SOF |
0 |
8 |
Frame start number, fixed to be 0xAA |
LEN |
1 |
10 |
Frame length, maximum length is 1023 bytes |
VER |
1 |
6 |
Version of the protocol |
RES |
5 |
40 |
Reserved bits, fixed to be 0 |
SEQ |
8 |
16 |
Frame sequence number |
CRC16 |
10 |
16 |
Frame header CRC16 checksum |
DATA |
12 |
--① |
Frame data, maximum length 1007 bytes |
CRC32 |
--② |
32 |
Frame CRC32 checksum |
① 帧数据大小是可变的,最大为1007字节。
② 该域的索引取决于数据域的长度。
数据域格式:
COMMAND SET |
COMMAND ID |
COMMAND DATA |
数据域解释:
Data Field |
Byte Index |
Size(byte) |
Description |
COMMAND SET |
0 |
1 |
Always 0x00 |
COMMAND ID |
1 |
1 |
e_image: 0x00; e_imu: 0x01; e_ultrasonic: 0x02; e_velocity: 0x03; e_obstacle_distance: 0x04 |
COMMAND DATA |
2 |
-- |
Data body |
数据类型
支持的数据类型描述如下。
- 错误码: 列举可能的错误代码。当错误发生时,通常会返回一个错误码,而开发者可以参考此枚举来检查错误类型。
- 速度数据: 机体坐标下的速度。单位是毫米每秒,频率是10 Hz.
- 障碍物距离数据: 从五个Guidance传感器模块读取的障碍物距离数据。单位是厘米,频率是20 Hz.
- IMU数据: IMU数据,包括加速度计(单位为重力加速度g)和陀螺仪(四元数格式)数据。频率为20 Hz.
- 超声波数据: 输出从五个Guidance传感器读取的超声波数据,包括障碍物距离(单位为米)和数据的可靠性。频率为20 Hz.
- 灰度图像: 输出五个方向的8比特灰度图像。每张图像分辨率为320*240. 默认频率为20Hz,可以通过API函数降频。
- 深度图像: 输出五个方向的16比特深度图像。每张图像分辨率为320*240. 默认频率为20Hz,可以通过API函数降频。
- 视差图像: 输出五个方向的16比特视差图像。这个数据在开发者想要进一步优化视差图时是有用的,比如用speckle filter等函数优化。每张图像分辨率为320*240. 默认频率为20Hz,可以通过API函数降频。
数据结构
e_sdk_err_code
描述: 定义SDK的错误代码。
enum e_sdk_err_code { e_timeout = -7, e_libusb_io_err = -1, e_sdk_no_err = 0, e_load_libusb_err=1, e_sdk_not_inited=2, e_hardware_not_ready=3, e_disparity_not_allowed=4, e_image_frequency_not_allowed=5, e_config_not_ready=6, e_online_flag_not_ready=7, e_stereo_cali_not_ready = 8, e_max_sdk_err = 100 };
|
解释:
e_timeout
: USB传输超时。
e_libusb_io_err
: libusb库IO错误。这可能由USB的连接错误引起。
e_OK
: 成功,没有错误。
e_load_libusb_err
: 加载的libusb库错误。这是由于使用了不正确的libusb库。
e_sdk_not_inited
: SDK软件还没有准备好。
e_hardware_not_ready
: Guidance硬件还没有准备好。
e_disparity_not_allowed
: 如果您的Guidance工作在标准模式下,且激活了障碍物感知功能,那么视差图和深度图是不允许被选择的。因为障碍物感知有自己的选择视差图的方法。
e_image_frequency_not_allowed
: 图像频率必须是枚举类型e_image_data_frequecy
之一。目前只支持3种传输频率:5Hz, 10Hz, 20Hz.
e_config_not_ready
: 配置数据没有准备好。Guidance上电时,需要花几秒钟时间(有时更长)来进行初始化,包括加载配置数据到内存,并将数据发送至应用层(即SDK软件)。如果用户在配置数据准备好之前启动了SDK程序,这个错误就会被抛出。配置数据包括:Guidance的工作模式,Guidance传感模块的在线状态,标定参数,等待。
e_online_flag_not_ready
: 在线标志没有准备好。Guidance系统允许用户使用任意数目的传感模块,从1到5. 我们使用一个在线状态数组来标识哪些传感模块是在线的。如果用户从不在线的传感模块订阅了数据,那么不会有数据传输过来。
e_stereo_cali_not_ready
: 摄像头标定参数没有准备好。这个参数对三维应用是有用的。因为图像已经是校正过的图像,我们没有提供畸变系数,只提供了:主点坐标cu, cv
,焦距focal
,和基线长度baseline
.
e_vbus_index
描述: 定义VBUS的逻辑方向,即Guidance传感模块的方向。注意它们只取决于Guidance处理模块上的VBUS接口,而不是Guidance传感模块。
每个枚举值的注释说明了当Guidance以默认方式安装在Matrice 100上时该枚举值代表的方向。但开发者可以任意方式安装Guidance在任意的设备上,因此
enum e_vbus_index { e_vbus1 = 1, e_vbus2 = 2, e_vbus3 = 3, e_vbus4 = 4, e_vbus5 = 0 };
|
e_image_data_frequecy
描述: 定义图像数据的频率。可选的频率有:5Hz, 10Hz, 20Hz. 订阅的图像越多,传输的频率就越低。
enum e_image_data_frequecy { e_frequecy_5 = 0, e_frequecy_10 = 1, e_frequecy_20 = 2 };
|
e_guidance_event
描述: 定义回调的事件类型。
enum e_guidance_event { e_image = 0, e_imu, e_ultrasonic, e_velocity, e_obstacle_distance, e_motion, e_event_num };
|
image_data
描述: 定义图像的数据结构。每个方向的深度图与双目灰度图中的左图对齐。
typedef struct _image_data { unsigned int frame_index; unsigned int time_stamp; char *m_greyscale_image_left[CAMERA_PAIR_NUM]; char *m_greyscale_image_right[CAMERA_PAIR_NUM]; har *m_depth_image[CAMERA_PAIR_NUM]; char *m_disparity_image[CAMERA_PAIR_NUM]; }image_data;
|
解释:
m_greyscale_image_left
和m_greyscale_image_right
都是宽320,高240的8比特灰度图。
m_depth_image
是宽320,高240的16比特深度图,每两个字节描述一个点的深度,低7位为小数位,高9位为整数位。
m_disparity_image
是宽320,高240的16比特视差图,每两个字节描述一个点的深度,低4位为小数位,高12位为整数位。
ultrasonic_data
描述: 定义超声波的数据结构。ultrasonic
是超声波传感器检测到的最近物体的距离,单位是mm
。reliability
是该距离测量的可信度,1为可信,0为不可信。由于观测数据存在噪声,建议对数据进行滤波后再使用。
typedef struct _ultrasonic_data { unsigned int frame_index; unsigned int time_stamp; short ultrasonic[CAMERA_PAIR_NUM]; unsigned short reliability[CAMERA_PAIR_NUM]; }ultrasonic_data;
|
velocity
描述: 定义体坐标系下的速度。单位是mm/s
。
typedef struct _velocity { unsigned int frame_index; unsigned int time_stamp; short vx; short vy; short vz; }velocity;
|
obstacle_distance
描述: 定义由视觉和超声波融合得到的障碍物距离。单位是cm
。
typedef struct _obstacle_distance { unsigned int frame_index; unsigned int time_stamp; unsigned short distance[CAMERA_PAIR_NUM]; }obstacle_distance;
|
imu
描述: 定义IMU数据结构。加速度单位为m/s^2
。
typedef struct _imu { unsigned int frame_index; unsigned int time_stamp; float acc_x; float acc_y; float acc_z; float q[4]; }imu;
|
stereo_cali
描述: 摄像头的标定参数。如果某个方向的传感器不在线,则所有值为0.
typedef struct _stereo_cali { float cu; float cv; float focal; float baseline; _stereo_cali() { } _stereo_cali(float _cu, float _cv, float _focal, float _baseline) { cu = _cu, cv = _cv; focal = _focal, baseline = _baseline; } }stereo_cali;
|
exposure_param
描述: 摄像头的曝光参数。当m_expo_time = m_expected_brightness=0时,变成默认的自动曝光控制。
typedef struct _exposure_param { float m_step; float m_exposure_time; unsigned int m_expected_brightness; unsigned int m_is_auto_exposure; int m_camera_pair_index; _exposure_param(){ m_step = 10; m_exposure_time = 7.68; m_expected_brightness = 85; m_is_auto_exposure = 1; m_camera_pair_index = 1; } }exposure_param;
|
motion
描述: 定义全局位置数据结构。位置单位为m
,速度单位为m/s
.
typedef struct _motion { unsigned int frame_index; unsigned int time_stamp; int corresponding_imu_index; float q0; float q1; float q2; float q3; int attitude_status; float position_in_global_x; float position_in_global_y; float position_in_global_z; int position_status; float velocity_in_global_x; float velocity_in_global_y; float velocity_in_global_z; int velocity_status; float reserve_float[8]; int reserve_int[4]; float uncertainty_location[3]; float uncertainty_velocity[3]; } motion;
|
API
概述
对USB接口,Guidance API提供了配置和控制Guidance的C接口。下面是该API提供的关键方法的概览。
当使用UART传输时请参考第2.1.2节的协议,以及uart_example
示例代码。
-
初始化
-
订阅数据
-
设置回调函数和曝光
-
获取数据
-
传输控制
方法
user_callback
- 描述: 回调函数的原型。 开发者的回调函数必须按照该原型编写。为了达到最佳性能,建议在回调函数中不执行任何耗时的处理,只复制数据。否则,传输频率可能会有所降低。
- 参数:
event_type
使用它来识别数据类型:图像,IMU,超声波,速度或障碍物距离;data_len
输入数据的长度; data
从Guidance输入的数据。
- 返回:
错误码
。如果发生错误为非零。
typedef int (*user_call_back)( int event_type, int data_len, char *data );
|
reset_config
- 描述: 清除订阅的配置,如果你想订阅跟上次不同的数据。
- 参数: 空
- 返回:
错误码
。如果发生错误则非零。
SDK_API int reset_config ( void );
|
init_transfer
- 描述: 初始化Guidance,创建数据传输线程。
- 参数: 空
- 返回:
错误码
。如果发生错误则非零。
SDK_API int init_transfer ( void );
|
select_imu
- 描述: 订阅IMU数据。在标准模式下,必须连接DJI N1飞控才能输出IMU数据。在自定义模式下则不需要连接飞控就可以输出。
- 参数: 空
- 返回: 空
SDK_API void select_imu ( void );
|
select_ultrasonic
SDK_API void select_ultrasonic ( void );
|
select_velocity
- 描述: 订阅速度数据。注意该速度是体坐标系下的速度。
- 参数: 空
- 返回: 空
SDK_API void select_velocity ( void );
|
select_obstacle_distance
- 描述: 订阅障碍物距离数据。
- 参数: 空
- 返回: 空
SDK_API void select_obstacle_distance ( void );
|
set_image_frequecy
- 描述: 设定图像传输的频率。
注意: 由于USB的带宽限制,如果订阅太多的图像(灰度图像或深度图像),应设置较小的频率,否则在SDK不能保证图像传输的连续性。
- 参数:
frequency
图像传输的频率。
- 返回:
错误码
。如果发生错误则非零。
SDK_API int set_image_frequecy ( e_image_data_frequecy frequecy );
|
select_depth_image
- 描述: 订阅深度图像数据。
- 参数:
camera_pair_index
选定双目相机对的索引。
- 返回:
错误码
。如果发生错误则非零。
SDK_API int select_depth_image ( e_vbus_index camera_pair_index );
|
示例:
#include "DJI_guidance.h" #include "DJI_utility.h" #include "opencv2/opencv.hpp" #include <stdio.h> #include <string> e_vbus_index sensor_id = e_vbus1; Mat g_depth; int my_callback(int data_type, int data_len, char *content) { g_lock.enter(); if (e_image == data_type && NULL != content) { image_data* data = (image_data* )content; if ( data->m_depth_image[sensor_id] ){ g_depth = Mat::zeros(HEIGHT,WIDTH,CV_16SC1); memcpy( g_depth.data, data->m_depth_image[sensor_id], IMAGE_SIZE * 2 ); } } g_lock.leave(); g_event.set_event(); return 0; } int main(int argc, const char** argv) { reset_config(); int err_code = init_transfer(); err_code = select_depth_image( sensor_id ); err_code = set_sdk_event_handler( my_callback ); err_code = start_transfer(); while(1) { g_event.wait_event(); if(!g_depth.empty()){ Mat depth8(HEIGHT,WIDTH,CV_8UC1); g_depth.convertTo(depth8, CV_8UC1); imshow(string("depth_")+char('0'+sensor_id), depth8); printf("Depth at point (%d,%d) is %f meters!\n", HEIGHT/2, WIDTH/2, float(g_depth.at<short>( HEIGHT/2,WIDTH/2))/128); } } err_code = stop_transfer(); sleep( 1000000 ); err_code = release_transfer(); }
|
select_disparity_image
- 描述: 订阅视差图像数据。视差图像可以用filterSpeckles等函数进行滤波处理。
- 参数:
camera_pair_index
选定双目相机对的索引。
- 返回:
错误码
。如果发生错误则非零。
SDK_API int select_disparity_image ( e_vbus_index camera_pair_index );
|
示例:
#include "DJI_guidance.h" #include "DJI_utility.h" #include "opencv2/opencv.hpp" #include <stdio.h> #include <string> e_vbus_index sensor_id = e_vbus1; Mat g_disparity; int my_callback(int data_type, int data_len, char *content) { g_lock.enter(); if (e_image == data_type && NULL != content) { image_data* data = (image_data* )content; if ( data->m_disparity_image[sensor_id] ){ g_disparity = Mat::zeros(HEIGHT,WIDTH,CV_16SC1); memcpy( g_disparity.data, data->m_disparity_image[sensor_id], IMAGE_SIZE * 2 ); } } g_lock.leave(); g_event.set_event(); return 0; } int main(int argc, const char** argv) { reset_config(); int err_code = init_transfer(); err_code = select_disparity_image( sensor_id ); err_code = set_sdk_event_handler( my_callback ); err_code = start_transfer(); while(1) { g_event.wait_event(); if(!g_disparity.empty()){ Mat disp8(HEIGHT,WIDTH,CV_8UC1); g_disparity.convertTo(disp8, CV_8UC1); imshow(string("disparity_")+char('0'+sensor_id), disp8); printf("Disparity at point (%d,%d) is %f pixels!\n", HEIGHT/2, WIDTH/2, float(g_disparity.at<short>( HEIGHT/2,WIDTH/2))/16); } } err_code = stop_transfer(); sleep( 1000000 ); err_code = release_transfer(); }
|
select_greyscale_image
- 描述: 订阅纠正灰度图像数据。
- 参数:
camera_pair_index
选择的摄像机对索引; is_left
是否选择左边的图像:为true
时选择左图,为false
时选择右图。
- 返回:
错误码
。如果发生错误则非零。
SDK_API int select_greyscale_image ( e_vbus_index camera_pair_index, bool is_left );
|
select_motion
- 描述: 订阅全局运动信息,即全局坐标系下Guidance的速度和位置。
- 返回:
错误码
。如果发生错误则非零。
SDK_API void select_motion( void );
|
set_sdk_event_handler
- 描述: 设置回调函数指针。当有数据从Guidance传过来时,回调函数将被传输线程调用。
- 参数:
handler
回调函数指针。
- 返回:
错误码
。如果发生错误则非零。
SDK_API int set_sdk_event_handler ( user_call_back handler );
|
start_transfer
- 描述: 通知Guidance开始传输数据。
- 参数: 空。
- 返回:
错误码
。如果发生错误则非零。
SDK_API int start_transfer ( void );
|
stop_transfer
- 描述: 通知Guidance停止数据传输。
- 参数: 空。
- 返回:
错误码
。如果发生错误则非零。
SDK_API int stop_transfer ( void );
|
release_transfer
- 描述: 释放数据传输线程。
- 参数: 空。
- 返回:
错误码
。如果发生错误则非零。
SDK_API int release_transfer ( void );
|
get_online_status
- 描述: 获取Guidance传感模块的在线状态。
- 参数:
online_status[CAMERA_PAIR_NUM]
Guidance传感模块的在线状态的数组。
- 返回:
错误码
。如果发生错误则非零。
SDK_API int get_online_status (int online_status[CAMERA_PAIR_NUM] );
|
get_device_type
- 描述: 获取设备类型。目前只支持Guidance一种设备。
- 参数:
device_type
设备类型。
- 返回:
错误码
。如果发生错误则非零。
SDK_API int get_device_type(e_device_type* device_type);
|
get_image_size
- 描述: 获取图像大小。
- 参数:
width
图像宽度。
- 参数:
height
图像高度。
- 返回:
错误码
。如果发生错误则非零。
SDK_API int get_image_size(int* width, int* height);
|
wait_for_board_ready
- 描述: 等待Guidance处理模块的准备信号。该函数最多会等待20秒,如果20秒内没有收到准备好信号,则返回一个超时错误。开发者一般不需要使用这个函数,因为它已经在init_transfer中被调用。
- 参数: 空。
- 返回:
错误码
。如果发生错误则非零。
SDK_API int wait_for_board_ready();
|
set_exposure_param
- 描述: 设置曝光模式及参数。
- 参数:
param
曝光参数结构体的指针。
- 返回:
错误码
。如果发生错误则非零。
SDK_API int set_exposure_param( exposure_param *param );
|