新航线任务实现教程
1. 概述
新航线任务支持用户手动选择目标点,通过不同的航线规划算法,自动生成飞行航线。用户可以自定义航线飞行参数以及航点的相机动作。
2. 流程图
为了使用任务规划功能,需要完成如下几个步骤
1、创建相关任务实体类,参看3.1节。
2、调用SDK算法生成航线任务文件,参看3.2节。
3、上传任务文件以及控制任务的开始、暂停、取消,参看3.4、3.5节。
下⾯以Autel SDK demo为例讲解如何进⾏通过Autel SDK实现任务规划功能。示例代码请参看Evo2WayPointActivity。
3. 任务规划相关API说明
3.1 航点任务
3.1.1 航点任务说明
航点任务包含多个航点,当飞行器飞到对应的航点时,会执行预设动作,当动作完成以后,飞行器会飞到下一个航点执行预设动作,直到所有航点的任务完成。
3.1.2 航点任务API说明
主要使用PathMission
来设置航点任务,主要包含航点个数、返航点坐标、航点的具体信息。
PathMission.java相关字段说明
public class PathMission {
/**
* 航点个数
*/
public short WPNum;
/**
* 是否使用默认半径,0:不用,1:用
*/
public short default_R_flag;
/**
* Home点坐标,经纬高
*/
public double[] HomeLLA;//3
/**
* 航点信息(500个)
*/
public PathPoint[] WP_Info_strc;//500
}
使用PathPoint
来设置航点信息,包含航点的经纬度、飞行姿态、相机动作、兴趣点等。
PathPoint.java相关字段说明
public class PathPoint {
/** 航点类型 1-代表停下的点,2-代表协调转弯 */
public short WPTypeUsr;
/** 用户设置的航点,经纬高 */
public double[] WPLLAUsr;//3
/** 用户设置转弯半径*/
public double RadUsr;
/** 速度 */
public double VelRefUsr;
/** 航点高度优先级 1表示优先级比前一个点高,-1表示比前一个点低,0表示无优先级 */
public short AltPrioUsr;
/** 此航点中 动作朝向模式 1表示协调转弯,2表示手动,3表示自定义 */
public short Heading_Mode;
/** 兴趣点是否有效 -1 表示无兴趣点, 1 表示有兴趣点 */
public short POI_Valid;
/** 对应兴趣点的坐标,经纬高 */
public double[] POIUsr;//3
/** 此航点相机动作总数 */
public short ActionNum;
/** 航点动作(10个) 实际Action_Num个,最大为10 */
public CameraActionJNI[] MSN_ActionInfo;//10
}
使用CameraActionJNI
来设置相机信息。
CameraActionJNI.java字段说明
public class CameraActionJNI {
/** 动作类型 */
public int Action_Type;
/** 云台Pitch角 */
public float Gimbal_Pitch;
/** 云台Roll角 */
public float Gimbal_Roll;
/** 偏航角度 */
public float Action_Yaw_Ref;
/** 定时拍照间隔(s) */
public int Shoot_Time_Interval;
/** 定距拍照距离间隔(mm) */
public float Shoot_Dis_Interval;
/** 动作执行时长(s) */
public int Action_Time;
/** 变焦倍数 */
public int Zoom_Rate;
/** 预留 */
public int[] reserved;//2
}
3.1.3 创建航点任务
创建航点任务示例如下,参看com.autel.sdksample.evo2.mission.Evo2WayPointActivity#initData()方法
PathMission autelMission = new PathMission();
autelMission.HomeLLA = new double[]{22.595607081159642, 113.99784043136384, 10.0};
autelMission.WPNum = 3; //航点数量
autelMission.WP_Info_strc = new PathPoint[autelMission.WPNum];
//第一条
PathPoint first = new PathPoint();
first.WPTypeUsr = 2;
first.WPLLAUsr = new double[]{22.595617689044104, 113.99774410808175, 10.0};
first.RadUsr = 0;
first.VelRefUsr = 10; // 速度 m/s
first.AltPrioUsr=0;
first.Heading_Mode= (short) DroneHeadingControl.FOLLOW_WAYLINE_DIRECTION.getValue();
first.POI_Valid = -1;
first.ActionNum = 2; //相机动作:最多 1个航线动作+10个航点动作
first.MSN_ActionInfo = new CameraActionJNI[2];
//航点动作
first.MSN_ActionInfo[0] = new CameraActionJNI();
first.MSN_ActionInfo[0].Action_Type = CameraAction.POINT_TIMELAPSE.getValue();
first.MSN_ActionInfo[0].Shoot_Time_Interval = 2; //定时拍照间隔 单位:s
first.MSN_ActionInfo[0].Action_Time = 6; //定时拍照时长 单位:s
//航线动作
first.MSN_ActionInfo[1] = new CameraActionJNI();
first.MSN_ActionInfo[1].Action_Type = CameraAction.DISTANCE.getValue();
first.MSN_ActionInfo[1].Shoot_Dis_Interval = 2; //定距拍照间隔 单位:m
autelMission.WP_Info_strc[0] = first;
//第二条
PathPoint second = new PathPoint();
second.WPTypeUsr = 2;
second.WPLLAUsr = new double[]{22.595650750293203, 113.9978042383155, 10.0};
second.RadUsr = 4;
second.VelRefUsr = 10; // 速度 m/s
second.AltPrioUsr=0;
second.Heading_Mode= (short) DroneHeadingControl.CUSTOM.getValue();
second.POI_Valid = -1;
second.ActionNum = 1; //相机动作:最多 1个航线动作+10个航点动作
second.MSN_ActionInfo = new CameraActionJNI[1];
second.MSN_ActionInfo[0] = new CameraActionJNI();
second.MSN_ActionInfo[0].Action_Type = CameraAction.RECORD.getValue();
second.MSN_ActionInfo[0].Gimbal_Pitch = 63;
second.MSN_ActionInfo[0].Action_Yaw_Ref = 179;
autelMission.WP_Info_strc[1] = second;
3.2 调用算法生成规划航线
航带规划算法主要在AirLineCreator
中。API如下所示。
/**
* 航点任务航线生成
**/
public static PathResultMission getWayPointMissionPath(PathMission mission)
示例如下
//传入3.1中设置的航带属性即可
PathResultMission m = AirLineCreator.getWayPointMissionPath(autelMission);
3.3 规划航线写入本地
航线任务写入本地需要使用AirLineCreator
。API如下。
/**
* 生成任务文件,任务以文件的方式上传下载
*
* @param filePath 生成的文件路径
* @param cfg
* @param m
* @return 返回结果: 0:正常;-1:路径不能为空;-2:创建文件目录失败;-3:创建文件目录异常;-4:任务航线不能为空
*/
public static int writeMissionFile(String filePath, MissionConfig cfg, PathResultMission m)
示例如下。
String path = getCacheDir() +"/mission/"+System.currentTimeMillis();
//根据算法生成的规划航线生成任务文件
MissionConfig cfg = new MissionConfig();
cfg.id = mid++;
cfg.type = MissionType.MISSION_TYPE_WAYPOINT;
cfg.altitudeType = MissionAltitudeType.RELATIVE;
cfg.finishAction = MissionFinishActionType.HOVER;
cfg.lossAction = RemoteControlLostSignalAction.CONTINUE;
cfg.vFov = 44.9f; ///相机实时心跳数据读取
AirLineCreator.writeMissionFile(path, cfg, m)
3.4 上传航线规划文件
3.4.1 获取Evo2FlyController
上传航线规划文件需要使用Evo2FlyController
接口,获取Evo2FlyController
对象方法如下
1、用户通过产品连接的监听回调,获取到与APP连接的飞行器的产品类对象BaseProduct,进而获取相关模块的接口。
Autel.setProductConnectListener(new ProductConnectListener() {
@Override
public void productConnected(BaseProduct product) {
//已连接
}
@Override
public void productDisconnected() {
//连接断开
}
});
2、通过产品对获取相关产品的Evo2FlyController接口
Evo2FlyController javamEvoFlyController = (Evo2FlyController) product.getFlyController();
示例如下
Evo2FlyController javamEvoFlyController = (Evo2FlyController) product.getFlyController();
mEvoFlyController.uploadFileData(path, FileDataType.FLY_TASK, new CallbackWithOneParamProgress<Float>() {
@Override
public void onProgress(float var) {
AutelLog.d("waypoint onProgress " + var);
}
@Override
public void onSuccess(Float data) {
flyState = FlyState.Prepare;
AutelLog.d("prepareMission success");
Toast.makeText(Evo2WayPointActivity.this, "prepare success", Toast.LENGTH_LONG).show();
}
@Override
public void onFailure(AutelError error) {
AutelLog.d("prepareMission onFailure");
Toast.makeText(Evo2WayPointActivity.this, "prepare failed", Toast.LENGTH_LONG).show();
}
});
3.5 执行任务
3.5.1 起飞前检查
为了飞行安全,在调用起飞之前, 请检查飞行器如下信息
1、电量检查
EvoBattery battery = (EvoBattery) product.getBattery();
battery.setBatteryStateListener(new CallbackWithOneParam<EvoBatteryInfo>() {
@Override
public void onSuccess(EvoBatteryInfo batteryState) {
isBatteryOk = batteryState.getRemainingPercent() > lowBatteryPercent;
}
@Override
public void onFailure(AutelError autelError) {
}
});
2、IMU、GPS、指南针、是否可以起飞检查
Evo2FlyController mEvoFlyController = (Evo2FlyController) product.getFlyController();
mEvoFlyController.setFlyControllerInfoListener(new CallbackWithOneParam<EvoFlyControllerInfo>() {
@Override
public void onSuccess(EvoFlyControllerInfo evoFlyControllerInfo) {
isCompassOk = evoFlyControllerInfo.getFlyControllerStatus().isCompassValid();
isCanTakeOff = evoFlyControllerInfo.getFlyControllerStatus().isTakeOffValid();
isImuOk = evoFlyControllerInfo.getFlyControllerStatus().getArmErrorCode() != ARMWarning.IMU_LOSS
&& evoFlyControllerInfo.getFlyControllerStatus().getArmErrorCode() != ARMWarning.DISARM_IMU_LOSS;
isGpsOk = evoFlyControllerInfo.getFlyControllerStatus().isGpsValid();
}
@Override
public void onFailure(AutelError autelError) {
}
});
3、图传信号检查
AutelRemoteController remoteController = product.getRemoteController();
remoteController.setInfoDataListener(new CallbackWithOneParam<RemoteControllerInfo>() {
@Override
public void onSuccess(RemoteControllerInfo remoteControllerInfo) {
isImageTransOk = remoteControllerInfo.getDSPPercentage() >= 30;
}
@Override
public void onFailure(AutelError autelError) {
}
});
3.5.2 获取MissionManager
1、用户通过产品连接的监听回调,获取到与APP连接的飞行器的产品类对象BaseProduct,进而获取相关模块的接口
Autel.setProductConnectListener(new ProductConnectListener() {
@Override
public void productConnected(BaseProduct product) {
//已连接
}
@Override
public void productDisconnected() {
//连接断开
}
});
2、通过产品对获取相关产品的MissionManager接口
MissionManager missionManager = product.getMissionManager()
3.5.3 执行任务
当任务开始以后,我们主要可以通过如下几个api来控制任务的进度
1、startMission(开始)
2、pauseMission(暂停)
3、resumeMission(继续)
4、cancelMission(取消)
6、downloadMission(下载正在执行的任务)
MissionManager#startMission
示例
missionManager.startMission(String guid,new CallbackWithNoParam() {
@Override
public void onSuccess() {
flyState = FlyState.Start;
Toast.makeText(Evo2WayPointActivity.this, "start success", Toast.LENGTH_LONG).show();
}
@Override
public void onFailure(AutelError autelError) {
}
});
MissionManager#pauseMission
missionManager.pauseMission(new CallbackWithNoParam() {
@Override
public void onSuccess() {
flyState = FlyState.Pause;
Toast.makeText(Evo2WayPointActivity.this, "pause success", Toast.LENGTH_LONG).show();
}
@Override
public void onFailure(AutelError autelError) {
}
});
MissionManager#resumeMission
missionManager.resumeMission(String guid,new CallbackWithNoParam() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(AutelError autelError) {
}
});
MissionManager#cancelMission
missionManager.cancelMission(new CallbackWithNoParam() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(AutelError autelError) {
}
});
MissionManager#downloadMission
missionManager.downloadMission(new CallbackWithOneParamProgress<AutelMission>() {
@Override
public void onProgress(float v) {
}
@Override
public void onSuccess(AutelMission autelMission) {
}
@Override
public void onFailure(AutelError autelError) {
}
});