目录
2、介绍(Guidance SDK reference)... 8
Guidance SDK综述
概述:通过授予对Guidance的完全控制权,Guidance SDK使您能够轻松地开发各种基于视觉的应用程序,您可以轻松地从所有主流系统的指南中访问所有输出数据。
支持平台:Windows、Linux、Embeded systems
特征:
1、机身状态:输出机身的三维速度与位置(世界坐标系?)、输出到最近障碍物的距离(图像和超声波数据)
2、传感器数据:输出机身IMU数据(三轴加速度计和陀螺仪(机体坐标系))、输出到最近障碍物的距离
3、图像:输出固定分辨率为3x240的8或16位灰度图像、
4、相机配置:有权获取双目相机标定参数、有权访问和修改相机曝光模式和参数
硬件接口:
- USB:以高数据速率传输所有数据并精确控制相机参数
- UART:传输除图像以外的所有数据,适用于所有具有串行通信的系统
Guidance SDK文件(document)
1.1启动
官方Guidance SDK包,用于通过USB和UART访问指南的丰富类别的输出数据,并根据需要配置Guidance。
1.1.1文件
A、开发者指南
B、运行例程
C、建立视觉跟踪项目
D、Guidance SDK参考
1.1.2结构
A、demo:使用Guidance SDK的演示应用程序
B、doc:文件
C、examples:USB和UART的例程
D、include:Guidance SDK的头文件
E、lib:Windows的库文件
2010/X64:使用Visual Studio 2010 64位生成
2010/X86:使用Visual Studio 2010 32位生成
2013/X64:使用Visual Studio 2013 64位生成
2013/X86:使用Visual Studio 2013 32位生成
F、so:Linux的库文件
X64:用g++在64位Linux系统上构建
X86:用g++在32位Linux系统上构建
XU3:用g++在XU3系统上构建
arm:在嵌入式ARM系统上,用最新的arm-linux-gnueabi-g++构建,通过下面语句安装交叉编译工具链:sudo apt-get install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
还要注意,为了使ROS用户能够快速下载,我们有一个单独的ROS报告,其规模要小得多:Guidance-SDK-ROS.
1.1.3用法
A、Windows
USB和UART的例子在examples/usb_example、examples/uart_example,包括待编译的Makefile文件。请记住将相应的DjiGuang.dLL文件复制到输出二进制位置所在的相同目录。
B、Linux
USB和UART的例子在examples/usb_example、examples/uart_example,包括待编译的Makefile文件。请记住将相应的DjiGuang.dLL文件复制到输出二进制位置所在的相同目录。
请注意,Linux中读写USB端口需要root权限,为了解决每次运行SDK应用程序时键入sudo的麻烦,建议将一个规则添加到/etc/udev/rules.d目录中,这可以在doc/51-guidance.rules中找到。或从终端输入以下行:
sudo sh -c 'echo "SUBSYSTEM==\"usb\", ATTR{idVendor}==\"fff0\", ATTR{idProduct}==\"d009\", MODE=\"0666\"" > /etc/udev/rules.d/51-guidance.rules'
1.2 运行例程
Guidance SDK提供了从Guidance系统获得数据的例子。本节将指导您如何执行这些示例。我们使用OpenCV来查看从Guidance传输的图像,因此建议在系统上安装OpenCV。但是,如果没有OpenCV,也可以获得除图像以外的所有数据。
我们提供Linux和Windows系统的CMAKLIST.TXT,它自动检测是否安装了OpenCV。
1.2.1用CMake编译USB实例
注:CMake是必需的。在Windows上,也需要VisualStudio(2010或2013)。
A、cd Guidance-SDK\examples\usb_example\DJI_guidance_example
B、mkdir build
C、cd build
D、cmake ..
E、build:
a、Linux系统:make
b、Windows系统:您将看到生成一个解决方案文件。打开它并建立项目dji_guidance_usb
1.2.2 Linux系统下运行USB例程
A、设置环境
Guidance SDK使用libusb-1.0.9库从Guidance系统读取数据。请参考 http://www.libusb.org/编译并安装源代码的LUBSB-1.0.9库。
B、复制相关文件
提供Makefile且已测试过。 用户无需更改任何内容即可运行示例代码。要在自己的项目中使用Guidance,用户可以按照以下说明操作:
- 复制libDJI_guidance.so到自己项目的库文件路径
- 复制DJI_guidance.h到头文件路径
- 在项目的Makefile中添加库,如下所示:
LDFLAGS = -Wl,-rpath,./ -lpthread -lrt -L./ -L/usr/local/lib/ -l **DJI\_guidance** -lusb-1.0
C、编译例程
进入项目目录并输入:Make -f Makefile_noOpenCV
注意:这里我们假设您没有安装OpenCV并使用Makefile_noOpenCV。 您可以根据自己的情况在make期间指定makefile。 例如,如果安装了OpenCV,请使用其他makefile:make –f Makefile
D、通过USB连接Guidance并运行
如果尚未按照开发人员指南中的说明将51-guidance.rules文件添加到/etc/udev/rules.d/目录,则需要root权限才能运行此示例。
sudo ./guidance_example
运行结果如下所示:
1.2.3 Windows下运行USB例程
A、配置环境
Guidance SDK使用libusb库从Guidance系统读取数据。 请确保正确安装Guidance Assistant软件,其中包括用于指导的DJI USB驱动程序。
B、安装Visual studio
提供并测试了不同版本的Visual Studio的解决方案。 用户无需更改任何内容即可运行示例代码。
要在自己的项目中使用Guidance,建议使用examples \ usb_example文件夹中提供的属性表文件。 用户只需要更改属性表文件中的头文件和库文件的目录。
或者,用户可以直接复制文件并按如下方式配置Visual Studio:
- 复制DJI_guidance.dll 、DJI_guidance.lib到自己项目的库文件路径
- 复制DJI_guidance.h到头文件路径
- 将DJI_guidance.lib添加到Visual Studio项目的其他依赖项中
C、编译
使用Microsoft Visual Studio编译示例项目。
如果安装了OpenCV,还可以通过在源文件main.cpp中或在Visual Studio的预处理设置中定义HAVE_OPENCV来将Visual Studio配置为使用OpenCV。
D、连接Guidance系统并进行测试
结果如下所示
1.2.4 Linux下运行UART例程
A、订阅UART数据
参考2.1.2**UART
B、编译
进入uart_example目录并make:
C、连接Guidance系统并进行测试
1.2.5 Windows下运行UART例程
A、订阅UART数据
参考2.1.2**UART
B、编译
使用VS编译
- 连接Guidance系统并测试
2、介绍(Guidance SDK reference)
2.1 背景
此文档提供了关于SDK的结构和API函数的详细解释。我们假设你有:
1、一个Guidance系统,
2、一台安装了OpenCV的计算机
并且你:
1、熟悉Linux编程,
2、或者熟悉Windows编程和Microsoft Visual Studio使用。
2.2 简介
本节介绍指导SDK的结构。该SDK分为三个层次:
应用: 该层处理由HAL层传来的数据,由开发者编写。
HAL: 硬件抽象层。该层打包/解析从驱动层传来的数据,由示例代码实现(串口)SDK库(用于USB)实现,例如libDJI_guidance.so。
驱动: 该层通过USB或者串口从Guidance接收数据,由操作系统或第三方库(如_libusb_)实现。
接口:
Guidance SDK支持两种通信协议:USB和串口。
1. USB
支持的数据类型包括速度数据,障碍物距离数据,IMU数据,超声波数据,灰度图像和深度图像。有两种方法可以通过USB订阅数据。
I、Guidance Assist软件
用户可以使用Guidance Assist软件中的“DIY-> API - > USB”选项卡来订阅数据。
A、使用USB线连接Guidance和PC,将Guidance上电
B、选择“启用”复选框
C、根据您的需求选择数据
注: 可用带宽是受制于选择的图像数据和输出频率。订阅图像数据和输出频率的选择将被保存在Guidance系统上,并在Guidance下一次启动时生效。
II、Guidance API
用户可以通过Guidance API订阅数据,这些API函数的名字都以"select"开头。
注: 如果用户通过Guidance API函数来订阅图像数据和输出频率,它只会在Guidance上电期间临时生效,Guidance断电后将恢复到Guidance Assist设置的状态。
2、串口
串口的输出数据类型包括速度数据,障碍物距离数据,IMU数据和超声波数据。由于带宽限制,图像数据不通过UART输出。
注: Guidance串口目前只支持115200波特率。
A、订阅数据
您只能使用Guidance Assist软件订阅UART数据。从“DIY-> API - > UART”页面启用串口。与USB相同,该配置将被保存在Guidance系统上,除非你在“UART”选项卡中取消选择“启用”选项。
B、协议说明
协议帧格式:
SOF LEN VER RES SEQ CRC16 DATA CRC32
协议帧解释:
|
名称 |
字节索引 |
大小(位) |
说明 |
|
SOF |
0 |
8 |
帧起始编号,固定为0xAA |
|
LEN |
1 |
10 |
帧长,最大长度为1023字节 |
|
VER |
1 |
6 |
协议版本 |
|
RES |
5 |
40 |
保留位,固定为0 |
|
SEQ |
8 |
16 |
帧*** |
|
CRC16 |
10 |
16 |
帧头CRC16校验和 |
|
DATA |
12 |
注释1 |
帧数据,最大长度为1007字节 |
|
CRC32 |
注释2 |
32 |
帧CRC32校验和 |
注释1:帧数据大小是可变的,最大为1007字节。
注释2:该域的索引取决于数据域的长度。
数据域格式:
COMMAND SET COMMAND ID COMMAND DATA
|
数据域 |
字节索引 |
大小(位) |
说明 |
|
COMMAND SET |
0 |
1 |
恒为0X00 |
|
COMMAND ID |
1 |
1 |
e_image: 0x00;;e_imu: 0x01; e_ultrasonic:0x02;e_velocity:0x03; e_obstacle_distance::0x04 |
|
COMMAND DATA |
2 |
-- |
数据体 |
数据类型:
支持的数据类型描述如下。
错误码: 列举可能的错误代码。当错误发生时,通常会返回一个错误码,而开发者可以参考此枚举来检查错误类型。
速度数据: 机体坐标下的速度。单位是毫米每秒,频率是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函数降频。
2.3 数据结构
I、e_sdk_err_code
描述: 定义SDK的错误代码。
enum e_sdk_err_code
{
e_timeout = -7, // USB传输超时
e_libusb_io_err = -1, // libusb库IO错误
e_sdk_no_err = 0, // 成功,没有错误
e_load_libusb_err=1, // 加载的libusb库错误
e_sdk_not_inited=2, // SDK软件还没有准备好
e_hardware_not_ready=3, // Guidance硬件还没有准备好
e_disparity_not_allowed=4, // 视差图或深度图不允许被选择
e_image_frequency_not_allowed=5, // 图像频率必须是枚举类型e_image_data_frequecy之一
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.
II、e_vbus_index
描述: 定义VBUS的逻辑方向,即Guidance传感模块的方向。注意它们只取决于Guidance处理模块上的VBUS接口,而不是Guidance传感模块。
每个枚举值的注释说明了当Guidance以默认方式安装在Matrice 100上时该枚举值代表的方向。但开发者可以任意方式安装Guidance在任意的设备上,因此
enum e_vbus_index
{
e_vbus1 = 1, // M100上为前视
e_vbus2 = 2, // M100上为右视
e_vbus3 = 3, // M100上为后视
e_vbus4 = 4, // M100上为左视
e_vbus5 = 0 // M100上为下视
};
III、e_image_data_frequecy
描述: 定义图像数据的频率。可选的频率有:5Hz, 10Hz, 20Hz. 订阅的图像越多,传输的频率就越低
enum e_image_data_frequecy
{
e_frequecy_5 = 0, // frequecy of image data: 5Hz
e_frequecy_10 = 1, // frequecy of image data: 10Hz
e_frequecy_20 = 2 // frequecy of image data: 20Hz
};
IV、e_guidance_event
描述: 定义回调的事件类型。
enum e_guidance_event
{
e_image = 0, // called back when image comes
e_imu, // called back when imu comes
e_ultrasonic, // called back when ultrasonic comes
e_velocity, // called back when velocity data comes
e_obstacle_distance, // called back when obstacle data comes
e_motion, // called back when global position comes
e_event_num
};
V、image_data
描述: 定义图像的数据结构。每个方向的深度图与双目灰度图中的左图对齐。
typedef struct _image_data
{
unsigned int frame_index; // frame index
unsigned int time_stamp; // time stamp of image captured in ms
char *m_greyscale_image_left[CAMERA_PAIR_NUM];// greyscale image of left camera
char *m_greyscale_image_right[CAMERA_PAIR_NUM]; // greyscale image of right camera
char *m_depth_image[CAMERA_PAIR_NUM]; // depth image in *128 meters
char *m_disparity_image[CAMERA_PAIR_NUM]; // disparity image in *16 pixels
}image_data;
解释:
1、m_greyscale_image_left和m_greyscale_image_right都是宽320,高240的8比特灰度图。
2、m_depth_image是宽320,高240的16比特深度图,每两个字节描述一个点的深度,低7位为小数位,高9位为整数位。
3、m_disparity_image是宽320,高240的16比特视差图,每两个字节描述一个点的深度,低4位为小数位,高12位为整数位。
VI、ultrasonic_data
描述: 定义超声波的数据结构。ultrasonic是超声波传感器检测到的最近物体的距离,单位是mm。reliability是该距离测量的可信度,1为可信,0为不可信。由于观测数据存在噪声,建议对数据进行滤波后再使用。
typedef struct _ultrasonic_data
{
unsigned int frame_index; // corresponse frame index
unsigned int time_stamp; // time stamp of corresponse image captured in ms
short ultrasonic[CAMERA_PAIR_NUM]; // distance in mm. -1 means invalid measurement.
unsigned short reliability[CAMERA_PAIR_NUM]; // reliability of the distance data
}ultrasonic_data;
VII、velocity
描述: 定义体坐标系下的速度。单位是mm/s。
typedef struct _velocity
{
unsigned int frame_index; // corresponse frame index
unsigned int time_stamp; // time stamp of corresponse image captured in ms
short vx; // velocity of x in mm/s
short vy; // velocity of y in mm/s
short vz; // velocity of z in mm/s
}velocity;
VIII、obstacle_distance
描述: 定义由视觉和超声波融合得到的障碍物距离。单位是cm。
typedef struct _obstacle_distance
{
unsigned int frame_index; // corresponse frame index
unsigned int time_stamp; // time stamp of corresponse image captured in ms
unsigned short distance[CAMERA_PAIR_NUM]; // distance of obstacle in cm
}obstacle_distance;
IX、imu
描述: 定义IMU数据结构。加速度单位为m/s^2
typedef struct _imu
{
unsigned int frame_index; //相应的帧索引
unsigned int time_stamp; //以ms为单位捕获的对应图像的时间戳
float acc_x; // acceleration of x in unit of m/s^2
float acc_y; // acceleration of y in unit of m/s^2
float acc_z; // acceleration of z in unit of m/s^2
float q[4]; // quaternion: [w,x,y,z]
}imu;
X、stereo_cali
描述: 摄像头的标定参数。如果某个方向的传感器不在线,则所有值为0.
typedef struct _stereo_cali
{
float cu; // 焦点中心的x位置,以像素为单位
float cv; // 焦点中心的y位置,以像素为单位
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;
XI、exposure_param
描述: 摄像头的曝光参数。当m_expo_time = m_expected_brightness=0时,变成默认的自动曝光控制
typedef struct _exposure_param
{
float m_step; // 自动曝光控制(AEC)的调整步骤。 默认值为10。
float m_exposure_time;// 持续曝光时间以微秒为单位。 范围是0.1~20。 默认值为7.25。
unsigned int m_expected_brightness; // AEC的恒定预期亮度。 范围是50~200。 默认值为85。
unsigned int m_is_auto_exposure; // 1:自动曝光; 0:持续曝光
int m_camera_pair_index; // index of Guidance Sensor
_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;
XII、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; // 0:invalid; 1:valid
float position_in_global_x; // position in global frame: x
float position_in_global_y; // position in global frame: y
float position_in_global_z; // position in global frame: z
int position_status; // lower 3 bits are confidence. 0:invalid; 1:valid
float velocity_in_global_x; // velocity in global frame: x
float velocity_in_global_y; // velocity in global frame: y
float velocity_in_global_z; // velocity in global frame: z
int velocity_status; // lower 3 bits are confidence. 0:invalid; 1:valid
float reserve_float[8];
int reserve_int[4];
float uncertainty_location[3];// uncertainty of position
float uncertainty_velocity[3];// uncertainty of velocity
} motion;
2.4 API
2.4.1 概述
对USB接口,Guidance API提供了配置和控制Guidance的C接口。下面是该API提供的关键方法的概览。
当使用UART传输时请参考第2.1.2节的协议,以及uart_example示例代码。
I、初始化
reset_config
init_transfer
II、订阅数据
select_imu
select_ultrasonic
select_velocity
select_obstacle_distance
set_image_frequecy
select_depth_image
select_disparity_image
select_greyscale_image
select_motion
III、设置回调函数和曝光
set_sdk_event_handler
set_exposure_param
IV、获取数据
get_online_status
get_stereo_cali
get_device_type
get_image_size
V、传输控制
start_transfer
stop_transfer
release_transfer
wait_for_board_ready
2.4.2 方法
I、user_callback
描述: 回调函数的原型。 开发者的回调函数必须按照该原型编写。为了达到最佳性能,建议在回调函数中不执行任何耗时的处理,只复制数据。否则,传输频率可能会有所降低。
参数: event_type使用它来识别数据类型:图像,IMU,超声波,速度或障碍物距离;data_len输入数据的长度; data从Guidance输入的数据。
返回: 错误码。如果发生错误为非零。
typedef int (*user_call_back)( int event_type, int data_len, char *data );
II、reset_config
描述: 清除订阅的配置,如果你想订阅跟上次不同的数据。
参数: 空
返回: 错误码。如果发生错误则非零。
SDK_API int reset_config ( void );
III、init_transfer
描述: 初始化Guidance,创建数据传输线程。
参数: 空
返回: 错误码。如果发生错误则非零。
SDK_API int init_transfer ( void );
IV、select_imu
描述: 订阅IMU数据。在标准模式下,必须连接DJI N1飞控才能输出IMU数据。在自定义模式下则不需要连接飞控就可以输出。
参数: 空
返回: 空
SDK_API void select_imu ( void );
V、select_ultrasonic
描述: 订阅超声波数据。
参数: 空
返回: 空
SDK_API void select_ultrasonic ( void );
VI、select_velocity
描述: 订阅速度数据。注意该速度是体坐标系下的速度。
参数: 空
返回: 空
SDK_API void select_velocity ( void );
VII、select_obstacle_distance
描述: 订阅障碍物距离数据。
参数: 空
返回: 空
SDK_API void select_obstacle_distance ( void );
VIII、set_image_frequecy
描述: 设定图像传输的频率。 注意: 由于USB的带宽限制,如果订阅太多的图像(灰度图像或深度图像),应设置较小的频率,否则在SDK不能保证图像传输的连续性。
参数: frequency 图像传输的频率。
返回: 错误码。如果发生错误则非零。
SDK_API int set_image_frequecy ( e_image_data_frequecy frequecy );
IX、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(); // clear all data subscription
int err_code = init_transfer(); //wait for board ready and init transfer thread
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();
//make sure the ack packet from GUIDANCE is received
sleep( 1000000 );
err_code = release_transfer();
}
X、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(); // clear all data subscription
int err_code = init_transfer(); //wait for board ready and init transfer thread
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();
//make sure the ack packet from GUIDANCE is received
sleep( 1000000 );
err_code = release_transfer();
}
XI、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 );
XII、select_motion
描述: 订阅全局运动信息,即全局坐标系下Guidance的速度和位置。
返回: 错误码。如果发生错误则非零。
SDK_API void select_motion( void );
XIII、set_sdk_event_handler
描述: 设置回调函数指针。当有数据从Guidance传过来时,回调函数将被传输线程调用。
参数: handler 回调函数指针。
返回: 错误码。如果发生错误则非零。
SDK_API int set_sdk_event_handler ( user_call_back handler );
XIV、start_transfer
描述: 通知Guidance开始传输数据。
参数: 空。
返回: 错误码。如果发生错误则非零。
SDK_API int start_transfer ( void );
XV、stop_transfer
描述: 通知Guidance停止数据传输。
参数: 空。
返回: 错误码。如果发生错误则非零。
SDK_API int stop_transfer ( void );
XVI、release_transfer
描述: 释放数据传输线程。
参数: 空。
返回: 错误码。如果发生错误则非零。
SDK_API int release_transfer ( void );
XVII、get_online_status
描述: 获取Guidance传感模块的在线状态。
参数: online_status[CAMERA_PAIR_NUM] Guidance传感模块的在线状态的数组。
返回: 错误码。如果发生错误则非零。
XVIII、get_device_type
描述: 获取设备类型。目前只支持Guidance一种设备。
参数: device_type 设备类型。
返回: 错误码。如果发生错误则非零。
SDK_API int get_device_type(e_device_type* device_type);
XIX、get_image_size
描述: 获取图像大小。
参数: width 图像宽度。
参数: height 图像高度。
返回: 错误码。如果发生错误则非零。
SDK_API int get_image_size(int* width, int* height);
XX、wait_for_board_ready
描述: 等待Guidance处理模块的准备信号。该函数最多会等待20秒,如果20秒内没有收到准备好信号,则返回一个超时错误。开发者一般不需要使用这个函数,因为它已经在init_transfer中被调用。
参数: 空。
返回: 错误码。如果发生错误则非零。
SDK_API int wait_for_board_ready();
XXI、set_exposure_param
描述: 设置曝光模式及参数。
参数: param 曝光参数结构体的指针。
返回: 错误码。如果发生错误则非零。
SDK_API int set_exposure_param( exposure_param *param );
3、Guidance SDK开发者指南
3.1 SDK包下载
Guidance SDK软件包在GitHub上更新和维护。
Guidance-SDK:完整包。包括头文件、所有平台的库文件、所有文档。
Guidance-SDK-ROS:ROS包。包括头文件、Ubuntu及Odroid XU3的库文件。
3.2 环境配置
3.2.1 Windows
I、安装Guidance Assistant软件
首先,在Windows平台下安装Guidance Assistant软件。软件在安装过程中会自动安装Guidance所需的USB驱动,在软件安装引导结束后需重启系统使之生效。系统重新启动后,将Guidance通过USB连至电脑并上电,进入计算机管理-设备管理器中查看,如果在设备列表中出现“DJI, Inc. - Guidance”,意味着软件安装成功。
II、安装UART驱动
如果要通过UART使用Guidance SDK,需要安装USB转RS232的驱动。使用过程中请注意,Guidance SDK中examples默认读取的串口号为COM5。如果您的计算机上的串口号与之不同,请修改代码中的设置或更改设备串口号。
III、通过Guidance Assistant软件**并订阅数据
假设用户已经在Windows上正确安装了Guidance Assistant软件。
A、首先,将Guidance连接至电脑并上电启动;接着等待Guidance上的绿灯开始闪烁后,打开Guidance Assistant软件,可以看到软件查看页面的左下角绿灯亮起,说明连接正常;此时将工作模式设置为自定义模式。
B、然后转到“自定义”页面,在“接口参数”选项卡中根据需要**USB与UART,并通过勾选相应的选项来订阅图像数据及图像输出频率;图像数据及频率设置也可通过Guidance SDK中相应的API进行设置。
C、关闭Guidance Assistant软件并重启Guidance使配置生效。
IV、推荐使用Visual Studio
Guidance SDK中提供了Demo与examples供参考使用,其中包含了Visual Studio 2010的完整配置文件与Visual studio 2013的部分配置文件。分别是Windows7系统下测试通过的32位与64位、debug与release相关的opencv与SDK配置文件,形如use_Guidance_*.prop,use_opencv_*.prop,用户可以根据需要将它们复制并添加到自己的工程中,省去配置的麻烦。
V、安装OpenCV
Guidance SDK分别在Opencv2.4.8、OpenCV2.4.9及OpenCV2.4.11上进行了测试,Demo及examples中的例程默认使用的是OpenCV2.4.11版本。用户可以从OpenCV官方网站 http://opencv.org/上下载合适版本的OpenCV并安装到电脑上。使用时请注意,在Demo及examples的配置文件中,由于使用了 OPENCVROOT 的环境变量,因此用户在配置OpenCV环境的过程中需要新建一个名为OPENCVROOT 的系统环境变量,其值为OpenCV的安装目录。
假设用户已经成功在电脑上安装了OpenCV2.4.11
A、安装目录为D:/OPENCV/opencv2411/build[sources],如下图所示,进入高级系统设置-环境变量-系统变量,新建一个变量,变量名为OPENCVROOT,值为 D:\OPENCV\opencv2411\
B、接着在系统变量的PATH变量尾部添加OpenCV的库目录,注意不同目录间用分号隔开:
D:/OPENCV/opencv2411/build/x64/vc10/bin; D:/OPENCV/opencv2411/build/x86/vc10/bin;
C、如果用户使用Visual Studio作为开发环境,接下来就只需将相应的 use_Guidance_*.prop 与 use_opencv_*.prop 配置文件添加到工程中去即可;或者也可直接复制例程,在例程的基础上进行开发。
VI、正确放置DJI_guidance.dll
务必记得将DJI_guidance.dll拷贝至exe所在的目录,否则会显示无法找到DJI_guidance.dll的错误。
3.2.2 Linux
I、安装libusb驱动
从http://www.libusb.org/下载并解压libusb-1.0.9.tar.bz2,并按照指导正确安装libusb驱动;不推荐通过apt-get install 安装libusb驱动;
例如: 解压libusb-1.0.9.tar.bz2并利用cd命令跳转到解压目录下;接着运行以下指令:
>> ./configure
>> make
>> make install
II、安装UART驱动
Linux默认包含了UART驱动,不需要另外安装。
III、通过Guidance Assistant软件**并订阅数据
参考上一篇通过Guidance Assistant软件**并订阅数据。
IV、将g++更新到最新版本
请确保使用的是最新版本的g++;如果更新后仍提示无法找到g++指令,请检查系统时间是否与真实世界不同步! 例如:
>> sudo apt-get install g++
V、安装OpenCV
用户可以直接通过apt-get install来安装OpenCV:
>> sudo apt-get install libopencv-dev
或者,用户可以上GitHub下载Install-OpenCV-master压缩包并解压到本地,这是由jayrambhia提供的一个Linux下各OpenCV版本的安装脚本,利用这个脚本用户可以非常方便地将OpenCV安装到Linux; 例如:
>> cd PATH/TO/Install-OpenCV-master/Ubuntu
>> ./dependencies.sh
>> cd 2.4
>> ./opencv2_4_9.sh
VI、正确放置DJI_guidance.so
将相应的Guidance共享库libDJI_guidance.so拷贝至 /usr/local/lib . 例如:
>> sudo cp libDJI_guidance.so /usr/local/lib
VII、通过sudo指令运行程序
使用Guidance的USB接口时,需要使用sudo指令,以取得对USB接口的root权限。否则会出现permission denied的错误。 例如:
>> sudo ./guidance_example
为了避免每次都要使用sudo来运行Guidance SDK程序的麻烦,可以在/etc/udev/rules.d/文件夹中创建一个规则文件51-guidance.rules,内容如下:
SUBSYSTEM=="usb", ATTR{idVendor}=="fff0", ATTR{idProduct}=="d009", MODE="0666"
然后再拨插USB线,就可以以普通用户的权限来运行Guidance SDK程序了。
3.3 常见错误
参考开发者指南给出的方法进行开发环境的搭建,能够避免大部分的错误。
3.3.1 连接错误
问题描述:
“usb error” 或者类似的报错,例如:
解决方法:
- 首先确定Guidance已经连接到电脑上,并且Guidance上的绿灯开始进入闪烁状态;
- 检查USB驱动是否正确安装,Windows下的检查方法连接上Guidance后进入设备管理器中查看;或者使用DJIGuidance软件进行查看,如果**“查看”**页面左下角的绿灯亮起,说明USB驱动已经正确安装;否则请参考开发者指南安装Guidance Assistant软件;Linux下用户需严格遵循开发者指南中给出的安装方法进行安装,通过Guidance SDK中相关的USB例程进行测试;
- 如果在Windows下使用UART获取数据,请检查串口号是否为COM5;否则请在查看串口端号后,在examples中进行相应更改;
- 成功连接上Guidance Assistant软件后,进入自定义界面的接口参数选项卡,查看是否已经**USB或UART选项;如果没有**,请勾选相应的选项并关闭软件与Guidance,Guidance重启后配置生效;
- 如果数据传输非正常退出,也就是线程在运行到 stop_transfer() 与 release_transfer() 之前就退出,也会导致此类错误,这种情况下需要重启Guidance;
- 在Linux下请务必使用sudo命令启动程序;
- 请确认在Guidance上的绿灯开始闪烁后运行程序;
- 请确认在使用SDK时已关闭“Guidance Assistant”软件;
- 在虚拟机上运行可能会导致问题;
3.3.2 编译错误
I、共享库加载错误
错误描述:
Error while loading shared libraries : libDJI_guidance.so: cannot open shared object file : No such file or directory.
解决方法:
- 请确认将系统所对应的DJI_guidance.so复制到了 /usr/local/lib 目录下;若仍存在这种错误,请将其再拷贝一份至out程序运行目录下;
- 请确认该so文件与你电脑的系统版本是对应的;
II、无法打开DJI_guidance.dll文件
错误描述:
Cannot open DJI_guidance.dll file:No such file or directory.
解决方法:
请确认将系统所对应的DJI_guidance.dll分别复制到了lib文件夹与*.exe程序运行目录下;以及其版本是否与可执行程序一致。
III、OpenCV相关错误
错误描述:
无法打开与OpenCV有关的***.h**与 *.dll 等文件;
解决办法:
请确认OpenCV是否正确安装,且版本与程序要求的一致;另外,若运行Guidance SDK中给出的Demo与examples,记得要在系统变量中添加OPENCVROOT变量;
3.3.3 数据传输错误
错误描述:
数据传输错误一般指得到了不正确的数据,例如图像显示错误:
解决办法:
- 首先检查你的代码,或者通过Guidance SDK中给出的例程进行检验;
- 确认不是代码的问题后,请重启Guidance,并在Guidance上的绿灯开始闪烁后再运行程序;这种情况一般是由于非正常退出导致的,例如线程在运行到 stop_transfer() 与 release_transfer() 之前就已经退出。
4、创建一个视觉跟踪工程
这里我们要实现的功能是利用Guidance SDK中的API,通过USB从Guidance中读取图像数据,使用camshift完成一个视觉跟踪的应用。该教程支持Windows和Ubuntu系统。
demo文件夹中已经有了一个完整的视觉跟踪的工程,用户可以直接编译运行这个工程,以便有一个整体的认识。然后依照下面的指示,从零开始建立一个视觉跟踪的工程。
4.1 下载并解压SDK
你可以从GitHub下载到最新的Guidance SDK并解压。
内容包括:
- demo:一个基于Guidance SDK 的视觉跟踪应用
- doc: API说明文档
- examples: USB, UART及ROS的示例代码
- include: Guidance SDK头文件
- lib: Windows下库文件
- so: Linux下库文件
4.2 Windows
1. 新建guidanceSDK_test测试工程
如下图所示,在SDK/demo目录下创建自己的工程,这里在VS2010中创建了一个空工程,工程名为guidanceSDK_test。
2. 添加相应的.h及.cpp到工程
2.1 添加main.cpp
向工程中添加空的源文件main.cpp。
2.2 添加DJI_utility与DJI_utility.cpp
首先将要使用到的线程操作保护的源文件DJI_utility.cpp与头文件DJI_utility.h复制到与main.cpp同目录下,并在项目中添加。DJI_utility.cpp与DJI_utility.h在demo及examples中均可找到。
- 在demo/sdk_tracking_camshift/camshift中的DJI_utility相关文件。
- 将DJI_utility文件复制到工程所在文件夹,并添加到guidanceSDK_test工程中:
2.3 配置头文件与链接库路径
需要配置的有DJI_guidance.h、DJI_guidance.lib与OpenCV头文件及库文件的路径。 DJI_guidance.h头文件位于SDK/include中;DJI_guidance.lib位于SDK/lib中,在VS2010中需要进行相应的配置将它们的路径包含到工程中。由于本教程运行于Release Win32模式下,最后编译输出x86平台的release文件,对应的DJI_guidance.lib文件具体路径为SDK/lib/2010/x86。
- Visual Studio 2010工程为Release Win32模式:
- 在SDK/include中找到DJI_guidance.h并复制到工程目录。
- 在SDK/lib/2010/x86中找到DJI_guidance.lib并复制到工程目录。
- 将OpenCV相关的头文件和库文件目录添加到工程。
为简化配置的繁琐,可直接复制SDK/demo/sdk_tracking_camshift目录下的 “use_opencv_release_vs2010_x86.props”“use_Guidance_vs2010_x86.props” 文件到解决方案目录下并添加到工程。
- 在sdk_tracking_camshift工程目录中找到 “use_opencv_release_vs2010_x86.props” 和 “use_Guidance_vs2010_x86.props” 配置文件:
- 将相应的props配置文件拷贝到 解决方案目录下:
- 切换工具栏到 ”配置管理器”,右键单击Release | Win32,点击添加已有配置表 “Add Existing Property Sheet”,将工程目录下的“use_opencv_release_vs2010_x86.prop” 与 “use_Guidance_vs2010_x86.prop” 这两个配置文件添加到工程中:
请注意:这里默认用户已按照环境配置中所述的方法,安装了Opencv2411,并正确添加了环境变量OPENCVROOT。这一环境变量在OpenCV的配置文件中被用到。
当工程路径变化时,用户也可以通过修改配置文件来适应;具体的可以查看相应的配置文件;这里给出一个Guidance相关文件配置的例子,OpenCV的配置类似。
- “use_Guidance_vs2010_x86.prop”中配置的头文件路径:
- “use_Guidance_vs2010_x86.prop”中配置的链接库路径:
3. 配置动态链接库文件
在SDK根目录下有lib文件夹,由于本教程中默认是VS2010建立的工程,并且运行Release Win32的程序,因此进入lib/2010/x86,将相应的DJI_guidance.dll文件复制出来。
4. 填入main.cpp代码
- 首先添加程序所需头文件。DJI_guidance.h中包含了Guidance API函数声明的头文件,必须添加;DJI_utility.h中包含了线程操作保护的头文件;OpenCV对应的头文件用于图像显示及视觉算法应用;
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include <fstream>
#include <iostream>
#include "DJI_guidance.h"
#include "DJI_utility.h"
using namespace cv;
using namespace std;
- 声明程序中需要用到的全局变量;其中image用作处理结果显示;g_lock是与线程操作保护有关的对象,g_event是与数据读取事件触发有关的对象,二者在DJI_utility.h中均有定义;selection用作鼠标选择跟踪目标;WIDTH, HEIGHT及IMAGE_SIZE宏定义为图像大小;
Mat image;
bool selectObject = false;
int trackObject = 0;
Point origin;
Rect selection;
DJI_event g_event;
DJI_lock g_lock;
#define WIDTH 320
#define HEIGHT 240
#define IMAGE_SIZE (HEIGHT * WIDTH)
- 接着定义鼠标交互事件函数,该函数使得用户可以在图像传输开始时用鼠标框出要跟踪的目标;
static void onMouse( int event, int x, int y, int, void* )
{
if( selectObject )
{
selection.x = MIN(x, origin.x);
selection.y = MIN(y, origin.y);
selection.width = std::abs(x - origin.x);
selection.height = std::abs(y - origin.y);
selection &= Rect(0, 0, image.cols, image.rows);
}
switch( event )
{
case CV_EVENT_LBUTTONDOWN:
origin = Point(x,y);
selection = Rect(x,y,0,0);
selectObject = true;
break;
case CV_EVENT_LBUTTONUP:
selectObject = false;
if( selection.width > 0 && selection.height > 0 )
trackObject = -1;
break;
}
}
- 再定义一个帮助函数,用来在Windows控制台模式下运行程序,如果输入
`guidanceSDK_test.exe -h`
则会返回给用户程序使用方法;
static void help()
{
cout << "\nThis is a demo that shows camshift based tracking with Guidance.\n"
"You select an objects such as your face and it tracks it.\n"
"This reads from greyscale and depth images from DJI Guidance.\n"
"Usage: \n"
" ./camshift.exe\n";
cout << "\n\nHot keys: \n"
"\tESC/q - quit the program\n"
"\tc - stop the tracking\n"
"\tb - switch to/from backprojection view\n"
"\tp - pause video\n"
"To initialize tracking, select the object with mouse\n";
}
本教程给出的是基于camshift算法与深度图的视觉跟踪demo,当程序开始运行用户需要首先使用鼠标在Guidance Tracking Demo窗口 中框出需要跟踪的目标,接着移动目标可以观察到跟踪效果;
- 然后定义一个回调函数,当订阅的数据到来时程序会自动调用该函数。用户应该只在回调函数中进行轻量级的处理,比如数据拷贝等,否则会降低数据传输频率。
Mat g_imleft(HEIGHT, WIDTH, CV_8U);
Mat g_imright(HEIGHT, WIDTH, CV_8U);
Mat g_depth(HEIGHT, WIDTH, CV_16SC1);
e_vbus_index selected_vbus = e_vbus1; // select front vbus
string winDemoName = "Guidance Tracking Demo";
int my_callback( int data_type, int data_len, char *content )
{
printf("enter callback..\n");
g_lock.enter();
if ( e_image == data_type && NULL != content )
{
printf("callback: type is image..\n");
image_data data;
memcpy((char*)&data, content, sizeof(data));
memcpy(g_imleft.data, data.m_greyscale_image_left[selected_vbus], IMAGE_SIZE);
memcpy(g_imright.data, data.m_greyscale_image_right[selected_vbus], IMAGE_SIZE);
memcpy(g_depth.data, data.m_depth_image[selected_vbus], IMAGE_SIZE * 2);
}
g_lock.leave();
g_event.set_event();
return 0;
}
- 当初始化、订阅或停止传输等操作失败时,返回为非0的int类型值,因此用户可以通过这些操作函数的返回值来判断失败的原因。我们这里宏定义两个操作,如果操作失败,则打印错误码或者直接终止程序;
#define RETURN_IF_ERR(err_code) { if( err_code ){ printf( "USB error code:%d in file %s %d\n", err_code, __FILE__, __LINE__ );}}
#define RELEASE_IF_ERR(err_code) { if( err_code ){ release_transfer(); printf( "USB error code:%d in file %s %d\n", err_code, __FILE__, __LINE__ );}}
- 在main函数中完成初始化、数据订阅、启动数据传输、图像处理显示、停止数据传输、释放传输线程等操作;
int main( int argc, const char* argv[] )
{
/* 帮助 */
if(argc>1)
help();
/* 准备写入视频 */
VideoWriter vWriter("result.avi", CV_FOURCC('M','J','P','G'), 25, Size(WIDTH, HEIGHT), false);
/* 跟踪窗口 */
Rect trackWindow;
int hsize[] = {16, 16};
float hranges[] = {0, 255};
float dranges[] = {0, 255};
const float* phranges[] = { hranges, dranges };
selection = Rect(10,10,100,100);
trackObject = 0;
namedWindow( winDemoName, 0 );
/* 等待鼠标框出 */
setMouseCallback( winDemoName, onMouse, 0 );
Mat imcolor, mask, hist, hist_of_object, backproj;
bool paused = false;
float hist_update_ratio = 0.2f;
/* 初始化Guidance数据传输 */
reset_config();
int err_code = init_transfer();
RETURN_IF_ERR(err_code);
/* 订阅selected_vbus左侧灰度图 */
err_code = select_greyscale_image(selected_vbus, true);
RELEASE_IF_ERR(err_code);
/* 订阅selected_vbus右侧灰度图 */
err_code = select_greyscale_image(selected_vbus, false);
RELEASE_IF_ERR(err_code);
/* 订阅selected_vbus深度图 */
err_code = select_depth_image(selected_vbus);
RELEASE_IF_ERR(err_code);
/* 设置数据到来时的回调函数*/
err_code = set_sdk_event_handler(my_callback);
RELEASE_IF_ERR(err_code);
/* 开启数据传输线程 */
err_code = start_transfer();
RELEASE_IF_ERR(err_code);
Mat depth(HEIGHT, WIDTH, CV_8UC1);
/* 设置传输事件循环次数 */
for( int times = 0; times < 30000; ++times )
{
/* 等待数据到来 */
g_event.wait_event();
// filter depth image
filterSpeckles(g_depth, -16, 50, 20);
// convert 16 bit depth image to 8 bit
g_depth.convertTo(depth, CV_8UC1);
/* 显示深度图 */
imshow("depth", depth);
waitKey(1);
/* 获得灰度图 */
g_imleft.copyTo(image);
if( !paused )
{
vector<Mat> ims(3);
ims[0] = image;
ims[1] = ims[2] = depth;
merge(ims, imcolor);
/* 如果鼠标框出了目标,则进行跟踪及效果显示 */
if( trackObject )
{
int ch[] = {0,1};
if( trackObject < 0 )
{
Mat roi(imcolor, selection);
calcHist(&roi, 1, &ch[0], Mat(), hist, 2, &hsize[0], &phranges[0]);
normalize(hist, hist, 0, 255, CV_MINMAX);
if(hist_of_object.empty())
hist_of_object = hist;
else
hist_of_object = (1-hist_update_ratio)*hist_of_object + hist_update_ratio*hist;
trackWindow = selection;
trackObject = 1;
}
calcBackProject(&imcolor, 1, ch, hist_of_object, backproj, phranges);
RotatedRect trackBox = CamShift(backproj, trackWindow,
TermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ));
if (trackWindow.area() <= 1)
{
int cols = backproj.cols, rows = backproj.rows, r = (MIN(cols, rows) + 5)/6;
trackWindow = Rect(trackWindow.x - r, trackWindow.y - r,
trackWindow.x + r, trackWindow.y + r) &
Rect(0, 0, cols, rows);
}
if( trackWindow.area() <= 1 )
break;
ellipse( image, trackBox, Scalar(0,0,255), 3, CV_AA );
}
else if( trackObject < 0 )
{
paused = false;
}
}
if( selectObject && selection.width > 0 && selection.height > 0 )
{
Mat roi(image, selection);
bitwise_not(roi, roi);
}
imshow( winDemoName, image );
vWriter<<image;
char c = (char)waitKey(10);
/* 按q键退出 */
if( c == 27 || c=='q')
{
break;
}
switch(c)
{
case 'c':
trackObject = 0;
break;
case 'p':
case ' ':
paused = !paused;
break;
default:
;
}
}
/* 停止数据传输 */
err_code = stop_transfer();
RELEASE_IF_ERR(err_code);
/* 确保停止 */
sleep(100000);
/* 释放传输线程 */
err_code = release_transfer();
RETURN_IF_ERR(err_code);
return 0;
}
5. 编译运行
由于本教程默认guidance SDK运行所需的工作环境已经按照环境配置中配置成功,因此这里只需Build编译完工程,启动并通过USB线连接Guidance,点击Start Debugging即可运行程序。
4.3 Linux
1. 新建工程文件夹
- 将SDK包下载到~/Desktop/GuidanceSDK目录。
- 新建工程目录 ~/Desktop/SDK/demo/guidance_track,并添加DJI_utility.cpp 与 DJI_utility.h;另外main.cpp中的代码也与上一节Windows的介绍中相同,在此不赘述,直接拷贝过来。
mkdir ~/Desktop/GuidanceSDK/demo/guidance_track
cd ~/Desktop/SDK/demo/guidance_track
2. 添加libDJI_guidance.so文件
由于本教程使用的是32位的Ubuntu14.04系统,因此去SDK根目录下的so/x86中,将libDJI_guidance.so文件复制到usr\local\lib 文件夹下即可,不同位数系统请复制对应的.so文件。请注意,复制时需要用到sudo权限。
sudo cp ~/Desktop/GuidanceSDK/so/x86/libDJI_guidance.so /usr/local/lib
3. 编写Makefile文件
接着编写Makefile文件。确保OpenCV已经正确安装。
gedit Makefile
Makefile代码如下:
#定义编译器
CXX = g++
#定义生成文件
TARGET = main
#定义生成依赖文件
OBJECTS = main.o DJI_utility.o
#定义头文件包含目录
CFLAGS = -g -Wall -I/usr/local/include -I../../../include
#定义动态链接库路径、opencv路径及选项
LDFLAGS = -Wl,-rpath,./ -lpthread -lrt -L./ -L/usr/local/lib/ -lDJI_guidance -lusb-1.0 `pkg-config --cflags --libs opencv`
$(TARGET) : $(OBJECTS)
$(CXX) -o $(TARGET) $(OBJECTS) $(LDFLAGS)
main.o : main.cpp DJI_utility.h
$(CXX) $(CFLAGS) -c main.cpp DJI_utility.h
DJI_utility.o : DJI_utility.cpp DJI_utility.h
$(CXX) $(CFLAGS) -c DJI_utility.cpp DJI_utility.h
clean:
rm -rf *.o *.gch *.avi $(TARGET)
4. 编译与运行
- 启动Guidance,并通过USB线将其与电脑连接。
- 编译并运行工程
make
sudo ./main
- 当程序启动后,在“Guidance Tracking Demo”窗口中用鼠标框出待跟踪目标,接着可以在图上看到目标跟踪效果:
- 在该窗口上按 q 键退出程序。
5、FAQ
I、Guidance SDK 包含些什么内容?
Guidance SDK 包含有:
- demo: 一个利用 Guidance API 实现的视觉跟踪应用程序
- doc: SDK 整体说明文档
- examples: USB、 UART 及 ROS 的使用例程
- include: Guidance API 的头文件
- lib: Windows 下的动态链接库文件
- so: Linux 下的动态链接库文件
Guidance API 给用户提供了 Guidance 传感数据的读取接口,这些数据包括 IMU data, Velocity, Obstacle distance, grey-scale image, depth image 及 ultrasonic data,并可通过 USB 与 UART 两种方式进行读取。
II、我可以在哪些平台上应用 Guidance SDK?
用户可以在 Guidance Core 硬件上单独使用 Guidance SDK,而与其他硬件平台独立开,也可连接到 M100 进行辅助视觉定位及避障。
用户可以在 32 位与 64 位的 Linux 及 Windows 操作系统上使用 Guidance SDK 进行 Guidance 的应用开发,这些操作系统平台所对应的动态链接库在 lib 与 so 中可以找到。
III、如何使用 Guidance SDK 从 Guidance Core 中获取传感数据?
首先你需要参考开发者指南中所述来配置开发环境,其中包括了驱动的安装及工程配置文件的设置。
成功完成相应的配置后,将 Guidance Core 连接至计算机并上电,运行 demo 或 examples 中的程序便可看到数据传输效果。
IV、为何我无法在“资源管理器”中找到 Guidance 设备?
首先,请确认 Guidance Core 连接了计算机并已经上电;
如果您是通过 USB 的方式进行连接的,请检查 DJI_Guidance 软件是否安装成功;
如果您是通过 UART 方式进行连接的,请检查 USB转RS232 驱动是否安装成功。
V、为什么我无法运行 demo 与 examples 中的程序?
首先确认 UART 或 USB 的驱动安装成功了,在 Windows 平台下可以通过查看设备管理器进行检查。
接着打开 DJI_Guidance 软件,将模式设置为自定义模式,并在接口参数选项卡中根据需要打开 USB 与 UART 的数据订阅选项。
如果以上都没问题,错误仍然存在,还有可能是 OpenCV 的配置错误,或者是 dll 文件未放置正确;这些问题都可以在开发者指南中找到解决方案。
VI、我能够通过 UART 的传输方式获取图像数据吗?
不能。由于 UART 传输的带宽限制,我们不提供 UART 下的图像传输方法。
VII、我能够一次性订阅并传输所有的灰度图与深度图数据吗?
不能。由于带宽的限制,你不能同时选择所有通道的灰度图与深度图数据。
VIII、如果我只想订阅深度图数据,我是否也需要同时订阅同一方向上的灰度图?
你可以只订阅深度图数据,而不用同时订阅你不需要的灰度图数据。
IX、我能够同时通过 USB 与 UART 获取数据吗?
是的,你可以同时通过这两种方式来读取数据,这意味着你将 USB 与 UART 同时连接至计算机并开启两个程序。但我们并不推荐这样做,用户可以单独通过 USB 方法获取所有的传感数据。
X、如果我在使用 Guidance SDK 中出现问题,应该去哪里寻求帮助?
首先你可以参考 SDK 包中的 开发者指南 来获得开发过程中可能出现的问题的解决方法。
如果在查阅了 开发者指南 后仍无法解决问题,你还可以登录我们的技术支持论坛http://forum.dji.com,将自己遇到的问题通过帖子的形式发表在论坛上,我们的工程师会为你及时地回复。
XI、我怎么才能用 Guidance SDK 来开发我自己的 Guidance 项目?
你可以通过修改 Guidance SDk 中提供的 demo 与 examples 来适应你的项目, 或者你也可以通过参考 开发者指南 中的教程 如何创建一个基于Guidance SDK的视觉跟踪程序 来建立你自己的项目。
XII、通过 USB 方式传输的数据频率最高能达到多少?
图像数据的最高频率为 20hz,其他如 IMU、速度等的数据频率固定为20hz。
XIII、通过 UART 方式进行数据传输,最高能到达多少波特率?
目前我们只支持 115200 波特率下 UART 方式的数据传输。
XIV、我能够通过 Guidance SDK 获得 Guidance 摄像头的标定内参吗?
目前我们并不支持这项功能。在下一版我们会考虑提供相应方法,使用户能够取得摄像头的标定内参。