刚刚结束了项目交付,趁热打铁分享一下这次遇到的新东西。首先了解一下大疆的无人机,它大致可以分为三级。
入门级:适合新手,没事干在野外飞一飞拍拍风景啥的。操作也简单,基本上看飞行教程都能懂,也不需要太高的专业性,飞机也相对较小安全系数相对较高。如:御2系列的一些飞机。
消费级:形体上会比入门级的大一点,但是飞机搭载了一些高精度的东西,比如rtk、高精度摄像头、红外镜头等。这类飞机则需要飞手具备一定的专业知识,并且需要考取大疆的初级飞手证书才能上手飞行。如:精灵系列、悟系列的一些飞机。
专业级:形体上更大,操作不当会出现一些严重后果。它的优势在于高续航、高精度定位、热成像镜头、搭载第三方喊话器等。一般用于大型工程作业,使用这个级别的飞机则需要考取大疆专业飞手证书,一般这个会在你购买专业级飞机的时候赠送你培训课程,一般全部听完就能考过。这类飞机的典型代表有:m30系列、m300系列。
1sdk开发包
大疆的sdk开发包目前分为两个大版本:
v4版
mobile sdk是一款软件开发套件,旨在让开发者能够访问dji无人机和手持相机产品的丰富功能。该sdk通过兼顾更底层的功能,诸如飞行稳定,电池管理,信号传输和通信等,简化了应用程序开发的过程。这样,开发者就不需要具备丰富的机器人或嵌入式系统背景知识,而可以专注于dji产品相关的行业应用开发。
该sdk包括:
可导入android或ios应用程序的库/框架,用于访问dji产品的功能。
飞行模拟器和可视化工具。
适用于ios的调试工具和远程logger。
示例代码和教程。
开发者指南和api文档。
功能概述
开发者可以通过sdk访问许多dji产品的功能。开发者可以实现自主飞行,控制相机和云台,接收实时视频图传和传感器数据,下载保存好的媒体文件,以及监听其他组件的状态。
飞行控制
mobile sdk提供三种控制无人机飞行的方式:
手动操控: 用户使用遥控器操控无人机,而sdk支持监控实时视频流和传感器数据。虚拟摇杆命令: sdk支持产生模拟遥控器摇杆的控制指令。
智能任务: 方便,易于实现无人机的高级控制。例如,可以通过航点任务,让无人机按预定义的飞行路径飞行。
虚拟摇杆命令和智能任务允许对dji无人机进行简单而功能强大的自主飞行控制。
相机
相机和云台的功能都支持编程调用, 例如:
相机模式: 视频和静态图像拍摄。
曝光: 快门,iso,光圈和曝光补偿均支持定制,以实现最大的灵活性。
图像参数: 屏幕长宽比,对比度,色相,清晰度,饱和度和滤镜。
视频参数: 分辨率和帧频。
方向: 使用云台时,相机的朝向和运动可以自动控制。
实时视频流
开发者可以通过mobile sdk获取无人机主摄像头的实时视频流。即使摄像头正在将图像或视频捕获到存储介质中,也可以获取实时视频流。
传感器数据
开发者可以通过sdk获得丰富的传感器数据。gps位置,指南针,气压计,飞行速度和海拔高度都是通过mobile sdk获取的一些传感器数据,频率最高可达10 hz。
下载媒体文件
开发者通过mobile sdk可以查看和下载保存在相机存储介质(sd卡或固态硬盘)中的照片和视频。预览图和完整的图像数据都可以被访问。
遥控器,电池和无线链路
遥控器,电池和无线链路都可以通过sdk进行访问。通常,这些组件会提供相关的状态信息,但开发者也可以对它们进行一些控制。
连接应用程序和产品
下图说明了mobile sdk如何与移动应用程序进行融合以及如何与dji飞行器进行连接。对于手持摄像机产品,遥控器已替换为手持控制器,并且没有飞行器或其他无线链路。
移动应用程序由mobile sdk,平台sdk(ios或android)构建而成,并在移动设备(apple iphone,ipad,nexus手机,nexus平板电脑等)上运行。
移动设备可以通过wifi无线连接到dji产品上,也可以通过usb线缆连接到dji产品上。
v5版
v5版现在只适用于m30、m300系列,目前还在持续更新,因为是新版的sdk,大疆的工程师也是在不断地再完善里面的内容,这里就不详细说了,之后的文章会详细说这个v5版的sdk。
2v4版sdk 二次开发
多的不说少的不唠,上主菜。“工欲善其事,必先利其器”,首先准备好开发软件,因为我们使用的是android版的sdk所以开发软件我们使用android studio,本人使用的是android studio fox版,版本之间感觉都一样没有什么开发上的区别。准备好工具之后,先去大疆无人机的开发者官网注册一个开发者账号,并且注册好自己的应用,拿到sdk的专用key值,申请的方法大疆官网有我就不赘述了。给大家个地址【大疆开发者官网】自己看吧,挺简单的。
注册成为dji开发者
在注册过程中,需要您提供电子邮件信息和信用卡或手机号码用于注册验证。您所提供的任何信用卡信息将仅用于验证,不会收取任何费用。
本指南假定您使用 xcode 7.3 以及 android studio 2.1.1 以上版本。
生成 app key
每个应用程序都需要一个唯一的应用程序密钥(app key)来初始化sdk。
要创建一个应用程序app key:
请访问dji开发者网站的 开发者中心
选择左侧栏的 应用 。
选择右侧的 “创建应用” 按钮。
输入应用程序的名称, 开发平台, package name,分类和描述信息。
会收到一封应用程序激活邮件,以完成app key的生成。
可以在开发者中心中找到appkey,复制粘贴到应用程序配置中。
android 示例代码配置
下载或者克隆github上的android示例代码工程。
在android studio中打开项目工程,将生成的app key字符串粘贴到 androidmanifest.xml 文件中 com.dji.sdk.api_key meda-data element下的 android:value。
3android studio项目集成
本节中的屏幕截图是使用android studio 4.1生成的。
创建一个新的应用
可以使用一个新的应用程序来演示如何将dji sdk集成到android studio项目中。
打开android studio,然后在初始屏幕上选择start a new android studio project。
在 new project 界面:
设置 application name 为 importsdkdemo。
设置 company domain 和package name 为 com.dji.importsdkdemo。
注意:package name是 生成app key 所需的标识字符串。在这个工程中package name为“com.dji.importsdkdemo”
在 target android devices 界面:
选择 phone and tablet 尺寸。
选择api 23:android 6.0 (marshmallow)。
在 add an activity to mobile 界面选择 empty activity。
在configure activity 界面:
设置 activity name: 为 mainactivity。
确认勾选generate layout file 。
设置layout name: 为activity_main。
点击finish 。
配置gradle 脚本
在gradle scripts 中双击 build.gradle (module: app)
使用以下内容进行更新:
apply plugin: 'com.android.application'android { ... defaultconfig { ... } ... packagingoptions{ donotstrip */*/libdjivideo.so donotstrip */*/libsdkrelativejni.so donotstrip */*/libflyforbid.so donotstrip */*/libduml_vision_bokeh.so donotstrip */*/libyuv2.so donotstrip */*/libgroudstation.so donotstrip */*/libfrcorkscrew.so donotstrip */*/libupgradeverify.so donotstrip */*/libfr.so donotstrip */*/libdjiflysafecore.so donotstrip */*/libdjifs_jni.so donotstrip */*/libsfjni.so exclude 'meta-inf/rxjava.properties' }}dependencies { ... implementation('com.dji4.15', { exclude module: 'library-anti-distortion' }) compileonly 'com.dji4.15}
主要变更为:
添加 packagingoptions以防止应用程序意外崩溃。
添加compile和provided依赖项以导入最新的djiandroid sdk maven依赖项。
选择 tools -> android -> sync project with gradle files 然后等待gradle项目同步完成。
再次确认 maven 依赖
在android studio菜单中选择file->project structure,以打开project structure界面。然后选择“app”模块,然后单击dependencies选项卡。
实现应用注册和sdk回调
右键单击com.dji.importsdkdemo,然后选择 new->java class以创建一个新的java类,并将其命名为“mapplication”。
打开mapplication.java文件,并将内容替换为以下内容:
package com.dji.importsdkdemo;import android.app.application;import android.content.context;import com.secneo.sdk.helper;public class mapplication extends application { @override protected void attachbasecontext(context paramcontext) { super.attachbasecontext(paramcontext); helper.install(mapplication.this); }}
在这里,重写了attachbasecontext()方法,添加了helper.install(mapplication.this);代码。
注意:由于某些sdk类现在需要在使用之前进行加载,因此加载过程由helper.install()完成。开发人员需要在使用任何sdk功能之前调用此方法, 否则可能会导致意外崩溃。
修改完成后需要在androidmanifest中 配置 application name。
双击app模块中的mainactivity.java。
mainactivity类需要注册应用程序以获得使用mobile sdk的授权。它还需要实现sdk回调方法。
首先将mainactivity类修改为包括几个类变量,其中包括mproduct,它是代表连接到移动设备的dji产品的对象。
另外,oncreate方法将被修改以调用checkandrequestpermissions方法来检查和请求运行时权限。同样,checkandrequestpermissions方法将有助于调用startsdkregistration()方法来注册应用程序。此外,重写onrequestpermissionsresult方法将有助于检查应用程序是否具有足够的权限,如果有,请调用startsdkregistration()方法来注册应用程序。
最后,将mainactivity类替换为:
public class mainactivity extends appcompatactivity { private static final string tag = mainactivity.class.getname(); public static final string flag_connection_change = dji_sdk_connection_change; private static baseproduct mproduct; private handler mhandler; private static final string[] required_permission_list = new string[]{ manifest.permission.vibrate, manifest.permission.internet, manifest.permission.access_wifi_state, manifest.permission.wake_lock, manifest.permission.access_coarse_location, manifest.permission.access_network_state, manifest.permission.access_fine_location, manifest.permission.change_wifi_state, manifest.permission.write_external_storage, manifest.permission.bluetooth, manifest.permission.bluetooth_admin, manifest.permission.read_external_storage, manifest.permission.read_phone_state, }; private list missingpermission = new arraylist(); private atomicboolean isregistrationinprogress = new atomicboolean(false); private static final int request_permission_code = 12345; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); // when the compile and target version is higher than 22, please request the following permission at runtime to ensure the sdk works well. if (build.version.sdk_int >= build.version_codes.m) { checkandrequestpermissions(); } setcontentview(r.layout.activity_main); //initialize dji sdk manager mhandler = new handler(looper.getmainlooper()); } /** * checks if there is any missing permissions, and * requests runtime permission if needed. */ private void checkandrequestpermissions() { // check for permissions for (string eachpermission : required_permission_list) { if (contextcompat.checkselfpermission(this, eachpermission) != packagemanager.permission_granted) { missingpermission.add(eachpermission); } } // request for missing permissions if (missingpermission.isempty()) { startsdkregistration(); } else if (build.version.sdk_int >= build.version_codes.m) { showtoast(need to grant the permissions!); activitycompat.requestpermissions(this, missingpermission.toarray(new string[missingpermission.size()]), request_permission_code); } } /** * result of runtime permission request */ @override public void onrequestpermissionsresult(int requestcode, @nonnull string[] permissions, @nonnull int[] grantresults) { super.onrequestpermissionsresult(requestcode, permissions, grantresults); // check for granted permission and remove from missing list if (requestcode == request_permission_code) { for (int i = grantresults.length - 1; i >= 0; i--) { if (grantresults[i] == packagemanager.permission_granted) { missingpermission.remove(permissions[i]); } } } // if there is enough permission, we will start the registration if (missingpermission.isempty()) { startsdkregistration(); } else { showtoast(missing permissions!!!); } }}
djisdkmanager的registerapp()方法具有一个回调,该回调需要处理两种方法:一、用于处理应用程序注册结果。二、用于通知硬件产品和移动设备的连接变更。
继续添加如下所示的 startsdkregistration() 方法,并实现 onregister(), onproductdisconnect(), onproductconnect(), oncomponentchange(), oninitprocess() and ondatabasedownloadprogress() 和sdkmanagercallback方法:
private void startsdkregistration() { if (isregistrationinprogress.compareandset(false, true)) { asynctask.execute(new runnable() { @override public void run() { showtoast(registering, pls wait...); djisdkmanager.getinstance().registerapp(mainactivity.this.getapplicationcontext(), new djisdkmanager.sdkmanagercallback() { @override public void onregister(djierror djierror) { if (djierror == djisdkerror.registration_success) { showtoast(register success); djisdkmanager.getinstance().startconnectiontoproduct(); } else { showtoast(register sdk fails, please check the bundle id and network connection!); } log.v(tag, djierror.getdescription()); } @override public void onproductdisconnect() { log.d(tag, onproductdisconnect); showtoast(product disconnected); notifystatuschange(); } @override public void onproductconnect(baseproduct baseproduct) { log.d(tag, string.format(onproductconnect newproduct:%s, baseproduct)); showtoast(product connected); notifystatuschange(); } @override public void oncomponentchange(baseproduct.componentkey componentkey, basecomponent oldcomponent, basecomponent newcomponent) { if (newcomponent != null) { newcomponent.setcomponentlistener(new basecomponent.componentlistener() { @override public void onconnectivitychange(boolean isconnected) { log.d(tag, oncomponentconnectivitychanged: + isconnected); notifystatuschange(); } }); } log.d(tag, string.format(oncomponentchange key:%s, oldcomponent:%s, newcomponent:%s, componentkey, oldcomponent, newcomponent)); } @override public void oninitprocess(djisdkinitevent djisdkinitevent, int i) { } @override public void ondatabasedownloadprogress(long l, long l1) { } }); } }); }}
最后需要实现 notifystatuschange, runnable 和 showtoast 方法:
private void notifystatuschange() { mhandler.removecallbacks(updaterunnable); mhandler.postdelayed(updaterunnable, 500);}private runnable updaterunnable = new runnable() { @override public void run() { intent intent = new intent(flag_connection_change); sendbroadcast(intent); }};private void showtoast(final string toastmsg) { handler handler = new handler(looper.getmainlooper()); handler.post(new runnable() { @override public void run() { toast.maketext(getapplicationcontext(), toastmsg, toast.length_long).show(); } });}
必须授予应用程序权限,dji sdk才能运行。
双击 app 模块中的 androidmanifest.xml 。
在 package=com.dji.importsdkdemo 后,
在 application 元素的开发添加 android:name=.mapplication :
在 android:theme=@style/apptheme> 之后,之前插入如下代码:
如下所示,在activity元素中插入android:configchanges =orientation和android:screenorientation =portrait,以防止在屏幕方向变更时重启activity,并将activity的屏幕方向设置为纵向模式 :
生成app key, 然后用app key 字符串替换androidmanifest.xml文件内please enter your app key here. 字段。
什么是供电电源轨?非轨到轨特性对电源设计的影响?
毫米波应用的挑战 毫米波测试的进展
OPPO、vivo、小米大举追加订单,联发科反超高通成台积电第三大客户
魅族回应高通专利诉讼 李楠发“黑盒子”引遐想
爱分析报告:生成式AI掀起产业智能化新浪潮
基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1)
英飞凌推新LTE低噪声放大器及LNA Bank 大幅改善用户体验
远程修改STM32 TIMER占空比的方案
酷比H9正式发布:无边框、双摄与Hi-Fi
小米将在国庆前加速推进线下渠道建设,以促进手机等产品的销售
华为OTN品质专线解决方案打造精品广电承载网
脉冲输出涡轮流量计工作原理_脉冲输出涡轮流量计结构图
经典指南:你真的了解开关电源吗?
卧式共模电感基本特性详解gujing
新能源汽车BMS与超充&核心电源技术研讨会已完美落幕
新兴的人工智能(AI)技术具有加速和转变对分子疗法的搜索的潜力
斯柯达自动空调空气护理系统保证车内的空气清洁
!销售/回收HP8922S/HP8922S/HP8922S现
采用无监督学习的方法,用深度摘要网络总结视频
DEVICENET转ETHERNET/IP网关devicenet通讯模块